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>
20 DEFINE_REF(eDVBRegisteredFrontend);
21 DEFINE_REF(eDVBRegisteredDemux);
23 DEFINE_REF(eDVBAllocatedFrontend);
25 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
30 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
33 if (m_fe->m_frontend->is_FBCTuner())
35 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
43 DEFINE_REF(eDVBAllocatedDemux);
45 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
50 eDVBAllocatedDemux::~eDVBAllocatedDemux()
55 DEFINE_REF(eDVBResourceManager);
57 eDVBResourceManager *eDVBResourceManager::instance;
59 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
69 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
71 ePtr<eDVBResourceManager> ptr;
72 eDVBResourceManager::getInstance(ptr);
76 eDVBResourceManager::eDVBResourceManager()
77 :m_releaseCachedChannelTimer(eTimer::create(eApp))
81 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
86 /* search available adapters... */
91 while (eDVBAdapterLinux::exist(num_adapter))
93 addAdapter(new eDVBAdapterLinux(num_adapter));
99 int fd = open("/proc/stb/info/model", O_RDONLY);
101 int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
105 if (!strncmp(tmp, "dm7025\n", rd))
107 else if (!strncmp(tmp, "dm8000\n", rd))
109 else if (!strncmp(tmp, "dm800\n", rd))
111 else if (!strncmp(tmp, "dm500hd\n", rd))
113 else if (!strncmp(tmp, "dm800se\n", rd))
115 else if (!strncmp(tmp, "dm7020hd\n", rd))
116 m_boxtype = DM7020HD;
118 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
119 if (m_demux.size() == 3)
121 else if (m_demux.size() < 5)
127 eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
128 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
130 eDVBCAService::registerChannelCallback(this);
132 m_fbc_mng = new eFBCTunerManager(this);
134 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
137 void eDVBResourceManager::feStateChanged()
140 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
142 mask |= ( 1 << i->m_frontend->getSlotID() );
143 /* emit */ frontendUseMaskChanged(mask);
146 DEFINE_REF(eDVBAdapterLinux);
147 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
152 eDebug("scanning for frontends..");
157 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
158 if (stat(filename, &s))
164 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
166 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
171 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
173 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
184 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
185 if (stat(filename, &s))
187 ePtr<eDVBDemux> demux;
189 demux = new eDVBDemux(m_nr, num_demux);
190 m_demux.push_back(demux);
196 int eDVBAdapterLinux::getNumDemux()
198 return m_demux.size();
201 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
203 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
204 while (nr && (i != m_demux.end()))
210 if (i != m_demux.end())
218 int eDVBAdapterLinux::getNumFrontends()
220 return m_frontend.size();
223 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
225 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
226 while (nr && (i != m_frontend.end()))
232 if (i != m_frontend.end())
240 int eDVBAdapterLinux::exist(int nr)
244 sprintf(filename, "/dev/dvb/adapter%d", nr);
245 if (!stat(filename, &s))
250 eDVBResourceManager::~eDVBResourceManager()
252 if (instance == this)
256 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
258 int num_fe = adapter->getNumFrontends();
259 int num_demux = adapter->getNumDemux();
261 m_adapter.push_back(adapter);
264 for (i=0; i<num_demux; ++i)
266 ePtr<eDVBDemux> demux;
267 if (!adapter->getDemux(demux, i))
268 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
271 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
272 for (i=0; i<num_fe; ++i)
274 ePtr<eDVBFrontend> frontend;
275 if (!adapter->getFrontend(frontend, i))
277 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
278 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
279 m_frontend.push_back(new_fe);
280 frontend->setSEC(m_sec);
281 // we must link all dvb-t frontends ( for active antenna voltage )
282 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
284 if (prev_dvbt_frontend)
286 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
287 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
289 prev_dvbt_frontend = new_fe;
294 prev_dvbt_frontend = 0;
295 for (i=0; i<num_fe; ++i)
297 ePtr<eDVBFrontend> frontend;
298 if (!adapter->getFrontend(frontend, i, true))
300 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
301 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
302 m_simulate_frontend.push_back(new_fe);
303 frontend->setSEC(m_sec);
304 // we must link all dvb-t frontends ( for active antenna voltage )
305 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
307 if (prev_dvbt_frontend)
309 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
310 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
312 prev_dvbt_frontend = new_fe;
319 void eDVBResourceManager::setUsbTuner()
321 std::ifstream in("/proc/bus/nim_sockets");
326 int usbtuner_idx[8] = {0};
327 int usbtuner_count = 0;
334 if ((res = sscanf(line.c_str(), "NIM Socket %d:", &fe_idx)) == 1)
337 if ((fe_idx != -1) && (line.find("\tName: ") == 0) && (line.find("VTUNER") != -1))
338 usbtuner_idx[usbtuner_count++] = fe_idx;
345 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_frontend.begin()); it != m_frontend.end(); ++it)
347 int slotid = it->m_frontend->getSlotID();
348 for (int i=0; i < usbtuner_count ; i++)
350 if (slotid == usbtuner_idx[i])
352 it->m_frontend->setUSBTuner(true);
357 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_simulate_frontend.begin()); it != m_simulate_frontend.end(); ++it)
359 int slotid = it->m_frontend->getSlotID();
360 for (int i=0; i < usbtuner_count ; i++)
362 if (slotid == usbtuner_idx[i])
364 it->m_frontend->setUSBTuner(true);
372 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
374 if (!PyList_Check(list))
376 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
379 unsigned int assigned=0;
380 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
383 while (pos < PyList_Size(list)) {
384 ePyObject obj = PyList_GET_ITEM(list, pos++);
385 if (!i->m_frontend->setSlotInfo(obj))
391 if (assigned != m_frontend.size()) {
393 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
394 m_frontend.size(), assigned);
395 PyErr_SetString(PyExc_StandardError, blasel);
398 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
401 while (pos < PyList_Size(list)) {
402 ePyObject obj = PyList_GET_ITEM(list, pos++);
403 if (!i->m_frontend->setSlotInfo(obj))
411 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
413 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
415 if (i->m_frontend->getSlotID() == index)
417 if (!strcmp(type, "DVB-S2"))
419 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
421 else if (!strcmp(type, "DVB-S"))
423 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
425 else if (!strcmp(type, "DVB-T2"))
427 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
429 else if (!strcmp(type, "DVB-T"))
431 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
433 else if (!strcmp(type, "DVB-C"))
435 #if defined SYS_DVBC_ANNEX_A
436 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
438 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
446 void eDVBResourceManager::setFrontendType(int index, const char *type)
448 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
450 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
452 if (i->m_frontend->getSlotID() == index)
454 std::vector<fe_delivery_system_t> whitelist;
455 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
457 whitelist.push_back(SYS_DVBS);
458 whitelist.push_back(SYS_DVBS2);
460 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
462 whitelist.push_back(SYS_DVBT);
463 whitelist.push_back(SYS_DVBT2);
465 else if (!strcmp(type, "DVB-C"))
467 #if defined SYS_DVBC_ANNEX_A
468 whitelist.push_back(SYS_DVBC_ANNEX_A);
470 whitelist.push_back(SYS_DVBC_ANNEX_AC);
473 i->m_frontend->setDeliverySystemWhitelist(whitelist);
479 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
481 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
482 eDVBRegisteredFrontend *best = NULL;
486 int check_fbc_leaf_linkable = 0;
487 int current_fbc_setid = -1;
488 eDVBRegisteredFrontend *fbc_fe = NULL;
489 eDVBRegisteredFrontend *best_fbc_fe = NULL;
491 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
495 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
497 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
498 if (fbc_setid != current_fbc_setid)
500 current_fbc_setid = fbc_setid;
501 check_fbc_leaf_linkable = 0;
504 if (!check_fbc_leaf_linkable)
506 c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
507 check_fbc_leaf_linkable = 1;
508 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);
513 c = i->m_frontend->isCompatibleWith(feparm);
516 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
521 eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
526 best_fbc_fe = fbc_fe;
531 eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
534 eDVBRegisteredFrontend *tmp = *i;
541 m_fbc_mng->addLink(best, best_fbc_fe, simulate);
544 fe = new eDVBAllocatedFrontend(best);
551 return errAllSourcesBusy;
553 return errNoSourceFound;
556 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
558 int err = errNoSourceFound;
559 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
560 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
562 // check if another slot linked to this is in use
564 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
567 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
568 if (satpos_depends_to_fe->m_inuse)
570 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
571 err = errAllSourcesBusy;
572 goto alloc_fe_by_id_not_possible;
575 else // check linked tuners
577 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
580 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
583 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
584 err = errAllSourcesBusy;
585 goto alloc_fe_by_id_not_possible;
587 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
589 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
592 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
595 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
596 err = errAllSourcesBusy;
597 goto alloc_fe_by_id_not_possible;
599 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
602 fe = new eDVBAllocatedFrontend(i);
605 alloc_fe_by_id_not_possible:
610 #define capHoldDecodeReference 64
612 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
614 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
615 never use the first one unless we need a decoding demux. */
617 eDebug("allocate demux");
618 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
622 if (i == m_demux.end())
625 ePtr<eDVBRegisteredDemux> unused;
627 if (m_boxtype == DM800) // dm800
629 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
630 for (; i != m_demux.end(); ++i, ++n)
641 if (i->m_adapter == fe->m_adapter &&
642 i->m_demux->getSource() == fe->m_frontend->getDVBID())
644 demux = new eDVBAllocatedDemux(i);
648 else if (i->m_demux->getSource() == -1) // PVR
650 demux = new eDVBAllocatedDemux(i);
656 else if (m_boxtype == DM7025) // ATI
658 /* FIXME: hardware demux policy */
659 if (!(cap & iDVBChannel::capDecode))
661 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
668 for (; i != m_demux.end(); ++i, ++n)
670 int is_decode = n < 2;
672 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
674 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
676 if ((cap & iDVBChannel::capDecode) && !is_decode)
683 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
685 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 */
686 int source = fe ? fe->m_frontend->getDVBID() : -1;
687 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
691 * For pvr playback, start with the last demux.
692 * On some hardware, we have less ca devices than demuxes,
693 * so we should try to leave the first demuxes for live tv,
694 * and start with the last for pvr playback
699 while (i != m_demux.end())
701 if (i->m_adapter == adapter)
705 /* mark the first unused demux, we'll use that when we do not find a better match */
706 if (!unused) unused = i;
710 /* demux is in use, see if we can share it */
711 if (source >= 0 && i->m_demux->getSource() == source)
713 demux = new eDVBAllocatedDemux(i);
731 demux = new eDVBAllocatedDemux(unused);
733 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
735 demux->get().setSourcePVR(0);
739 eDebug("demux not found");
743 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
749 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
758 #define eDebugNoSimulate(x...) \
764 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
766 /* first, check if a channel is already existing. */
767 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
769 if (!simulate && m_cached_channel)
771 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
772 if(channelid==cache_chan->getChannelID())
774 eDebug("use cached_channel");
775 channel = m_cached_channel;
778 m_cached_channel_state_changed_conn.disconnect();
780 m_releaseCachedChannelTimer->stop();
783 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
784 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
786 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
787 if (i->m_channel_id == channelid)
789 eDebugNoSimulate("found shared channel..");
790 channel = i->m_channel;
795 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
799 eDebugNoSimulate("no channel list set!");
800 return errNoChannelList;
803 ePtr<iDVBFrontendParameters> feparm;
804 if (m_list->getChannelFrontendData(channelid, feparm))
806 eDebugNoSimulate("channel not found!");
807 return errChannelNotInList;
810 /* allocate a frontend. */
812 ePtr<eDVBAllocatedFrontend> fe;
814 int err = allocateFrontend(fe, feparm, simulate);
819 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
821 res = ch->setChannel(channelid, feparm);
825 return errChidNotFound;
832 m_cached_channel = channel = ch;
833 m_cached_channel_state_changed_conn =
834 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
840 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
843 chan->getState(state);
846 case iDVBChannel::state_release:
847 case iDVBChannel::state_ok:
849 eDebug("stop release channel timer");
850 m_releaseCachedChannelTimer->stop();
853 case iDVBChannel::state_last_instance:
855 eDebug("start release channel timer");
856 m_releaseCachedChannelTimer->start(3000, true);
859 default: // ignore all other events
864 void eDVBResourceManager::releaseCachedChannel()
866 eDebug("release cached channel (timer timeout)");
870 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
872 ePtr<eDVBAllocatedFrontend> fe;
874 if (m_cached_channel)
876 m_cached_channel_state_changed_conn.disconnect();
878 m_releaseCachedChannelTimer->stop();
881 int err = allocateFrontendByIndex(fe, slot_index);
885 channel = new eDVBChannel(this, fe);
889 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
891 ePtr<eDVBAllocatedDemux> demux;
893 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
895 m_cached_channel_state_changed_conn.disconnect();
897 m_releaseCachedChannelTimer->stop();
900 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
904 * user provided a channelid, with the clear intention for
905 * this channel to be registered at the resource manager.
906 * (allowing e.g. epgcache to be started)
908 ePtr<iDVBFrontendParameters> feparm;
909 ch->setChannel(channelid, feparm);
915 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
917 ePtr<iDVBFrontend> fe;
918 if (!ch->getFrontend(fe))
920 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
921 if (frontend->is_simulate())
922 m_active_simulate_channels.push_back(active_channel(chid, ch));
925 m_active_channels.push_back(active_channel(chid, ch));
926 /* emit */ m_channelAdded(ch);
932 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
934 ePtr<iDVBFrontend> fe;
935 if (!ch->getFrontend(fe))
937 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
938 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
940 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
942 if (i->m_channel == ch)
944 i = active_channels.erase(i);
956 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
958 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
962 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
964 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
965 ePtr<eDVBRegisteredFrontend> best;
967 int check_fbc_leaf_linkable = 0;
968 int current_fbc_setid = -1;
970 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
975 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
977 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
978 if (fbc_setid != current_fbc_setid)
980 current_fbc_setid = fbc_setid;
981 check_fbc_leaf_linkable = 0;
984 if (!check_fbc_leaf_linkable)
986 eDVBRegisteredFrontend *dummy;
987 c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
988 check_fbc_leaf_linkable = 1;
993 c = i->m_frontend->isCompatibleWith(feparm);
1002 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
1004 system = iDVBFrontend::feSatellite;
1007 ePtr<iDVBFrontendParameters> feparm;
1008 if (!channellist->getChannelFrontendData(chid, feparm))
1010 if (!feparm->getSystem(system))
1014 case iDVBFrontend::feSatellite:
1016 case iDVBFrontend::feCable:
1018 case iDVBFrontend::feTerrestrial:
1029 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
1031 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
1033 system = iDVBFrontend::feSatellite;
1034 if (!simulate && m_cached_channel)
1036 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
1037 if(channelid==cache_chan->getChannelID())
1038 return tuner_type_channel_default(m_list, channelid, system);
1041 /* first, check if a channel is already existing. */
1042 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
1043 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1045 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1046 if (i->m_channel_id == channelid)
1048 // eDebug("found shared channel..");
1049 return tuner_type_channel_default(m_list, channelid, system);
1053 int *decremented_cached_channel_fe_usecount=NULL,
1054 *decremented_fe_usecount=NULL;
1056 /* check FCC channels */
1057 std::vector<int*> fcc_decremented_fe_usecounts;
1058 std::map<eDVBChannelID, int> fcc_chids;
1059 int apply_to_ignore = 0;
1060 if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
1062 for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
1064 //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());
1065 if (ignore == i->first)
1067 apply_to_ignore = i->second;
1070 for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
1072 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1073 if (ii->m_channel_id == i->first)
1075 eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
1077 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1078 check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1079 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1080 if (channel->getUseCount() == check_usecount)
1082 ePtr<iDVBFrontend> fe;
1083 if (!ii->m_channel->getFrontend(fe))
1085 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
1087 if ( &(*fe) == &(*iii->m_frontend) )
1089 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
1091 int *tmp_decremented_fe_usecount = &iii->m_inuse;
1092 fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
1093 if (channel == &(*m_cached_channel))
1094 decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
1106 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1108 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1109 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1110 if (i->m_channel_id == ignore)
1112 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
1113 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
1114 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1115 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1116 // or 2 when the cached channel is not equal to the compared channel
1117 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1118 check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1119 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1120 if (channel->getUseCount() == check_usecount) // channel only used once..(except fcc)
1122 ePtr<iDVBFrontend> fe;
1123 if (!i->m_channel->getFrontend(fe))
1125 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1127 if ( &(*fe) == &(*ii->m_frontend) )
1129 //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
1131 decremented_fe_usecount = &ii->m_inuse;
1132 if (channel == &(*m_cached_channel))
1133 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1143 if (!decremented_cached_channel_fe_usecount)
1145 if (m_cached_channel)
1147 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1148 if (channel->getUseCount() == 1)
1150 ePtr<iDVBFrontend> fe;
1151 if (!channel->getFrontend(fe))
1153 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1154 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1156 if ( &(*fe) == &(*ii->m_frontend) )
1159 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1168 decremented_cached_channel_fe_usecount=NULL;
1170 ePtr<iDVBFrontendParameters> feparm;
1174 eDebug("no channel list set!");
1178 if (m_list->getChannelFrontendData(channelid, feparm))
1180 eDebug("channel not found!");
1183 feparm->getSystem(system);
1185 ret = canAllocateFrontend(feparm, simulate);
1188 if (decremented_fe_usecount)
1189 ++(*decremented_fe_usecount);
1190 if (decremented_cached_channel_fe_usecount)
1191 ++(*decremented_cached_channel_fe_usecount);
1192 if (fcc_decremented_fe_usecounts.size())
1194 for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
1196 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
1204 bool eDVBResourceManager::canMeasureFrontendInputPower()
1206 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1208 return i->m_frontend->readInputpower() >= 0;
1213 class eDVBChannelFilePush: public eFilePushThread
1216 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1217 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1219 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1220 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1221 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1223 int m_iframe_search, m_iframe_state, m_pid;
1224 int m_timebase_change;
1225 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1228 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1231 if (m_timebase_change)
1233 eDebug("timebase change: %d", m_timebase_change);
1235 for (offset = 0; offset < len; offset += 188)
1237 unsigned char *pkt = (unsigned char*)_data + offset;
1238 if (pkt[1] & 0x40) /* pusi */
1240 if (pkt[3] & 0x20) // adaption field present?
1241 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1243 pkt += 4; /* skip header */
1244 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1246 eWarning("broken startcode");
1252 if (pkt[7] & 0x80) // PTS present?
1254 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1255 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1256 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1257 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1258 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1262 RESULT r = m_tstools.fixupPTS(off, pts);
1264 eWarning("fixup PTS while trickmode playback failed.\n");
1267 int sec = pts / 90000;
1268 int frm = pts % 90000;
1276 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1278 pts += 0x80000000LL;
1279 pts *= m_timebase_change;
1291 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1299 pkt[9] |= (pts >> 29) & 0xE;
1300 pkt[10] |= (pts >> 22) & 0xFF;
1301 pkt[11] |= (pts >> 14) & 0xFE;
1302 pkt[12] |= (pts >> 7) & 0xFF;
1303 pkt[13] |= (pts << 1) & 0xFE;
1311 if (!m_iframe_search)
1314 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1316 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1318 unsigned char *d = data;
1319 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1321 int offset = d - data;
1322 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1323 unsigned char *ts = data + ts_offset;
1324 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1326 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1328 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1331 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1333 if (m_iframe_state == 1)
1335 /* we are allowing data, and stop allowing data on the next frame.
1336 we now found a frame. so stop here. */
1337 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1338 current_span_remaining = 0;
1340 unsigned char *fts = ts + 188;
1341 while (fts < (data + len))
1344 fts[2] |= 0xff; /* drop packet */
1348 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1351 if (picture_type != 1) /* we are only interested in I frames */
1354 unsigned char *fts = data;
1358 fts[2] |= 0xff; /* drop packet */
1365 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1367 /* verify that this is actually a PES header, not just some ES data */
1368 if (ts[1] & 0x40) /* PUSI set */
1370 int payload_start = 4;
1371 if (ts[3] & 0x20) /* adaptation field present */
1372 payload_start += ts[4] + 1; /* skip AF */
1373 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1377 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1385 d += 4; /* ignore */
1388 if (m_iframe_state == 1)
1391 return 0; /* we need find an iframe first */
1397 DEFINE_REF(eDVBChannel);
1399 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1401 m_frontend = frontend;
1406 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1409 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1412 eDVBChannel::~eDVBChannel()
1415 m_mgr->removeChannel(this);
1420 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1422 int state, ourstate = 0;
1424 /* if we are already in shutdown, don't change state. */
1425 if (m_state == state_release)
1428 if (fe->getState(state))
1431 if (state == iDVBFrontend::stateLock)
1433 eDebug("OURSTATE: ok");
1434 ourstate = state_ok;
1435 } else if (state == iDVBFrontend::stateTuning)
1437 eDebug("OURSTATE: tuning");
1438 ourstate = state_tuning;
1439 } else if (state == iDVBFrontend::stateLostLock)
1441 /* on managed channels, we try to retune in order to re-acquire lock. */
1442 if (m_current_frontend_parameters)
1444 eDebug("OURSTATE: lost lock, trying to retune");
1445 ourstate = state_tuning;
1446 m_frontend->get().tune(*m_current_frontend_parameters);
1448 /* on unmanaged channels, we don't do this. the client will do this. */
1450 eDebug("OURSTATE: lost lock, unavailable now.");
1451 ourstate = state_unavailable;
1453 } else if (state == iDVBFrontend::stateFailed)
1456 if (m_current_frontend_parameters)
1458 eDebug("OURSTATE: lost lock, trying to retune");
1459 ourstate = state_tuning;
1460 m_frontend->get().tune(*m_current_frontend_parameters);
1464 eDebug("OURSTATE: failed");
1465 ourstate = state_failed;
1468 eDebug("OURSTATE: failed");
1469 ourstate = state_failed;
1472 eFatal("state unknown");
1474 if (ourstate != m_state)
1477 m_stateChanged(this);
1481 void eDVBChannel::pvrEvent(int event)
1485 case eFilePushThread::evtEOF:
1486 eDebug("eDVBChannel: End of file!");
1487 m_event(this, evtEOF);
1489 case eFilePushThread::evtUser: /* start */
1491 m_event(this, evtSOF);
1493 case eFilePushThread::evtUser+3: /* limit space */
1494 eDebug("Too large file");
1495 m_event(this, evtFailed+3);
1500 void eDVBChannel::cueSheetEvent(int event)
1502 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1507 case eCueSheet::evtSeek:
1509 flushPVR(m_cue->m_decoding_demux);
1511 case eCueSheet::evtSkipmode:
1514 m_cue->m_lock.WrLock();
1515 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1516 m_cue->m_lock.Unlock();
1517 eRdLocker l(m_cue->m_lock);
1518 if (m_cue->m_skipmode_ratio)
1520 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1521 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1522 /* i agree that this might look a bit like black magic. */
1523 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1524 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1525 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1526 m_skipmode_frames_remainder = 0;
1528 if (m_cue->m_skipmode_ratio < 0)
1529 m_skipmode_m -= m_skipmode_n;
1531 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1533 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1535 eWarning("something is wrong with this calculation");
1536 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1540 eDebug("skipmode ratio is 0, normal play");
1541 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1544 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1545 if (m_cue->m_skipmode_ratio != 0)
1546 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1548 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1549 eDebug("flush pvr");
1550 flushPVR(m_cue->m_decoding_demux);
1554 case eCueSheet::evtSpanChanged:
1556 m_source_span.clear();
1557 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1559 off_t offset_in, offset_out;
1560 pts_t pts_in = i->first, pts_out = i->second;
1561 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1563 eDebug("span translation failed.\n");
1566 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1567 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1574 /* align toward zero */
1575 static inline long long align(long long x, int align)
1590 /* align toward zero */
1591 static inline long long align_with_len(long long x, int align, size_t &len)
1608 /* remember, this gets called from another thread. */
1609 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1611 const int blocksize = 188;
1612 unsigned int max = align(10*1024*1024, blocksize);
1613 current_offset = align(current_offset, blocksize);
1617 eDebug("no cue sheet. forcing normal play");
1618 start = current_offset;
1625 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1626 max = align(m_skipmode_n, blocksize);
1629 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1630 int frame_skip_success = 0;
1634 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1635 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1637 off_t iframe_start = current_offset;
1638 int frames_skipped = frames_to_skip;
1639 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1641 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1642 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1643 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1644 max = align(iframe_len + 187, blocksize);
1645 frame_skip_success = 1;
1648 m_skipmode_frames_remainder = 0;
1649 eDebug("frame skipping failed, reverting to byte-skipping");
1653 if (!frame_skip_success)
1655 current_offset += align(m_skipmode_m, blocksize);
1656 if(current_offset < 0)
1662 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1664 off_t start_offset = current_offset;
1665 off_t new_offset = start_offset;
1666 int direction = (m_skipmode_m < 0) ? -1 : +1;
1667 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1671 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1672 max = align(iframe_len, blocksize);
1678 m_cue->m_lock.RdLock();
1680 while (!m_cue->m_seek_requests.empty())
1682 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1683 m_cue->m_lock.Unlock();
1684 m_cue->m_lock.WrLock();
1685 m_cue->m_seek_requests.pop_front();
1686 m_cue->m_lock.Unlock();
1687 m_cue->m_lock.RdLock();
1688 int relative = seek.first;
1689 pts_t pts = seek.second;
1694 if (!m_cue->m_decoder)
1696 eDebug("no decoder - can't seek relative");
1699 if (m_cue->m_decoder->getPTS(0, now))
1701 eDebug("decoder getPTS failed, can't seek relative");
1704 if (!m_cue->m_decoding_demux)
1706 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1707 start = current_offset;
1711 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1713 eDebug("seekTo: getCurrentPosition failed!");
1716 } else if (pts < 0) /* seek relative to end */
1719 if (!getLength(len))
1721 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1725 eWarning("getLength failed - can't seek relative to end!");
1730 if (relative == 1) /* pts relative */
1741 if (relative == 2) /* AP relative */
1743 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1745 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1747 pts = now - 90000; /* approx. 1s */
1748 eDebug("AP relative seeking failed!");
1752 eDebug("next ap is %llx\n", pts);
1757 if (m_tstools.getOffset(offset, pts, -1))
1759 eDebug("get offset for pts=%lld failed!", pts);
1763 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1764 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1767 m_cue->m_lock.Unlock();
1769 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1771 long long aligned_start = align(i->first, blocksize);
1772 long long aligned_end = align(i->second, blocksize);
1774 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1776 start = current_offset;
1777 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1778 if ((aligned_end - current_offset) > max)
1781 size = aligned_end - current_offset;
1782 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1785 if (current_offset < aligned_start)
1787 /* ok, our current offset is in an 'out' zone. */
1788 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1790 /* in normal playback, just start at the next zone. */
1793 /* size is not 64bit! */
1794 if ((i->second - i->first) > max)
1797 size = aligned_end - aligned_start;
1800 if (m_skipmode_m < 0)
1802 eDebug("reached SOF");
1805 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1809 /* when skipping reverse, however, choose the zone before. */
1811 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1814 aligned_start = align(i->first, blocksize);
1815 aligned_end = align(i->second, blocksize);
1817 if ((aligned_end - aligned_start) > max)
1820 len = aligned_end - aligned_start;
1822 start = aligned_end - len;
1823 eDebug("skipping to %llx, %zd", start, len);
1826 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1831 if(current_offset <0)
1833 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1835 eDebug("reached SOF");
1837 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1839 if (m_source_span.empty())
1841 start = current_offset;
1843 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1846 start = current_offset;
1852 void eDVBChannel::AddUse()
1854 if (++m_use_count > 1 && m_state == state_last_instance)
1857 m_stateChanged(this);
1861 void eDVBChannel::ReleaseUse()
1865 m_state = state_release;
1866 m_stateChanged(this);
1868 else if (m_use_count == 1)
1870 m_state = state_last_instance;
1871 m_stateChanged(this);
1875 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1878 m_mgr->removeChannel(this);
1883 m_channel_id = channelid;
1884 m_mgr->addChannel(channelid, this);
1888 /* no frontend, no need to tune (must be a streamed service) */
1892 m_state = state_tuning;
1893 /* if tuning fails, shutdown the channel immediately. */
1895 res = m_frontend->get().tune(*feparm);
1896 m_current_frontend_parameters = feparm;
1900 m_state = state_release;
1901 m_stateChanged(this);
1908 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1910 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1914 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1916 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1920 RESULT eDVBChannel::getState(int &state)
1926 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1931 void eDVBChannel::SDTready(int result)
1933 ePyObject args = PyTuple_New(2), ret;
1937 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1940 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1941 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1947 PyTuple_SET_ITEM(args, 0, Py_None);
1948 PyTuple_SET_ITEM(args, 1, Py_None);
1952 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1956 Py_DECREF(m_tsid_onid_callback);
1957 m_tsid_onid_callback = ePyObject();
1958 m_tsid_onid_demux = 0;
1962 int eDVBChannel::reserveDemux()
1964 ePtr<iDVBDemux> dmx;
1965 if (!getDemux(dmx, 0))
1968 if (!dmx->getCADemuxID(id))
1974 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1976 if (PyCallable_Check(callback))
1978 if (!getDemux(m_tsid_onid_demux, 0))
1980 m_SDT = new eTable<ServiceDescriptionSection>;
1981 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1982 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1984 m_tsid_onid_demux = 0;
1989 Py_INCREF(callback);
1990 m_tsid_onid_callback = callback;
1998 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
2000 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
2002 if (m_frontend == NULL)
2004 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
2005 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
2012 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
2017 /* don't hold a reference to the decoding demux, we don't need it. */
2019 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
2020 the refcount is lost. thus, decoding demuxes are never allocated.
2022 this poses a big problem for PiP. */
2024 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
2026 else if (cap & capDecode)
2035 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
2040 frontend = &m_frontend->get();
2046 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
2048 param = m_current_frontend_parameters;
2052 RESULT eDVBChannel::playFile(const char *file)
2054 eRawFile *f = new eRawFile();
2055 ePtr<iTsSource> source = f;
2057 if (f->open(file) < 0)
2059 eDebug("can't open PVR file %s (%m)", file);
2063 return playSource(source, file);
2066 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2068 ASSERT(!m_frontend);
2071 m_pvr_thread->stop();
2072 delete m_pvr_thread;
2076 if (!source->valid() && !source->isStream())
2078 eDebug("PVR source is not valid!");
2083 m_tstools.setSource(m_source, streaminfo_file);
2085 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2086 THEN DO A REAL FIX HERE! */
2088 if (m_pvr_fd_dst < 0)
2090 /* (this codepath needs to be improved anyway.) */
2091 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2094 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2095 if (m_pvr_fd_dst < 0)
2097 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2103 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2108 m_pvr_thread = new eDVBChannelFilePush();
2109 m_pvr_thread->enablePVRCommit(1);
2110 /* If the source specifies a length, it's a file. If not, it's a stream */
2111 m_pvr_thread->setStreamMode(m_source->isStream());
2112 m_pvr_thread->setScatterGather(this);
2114 m_event(this, evtPreStart);
2116 m_pvr_thread->start(m_source, m_pvr_fd_dst);
2117 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2120 m_stateChanged(this);
2125 void eDVBChannel::stopSource()
2129 m_pvr_thread->stop();
2130 delete m_pvr_thread;
2133 if (m_pvr_fd_dst >= 0)
2135 ::close(m_pvr_fd_dst);
2140 m_tstools.setSource(m_source);
2143 void eDVBChannel::stopFile()
2148 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2150 m_conn_cueSheetEvent = 0;
2153 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2156 RESULT eDVBChannel::getLength(pts_t &len)
2158 return m_tstools.calcLen(len);
2161 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2163 if (!decoding_demux)
2170 if (mode == 0) /* demux */
2172 r = decoding_demux->getSTC(now, 0);
2175 eDebug("demux getSTC failed");
2179 now = pos; /* fixup supplied */
2181 r = m_tstools.fixupPTS(m_source ? m_source->offset() : 0, now);
2184 eDebug("fixup PTS failed");
2193 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2195 /* when seeking, we have to ensure that all buffers are flushed.
2196 there are basically 3 buffers:
2197 a.) the filepush's internal buffer
2198 b.) the PVR buffer (before demux)
2199 c.) the ratebuffer (after demux)
2201 it's important to clear them in the correct order, otherwise
2202 the ratebuffer (for example) would immediately refill from
2203 the not-yet-flushed PVR buffer.
2206 m_pvr_thread->pause();
2207 /* flush internal filepush buffer */
2208 m_pvr_thread->flush();
2209 /* HACK: flush PVR buffer */
2210 ::ioctl(m_pvr_fd_dst, 0);
2212 /* flush ratebuffers (video, audio) */
2214 decoding_demux->flush();
2216 /* demux will also flush all decoder.. */
2217 /* resume will re-query the SG */
2218 m_pvr_thread->resume();
2221 DEFINE_REF(eCueSheet);
2223 eCueSheet::eCueSheet()
2225 m_skipmode_ratio = 0;
2228 void eCueSheet::seekTo(int relative, const pts_t &pts)
2231 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2236 void eCueSheet::clear()
2243 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2245 ASSERT(begin < end);
2247 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2251 void eCueSheet::commitSpans()
2253 m_event(evtSpanChanged);
2256 void eCueSheet::setSkipmode(const pts_t &ratio)
2259 m_skipmode_ratio = ratio;
2261 m_event(evtSkipmode);
2264 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2266 m_decoding_demux = demux;
2267 m_decoder = decoder;
2270 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2272 connection = new eConnection(this, m_event.connect(event));