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>
12 #include <sys/ioctl.h>
14 DEFINE_REF(eDVBRegisteredFrontend);
15 DEFINE_REF(eDVBRegisteredDemux);
17 DEFINE_REF(eDVBAllocatedFrontend);
19 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
29 DEFINE_REF(eDVBAllocatedDemux);
31 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
36 eDVBAllocatedDemux::~eDVBAllocatedDemux()
41 DEFINE_REF(eDVBResourceManager);
43 eDVBResourceManager *eDVBResourceManager::instance;
45 eDVBResourceManager::eDVBResourceManager()
49 m_sec = new eDVBSatelliteEquipmentControl;
53 /* search available adapters... */
58 while (eDVBAdapterLinux::exist(num_adapter))
60 addAdapter(new eDVBAdapterLinux(num_adapter));
64 eDebug("found %d adapter, %d frontends and %d demux",
65 m_adapter.size(), m_frontend.size(), m_demux.size());
69 DEFINE_REF(eDVBAdapterLinux);
70 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
75 eDebug("scanning for frontends..");
80 #if HAVE_DVB_API_VERSION < 3
81 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
83 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
85 if (stat(filename, &s))
87 ePtr<eDVBFrontend> fe;
90 fe = new eDVBFrontend(m_nr, num_fe, ok);
92 m_frontend.push_back(fe);
102 #if HAVE_DVB_API_VERSION < 3
103 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
105 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
107 if (stat(filename, &s))
109 ePtr<eDVBDemux> demux;
111 demux = new eDVBDemux(m_nr, num_demux);
112 m_demux.push_back(demux);
118 int eDVBAdapterLinux::getNumDemux()
120 return m_demux.size();
123 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
125 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
126 while (nr && (i != m_demux.end()))
132 if (i != m_demux.end())
140 int eDVBAdapterLinux::getNumFrontends()
142 return m_frontend.size();
145 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
147 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
148 while (nr && (i != m_frontend.end()))
154 if (i != m_frontend.end())
162 int eDVBAdapterLinux::exist(int nr)
166 #if HAVE_DVB_API_VERSION < 3
167 sprintf(filename, "/dev/dvb/card%d", nr);
169 sprintf(filename, "/dev/dvb/adapter%d", nr);
171 if (!stat(filename, &s))
176 eDVBResourceManager::~eDVBResourceManager()
178 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, int cap)
219 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
220 never use the first one unless we need a decoding demux. */
222 eDebug("allocate demux");
223 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
225 if (i == m_demux.end())
229 /* FIXME: hardware demux policy */
230 if (!(cap & iDVBChannel::capDecode))
233 for (; i != m_demux.end(); ++i, ++n)
234 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
236 if ((cap & iDVBChannel::capDecode) && n)
239 demux = new eDVBAllocatedDemux(i);
241 demux->get().setSourceFrontend(fe->m_frontend->getID());
243 demux->get().setSourcePVR(0);
246 eDebug("demux not found");
250 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
256 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
266 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
268 /* first, check if a channel is already existing. */
270 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
271 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
273 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
274 if (i->m_channel_id == channelid)
276 // eDebug("found shared channel..");
277 channel = i->m_channel;
282 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
284 /* allocate a frontend. */
286 ePtr<eDVBAllocatedFrontend> fe;
288 if (allocateFrontend(channelid, fe))
289 return errNoFrontend;
291 // will be allocated on demand:
292 // ePtr<eDVBAllocatedDemux> demux;
294 // if (allocateDemux(*fe, demux))
295 // return errNoDemux;
298 ePtr<eDVBChannel> ch;
299 ch = new eDVBChannel(this, fe);
301 ePtr<iDVBFrontend> myfe;
302 if (!ch->getFrontend(myfe))
305 res = ch->setChannel(channelid);
309 return errChidNotFound;
316 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
318 ePtr<eDVBAllocatedFrontend> fe;
320 if (allocateFrontend(eDVBChannelID(), fe))
321 return errNoFrontend;
323 // ePtr<eDVBAllocatedDemux> demux;
325 // if (allocateDemux(*fe, demux))
326 // return errNoDemux;
329 ch = new eDVBChannel(this, fe);
331 ePtr<iDVBFrontend> myfe;
332 if (!ch->getFrontend(myfe))
340 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
342 ePtr<eDVBAllocatedDemux> demux;
344 // if (allocateDemux(0, demux))
345 // return errNoDemux;
348 ch = new eDVBChannel(this, 0);
354 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
356 m_active_channels.push_back(active_channel(chid, ch));
357 /* emit */ m_channelAdded(ch);
361 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
364 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
366 if (i->m_channel == ch)
368 i = m_active_channels.erase(i);
379 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
381 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
385 DEFINE_REF(eDVBChannel);
387 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
389 m_frontend = frontend;
394 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
397 eDVBChannel::~eDVBChannel()
400 m_mgr->removeChannel(this);
404 m_pvr_thread->stop();
405 ::close(m_pvr_fd_src);
406 ::close(m_pvr_fd_dst);
411 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
413 int state, ourstate = 0;
415 /* if we are already in shutdown, don't change state. */
416 if (m_state == state_release)
419 if (fe->getState(state))
422 if (state == iDVBFrontend::stateLock)
424 eDebug("OURSTATE: ok");
426 } else if (state == iDVBFrontend::stateTuning)
428 eDebug("OURSTATE: tuning");
429 ourstate = state_tuning;
430 } else if (state == iDVBFrontend::stateLostLock)
432 eDebug("OURSTATE: lost lock");
433 ourstate = state_unavailable;
434 } else if (state == iDVBFrontend::stateFailed)
436 eDebug("OURSTATE: failed");
437 ourstate = state_failed;
439 eFatal("state unknown");
441 if (ourstate != m_state)
444 m_stateChanged(this);
448 void eDVBChannel::AddUse()
453 void eDVBChannel::ReleaseUse()
457 m_state = state_release;
458 m_stateChanged(this);
462 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
465 m_mgr->removeChannel(this);
470 ePtr<iDVBChannelList> list;
472 if (m_mgr->getChannelList(list))
474 eDebug("no channel list set!");
478 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
479 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
481 ePtr<iDVBFrontendParameters> feparm;
482 if (list->getChannelFrontendData(channelid, feparm))
484 eDebug("channel not found!");
490 eDebug("no frontend to tune!");
494 m_channel_id = channelid;
495 m_mgr->addChannel(channelid, this);
496 m_state = state_tuning;
497 /* if tuning fails, shutdown the channel immediately. */
499 res = m_frontend->get().tune(*feparm);
503 m_state = state_release;
504 m_stateChanged(this);
511 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
513 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
517 RESULT eDVBChannel::getState(int &state)
523 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
528 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
530 eDebug("get %d demux", cap);
531 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
537 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
550 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
552 frontend = &m_frontend->get();
559 RESULT eDVBChannel::playFile(const char *file)
564 m_pvr_thread->stop();
569 m_tstools.openFile(file);
571 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
572 THEN DO A REAL FIX HERE! */
574 /* (this codepath needs to be improved anyway.) */
575 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
576 if (m_pvr_fd_dst < 0)
578 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
582 m_pvr_fd_src = open(file, O_RDONLY);
583 if (m_pvr_fd_src < 0)
585 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
591 m_stateChanged(this);
593 m_pvr_thread = new eFilePushThread();
594 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
599 RESULT eDVBChannel::getLength(pts_t &len)
601 return m_tstools.calcLen(len);
604 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
606 if (!m_decoder_demux)
610 /* getPTS for offset 0 is cached, so it doesn't harm. */
611 int r = m_tstools.getPTS(begin, pos);
614 eDebug("tstools getpts(0) failed!");
620 r = m_decoder_demux->get().getSTC(now);
624 eDebug("demux getSTC failed");
628 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
629 /* when we are less than 10 seconds before the start, return 0. */
630 /* (we're just waiting for the timespam to start) */
631 if ((now < pos) && ((pos - now) < 90000 * 10))
637 if (now < pos) /* wrap around */
638 pos = now + ((pts_t)1)<<33 - pos;
645 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
647 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
655 if (getCurrentPosition(now))
657 eDebug("seekTo: getCurrentPosition failed!");
666 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
668 seekToPosition(offset);
672 RESULT eDVBChannel::seekToPosition(const off_t &r)
674 /* when seeking, we have to ensure that all buffers are flushed.
675 there are basically 3 buffers:
676 a.) the filepush's internal buffer
677 b.) the PVR buffer (before demux)
678 c.) the ratebuffer (after demux)
680 it's important to clear them in the correct order, otherwise
681 the ratebuffer (for example) would immediately refill from
682 the not-yet-flushed PVR buffer.
684 eDebug("eDVBChannel: seekToPosition .. %llx", r);
685 m_pvr_thread->pause();
687 /* flush internal filepush buffer */
688 m_pvr_thread->flush();
690 /* HACK: flush PVR buffer */
691 ::ioctl(m_pvr_fd_dst, 0);
693 /* flush ratebuffers (video, audio) */
695 m_decoder_demux->get().flush();
697 /* demux will also flush all decoder.. */
698 m_pvr_thread->seek(SEEK_SET, r);
699 m_pvr_thread->resume();