1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/init_num.h>
7 #include <lib/base/init.h>
8 #include <lib/base/nconfig.h> // access to python config
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
21 #include <lib/gui/esubtitle.h>
26 #include <netinet/in.h>
28 #include <dvbsi++/event_information_section.h>
30 #define INTERNAL_TELETEXT
33 #error no byte order defined!
36 #define TSPATH "/media/hdd"
38 class eStaticServiceDVBInformation: public iStaticServiceInformation
40 DECLARE_REF(eStaticServiceDVBInformation);
42 RESULT getName(const eServiceReference &ref, std::string &name);
43 int getLength(const eServiceReference &ref);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
97 DECLARE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT getName(const eServiceReference &ref, std::string &name);
100 int getLength(const eServiceReference &ref);
103 DEFINE_REF(eStaticServiceDVBBouquetInformation);
105 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
107 ePtr<iDVBChannelList> db;
108 ePtr<eDVBResourceManager> res;
111 if ((err = eDVBResourceManager::getInstance(res)) != 0)
113 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
116 if ((err = res->getChannelList(db)) != 0)
118 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
123 if ((err = db->getBouquet(ref, bouquet)) != 0)
125 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
129 if ( bouquet && bouquet->m_bouquet_name.length() )
131 name = bouquet->m_bouquet_name;
138 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
143 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
145 DECLARE_REF(eStaticServiceDVBPVRInformation);
146 eServiceReference m_ref;
147 eDVBMetaParser m_parser;
149 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
150 RESULT getName(const eServiceReference &ref, std::string &name);
151 int getLength(const eServiceReference &ref);
153 int getInfo(const eServiceReference &ref, int w);
154 std::string getInfoString(const eServiceReference &ref,int w);
157 DEFINE_REF(eStaticServiceDVBPVRInformation);
159 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
162 m_parser.parseFile(ref.path);
165 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
167 ASSERT(ref == m_ref);
168 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
172 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
174 ASSERT(ref == m_ref);
178 if (tstools.openFile(ref.path.c_str()))
182 if (tstools.calcLen(len))
188 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
192 case iServiceInformation::sDescription:
193 return iServiceInformation::resIsString;
194 case iServiceInformation::sServiceref:
195 return iServiceInformation::resIsString;
196 case iServiceInformation::sTimeCreate:
197 if (m_parser.m_time_create)
198 return m_parser.m_time_create;
200 return iServiceInformation::resNA;
202 return iServiceInformation::resNA;
206 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
210 case iServiceInformation::sDescription:
211 return m_parser.m_description;
212 case iServiceInformation::sServiceref:
213 return m_parser.m_ref.toString();
219 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
221 DECLARE_REF(eDVBPVRServiceOfflineOperations);
222 eServiceReferenceDVB m_ref;
224 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
226 RESULT deleteFromDisk(int simulate);
227 RESULT getListOfFilenames(std::list<std::string> &);
230 DEFINE_REF(eDVBPVRServiceOfflineOperations);
232 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
236 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
242 std::list<std::string> res;
243 if (getListOfFilenames(res))
246 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
248 eDebug("FATAL !! can't get background file eraser");
250 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
252 eDebug("Removing %s...", i->c_str());
254 eraser->erase(i->c_str());
256 ::unlink(i->c_str());
263 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
266 res.push_back(m_ref.path);
268 // handling for old splitted recordings (enigma 1)
273 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
275 if (stat(buf, &s) < 0)
280 res.push_back(m_ref.path + ".meta");
281 res.push_back(m_ref.path + ".ap");
282 res.push_back(m_ref.path + ".cuts");
283 std::string tmp = m_ref.path;
284 tmp.erase(m_ref.path.length()-3);
285 res.push_back(tmp + ".eit");
289 DEFINE_REF(eServiceFactoryDVB)
291 eServiceFactoryDVB::eServiceFactoryDVB()
293 ePtr<eServiceCenter> sc;
295 eServiceCenter::getPrivInstance(sc);
297 sc->addServiceFactory(eServiceFactoryDVB::id, this);
300 eServiceFactoryDVB::~eServiceFactoryDVB()
302 ePtr<eServiceCenter> sc;
304 eServiceCenter::getPrivInstance(sc);
306 sc->removeServiceFactory(eServiceFactoryDVB::id);
309 DEFINE_REF(eDVBServiceList);
311 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
315 eDVBServiceList::~eDVBServiceList()
319 RESULT eDVBServiceList::startQuery()
321 ePtr<iDVBChannelList> db;
322 ePtr<eDVBResourceManager> res;
325 if ((err = eDVBResourceManager::getInstance(res)) != 0)
327 eDebug("no resource manager");
330 if ((err = res->getChannelList(db)) != 0)
332 eDebug("no channel list");
336 ePtr<eDVBChannelQuery> q;
338 if (!m_parent.path.empty())
340 eDVBChannelQuery::compile(q, m_parent.path);
343 eDebug("compile query failed");
348 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
350 eDebug("startQuery failed");
357 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
359 eServiceReferenceDVB ref;
364 while (!m_query->getNextResult(ref))
368 list.sort(iListableServiceCompare(this));
373 // The first argument of this function is a format string to specify the order and
374 // the content of the returned list
375 // useable format options are
376 // R = Service Reference (as swig object .. this is very slow)
377 // S = Service Reference (as python string object .. same as ref.toString())
378 // N = Service Name (as python string object)
379 // when exactly one return value per service is selected in the format string,
380 // then each value is directly a list entry
381 // when more than one value is returned per service, then the list is a list of
383 // unknown format string chars are returned as python None values !
384 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
387 std::list<eServiceReference> tmplist;
390 if (!format || !(retcount=strlen(format)))
391 format = "R"; // just return service reference swig object ...
393 if (!getContent(tmplist, sorted))
395 int services=tmplist.size();
396 ePtr<iStaticServiceInformation> sptr;
397 eServiceCenterPtr service_center;
399 if (strchr(format, 'N'))
400 eServiceCenter::getPrivInstance(service_center);
402 ret = PyList_New(services);
403 std::list<eServiceReference>::iterator it(tmplist.begin());
405 for (int cnt=0; cnt < services; ++cnt)
407 eServiceReference &ref=*it++;
408 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
409 for (int i=0; i < retcount; ++i)
414 case 'R': // service reference (swig)object
415 tmp = New_eServiceReference(ref);
417 case 'S': // service reference string
418 tmp = PyString_FromString(ref.toString().c_str());
420 case 'N': // service name
423 service_center->info(ref, sptr);
427 sptr->getName(ref, name);
429 tmp = PyString_FromString(name.c_str());
433 tmp = PyString_FromString("<n/a>");
446 PyTuple_SET_ITEM(tuple, i, tmp);
448 PyList_SET_ITEM(ret, cnt, tmp);
452 PyList_SET_ITEM(ret, cnt, tuple);
455 return ret ? ret : PyList_New(0);
458 RESULT eDVBServiceList::getNext(eServiceReference &ref)
463 return m_query->getNextResult((eServiceReferenceDVB&)ref);
466 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
468 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
471 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
473 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
475 ePtr<iDVBChannelList> db;
476 ePtr<eDVBResourceManager> resm;
478 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
481 if (db->getBouquet(m_parent, m_bouquet) != 0)
492 RESULT eDVBServiceList::addService(eServiceReference &ref)
496 return m_bouquet->addService(ref);
499 RESULT eDVBServiceList::removeService(eServiceReference &ref)
503 return m_bouquet->removeService(ref);
506 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
510 return m_bouquet->moveService(ref, pos);
513 RESULT eDVBServiceList::flushChanges()
517 return m_bouquet->flushChanges();
520 RESULT eDVBServiceList::setListName(const std::string &name)
524 return m_bouquet->setListName(name);
527 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
529 ePtr<eDVBService> service;
530 int r = lookupService(service, ref);
533 // check resources...
534 ptr = new eDVBServicePlay(ref, service);
538 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
540 if (ref.path.empty())
542 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
551 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
553 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
554 if (list->startQuery())
564 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
566 /* is a listable service? */
567 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
569 if ( !ref.name.empty() ) // satellites or providers list
570 ptr = new eStaticServiceDVBInformation;
571 else // a dvb bouquet
572 ptr = new eStaticServiceDVBBouquetInformation;
574 else if (!ref.path.empty()) /* do we have a PVR service? */
575 ptr = new eStaticServiceDVBPVRInformation(ref);
576 else // normal dvb service
578 ePtr<eDVBService> service;
579 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
580 ptr = new eStaticServiceDVBInformation;
582 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
588 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
590 if (ref.path.empty())
596 ptr = new eDVBPVRServiceOfflineOperations(ref);
601 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
603 // TODO: handle the listing itself
604 // if (ref.... == -1) .. return "... bouquets ...";
605 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
607 ePtr<iDVBChannelList> db;
608 ePtr<eDVBResourceManager> res;
611 if ((err = eDVBResourceManager::getInstance(res)) != 0)
613 eDebug("no resource manager");
616 if ((err = res->getChannelList(db)) != 0)
618 eDebug("no channel list");
622 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
623 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
625 eDebug("getService failed!");
632 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
633 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
636 m_is_pvr = !m_reference.path.empty();
638 m_timeshift_enabled = m_timeshift_active = 0;
641 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
642 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
643 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
645 m_cuesheet_changed = 0;
646 m_cutlist_enabled = 1;
648 m_subtitle_widget = 0;
650 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
653 eDVBServicePlay::~eDVBServicePlay()
655 delete m_subtitle_widget;
658 void eDVBServicePlay::gotNewEvent()
662 ePtr<eServiceEvent> m_event_now, m_event_next;
663 getEvent(m_event_now, 0);
664 getEvent(m_event_next, 1);
667 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
669 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
671 m_event((iPlayableService*)this, evUpdatedEventInfo);
674 void eDVBServicePlay::serviceEvent(int event)
678 case eDVBServicePMTHandler::eventTuned:
680 ePtr<iDVBDemux> m_demux;
681 if (!m_service_handler.getDataDemux(m_demux))
683 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
684 int sid = ref.getParentServiceID().get();
686 sid = ref.getServiceID().get();
687 if ( ref.getParentTransportStreamID().get() &&
688 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
689 m_event_handler.startOther(m_demux, sid);
691 m_event_handler.start(m_demux, sid);
695 case eDVBServicePMTHandler::eventTuneFailed:
697 eDebug("DVB service failed to tune");
698 m_event((iPlayableService*)this, evTuneFailed);
701 case eDVBServicePMTHandler::eventNewProgramInfo:
703 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
704 if (m_timeshift_enabled)
705 updateTimeshiftPids();
706 if (!m_timeshift_active)
708 if (m_first_program_info && m_is_pvr)
710 m_first_program_info = 0;
713 m_event((iPlayableService*)this, evUpdatedInfo);
716 case eDVBServicePMTHandler::eventEOF:
717 m_event((iPlayableService*)this, evEOF);
719 case eDVBServicePMTHandler::eventSOF:
720 m_event((iPlayableService*)this, evSOF);
725 void eDVBServicePlay::serviceEventTimeshift(int event)
729 case eDVBServicePMTHandler::eventNewProgramInfo:
730 if (m_timeshift_active)
733 case eDVBServicePMTHandler::eventSOF:
734 m_event((iPlayableService*)this, evSOF);
736 case eDVBServicePMTHandler::eventEOF:
742 RESULT eDVBServicePlay::start()
745 /* in pvr mode, we only want to use one demux. in tv mode, we're using
746 two (one for decoding, one for data source), as we must be prepared
747 to start recording from the data demux. */
749 m_cue = new eCueSheet();
751 m_first_program_info = 1;
752 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
753 r = m_service_handler.tune(service, m_is_pvr, m_cue);
755 /* inject EIT if there is a stored one */
758 std::string filename = service.path;
759 filename.erase(filename.length()-2, 2);
761 int fd = ::open( filename.c_str(), O_RDONLY );
765 int rd = ::read(fd, buf, 4096);
767 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
770 ePtr<eServiceEvent> event = new eServiceEvent;
771 ePtr<eServiceEvent> empty;
772 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
773 m_event_handler.inject(event, 0);
774 m_event_handler.inject(empty, 1);
783 m_event(this, evStart);
784 m_event((iPlayableService*)this, evSeekableStatusChanged);
788 RESULT eDVBServicePlay::stop()
790 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
792 m_service_handler_timeshift.free();
793 m_service_handler.free();
795 if (m_is_pvr && m_cuesheet_changed)
801 RESULT eDVBServicePlay::setTarget(int target)
803 m_is_primary = !target;
807 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
809 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
813 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
815 /* note: we check for timeshift to be enabled,
816 not neccessary active. if you pause when timeshift
817 is not active, you should activate it when unpausing */
818 if ((!m_is_pvr) && (!m_timeshift_enabled))
828 RESULT eDVBServicePlay::setSlowMotion(int ratio)
831 return m_decoder->setSlowMotion(ratio);
836 RESULT eDVBServicePlay::setFastForward(int ratio)
838 int skipmode, ffratio;
844 } else if (ratio > 0)
852 } else // if (ratio < 0)
858 if (m_skipmode != skipmode)
860 eDebug("setting cue skipmode to %d", skipmode);
862 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
865 m_skipmode = skipmode;
870 return m_decoder->setFastForward(ffratio);
873 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
875 if (m_is_pvr || m_timeshift_enabled)
885 /* TODO: when timeshift is enabled but not active, this doesn't work. */
886 RESULT eDVBServicePlay::getLength(pts_t &len)
888 ePtr<iDVBPVRChannel> pvr_channel;
890 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
893 return pvr_channel->getLength(len);
896 RESULT eDVBServicePlay::pause()
898 if (!m_is_paused && m_decoder)
901 return m_decoder->freeze(0);
906 RESULT eDVBServicePlay::unpause()
908 if (m_is_paused && m_decoder)
911 return m_decoder->unfreeze();
916 RESULT eDVBServicePlay::seekTo(pts_t to)
918 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
923 ePtr<iDVBPVRChannel> pvr_channel;
925 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
931 m_cue->seekTo(0, to);
935 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
937 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
942 ePtr<iDVBPVRChannel> pvr_channel;
944 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
949 /* HACK until we have skip-AP api */
950 if ((to > 0) && (to < 100))
958 m_cue->seekTo(mode, to);
962 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
964 ePtr<iDVBPVRChannel> pvr_channel;
969 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
974 /* if there is a decoder, use audio or video PTS */
977 r = m_decoder->getPTS(0, pos);
983 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
986 RESULT eDVBServicePlay::setTrickmode(int trick)
989 m_decoder->setTrickmode(trick);
993 RESULT eDVBServicePlay::isCurrentlySeekable()
995 return m_is_pvr || m_timeshift_active;
998 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1004 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1010 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1016 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1022 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1028 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1031 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1032 (m_timeshift_enabled || !m_is_pvr))
1034 if (!m_timeshift_enabled)
1036 /* we need enough diskspace */
1038 if (statfs(TSPATH "/.", &fs) < 0)
1040 eDebug("statfs failed!");
1044 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1046 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1056 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1067 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1073 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1079 RESULT eDVBServicePlay::getName(std::string &name)
1083 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1084 return i->getName(m_reference, name);
1088 m_dvb_service->getName(m_reference, name);
1092 else if (!m_reference.name.empty())
1093 eStaticServiceDVBInformation().getName(m_reference, name);
1095 name = "DVB service";
1099 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1101 return m_event_handler.getEvent(evt, nownext);
1104 int eDVBServicePlay::getInfo(int w)
1106 eDVBServicePMTHandler::program program;
1109 return resIsPyObject;
1111 if (m_service_handler.getProgramInfo(program))
1117 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1119 ePtr<eServiceEvent> evt;
1120 if (!m_event_handler.getEvent(evt, 0))
1122 ePtr<eComponentData> data;
1123 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1125 if ( data->getStreamContent() == 1 )
1127 switch(data->getComponentType())
1130 case 1: // 4:3 SD PAL
1132 case 3: // 16:9 SD PAL
1133 case 4: // > 16:9 PAL
1134 case 5: // 4:3 SD NTSC
1136 case 7: // 16:9 SD NTSC
1137 case 8: // > 16:9 NTSC
1140 case 9: // 4:3 HD PAL
1142 case 0xB: // 16:9 HD PAL
1143 case 0xC: // > 16:9 HD PAL
1144 case 0xD: // 4:3 HD NTSC
1146 case 0xF: // 16:9 HD NTSC
1147 case 0x10: // > 16:9 HD PAL
1148 return data->getComponentType();
1155 case sIsCrypted: return program.isCrypted();
1156 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1157 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1158 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1159 case sPCRPID: return program.pcrPid;
1160 case sPMTPID: return program.pmtPid;
1161 case sTXTPID: return program.textPid;
1162 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1163 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1164 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1165 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1166 case sProvider: if (!m_dvb_service) return -1; return -2;
1172 std::string eDVBServicePlay::getInfoString(int w)
1177 if (!m_dvb_service) return "";
1178 return m_dvb_service->m_provider_name;
1182 return iServiceInformation::getInfoString(w);
1185 PyObject *eDVBServicePlay::getInfoObject(int w)
1190 return m_service_handler.getCaIds();
1194 return iServiceInformation::getInfoObject(w);
1197 int eDVBServicePlay::getNumberOfTracks()
1199 eDVBServicePMTHandler::program program;
1200 if (m_service_handler.getProgramInfo(program))
1202 return program.audioStreams.size();
1205 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1207 int ret = selectAudioStream(i);
1209 if (m_decoder->start())
1215 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1217 eDVBServicePMTHandler::program program;
1219 if (m_service_handler.getProgramInfo(program))
1222 if (i >= program.audioStreams.size())
1225 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1226 info.m_description = "MPEG";
1227 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1228 info.m_description = "AC3";
1229 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1230 info.m_description = "AAC";
1231 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1232 info.m_description = "DTS";
1234 info.m_description = "???";
1236 if (program.audioStreams[i].component_tag != -1)
1238 ePtr<eServiceEvent> evt;
1239 if (!m_event_handler.getEvent(evt, 0))
1241 ePtr<eComponentData> data;
1242 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1243 info.m_language = data->getText();
1247 if (info.m_language.empty())
1248 info.m_language = program.audioStreams[i].language_code;
1253 int eDVBServicePlay::selectAudioStream(int i)
1255 eDVBServicePMTHandler::program program;
1257 if (m_service_handler.getProgramInfo(program))
1260 if ((unsigned int)i >= program.audioStreams.size())
1266 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1269 if (m_dvb_service && !m_is_pvr)
1271 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1273 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1274 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1277 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1278 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1282 m_current_audio_stream = i;
1287 int eDVBServicePlay::getCurrentChannel()
1289 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1292 RESULT eDVBServicePlay::selectChannel(int i)
1294 if (i < LEFT || i > RIGHT || i == STEREO)
1297 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1299 m_decoder->setAudioChannel(i);
1303 int eDVBServiceBase::getFrontendInfo(int w)
1305 eUsePtr<iDVBChannel> channel;
1306 if(m_service_handler.getChannel(channel))
1308 ePtr<iDVBFrontend> fe;
1309 if(channel->getFrontend(fe))
1311 return fe->readFrontendData(w);
1314 PyObject *eDVBServiceBase::getFrontendData(bool original)
1318 eUsePtr<iDVBChannel> channel;
1319 if(!m_service_handler.getChannel(channel))
1321 ePtr<iDVBFrontend> fe;
1322 if(!channel->getFrontend(fe))
1324 ret = fe->readTransponderData(original);
1327 ePtr<iDVBFrontendParameters> feparm;
1328 channel->getCurrentFrontendParameters(feparm);
1331 eDVBFrontendParametersSatellite osat;
1332 if (!feparm->getDVBS(osat))
1334 void PutToDict(PyObject *, const char*, long);
1335 void PutToDict(PyObject *, const char*, const char*);
1336 PutToDict(ret, "orbital_position", osat.orbital_position);
1337 const char *tmp = "UNKNOWN";
1338 switch(osat.polarisation)
1340 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1341 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1342 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1343 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1346 PutToDict(ret, "polarization", tmp);
1360 int eDVBServicePlay::getNumberOfSubservices()
1362 ePtr<eServiceEvent> evt;
1363 if (!m_event_handler.getEvent(evt, 0))
1364 return evt->getNumOfLinkageServices();
1368 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1370 ePtr<eServiceEvent> evt;
1371 if (!m_event_handler.getEvent(evt, 0))
1373 if (!evt->getLinkageService(sub, m_reference, n))
1376 sub.type=eServiceReference::idInvalid;
1380 RESULT eDVBServicePlay::startTimeshift()
1382 ePtr<iDVBDemux> demux;
1384 eDebug("Start timeshift!");
1386 if (m_timeshift_enabled)
1389 /* start recording with the data demux. */
1390 if (m_service_handler.getDataDemux(demux))
1393 demux->createTSRecorder(m_record);
1397 char templ[]=TSPATH "/timeshift.XXXXXX";
1398 m_timeshift_fd = mkstemp(templ);
1399 m_timeshift_file = templ;
1401 eDebug("recording to %s", templ);
1403 if (m_timeshift_fd < 0)
1409 m_record->setTargetFD(m_timeshift_fd);
1411 m_timeshift_enabled = 1;
1413 updateTimeshiftPids();
1419 RESULT eDVBServicePlay::stopTimeshift()
1421 if (!m_timeshift_enabled)
1426 m_timeshift_enabled = 0;
1431 close(m_timeshift_fd);
1432 eDebug("remove timeshift file");
1433 remove(m_timeshift_file.c_str());
1438 int eDVBServicePlay::isTimeshiftActive()
1440 return m_timeshift_enabled && m_timeshift_active;
1443 RESULT eDVBServicePlay::activateTimeshift()
1445 if (!m_timeshift_enabled)
1448 if (!m_timeshift_active)
1450 switchToTimeshift();
1457 PyObject *eDVBServicePlay::getCutList()
1459 PyObject *list = PyList_New(0);
1461 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1463 PyObject *tuple = PyTuple_New(2);
1464 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1465 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1466 PyList_Append(list, tuple);
1473 void eDVBServicePlay::setCutList(PyObject *list)
1475 if (!PyList_Check(list))
1477 int size = PyList_Size(list);
1480 m_cue_entries.clear();
1482 for (i=0; i<size; ++i)
1484 PyObject *tuple = PyList_GetItem(list, i);
1485 if (!PyTuple_Check(tuple))
1487 eDebug("non-tuple in cutlist");
1490 if (PyTuple_Size(tuple) != 2)
1492 eDebug("cutlist entries need to be a 2-tuple");
1495 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1496 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1498 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1501 pts_t pts = PyLong_AsLongLong(ppts);
1502 int type = PyInt_AsLong(ptype);
1503 m_cue_entries.insert(cueEntry(pts, type));
1504 eDebug("adding %08llx, %d", pts, type);
1506 m_cuesheet_changed = 1;
1508 cutlistToCuesheet();
1509 m_event((iPlayableService*)this, evCuesheetChanged);
1512 void eDVBServicePlay::setCutListEnable(int enable)
1514 m_cutlist_enabled = enable;
1515 cutlistToCuesheet();
1518 void eDVBServicePlay::updateTimeshiftPids()
1523 eDVBServicePMTHandler::program program;
1524 if (m_service_handler.getProgramInfo(program))
1528 std::set<int> pids_to_record;
1529 pids_to_record.insert(0); // PAT
1530 if (program.pmtPid != -1)
1531 pids_to_record.insert(program.pmtPid); // PMT
1533 if (program.textPid != -1)
1534 pids_to_record.insert(program.textPid); // Videotext
1536 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1537 i(program.videoStreams.begin());
1538 i != program.videoStreams.end(); ++i)
1539 pids_to_record.insert(i->pid);
1541 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1542 i(program.audioStreams.begin());
1543 i != program.audioStreams.end(); ++i)
1544 pids_to_record.insert(i->pid);
1546 std::set<int> new_pids, obsolete_pids;
1548 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1549 m_pids_active.begin(), m_pids_active.end(),
1550 std::inserter(new_pids, new_pids.begin()));
1552 std::set_difference(
1553 m_pids_active.begin(), m_pids_active.end(),
1554 pids_to_record.begin(), pids_to_record.end(),
1555 std::inserter(new_pids, new_pids.begin())
1558 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1559 m_record->addPID(*i);
1561 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1562 m_record->removePID(*i);
1566 void eDVBServicePlay::switchToLive()
1568 if (!m_timeshift_active)
1574 m_teletext_parser = 0;
1575 m_new_subtitle_page_connection = 0;
1577 /* free the timeshift service handler, we need the resources */
1578 m_service_handler_timeshift.free();
1579 m_timeshift_active = 0;
1581 m_event((iPlayableService*)this, evSeekableStatusChanged);
1586 void eDVBServicePlay::switchToTimeshift()
1588 if (m_timeshift_active)
1593 m_teletext_parser = 0;
1594 m_new_subtitle_page_connection = 0;
1596 m_timeshift_active = 1;
1598 m_event((iPlayableService*)this, evSeekableStatusChanged);
1600 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1601 r.path = m_timeshift_file;
1603 m_cue = new eCueSheet();
1604 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1605 updateDecoder(); /* mainly to switch off PCR */
1608 void eDVBServicePlay::updateDecoder()
1610 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1612 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1614 bool defaultac3=false;
1615 std::string default_ac3;
1617 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1618 defaultac3 = default_ac3 == "enable";
1620 eDVBServicePMTHandler::program program;
1621 if (h.getProgramInfo(program))
1622 eDebug("getting program info failed.");
1625 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1626 if (!program.videoStreams.empty())
1628 eDebugNoNewLine(" (");
1629 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1630 i(program.videoStreams.begin());
1631 i != program.videoStreams.end(); ++i)
1638 if (i != program.videoStreams.begin())
1639 eDebugNoNewLine(", ");
1640 eDebugNoNewLine("%04x", i->pid);
1642 eDebugNoNewLine(")");
1644 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1645 if (!program.audioStreams.empty())
1647 eDebugNoNewLine(" (");
1648 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1649 i(program.audioStreams.begin());
1650 i != program.audioStreams.end(); ++i)
1652 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1654 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1660 if (i != program.audioStreams.begin())
1661 eDebugNoNewLine(", ");
1662 eDebugNoNewLine("%04x", i->pid);
1664 eDebugNoNewLine(")");
1666 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1667 pcrpid = program.pcrPid;
1668 eDebug(", and the text pid is %04x", program.textPid);
1669 tpid = program.textPid;
1674 h.getDecodeDemux(m_decode_demux);
1676 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1678 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1679 #ifdef INTERNAL_TELETEXT
1680 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1681 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1689 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1690 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1691 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1693 else // subservice or recording
1695 eServiceReferenceDVB ref;
1696 m_service_handler.getServiceReference(ref);
1697 eServiceReferenceDVB parent = ref.getParentServiceReference();
1702 ePtr<eDVBResourceManager> res_mgr;
1703 if (!eDVBResourceManager::getInstance(res_mgr))
1705 ePtr<iDVBChannelList> db;
1706 if (!res_mgr->getChannelList(db))
1708 ePtr<eDVBService> origService;
1709 if (!db->getService(parent, origService))
1711 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1712 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1718 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1719 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1721 m_decoder->setVideoPID(vpid, vpidtype);
1722 m_current_audio_stream = 0;
1723 m_decoder->setAudioPID(apid, apidtype);
1724 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1725 m_decoder->setSyncPCR(pcrpid);
1727 m_decoder->setSyncPCR(-1);
1729 m_decoder->setTextPID(tpid);
1731 if (m_teletext_parser)
1732 m_teletext_parser->start(tpid);
1735 m_decoder->setTrickmode(1);
1739 if (vpid > 0 && vpid < 0x2000)
1743 std::string radio_pic;
1744 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1745 m_decoder->setRadioPic(radio_pic);
1748 m_decoder->setAudioChannel(achannel);
1750 // how we can do this better?
1751 // update cache pid when the user changed the audio track or video track
1752 // TODO handling of difference audio types.. default audio types..
1754 /* don't worry about non-existing services, nor pvr services */
1755 if (m_dvb_service && !m_is_pvr)
1757 if (apidtype == eDVBAudio::aMPEG)
1759 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1760 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1764 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1765 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1767 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1768 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1769 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1770 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1773 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1776 void eDVBServicePlay::loadCuesheet()
1778 std::string filename = m_reference.path + ".cuts";
1780 m_cue_entries.clear();
1782 FILE *f = fopen(filename.c_str(), "rb");
1786 eDebug("loading cuts..");
1789 unsigned long long where;
1792 if (!fread(&where, sizeof(where), 1, f))
1794 if (!fread(&what, sizeof(what), 1, f))
1797 #if BYTE_ORDER == LITTLE_ENDIAN
1798 where = bswap_64(where);
1805 m_cue_entries.insert(cueEntry(where, what));
1808 eDebug("%d entries", m_cue_entries.size());
1810 eDebug("cutfile not found!");
1812 m_cuesheet_changed = 0;
1813 cutlistToCuesheet();
1814 m_event((iPlayableService*)this, evCuesheetChanged);
1817 void eDVBServicePlay::saveCuesheet()
1819 std::string filename = m_reference.path + ".cuts";
1821 FILE *f = fopen(filename.c_str(), "wb");
1825 unsigned long long where;
1828 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1830 #if BYTE_ORDER == BIG_ENDIAN
1833 where = bswap_64(i->where);
1835 what = htonl(i->what);
1836 fwrite(&where, sizeof(where), 1, f);
1837 fwrite(&what, sizeof(what), 1, f);
1843 m_cuesheet_changed = 0;
1846 void eDVBServicePlay::cutlistToCuesheet()
1850 eDebug("no cue sheet");
1855 if (!m_cutlist_enabled)
1857 m_cue->commitSpans();
1858 eDebug("cutlists where disabled");
1862 pts_t in = 0, out = 0, length = 0;
1866 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1870 if (i == m_cue_entries.end())
1873 if (i->what == 0) /* in */
1877 } else if (i->what == 1) /* out */
1887 m_cue->addSourceSpan(in, out);
1891 if (i == m_cue_entries.end())
1894 m_cue->commitSpans();
1897 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1899 if (m_subtitle_widget)
1900 disableSubtitles(parent);
1902 if (!m_teletext_parser)
1905 if (!PyInt_Check(entry))
1908 m_subtitle_widget = new eSubtitleWidget(parent);
1909 m_subtitle_widget->resize(parent->size()); /* full size */
1911 int page = PyInt_AsLong(entry);
1913 m_teletext_parser->setPage(page);
1918 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1920 delete m_subtitle_widget;
1921 m_subtitle_widget = 0;
1925 PyObject *eDVBServicePlay::getSubtitleList()
1927 if (!m_teletext_parser)
1933 PyObject *l = PyList_New(0);
1935 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1937 PyObject *tuple = PyTuple_New(2);
1939 sprintf(desc, "Page %x", *i);
1940 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1941 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1942 PyList_Append(l, tuple);
1948 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1950 if (m_subtitle_widget)
1952 m_subtitle_pages.push_back(page);
1954 checkSubtitleTiming();
1958 void eDVBServicePlay::checkSubtitleTiming()
1962 if (m_subtitle_pages.empty())
1965 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1970 m_decoder->getPTS(0, pos);
1972 int diff = p.m_pts - pos;
1975 eDebug("[late (%d ms)]", -diff / 90);
1980 eDebug("[invalid]");
1986 m_subtitle_widget->setPage(p);
1987 m_subtitle_pages.pop_front();
1990 m_subtitle_sync_timer.start(diff / 90, 1);
1996 int eDVBServicePlay::getAC3Delay()
1999 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2001 return m_decoder->getAC3Delay();
2006 int eDVBServicePlay::getPCMDelay()
2009 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2011 return m_decoder->getPCMDelay();
2016 void eDVBServicePlay::setAC3Delay(int delay)
2019 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2021 m_decoder->setAC3Delay(delay);
2024 void eDVBServicePlay::setPCMDelay(int delay)
2027 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2029 m_decoder->setPCMDelay(delay);
2032 DEFINE_REF(eDVBServicePlay)
2034 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");