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>
10 #include <lib/dvb/fcc.h>
13 #include <sys/types.h>
17 #include <sys/ioctl.h>
19 DEFINE_REF(eDVBRegisteredFrontend);
20 DEFINE_REF(eDVBRegisteredDemux);
22 DEFINE_REF(eDVBAllocatedFrontend);
24 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
29 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
32 if (m_fe->m_frontend->is_FBCTuner())
34 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
42 DEFINE_REF(eDVBAllocatedDemux);
44 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
49 eDVBAllocatedDemux::~eDVBAllocatedDemux()
54 DEFINE_REF(eDVBResourceManager);
56 eDVBResourceManager *eDVBResourceManager::instance;
58 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
68 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
70 ePtr<eDVBResourceManager> ptr;
71 eDVBResourceManager::getInstance(ptr);
75 eDVBResourceManager::eDVBResourceManager()
76 :m_releaseCachedChannelTimer(eTimer::create(eApp))
80 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
85 /* search available adapters... */
90 while (eDVBAdapterLinux::exist(num_adapter))
92 addAdapter(new eDVBAdapterLinux(num_adapter));
96 int fd = open("/proc/stb/info/model", O_RDONLY);
98 int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
102 if (!strncmp(tmp, "dm7025\n", rd))
104 else if (!strncmp(tmp, "dm8000\n", rd))
106 else if (!strncmp(tmp, "dm800\n", rd))
108 else if (!strncmp(tmp, "dm500hd\n", rd))
110 else if (!strncmp(tmp, "dm800se\n", rd))
112 else if (!strncmp(tmp, "dm7020hd\n", rd))
113 m_boxtype = DM7020HD;
115 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
116 if (m_demux.size() == 3)
118 else if (m_demux.size() < 5)
124 eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
125 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
127 eDVBCAService::registerChannelCallback(this);
129 m_fbc_mng = new eFBCTunerManager(this);
131 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
134 void eDVBResourceManager::feStateChanged()
137 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
139 mask |= ( 1 << i->m_frontend->getSlotID() );
140 /* emit */ frontendUseMaskChanged(mask);
143 DEFINE_REF(eDVBAdapterLinux);
144 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
149 eDebug("scanning for frontends..");
154 #if HAVE_DVB_API_VERSION < 3
155 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
157 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
159 if (stat(filename, &s))
165 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
167 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
172 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
174 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
185 #if HAVE_DVB_API_VERSION < 3
186 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
188 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
190 if (stat(filename, &s))
192 ePtr<eDVBDemux> demux;
194 demux = new eDVBDemux(m_nr, num_demux);
195 m_demux.push_back(demux);
201 int eDVBAdapterLinux::getNumDemux()
203 return m_demux.size();
206 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
208 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
209 while (nr && (i != m_demux.end()))
215 if (i != m_demux.end())
223 int eDVBAdapterLinux::getNumFrontends()
225 return m_frontend.size();
228 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
230 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
231 while (nr && (i != m_frontend.end()))
237 if (i != m_frontend.end())
245 int eDVBAdapterLinux::exist(int nr)
249 #if HAVE_DVB_API_VERSION < 3
250 sprintf(filename, "/dev/dvb/card%d", nr);
252 sprintf(filename, "/dev/dvb/adapter%d", nr);
254 if (!stat(filename, &s))
259 eDVBResourceManager::~eDVBResourceManager()
261 if (instance == this)
265 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
267 int num_fe = adapter->getNumFrontends();
268 int num_demux = adapter->getNumDemux();
270 m_adapter.push_back(adapter);
273 for (i=0; i<num_demux; ++i)
275 ePtr<eDVBDemux> demux;
276 if (!adapter->getDemux(demux, i))
277 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
280 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
281 for (i=0; i<num_fe; ++i)
283 ePtr<eDVBFrontend> frontend;
284 if (!adapter->getFrontend(frontend, i))
286 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
287 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
288 m_frontend.push_back(new_fe);
289 frontend->setSEC(m_sec);
290 // we must link all dvb-t frontends ( for active antenna voltage )
291 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
293 if (prev_dvbt_frontend)
295 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
296 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
298 prev_dvbt_frontend = new_fe;
303 prev_dvbt_frontend = 0;
304 for (i=0; i<num_fe; ++i)
306 ePtr<eDVBFrontend> frontend;
307 if (!adapter->getFrontend(frontend, i, true))
309 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
310 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
311 m_simulate_frontend.push_back(new_fe);
312 frontend->setSEC(m_sec);
313 // we must link all dvb-t frontends ( for active antenna voltage )
314 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
316 if (prev_dvbt_frontend)
318 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
319 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
321 prev_dvbt_frontend = new_fe;
328 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
330 if (!PyList_Check(list))
332 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
335 unsigned int assigned=0;
336 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
339 while (pos < PyList_Size(list)) {
340 ePyObject obj = PyList_GET_ITEM(list, pos++);
341 if (!i->m_frontend->setSlotInfo(obj))
347 if (assigned != m_frontend.size()) {
349 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
350 m_frontend.size(), assigned);
351 PyErr_SetString(PyExc_StandardError, blasel);
354 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
357 while (pos < PyList_Size(list)) {
358 ePyObject obj = PyList_GET_ITEM(list, pos++);
359 if (!i->m_frontend->setSlotInfo(obj))
367 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
369 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
371 if (i->m_frontend->getSlotID() == index)
373 if (!strcmp(type, "DVB-S2"))
375 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
377 else if (!strcmp(type, "DVB-S"))
379 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
381 else if (!strcmp(type, "DVB-T2"))
383 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
385 else if (!strcmp(type, "DVB-T"))
387 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
389 else if (!strcmp(type, "DVB-C"))
391 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
392 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
394 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
402 void eDVBResourceManager::setFrontendType(int index, const char *type)
404 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
406 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
408 if (i->m_frontend->getSlotID() == index)
410 std::vector<fe_delivery_system_t> whitelist;
411 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
413 whitelist.push_back(SYS_DVBS);
414 whitelist.push_back(SYS_DVBS2);
416 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
418 whitelist.push_back(SYS_DVBT);
419 whitelist.push_back(SYS_DVBT2);
421 else if (!strcmp(type, "DVB-C"))
423 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
424 whitelist.push_back(SYS_DVBC_ANNEX_A);
426 whitelist.push_back(SYS_DVBC_ANNEX_AC);
429 i->m_frontend->setDeliverySystemWhitelist(whitelist);
435 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
437 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
438 eDVBRegisteredFrontend *best = NULL;
442 int check_fbc_leaf_linkable = 0;
443 int current_fbc_setid = -1;
444 eDVBRegisteredFrontend *fbc_fe = NULL;
445 eDVBRegisteredFrontend *best_fbc_fe = NULL;
447 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
451 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
453 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
454 if (fbc_setid != current_fbc_setid)
456 current_fbc_setid = fbc_setid;
457 check_fbc_leaf_linkable = 0;
460 if (!check_fbc_leaf_linkable)
462 c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
463 check_fbc_leaf_linkable = 1;
464 eDebug("[eDVBResourceManager::allocateFrontend] m_fbc_mng->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);
469 c = i->m_frontend->isCompatibleWith(feparm);
472 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
477 eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
482 best_fbc_fe = fbc_fe;
487 eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
490 eDVBRegisteredFrontend *tmp = *i;
497 m_fbc_mng->addLink(best, best_fbc_fe, simulate);
500 fe = new eDVBAllocatedFrontend(best);
507 return errAllSourcesBusy;
509 return errNoSourceFound;
512 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
514 int err = errNoSourceFound;
515 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
516 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
518 // check if another slot linked to this is in use
520 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
523 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
524 if (satpos_depends_to_fe->m_inuse)
526 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
527 err = errAllSourcesBusy;
528 goto alloc_fe_by_id_not_possible;
531 else // check linked tuners
533 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
536 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
539 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
540 err = errAllSourcesBusy;
541 goto alloc_fe_by_id_not_possible;
543 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
545 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
548 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
551 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
552 err = errAllSourcesBusy;
553 goto alloc_fe_by_id_not_possible;
555 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
558 fe = new eDVBAllocatedFrontend(i);
561 alloc_fe_by_id_not_possible:
566 #define capHoldDecodeReference 64
568 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
570 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
571 never use the first one unless we need a decoding demux. */
573 eDebug("allocate demux");
574 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
578 if (i == m_demux.end())
581 ePtr<eDVBRegisteredDemux> unused;
583 if (m_boxtype == DM800) // dm800
585 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
586 for (; i != m_demux.end(); ++i, ++n)
597 if (i->m_adapter == fe->m_adapter &&
598 i->m_demux->getSource() == fe->m_frontend->getDVBID())
600 demux = new eDVBAllocatedDemux(i);
604 else if (i->m_demux->getSource() == -1) // PVR
606 demux = new eDVBAllocatedDemux(i);
612 else if (m_boxtype == DM7025) // ATI
614 /* FIXME: hardware demux policy */
615 if (!(cap & iDVBChannel::capDecode))
617 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
624 for (; i != m_demux.end(); ++i, ++n)
626 int is_decode = n < 2;
628 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
630 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
632 if ((cap & iDVBChannel::capDecode) && !is_decode)
639 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
641 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 */
642 int source = fe ? fe->m_frontend->getDVBID() : -1;
643 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
647 * For pvr playback, start with the last demux.
648 * On some hardware, we have less ca devices than demuxes,
649 * so we should try to leave the first demuxes for live tv,
650 * and start with the last for pvr playback
655 while (i != m_demux.end())
657 if (i->m_adapter == adapter)
661 /* mark the first unused demux, we'll use that when we do not find a better match */
662 if (!unused) unused = i;
666 /* demux is in use, see if we can share it */
667 if (source >= 0 && i->m_demux->getSource() == source)
669 demux = new eDVBAllocatedDemux(i);
687 demux = new eDVBAllocatedDemux(unused);
689 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
691 demux->get().setSourcePVR(0);
695 eDebug("demux not found");
699 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
705 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
714 #define eDebugNoSimulate(x...) \
720 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
722 /* first, check if a channel is already existing. */
723 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
725 if (!simulate && m_cached_channel)
727 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
728 if(channelid==cache_chan->getChannelID())
730 eDebug("use cached_channel");
731 channel = m_cached_channel;
734 m_cached_channel_state_changed_conn.disconnect();
736 m_releaseCachedChannelTimer->stop();
739 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
740 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
742 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
743 if (i->m_channel_id == channelid)
745 eDebugNoSimulate("found shared channel..");
746 channel = i->m_channel;
751 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
755 eDebugNoSimulate("no channel list set!");
756 return errNoChannelList;
759 ePtr<iDVBFrontendParameters> feparm;
760 if (m_list->getChannelFrontendData(channelid, feparm))
762 eDebugNoSimulate("channel not found!");
763 return errChannelNotInList;
766 /* allocate a frontend. */
768 ePtr<eDVBAllocatedFrontend> fe;
770 int err = allocateFrontend(fe, feparm, simulate);
775 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
777 res = ch->setChannel(channelid, feparm);
781 return errChidNotFound;
788 m_cached_channel = channel = ch;
789 m_cached_channel_state_changed_conn =
790 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
796 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
799 chan->getState(state);
802 case iDVBChannel::state_release:
803 case iDVBChannel::state_ok:
805 eDebug("stop release channel timer");
806 m_releaseCachedChannelTimer->stop();
809 case iDVBChannel::state_last_instance:
811 eDebug("start release channel timer");
812 m_releaseCachedChannelTimer->start(3000, true);
815 default: // ignore all other events
820 void eDVBResourceManager::releaseCachedChannel()
822 eDebug("release cached channel (timer timeout)");
826 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
828 ePtr<eDVBAllocatedFrontend> fe;
830 if (m_cached_channel)
832 m_cached_channel_state_changed_conn.disconnect();
834 m_releaseCachedChannelTimer->stop();
837 int err = allocateFrontendByIndex(fe, slot_index);
841 channel = new eDVBChannel(this, fe);
845 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
847 ePtr<eDVBAllocatedDemux> demux;
849 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
851 m_cached_channel_state_changed_conn.disconnect();
853 m_releaseCachedChannelTimer->stop();
856 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
860 * user provided a channelid, with the clear intention for
861 * this channel to be registered at the resource manager.
862 * (allowing e.g. epgcache to be started)
864 ePtr<iDVBFrontendParameters> feparm;
865 ch->setChannel(channelid, feparm);
871 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
873 ePtr<iDVBFrontend> fe;
874 if (!ch->getFrontend(fe))
876 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
877 if (frontend->is_simulate())
878 m_active_simulate_channels.push_back(active_channel(chid, ch));
881 m_active_channels.push_back(active_channel(chid, ch));
882 /* emit */ m_channelAdded(ch);
888 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
890 ePtr<iDVBFrontend> fe;
891 if (!ch->getFrontend(fe))
893 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
894 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
896 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
898 if (i->m_channel == ch)
900 i = active_channels.erase(i);
912 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
914 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
918 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
920 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
921 ePtr<eDVBRegisteredFrontend> best;
923 int check_fbc_leaf_linkable = 0;
924 int current_fbc_setid = -1;
926 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
931 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
933 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
934 if (fbc_setid != current_fbc_setid)
936 current_fbc_setid = fbc_setid;
937 check_fbc_leaf_linkable = 0;
940 if (!check_fbc_leaf_linkable)
942 eDVBRegisteredFrontend *dummy;
943 c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
944 check_fbc_leaf_linkable = 1;
949 c = i->m_frontend->isCompatibleWith(feparm);
958 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
960 system = iDVBFrontend::feSatellite;
963 ePtr<iDVBFrontendParameters> feparm;
964 if (!channellist->getChannelFrontendData(chid, feparm))
966 if (!feparm->getSystem(system))
970 case iDVBFrontend::feSatellite:
972 case iDVBFrontend::feCable:
974 case iDVBFrontend::feTerrestrial:
985 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
987 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
989 system = iDVBFrontend::feSatellite;
990 if (!simulate && m_cached_channel)
992 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
993 if(channelid==cache_chan->getChannelID())
994 return tuner_type_channel_default(m_list, channelid, system);
997 /* first, check if a channel is already existing. */
998 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
999 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1001 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1002 if (i->m_channel_id == channelid)
1004 // eDebug("found shared channel..");
1005 return tuner_type_channel_default(m_list, channelid, system);
1009 int *decremented_cached_channel_fe_usecount=NULL,
1010 *decremented_fe_usecount=NULL;
1012 /* check FCC channels */
1013 std::vector<int*> fcc_decremented_fe_usecounts;
1014 std::map<eDVBChannelID, int> fcc_chids;
1015 int apply_to_ignore = 0;
1016 if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
1018 for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
1020 //eDebug("[eDVBResourceManager::canAllocateChannel] FCC NS : %08x, TSID : %04x, ONID : %04x", i->first.dvbnamespace.get(), i->first.transport_stream_id.get(), i->first.original_network_id.get());
1021 if (ignore == i->first)
1023 apply_to_ignore = i->second;
1026 for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
1028 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1029 if (ii->m_channel_id == i->first)
1031 eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
1033 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1034 check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1035 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1036 if (channel->getUseCount() == check_usecount)
1038 ePtr<iDVBFrontend> fe;
1039 if (!ii->m_channel->getFrontend(fe))
1041 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
1043 if ( &(*fe) == &(*iii->m_frontend) )
1045 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
1047 int *tmp_decremented_fe_usecount = &iii->m_inuse;
1048 fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
1049 if (channel == &(*m_cached_channel))
1050 decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
1062 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1064 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1065 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1066 if (i->m_channel_id == ignore)
1068 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
1069 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
1070 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1071 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1072 // or 2 when the cached channel is not equal to the compared channel
1073 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1074 check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1075 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1076 if (channel->getUseCount() == check_usecount) // channel only used once..(except fcc)
1078 ePtr<iDVBFrontend> fe;
1079 if (!i->m_channel->getFrontend(fe))
1081 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1083 if ( &(*fe) == &(*ii->m_frontend) )
1085 //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
1087 decremented_fe_usecount = &ii->m_inuse;
1088 if (channel == &(*m_cached_channel))
1089 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1099 if (!decremented_cached_channel_fe_usecount)
1101 if (m_cached_channel)
1103 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1104 if (channel->getUseCount() == 1)
1106 ePtr<iDVBFrontend> fe;
1107 if (!channel->getFrontend(fe))
1109 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1110 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1112 if ( &(*fe) == &(*ii->m_frontend) )
1115 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1124 decremented_cached_channel_fe_usecount=NULL;
1126 ePtr<iDVBFrontendParameters> feparm;
1130 eDebug("no channel list set!");
1134 if (m_list->getChannelFrontendData(channelid, feparm))
1136 eDebug("channel not found!");
1139 feparm->getSystem(system);
1141 ret = canAllocateFrontend(feparm, simulate);
1144 if (decremented_fe_usecount)
1145 ++(*decremented_fe_usecount);
1146 if (decremented_cached_channel_fe_usecount)
1147 ++(*decremented_cached_channel_fe_usecount);
1148 if (fcc_decremented_fe_usecounts.size())
1150 for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
1152 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
1160 bool eDVBResourceManager::canMeasureFrontendInputPower()
1162 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1164 return i->m_frontend->readInputpower() >= 0;
1169 class eDVBChannelFilePush: public eFilePushThread
1172 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1173 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1175 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1176 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1177 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1179 int m_iframe_search, m_iframe_state, m_pid;
1180 int m_timebase_change;
1181 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1184 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1187 if (m_timebase_change)
1189 eDebug("timebase change: %d", m_timebase_change);
1191 for (offset = 0; offset < len; offset += 188)
1193 unsigned char *pkt = (unsigned char*)_data + offset;
1194 if (pkt[1] & 0x40) /* pusi */
1196 if (pkt[3] & 0x20) // adaption field present?
1197 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1199 pkt += 4; /* skip header */
1200 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1202 eWarning("broken startcode");
1208 if (pkt[7] & 0x80) // PTS present?
1210 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1211 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1212 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1213 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1214 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1218 RESULT r = m_tstools.fixupPTS(off, pts);
1220 eWarning("fixup PTS while trickmode playback failed.\n");
1223 int sec = pts / 90000;
1224 int frm = pts % 90000;
1232 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1234 pts += 0x80000000LL;
1235 pts *= m_timebase_change;
1247 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1255 pkt[9] |= (pts >> 29) & 0xE;
1256 pkt[10] |= (pts >> 22) & 0xFF;
1257 pkt[11] |= (pts >> 14) & 0xFE;
1258 pkt[12] |= (pts >> 7) & 0xFF;
1259 pkt[13] |= (pts << 1) & 0xFE;
1267 if (!m_iframe_search)
1270 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1272 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1274 unsigned char *d = data;
1275 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1277 int offset = d - data;
1278 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1279 unsigned char *ts = data + ts_offset;
1280 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1282 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1284 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1287 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1289 if (m_iframe_state == 1)
1291 /* we are allowing data, and stop allowing data on the next frame.
1292 we now found a frame. so stop here. */
1293 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1294 current_span_remaining = 0;
1296 unsigned char *fts = ts + 188;
1297 while (fts < (data + len))
1300 fts[2] |= 0xff; /* drop packet */
1304 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1307 if (picture_type != 1) /* we are only interested in I frames */
1310 unsigned char *fts = data;
1314 fts[2] |= 0xff; /* drop packet */
1321 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1323 /* verify that this is actually a PES header, not just some ES data */
1324 if (ts[1] & 0x40) /* PUSI set */
1326 int payload_start = 4;
1327 if (ts[3] & 0x20) /* adaptation field present */
1328 payload_start += ts[4] + 1; /* skip AF */
1329 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1333 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1341 d += 4; /* ignore */
1344 if (m_iframe_state == 1)
1347 return 0; /* we need find an iframe first */
1353 DEFINE_REF(eDVBChannel);
1355 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1357 m_frontend = frontend;
1362 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1365 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1368 eDVBChannel::~eDVBChannel()
1371 m_mgr->removeChannel(this);
1376 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1378 int state, ourstate = 0;
1380 /* if we are already in shutdown, don't change state. */
1381 if (m_state == state_release)
1384 if (fe->getState(state))
1387 if (state == iDVBFrontend::stateLock)
1389 eDebug("OURSTATE: ok");
1390 ourstate = state_ok;
1391 } else if (state == iDVBFrontend::stateTuning)
1393 eDebug("OURSTATE: tuning");
1394 ourstate = state_tuning;
1395 } else if (state == iDVBFrontend::stateLostLock)
1397 /* on managed channels, we try to retune in order to re-acquire lock. */
1398 if (m_current_frontend_parameters)
1400 eDebug("OURSTATE: lost lock, trying to retune");
1401 ourstate = state_tuning;
1402 m_frontend->get().tune(*m_current_frontend_parameters);
1404 /* on unmanaged channels, we don't do this. the client will do this. */
1406 eDebug("OURSTATE: lost lock, unavailable now.");
1407 ourstate = state_unavailable;
1409 } else if (state == iDVBFrontend::stateFailed)
1412 if (m_current_frontend_parameters)
1414 eDebug("OURSTATE: lost lock, trying to retune");
1415 ourstate = state_tuning;
1416 m_frontend->get().tune(*m_current_frontend_parameters);
1420 eDebug("OURSTATE: failed");
1421 ourstate = state_failed;
1424 eDebug("OURSTATE: failed");
1425 ourstate = state_failed;
1428 eFatal("state unknown");
1430 if (ourstate != m_state)
1433 m_stateChanged(this);
1437 void eDVBChannel::pvrEvent(int event)
1441 case eFilePushThread::evtEOF:
1442 eDebug("eDVBChannel: End of file!");
1443 m_event(this, evtEOF);
1445 case eFilePushThread::evtUser: /* start */
1447 m_event(this, evtSOF);
1449 case eFilePushThread::evtUser+3: /* limit space */
1450 eDebug("Too large file");
1451 m_event(this, evtFailed+3);
1456 void eDVBChannel::cueSheetEvent(int event)
1458 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1463 case eCueSheet::evtSeek:
1465 flushPVR(m_cue->m_decoding_demux);
1467 case eCueSheet::evtSkipmode:
1470 m_cue->m_lock.WrLock();
1471 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1472 m_cue->m_lock.Unlock();
1473 eRdLocker l(m_cue->m_lock);
1474 if (m_cue->m_skipmode_ratio)
1476 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1477 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1478 /* i agree that this might look a bit like black magic. */
1479 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1480 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1481 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1482 m_skipmode_frames_remainder = 0;
1484 if (m_cue->m_skipmode_ratio < 0)
1485 m_skipmode_m -= m_skipmode_n;
1487 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1489 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1491 eWarning("something is wrong with this calculation");
1492 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1496 eDebug("skipmode ratio is 0, normal play");
1497 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1500 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1501 if (m_cue->m_skipmode_ratio != 0)
1502 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1504 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1505 eDebug("flush pvr");
1506 flushPVR(m_cue->m_decoding_demux);
1510 case eCueSheet::evtSpanChanged:
1512 m_source_span.clear();
1513 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1515 off_t offset_in, offset_out;
1516 pts_t pts_in = i->first, pts_out = i->second;
1517 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1519 eDebug("span translation failed.\n");
1522 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1523 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1530 /* align toward zero */
1531 static inline long long align(long long x, int align)
1546 /* align toward zero */
1547 static inline long long align_with_len(long long x, int align, size_t &len)
1564 /* remember, this gets called from another thread. */
1565 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1567 const int blocksize = 188;
1568 unsigned int max = align(10*1024*1024, blocksize);
1569 current_offset = align(current_offset, blocksize);
1573 eDebug("no cue sheet. forcing normal play");
1574 start = current_offset;
1581 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1582 max = align(m_skipmode_n, blocksize);
1585 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1586 int frame_skip_success = 0;
1590 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1591 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1593 off_t iframe_start = current_offset;
1594 int frames_skipped = frames_to_skip;
1595 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1597 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1598 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1599 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1600 max = align(iframe_len + 187, blocksize);
1601 frame_skip_success = 1;
1604 m_skipmode_frames_remainder = 0;
1605 eDebug("frame skipping failed, reverting to byte-skipping");
1609 if (!frame_skip_success)
1611 current_offset += align(m_skipmode_m, blocksize);
1612 if(current_offset < 0)
1618 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1620 off_t start_offset = current_offset;
1621 off_t new_offset = start_offset;
1622 int direction = (m_skipmode_m < 0) ? -1 : +1;
1623 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1627 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1628 max = align(iframe_len, blocksize);
1634 m_cue->m_lock.RdLock();
1636 while (!m_cue->m_seek_requests.empty())
1638 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1639 m_cue->m_lock.Unlock();
1640 m_cue->m_lock.WrLock();
1641 m_cue->m_seek_requests.pop_front();
1642 m_cue->m_lock.Unlock();
1643 m_cue->m_lock.RdLock();
1644 int relative = seek.first;
1645 pts_t pts = seek.second;
1650 if (!m_cue->m_decoder)
1652 eDebug("no decoder - can't seek relative");
1655 if (m_cue->m_decoder->getPTS(0, now))
1657 eDebug("decoder getPTS failed, can't seek relative");
1660 if (!m_cue->m_decoding_demux)
1662 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1663 start = current_offset;
1667 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1669 eDebug("seekTo: getCurrentPosition failed!");
1672 } else if (pts < 0) /* seek relative to end */
1675 if (!getLength(len))
1677 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1681 eWarning("getLength failed - can't seek relative to end!");
1686 if (relative == 1) /* pts relative */
1697 if (relative == 2) /* AP relative */
1699 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1701 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1703 pts = now - 90000; /* approx. 1s */
1704 eDebug("AP relative seeking failed!");
1708 eDebug("next ap is %llx\n", pts);
1713 if (m_tstools.getOffset(offset, pts, -1))
1715 eDebug("get offset for pts=%lld failed!", pts);
1719 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1720 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1723 m_cue->m_lock.Unlock();
1725 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1727 long long aligned_start = align(i->first, blocksize);
1728 long long aligned_end = align(i->second, blocksize);
1730 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1732 start = current_offset;
1733 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1734 if ((aligned_end - current_offset) > max)
1737 size = aligned_end - current_offset;
1738 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1741 if (current_offset < aligned_start)
1743 /* ok, our current offset is in an 'out' zone. */
1744 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1746 /* in normal playback, just start at the next zone. */
1749 /* size is not 64bit! */
1750 if ((i->second - i->first) > max)
1753 size = aligned_end - aligned_start;
1756 if (m_skipmode_m < 0)
1758 eDebug("reached SOF");
1761 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1765 /* when skipping reverse, however, choose the zone before. */
1767 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1770 aligned_start = align(i->first, blocksize);
1771 aligned_end = align(i->second, blocksize);
1773 if ((aligned_end - aligned_start) > max)
1776 len = aligned_end - aligned_start;
1778 start = aligned_end - len;
1779 eDebug("skipping to %llx, %zd", start, len);
1782 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1787 if(current_offset <0)
1789 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1791 eDebug("reached SOF");
1793 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1795 if (m_source_span.empty())
1797 start = current_offset;
1799 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1802 start = current_offset;
1808 void eDVBChannel::AddUse()
1810 if (++m_use_count > 1 && m_state == state_last_instance)
1813 m_stateChanged(this);
1817 void eDVBChannel::ReleaseUse()
1821 m_state = state_release;
1822 m_stateChanged(this);
1824 else if (m_use_count == 1)
1826 m_state = state_last_instance;
1827 m_stateChanged(this);
1831 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1834 m_mgr->removeChannel(this);
1839 m_channel_id = channelid;
1840 m_mgr->addChannel(channelid, this);
1844 /* no frontend, no need to tune (must be a streamed service) */
1848 m_state = state_tuning;
1849 /* if tuning fails, shutdown the channel immediately. */
1851 res = m_frontend->get().tune(*feparm);
1852 m_current_frontend_parameters = feparm;
1856 m_state = state_release;
1857 m_stateChanged(this);
1864 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1866 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1870 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1872 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1876 RESULT eDVBChannel::getState(int &state)
1882 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1887 void eDVBChannel::SDTready(int result)
1889 ePyObject args = PyTuple_New(2), ret;
1893 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1896 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1897 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1903 PyTuple_SET_ITEM(args, 0, Py_None);
1904 PyTuple_SET_ITEM(args, 1, Py_None);
1908 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1912 Py_DECREF(m_tsid_onid_callback);
1913 m_tsid_onid_callback = ePyObject();
1914 m_tsid_onid_demux = 0;
1918 int eDVBChannel::reserveDemux()
1920 ePtr<iDVBDemux> dmx;
1921 if (!getDemux(dmx, 0))
1924 if (!dmx->getCADemuxID(id))
1930 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1932 if (PyCallable_Check(callback))
1934 if (!getDemux(m_tsid_onid_demux, 0))
1936 m_SDT = new eTable<ServiceDescriptionSection>;
1937 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1938 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1940 m_tsid_onid_demux = 0;
1945 Py_INCREF(callback);
1946 m_tsid_onid_callback = callback;
1954 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1956 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1958 if (m_frontend == NULL)
1960 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1961 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1968 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1973 /* don't hold a reference to the decoding demux, we don't need it. */
1975 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1976 the refcount is lost. thus, decoding demuxes are never allocated.
1978 this poses a big problem for PiP. */
1980 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1982 else if (cap & capDecode)
1991 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1996 frontend = &m_frontend->get();
2002 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
2004 param = m_current_frontend_parameters;
2008 RESULT eDVBChannel::playFile(const char *file)
2010 eRawFile *f = new eRawFile();
2011 ePtr<iTsSource> source = f;
2013 if (f->open(file) < 0)
2015 eDebug("can't open PVR file %s (%m)", file);
2019 return playSource(source, file);
2022 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2024 ASSERT(!m_frontend);
2027 m_pvr_thread->stop();
2028 delete m_pvr_thread;
2032 if (!source->valid() && !source->isStream())
2034 eDebug("PVR source is not valid!");
2038 m_tstools.setSource(source, streaminfo_file);
2040 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2041 THEN DO A REAL FIX HERE! */
2043 if (m_pvr_fd_dst < 0)
2045 /* (this codepath needs to be improved anyway.) */
2046 #if HAVE_DVB_API_VERSION < 3
2047 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
2048 if (m_pvr_fd_dst < 0)
2050 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2054 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2057 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2058 if (m_pvr_fd_dst < 0)
2060 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2066 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2072 m_pvr_thread = new eDVBChannelFilePush();
2073 m_pvr_thread->enablePVRCommit(1);
2074 /* If the source specifies a length, it's a file. If not, it's a stream */
2075 m_pvr_thread->setStreamMode(source->isStream());
2076 m_pvr_thread->setScatterGather(this);
2078 m_event(this, evtPreStart);
2080 m_pvr_thread->start(source, m_pvr_fd_dst);
2081 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2084 m_stateChanged(this);
2089 void eDVBChannel::stopSource()
2093 m_pvr_thread->stop();
2094 delete m_pvr_thread;
2097 if (m_pvr_fd_dst >= 0)
2099 ::close(m_pvr_fd_dst);
2103 m_tstools.setSource(d);
2106 void eDVBChannel::stopFile()
2111 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2113 m_conn_cueSheetEvent = 0;
2116 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2119 RESULT eDVBChannel::getLength(pts_t &len)
2121 return m_tstools.calcLen(len);
2124 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2126 if (!decoding_demux)
2133 if (mode == 0) /* demux */
2135 r = decoding_demux->getSTC(now, 0);
2138 eDebug("demux getSTC failed");
2142 now = pos; /* fixup supplied */
2144 off_t off = 0; /* TODO: fixme */
2145 r = m_tstools.fixupPTS(off, now);
2148 eDebug("fixup PTS failed");
2157 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2159 /* when seeking, we have to ensure that all buffers are flushed.
2160 there are basically 3 buffers:
2161 a.) the filepush's internal buffer
2162 b.) the PVR buffer (before demux)
2163 c.) the ratebuffer (after demux)
2165 it's important to clear them in the correct order, otherwise
2166 the ratebuffer (for example) would immediately refill from
2167 the not-yet-flushed PVR buffer.
2170 m_pvr_thread->pause();
2171 /* flush internal filepush buffer */
2172 m_pvr_thread->flush();
2173 /* HACK: flush PVR buffer */
2174 ::ioctl(m_pvr_fd_dst, 0);
2176 /* flush ratebuffers (video, audio) */
2178 decoding_demux->flush();
2180 /* demux will also flush all decoder.. */
2181 /* resume will re-query the SG */
2182 m_pvr_thread->resume();
2185 DEFINE_REF(eCueSheet);
2187 eCueSheet::eCueSheet()
2189 m_skipmode_ratio = 0;
2192 void eCueSheet::seekTo(int relative, const pts_t &pts)
2195 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2200 void eCueSheet::clear()
2207 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2209 ASSERT(begin < end);
2211 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2215 void eCueSheet::commitSpans()
2217 m_event(evtSpanChanged);
2220 void eCueSheet::setSkipmode(const pts_t &ratio)
2223 m_skipmode_ratio = ratio;
2225 m_event(evtSkipmode);
2228 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2230 m_decoding_demux = demux;
2231 m_decoder = decoder;
2234 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2236 connection = new eConnection(this, m_event.connect(event));