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;
201 if (!adapter->getFrontend(frontend, i))
203 frontend->setSEC(m_sec);
204 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
209 RESULT eDVBResourceManager::allocateFrontend(const eDVBChannelID &chid, ePtr<eDVBAllocatedFrontend> &fe)
211 ePtr<eDVBRegisteredFrontend> best;
214 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
217 int c = i->m_frontend->isCompatibleWith(chid);
227 fe = new eDVBAllocatedFrontend(best);
236 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
238 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
239 never use the first one unless we need a decoding demux. */
241 eDebug("allocate demux");
242 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
244 if (i == m_demux.end())
248 /* FIXME: hardware demux policy */
249 if (!(cap & iDVBChannel::capDecode))
252 for (; i != m_demux.end(); ++i, ++n)
253 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
255 if ((cap & iDVBChannel::capDecode) && n)
258 demux = new eDVBAllocatedDemux(i);
260 demux->get().setSourceFrontend(fe->m_frontend->getID());
262 demux->get().setSourcePVR(0);
265 eDebug("demux not found");
269 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
275 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
285 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
287 /* first, check if a channel is already existing. */
289 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
290 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
292 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
293 if (i->m_channel_id == channelid)
295 // eDebug("found shared channel..");
296 channel = i->m_channel;
301 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
303 /* allocate a frontend. */
305 ePtr<eDVBAllocatedFrontend> fe;
307 if (allocateFrontend(channelid, fe))
308 return errNoFrontend;
310 // will be allocated on demand:
311 // ePtr<eDVBAllocatedDemux> demux;
313 // if (allocateDemux(*fe, demux))
314 // return errNoDemux;
317 ePtr<eDVBChannel> ch;
318 ch = new eDVBChannel(this, fe);
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);
351 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
353 ePtr<eDVBAllocatedDemux> demux;
355 // if (allocateDemux(0, demux))
356 // return errNoDemux;
359 ch = new eDVBChannel(this, 0);
365 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
367 m_active_channels.push_back(active_channel(chid, ch));
368 /* emit */ m_channelAdded(ch);
372 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
375 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
377 if (i->m_channel == ch)
379 i = m_active_channels.erase(i);
390 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
392 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
396 DEFINE_REF(eDVBChannel);
398 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
400 m_frontend = frontend;
405 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
408 eDVBChannel::~eDVBChannel()
411 m_mgr->removeChannel(this);
415 m_pvr_thread->stop();
416 ::close(m_pvr_fd_src);
417 ::close(m_pvr_fd_dst);
422 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
424 int state, ourstate = 0;
426 /* if we are already in shutdown, don't change state. */
427 if (m_state == state_release)
430 if (fe->getState(state))
433 if (state == iDVBFrontend::stateLock)
435 eDebug("OURSTATE: ok");
437 } else if (state == iDVBFrontend::stateTuning)
439 eDebug("OURSTATE: tuning");
440 ourstate = state_tuning;
441 } else if (state == iDVBFrontend::stateLostLock)
443 eDebug("OURSTATE: lost lock");
444 ourstate = state_unavailable;
445 } else if (state == iDVBFrontend::stateFailed)
447 eDebug("OURSTATE: failed");
448 ourstate = state_failed;
450 eFatal("state unknown");
452 if (ourstate != m_state)
455 m_stateChanged(this);
459 void eDVBChannel::AddUse()
464 void eDVBChannel::ReleaseUse()
468 m_state = state_release;
469 m_stateChanged(this);
473 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid)
476 m_mgr->removeChannel(this);
481 ePtr<iDVBChannelList> list;
483 if (m_mgr->getChannelList(list))
485 eDebug("no channel list set!");
489 eDebug("tuning to chid: ns: %08x tsid %04x onid %04x",
490 channelid.dvbnamespace.get(), channelid.transport_stream_id.get(), channelid.original_network_id.get());
492 ePtr<iDVBFrontendParameters> feparm;
493 if (list->getChannelFrontendData(channelid, feparm))
495 eDebug("channel not found!");
501 eDebug("no frontend to tune!");
505 m_channel_id = channelid;
506 m_mgr->addChannel(channelid, this);
507 m_state = state_tuning;
508 /* if tuning fails, shutdown the channel immediately. */
510 res = m_frontend->get().tune(*feparm);
514 m_state = state_release;
515 m_stateChanged(this);
522 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
524 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
528 RESULT eDVBChannel::getState(int &state)
534 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
539 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
541 eDebug("get %d demux", cap);
542 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
548 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
561 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
563 frontend = &m_frontend->get();
570 RESULT eDVBChannel::playFile(const char *file)
575 m_pvr_thread->stop();
580 m_tstools.openFile(file);
582 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
583 THEN DO A REAL FIX HERE! */
585 /* (this codepath needs to be improved anyway.) */
586 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
587 if (m_pvr_fd_dst < 0)
589 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)");
593 m_pvr_fd_src = open(file, O_RDONLY);
594 if (m_pvr_fd_src < 0)
596 eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
602 m_stateChanged(this);
604 m_pvr_thread = new eFilePushThread();
605 m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
610 RESULT eDVBChannel::getLength(pts_t &len)
612 return m_tstools.calcLen(len);
615 RESULT eDVBChannel::getCurrentPosition(pts_t &pos)
617 if (!m_decoder_demux)
621 /* getPTS for offset 0 is cached, so it doesn't harm. */
622 int r = m_tstools.getPTS(begin, pos);
625 eDebug("tstools getpts(0) failed!");
631 r = m_decoder_demux->get().getSTC(now);
635 eDebug("demux getSTC failed");
639 // eDebug("STC: %08llx PTS: %08llx, diff %lld", now, pos, now - pos);
640 /* when we are less than 10 seconds before the start, return 0. */
641 /* (we're just waiting for the timespam to start) */
642 if ((now < pos) && ((pos - now) < 90000 * 10))
648 if (now < pos) /* wrap around */
649 pos = now + ((pts_t)1)<<33 - pos;
656 RESULT eDVBChannel::seekTo(int relative, pts_t &pts)
658 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
666 if (getCurrentPosition(now))
668 eDebug("seekTo: getCurrentPosition failed!");
677 off_t offset = (pts * (pts_t)bitrate) / 8ULL / 90000ULL;
679 seekToPosition(offset);
683 RESULT eDVBChannel::seekToPosition(const off_t &r)
685 /* when seeking, we have to ensure that all buffers are flushed.
686 there are basically 3 buffers:
687 a.) the filepush's internal buffer
688 b.) the PVR buffer (before demux)
689 c.) the ratebuffer (after demux)
691 it's important to clear them in the correct order, otherwise
692 the ratebuffer (for example) would immediately refill from
693 the not-yet-flushed PVR buffer.
695 eDebug("eDVBChannel: seekToPosition .. %llx", r);
696 m_pvr_thread->pause();
698 /* flush internal filepush buffer */
699 m_pvr_thread->flush();
701 /* HACK: flush PVR buffer */
702 ::ioctl(m_pvr_fd_dst, 0);
704 /* flush ratebuffers (video, audio) */
706 m_decoder_demux->get().flush();
708 /* demux will also flush all decoder.. */
709 m_pvr_thread->seek(SEEK_SET, r);
710 m_pvr_thread->resume();