1 #include <lib/base/eerror.h>
2 #include <lib/base/filepush.h>
3 #include <lib/dvb/idvb.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/sec.h>
13 DEFINE_REF(eDVBRegisteredFrontend);
14 DEFINE_REF(eDVBRegisteredDemux);
16 DEFINE_REF(eDVBAllocatedFrontend);
18 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
23 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
28 DEFINE_REF(eDVBAllocatedDemux);
30 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
35 eDVBAllocatedDemux::~eDVBAllocatedDemux()
40 DEFINE_REF(eDVBResourceManager);
42 eDVBResourceManager *eDVBResourceManager::instance;
44 eDVBResourceManager::eDVBResourceManager()
48 m_sec = new eDVBSatelliteEquipmentControl;
52 /* search available adapters... */
57 while (eDVBAdapterLinux::exist(num_adapter))
59 addAdapter(new eDVBAdapterLinux(num_adapter));
63 eDebug("found %d adapter, %d frontends and %d demux",
64 m_adapter.size(), m_frontend.size(), m_demux.size());
68 DEFINE_REF(eDVBAdapterLinux);
69 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
74 eDebug("scanning for frontends..");
79 #if HAVE_DVB_API_VERSION < 3
80 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
82 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
84 if (stat(filename, &s))
86 ePtr<eDVBFrontend> fe;
89 fe = new eDVBFrontend(m_nr, num_fe, ok);
91 m_frontend.push_back(fe);
101 #if HAVE_DVB_API_VERSION < 3
102 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
104 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
106 if (stat(filename, &s))
108 ePtr<eDVBDemux> demux;
110 demux = new eDVBDemux(m_nr, num_demux);
111 m_demux.push_back(demux);
117 int eDVBAdapterLinux::getNumDemux()
119 return m_demux.size();
122 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
124 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
125 while (nr && (i != m_demux.end()))
131 if (i != m_demux.end())
139 int eDVBAdapterLinux::getNumFrontends()
141 return m_frontend.size();
144 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
146 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
147 while (nr && (i != m_frontend.end()))
153 if (i != m_frontend.end())
161 int eDVBAdapterLinux::exist(int nr)
165 #if HAVE_DVB_API_VERSION < 3
166 sprintf(filename, "/dev/dvb/card%d", nr);
168 sprintf(filename, "/dev/dvb/adapter%d", nr);
170 if (!stat(filename, &s))
175 eDVBResourceManager::~eDVBResourceManager()
177 if (instance == this)
182 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
184 int num_fe = adapter->getNumFrontends();
185 int num_demux = adapter->getNumDemux();
187 m_adapter.push_back(adapter);
190 for (i=0; i<num_demux; ++i)
192 ePtr<eDVBDemux> demux;
193 if (!adapter->getDemux(demux, i))
194 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
197 for (i=0; i<num_fe; ++i)
199 ePtr<eDVBFrontend> frontend;
200 if (!adapter->getFrontend(frontend, i))
201 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
205 RESULT eDVBResourceManager::allocateFrontend(const eDVBChannelID &chid, ePtr<eDVBAllocatedFrontend> &fe)
207 /* find first unused frontend. we ignore compatibility for now. */
208 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
211 fe = new eDVBAllocatedFrontend(i);
217 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux)
219 /* find first unused demux which is on same adapter as frontend (or any, if PVR) */
220 for (eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin()); i != m_demux.end(); ++i)
221 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
223 demux = new eDVBAllocatedDemux(i);
229 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
235 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
245 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
247 /* first, check if a channel is already existing. */
249 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
250 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
252 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
253 if (i->m_channel_id == channelid)
255 // eDebug("found shared channel..");
256 channel = i->m_channel;
261 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
263 /* allocate a frontend. */
265 ePtr<eDVBAllocatedFrontend> fe;
267 if (allocateFrontend(channelid, fe))
268 return errNoFrontend;
270 ePtr<eDVBAllocatedDemux> demux;
272 if (allocateDemux(*fe, demux))
277 ch = new eDVBChannel(this, fe, demux);
279 ePtr<iDVBFrontend> myfe;
280 if (!ch->getFrontend(myfe))
283 res = ch->setChannel(channelid);
287 return errChidNotFound;
294 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
296 ePtr<eDVBAllocatedFrontend> fe;
298 if (allocateFrontend(eDVBChannelID(), fe))
299 return errNoFrontend;
301 ePtr<eDVBAllocatedDemux> demux;
303 if (allocateDemux(*fe, demux))
307 ch = new eDVBChannel(this, fe, demux);
309 ePtr<iDVBFrontend> myfe;
310 if (!ch->getFrontend(myfe))
318 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
320 ePtr<eDVBAllocatedDemux> demux;
322 if (allocateDemux(0, demux))
326 ch = new eDVBChannel(this, 0, demux);
332 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
334 eDebug("add channel %p", ch);
335 m_active_channels.push_back(active_channel(chid, ch));
336 /* emit */ m_channelAdded(ch);
340 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
343 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
345 if (i->m_channel == ch)
347 i = m_active_channels.erase(i);
358 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
360 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
364 DEFINE_REF(eDVBChannel);
366 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend, eDVBAllocatedDemux *demux): m_state(state_idle), m_mgr(mgr)
368 m_frontend = frontend;
374 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
377 eDVBChannel::~eDVBChannel()
380 m_mgr->removeChannel(this);
384 m_pvr_thread->stop();
389 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
391 eDebug("fe state changed!");
392 int state, ourstate = 0;
394 /* if we are already in shutdown, don't change state. */
395 if (m_state == state_release)
398 if (fe->getState(state))
401 if (state == iDVBFrontend::stateLock)
403 eDebug("OURSTATE: ok");
405 } else if (state == iDVBFrontend::stateTuning)
407 eDebug("OURSTATE: tuning");
408 ourstate = state_tuning;
409 } else if (state == iDVBFrontend::stateFailed)
411 eDebug("OURSTATE: failed/unavailable");
412 ourstate = state_unavailable;
414 eFatal("state unknown");
416 if (ourstate != m_state)
419 m_stateChanged(this);
423 void eDVBChannel::AddUse()
428 void eDVBChannel::ReleaseUse()
432 m_state = state_release;
433 m_stateChanged(this);
437 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
440 m_mgr->removeChannel(this);
445 ePtr<iDVBChannelList> list;
447 if (m_mgr->getChannelList(list))
449 eDebug("no channel list set!");
453 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
454 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
456 ePtr<iDVBFrontendParameters> feparm;
457 if (list->getChannelFrontendData(channelid, feparm))
459 eDebug("channel not found!");
462 eDebug("allocateChannel: channel found..");
466 eDebug("no frontend to tune!");
470 m_channel_id = channelid;
471 m_mgr->addChannel(channelid, this);
472 m_state = state_tuning;
473 return m_frontend->get().tune(*feparm);
476 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
478 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
482 RESULT eDVBChannel::getState(int &state)
488 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
493 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux)
495 demux = &m_demux->get();
499 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
501 frontend = &m_frontend->get();
508 RESULT eDVBChannel::playFile(const char *file)
513 m_pvr_thread->stop();
518 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
519 THEN DO A REAL FIX HERE! */
522 /* (this codepath needs to be improved anyway.) */
523 int dest = open("/dev/misc/pvr", O_WRONLY);
526 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
530 int source = open(file, O_RDONLY);
533 eDebug("can't open PVR source file %s (%m)", file);
539 m_stateChanged(this);
541 m_pvr_thread = new eFilePushThread();
542 m_pvr_thread->start(source, dest);