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 extensions.push_back("trp");
528 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
531 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
532 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
535 eServiceFactoryDVB::~eServiceFactoryDVB()
537 ePtr<eServiceCenter> sc;
539 eServiceCenter::getPrivInstance(sc);
541 sc->removeServiceFactory(eServiceFactoryDVB::id);
544 DEFINE_REF(eDVBServiceList);
546 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
550 eDVBServiceList::~eDVBServiceList()
554 RESULT eDVBServiceList::startQuery()
556 ePtr<iDVBChannelList> db;
557 ePtr<eDVBResourceManager> res;
560 if ((err = eDVBResourceManager::getInstance(res)) != 0)
562 eDebug("no resource manager");
565 if ((err = res->getChannelList(db)) != 0)
567 eDebug("no channel list");
571 ePtr<eDVBChannelQuery> q;
573 if (!m_parent.path.empty())
575 eDVBChannelQuery::compile(q, m_parent.path);
578 eDebug("compile query failed");
583 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
585 eDebug("startQuery failed");
592 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
594 eServiceReferenceDVB ref;
599 while (!m_query->getNextResult(ref))
603 list.sort(iListableServiceCompare(this));
608 // The first argument of this function is a format string to specify the order and
609 // the content of the returned list
610 // useable format options are
611 // R = Service Reference (as swig object .. this is very slow)
612 // S = Service Reference (as python string object .. same as ref.toString())
613 // C = Service Reference (as python string object .. same as ref.toCompareString())
614 // N = Service Name (as python string object)
615 // n = Short Service Name (short name brakets used) (as python string object)
616 // when exactly one return value per service is selected in the format string,
617 // then each value is directly a list entry
618 // when more than one value is returned per service, then the list is a list of
620 // unknown format string chars are returned as python None values !
621 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
624 std::list<eServiceReference> tmplist;
627 if (!format || !(retcount=strlen(format)))
628 format = "R"; // just return service reference swig object ...
630 if (!getContent(tmplist, sorted))
632 int services=tmplist.size();
633 ePtr<iStaticServiceInformation> sptr;
634 eServiceCenterPtr service_center;
636 if (strchr(format, 'N') || strchr(format, 'n'))
637 eServiceCenter::getPrivInstance(service_center);
639 ret = PyList_New(services);
640 std::list<eServiceReference>::iterator it(tmplist.begin());
642 for (int cnt=0; cnt < services; ++cnt)
644 eServiceReference &ref=*it++;
645 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
646 for (int i=0; i < retcount; ++i)
651 case 'R': // service reference (swig)object
652 tmp = NEW_eServiceReference(ref);
654 case 'C': // service reference compare string
655 tmp = PyString_FromString(ref.toCompareString().c_str());
657 case 'S': // service reference string
658 tmp = PyString_FromString(ref.toString().c_str());
660 case 'N': // service name
663 service_center->info(ref, sptr);
667 sptr->getName(ref, name);
669 // filter short name brakets
671 while((pos = name.find("\xc2\x86")) != std::string::npos)
673 while((pos = name.find("\xc2\x87")) != std::string::npos)
677 tmp = PyString_FromString(name.c_str());
681 tmp = PyString_FromString("<n/a>");
683 case 'n': // short service name
686 service_center->info(ref, sptr);
690 sptr->getName(ref, name);
691 name = buildShortName(name);
693 tmp = PyString_FromString(name.c_str());
697 tmp = PyString_FromString("<n/a>");
710 PyTuple_SET_ITEM(tuple, i, tmp);
712 PyList_SET_ITEM(ret, cnt, tmp);
716 PyList_SET_ITEM(ret, cnt, tuple);
719 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
722 RESULT eDVBServiceList::getNext(eServiceReference &ref)
727 return m_query->getNextResult((eServiceReferenceDVB&)ref);
730 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
732 if (m_parent.flags & eServiceReference::canDescent) // bouquet
734 ePtr<iDVBChannelList> db;
735 ePtr<eDVBResourceManager> resm;
737 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
740 if (db->getBouquet(m_parent, m_bouquet) != 0)
751 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
755 return m_bouquet->addService(ref, before);
758 RESULT eDVBServiceList::removeService(eServiceReference &ref)
762 return m_bouquet->removeService(ref);
765 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
769 return m_bouquet->moveService(ref, pos);
772 RESULT eDVBServiceList::flushChanges()
776 return m_bouquet->flushChanges();
779 RESULT eDVBServiceList::setListName(const std::string &name)
783 return m_bouquet->setListName(name);
786 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
788 ePtr<eDVBService> service;
789 int r = lookupService(service, ref);
792 // check resources...
793 ptr = new eDVBServicePlay(ref, service);
797 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
799 if (ref.path.empty())
801 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
810 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
812 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
813 if (list->startQuery())
823 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
825 /* is a listable service? */
826 if (ref.flags & eServiceReference::canDescent) // bouquet
828 if ( !ref.name.empty() ) // satellites or providers list
829 ptr = m_StaticServiceDVBInfo;
830 else // a dvb bouquet
831 ptr = m_StaticServiceDVBBouquetInfo;
833 else if (!ref.path.empty()) /* do we have a PVR service? */
834 ptr = new eStaticServiceDVBPVRInformation(ref);
835 else // normal dvb service
837 ePtr<eDVBService> service;
838 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
839 ptr = m_StaticServiceDVBInfo;
841 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
847 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
849 if (ref.path.empty())
855 ptr = new eDVBPVRServiceOfflineOperations(ref);
860 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
862 // TODO: handle the listing itself
863 // if (ref.... == -1) .. return "... bouquets ...";
864 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
866 ePtr<iDVBChannelList> db;
867 ePtr<eDVBResourceManager> res;
870 if ((err = eDVBResourceManager::getInstance(res)) != 0)
872 eDebug("no resource manager");
875 if ((err = res->getChannelList(db)) != 0)
877 eDebug("no channel list");
881 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
882 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
884 eDebug("getService failed!");
891 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
892 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
895 m_is_pvr = !m_reference.path.empty();
897 m_timeshift_enabled = m_timeshift_active = 0;
900 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
901 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
902 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
904 m_cuesheet_changed = 0;
905 m_cutlist_enabled = 1;
907 m_subtitle_widget = 0;
911 m_subtitle_sync_timer = eTimer::create(eApp);
913 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
916 eDVBServicePlay::~eDVBServicePlay()
918 delete m_subtitle_widget;
921 void eDVBServicePlay::gotNewEvent()
925 ePtr<eServiceEvent> m_event_now, m_event_next;
926 getEvent(m_event_now, 0);
927 getEvent(m_event_next, 1);
930 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
932 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
934 m_event((iPlayableService*)this, evUpdatedEventInfo);
937 void eDVBServicePlay::serviceEvent(int event)
939 m_tune_state = event;
943 case eDVBServicePMTHandler::eventTuned:
945 ePtr<iDVBDemux> m_demux;
946 if (!m_service_handler.getDataDemux(m_demux))
948 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
949 int sid = ref.getParentServiceID().get();
951 sid = ref.getServiceID().get();
952 if ( ref.getParentTransportStreamID().get() &&
953 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
954 m_event_handler.startOther(m_demux, sid);
956 m_event_handler.start(m_demux, sid);
958 m_event((iPlayableService*)this, evTunedIn);
961 case eDVBServicePMTHandler::eventNoResources:
962 case eDVBServicePMTHandler::eventNoPAT:
963 case eDVBServicePMTHandler::eventNoPATEntry:
964 case eDVBServicePMTHandler::eventNoPMT:
965 case eDVBServicePMTHandler::eventTuneFailed:
966 case eDVBServicePMTHandler::eventMisconfiguration:
968 eDebug("DVB service failed to tune - error %d", event);
969 m_event((iPlayableService*)this, evTuneFailed);
972 case eDVBServicePMTHandler::eventNewProgramInfo:
974 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
975 if (m_timeshift_enabled)
976 updateTimeshiftPids();
977 if (!m_timeshift_active)
979 if (m_first_program_info && m_is_pvr)
981 m_first_program_info = 0;
984 m_event((iPlayableService*)this, evUpdatedInfo);
987 case eDVBServicePMTHandler::eventEOF:
988 m_event((iPlayableService*)this, evEOF);
990 case eDVBServicePMTHandler::eventSOF:
991 m_event((iPlayableService*)this, evSOF);
996 void eDVBServicePlay::serviceEventTimeshift(int event)
1000 case eDVBServicePMTHandler::eventNewProgramInfo:
1001 if (m_timeshift_active)
1004 case eDVBServicePMTHandler::eventSOF:
1005 m_event((iPlayableService*)this, evSOF);
1007 case eDVBServicePMTHandler::eventEOF:
1008 if ((!m_is_paused) && (m_skipmode >= 0))
1014 RESULT eDVBServicePlay::start()
1017 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1018 two (one for decoding, one for data source), as we must be prepared
1019 to start recording from the data demux. */
1021 m_cue = new eCueSheet();
1023 m_event(this, evStart);
1025 m_first_program_info = 1;
1026 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1027 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1029 /* inject EIT if there is a stored one */
1032 std::string filename = service.path;
1033 filename.erase(filename.length()-2, 2);
1035 ePtr<eServiceEvent> event = new eServiceEvent;
1036 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1038 ePtr<eServiceEvent> empty;
1039 m_event_handler.inject(event, 0);
1040 m_event_handler.inject(empty, 1);
1047 m_event(this, evStart);
1052 RESULT eDVBServicePlay::stop()
1054 /* add bookmark for last play position */
1057 pts_t play_position, length;
1058 if (!getPlayPosition(play_position))
1060 /* remove last position */
1061 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1063 if (i->what == 3) /* current play position */
1065 m_cue_entries.erase(i);
1066 i = m_cue_entries.begin();
1072 if (getLength(length))
1077 int perc = play_position * 100LL / length;
1079 /* only store last play position when between 1% and 99% */
1080 if ((1 < perc) && (perc < 99))
1081 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1083 m_cuesheet_changed = 1;
1087 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1089 m_service_handler_timeshift.free();
1090 m_service_handler.free();
1092 if (m_is_pvr && m_cuesheet_changed)
1095 /* save cuesheet only when main file is accessible. */
1096 if (!::stat(m_reference.path.c_str(), &s))
1099 m_event((iPlayableService*)this, evStopped);
1103 RESULT eDVBServicePlay::setTarget(int target)
1105 m_is_primary = !target;
1109 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1111 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1115 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1117 /* note: we check for timeshift to be enabled,
1118 not neccessary active. if you pause when timeshift
1119 is not active, you should activate it when unpausing */
1120 if ((!m_is_pvr) && (!m_timeshift_enabled))
1130 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1133 return m_decoder->setSlowMotion(ratio);
1138 RESULT eDVBServicePlay::setFastForward(int ratio)
1140 int skipmode, ffratio;
1146 } else if (ratio > 0)
1154 } else // if (ratio < 0)
1160 if (m_skipmode != skipmode)
1162 eDebug("setting cue skipmode to %d", skipmode);
1164 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1167 m_skipmode = skipmode;
1172 return m_decoder->setFastForward(ffratio);
1175 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1177 if (m_is_pvr || m_timeshift_enabled)
1187 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1188 RESULT eDVBServicePlay::getLength(pts_t &len)
1190 ePtr<iDVBPVRChannel> pvr_channel;
1192 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1195 return pvr_channel->getLength(len);
1198 RESULT eDVBServicePlay::pause()
1200 if (!m_is_paused && m_decoder)
1203 return m_decoder->freeze(0);
1208 RESULT eDVBServicePlay::unpause()
1210 if (m_is_paused && m_decoder)
1213 return m_decoder->unfreeze();
1218 RESULT eDVBServicePlay::seekTo(pts_t to)
1220 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1222 if (!m_decode_demux)
1225 ePtr<iDVBPVRChannel> pvr_channel;
1227 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1233 m_cue->seekTo(0, to);
1234 m_dvb_subtitle_pages.clear();
1235 m_subtitle_pages.clear();
1240 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1242 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1244 if (!m_decode_demux)
1247 ePtr<iDVBPVRChannel> pvr_channel;
1249 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1254 /* HACK until we have skip-AP api */
1255 if ((to > 0) && (to < 100))
1263 m_cue->seekTo(mode, to);
1264 m_dvb_subtitle_pages.clear();
1265 m_subtitle_pages.clear();
1269 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1271 ePtr<iDVBPVRChannel> pvr_channel;
1273 if (!m_decode_demux)
1276 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1281 /* if there is a decoder, use audio or video PTS */
1284 r = m_decoder->getPTS(0, pos);
1290 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1293 RESULT eDVBServicePlay::setTrickmode(int trick)
1296 m_decoder->setTrickmode(trick);
1300 RESULT eDVBServicePlay::isCurrentlySeekable()
1302 return m_is_pvr || m_timeshift_active;
1305 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1311 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1317 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1323 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1329 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1335 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1338 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1339 (m_timeshift_enabled || !m_is_pvr))
1341 if (!m_timeshift_enabled)
1343 /* query config path */
1345 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1346 eDebug("could not query ts path from config");
1350 /* we need enough diskspace */
1352 if (statfs(tspath.c_str(), &fs) < 0)
1354 eDebug("statfs failed!");
1358 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1360 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1370 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1381 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1387 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1393 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1399 RESULT eDVBServicePlay::getName(std::string &name)
1403 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1404 return i->getName(m_reference, name);
1408 m_dvb_service->getName(m_reference, name);
1412 else if (!m_reference.name.empty())
1413 eStaticServiceDVBInformation().getName(m_reference, name);
1415 name = "DVB service";
1419 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1421 return m_event_handler.getEvent(evt, nownext);
1424 int eDVBServicePlay::getInfo(int w)
1426 eDVBServicePMTHandler::program program;
1429 return resIsPyObject;
1431 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1433 int no_program_info = 0;
1435 if (h.getProgramInfo(program))
1436 no_program_info = 1;
1442 return m_decoder->getVideoHeight();
1446 return m_decoder->getVideoWidth();
1450 return m_decoder->getVideoFrameRate();
1454 return m_decoder->getVideoProgressive();
1460 aspect = m_decoder->getVideoAspect();
1461 if (no_program_info)
1463 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1465 ePtr<eServiceEvent> evt;
1466 if (!m_event_handler.getEvent(evt, 0))
1468 ePtr<eComponentData> data;
1469 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1471 if ( data->getStreamContent() == 1 )
1473 switch(data->getComponentType())
1476 case 1: // 4:3 SD PAL
1478 case 3: // 16:9 SD PAL
1479 case 4: // > 16:9 PAL
1480 case 5: // 4:3 SD NTSC
1482 case 7: // 16:9 SD NTSC
1483 case 8: // > 16:9 NTSC
1486 case 9: // 4:3 HD PAL
1488 case 0xB: // 16:9 HD PAL
1489 case 0xC: // > 16:9 HD PAL
1490 case 0xD: // 4:3 HD NTSC
1492 case 0xF: // 16:9 HD NTSC
1493 case 0x10: // > 16:9 HD PAL
1494 return data->getComponentType();
1504 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1505 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1506 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1507 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1508 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1509 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1510 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1511 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1512 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1513 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1514 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1515 case sProvider: if (!m_dvb_service) return -1; return -2;
1516 case sServiceref: return resIsString;
1517 case sDVBState: return m_tune_state;
1524 std::string eDVBServicePlay::getInfoString(int w)
1529 if (!m_dvb_service) return "";
1530 return m_dvb_service->m_provider_name;
1532 return m_reference.toString();
1536 return iServiceInformation::getInfoString(w);
1539 PyObject *eDVBServicePlay::getInfoObject(int w)
1544 return m_service_handler.getCaIds();
1545 case sTransponderData:
1546 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1550 return iServiceInformation::getInfoObject(w);
1553 int eDVBServicePlay::getNumberOfTracks()
1555 eDVBServicePMTHandler::program program;
1556 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1557 if (h.getProgramInfo(program))
1559 return program.audioStreams.size();
1562 int eDVBServicePlay::getCurrentTrack()
1564 eDVBServicePMTHandler::program program;
1565 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1566 if (h.getProgramInfo(program))
1569 int max = program.audioStreams.size();
1572 for (i = 0; i < max; ++i)
1573 if (program.audioStreams[i].pid == m_current_audio_pid)
1579 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1581 int ret = selectAudioStream(i);
1583 if (m_decoder->start())
1589 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1591 eDVBServicePMTHandler::program program;
1592 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1594 if (h.getProgramInfo(program))
1597 if (i >= program.audioStreams.size())
1600 info.m_pid = program.audioStreams[i].pid;
1602 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1603 info.m_description = "MPEG";
1604 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1605 info.m_description = "AC3";
1606 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1607 info.m_description = "AAC";
1608 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1609 info.m_description = "AAC-HE";
1610 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1611 info.m_description = "DTS";
1613 info.m_description = "???";
1615 if (program.audioStreams[i].component_tag != -1)
1617 ePtr<eServiceEvent> evt;
1618 if (!m_event_handler.getEvent(evt, 0))
1620 ePtr<eComponentData> data;
1621 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1622 info.m_language = data->getText();
1626 if (info.m_language.empty())
1627 info.m_language = program.audioStreams[i].language_code;
1632 int eDVBServicePlay::selectAudioStream(int i)
1634 eDVBServicePMTHandler::program program;
1635 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1637 if (h.getProgramInfo(program))
1640 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1648 stream = program.defaultAudioStream;
1650 int apid = -1, apidtype = -1;
1652 if (((unsigned int)stream) < program.audioStreams.size())
1654 apid = program.audioStreams[stream].pid;
1655 apidtype = program.audioStreams[stream].type;
1658 m_current_audio_pid = apid;
1660 if (m_decoder->setAudioPID(apid, apidtype))
1662 eDebug("set audio pid failed");
1666 /* 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 */
1667 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1670 ePtr<iDVBDemux> data_demux;
1671 if (!h.getDataDemux(data_demux))
1673 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1674 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1678 /* if we decided that we need one, update the pid */
1680 m_rds_decoder->start(apid);
1682 /* store new pid as default only when:
1683 a.) we have an entry in the service db for the current service,
1684 b.) we are not playing back something,
1685 c.) we are not selecting the default entry. (we wouldn't change
1686 anything in the best case, or destroy the default setting in
1687 case the real default is not yet available.)
1689 if (m_dvb_service && !m_is_pvr && ((i != -1)
1690 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1692 if (apidtype == eDVBAudio::aMPEG)
1694 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1695 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1699 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1700 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1704 h.resetCachedProgram();
1709 int eDVBServicePlay::getCurrentChannel()
1711 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1714 RESULT eDVBServicePlay::selectChannel(int i)
1716 if (i < LEFT || i > RIGHT || i == STEREO)
1719 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1721 m_decoder->setAudioChannel(i);
1725 std::string eDVBServicePlay::getText(int x)
1731 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1733 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1738 void eDVBServicePlay::rdsDecoderEvent(int what)
1742 case eDVBRdsDecoder::RadioTextChanged:
1743 m_event((iPlayableService*)this, evUpdatedRadioText);
1745 case eDVBRdsDecoder::RtpTextChanged:
1746 m_event((iPlayableService*)this, evUpdatedRtpText);
1748 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1749 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1751 case eDVBRdsDecoder::RecvRassSlidePic:
1752 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1757 void eDVBServicePlay::showRassSlidePicture()
1763 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1764 if (rass_slide_pic.length())
1765 m_decoder->showSinglePic(rass_slide_pic.c_str());
1767 eDebug("empty filename for rass slide picture received!!");
1770 eDebug("no MPEG Decoder to show iframes avail");
1773 eDebug("showRassSlidePicture called.. but not decoder");
1776 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1782 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1783 if (rass_interactive_pic.length())
1784 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1786 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1789 eDebug("no MPEG Decoder to show iframes avail");
1792 eDebug("showRassInteractivePic called.. but not decoder");
1795 ePyObject eDVBServicePlay::getRassInteractiveMask()
1798 return m_rds_decoder->getRassPictureMask();
1802 int eDVBServiceBase::getFrontendInfo(int w)
1804 eUsePtr<iDVBChannel> channel;
1805 if(m_service_handler.getChannel(channel))
1807 ePtr<iDVBFrontend> fe;
1808 if(channel->getFrontend(fe))
1810 return fe->readFrontendData(w);
1813 PyObject *eDVBServiceBase::getFrontendData()
1815 ePyObject ret = PyDict_New();
1818 eUsePtr<iDVBChannel> channel;
1819 if(!m_service_handler.getChannel(channel))
1821 ePtr<iDVBFrontend> fe;
1822 if(!channel->getFrontend(fe))
1823 fe->getFrontendData(ret);
1831 PyObject *eDVBServiceBase::getFrontendStatus()
1833 ePyObject ret = PyDict_New();
1836 eUsePtr<iDVBChannel> channel;
1837 if(!m_service_handler.getChannel(channel))
1839 ePtr<iDVBFrontend> fe;
1840 if(!channel->getFrontend(fe))
1841 fe->getFrontendStatus(ret);
1849 PyObject *eDVBServiceBase::getTransponderData(bool original)
1851 ePyObject ret = PyDict_New();
1854 eUsePtr<iDVBChannel> channel;
1855 if(!m_service_handler.getChannel(channel))
1857 ePtr<iDVBFrontend> fe;
1858 if(!channel->getFrontend(fe))
1859 fe->getTransponderData(ret, original);
1867 PyObject *eDVBServiceBase::getAll(bool original)
1869 ePyObject ret = getTransponderData(original);
1872 eUsePtr<iDVBChannel> channel;
1873 if(!m_service_handler.getChannel(channel))
1875 ePtr<iDVBFrontend> fe;
1876 if(!channel->getFrontend(fe))
1878 fe->getFrontendData(ret);
1879 fe->getFrontendStatus(ret);
1886 int eDVBServicePlay::getNumberOfSubservices()
1888 ePtr<eServiceEvent> evt;
1889 if (!m_event_handler.getEvent(evt, 0))
1890 return evt->getNumOfLinkageServices();
1894 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1896 ePtr<eServiceEvent> evt;
1897 if (!m_event_handler.getEvent(evt, 0))
1899 if (!evt->getLinkageService(sub, m_reference, n))
1902 sub.type=eServiceReference::idInvalid;
1906 RESULT eDVBServicePlay::startTimeshift()
1908 ePtr<iDVBDemux> demux;
1910 eDebug("Start timeshift!");
1912 if (m_timeshift_enabled)
1915 /* start recording with the data demux. */
1916 if (m_service_handler.getDataDemux(demux))
1919 demux->createTSRecorder(m_record);
1924 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1925 eDebug("could not query ts path");
1928 tspath.append("/timeshift.XXXXXX");
1930 templ = new char[tspath.length() + 1];
1931 strcpy(templ, tspath.c_str());
1933 m_timeshift_fd = mkstemp(templ);
1934 m_timeshift_file = std::string(templ);
1936 eDebug("recording to %s", templ);
1940 if (m_timeshift_fd < 0)
1946 m_record->setTargetFD(m_timeshift_fd);
1948 m_timeshift_enabled = 1;
1950 updateTimeshiftPids();
1956 RESULT eDVBServicePlay::stopTimeshift()
1958 if (!m_timeshift_enabled)
1963 m_timeshift_enabled = 0;
1968 close(m_timeshift_fd);
1969 eDebug("remove timeshift file");
1970 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1975 int eDVBServicePlay::isTimeshiftActive()
1977 return m_timeshift_enabled && m_timeshift_active;
1980 RESULT eDVBServicePlay::activateTimeshift()
1982 if (!m_timeshift_enabled)
1985 if (!m_timeshift_active)
1987 switchToTimeshift();
1994 PyObject *eDVBServicePlay::getCutList()
1996 ePyObject list = PyList_New(0);
1998 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2000 ePyObject tuple = PyTuple_New(2);
2001 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2002 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2003 PyList_Append(list, tuple);
2010 void eDVBServicePlay::setCutList(ePyObject list)
2012 if (!PyList_Check(list))
2014 int size = PyList_Size(list);
2017 m_cue_entries.clear();
2019 for (i=0; i<size; ++i)
2021 ePyObject tuple = PyList_GET_ITEM(list, i);
2022 if (!PyTuple_Check(tuple))
2024 eDebug("non-tuple in cutlist");
2027 if (PyTuple_Size(tuple) != 2)
2029 eDebug("cutlist entries need to be a 2-tuple");
2032 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2033 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2035 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2038 pts_t pts = PyLong_AsLongLong(ppts);
2039 int type = PyInt_AsLong(ptype);
2040 m_cue_entries.insert(cueEntry(pts, type));
2041 eDebug("adding %08llx, %d", pts, type);
2043 m_cuesheet_changed = 1;
2045 cutlistToCuesheet();
2046 m_event((iPlayableService*)this, evCuesheetChanged);
2049 void eDVBServicePlay::setCutListEnable(int enable)
2051 m_cutlist_enabled = enable;
2052 cutlistToCuesheet();
2055 void eDVBServicePlay::updateTimeshiftPids()
2060 eDVBServicePMTHandler::program program;
2061 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2063 if (h.getProgramInfo(program))
2067 std::set<int> pids_to_record;
2068 pids_to_record.insert(0); // PAT
2069 if (program.pmtPid != -1)
2070 pids_to_record.insert(program.pmtPid); // PMT
2072 if (program.textPid != -1)
2073 pids_to_record.insert(program.textPid); // Videotext
2075 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2076 i(program.videoStreams.begin());
2077 i != program.videoStreams.end(); ++i)
2078 pids_to_record.insert(i->pid);
2080 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2081 i(program.audioStreams.begin());
2082 i != program.audioStreams.end(); ++i)
2083 pids_to_record.insert(i->pid);
2085 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2086 i(program.subtitleStreams.begin());
2087 i != program.subtitleStreams.end(); ++i)
2088 pids_to_record.insert(i->pid);
2090 std::set<int> new_pids, obsolete_pids;
2092 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2093 m_pids_active.begin(), m_pids_active.end(),
2094 std::inserter(new_pids, new_pids.begin()));
2096 std::set_difference(
2097 m_pids_active.begin(), m_pids_active.end(),
2098 pids_to_record.begin(), pids_to_record.end(),
2099 std::inserter(new_pids, new_pids.begin())
2102 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2103 m_record->addPID(*i);
2105 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2106 m_record->removePID(*i);
2110 void eDVBServicePlay::switchToLive()
2112 if (!m_timeshift_active)
2118 m_teletext_parser = 0;
2120 m_subtitle_parser = 0;
2121 m_new_dvb_subtitle_page_connection = 0;
2122 m_new_subtitle_page_connection = 0;
2123 m_rds_decoder_event_connection = 0;
2124 m_video_event_connection = 0;
2126 /* free the timeshift service handler, we need the resources */
2127 m_service_handler_timeshift.free();
2128 m_timeshift_active = 0;
2130 m_event((iPlayableService*)this, evSeekableStatusChanged);
2135 void eDVBServicePlay::switchToTimeshift()
2137 if (m_timeshift_active)
2142 m_teletext_parser = 0;
2144 m_subtitle_parser = 0;
2145 m_new_subtitle_page_connection = 0;
2146 m_new_dvb_subtitle_page_connection = 0;
2147 m_rds_decoder_event_connection = 0;
2148 m_video_event_connection = 0;
2150 m_timeshift_active = 1;
2152 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2153 r.path = m_timeshift_file;
2155 m_cue = new eCueSheet();
2156 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2158 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2160 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2162 m_event((iPlayableService*)this, evSeekableStatusChanged);
2165 void eDVBServicePlay::updateDecoder()
2167 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2169 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2171 eDVBServicePMTHandler::program program;
2172 if (h.getProgramInfo(program))
2173 eDebug("getting program info failed.");
2176 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2177 if (!program.videoStreams.empty())
2179 eDebugNoNewLine(" (");
2180 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2181 i(program.videoStreams.begin());
2182 i != program.videoStreams.end(); ++i)
2189 if (i != program.videoStreams.begin())
2190 eDebugNoNewLine(", ");
2191 eDebugNoNewLine("%04x", i->pid);
2193 eDebugNoNewLine(")");
2195 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2196 if (!program.audioStreams.empty())
2198 eDebugNoNewLine(" (");
2199 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2200 i(program.audioStreams.begin());
2201 i != program.audioStreams.end(); ++i)
2203 if (i != program.audioStreams.begin())
2204 eDebugNoNewLine(", ");
2205 eDebugNoNewLine("%04x", i->pid);
2207 eDebugNoNewLine(")");
2209 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2210 pcrpid = program.pcrPid;
2211 eDebug(", and the text pid is %04x", program.textPid);
2212 tpid = program.textPid;
2217 h.getDecodeDemux(m_decode_demux);
2220 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2222 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2223 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2224 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2225 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2226 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2229 m_teletext_parser = 0;
2230 m_subtitle_parser = 0;
2234 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2241 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2242 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2243 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2245 else // subservice or recording
2247 eServiceReferenceDVB ref;
2248 m_service_handler.getServiceReference(ref);
2249 eServiceReferenceDVB parent = ref.getParentServiceReference();
2254 ePtr<eDVBResourceManager> res_mgr;
2255 if (!eDVBResourceManager::getInstance(res_mgr))
2257 ePtr<iDVBChannelList> db;
2258 if (!res_mgr->getChannelList(db))
2260 ePtr<eDVBService> origService;
2261 if (!db->getService(parent, origService))
2263 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2264 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2270 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2271 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2273 m_decoder->setVideoPID(vpid, vpidtype);
2274 selectAudioStream();
2276 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2277 m_decoder->setSyncPCR(pcrpid);
2279 m_decoder->setSyncPCR(-1);
2281 m_decoder->setTextPID(tpid);
2283 m_teletext_parser->start(program.textPid);
2286 m_decoder->setTrickmode(1);
2289 m_decoder->preroll();
2293 if (vpid > 0 && vpid < 0x2000)
2297 std::string radio_pic;
2298 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2299 m_decoder->setRadioPic(radio_pic);
2302 m_decoder->setAudioChannel(achannel);
2304 /* don't worry about non-existing services, nor pvr services */
2305 if (m_dvb_service && !m_is_pvr)
2307 /* (audio pid will be set in selectAudioTrack */
2308 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2309 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2310 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2311 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2314 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2317 void eDVBServicePlay::loadCuesheet()
2319 std::string filename = m_reference.path + ".cuts";
2321 m_cue_entries.clear();
2323 FILE *f = fopen(filename.c_str(), "rb");
2327 eDebug("loading cuts..");
2330 unsigned long long where;
2333 if (!fread(&where, sizeof(where), 1, f))
2335 if (!fread(&what, sizeof(what), 1, f))
2338 #if BYTE_ORDER == LITTLE_ENDIAN
2339 where = bswap_64(where);
2346 m_cue_entries.insert(cueEntry(where, what));
2349 eDebug("%d entries", m_cue_entries.size());
2351 eDebug("cutfile not found!");
2353 m_cuesheet_changed = 0;
2354 cutlistToCuesheet();
2355 m_event((iPlayableService*)this, evCuesheetChanged);
2358 void eDVBServicePlay::saveCuesheet()
2360 std::string filename = m_reference.path + ".cuts";
2362 FILE *f = fopen(filename.c_str(), "wb");
2366 unsigned long long where;
2369 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2371 #if BYTE_ORDER == BIG_ENDIAN
2374 where = bswap_64(i->where);
2376 what = htonl(i->what);
2377 fwrite(&where, sizeof(where), 1, f);
2378 fwrite(&what, sizeof(what), 1, f);
2384 m_cuesheet_changed = 0;
2387 void eDVBServicePlay::cutlistToCuesheet()
2391 eDebug("no cue sheet");
2396 if (!m_cutlist_enabled)
2398 m_cue->commitSpans();
2399 eDebug("cutlists were disabled");
2403 pts_t in = 0, out = 0, length = 0;
2407 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2411 if (i == m_cue_entries.end())
2414 if (i->what == 0) /* in */
2418 } else if (i->what == 1) /* out */
2420 else /* mark (2) or last play position (3) */
2437 m_cue->addSourceSpan(in, out);
2441 if (i == m_cue_entries.end())
2444 m_cue->commitSpans();
2447 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2449 if (m_subtitle_widget)
2450 disableSubtitles(parent);
2453 int tuplesize = PyTuple_Size(tuple);
2456 if (!PyTuple_Check(tuple))
2462 entry = PyTuple_GET_ITEM(tuple, 0);
2464 if (!PyInt_Check(entry))
2467 type = PyInt_AsLong(entry);
2469 if (type == 1) // teletext subtitles
2471 int page, magazine, pid;
2475 if (!m_teletext_parser)
2477 eDebug("enable teletext subtitles.. no parser !!!");
2481 entry = PyTuple_GET_ITEM(tuple, 1);
2482 if (!PyInt_Check(entry))
2484 pid = PyInt_AsLong(entry);
2486 entry = PyTuple_GET_ITEM(tuple, 2);
2487 if (!PyInt_Check(entry))
2489 page = PyInt_AsLong(entry);
2491 entry = PyTuple_GET_ITEM(tuple, 3);
2492 if (!PyInt_Check(entry))
2494 magazine = PyInt_AsLong(entry);
2496 m_subtitle_widget = new eSubtitleWidget(parent);
2497 m_subtitle_widget->resize(parent->size()); /* full size */
2498 m_teletext_parser->setPageAndMagazine(page, magazine);
2500 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2504 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2505 if (!m_subtitle_parser)
2507 eDebug("enable dvb subtitles.. no parser !!!");
2513 entry = PyTuple_GET_ITEM(tuple, 1);
2514 if (!PyInt_Check(entry))
2516 pid = PyInt_AsLong(entry);
2518 entry = PyTuple_GET_ITEM(tuple, 2);
2519 if (!PyInt_Check(entry))
2521 composition_page_id = PyInt_AsLong(entry);
2523 entry = PyTuple_GET_ITEM(tuple, 3);
2524 if (!PyInt_Check(entry))
2526 ancillary_page_id = PyInt_AsLong(entry);
2528 m_subtitle_widget = new eSubtitleWidget(parent);
2529 m_subtitle_widget->resize(parent->size()); /* full size */
2530 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2532 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2538 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2539 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2540 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2544 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2546 delete m_subtitle_widget;
2547 m_subtitle_widget = 0;
2548 if (m_subtitle_parser)
2550 m_subtitle_parser->stop();
2551 m_dvb_subtitle_pages.clear();
2553 if (m_teletext_parser)
2555 m_teletext_parser->setPageAndMagazine(-1, -1);
2556 m_subtitle_pages.clear();
2559 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2563 PyObject *eDVBServicePlay::getCachedSubtitle()
2567 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2570 unsigned int data = (unsigned int)tmp;
2571 int pid = (data&0xFFFF0000)>>16;
2572 ePyObject tuple = PyTuple_New(4);
2573 eDVBServicePMTHandler::program program;
2574 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2575 if (!h.getProgramInfo(program))
2577 if (program.textPid==pid) // teletext
2578 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2580 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2581 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2582 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2583 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2591 PyObject *eDVBServicePlay::getSubtitleList()
2593 if (!m_teletext_parser)
2596 ePyObject l = PyList_New(0);
2597 std::set<int> added_ttx_pages;
2599 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2600 m_teletext_parser->m_found_subtitle_pages;
2602 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2603 eDVBServicePMTHandler::program program;
2604 if (h.getProgramInfo(program))
2605 eDebug("getting program info failed.");
2608 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2609 it != program.subtitleStreams.end(); ++it)
2611 switch(it->subtitling_type)
2613 case 0x01: // ebu teletext subtitles
2615 int page_number = it->teletext_page_number & 0xFF;
2616 int magazine_number = it->teletext_magazine_number & 7;
2617 int hash = magazine_number << 8 | page_number;
2618 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2620 ePyObject tuple = PyTuple_New(5);
2621 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2622 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2623 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2624 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2625 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2626 PyList_Append(l, tuple);
2628 added_ttx_pages.insert(hash);
2633 case 0x20 ... 0x23: // dvb subtitles
2635 ePyObject tuple = PyTuple_New(5);
2636 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2637 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2638 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2639 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2640 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2641 PyList_Insert(l, 0, tuple);
2649 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2650 it != subs.end(); ++it)
2652 int page_number = it->teletext_page_number & 0xFF;
2653 int magazine_number = it->teletext_magazine_number & 7;
2654 int hash = magazine_number << 8 | page_number;
2655 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2657 ePyObject tuple = PyTuple_New(5);
2658 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2659 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2660 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2661 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2662 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2663 PyList_Append(l, tuple);
2671 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2673 if (m_subtitle_widget)
2677 m_decoder->getPTS(0, pos);
2678 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2679 m_subtitle_pages.push_back(page);
2680 checkSubtitleTiming();
2684 void eDVBServicePlay::checkSubtitleTiming()
2686 eDebug("checkSubtitleTiming");
2687 if (!m_subtitle_widget)
2691 enum { TELETEXT, DVB } type;
2692 eDVBTeletextSubtitlePage page;
2693 eDVBSubtitlePage dvb_page;
2695 if (!m_subtitle_pages.empty())
2697 page = m_subtitle_pages.front();
2699 show_time = page.m_pts;
2701 else if (!m_dvb_subtitle_pages.empty())
2703 dvb_page = m_dvb_subtitle_pages.front();
2705 show_time = dvb_page.m_show_time;
2713 m_decoder->getPTS(0, pos);
2715 eDebug("%lld %lld", pos, show_time);
2716 int diff = show_time - pos;
2719 eDebug("[late (%d ms)]", -diff / 90);
2722 // if (diff > 900000)
2724 // eDebug("[invalid]");
2730 if (type == TELETEXT)
2732 eDebug("display teletext subtitle page %lld", show_time);
2733 m_subtitle_widget->setPage(page);
2734 m_subtitle_pages.pop_front();
2738 eDebug("display dvb subtitle Page %lld", show_time);
2739 m_subtitle_widget->setPage(dvb_page);
2740 m_dvb_subtitle_pages.pop_front();
2744 eDebug("start subtitle delay %d", diff / 90);
2745 m_subtitle_sync_timer->start(diff / 90, 1);
2751 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2753 if (m_subtitle_widget)
2757 m_decoder->getPTS(0, pos);
2758 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2759 m_dvb_subtitle_pages.push_back(p);
2760 checkSubtitleTiming();
2764 int eDVBServicePlay::getAC3Delay()
2767 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2769 return m_decoder->getAC3Delay();
2774 int eDVBServicePlay::getPCMDelay()
2777 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2779 return m_decoder->getPCMDelay();
2784 void eDVBServicePlay::setAC3Delay(int delay)
2787 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2789 m_decoder->setAC3Delay(delay);
2792 void eDVBServicePlay::setPCMDelay(int delay)
2795 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2797 m_decoder->setPCMDelay(delay);
2800 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2802 switch(event.type) {
2803 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2804 m_event((iPlayableService*)this, evVideoSizeChanged);
2806 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2807 m_event((iPlayableService*)this, evVideoFramerateChanged);
2809 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2810 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2817 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2823 PyObject *eDVBServicePlay::getStreamingData()
2825 eDVBServicePMTHandler::program program;
2826 if (m_service_handler.getProgramInfo(program))
2831 ePyObject r = program.createPythonObject();
2832 ePtr<iDVBDemux> demux;
2833 if (!m_service_handler.getDataDemux(demux))
2836 if (!demux->getCADemuxID(demux_id))
2837 PutToDict(r, "demux", demux_id);
2844 DEFINE_REF(eDVBServicePlay)
2846 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2850 case iServiceInformation::sTransponderData:
2851 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2855 return iStaticServiceInformation::getInfoObject(ref, w);
2858 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");