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_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 // get back correct service reference (after parsing of recording meta files)
756 m_service_handler.getServiceReference(service);
758 /* inject EIT if there is a stored one */
761 std::string filename = service.path;
762 filename.erase(filename.length()-2, 2);
764 int fd = ::open( filename.c_str(), O_RDONLY );
768 int rd = ::read(fd, buf, 4096);
770 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
773 ePtr<eServiceEvent> event = new eServiceEvent;
774 ePtr<eServiceEvent> empty;
775 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
776 m_event_handler.inject(event, 0);
777 m_event_handler.inject(empty, 1);
786 m_event(this, evStart);
787 m_event((iPlayableService*)this, evSeekableStatusChanged);
791 RESULT eDVBServicePlay::stop()
793 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
795 m_service_handler_timeshift.free();
796 m_service_handler.free();
798 if (m_is_pvr && m_cuesheet_changed)
804 RESULT eDVBServicePlay::setTarget(int target)
806 m_is_primary = !target;
810 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
812 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
816 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
818 /* note: we check for timeshift to be enabled,
819 not neccessary active. if you pause when timeshift
820 is not active, you should activate it when unpausing */
821 if ((!m_is_pvr) && (!m_timeshift_enabled))
831 RESULT eDVBServicePlay::setSlowMotion(int ratio)
834 return m_decoder->setSlowMotion(ratio);
839 RESULT eDVBServicePlay::setFastForward(int ratio)
841 int skipmode, ffratio;
847 } else if (ratio > 0)
855 } else // if (ratio < 0)
861 if (m_skipmode != skipmode)
863 eDebug("setting cue skipmode to %d", skipmode);
865 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
868 m_skipmode = skipmode;
873 return m_decoder->setFastForward(ffratio);
876 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
878 if (m_is_pvr || m_timeshift_enabled)
888 /* TODO: when timeshift is enabled but not active, this doesn't work. */
889 RESULT eDVBServicePlay::getLength(pts_t &len)
891 ePtr<iDVBPVRChannel> pvr_channel;
893 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
896 return pvr_channel->getLength(len);
899 RESULT eDVBServicePlay::pause()
901 if (!m_is_paused && m_decoder)
904 return m_decoder->freeze(0);
909 RESULT eDVBServicePlay::unpause()
911 if (m_is_paused && m_decoder)
914 return m_decoder->unfreeze();
919 RESULT eDVBServicePlay::seekTo(pts_t to)
921 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
926 ePtr<iDVBPVRChannel> pvr_channel;
928 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
934 m_cue->seekTo(0, to);
938 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
940 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
945 ePtr<iDVBPVRChannel> pvr_channel;
947 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
952 /* HACK until we have skip-AP api */
953 if ((to > 0) && (to < 100))
961 m_cue->seekTo(mode, to);
965 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
967 ePtr<iDVBPVRChannel> pvr_channel;
972 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
977 /* if there is a decoder, use audio or video PTS */
980 r = m_decoder->getPTS(0, pos);
986 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
989 RESULT eDVBServicePlay::setTrickmode(int trick)
992 m_decoder->setTrickmode(trick);
996 RESULT eDVBServicePlay::isCurrentlySeekable()
998 return m_is_pvr || m_timeshift_active;
1001 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1007 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1013 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1019 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1025 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1031 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1034 if (m_timeshift_enabled || !m_is_pvr)
1036 if (!m_timeshift_enabled)
1038 /* we need enough diskspace */
1040 if (statfs(TSPATH "/.", &fs) < 0)
1042 eDebug("statfs failed!");
1046 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1048 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1058 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1069 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1075 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1081 RESULT eDVBServicePlay::getName(std::string &name)
1085 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1086 return i->getName(m_reference, name);
1090 m_dvb_service->getName(m_reference, name);
1094 else if (!m_reference.name.empty())
1095 eStaticServiceDVBInformation().getName(m_reference, name);
1097 name = "DVB service";
1101 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1103 return m_event_handler.getEvent(evt, nownext);
1106 int eDVBServicePlay::getInfo(int w)
1108 eDVBServicePMTHandler::program program;
1111 return resIsPyObject;
1113 if (m_service_handler.getProgramInfo(program))
1119 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1121 ePtr<eServiceEvent> evt;
1122 if (!m_event_handler.getEvent(evt, 0))
1124 ePtr<eComponentData> data;
1125 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1127 if ( data->getStreamContent() == 1 )
1129 switch(data->getComponentType())
1132 case 1: // 4:3 SD PAL
1134 case 3: // 16:9 SD PAL
1135 case 4: // > 16:9 PAL
1136 case 5: // 4:3 SD NTSC
1138 case 7: // 16:9 SD NTSC
1139 case 8: // > 16:9 NTSC
1142 case 9: // 4:3 HD PAL
1144 case 0xB: // 16:9 HD PAL
1145 case 0xC: // > 16:9 HD PAL
1146 case 0xD: // 4:3 HD NTSC
1148 case 0xF: // 16:9 HD NTSC
1149 case 0x10: // > 16:9 HD PAL
1150 return data->getComponentType();
1157 case sIsCrypted: return program.isCrypted();
1158 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1159 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1160 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1161 case sPCRPID: return program.pcrPid;
1162 case sPMTPID: return program.pmtPid;
1163 case sTXTPID: return program.textPid;
1164 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1165 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1166 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1167 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1168 case sProvider: if (!m_dvb_service) return -1; return -2;
1174 std::string eDVBServicePlay::getInfoString(int w)
1179 if (!m_dvb_service) return "";
1180 return m_dvb_service->m_provider_name;
1184 return iServiceInformation::getInfoString(w);
1187 PyObject *eDVBServicePlay::getInfoObject(int w)
1192 return m_service_handler.getCaIds();
1196 return iServiceInformation::getInfoObject(w);
1199 int eDVBServicePlay::getNumberOfTracks()
1201 eDVBServicePMTHandler::program program;
1202 if (m_service_handler.getProgramInfo(program))
1204 return program.audioStreams.size();
1207 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1209 int ret = selectAudioStream(i);
1211 if (m_decoder->start())
1217 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1219 eDVBServicePMTHandler::program program;
1221 if (m_service_handler.getProgramInfo(program))
1224 if (i >= program.audioStreams.size())
1227 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1228 info.m_description = "MPEG";
1229 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1230 info.m_description = "AC3";
1231 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1232 info.m_description = "AAC";
1233 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1234 info.m_description = "DTS";
1236 info.m_description = "???";
1238 if (program.audioStreams[i].component_tag != -1)
1240 ePtr<eServiceEvent> evt;
1241 if (!m_event_handler.getEvent(evt, 0))
1243 ePtr<eComponentData> data;
1244 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1245 info.m_language = data->getText();
1249 if (info.m_language.empty())
1250 info.m_language = program.audioStreams[i].language_code;
1255 int eDVBServicePlay::selectAudioStream(int i)
1257 eDVBServicePMTHandler::program program;
1259 if (m_service_handler.getProgramInfo(program))
1262 if ((unsigned int)i >= program.audioStreams.size())
1268 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1271 if (m_dvb_service && !m_is_pvr)
1273 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1275 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1276 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1279 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1280 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1284 m_current_audio_stream = i;
1289 int eDVBServicePlay::getCurrentChannel()
1291 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1294 RESULT eDVBServicePlay::selectChannel(int i)
1296 if (i < LEFT || i > RIGHT || i == STEREO)
1299 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1301 m_decoder->setAudioChannel(i);
1305 int eDVBServiceBase::getFrontendInfo(int w)
1307 eUsePtr<iDVBChannel> channel;
1308 if(m_service_handler.getChannel(channel))
1310 ePtr<iDVBFrontend> fe;
1311 if(channel->getFrontend(fe))
1313 return fe->readFrontendData(w);
1316 PyObject *eDVBServiceBase::getFrontendData(bool original)
1320 eUsePtr<iDVBChannel> channel;
1321 if(!m_service_handler.getChannel(channel))
1323 ePtr<iDVBFrontend> fe;
1324 if(!channel->getFrontend(fe))
1326 ret = fe->readTransponderData(original);
1329 ePtr<iDVBFrontendParameters> feparm;
1330 channel->getCurrentFrontendParameters(feparm);
1333 eDVBFrontendParametersSatellite osat;
1334 if (!feparm->getDVBS(osat))
1336 void PutToDict(PyObject *, const char*, long);
1337 void PutToDict(PyObject *, const char*, const char*);
1338 PutToDict(ret, "orbital_position", osat.orbital_position);
1339 const char *tmp = "UNKNOWN";
1340 switch(osat.polarisation)
1342 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1343 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1344 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1345 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1348 PutToDict(ret, "polarization", tmp);
1362 int eDVBServicePlay::getNumberOfSubservices()
1364 ePtr<eServiceEvent> evt;
1365 if (!m_event_handler.getEvent(evt, 0))
1366 return evt->getNumOfLinkageServices();
1370 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1372 ePtr<eServiceEvent> evt;
1373 if (!m_event_handler.getEvent(evt, 0))
1375 if (!evt->getLinkageService(sub, m_reference, n))
1378 sub.type=eServiceReference::idInvalid;
1382 RESULT eDVBServicePlay::startTimeshift()
1384 ePtr<iDVBDemux> demux;
1386 eDebug("Start timeshift!");
1388 if (m_timeshift_enabled)
1391 /* start recording with the data demux. */
1392 if (m_service_handler.getDataDemux(demux))
1395 demux->createTSRecorder(m_record);
1399 char templ[]=TSPATH "/timeshift.XXXXXX";
1400 m_timeshift_fd = mkstemp(templ);
1401 m_timeshift_file = templ;
1403 eDebug("recording to %s", templ);
1405 if (m_timeshift_fd < 0)
1411 m_record->setTargetFD(m_timeshift_fd);
1413 m_timeshift_enabled = 1;
1415 updateTimeshiftPids();
1421 RESULT eDVBServicePlay::stopTimeshift()
1423 if (!m_timeshift_enabled)
1428 m_timeshift_enabled = 0;
1433 close(m_timeshift_fd);
1434 eDebug("remove timeshift file");
1435 remove(m_timeshift_file.c_str());
1440 int eDVBServicePlay::isTimeshiftActive()
1442 return m_timeshift_enabled && m_timeshift_active;
1445 RESULT eDVBServicePlay::activateTimeshift()
1447 if (!m_timeshift_enabled)
1450 if (!m_timeshift_active)
1452 switchToTimeshift();
1459 PyObject *eDVBServicePlay::getCutList()
1461 PyObject *list = PyList_New(0);
1463 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1465 PyObject *tuple = PyTuple_New(2);
1466 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1467 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1468 PyList_Append(list, tuple);
1475 void eDVBServicePlay::setCutList(PyObject *list)
1477 if (!PyList_Check(list))
1479 int size = PyList_Size(list);
1482 m_cue_entries.clear();
1484 for (i=0; i<size; ++i)
1486 PyObject *tuple = PyList_GetItem(list, i);
1487 if (!PyTuple_Check(tuple))
1489 eDebug("non-tuple in cutlist");
1492 if (PyTuple_Size(tuple) != 2)
1494 eDebug("cutlist entries need to be a 2-tuple");
1497 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1498 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1500 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1503 pts_t pts = PyLong_AsLongLong(ppts);
1504 int type = PyInt_AsLong(ptype);
1505 m_cue_entries.insert(cueEntry(pts, type));
1506 eDebug("adding %08llx, %d", pts, type);
1508 m_cuesheet_changed = 1;
1510 cutlistToCuesheet();
1511 m_event((iPlayableService*)this, evCuesheetChanged);
1514 void eDVBServicePlay::setCutListEnable(int enable)
1516 m_cutlist_enabled = enable;
1517 cutlistToCuesheet();
1520 void eDVBServicePlay::updateTimeshiftPids()
1525 eDVBServicePMTHandler::program program;
1526 if (m_service_handler.getProgramInfo(program))
1530 std::set<int> pids_to_record;
1531 pids_to_record.insert(0); // PAT
1532 if (program.pmtPid != -1)
1533 pids_to_record.insert(program.pmtPid); // PMT
1535 if (program.textPid != -1)
1536 pids_to_record.insert(program.textPid); // Videotext
1538 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1539 i(program.videoStreams.begin());
1540 i != program.videoStreams.end(); ++i)
1541 pids_to_record.insert(i->pid);
1543 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1544 i(program.audioStreams.begin());
1545 i != program.audioStreams.end(); ++i)
1546 pids_to_record.insert(i->pid);
1548 std::set<int> new_pids, obsolete_pids;
1550 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1551 m_pids_active.begin(), m_pids_active.end(),
1552 std::inserter(new_pids, new_pids.begin()));
1554 std::set_difference(
1555 m_pids_active.begin(), m_pids_active.end(),
1556 pids_to_record.begin(), pids_to_record.end(),
1557 std::inserter(new_pids, new_pids.begin())
1560 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1561 m_record->addPID(*i);
1563 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1564 m_record->removePID(*i);
1568 void eDVBServicePlay::switchToLive()
1570 if (!m_timeshift_active)
1576 m_teletext_parser = 0;
1577 m_new_subtitle_page_connection = 0;
1579 /* free the timeshift service handler, we need the resources */
1580 m_service_handler_timeshift.free();
1581 m_timeshift_active = 0;
1583 m_event((iPlayableService*)this, evSeekableStatusChanged);
1588 void eDVBServicePlay::switchToTimeshift()
1590 if (m_timeshift_active)
1595 m_teletext_parser = 0;
1596 m_new_subtitle_page_connection = 0;
1598 m_timeshift_active = 1;
1600 m_event((iPlayableService*)this, evSeekableStatusChanged);
1602 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1603 r.path = m_timeshift_file;
1605 m_cue = new eCueSheet();
1606 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1607 updateDecoder(); /* mainly to switch off PCR */
1610 void eDVBServicePlay::updateDecoder()
1612 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1614 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1616 bool defaultac3=false;
1617 std::string default_ac3;
1619 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1620 defaultac3 = default_ac3 == "enable";
1622 eDVBServicePMTHandler::program program;
1623 if (h.getProgramInfo(program))
1624 eDebug("getting program info failed.");
1627 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1628 if (!program.videoStreams.empty())
1630 eDebugNoNewLine(" (");
1631 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1632 i(program.videoStreams.begin());
1633 i != program.videoStreams.end(); ++i)
1640 if (i != program.videoStreams.begin())
1641 eDebugNoNewLine(", ");
1642 eDebugNoNewLine("%04x", i->pid);
1644 eDebugNoNewLine(")");
1646 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1647 if (!program.audioStreams.empty())
1649 eDebugNoNewLine(" (");
1650 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1651 i(program.audioStreams.begin());
1652 i != program.audioStreams.end(); ++i)
1654 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1656 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1662 if (i != program.audioStreams.begin())
1663 eDebugNoNewLine(", ");
1664 eDebugNoNewLine("%04x", i->pid);
1666 eDebugNoNewLine(")");
1668 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1669 pcrpid = program.pcrPid;
1670 eDebug(", and the text pid is %04x", program.textPid);
1671 tpid = program.textPid;
1676 h.getDecodeDemux(m_decode_demux);
1678 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1680 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1681 #ifdef INTERNAL_TELETEXT
1682 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1683 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1691 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1692 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1693 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1695 else // subservice or recording
1697 eServiceReferenceDVB parent = ((eServiceReferenceDVB&)m_reference).getParentServiceReference();
1698 if (!parent && !m_reference.path.empty()) // is recording
1700 parent = (eServiceReferenceDVB&)m_reference;
1705 ePtr<eDVBResourceManager> res_mgr;
1706 if (!eDVBResourceManager::getInstance(res_mgr))
1708 ePtr<iDVBChannelList> db;
1709 if (!res_mgr->getChannelList(db))
1711 ePtr<eDVBService> origService;
1712 if (!db->getService(parent, origService))
1714 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1715 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1722 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1723 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1725 m_decoder->setVideoPID(vpid, vpidtype);
1726 m_current_audio_stream = 0;
1727 m_decoder->setAudioPID(apid, apidtype);
1728 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1729 m_decoder->setSyncPCR(pcrpid);
1731 m_decoder->setSyncPCR(-1);
1733 m_decoder->setTextPID(tpid);
1735 if (m_teletext_parser)
1736 m_teletext_parser->start(tpid);
1739 m_decoder->setTrickmode(1);
1743 if (vpid > 0 && vpid < 0x2000)
1747 std::string radio_pic;
1748 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1749 m_decoder->setRadioPic(radio_pic);
1752 m_decoder->setAudioChannel(achannel);
1754 // how we can do this better?
1755 // update cache pid when the user changed the audio track or video track
1756 // TODO handling of difference audio types.. default audio types..
1758 /* don't worry about non-existing services, nor pvr services */
1759 if (m_dvb_service && !m_is_pvr)
1761 if (apidtype == eDVBAudio::aMPEG)
1763 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1764 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1768 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1769 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1771 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1772 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1773 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1774 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1779 void eDVBServicePlay::loadCuesheet()
1781 std::string filename = m_reference.path + ".cuts";
1783 m_cue_entries.clear();
1785 FILE *f = fopen(filename.c_str(), "rb");
1789 eDebug("loading cuts..");
1792 unsigned long long where;
1795 if (!fread(&where, sizeof(where), 1, f))
1797 if (!fread(&what, sizeof(what), 1, f))
1800 #if BYTE_ORDER == LITTLE_ENDIAN
1801 where = bswap_64(where);
1808 m_cue_entries.insert(cueEntry(where, what));
1811 eDebug("%d entries", m_cue_entries.size());
1813 eDebug("cutfile not found!");
1815 m_cuesheet_changed = 0;
1816 cutlistToCuesheet();
1817 m_event((iPlayableService*)this, evCuesheetChanged);
1820 void eDVBServicePlay::saveCuesheet()
1822 std::string filename = m_reference.path + ".cuts";
1824 FILE *f = fopen(filename.c_str(), "wb");
1828 unsigned long long where;
1831 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1833 #if BYTE_ORDER == BIG_ENDIAN
1836 where = bswap_64(i->where);
1838 what = htonl(i->what);
1839 fwrite(&where, sizeof(where), 1, f);
1840 fwrite(&what, sizeof(what), 1, f);
1846 m_cuesheet_changed = 0;
1849 void eDVBServicePlay::cutlistToCuesheet()
1853 eDebug("no cue sheet");
1858 if (!m_cutlist_enabled)
1860 m_cue->commitSpans();
1861 eDebug("cutlists where disabled");
1865 pts_t in = 0, out = 0, length = 0;
1869 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1873 if (i == m_cue_entries.end())
1876 if (i->what == 0) /* in */
1880 } else if (i->what == 1) /* out */
1890 m_cue->addSourceSpan(in, out);
1894 if (i == m_cue_entries.end())
1897 m_cue->commitSpans();
1900 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1902 if (m_subtitle_widget)
1903 disableSubtitles(parent);
1905 if (!m_teletext_parser)
1908 if (!PyInt_Check(entry))
1911 m_subtitle_widget = new eSubtitleWidget(parent);
1912 m_subtitle_widget->resize(parent->size()); /* full size */
1914 int page = PyInt_AsLong(entry);
1916 m_teletext_parser->setPage(page);
1921 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1923 delete m_subtitle_widget;
1924 m_subtitle_widget = 0;
1928 PyObject *eDVBServicePlay::getSubtitleList()
1930 if (!m_teletext_parser)
1936 PyObject *l = PyList_New(0);
1938 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1940 PyObject *tuple = PyTuple_New(2);
1942 sprintf(desc, "Page %x", *i);
1943 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1944 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1945 PyList_Append(l, tuple);
1951 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1953 if (m_subtitle_widget)
1955 m_subtitle_pages.push_back(page);
1957 checkSubtitleTiming();
1961 void eDVBServicePlay::checkSubtitleTiming()
1965 if (m_subtitle_pages.empty())
1968 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1973 m_decoder->getPTS(0, pos);
1975 int diff = p.m_pts - pos;
1978 eDebug("[late (%d ms)]", -diff / 90);
1983 eDebug("[invalid]");
1989 m_subtitle_widget->setPage(p);
1990 m_subtitle_pages.pop_front();
1993 m_subtitle_sync_timer.start(diff / 90, 1);
1999 int eDVBServicePlay::getAC3Delay()
2002 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2004 return m_decoder->getAC3Delay();
2009 int eDVBServicePlay::getPCMDelay()
2012 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2014 return m_decoder->getPCMDelay();
2019 void eDVBServicePlay::setAC3Delay(int delay)
2022 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2024 m_decoder->setAC3Delay(delay);
2027 void eDVBServicePlay::setPCMDelay(int delay)
2030 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2032 m_decoder->setPCMDelay(delay);
2035 DEFINE_REF(eDVBServicePlay)
2037 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");