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));
327 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
330 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
332 if (i->m_channel == ch)
334 i = m_active_channels.erase(i);
345 DEFINE_REF(eDVBChannel);
347 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend, eDVBAllocatedDemux *demux): m_state(state_idle), m_mgr(mgr)
349 m_frontend = frontend;
353 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
356 eDVBChannel::~eDVBChannel()
359 m_mgr->removeChannel(this);
362 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
364 eDebug("fe state changed!");
365 int state, ourstate = 0;
366 if (fe->getState(state))
369 if (state == iDVBFrontend::stateLock)
371 eDebug("OURSTATE: ok");
373 } else if (state == iDVBFrontend::stateTuning)
375 eDebug("OURSTATE: tuning");
376 ourstate = state_tuning;
377 } else if (state == iDVBFrontend::stateFailed)
379 eDebug("OURSTATE: failed/unavailable");
380 ourstate = state_unavailable;
382 eFatal("state unknown");
384 if (ourstate != m_state)
387 m_stateChanged(this);
391 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
394 m_mgr->removeChannel(this);
399 ePtr<iDVBChannelList> list;
401 if (m_mgr->getChannelList(list))
403 eDebug("no channel list set!");
407 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
408 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
410 ePtr<iDVBFrontendParameters> feparm;
411 if (list->getChannelFrontendData(channelid, feparm))
413 eDebug("channel not found!");
416 eDebug("allocateChannel: channel found..");
420 eDebug("no frontend to tune!");
424 m_channel_id = channelid;
425 m_mgr->addChannel(channelid, this);
426 m_state = state_tuning;
427 return m_frontend->get().tune(*feparm);
430 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
432 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
436 RESULT eDVBChannel::getState(int &state)
442 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
447 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux)
449 demux = &m_demux->get();
453 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
455 frontend = &m_frontend->get();