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 ePtr<eDVBRegisteredFrontend> best;
210 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
213 int c = i->m_frontend->isCompatibleWith(chid);
223 fe = new eDVBAllocatedFrontend(best);
232 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
234 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
235 never use the first one unless we need a decoding demux. */
237 eDebug("allocate demux");
238 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
240 if (i == m_demux.end())
244 /* FIXME: hardware demux policy */
245 if (!(cap & iDVBChannel::capDecode))
248 for (; i != m_demux.end(); ++i, ++n)
249 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
251 if ((cap & iDVBChannel::capDecode) && n)
254 demux = new eDVBAllocatedDemux(i);
256 demux->get().setSourceFrontend(fe->m_frontend->getID());
258 demux->get().setSourcePVR(0);
261 eDebug("demux not found");
265 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
271 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
281 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
283 /* first, check if a channel is already existing. */
285 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
286 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
288 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
289 if (i->m_channel_id == channelid)
291 // eDebug("found shared channel..");
292 channel = i->m_channel;
297 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
299 /* allocate a frontend. */
301 ePtr<eDVBAllocatedFrontend> fe;
303 if (allocateFrontend(channelid, fe))
304 return errNoFrontend;
306 // will be allocated on demand:
307 // ePtr<eDVBAllocatedDemux> demux;
309 // if (allocateDemux(*fe, demux))
310 // return errNoDemux;
313 ePtr<eDVBChannel> ch;
314 ch = new eDVBChannel(this, fe);
316 ePtr<iDVBFrontend> myfe;
317 if (!ch->getFrontend(myfe))
320 res = ch->setChannel(channelid);
324 return errChidNotFound;
331 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel)
333 ePtr<eDVBAllocatedFrontend> fe;
335 if (allocateFrontend(eDVBChannelID(), fe))
336 return errNoFrontend;
338 // ePtr<eDVBAllocatedDemux> demux;
340 // if (allocateDemux(*fe, demux))
341 // return errNoDemux;
344 ch = new eDVBChannel(this, fe);
346 ePtr<iDVBFrontend> myfe;
347 if (!ch->getFrontend(myfe))
355 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
357 ePtr<eDVBAllocatedDemux> demux;
359 // if (allocateDemux(0, demux))
360 // return errNoDemux;
363 ch = new eDVBChannel(this, 0);
369 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
371 m_active_channels.push_back(active_channel(chid, ch));
372 /* emit */ m_channelAdded(ch);
376 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
379 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
381 if (i->m_channel == ch)
383 i = m_active_channels.erase(i);
394 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
396 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
400 DEFINE_REF(eDVBChannel);
402 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
404 m_frontend = frontend;
409 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
412 eDVBChannel::~eDVBChannel()
415 m_mgr->removeChannel(this);
419 m_pvr_thread->stop();
420 ::close(m_pvr_fd_src);
421 ::close(m_pvr_fd_dst);
426 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
428 int state, ourstate = 0;
430 /* if we are already in shutdown, don't change state. */
431 if (m_state == state_release)
434 if (fe->getState(state))
437 if (state == iDVBFrontend::stateLock)
439 eDebug("OURSTATE: ok");
441 } else if (state == iDVBFrontend::stateTuning)
443 eDebug("OURSTATE: tuning");
444 ourstate = state_tuning;
445 } else if (state == iDVBFrontend::stateLostLock)
447 eDebug("OURSTATE: lost lock");
448 ourstate = state_unavailable;
449 } else if (state == iDVBFrontend::stateFailed)
451 eDebug("OURSTATE: failed");
452 ourstate = state_failed;
454 eFatal("state unknown");
456 if (ourstate != m_state)
459 m_stateChanged(this);
463 void eDVBChannel::AddUse()
468 void eDVBChannel::ReleaseUse()
472 m_state = state_release;
473 m_stateChanged(this);
477 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
480 m_mgr->removeChannel(this);
485 ePtr<iDVBChannelList> list;
487 if (m_mgr->getChannelList(list))
489 eDebug("no channel list set!");
493 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
494 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
496 ePtr<iDVBFrontendParameters> feparm;
497 if (list->getChannelFrontendData(channelid, feparm))
499 eDebug("channel not found!");
505 eDebug("no frontend to tune!");
509 m_channel_id = channelid;
510 m_mgr->addChannel(channelid, this);
511 m_state = state_tuning;
512 /* if tuning fails, shutdown the channel immediately. */
514 res = m_frontend->get().tune(*feparm);
518 m_state = state_release;
519 m_stateChanged(this);
526 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
528 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
532 RESULT eDVBChannel::getState(int &state)
538 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
543 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
545 eDebug("get %d demux", cap);
546 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
552 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
565 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
567 frontend = &m_frontend->get();
574 RESULT eDVBChannel::playFile(const char *file)
579 m_pvr_thread->stop();
584 m_tstools.openFile(file);
586 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
587 THEN DO A REAL FIX HERE! */
589 /* (this codepath needs to be improved anyway.) */
590 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
591 if (m_pvr_fd_dst < 0)
593 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
597 m_pvr_fd_src = open(file, O_RDONLY);
598 if (m_pvr_fd_src < 0)
600 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
606 m_stateChanged(this);
608 m_pvr_thread = new eFilePushThread();
609 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
614 RESULT eDVBChannel::getLength(pts_t &len)
616 return m_tstools.calcLen(len);
619 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
621 if (!m_decoder_demux)
625 /* getPTS for offset 0 is cached, so it doesn't harm. */
626 int r = m_tstools.getPTS(begin, pos);
629 eDebug("tstools getpts(0) failed!");
635 r = m_decoder_demux->get().getSTC(now);
639 eDebug("demux getSTC failed");
643 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
644 /* when we are less than 10 seconds before the start, return 0. */
645 /* (we're just waiting for the timespam to start) */
646 if ((now < pos) && ((pos - now) < 90000 * 10))
652 if (now < pos) /* wrap around */
653 pos = now + ((pts_t)1)<<33 - pos;
660 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
662 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
670 if (getCurrentPosition(now))
672 eDebug("seekTo: getCurrentPosition failed!");
681 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
683 seekToPosition(offset);
687 RESULT eDVBChannel::seekToPosition(const off_t &r)
689 /* when seeking, we have to ensure that all buffers are flushed.
690 there are basically 3 buffers:
691 a.) the filepush's internal buffer
692 b.) the PVR buffer (before demux)
693 c.) the ratebuffer (after demux)
695 it's important to clear them in the correct order, otherwise
696 the ratebuffer (for example) would immediately refill from
697 the not-yet-flushed PVR buffer.
699 eDebug("eDVBChannel: seekToPosition .. %llx", r);
700 m_pvr_thread->pause();
702 /* flush internal filepush buffer */
703 m_pvr_thread->flush();
705 /* HACK: flush PVR buffer */
706 ::ioctl(m_pvr_fd_dst, 0);
708 /* flush ratebuffers (video, audio) */
710 m_decoder_demux->get().flush();
712 /* demux will also flush all decoder.. */
713 m_pvr_thread->seek(SEEK_SET, r);
714 m_pvr_thread->resume();