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/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
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>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
101 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
103 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
105 PutToDict(dict, "tuner_type", "DVB-S");
106 PutToDict(dict, "frequency", feparm.frequency);
107 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
108 PutToDict(dict, "orbital_position", feparm.orbital_position);
109 PutToDict(dict, "inversion", feparm.inversion);
110 PutToDict(dict, "fec_inner", feparm.fec);
111 PutToDict(dict, "modulation", feparm.modulation);
112 PutToDict(dict, "polarization", feparm.polarisation);
113 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
115 PutToDict(dict, "rolloff", feparm.rolloff);
116 PutToDict(dict, "pilot", feparm.pilot);
118 PutToDict(dict, "system", feparm.system);
121 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
123 PutToDict(dict, "tuner_type", "DVB-T");
124 PutToDict(dict, "frequency", feparm.frequency);
125 PutToDict(dict, "bandwidth", feparm.bandwidth);
126 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
127 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
128 PutToDict(dict, "constellation", feparm.modulation);
129 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
130 PutToDict(dict, "guard_interval", feparm.guard_interval);
131 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
132 PutToDict(dict, "inversion", feparm.inversion);
135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
137 PutToDict(dict, "tuner_type", "DVB-C");
138 PutToDict(dict, "frequency", feparm.frequency);
139 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
140 PutToDict(dict, "modulation", feparm.modulation);
141 PutToDict(dict, "inversion", feparm.inversion);
142 PutToDict(dict, "fec_inner", feparm.fec_inner);
145 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
147 if (r.type == eServiceReference::idDVB)
149 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
152 case iServiceInformation::sTransponderData:
154 ePtr<eDVBResourceManager> res;
155 if (!eDVBResourceManager::getInstance(res))
157 ePtr<iDVBChannelList> db;
158 if (!res->getChannelList(db))
161 ref.getChannelID(chid);
162 ePtr<iDVBFrontendParameters> feparm;
163 if (!db->getChannelFrontendData(chid, feparm))
166 if (!feparm->getSystem(system))
168 ePyObject dict = PyDict_New();
171 case iDVBFrontend::feSatellite:
173 eDVBFrontendParametersSatellite s;
175 PutSatelliteDataToDict(dict, s);
178 case iDVBFrontend::feTerrestrial:
180 eDVBFrontendParametersTerrestrial t;
182 PutTerrestrialDataToDict(dict, t);
185 case iDVBFrontend::feCable:
187 eDVBFrontendParametersCable c;
189 PutCableDataToDict(dict, c);
193 eDebug("unknown frontend type %d", system);
208 DEFINE_REF(eStaticServiceDVBBouquetInformation);
210 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
212 ePtr<iDVBChannelList> db;
213 ePtr<eDVBResourceManager> res;
216 if ((err = eDVBResourceManager::getInstance(res)) != 0)
218 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
221 if ((err = res->getChannelList(db)) != 0)
223 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
228 if ((err = db->getBouquet(ref, bouquet)) != 0)
230 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
234 if ( bouquet && bouquet->m_bouquet_name.length() )
236 name = bouquet->m_bouquet_name;
243 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
245 if (ref.flags & eServiceReference::isGroup)
247 ePtr<iDVBChannelList> db;
248 ePtr<eDVBResourceManager> res;
250 if (eDVBResourceManager::getInstance(res))
252 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
256 if (res->getChannelList(db))
258 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
263 if (db->getBouquet(ref, bouquet))
265 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
269 int prio_order = eDVBFrontend::getTypePriorityOrder();
271 eDVBChannelID chid, chid_ignore;
272 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
273 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
275 static unsigned char prio_map[6][3] = {
276 { 3, 2, 1 }, // -S -C -T
277 { 3, 1, 2 }, // -S -T -C
278 { 2, 3, 1 }, // -C -S -T
279 { 1, 3, 2 }, // -C -T -S
280 { 1, 2, 3 }, // -T -C -S
281 { 2, 1, 3 } // -T -S -C
283 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
284 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
289 case 30000: // cached DVB-T channel
290 case 1: // DVB-T frontend
291 tmp = prio_map[prio_order][2];
293 case 40000: // cached DVB-C channel
295 tmp = prio_map[prio_order][1];
298 tmp = prio_map[prio_order][0];
303 m_playable_service = *it;
310 m_playable_service = eServiceReference();
314 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
319 #include <lib/dvb/epgcache.h>
321 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
323 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
326 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
328 DECLARE_REF(eStaticServiceDVBPVRInformation);
329 eServiceReference m_ref;
330 eDVBMetaParser m_parser;
332 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
333 RESULT getName(const eServiceReference &ref, std::string &name);
334 int getLength(const eServiceReference &ref);
335 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
336 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
337 int getInfo(const eServiceReference &ref, int w);
338 std::string getInfoString(const eServiceReference &ref,int w);
341 DEFINE_REF(eStaticServiceDVBPVRInformation);
343 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
346 m_parser.parseFile(ref.path);
349 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
351 ASSERT(ref == m_ref);
352 if (m_parser.m_name.size())
353 name = m_parser.m_name;
357 size_t n = name.rfind('/');
358 if (n != std::string::npos)
359 name = name.substr(n + 1);
364 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
366 ASSERT(ref == m_ref);
371 stat(ref.path.c_str(), &s);
373 if (tstools.openFile(ref.path.c_str(), 1))
376 /* check if cached data is still valid */
377 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
378 return m_parser.m_length / 90000;
380 /* open again, this time with stream info */
381 if (tstools.openFile(ref.path.c_str()))
384 /* otherwise, re-calc length and update meta file */
386 if (tstools.calcLen(len))
389 m_parser.m_length = len;
390 m_parser.m_filesize = s.st_size;
391 m_parser.updateMeta(ref.path);
392 return m_parser.m_length / 90000;
395 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
399 case iServiceInformation::sDescription:
400 return iServiceInformation::resIsString;
401 case iServiceInformation::sServiceref:
402 return iServiceInformation::resIsString;
403 case iServiceInformation::sTimeCreate:
404 if (m_parser.m_time_create)
405 return m_parser.m_time_create;
407 return iServiceInformation::resNA;
409 return iServiceInformation::resNA;
413 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
417 case iServiceInformation::sDescription:
418 return m_parser.m_description;
419 case iServiceInformation::sServiceref:
420 return m_parser.m_ref.toString();
421 case iServiceInformation::sTags:
422 return m_parser.m_tags;
428 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
430 if (!ref.path.empty())
432 ePtr<eServiceEvent> event = new eServiceEvent;
433 std::string filename = ref.path;
434 filename.erase(filename.length()-2, 2);
436 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
446 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
448 DECLARE_REF(eDVBPVRServiceOfflineOperations);
449 eServiceReferenceDVB m_ref;
451 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
453 RESULT deleteFromDisk(int simulate);
454 RESULT getListOfFilenames(std::list<std::string> &);
457 DEFINE_REF(eDVBPVRServiceOfflineOperations);
459 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
463 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
469 std::list<std::string> res;
470 if (getListOfFilenames(res))
473 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
475 eDebug("FATAL !! can't get background file eraser");
477 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
479 eDebug("Removing %s...", i->c_str());
481 eraser->erase(i->c_str());
483 ::unlink(i->c_str());
490 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
493 res.push_back(m_ref.path);
495 // handling for old splitted recordings (enigma 1)
500 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
502 if (stat(buf, &s) < 0)
507 res.push_back(m_ref.path + ".meta");
508 res.push_back(m_ref.path + ".ap");
509 res.push_back(m_ref.path + ".cuts");
510 std::string tmp = m_ref.path;
511 tmp.erase(m_ref.path.length()-3);
512 res.push_back(tmp + ".eit");
516 DEFINE_REF(eServiceFactoryDVB)
518 eServiceFactoryDVB::eServiceFactoryDVB()
520 ePtr<eServiceCenter> sc;
522 eServiceCenter::getPrivInstance(sc);
525 std::list<std::string> extensions;
526 extensions.push_back("ts");
527 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
530 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
531 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
534 eServiceFactoryDVB::~eServiceFactoryDVB()
536 ePtr<eServiceCenter> sc;
538 eServiceCenter::getPrivInstance(sc);
540 sc->removeServiceFactory(eServiceFactoryDVB::id);
543 DEFINE_REF(eDVBServiceList);
545 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
549 eDVBServiceList::~eDVBServiceList()
553 RESULT eDVBServiceList::startQuery()
555 ePtr<iDVBChannelList> db;
556 ePtr<eDVBResourceManager> res;
559 if ((err = eDVBResourceManager::getInstance(res)) != 0)
561 eDebug("no resource manager");
564 if ((err = res->getChannelList(db)) != 0)
566 eDebug("no channel list");
570 ePtr<eDVBChannelQuery> q;
572 if (!m_parent.path.empty())
574 eDVBChannelQuery::compile(q, m_parent.path);
577 eDebug("compile query failed");
582 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
584 eDebug("startQuery failed");
591 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
593 eServiceReferenceDVB ref;
598 while (!m_query->getNextResult(ref))
602 list.sort(iListableServiceCompare(this));
607 // The first argument of this function is a format string to specify the order and
608 // the content of the returned list
609 // useable format options are
610 // R = Service Reference (as swig object .. this is very slow)
611 // S = Service Reference (as python string object .. same as ref.toString())
612 // C = Service Reference (as python string object .. same as ref.toCompareString())
613 // N = Service Name (as python string object)
614 // n = Short Service Name (short name brakets used) (as python string object)
615 // when exactly one return value per service is selected in the format string,
616 // then each value is directly a list entry
617 // when more than one value is returned per service, then the list is a list of
619 // unknown format string chars are returned as python None values !
620 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
623 std::list<eServiceReference> tmplist;
626 if (!format || !(retcount=strlen(format)))
627 format = "R"; // just return service reference swig object ...
629 if (!getContent(tmplist, sorted))
631 int services=tmplist.size();
632 ePtr<iStaticServiceInformation> sptr;
633 eServiceCenterPtr service_center;
635 if (strchr(format, 'N') || strchr(format, 'n'))
636 eServiceCenter::getPrivInstance(service_center);
638 ret = PyList_New(services);
639 std::list<eServiceReference>::iterator it(tmplist.begin());
641 for (int cnt=0; cnt < services; ++cnt)
643 eServiceReference &ref=*it++;
644 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
645 for (int i=0; i < retcount; ++i)
650 case 'R': // service reference (swig)object
651 tmp = NEW_eServiceReference(ref);
653 case 'C': // service reference compare string
654 tmp = PyString_FromString(ref.toCompareString().c_str());
656 case 'S': // service reference string
657 tmp = PyString_FromString(ref.toString().c_str());
659 case 'N': // service name
662 service_center->info(ref, sptr);
666 sptr->getName(ref, name);
668 // filter short name brakets
670 while((pos = name.find("\xc2\x86")) != std::string::npos)
672 while((pos = name.find("\xc2\x87")) != std::string::npos)
676 tmp = PyString_FromString(name.c_str());
680 tmp = PyString_FromString("<n/a>");
682 case 'n': // short service name
685 service_center->info(ref, sptr);
689 sptr->getName(ref, name);
690 name = buildShortName(name);
692 tmp = PyString_FromString(name.c_str());
696 tmp = PyString_FromString("<n/a>");
709 PyTuple_SET_ITEM(tuple, i, tmp);
711 PyList_SET_ITEM(ret, cnt, tmp);
715 PyList_SET_ITEM(ret, cnt, tuple);
718 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
721 RESULT eDVBServiceList::getNext(eServiceReference &ref)
726 return m_query->getNextResult((eServiceReferenceDVB&)ref);
729 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
731 if (m_parent.flags & eServiceReference::canDescent) // bouquet
733 ePtr<iDVBChannelList> db;
734 ePtr<eDVBResourceManager> resm;
736 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
739 if (db->getBouquet(m_parent, m_bouquet) != 0)
750 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
754 return m_bouquet->addService(ref, before);
757 RESULT eDVBServiceList::removeService(eServiceReference &ref)
761 return m_bouquet->removeService(ref);
764 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
768 return m_bouquet->moveService(ref, pos);
771 RESULT eDVBServiceList::flushChanges()
775 return m_bouquet->flushChanges();
778 RESULT eDVBServiceList::setListName(const std::string &name)
782 return m_bouquet->setListName(name);
785 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
787 ePtr<eDVBService> service;
788 int r = lookupService(service, ref);
791 // check resources...
792 ptr = new eDVBServicePlay(ref, service);
796 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
798 if (ref.path.empty())
800 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
809 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
811 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
812 if (list->startQuery())
822 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
824 /* is a listable service? */
825 if (ref.flags & eServiceReference::canDescent) // bouquet
827 if ( !ref.name.empty() ) // satellites or providers list
828 ptr = m_StaticServiceDVBInfo;
829 else // a dvb bouquet
830 ptr = m_StaticServiceDVBBouquetInfo;
832 else if (!ref.path.empty()) /* do we have a PVR service? */
833 ptr = new eStaticServiceDVBPVRInformation(ref);
834 else // normal dvb service
836 ePtr<eDVBService> service;
837 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
838 ptr = m_StaticServiceDVBInfo;
840 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
846 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
848 if (ref.path.empty())
854 ptr = new eDVBPVRServiceOfflineOperations(ref);
859 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
861 // TODO: handle the listing itself
862 // if (ref.... == -1) .. return "... bouquets ...";
863 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
865 ePtr<iDVBChannelList> db;
866 ePtr<eDVBResourceManager> res;
869 if ((err = eDVBResourceManager::getInstance(res)) != 0)
871 eDebug("no resource manager");
874 if ((err = res->getChannelList(db)) != 0)
876 eDebug("no channel list");
880 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
881 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
883 eDebug("getService failed!");
890 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
891 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
894 m_is_pvr = !m_reference.path.empty();
896 m_timeshift_enabled = m_timeshift_active = 0;
899 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
900 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
901 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
903 m_cuesheet_changed = 0;
904 m_cutlist_enabled = 1;
906 m_subtitle_widget = 0;
910 m_subtitle_sync_timer = eTimer::create(eApp);
912 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
915 eDVBServicePlay::~eDVBServicePlay()
917 delete m_subtitle_widget;
920 void eDVBServicePlay::gotNewEvent()
924 ePtr<eServiceEvent> m_event_now, m_event_next;
925 getEvent(m_event_now, 0);
926 getEvent(m_event_next, 1);
929 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
931 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
933 m_event((iPlayableService*)this, evUpdatedEventInfo);
936 void eDVBServicePlay::serviceEvent(int event)
938 m_tune_state = event;
942 case eDVBServicePMTHandler::eventTuned:
944 ePtr<iDVBDemux> m_demux;
945 if (!m_service_handler.getDataDemux(m_demux))
947 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
948 int sid = ref.getParentServiceID().get();
950 sid = ref.getServiceID().get();
951 if ( ref.getParentTransportStreamID().get() &&
952 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
953 m_event_handler.startOther(m_demux, sid);
955 m_event_handler.start(m_demux, sid);
957 m_event((iPlayableService*)this, evTunedIn);
960 case eDVBServicePMTHandler::eventNoResources:
961 case eDVBServicePMTHandler::eventNoPAT:
962 case eDVBServicePMTHandler::eventNoPATEntry:
963 case eDVBServicePMTHandler::eventNoPMT:
964 case eDVBServicePMTHandler::eventTuneFailed:
965 case eDVBServicePMTHandler::eventMisconfiguration:
967 eDebug("DVB service failed to tune - error %d", event);
968 m_event((iPlayableService*)this, evTuneFailed);
971 case eDVBServicePMTHandler::eventNewProgramInfo:
973 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
974 if (m_timeshift_enabled)
975 updateTimeshiftPids();
976 if (!m_timeshift_active)
978 if (m_first_program_info && m_is_pvr)
980 m_first_program_info = 0;
983 m_event((iPlayableService*)this, evUpdatedInfo);
986 case eDVBServicePMTHandler::eventEOF:
987 m_event((iPlayableService*)this, evEOF);
989 case eDVBServicePMTHandler::eventSOF:
990 m_event((iPlayableService*)this, evSOF);
995 void eDVBServicePlay::serviceEventTimeshift(int event)
999 case eDVBServicePMTHandler::eventNewProgramInfo:
1000 if (m_timeshift_active)
1003 case eDVBServicePMTHandler::eventSOF:
1004 m_event((iPlayableService*)this, evSOF);
1006 case eDVBServicePMTHandler::eventEOF:
1007 if ((!m_is_paused) && (m_skipmode >= 0))
1013 RESULT eDVBServicePlay::start()
1016 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1017 two (one for decoding, one for data source), as we must be prepared
1018 to start recording from the data demux. */
1020 m_cue = new eCueSheet();
1022 m_event(this, evStart);
1024 m_first_program_info = 1;
1025 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1026 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1028 /* inject EIT if there is a stored one */
1031 std::string filename = service.path;
1032 filename.erase(filename.length()-2, 2);
1034 ePtr<eServiceEvent> event = new eServiceEvent;
1035 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1037 ePtr<eServiceEvent> empty;
1038 m_event_handler.inject(event, 0);
1039 m_event_handler.inject(empty, 1);
1046 m_event(this, evStart);
1051 RESULT eDVBServicePlay::stop()
1053 /* add bookmark for last play position */
1056 pts_t play_position, length;
1057 if (!getPlayPosition(play_position))
1059 /* remove last position */
1060 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1062 if (i->what == 3) /* current play position */
1064 m_cue_entries.erase(i);
1065 i = m_cue_entries.begin();
1071 if (getLength(length))
1076 int perc = play_position * 100LL / length;
1078 /* only store last play position when between 1% and 99% */
1079 if ((1 < perc) && (perc < 99))
1080 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1082 m_cuesheet_changed = 1;
1086 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1088 m_service_handler_timeshift.free();
1089 m_service_handler.free();
1091 if (m_is_pvr && m_cuesheet_changed)
1094 /* save cuesheet only when main file is accessible. */
1095 if (!::stat(m_reference.path.c_str(), &s))
1098 m_event((iPlayableService*)this, evStopped);
1102 RESULT eDVBServicePlay::setTarget(int target)
1104 m_is_primary = !target;
1108 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1110 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1114 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1116 /* note: we check for timeshift to be enabled,
1117 not neccessary active. if you pause when timeshift
1118 is not active, you should activate it when unpausing */
1119 if ((!m_is_pvr) && (!m_timeshift_enabled))
1129 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1132 return m_decoder->setSlowMotion(ratio);
1137 RESULT eDVBServicePlay::setFastForward(int ratio)
1139 int skipmode, ffratio;
1145 } else if (ratio > 0)
1153 } else // if (ratio < 0)
1159 if (m_skipmode != skipmode)
1161 eDebug("setting cue skipmode to %d", skipmode);
1163 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1166 m_skipmode = skipmode;
1171 return m_decoder->setFastForward(ffratio);
1174 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1176 if (m_is_pvr || m_timeshift_enabled)
1186 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1187 RESULT eDVBServicePlay::getLength(pts_t &len)
1189 ePtr<iDVBPVRChannel> pvr_channel;
1191 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1194 return pvr_channel->getLength(len);
1197 RESULT eDVBServicePlay::pause()
1199 if (!m_is_paused && m_decoder)
1202 return m_decoder->freeze(0);
1207 RESULT eDVBServicePlay::unpause()
1209 if (m_is_paused && m_decoder)
1212 return m_decoder->unfreeze();
1217 RESULT eDVBServicePlay::seekTo(pts_t to)
1219 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1221 if (!m_decode_demux)
1224 ePtr<iDVBPVRChannel> pvr_channel;
1226 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1232 m_cue->seekTo(0, to);
1233 m_dvb_subtitle_pages.clear();
1234 m_subtitle_pages.clear();
1239 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1241 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1243 if (!m_decode_demux)
1246 ePtr<iDVBPVRChannel> pvr_channel;
1248 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1253 /* HACK until we have skip-AP api */
1254 if ((to > 0) && (to < 100))
1262 m_cue->seekTo(mode, to);
1263 m_dvb_subtitle_pages.clear();
1264 m_subtitle_pages.clear();
1268 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1270 ePtr<iDVBPVRChannel> pvr_channel;
1272 if (!m_decode_demux)
1275 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1280 /* if there is a decoder, use audio or video PTS */
1283 r = m_decoder->getPTS(0, pos);
1289 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1292 RESULT eDVBServicePlay::setTrickmode(int trick)
1295 m_decoder->setTrickmode(trick);
1299 RESULT eDVBServicePlay::isCurrentlySeekable()
1301 return m_is_pvr || m_timeshift_active;
1304 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1310 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1316 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1322 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1328 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1334 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1337 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1338 (m_timeshift_enabled || !m_is_pvr))
1340 if (!m_timeshift_enabled)
1342 /* query config path */
1344 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1345 eDebug("could not query ts path from config");
1349 /* we need enough diskspace */
1351 if (statfs(tspath.c_str(), &fs) < 0)
1353 eDebug("statfs failed!");
1357 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1359 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1369 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1380 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1386 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1392 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1398 RESULT eDVBServicePlay::getName(std::string &name)
1402 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1403 return i->getName(m_reference, name);
1407 m_dvb_service->getName(m_reference, name);
1411 else if (!m_reference.name.empty())
1412 eStaticServiceDVBInformation().getName(m_reference, name);
1414 name = "DVB service";
1418 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1420 return m_event_handler.getEvent(evt, nownext);
1423 int eDVBServicePlay::getInfo(int w)
1425 eDVBServicePMTHandler::program program;
1428 return resIsPyObject;
1430 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1432 int no_program_info = 0;
1434 if (h.getProgramInfo(program))
1435 no_program_info = 1;
1441 return m_decoder->getVideoHeight();
1445 return m_decoder->getVideoWidth();
1449 return m_decoder->getVideoFrameRate();
1453 return m_decoder->getVideoProgressive();
1459 aspect = m_decoder->getVideoAspect();
1460 if (no_program_info)
1462 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1464 ePtr<eServiceEvent> evt;
1465 if (!m_event_handler.getEvent(evt, 0))
1467 ePtr<eComponentData> data;
1468 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1470 if ( data->getStreamContent() == 1 )
1472 switch(data->getComponentType())
1475 case 1: // 4:3 SD PAL
1477 case 3: // 16:9 SD PAL
1478 case 4: // > 16:9 PAL
1479 case 5: // 4:3 SD NTSC
1481 case 7: // 16:9 SD NTSC
1482 case 8: // > 16:9 NTSC
1485 case 9: // 4:3 HD PAL
1487 case 0xB: // 16:9 HD PAL
1488 case 0xC: // > 16:9 HD PAL
1489 case 0xD: // 4:3 HD NTSC
1491 case 0xF: // 16:9 HD NTSC
1492 case 0x10: // > 16:9 HD PAL
1493 return data->getComponentType();
1503 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1504 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1505 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1506 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1507 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1508 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1509 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1510 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1511 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1512 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1513 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1514 case sProvider: if (!m_dvb_service) return -1; return -2;
1515 case sServiceref: return resIsString;
1516 case sDVBState: return m_tune_state;
1523 std::string eDVBServicePlay::getInfoString(int w)
1528 if (!m_dvb_service) return "";
1529 return m_dvb_service->m_provider_name;
1531 return m_reference.toString();
1535 return iServiceInformation::getInfoString(w);
1538 PyObject *eDVBServicePlay::getInfoObject(int w)
1543 return m_service_handler.getCaIds();
1544 case sTransponderData:
1545 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1549 return iServiceInformation::getInfoObject(w);
1552 int eDVBServicePlay::getNumberOfTracks()
1554 eDVBServicePMTHandler::program program;
1555 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1556 if (h.getProgramInfo(program))
1558 return program.audioStreams.size();
1561 int eDVBServicePlay::getCurrentTrack()
1563 eDVBServicePMTHandler::program program;
1564 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1565 if (h.getProgramInfo(program))
1568 int max = program.audioStreams.size();
1571 for (i = 0; i < max; ++i)
1572 if (program.audioStreams[i].pid == m_current_audio_pid)
1578 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1580 int ret = selectAudioStream(i);
1582 if (m_decoder->start())
1588 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1590 eDVBServicePMTHandler::program program;
1591 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1593 if (h.getProgramInfo(program))
1596 if (i >= program.audioStreams.size())
1599 info.m_pid = program.audioStreams[i].pid;
1601 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1602 info.m_description = "MPEG";
1603 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1604 info.m_description = "AC3";
1605 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1606 info.m_description = "AAC";
1607 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1608 info.m_description = "AAC-HE";
1609 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1610 info.m_description = "DTS";
1612 info.m_description = "???";
1614 if (program.audioStreams[i].component_tag != -1)
1616 ePtr<eServiceEvent> evt;
1617 if (!m_event_handler.getEvent(evt, 0))
1619 ePtr<eComponentData> data;
1620 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1621 info.m_language = data->getText();
1625 if (info.m_language.empty())
1626 info.m_language = program.audioStreams[i].language_code;
1631 int eDVBServicePlay::selectAudioStream(int i)
1633 eDVBServicePMTHandler::program program;
1634 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1636 if (h.getProgramInfo(program))
1639 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1647 stream = program.defaultAudioStream;
1649 int apid = -1, apidtype = -1;
1651 if (((unsigned int)stream) < program.audioStreams.size())
1653 apid = program.audioStreams[stream].pid;
1654 apidtype = program.audioStreams[stream].type;
1657 m_current_audio_pid = apid;
1659 if (m_decoder->setAudioPID(apid, apidtype))
1661 eDebug("set audio pid failed");
1665 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1666 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1669 ePtr<iDVBDemux> data_demux;
1670 if (!h.getDataDemux(data_demux))
1672 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1673 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1677 /* if we decided that we need one, update the pid */
1679 m_rds_decoder->start(apid);
1681 /* store new pid as default only when:
1682 a.) we have an entry in the service db for the current service,
1683 b.) we are not playing back something,
1684 c.) we are not selecting the default entry. (we wouldn't change
1685 anything in the best case, or destroy the default setting in
1686 case the real default is not yet available.)
1688 if (m_dvb_service && !m_is_pvr && ((i != -1)
1689 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1691 if (apidtype == eDVBAudio::aMPEG)
1693 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1694 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1698 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1699 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1703 h.resetCachedProgram();
1708 int eDVBServicePlay::getCurrentChannel()
1710 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1713 RESULT eDVBServicePlay::selectChannel(int i)
1715 if (i < LEFT || i > RIGHT || i == STEREO)
1718 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1720 m_decoder->setAudioChannel(i);
1724 std::string eDVBServicePlay::getText(int x)
1730 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1732 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1737 void eDVBServicePlay::rdsDecoderEvent(int what)
1741 case eDVBRdsDecoder::RadioTextChanged:
1742 m_event((iPlayableService*)this, evUpdatedRadioText);
1744 case eDVBRdsDecoder::RtpTextChanged:
1745 m_event((iPlayableService*)this, evUpdatedRtpText);
1747 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1748 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1750 case eDVBRdsDecoder::RecvRassSlidePic:
1751 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1756 void eDVBServicePlay::showRassSlidePicture()
1762 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1763 if (rass_slide_pic.length())
1764 m_decoder->showSinglePic(rass_slide_pic.c_str());
1766 eDebug("empty filename for rass slide picture received!!");
1769 eDebug("no MPEG Decoder to show iframes avail");
1772 eDebug("showRassSlidePicture called.. but not decoder");
1775 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1781 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1782 if (rass_interactive_pic.length())
1783 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1785 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1788 eDebug("no MPEG Decoder to show iframes avail");
1791 eDebug("showRassInteractivePic called.. but not decoder");
1794 ePyObject eDVBServicePlay::getRassInteractiveMask()
1797 return m_rds_decoder->getRassPictureMask();
1801 int eDVBServiceBase::getFrontendInfo(int w)
1803 eUsePtr<iDVBChannel> channel;
1804 if(m_service_handler.getChannel(channel))
1806 ePtr<iDVBFrontend> fe;
1807 if(channel->getFrontend(fe))
1809 return fe->readFrontendData(w);
1812 PyObject *eDVBServiceBase::getFrontendData()
1814 ePyObject ret = PyDict_New();
1817 eUsePtr<iDVBChannel> channel;
1818 if(!m_service_handler.getChannel(channel))
1820 ePtr<iDVBFrontend> fe;
1821 if(!channel->getFrontend(fe))
1822 fe->getFrontendData(ret);
1830 PyObject *eDVBServiceBase::getFrontendStatus()
1832 ePyObject ret = PyDict_New();
1835 eUsePtr<iDVBChannel> channel;
1836 if(!m_service_handler.getChannel(channel))
1838 ePtr<iDVBFrontend> fe;
1839 if(!channel->getFrontend(fe))
1840 fe->getFrontendStatus(ret);
1848 PyObject *eDVBServiceBase::getTransponderData(bool original)
1850 ePyObject ret = PyDict_New();
1853 eUsePtr<iDVBChannel> channel;
1854 if(!m_service_handler.getChannel(channel))
1856 ePtr<iDVBFrontend> fe;
1857 if(!channel->getFrontend(fe))
1858 fe->getTransponderData(ret, original);
1866 PyObject *eDVBServiceBase::getAll(bool original)
1868 ePyObject ret = getTransponderData(original);
1871 eUsePtr<iDVBChannel> channel;
1872 if(!m_service_handler.getChannel(channel))
1874 ePtr<iDVBFrontend> fe;
1875 if(!channel->getFrontend(fe))
1877 fe->getFrontendData(ret);
1878 fe->getFrontendStatus(ret);
1885 int eDVBServicePlay::getNumberOfSubservices()
1887 ePtr<eServiceEvent> evt;
1888 if (!m_event_handler.getEvent(evt, 0))
1889 return evt->getNumOfLinkageServices();
1893 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1895 ePtr<eServiceEvent> evt;
1896 if (!m_event_handler.getEvent(evt, 0))
1898 if (!evt->getLinkageService(sub, m_reference, n))
1901 sub.type=eServiceReference::idInvalid;
1905 RESULT eDVBServicePlay::startTimeshift()
1907 ePtr<iDVBDemux> demux;
1909 eDebug("Start timeshift!");
1911 if (m_timeshift_enabled)
1914 /* start recording with the data demux. */
1915 if (m_service_handler.getDataDemux(demux))
1918 demux->createTSRecorder(m_record);
1923 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1924 eDebug("could not query ts path");
1927 tspath.append("/timeshift.XXXXXX");
1929 templ = new char[tspath.length() + 1];
1930 strcpy(templ, tspath.c_str());
1932 m_timeshift_fd = mkstemp(templ);
1933 m_timeshift_file = std::string(templ);
1935 eDebug("recording to %s", templ);
1939 if (m_timeshift_fd < 0)
1945 m_record->setTargetFD(m_timeshift_fd);
1947 m_timeshift_enabled = 1;
1949 updateTimeshiftPids();
1955 RESULT eDVBServicePlay::stopTimeshift()
1957 if (!m_timeshift_enabled)
1962 m_timeshift_enabled = 0;
1967 close(m_timeshift_fd);
1968 eDebug("remove timeshift file");
1969 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1974 int eDVBServicePlay::isTimeshiftActive()
1976 return m_timeshift_enabled && m_timeshift_active;
1979 RESULT eDVBServicePlay::activateTimeshift()
1981 if (!m_timeshift_enabled)
1984 if (!m_timeshift_active)
1986 switchToTimeshift();
1993 PyObject *eDVBServicePlay::getCutList()
1995 ePyObject list = PyList_New(0);
1997 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1999 ePyObject tuple = PyTuple_New(2);
2000 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2001 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2002 PyList_Append(list, tuple);
2009 void eDVBServicePlay::setCutList(ePyObject list)
2011 if (!PyList_Check(list))
2013 int size = PyList_Size(list);
2016 m_cue_entries.clear();
2018 for (i=0; i<size; ++i)
2020 ePyObject tuple = PyList_GET_ITEM(list, i);
2021 if (!PyTuple_Check(tuple))
2023 eDebug("non-tuple in cutlist");
2026 if (PyTuple_Size(tuple) != 2)
2028 eDebug("cutlist entries need to be a 2-tuple");
2031 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2032 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2034 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2037 pts_t pts = PyLong_AsLongLong(ppts);
2038 int type = PyInt_AsLong(ptype);
2039 m_cue_entries.insert(cueEntry(pts, type));
2040 eDebug("adding %08llx, %d", pts, type);
2042 m_cuesheet_changed = 1;
2044 cutlistToCuesheet();
2045 m_event((iPlayableService*)this, evCuesheetChanged);
2048 void eDVBServicePlay::setCutListEnable(int enable)
2050 m_cutlist_enabled = enable;
2051 cutlistToCuesheet();
2054 void eDVBServicePlay::updateTimeshiftPids()
2059 eDVBServicePMTHandler::program program;
2060 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2062 if (h.getProgramInfo(program))
2066 std::set<int> pids_to_record;
2067 pids_to_record.insert(0); // PAT
2068 if (program.pmtPid != -1)
2069 pids_to_record.insert(program.pmtPid); // PMT
2071 if (program.textPid != -1)
2072 pids_to_record.insert(program.textPid); // Videotext
2074 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2075 i(program.videoStreams.begin());
2076 i != program.videoStreams.end(); ++i)
2077 pids_to_record.insert(i->pid);
2079 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2080 i(program.audioStreams.begin());
2081 i != program.audioStreams.end(); ++i)
2082 pids_to_record.insert(i->pid);
2084 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2085 i(program.subtitleStreams.begin());
2086 i != program.subtitleStreams.end(); ++i)
2087 pids_to_record.insert(i->pid);
2089 std::set<int> new_pids, obsolete_pids;
2091 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2092 m_pids_active.begin(), m_pids_active.end(),
2093 std::inserter(new_pids, new_pids.begin()));
2095 std::set_difference(
2096 m_pids_active.begin(), m_pids_active.end(),
2097 pids_to_record.begin(), pids_to_record.end(),
2098 std::inserter(new_pids, new_pids.begin())
2101 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2102 m_record->addPID(*i);
2104 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2105 m_record->removePID(*i);
2109 void eDVBServicePlay::switchToLive()
2111 if (!m_timeshift_active)
2117 m_teletext_parser = 0;
2119 m_subtitle_parser = 0;
2120 m_new_dvb_subtitle_page_connection = 0;
2121 m_new_subtitle_page_connection = 0;
2122 m_rds_decoder_event_connection = 0;
2123 m_video_event_connection = 0;
2125 /* free the timeshift service handler, we need the resources */
2126 m_service_handler_timeshift.free();
2127 m_timeshift_active = 0;
2129 m_event((iPlayableService*)this, evSeekableStatusChanged);
2134 void eDVBServicePlay::switchToTimeshift()
2136 if (m_timeshift_active)
2141 m_teletext_parser = 0;
2143 m_subtitle_parser = 0;
2144 m_new_subtitle_page_connection = 0;
2145 m_new_dvb_subtitle_page_connection = 0;
2146 m_rds_decoder_event_connection = 0;
2147 m_video_event_connection = 0;
2149 m_timeshift_active = 1;
2151 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2152 r.path = m_timeshift_file;
2154 m_cue = new eCueSheet();
2155 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2157 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2159 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2161 m_event((iPlayableService*)this, evSeekableStatusChanged);
2164 void eDVBServicePlay::updateDecoder()
2166 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2168 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2170 eDVBServicePMTHandler::program program;
2171 if (h.getProgramInfo(program))
2172 eDebug("getting program info failed.");
2175 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2176 if (!program.videoStreams.empty())
2178 eDebugNoNewLine(" (");
2179 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2180 i(program.videoStreams.begin());
2181 i != program.videoStreams.end(); ++i)
2188 if (i != program.videoStreams.begin())
2189 eDebugNoNewLine(", ");
2190 eDebugNoNewLine("%04x", i->pid);
2192 eDebugNoNewLine(")");
2194 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2195 if (!program.audioStreams.empty())
2197 eDebugNoNewLine(" (");
2198 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2199 i(program.audioStreams.begin());
2200 i != program.audioStreams.end(); ++i)
2202 if (i != program.audioStreams.begin())
2203 eDebugNoNewLine(", ");
2204 eDebugNoNewLine("%04x", i->pid);
2206 eDebugNoNewLine(")");
2208 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2209 pcrpid = program.pcrPid;
2210 eDebug(", and the text pid is %04x", program.textPid);
2211 tpid = program.textPid;
2216 h.getDecodeDemux(m_decode_demux);
2219 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2221 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2222 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2223 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2224 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2225 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2228 m_teletext_parser = 0;
2229 m_subtitle_parser = 0;
2233 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2240 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2241 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2242 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2244 else // subservice or recording
2246 eServiceReferenceDVB ref;
2247 m_service_handler.getServiceReference(ref);
2248 eServiceReferenceDVB parent = ref.getParentServiceReference();
2253 ePtr<eDVBResourceManager> res_mgr;
2254 if (!eDVBResourceManager::getInstance(res_mgr))
2256 ePtr<iDVBChannelList> db;
2257 if (!res_mgr->getChannelList(db))
2259 ePtr<eDVBService> origService;
2260 if (!db->getService(parent, origService))
2262 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2263 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2269 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2270 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2272 m_decoder->setVideoPID(vpid, vpidtype);
2273 selectAudioStream();
2275 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2276 m_decoder->setSyncPCR(pcrpid);
2278 m_decoder->setSyncPCR(-1);
2280 m_decoder->setTextPID(tpid);
2282 m_teletext_parser->start(program.textPid);
2285 m_decoder->setTrickmode(1);
2288 m_decoder->preroll();
2292 if (vpid > 0 && vpid < 0x2000)
2296 std::string radio_pic;
2297 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2298 m_decoder->setRadioPic(radio_pic);
2301 m_decoder->setAudioChannel(achannel);
2303 /* don't worry about non-existing services, nor pvr services */
2304 if (m_dvb_service && !m_is_pvr)
2306 /* (audio pid will be set in selectAudioTrack */
2307 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2308 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2309 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2310 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2313 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2316 void eDVBServicePlay::loadCuesheet()
2318 std::string filename = m_reference.path + ".cuts";
2320 m_cue_entries.clear();
2322 FILE *f = fopen(filename.c_str(), "rb");
2326 eDebug("loading cuts..");
2329 unsigned long long where;
2332 if (!fread(&where, sizeof(where), 1, f))
2334 if (!fread(&what, sizeof(what), 1, f))
2337 #if BYTE_ORDER == LITTLE_ENDIAN
2338 where = bswap_64(where);
2345 m_cue_entries.insert(cueEntry(where, what));
2348 eDebug("%d entries", m_cue_entries.size());
2350 eDebug("cutfile not found!");
2352 m_cuesheet_changed = 0;
2353 cutlistToCuesheet();
2354 m_event((iPlayableService*)this, evCuesheetChanged);
2357 void eDVBServicePlay::saveCuesheet()
2359 std::string filename = m_reference.path + ".cuts";
2361 FILE *f = fopen(filename.c_str(), "wb");
2365 unsigned long long where;
2368 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2370 #if BYTE_ORDER == BIG_ENDIAN
2373 where = bswap_64(i->where);
2375 what = htonl(i->what);
2376 fwrite(&where, sizeof(where), 1, f);
2377 fwrite(&what, sizeof(what), 1, f);
2383 m_cuesheet_changed = 0;
2386 void eDVBServicePlay::cutlistToCuesheet()
2390 eDebug("no cue sheet");
2395 if (!m_cutlist_enabled)
2397 m_cue->commitSpans();
2398 eDebug("cutlists were disabled");
2402 pts_t in = 0, out = 0, length = 0;
2406 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2410 if (i == m_cue_entries.end())
2413 if (i->what == 0) /* in */
2417 } else if (i->what == 1) /* out */
2419 else /* mark (2) or last play position (3) */
2436 m_cue->addSourceSpan(in, out);
2440 if (i == m_cue_entries.end())
2443 m_cue->commitSpans();
2446 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2448 if (m_subtitle_widget)
2449 disableSubtitles(parent);
2452 int tuplesize = PyTuple_Size(tuple);
2455 if (!PyTuple_Check(tuple))
2461 entry = PyTuple_GET_ITEM(tuple, 0);
2463 if (!PyInt_Check(entry))
2466 type = PyInt_AsLong(entry);
2468 if (type == 1) // teletext subtitles
2470 int page, magazine, pid;
2474 if (!m_teletext_parser)
2476 eDebug("enable teletext subtitles.. no parser !!!");
2480 entry = PyTuple_GET_ITEM(tuple, 1);
2481 if (!PyInt_Check(entry))
2483 pid = PyInt_AsLong(entry);
2485 entry = PyTuple_GET_ITEM(tuple, 2);
2486 if (!PyInt_Check(entry))
2488 page = PyInt_AsLong(entry);
2490 entry = PyTuple_GET_ITEM(tuple, 3);
2491 if (!PyInt_Check(entry))
2493 magazine = PyInt_AsLong(entry);
2495 m_subtitle_widget = new eSubtitleWidget(parent);
2496 m_subtitle_widget->resize(parent->size()); /* full size */
2497 m_teletext_parser->setPageAndMagazine(page, magazine);
2499 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2503 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2504 if (!m_subtitle_parser)
2506 eDebug("enable dvb subtitles.. no parser !!!");
2512 entry = PyTuple_GET_ITEM(tuple, 1);
2513 if (!PyInt_Check(entry))
2515 pid = PyInt_AsLong(entry);
2517 entry = PyTuple_GET_ITEM(tuple, 2);
2518 if (!PyInt_Check(entry))
2520 composition_page_id = PyInt_AsLong(entry);
2522 entry = PyTuple_GET_ITEM(tuple, 3);
2523 if (!PyInt_Check(entry))
2525 ancillary_page_id = PyInt_AsLong(entry);
2527 m_subtitle_widget = new eSubtitleWidget(parent);
2528 m_subtitle_widget->resize(parent->size()); /* full size */
2529 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2531 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2537 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2538 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2539 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2543 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2545 delete m_subtitle_widget;
2546 m_subtitle_widget = 0;
2547 if (m_subtitle_parser)
2549 m_subtitle_parser->stop();
2550 m_dvb_subtitle_pages.clear();
2552 if (m_teletext_parser)
2554 m_teletext_parser->setPageAndMagazine(-1, -1);
2555 m_subtitle_pages.clear();
2558 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2562 PyObject *eDVBServicePlay::getCachedSubtitle()
2566 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2569 unsigned int data = (unsigned int)tmp;
2570 int pid = (data&0xFFFF0000)>>16;
2571 ePyObject tuple = PyTuple_New(4);
2572 eDVBServicePMTHandler::program program;
2573 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2574 if (!h.getProgramInfo(program))
2576 if (program.textPid==pid) // teletext
2577 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2579 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2580 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2581 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2582 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2590 PyObject *eDVBServicePlay::getSubtitleList()
2592 if (!m_teletext_parser)
2595 ePyObject l = PyList_New(0);
2596 std::set<int> added_ttx_pages;
2598 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2599 m_teletext_parser->m_found_subtitle_pages;
2601 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2602 eDVBServicePMTHandler::program program;
2603 if (h.getProgramInfo(program))
2604 eDebug("getting program info failed.");
2607 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2608 it != program.subtitleStreams.end(); ++it)
2610 switch(it->subtitling_type)
2612 case 0x01: // ebu teletext subtitles
2614 int page_number = it->teletext_page_number & 0xFF;
2615 int magazine_number = it->teletext_magazine_number & 7;
2616 int hash = magazine_number << 8 | page_number;
2617 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2619 ePyObject tuple = PyTuple_New(5);
2620 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2621 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2622 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2623 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2624 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2625 PyList_Append(l, tuple);
2627 added_ttx_pages.insert(hash);
2632 case 0x20 ... 0x23: // dvb subtitles
2634 ePyObject tuple = PyTuple_New(5);
2635 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2636 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2637 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2638 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2639 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2640 PyList_Insert(l, 0, tuple);
2648 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2649 it != subs.end(); ++it)
2651 int page_number = it->teletext_page_number & 0xFF;
2652 int magazine_number = it->teletext_magazine_number & 7;
2653 int hash = magazine_number << 8 | page_number;
2654 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2656 ePyObject tuple = PyTuple_New(5);
2657 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2658 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2659 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2660 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2661 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2662 PyList_Append(l, tuple);
2670 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2672 if (m_subtitle_widget)
2676 m_decoder->getPTS(0, pos);
2677 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2678 m_subtitle_pages.push_back(page);
2679 checkSubtitleTiming();
2683 void eDVBServicePlay::checkSubtitleTiming()
2685 eDebug("checkSubtitleTiming");
2686 if (!m_subtitle_widget)
2690 enum { TELETEXT, DVB } type;
2691 eDVBTeletextSubtitlePage page;
2692 eDVBSubtitlePage dvb_page;
2694 if (!m_subtitle_pages.empty())
2696 page = m_subtitle_pages.front();
2698 show_time = page.m_pts;
2700 else if (!m_dvb_subtitle_pages.empty())
2702 dvb_page = m_dvb_subtitle_pages.front();
2704 show_time = dvb_page.m_show_time;
2712 m_decoder->getPTS(0, pos);
2714 eDebug("%lld %lld", pos, show_time);
2715 int diff = show_time - pos;
2718 eDebug("[late (%d ms)]", -diff / 90);
2721 // if (diff > 900000)
2723 // eDebug("[invalid]");
2729 if (type == TELETEXT)
2731 eDebug("display teletext subtitle page %lld", show_time);
2732 m_subtitle_widget->setPage(page);
2733 m_subtitle_pages.pop_front();
2737 eDebug("display dvb subtitle Page %lld", show_time);
2738 m_subtitle_widget->setPage(dvb_page);
2739 m_dvb_subtitle_pages.pop_front();
2743 eDebug("start subtitle delay %d", diff / 90);
2744 m_subtitle_sync_timer->start(diff / 90, 1);
2750 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2752 if (m_subtitle_widget)
2756 m_decoder->getPTS(0, pos);
2757 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2758 m_dvb_subtitle_pages.push_back(p);
2759 checkSubtitleTiming();
2763 int eDVBServicePlay::getAC3Delay()
2766 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2768 return m_decoder->getAC3Delay();
2773 int eDVBServicePlay::getPCMDelay()
2776 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2778 return m_decoder->getPCMDelay();
2783 void eDVBServicePlay::setAC3Delay(int delay)
2786 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2788 m_decoder->setAC3Delay(delay);
2791 void eDVBServicePlay::setPCMDelay(int delay)
2794 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2796 m_decoder->setPCMDelay(delay);
2799 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2801 switch(event.type) {
2802 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2803 m_event((iPlayableService*)this, evVideoSizeChanged);
2805 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2806 m_event((iPlayableService*)this, evVideoFramerateChanged);
2808 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2809 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2816 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2822 PyObject *eDVBServicePlay::getStreamingData()
2824 eDVBServicePMTHandler::program program;
2825 if (m_service_handler.getProgramInfo(program))
2830 ePyObject r = program.createPythonObject();
2831 ePtr<iDVBDemux> demux;
2832 if (!m_service_handler.getDataDemux(demux))
2835 if (!demux->getCADemuxID(demux_id))
2836 PutToDict(r, "demux", demux_id);
2843 DEFINE_REF(eDVBServicePlay)
2845 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2849 case iServiceInformation::sTransponderData:
2850 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2854 return iStaticServiceInformation::getInfoObject(ref, w);
2857 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");