1 #include <lib/dvb/idvb.h>
2 #include <lib/base/eerror.h>
3 #include <lib/dvb/dvb.h>
4 #include <lib/dvb/sec.h>
11 DEFINE_REF(eDVBRegisteredFrontend);
12 DEFINE_REF(eDVBRegisteredDemux);
14 DEFINE_REF(eDVBAllocatedFrontend);
16 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
21 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
26 DEFINE_REF(eDVBAllocatedDemux);
28 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
33 eDVBAllocatedDemux::~eDVBAllocatedDemux()
38 DEFINE_REF(eDVBResourceManager);
40 eDVBResourceManager *eDVBResourceManager::instance;
42 eDVBResourceManager::eDVBResourceManager()
46 m_sec = new eDVBSatelliteEquipmentControl;
50 /* search available adapters... */
55 while (eDVBAdapterLinux::exist(num_adapter))
57 addAdapter(new eDVBAdapterLinux(num_adapter));
61 eDebug("found %d adapter, %d frontends and %d demux",
62 m_adapter.size(), m_frontend.size(), m_demux.size());
66 DEFINE_REF(eDVBAdapterLinux);
67 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
72 eDebug("scanning for frontends..");
77 #if HAVE_DVB_API_VERSION < 3
78 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
80 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
82 if (stat(filename, &s))
84 ePtr<eDVBFrontend> fe;
87 fe = new eDVBFrontend(m_nr, num_fe, ok);
89 m_frontend.push_back(fe);
99 #if HAVE_DVB_API_VERSION < 3
100 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
102 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
104 if (stat(filename, &s))
106 ePtr<eDVBDemux> demux;
108 demux = new eDVBDemux(m_nr, num_demux);
109 m_demux.push_back(demux);
115 int eDVBAdapterLinux::getNumDemux()
117 return m_demux.size();
120 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
122 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
123 while (nr && (i != m_demux.end()))
129 if (i != m_demux.end())
137 int eDVBAdapterLinux::getNumFrontends()
139 return m_frontend.size();
142 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
144 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
145 while (nr && (i != m_frontend.end()))
151 if (i != m_frontend.end())
159 int eDVBAdapterLinux::exist(int nr)
163 #if HAVE_DVB_API_VERSION < 3
164 sprintf(filename, "/dev/dvb/card%d", nr);
166 sprintf(filename, "/dev/dvb/adapter%d", nr);
168 if (!stat(filename, &s))
173 eDVBResourceManager::~eDVBResourceManager()
175 if (instance == this)
180 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
182 int num_fe = adapter->getNumFrontends();
183 int num_demux = adapter->getNumDemux();
185 m_adapter.push_back(adapter);
188 for (i=0; i<num_demux; ++i)
190 ePtr<eDVBDemux> demux;
191 if (!adapter->getDemux(demux, i))
192 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
195 for (i=0; i<num_fe; ++i)
197 ePtr<eDVBFrontend> frontend;
198 if (!adapter->getFrontend(frontend, i))
199 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
203 RESULT eDVBResourceManager::allocateFrontend(const eDVBChannelID &chid, ePtr<eDVBAllocatedFrontend> &fe)
205 /* find first unused frontend. we ignore compatibility for now. */
206 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
209 fe = new eDVBAllocatedFrontend(i);
215 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux)
217 /* find first unused demux which is on same adapter as frontend */
218 for (eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin()); i != m_demux.end(); ++i)
219 if ((!i->m_inuse) && (i->m_adapter == fe->m_adapter))
221 demux = new eDVBAllocatedDemux(i);
227 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
233 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
243 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, ePtr<iDVBChannel> &channel)
245 /* first, check if a channel is already existing. */
247 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
248 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
250 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
251 if (i->m_channel_id == channelid)
253 // eDebug("found shared channel..");
254 channel = i->m_channel;
259 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
261 /* allocate a frontend. */
263 ePtr<eDVBAllocatedFrontend> fe;
265 if (allocateFrontend(channelid, fe))
266 return errNoFrontend;
268 ePtr<eDVBAllocatedDemux> demux;
270 if (allocateDemux(*fe, demux))
275 ch = new eDVBChannel(this, fe, demux);
277 ePtr<iDVBFrontend> myfe;
278 if (!ch->getFrontend(myfe))
281 res = ch->setChannel(channelid);
285 return errChidNotFound;
292 RESULT eDVBResourceManager::allocateRawChannel(ePtr<iDVBChannel> &channel)
294 ePtr<eDVBAllocatedFrontend> fe;
296 if (allocateFrontend(eDVBChannelID(), fe))
297 return errNoFrontend;
299 ePtr<eDVBAllocatedDemux> demux;
301 if (allocateDemux(*fe, demux))
305 ch = new eDVBChannel(this, fe, demux);
307 ePtr<iDVBFrontend> myfe;
308 if (!ch->getFrontend(myfe))
315 RESULT eDVBResourceManager::allocatePVRChannel(int caps)
317 return -1; // will nicht, mag nicht, und das interface ist auch kaputt
320 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
322 eDebug("add channel %p", ch);
323 m_active_channels.push_back(active_channel(chid, ch));
324 /* emit */ m_channelAdded(ch);
328 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
331 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
333 if (i->m_channel == ch)
335 i = m_active_channels.erase(i);
337 /* emit */ m_channelRemoved(ch);
347 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
349 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
353 RESULT eDVBResourceManager::connectChannelRemoved(const Slot1<void,eDVBChannel*> &channelRemoved, ePtr<eConnection> &connection)
355 connection = new eConnection((eDVBResourceManager*)this, m_channelRemoved.connect(channelRemoved));
359 RESULT eDVBResourceManager::connectChannelRunning(const Slot1<void,iDVBChannel*> &channelRunning, ePtr<eConnection> &connection)
361 connection = new eConnection((eDVBResourceManager*)this, m_channelRunning.connect(channelRunning));
365 DEFINE_REF(eDVBChannel);
367 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend, eDVBAllocatedDemux *demux): m_state(state_idle), m_mgr(mgr)
369 m_frontend = frontend;
373 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
376 eDVBChannel::~eDVBChannel()
379 m_mgr->removeChannel(this);
382 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
384 eDebug("fe state changed!");
385 int state, ourstate = 0;
386 if (fe->getState(state))
389 if (state == iDVBFrontend::stateLock)
391 eDebug("OURSTATE: ok");
393 } else if (state == iDVBFrontend::stateTuning)
395 eDebug("OURSTATE: tuning");
396 ourstate = state_tuning;
397 } else if (state == iDVBFrontend::stateFailed)
399 eDebug("OURSTATE: failed/unavailable");
400 ourstate = state_unavailable;
402 eFatal("state unknown");
404 if (ourstate != m_state)
407 m_stateChanged(this);
411 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
414 m_mgr->removeChannel(this);
419 ePtr<iDVBChannelList> list;
421 if (m_mgr->getChannelList(list))
423 eDebug("no channel list set!");
427 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
428 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
430 ePtr<iDVBFrontendParameters> feparm;
431 if (list->getChannelFrontendData(channelid, feparm))
433 eDebug("channel not found!");
436 eDebug("allocateChannel: channel found..");
440 eDebug("no frontend to tune!");
444 m_channel_id = channelid;
445 m_mgr->addChannel(channelid, this);
446 m_state = state_tuning;
447 return m_frontend->get().tune(*feparm);
450 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
452 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
456 RESULT eDVBChannel::getState(int &state)
462 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
467 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux)
469 demux = &m_demux->get();
473 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
475 frontend = &m_frontend->get();