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/pmt.h>
6 #include <lib/dvb/sec.h>
7 #include <lib/dvb/specs.h>
9 #include <lib/dvb/fbc.h>
12 #include <sys/types.h>
16 #include <sys/ioctl.h>
18 DEFINE_REF(eDVBRegisteredFrontend);
19 DEFINE_REF(eDVBRegisteredDemux);
21 DEFINE_REF(eDVBAllocatedFrontend);
23 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
28 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
31 if (m_fe->m_frontend->is_FBCTuner())
33 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
41 DEFINE_REF(eDVBAllocatedDemux);
43 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
48 eDVBAllocatedDemux::~eDVBAllocatedDemux()
53 DEFINE_REF(eDVBResourceManager);
55 eDVBResourceManager *eDVBResourceManager::instance;
57 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
67 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
69 ePtr<eDVBResourceManager> ptr;
70 eDVBResourceManager::getInstance(ptr);
74 eDVBResourceManager::eDVBResourceManager()
75 :m_releaseCachedChannelTimer(eTimer::create(eApp))
79 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
84 /* search available adapters... */
89 while (eDVBAdapterLinux::exist(num_adapter))
91 addAdapter(new eDVBAdapterLinux(num_adapter));
95 int fd = open("/proc/stb/info/model", O_RDONLY);
97 int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
101 if (!strncmp(tmp, "dm7025\n", rd))
103 else if (!strncmp(tmp, "dm8000\n", rd))
105 else if (!strncmp(tmp, "dm800\n", rd))
107 else if (!strncmp(tmp, "dm500hd\n", rd))
109 else if (!strncmp(tmp, "dm800se\n", rd))
111 else if (!strncmp(tmp, "dm7020hd\n", rd))
112 m_boxtype = DM7020HD;
114 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
115 if (m_demux.size() == 3)
117 else if (m_demux.size() < 5)
123 eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
124 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
126 eDVBCAService::registerChannelCallback(this);
128 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
131 void eDVBResourceManager::feStateChanged()
134 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
136 mask |= ( 1 << i->m_frontend->getSlotID() );
137 /* emit */ frontendUseMaskChanged(mask);
140 DEFINE_REF(eDVBAdapterLinux);
141 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
146 eDebug("scanning for frontends..");
151 #if HAVE_DVB_API_VERSION < 3
152 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
154 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
156 if (stat(filename, &s))
162 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
164 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
169 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
171 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
182 #if HAVE_DVB_API_VERSION < 3
183 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
185 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
187 if (stat(filename, &s))
189 ePtr<eDVBDemux> demux;
191 demux = new eDVBDemux(m_nr, num_demux);
192 m_demux.push_back(demux);
198 int eDVBAdapterLinux::getNumDemux()
200 return m_demux.size();
203 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
205 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
206 while (nr && (i != m_demux.end()))
212 if (i != m_demux.end())
220 int eDVBAdapterLinux::getNumFrontends()
222 return m_frontend.size();
225 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
227 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
228 while (nr && (i != m_frontend.end()))
234 if (i != m_frontend.end())
242 int eDVBAdapterLinux::exist(int nr)
246 #if HAVE_DVB_API_VERSION < 3
247 sprintf(filename, "/dev/dvb/card%d", nr);
249 sprintf(filename, "/dev/dvb/adapter%d", nr);
251 if (!stat(filename, &s))
256 eDVBResourceManager::~eDVBResourceManager()
258 if (instance == this)
262 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
264 int num_fe = adapter->getNumFrontends();
265 int num_demux = adapter->getNumDemux();
267 m_adapter.push_back(adapter);
270 for (i=0; i<num_demux; ++i)
272 ePtr<eDVBDemux> demux;
273 if (!adapter->getDemux(demux, i))
274 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
277 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
278 for (i=0; i<num_fe; ++i)
280 ePtr<eDVBFrontend> frontend;
281 if (!adapter->getFrontend(frontend, i))
283 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
284 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
285 m_frontend.push_back(new_fe);
286 frontend->setSEC(m_sec);
287 // we must link all dvb-t frontends ( for active antenna voltage )
288 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
290 if (prev_dvbt_frontend)
292 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
293 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
295 prev_dvbt_frontend = new_fe;
300 prev_dvbt_frontend = 0;
301 for (i=0; i<num_fe; ++i)
303 ePtr<eDVBFrontend> frontend;
304 if (!adapter->getFrontend(frontend, i, true))
306 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
307 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
308 m_simulate_frontend.push_back(new_fe);
309 frontend->setSEC(m_sec);
310 // we must link all dvb-t frontends ( for active antenna voltage )
311 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
313 if (prev_dvbt_frontend)
315 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
316 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
318 prev_dvbt_frontend = new_fe;
325 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
327 if (!PyList_Check(list))
329 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
332 unsigned int assigned=0;
333 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
336 while (pos < PyList_Size(list)) {
337 ePyObject obj = PyList_GET_ITEM(list, pos++);
338 if (!i->m_frontend->setSlotInfo(obj))
344 if (assigned != m_frontend.size()) {
346 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
347 m_frontend.size(), assigned);
348 PyErr_SetString(PyExc_StandardError, blasel);
351 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
354 while (pos < PyList_Size(list)) {
355 ePyObject obj = PyList_GET_ITEM(list, pos++);
356 if (!i->m_frontend->setSlotInfo(obj))
364 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
366 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
368 if (i->m_frontend->getSlotID() == index)
370 if (!strcmp(type, "DVB-S2"))
372 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
374 else if (!strcmp(type, "DVB-S"))
376 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
378 else if (!strcmp(type, "DVB-T2"))
380 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
382 else if (!strcmp(type, "DVB-T"))
384 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
386 else if (!strcmp(type, "DVB-C"))
388 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
389 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
391 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
399 void eDVBResourceManager::setFrontendType(int index, const char *type)
401 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
403 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
405 if (i->m_frontend->getSlotID() == index)
407 std::vector<fe_delivery_system_t> whitelist;
408 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
410 whitelist.push_back(SYS_DVBS);
411 whitelist.push_back(SYS_DVBS2);
413 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
415 whitelist.push_back(SYS_DVBT);
416 whitelist.push_back(SYS_DVBT2);
418 else if (!strcmp(type, "DVB-C"))
420 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
421 whitelist.push_back(SYS_DVBC_ANNEX_A);
423 whitelist.push_back(SYS_DVBC_ANNEX_AC);
426 i->m_frontend->setDeliverySystemWhitelist(whitelist);
432 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
434 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
435 // ePtr<eDVBRegisteredFrontend> best;
436 eDVBRegisteredFrontend *best = NULL;
440 int check_fbc_linked = 0;
441 eDVBRegisteredFrontend *fbc_fe = NULL;
442 eDVBRegisteredFrontend *best_fbc_fe = NULL;
443 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
445 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
449 if (!check_fbc_linked && i->m_frontend->is_FBCTuner() && fbcmng && fbcmng->canLink(*i))
451 check_fbc_linked = 1;
452 c = fbcmng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
454 // eDebug("[eDVBResourceManager::allocateFrontend] fbcmng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i, i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);
458 c = i->m_frontend->isCompatibleWith(feparm);
461 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
466 // eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
472 best_fbc_fe = fbc_fe;
477 // eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
480 eDVBRegisteredFrontend *tmp = *i;
485 if (fbcmng && best_fbc_fe)
487 fbcmng->addLink(best, best_fbc_fe, simulate);
490 fe = new eDVBAllocatedFrontend(best);
497 return errAllSourcesBusy;
499 return errNoSourceFound;
502 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
504 int err = errNoSourceFound;
505 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
506 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
508 // check if another slot linked to this is in use
510 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
513 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
514 if (satpos_depends_to_fe->m_inuse)
516 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
517 err = errAllSourcesBusy;
518 goto alloc_fe_by_id_not_possible;
521 else // check linked tuners
523 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
526 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
529 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
530 err = errAllSourcesBusy;
531 goto alloc_fe_by_id_not_possible;
533 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
535 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
538 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
541 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
542 err = errAllSourcesBusy;
543 goto alloc_fe_by_id_not_possible;
545 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
548 fe = new eDVBAllocatedFrontend(i);
551 alloc_fe_by_id_not_possible:
556 #define capHoldDecodeReference 64
558 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
560 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
561 never use the first one unless we need a decoding demux. */
563 eDebug("allocate demux");
564 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
568 if (i == m_demux.end())
571 ePtr<eDVBRegisteredDemux> unused;
573 if (m_boxtype == DM800) // dm800
575 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
576 for (; i != m_demux.end(); ++i, ++n)
587 if (i->m_adapter == fe->m_adapter &&
588 i->m_demux->getSource() == fe->m_frontend->getDVBID())
590 demux = new eDVBAllocatedDemux(i);
594 else if (i->m_demux->getSource() == -1) // PVR
596 demux = new eDVBAllocatedDemux(i);
602 else if (m_boxtype == DM7025) // ATI
604 /* FIXME: hardware demux policy */
605 if (!(cap & iDVBChannel::capDecode))
607 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
614 for (; i != m_demux.end(); ++i, ++n)
616 int is_decode = n < 2;
618 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
620 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
622 if ((cap & iDVBChannel::capDecode) && !is_decode)
629 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
631 iDVBAdapter *adapter = fe ? fe->m_adapter : m_adapter.begin(); /* look for a demux on the same adapter as the frontend, or the first adapter for dvr playback */
632 int source = fe ? fe->m_frontend->getDVBID() : -1;
633 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
637 * For pvr playback, start with the last demux.
638 * On some hardware, we have less ca devices than demuxes,
639 * so we should try to leave the first demuxes for live tv,
640 * and start with the last for pvr playback
645 while (i != m_demux.end())
647 if (i->m_adapter == adapter)
651 /* mark the first unused demux, we'll use that when we do not find a better match */
652 if (!unused) unused = i;
656 /* demux is in use, see if we can share it */
657 if (source >= 0 && i->m_demux->getSource() == source)
659 demux = new eDVBAllocatedDemux(i);
677 demux = new eDVBAllocatedDemux(unused);
679 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
681 demux->get().setSourcePVR(0);
685 eDebug("demux not found");
689 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
695 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
704 #define eDebugNoSimulate(x...) \
710 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
712 /* first, check if a channel is already existing. */
713 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
715 if (!simulate && m_cached_channel)
717 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
718 if(channelid==cache_chan->getChannelID())
720 eDebug("use cached_channel");
721 channel = m_cached_channel;
724 m_cached_channel_state_changed_conn.disconnect();
726 m_releaseCachedChannelTimer->stop();
729 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
730 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
732 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
733 if (i->m_channel_id == channelid)
735 eDebugNoSimulate("found shared channel..");
736 channel = i->m_channel;
741 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
745 eDebugNoSimulate("no channel list set!");
746 return errNoChannelList;
749 ePtr<iDVBFrontendParameters> feparm;
750 if (m_list->getChannelFrontendData(channelid, feparm))
752 eDebugNoSimulate("channel not found!");
753 return errChannelNotInList;
756 /* allocate a frontend. */
758 ePtr<eDVBAllocatedFrontend> fe;
760 int err = allocateFrontend(fe, feparm, simulate);
765 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
767 res = ch->setChannel(channelid, feparm);
771 return errChidNotFound;
778 m_cached_channel = channel = ch;
779 m_cached_channel_state_changed_conn =
780 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
786 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
789 chan->getState(state);
792 case iDVBChannel::state_release:
793 case iDVBChannel::state_ok:
795 eDebug("stop release channel timer");
796 m_releaseCachedChannelTimer->stop();
799 case iDVBChannel::state_last_instance:
801 eDebug("start release channel timer");
802 m_releaseCachedChannelTimer->start(3000, true);
805 default: // ignore all other events
810 void eDVBResourceManager::releaseCachedChannel()
812 eDebug("release cached channel (timer timeout)");
816 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
818 ePtr<eDVBAllocatedFrontend> fe;
820 if (m_cached_channel)
822 m_cached_channel_state_changed_conn.disconnect();
824 m_releaseCachedChannelTimer->stop();
827 int err = allocateFrontendByIndex(fe, slot_index);
831 channel = new eDVBChannel(this, fe);
835 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
837 ePtr<eDVBAllocatedDemux> demux;
839 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
841 m_cached_channel_state_changed_conn.disconnect();
843 m_releaseCachedChannelTimer->stop();
846 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
850 * user provided a channelid, with the clear intention for
851 * this channel to be registered at the resource manager.
852 * (allowing e.g. epgcache to be started)
854 ePtr<iDVBFrontendParameters> feparm;
855 ch->setChannel(channelid, feparm);
861 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
863 ePtr<iDVBFrontend> fe;
864 if (!ch->getFrontend(fe))
866 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
867 if (frontend->is_simulate())
868 m_active_simulate_channels.push_back(active_channel(chid, ch));
871 m_active_channels.push_back(active_channel(chid, ch));
872 /* emit */ m_channelAdded(ch);
878 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
880 ePtr<iDVBFrontend> fe;
881 if (!ch->getFrontend(fe))
883 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
884 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
886 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
888 if (i->m_channel == ch)
890 i = active_channels.erase(i);
902 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
904 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
908 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
910 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
911 ePtr<eDVBRegisteredFrontend> best;
913 int check_fbc_link = 0;
914 eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
916 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
921 if(fbcmng && i->m_frontend->is_FBCTuner() && fbcmng->canLink(*i) && !check_fbc_link)
924 c = fbcmng->isCompatibleWith(feparm, *i, simulate);
928 c = i->m_frontend->isCompatibleWith(feparm);
937 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
939 system = iDVBFrontend::feSatellite;
942 ePtr<iDVBFrontendParameters> feparm;
943 if (!channellist->getChannelFrontendData(chid, feparm))
945 if (!feparm->getSystem(system))
949 case iDVBFrontend::feSatellite:
951 case iDVBFrontend::feCable:
953 case iDVBFrontend::feTerrestrial:
964 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
966 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
968 system = iDVBFrontend::feSatellite;
969 if (!simulate && m_cached_channel)
971 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
972 if(channelid==cache_chan->getChannelID())
973 return tuner_type_channel_default(m_list, channelid, system);
976 /* first, check if a channel is already existing. */
977 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
978 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
980 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
981 if (i->m_channel_id == channelid)
983 // eDebug("found shared channel..");
984 return tuner_type_channel_default(m_list, channelid, system);
988 int *decremented_cached_channel_fe_usecount=NULL,
989 *decremented_fe_usecount=NULL;
991 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
993 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
994 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
995 if (i->m_channel_id == ignore)
997 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
998 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
999 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1000 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1001 // or 2 when the cached channel is not equal to the compared channel
1002 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
1004 ePtr<iDVBFrontend> fe;
1005 if (!i->m_channel->getFrontend(fe))
1007 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1009 if ( &(*fe) == &(*ii->m_frontend) )
1012 decremented_fe_usecount = &ii->m_inuse;
1013 if (channel == &(*m_cached_channel))
1014 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1024 if (!decremented_cached_channel_fe_usecount)
1026 if (m_cached_channel)
1028 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1029 if (channel->getUseCount() == 1)
1031 ePtr<iDVBFrontend> fe;
1032 if (!channel->getFrontend(fe))
1034 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1035 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1037 if ( &(*fe) == &(*ii->m_frontend) )
1040 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1049 decremented_cached_channel_fe_usecount=NULL;
1051 ePtr<iDVBFrontendParameters> feparm;
1055 eDebug("no channel list set!");
1059 if (m_list->getChannelFrontendData(channelid, feparm))
1061 eDebug("channel not found!");
1064 feparm->getSystem(system);
1066 ret = canAllocateFrontend(feparm, simulate);
1069 if (decremented_fe_usecount)
1070 ++(*decremented_fe_usecount);
1071 if (decremented_cached_channel_fe_usecount)
1072 ++(*decremented_cached_channel_fe_usecount);
1077 bool eDVBResourceManager::canMeasureFrontendInputPower()
1079 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1081 return i->m_frontend->readInputpower() >= 0;
1086 class eDVBChannelFilePush: public eFilePushThread
1089 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1090 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1092 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1093 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1094 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1096 int m_iframe_search, m_iframe_state, m_pid;
1097 int m_timebase_change;
1098 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1101 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1104 if (m_timebase_change)
1106 eDebug("timebase change: %d", m_timebase_change);
1108 for (offset = 0; offset < len; offset += 188)
1110 unsigned char *pkt = (unsigned char*)_data + offset;
1111 if (pkt[1] & 0x40) /* pusi */
1113 if (pkt[3] & 0x20) // adaption field present?
1114 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1116 pkt += 4; /* skip header */
1117 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1119 eWarning("broken startcode");
1125 if (pkt[7] & 0x80) // PTS present?
1127 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1128 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1129 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1130 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1131 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1135 RESULT r = m_tstools.fixupPTS(off, pts);
1137 eWarning("fixup PTS while trickmode playback failed.\n");
1140 int sec = pts / 90000;
1141 int frm = pts % 90000;
1149 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1151 pts += 0x80000000LL;
1152 pts *= m_timebase_change;
1164 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1172 pkt[9] |= (pts >> 29) & 0xE;
1173 pkt[10] |= (pts >> 22) & 0xFF;
1174 pkt[11] |= (pts >> 14) & 0xFE;
1175 pkt[12] |= (pts >> 7) & 0xFF;
1176 pkt[13] |= (pts << 1) & 0xFE;
1184 if (!m_iframe_search)
1187 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1189 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1191 unsigned char *d = data;
1192 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1194 int offset = d - data;
1195 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1196 unsigned char *ts = data + ts_offset;
1197 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1199 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1201 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1204 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1206 if (m_iframe_state == 1)
1208 /* we are allowing data, and stop allowing data on the next frame.
1209 we now found a frame. so stop here. */
1210 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1211 current_span_remaining = 0;
1213 unsigned char *fts = ts + 188;
1214 while (fts < (data + len))
1217 fts[2] |= 0xff; /* drop packet */
1221 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1224 if (picture_type != 1) /* we are only interested in I frames */
1227 unsigned char *fts = data;
1231 fts[2] |= 0xff; /* drop packet */
1238 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1240 /* verify that this is actually a PES header, not just some ES data */
1241 if (ts[1] & 0x40) /* PUSI set */
1243 int payload_start = 4;
1244 if (ts[3] & 0x20) /* adaptation field present */
1245 payload_start += ts[4] + 1; /* skip AF */
1246 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1250 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1258 d += 4; /* ignore */
1261 if (m_iframe_state == 1)
1264 return 0; /* we need find an iframe first */
1270 DEFINE_REF(eDVBChannel);
1272 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1274 m_frontend = frontend;
1279 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1282 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1285 eDVBChannel::~eDVBChannel()
1288 m_mgr->removeChannel(this);
1293 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1295 int state, ourstate = 0;
1297 /* if we are already in shutdown, don't change state. */
1298 if (m_state == state_release)
1301 if (fe->getState(state))
1304 if (state == iDVBFrontend::stateLock)
1306 eDebug("OURSTATE: ok");
1307 ourstate = state_ok;
1308 } else if (state == iDVBFrontend::stateTuning)
1310 eDebug("OURSTATE: tuning");
1311 ourstate = state_tuning;
1312 } else if (state == iDVBFrontend::stateLostLock)
1314 /* on managed channels, we try to retune in order to re-acquire lock. */
1315 if (m_current_frontend_parameters)
1317 eDebug("OURSTATE: lost lock, trying to retune");
1318 ourstate = state_tuning;
1319 m_frontend->get().tune(*m_current_frontend_parameters);
1321 /* on unmanaged channels, we don't do this. the client will do this. */
1323 eDebug("OURSTATE: lost lock, unavailable now.");
1324 ourstate = state_unavailable;
1326 } else if (state == iDVBFrontend::stateFailed)
1329 if (m_current_frontend_parameters)
1331 eDebug("OURSTATE: lost lock, trying to retune");
1332 ourstate = state_tuning;
1333 m_frontend->get().tune(*m_current_frontend_parameters);
1337 eDebug("OURSTATE: failed");
1338 ourstate = state_failed;
1341 eDebug("OURSTATE: failed");
1342 ourstate = state_failed;
1345 eFatal("state unknown");
1347 if (ourstate != m_state)
1350 m_stateChanged(this);
1354 void eDVBChannel::pvrEvent(int event)
1358 case eFilePushThread::evtEOF:
1359 eDebug("eDVBChannel: End of file!");
1360 m_event(this, evtEOF);
1362 case eFilePushThread::evtUser: /* start */
1364 m_event(this, evtSOF);
1369 void eDVBChannel::cueSheetEvent(int event)
1371 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1376 case eCueSheet::evtSeek:
1378 flushPVR(m_cue->m_decoding_demux);
1380 case eCueSheet::evtSkipmode:
1383 m_cue->m_lock.WrLock();
1384 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1385 m_cue->m_lock.Unlock();
1386 eRdLocker l(m_cue->m_lock);
1387 if (m_cue->m_skipmode_ratio)
1389 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1390 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1391 /* i agree that this might look a bit like black magic. */
1392 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1393 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1394 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1395 m_skipmode_frames_remainder = 0;
1397 if (m_cue->m_skipmode_ratio < 0)
1398 m_skipmode_m -= m_skipmode_n;
1400 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1402 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1404 eWarning("something is wrong with this calculation");
1405 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1409 eDebug("skipmode ratio is 0, normal play");
1410 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1413 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1414 if (m_cue->m_skipmode_ratio != 0)
1415 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1417 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1418 eDebug("flush pvr");
1419 flushPVR(m_cue->m_decoding_demux);
1423 case eCueSheet::evtSpanChanged:
1425 m_source_span.clear();
1426 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1428 off_t offset_in, offset_out;
1429 pts_t pts_in = i->first, pts_out = i->second;
1430 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1432 eDebug("span translation failed.\n");
1435 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1436 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1443 /* align toward zero */
1444 static inline long long align(long long x, int align)
1459 /* align toward zero */
1460 static inline long long align_with_len(long long x, int align, size_t &len)
1477 /* remember, this gets called from another thread. */
1478 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1480 const int blocksize = 188;
1481 unsigned int max = align(10*1024*1024, blocksize);
1482 current_offset = align(current_offset, blocksize);
1486 eDebug("no cue sheet. forcing normal play");
1487 start = current_offset;
1494 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1495 max = align(m_skipmode_n, blocksize);
1498 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1499 int frame_skip_success = 0;
1503 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1504 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1506 off_t iframe_start = current_offset;
1507 int frames_skipped = frames_to_skip;
1508 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1510 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1511 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1512 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1513 max = align(iframe_len + 187, blocksize);
1514 frame_skip_success = 1;
1517 m_skipmode_frames_remainder = 0;
1518 eDebug("frame skipping failed, reverting to byte-skipping");
1522 if (!frame_skip_success)
1524 current_offset += align(m_skipmode_m, blocksize);
1525 if(current_offset < 0)
1531 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1533 off_t start_offset = current_offset;
1534 off_t new_offset = start_offset;
1535 int direction = (m_skipmode_m < 0) ? -1 : +1;
1536 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1540 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1541 max = align(iframe_len, blocksize);
1547 m_cue->m_lock.RdLock();
1549 while (!m_cue->m_seek_requests.empty())
1551 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1552 m_cue->m_lock.Unlock();
1553 m_cue->m_lock.WrLock();
1554 m_cue->m_seek_requests.pop_front();
1555 m_cue->m_lock.Unlock();
1556 m_cue->m_lock.RdLock();
1557 int relative = seek.first;
1558 pts_t pts = seek.second;
1563 if (!m_cue->m_decoder)
1565 eDebug("no decoder - can't seek relative");
1568 if (m_cue->m_decoder->getPTS(0, now))
1570 eDebug("decoder getPTS failed, can't seek relative");
1573 if (!m_cue->m_decoding_demux)
1575 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1576 start = current_offset;
1580 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1582 eDebug("seekTo: getCurrentPosition failed!");
1585 } else if (pts < 0) /* seek relative to end */
1588 if (!getLength(len))
1590 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1594 eWarning("getLength failed - can't seek relative to end!");
1599 if (relative == 1) /* pts relative */
1610 if (relative == 2) /* AP relative */
1612 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1614 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1616 pts = now - 90000; /* approx. 1s */
1617 eDebug("AP relative seeking failed!");
1621 eDebug("next ap is %llx\n", pts);
1626 if (m_tstools.getOffset(offset, pts, -1))
1628 eDebug("get offset for pts=%lld failed!", pts);
1632 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1633 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1636 m_cue->m_lock.Unlock();
1638 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1640 long long aligned_start = align(i->first, blocksize);
1641 long long aligned_end = align(i->second, blocksize);
1643 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1645 start = current_offset;
1646 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1647 if ((aligned_end - current_offset) > max)
1650 size = aligned_end - current_offset;
1651 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1654 if (current_offset < aligned_start)
1656 /* ok, our current offset is in an 'out' zone. */
1657 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1659 /* in normal playback, just start at the next zone. */
1662 /* size is not 64bit! */
1663 if ((i->second - i->first) > max)
1666 size = aligned_end - aligned_start;
1669 if (m_skipmode_m < 0)
1671 eDebug("reached SOF");
1674 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1678 /* when skipping reverse, however, choose the zone before. */
1680 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1683 aligned_start = align(i->first, blocksize);
1684 aligned_end = align(i->second, blocksize);
1686 if ((aligned_end - aligned_start) > max)
1689 len = aligned_end - aligned_start;
1691 start = aligned_end - len;
1692 eDebug("skipping to %llx, %zd", start, len);
1695 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1700 if(current_offset <0)
1702 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1704 eDebug("reached SOF");
1706 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1708 if (m_source_span.empty())
1710 start = current_offset;
1712 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1715 start = current_offset;
1721 void eDVBChannel::AddUse()
1723 if (++m_use_count > 1 && m_state == state_last_instance)
1726 m_stateChanged(this);
1730 void eDVBChannel::ReleaseUse()
1734 m_state = state_release;
1735 m_stateChanged(this);
1737 else if (m_use_count == 1)
1739 m_state = state_last_instance;
1740 m_stateChanged(this);
1744 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1747 m_mgr->removeChannel(this);
1752 m_channel_id = channelid;
1753 m_mgr->addChannel(channelid, this);
1757 /* no frontend, no need to tune (must be a streamed service) */
1761 m_state = state_tuning;
1762 /* if tuning fails, shutdown the channel immediately. */
1764 res = m_frontend->get().tune(*feparm);
1765 m_current_frontend_parameters = feparm;
1769 m_state = state_release;
1770 m_stateChanged(this);
1777 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1779 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1783 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1785 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1789 RESULT eDVBChannel::getState(int &state)
1795 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1800 void eDVBChannel::SDTready(int result)
1802 ePyObject args = PyTuple_New(2), ret;
1806 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1809 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1810 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1816 PyTuple_SET_ITEM(args, 0, Py_None);
1817 PyTuple_SET_ITEM(args, 1, Py_None);
1821 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1825 Py_DECREF(m_tsid_onid_callback);
1826 m_tsid_onid_callback = ePyObject();
1827 m_tsid_onid_demux = 0;
1831 int eDVBChannel::reserveDemux()
1833 ePtr<iDVBDemux> dmx;
1834 if (!getDemux(dmx, 0))
1837 if (!dmx->getCADemuxID(id))
1843 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1845 if (PyCallable_Check(callback))
1847 if (!getDemux(m_tsid_onid_demux, 0))
1849 m_SDT = new eTable<ServiceDescriptionSection>;
1850 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1851 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1853 m_tsid_onid_demux = 0;
1858 Py_INCREF(callback);
1859 m_tsid_onid_callback = callback;
1867 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1869 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1871 if (m_frontend == NULL)
1873 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1874 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1881 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1886 /* don't hold a reference to the decoding demux, we don't need it. */
1888 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1889 the refcount is lost. thus, decoding demuxes are never allocated.
1891 this poses a big problem for PiP. */
1893 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1895 else if (cap & capDecode)
1904 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1909 frontend = &m_frontend->get();
1915 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1917 param = m_current_frontend_parameters;
1921 RESULT eDVBChannel::playFile(const char *file)
1923 eRawFile *f = new eRawFile();
1924 ePtr<iTsSource> source = f;
1926 if (f->open(file) < 0)
1928 eDebug("can't open PVR file %s (%m)", file);
1932 return playSource(source, file);
1935 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1937 ASSERT(!m_frontend);
1940 m_pvr_thread->stop();
1941 delete m_pvr_thread;
1945 if (!source->valid() && !source->isStream())
1947 eDebug("PVR source is not valid!");
1951 m_tstools.setSource(source, streaminfo_file);
1953 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1954 THEN DO A REAL FIX HERE! */
1956 if (m_pvr_fd_dst < 0)
1958 /* (this codepath needs to be improved anyway.) */
1959 #if HAVE_DVB_API_VERSION < 3
1960 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1961 if (m_pvr_fd_dst < 0)
1963 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1967 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1970 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1971 if (m_pvr_fd_dst < 0)
1973 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1979 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1985 m_pvr_thread = new eDVBChannelFilePush();
1986 m_pvr_thread->enablePVRCommit(1);
1987 /* If the source specifies a length, it's a file. If not, it's a stream */
1988 m_pvr_thread->setStreamMode(source->isStream());
1989 m_pvr_thread->setScatterGather(this);
1991 m_event(this, evtPreStart);
1993 m_pvr_thread->start(source, m_pvr_fd_dst);
1994 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1997 m_stateChanged(this);
2002 void eDVBChannel::stopSource()
2006 m_pvr_thread->stop();
2007 delete m_pvr_thread;
2010 if (m_pvr_fd_dst >= 0)
2011 ::close(m_pvr_fd_dst);
2013 m_tstools.setSource(d);
2016 void eDVBChannel::stopFile()
2021 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2023 m_conn_cueSheetEvent = 0;
2026 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2029 RESULT eDVBChannel::getLength(pts_t &len)
2031 return m_tstools.calcLen(len);
2034 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2036 if (!decoding_demux)
2043 if (mode == 0) /* demux */
2045 r = decoding_demux->getSTC(now, 0);
2048 eDebug("demux getSTC failed");
2052 now = pos; /* fixup supplied */
2054 off_t off = 0; /* TODO: fixme */
2055 r = m_tstools.fixupPTS(off, now);
2058 eDebug("fixup PTS failed");
2067 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2069 /* when seeking, we have to ensure that all buffers are flushed.
2070 there are basically 3 buffers:
2071 a.) the filepush's internal buffer
2072 b.) the PVR buffer (before demux)
2073 c.) the ratebuffer (after demux)
2075 it's important to clear them in the correct order, otherwise
2076 the ratebuffer (for example) would immediately refill from
2077 the not-yet-flushed PVR buffer.
2080 m_pvr_thread->pause();
2081 /* flush internal filepush buffer */
2082 m_pvr_thread->flush();
2083 /* HACK: flush PVR buffer */
2084 ::ioctl(m_pvr_fd_dst, 0);
2086 /* flush ratebuffers (video, audio) */
2088 decoding_demux->flush();
2090 /* demux will also flush all decoder.. */
2091 /* resume will re-query the SG */
2092 m_pvr_thread->resume();
2095 DEFINE_REF(eCueSheet);
2097 eCueSheet::eCueSheet()
2099 m_skipmode_ratio = 0;
2102 void eCueSheet::seekTo(int relative, const pts_t &pts)
2105 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2110 void eCueSheet::clear()
2117 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2119 ASSERT(begin < end);
2121 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2125 void eCueSheet::commitSpans()
2127 m_event(evtSpanChanged);
2130 void eCueSheet::setSkipmode(const pts_t &ratio)
2133 m_skipmode_ratio = ratio;
2135 m_event(evtSkipmode);
2138 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2140 m_decoding_demux = demux;
2141 m_decoder = decoder;
2144 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2146 connection = new eConnection(this, m_event.connect(event));