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, "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, "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, "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()))
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 /* otherwise, re-calc length and update meta file */
382 if (tstools.calcLen(len))
385 m_parser.m_length = len;
386 m_parser.m_filesize = s.st_size;
387 m_parser.updateMeta(ref.path);
388 return m_parser.m_length / 90000;
391 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
395 case iServiceInformation::sDescription:
396 return iServiceInformation::resIsString;
397 case iServiceInformation::sServiceref:
398 return iServiceInformation::resIsString;
399 case iServiceInformation::sTimeCreate:
400 if (m_parser.m_time_create)
401 return m_parser.m_time_create;
403 return iServiceInformation::resNA;
405 return iServiceInformation::resNA;
409 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
413 case iServiceInformation::sDescription:
414 return m_parser.m_description;
415 case iServiceInformation::sServiceref:
416 return m_parser.m_ref.toString();
417 case iServiceInformation::sTags:
418 return m_parser.m_tags;
424 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
426 if (!ref.path.empty())
428 ePtr<eServiceEvent> event = new eServiceEvent;
429 std::string filename = ref.path;
430 filename.erase(filename.length()-2, 2);
432 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
442 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
444 DECLARE_REF(eDVBPVRServiceOfflineOperations);
445 eServiceReferenceDVB m_ref;
447 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
449 RESULT deleteFromDisk(int simulate);
450 RESULT getListOfFilenames(std::list<std::string> &);
453 DEFINE_REF(eDVBPVRServiceOfflineOperations);
455 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
459 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
465 std::list<std::string> res;
466 if (getListOfFilenames(res))
469 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
471 eDebug("FATAL !! can't get background file eraser");
473 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
475 eDebug("Removing %s...", i->c_str());
477 eraser->erase(i->c_str());
479 ::unlink(i->c_str());
486 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
489 res.push_back(m_ref.path);
491 // handling for old splitted recordings (enigma 1)
496 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
498 if (stat(buf, &s) < 0)
503 res.push_back(m_ref.path + ".meta");
504 res.push_back(m_ref.path + ".ap");
505 res.push_back(m_ref.path + ".cuts");
506 std::string tmp = m_ref.path;
507 tmp.erase(m_ref.path.length()-3);
508 res.push_back(tmp + ".eit");
512 DEFINE_REF(eServiceFactoryDVB)
514 eServiceFactoryDVB::eServiceFactoryDVB()
516 ePtr<eServiceCenter> sc;
518 eServiceCenter::getPrivInstance(sc);
521 std::list<std::string> extensions;
522 extensions.push_back("ts");
523 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
526 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
527 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
530 eServiceFactoryDVB::~eServiceFactoryDVB()
532 ePtr<eServiceCenter> sc;
534 eServiceCenter::getPrivInstance(sc);
536 sc->removeServiceFactory(eServiceFactoryDVB::id);
539 DEFINE_REF(eDVBServiceList);
541 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
545 eDVBServiceList::~eDVBServiceList()
549 RESULT eDVBServiceList::startQuery()
551 ePtr<iDVBChannelList> db;
552 ePtr<eDVBResourceManager> res;
555 if ((err = eDVBResourceManager::getInstance(res)) != 0)
557 eDebug("no resource manager");
560 if ((err = res->getChannelList(db)) != 0)
562 eDebug("no channel list");
566 ePtr<eDVBChannelQuery> q;
568 if (!m_parent.path.empty())
570 eDVBChannelQuery::compile(q, m_parent.path);
573 eDebug("compile query failed");
578 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
580 eDebug("startQuery failed");
587 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
589 eServiceReferenceDVB ref;
594 while (!m_query->getNextResult(ref))
598 list.sort(iListableServiceCompare(this));
603 // The first argument of this function is a format string to specify the order and
604 // the content of the returned list
605 // useable format options are
606 // R = Service Reference (as swig object .. this is very slow)
607 // S = Service Reference (as python string object .. same as ref.toString())
608 // C = Service Reference (as python string object .. same as ref.toCompareString())
609 // N = Service Name (as python string object)
610 // n = Short Service Name (short name brakets used) (as python string object)
611 // when exactly one return value per service is selected in the format string,
612 // then each value is directly a list entry
613 // when more than one value is returned per service, then the list is a list of
615 // unknown format string chars are returned as python None values !
616 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
619 std::list<eServiceReference> tmplist;
622 if (!format || !(retcount=strlen(format)))
623 format = "R"; // just return service reference swig object ...
625 if (!getContent(tmplist, sorted))
627 int services=tmplist.size();
628 ePtr<iStaticServiceInformation> sptr;
629 eServiceCenterPtr service_center;
631 if (strchr(format, 'N') || strchr(format, 'n'))
632 eServiceCenter::getPrivInstance(service_center);
634 ret = PyList_New(services);
635 std::list<eServiceReference>::iterator it(tmplist.begin());
637 for (int cnt=0; cnt < services; ++cnt)
639 eServiceReference &ref=*it++;
640 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
641 for (int i=0; i < retcount; ++i)
646 case 'R': // service reference (swig)object
647 tmp = NEW_eServiceReference(ref);
649 case 'C': // service reference compare string
650 tmp = PyString_FromString(ref.toCompareString().c_str());
652 case 'S': // service reference string
653 tmp = PyString_FromString(ref.toString().c_str());
655 case 'N': // service name
658 service_center->info(ref, sptr);
662 sptr->getName(ref, name);
664 // filter short name brakets
666 while((pos = name.find("\xc2\x86")) != std::string::npos)
668 while((pos = name.find("\xc2\x87")) != std::string::npos)
672 tmp = PyString_FromString(name.c_str());
676 tmp = PyString_FromString("<n/a>");
678 case 'n': // short service name
681 service_center->info(ref, sptr);
685 sptr->getName(ref, name);
686 name = buildShortName(name);
688 tmp = PyString_FromString(name.c_str());
692 tmp = PyString_FromString("<n/a>");
705 PyTuple_SET_ITEM(tuple, i, tmp);
707 PyList_SET_ITEM(ret, cnt, tmp);
711 PyList_SET_ITEM(ret, cnt, tuple);
714 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
717 RESULT eDVBServiceList::getNext(eServiceReference &ref)
722 return m_query->getNextResult((eServiceReferenceDVB&)ref);
725 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
727 if (m_parent.flags & eServiceReference::canDescent) // bouquet
729 ePtr<iDVBChannelList> db;
730 ePtr<eDVBResourceManager> resm;
732 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
735 if (db->getBouquet(m_parent, m_bouquet) != 0)
746 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
750 return m_bouquet->addService(ref, before);
753 RESULT eDVBServiceList::removeService(eServiceReference &ref)
757 return m_bouquet->removeService(ref);
760 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
764 return m_bouquet->moveService(ref, pos);
767 RESULT eDVBServiceList::flushChanges()
771 return m_bouquet->flushChanges();
774 RESULT eDVBServiceList::setListName(const std::string &name)
778 return m_bouquet->setListName(name);
781 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
783 ePtr<eDVBService> service;
784 int r = lookupService(service, ref);
787 // check resources...
788 ptr = new eDVBServicePlay(ref, service);
792 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
794 if (ref.path.empty())
796 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
805 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
807 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
808 if (list->startQuery())
818 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
820 /* is a listable service? */
821 if (ref.flags & eServiceReference::canDescent) // bouquet
823 if ( !ref.name.empty() ) // satellites or providers list
824 ptr = m_StaticServiceDVBInfo;
825 else // a dvb bouquet
826 ptr = m_StaticServiceDVBBouquetInfo;
828 else if (!ref.path.empty()) /* do we have a PVR service? */
829 ptr = new eStaticServiceDVBPVRInformation(ref);
830 else // normal dvb service
832 ePtr<eDVBService> service;
833 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
834 ptr = m_StaticServiceDVBInfo;
836 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
842 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
844 if (ref.path.empty())
850 ptr = new eDVBPVRServiceOfflineOperations(ref);
855 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
857 // TODO: handle the listing itself
858 // if (ref.... == -1) .. return "... bouquets ...";
859 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
861 ePtr<iDVBChannelList> db;
862 ePtr<eDVBResourceManager> res;
865 if ((err = eDVBResourceManager::getInstance(res)) != 0)
867 eDebug("no resource manager");
870 if ((err = res->getChannelList(db)) != 0)
872 eDebug("no channel list");
876 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
877 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
879 eDebug("getService failed!");
886 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
887 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
890 m_is_pvr = !m_reference.path.empty();
892 m_timeshift_enabled = m_timeshift_active = 0;
895 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
896 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
897 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
899 m_cuesheet_changed = 0;
900 m_cutlist_enabled = 1;
902 m_subtitle_widget = 0;
906 m_subtitle_sync_timer = eTimer::create(eApp);
908 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
911 eDVBServicePlay::~eDVBServicePlay()
913 delete m_subtitle_widget;
916 void eDVBServicePlay::gotNewEvent()
920 ePtr<eServiceEvent> m_event_now, m_event_next;
921 getEvent(m_event_now, 0);
922 getEvent(m_event_next, 1);
925 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
927 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
929 m_event((iPlayableService*)this, evUpdatedEventInfo);
932 void eDVBServicePlay::serviceEvent(int event)
934 m_tune_state = event;
938 case eDVBServicePMTHandler::eventTuned:
940 ePtr<iDVBDemux> m_demux;
941 if (!m_service_handler.getDataDemux(m_demux))
943 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
944 int sid = ref.getParentServiceID().get();
946 sid = ref.getServiceID().get();
947 if ( ref.getParentTransportStreamID().get() &&
948 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
949 m_event_handler.startOther(m_demux, sid);
951 m_event_handler.start(m_demux, sid);
953 m_event((iPlayableService*)this, evTunedIn);
956 case eDVBServicePMTHandler::eventNoResources:
957 case eDVBServicePMTHandler::eventNoPAT:
958 case eDVBServicePMTHandler::eventNoPATEntry:
959 case eDVBServicePMTHandler::eventNoPMT:
960 case eDVBServicePMTHandler::eventTuneFailed:
961 case eDVBServicePMTHandler::eventMisconfiguration:
963 eDebug("DVB service failed to tune - error %d", event);
964 m_event((iPlayableService*)this, evTuneFailed);
967 case eDVBServicePMTHandler::eventNewProgramInfo:
969 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
970 if (m_timeshift_enabled)
971 updateTimeshiftPids();
972 if (!m_timeshift_active)
974 if (m_first_program_info && m_is_pvr)
976 m_first_program_info = 0;
979 m_event((iPlayableService*)this, evUpdatedInfo);
982 case eDVBServicePMTHandler::eventEOF:
983 m_event((iPlayableService*)this, evEOF);
985 case eDVBServicePMTHandler::eventSOF:
986 m_event((iPlayableService*)this, evSOF);
991 void eDVBServicePlay::serviceEventTimeshift(int event)
995 case eDVBServicePMTHandler::eventNewProgramInfo:
996 if (m_timeshift_active)
999 case eDVBServicePMTHandler::eventSOF:
1000 m_event((iPlayableService*)this, evSOF);
1002 case eDVBServicePMTHandler::eventEOF:
1003 if ((!m_is_paused) && (m_skipmode >= 0))
1009 RESULT eDVBServicePlay::start()
1012 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1013 two (one for decoding, one for data source), as we must be prepared
1014 to start recording from the data demux. */
1016 m_cue = new eCueSheet();
1018 m_event(this, evStart);
1020 m_first_program_info = 1;
1021 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1022 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1024 /* inject EIT if there is a stored one */
1027 std::string filename = service.path;
1028 filename.erase(filename.length()-2, 2);
1030 ePtr<eServiceEvent> event = new eServiceEvent;
1031 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1033 ePtr<eServiceEvent> empty;
1034 m_event_handler.inject(event, 0);
1035 m_event_handler.inject(empty, 1);
1042 m_event(this, evStart);
1047 RESULT eDVBServicePlay::stop()
1049 /* add bookmark for last play position */
1052 pts_t play_position, length;
1053 if (!getPlayPosition(play_position))
1055 /* remove last position */
1056 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1058 if (i->what == 3) /* current play position */
1060 m_cue_entries.erase(i);
1061 i = m_cue_entries.begin();
1067 if (getLength(length))
1072 int perc = play_position * 100LL / length;
1074 /* only store last play position when between 1% and 99% */
1075 if ((1 < perc) && (perc < 99))
1076 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1078 m_cuesheet_changed = 1;
1082 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1084 m_service_handler_timeshift.free();
1085 m_service_handler.free();
1087 if (m_is_pvr && m_cuesheet_changed)
1090 /* save cuesheet only when main file is accessible. */
1091 if (!::stat(m_reference.path.c_str(), &s))
1094 m_event((iPlayableService*)this, evStopped);
1098 RESULT eDVBServicePlay::setTarget(int target)
1100 m_is_primary = !target;
1104 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1106 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1110 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1112 /* note: we check for timeshift to be enabled,
1113 not neccessary active. if you pause when timeshift
1114 is not active, you should activate it when unpausing */
1115 if ((!m_is_pvr) && (!m_timeshift_enabled))
1125 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1128 return m_decoder->setSlowMotion(ratio);
1133 RESULT eDVBServicePlay::setFastForward(int ratio)
1135 int skipmode, ffratio;
1141 } else if (ratio > 0)
1149 } else // if (ratio < 0)
1155 if (m_skipmode != skipmode)
1157 eDebug("setting cue skipmode to %d", skipmode);
1159 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1162 m_skipmode = skipmode;
1167 return m_decoder->setFastForward(ffratio);
1170 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1172 if (m_is_pvr || m_timeshift_enabled)
1182 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1183 RESULT eDVBServicePlay::getLength(pts_t &len)
1185 ePtr<iDVBPVRChannel> pvr_channel;
1187 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1190 return pvr_channel->getLength(len);
1193 RESULT eDVBServicePlay::pause()
1195 if (!m_is_paused && m_decoder)
1198 return m_decoder->freeze(0);
1203 RESULT eDVBServicePlay::unpause()
1205 if (m_is_paused && m_decoder)
1208 return m_decoder->unfreeze();
1213 RESULT eDVBServicePlay::seekTo(pts_t to)
1215 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1217 if (!m_decode_demux)
1220 ePtr<iDVBPVRChannel> pvr_channel;
1222 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1228 m_cue->seekTo(0, to);
1229 m_dvb_subtitle_pages.clear();
1230 m_subtitle_pages.clear();
1235 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1237 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1239 if (!m_decode_demux)
1242 ePtr<iDVBPVRChannel> pvr_channel;
1244 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1249 /* HACK until we have skip-AP api */
1250 if ((to > 0) && (to < 100))
1258 m_cue->seekTo(mode, to);
1259 m_dvb_subtitle_pages.clear();
1260 m_subtitle_pages.clear();
1264 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1266 ePtr<iDVBPVRChannel> pvr_channel;
1268 if (!m_decode_demux)
1271 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1276 /* if there is a decoder, use audio or video PTS */
1279 r = m_decoder->getPTS(0, pos);
1285 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1288 RESULT eDVBServicePlay::setTrickmode(int trick)
1291 m_decoder->setTrickmode(trick);
1295 RESULT eDVBServicePlay::isCurrentlySeekable()
1297 return m_is_pvr || m_timeshift_active;
1300 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1306 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1312 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1318 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1324 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1330 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1333 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1334 (m_timeshift_enabled || !m_is_pvr))
1336 if (!m_timeshift_enabled)
1338 /* query config path */
1340 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1341 eDebug("could not query ts path from config");
1345 /* we need enough diskspace */
1347 if (statfs(tspath.c_str(), &fs) < 0)
1349 eDebug("statfs failed!");
1353 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1355 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1365 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1376 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1382 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1388 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1394 RESULT eDVBServicePlay::getName(std::string &name)
1398 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1399 return i->getName(m_reference, name);
1403 m_dvb_service->getName(m_reference, name);
1407 else if (!m_reference.name.empty())
1408 eStaticServiceDVBInformation().getName(m_reference, name);
1410 name = "DVB service";
1414 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1416 return m_event_handler.getEvent(evt, nownext);
1419 int eDVBServicePlay::getInfo(int w)
1421 eDVBServicePMTHandler::program program;
1424 return resIsPyObject;
1426 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1428 int no_program_info = 0;
1430 if (h.getProgramInfo(program))
1431 no_program_info = 1;
1437 return m_decoder->getVideoHeight();
1441 return m_decoder->getVideoWidth();
1445 return m_decoder->getVideoFrameRate();
1449 return m_decoder->getVideoProgressive();
1455 aspect = m_decoder->getVideoAspect();
1456 if (no_program_info)
1458 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1460 ePtr<eServiceEvent> evt;
1461 if (!m_event_handler.getEvent(evt, 0))
1463 ePtr<eComponentData> data;
1464 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1466 if ( data->getStreamContent() == 1 )
1468 switch(data->getComponentType())
1471 case 1: // 4:3 SD PAL
1473 case 3: // 16:9 SD PAL
1474 case 4: // > 16:9 PAL
1475 case 5: // 4:3 SD NTSC
1477 case 7: // 16:9 SD NTSC
1478 case 8: // > 16:9 NTSC
1481 case 9: // 4:3 HD PAL
1483 case 0xB: // 16:9 HD PAL
1484 case 0xC: // > 16:9 HD PAL
1485 case 0xD: // 4:3 HD NTSC
1487 case 0xF: // 16:9 HD NTSC
1488 case 0x10: // > 16:9 HD PAL
1489 return data->getComponentType();
1499 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1500 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1501 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1502 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1503 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1504 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1505 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1506 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1507 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1508 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1509 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1510 case sProvider: if (!m_dvb_service) return -1; return -2;
1511 case sServiceref: return resIsString;
1512 case sDVBState: return m_tune_state;
1519 std::string eDVBServicePlay::getInfoString(int w)
1524 if (!m_dvb_service) return "";
1525 return m_dvb_service->m_provider_name;
1527 return m_reference.toString();
1531 return iServiceInformation::getInfoString(w);
1534 PyObject *eDVBServicePlay::getInfoObject(int w)
1539 return m_service_handler.getCaIds();
1540 case sTransponderData:
1541 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1545 return iServiceInformation::getInfoObject(w);
1548 int eDVBServicePlay::getNumberOfTracks()
1550 eDVBServicePMTHandler::program program;
1551 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1552 if (h.getProgramInfo(program))
1554 return program.audioStreams.size();
1557 int eDVBServicePlay::getCurrentTrack()
1559 eDVBServicePMTHandler::program program;
1560 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1561 if (h.getProgramInfo(program))
1564 int max = program.audioStreams.size();
1567 for (i = 0; i < max; ++i)
1568 if (program.audioStreams[i].pid == m_current_audio_pid)
1574 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1576 int ret = selectAudioStream(i);
1578 if (m_decoder->start())
1584 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1586 eDVBServicePMTHandler::program program;
1587 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1589 if (h.getProgramInfo(program))
1592 if (i >= program.audioStreams.size())
1595 info.m_pid = program.audioStreams[i].pid;
1597 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1598 info.m_description = "MPEG";
1599 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1600 info.m_description = "AC3";
1601 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1602 info.m_description = "AAC";
1603 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1604 info.m_description = "DTS";
1606 info.m_description = "???";
1608 if (program.audioStreams[i].component_tag != -1)
1610 ePtr<eServiceEvent> evt;
1611 if (!m_event_handler.getEvent(evt, 0))
1613 ePtr<eComponentData> data;
1614 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1615 info.m_language = data->getText();
1619 if (info.m_language.empty())
1620 info.m_language = program.audioStreams[i].language_code;
1625 int eDVBServicePlay::selectAudioStream(int i)
1627 eDVBServicePMTHandler::program program;
1628 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1630 if (h.getProgramInfo(program))
1633 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1641 stream = program.defaultAudioStream;
1643 int apid = -1, apidtype = -1;
1645 if (((unsigned int)stream) < program.audioStreams.size())
1647 apid = program.audioStreams[stream].pid;
1648 apidtype = program.audioStreams[stream].type;
1651 m_current_audio_pid = apid;
1653 if (m_decoder->setAudioPID(apid, apidtype))
1655 eDebug("set audio pid failed");
1659 /* 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 */
1660 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1663 ePtr<iDVBDemux> data_demux;
1664 if (!h.getDataDemux(data_demux))
1666 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1667 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1671 /* if we decided that we need one, update the pid */
1673 m_rds_decoder->start(apid);
1675 /* store new pid as default only when:
1676 a.) we have an entry in the service db for the current service,
1677 b.) we are not playing back something,
1678 c.) we are not selecting the default entry. (we wouldn't change
1679 anything in the best case, or destroy the default setting in
1680 case the real default is not yet available.)
1682 if (m_dvb_service && !m_is_pvr && ((i != -1)
1683 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1685 if (apidtype == eDVBAudio::aMPEG)
1687 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1688 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1692 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1693 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1697 h.resetCachedProgram();
1702 int eDVBServicePlay::getCurrentChannel()
1704 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1707 RESULT eDVBServicePlay::selectChannel(int i)
1709 if (i < LEFT || i > RIGHT || i == STEREO)
1712 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1714 m_decoder->setAudioChannel(i);
1718 std::string eDVBServicePlay::getText(int x)
1724 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1726 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1731 void eDVBServicePlay::rdsDecoderEvent(int what)
1735 case eDVBRdsDecoder::RadioTextChanged:
1736 m_event((iPlayableService*)this, evUpdatedRadioText);
1738 case eDVBRdsDecoder::RtpTextChanged:
1739 m_event((iPlayableService*)this, evUpdatedRtpText);
1741 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1742 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1744 case eDVBRdsDecoder::RecvRassSlidePic:
1745 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1750 void eDVBServicePlay::showRassSlidePicture()
1756 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1757 if (rass_slide_pic.length())
1758 m_decoder->showSinglePic(rass_slide_pic.c_str());
1760 eDebug("empty filename for rass slide picture received!!");
1763 eDebug("no MPEG Decoder to show iframes avail");
1766 eDebug("showRassSlidePicture called.. but not decoder");
1769 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1775 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1776 if (rass_interactive_pic.length())
1777 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1779 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1782 eDebug("no MPEG Decoder to show iframes avail");
1785 eDebug("showRassInteractivePic called.. but not decoder");
1788 ePyObject eDVBServicePlay::getRassInteractiveMask()
1791 return m_rds_decoder->getRassPictureMask();
1795 int eDVBServiceBase::getFrontendInfo(int w)
1797 eUsePtr<iDVBChannel> channel;
1798 if(m_service_handler.getChannel(channel))
1800 ePtr<iDVBFrontend> fe;
1801 if(channel->getFrontend(fe))
1803 return fe->readFrontendData(w);
1806 PyObject *eDVBServiceBase::getFrontendData()
1808 ePyObject ret = PyDict_New();
1811 eUsePtr<iDVBChannel> channel;
1812 if(!m_service_handler.getChannel(channel))
1814 ePtr<iDVBFrontend> fe;
1815 if(!channel->getFrontend(fe))
1816 fe->getFrontendData(ret);
1824 PyObject *eDVBServiceBase::getFrontendStatus()
1826 ePyObject ret = PyDict_New();
1829 eUsePtr<iDVBChannel> channel;
1830 if(!m_service_handler.getChannel(channel))
1832 ePtr<iDVBFrontend> fe;
1833 if(!channel->getFrontend(fe))
1834 fe->getFrontendStatus(ret);
1842 PyObject *eDVBServiceBase::getTransponderData(bool original)
1844 ePyObject ret = PyDict_New();
1847 eUsePtr<iDVBChannel> channel;
1848 if(!m_service_handler.getChannel(channel))
1850 ePtr<iDVBFrontend> fe;
1851 if(!channel->getFrontend(fe))
1853 fe->getTransponderData(ret, original);
1854 ePtr<iDVBFrontendParameters> feparm;
1855 channel->getCurrentFrontendParameters(feparm);
1858 eDVBFrontendParametersSatellite osat;
1859 if (!feparm->getDVBS(osat))
1861 PutToDict(ret, "orbital_position", osat.orbital_position);
1862 PutToDict(ret, "polarization", osat.polarisation);
1873 PyObject *eDVBServiceBase::getAll(bool original)
1875 ePyObject ret = getTransponderData(original);
1878 eUsePtr<iDVBChannel> channel;
1879 if(!m_service_handler.getChannel(channel))
1881 ePtr<iDVBFrontend> fe;
1882 if(!channel->getFrontend(fe))
1884 fe->getFrontendData(ret);
1885 fe->getFrontendStatus(ret);
1892 int eDVBServicePlay::getNumberOfSubservices()
1894 ePtr<eServiceEvent> evt;
1895 if (!m_event_handler.getEvent(evt, 0))
1896 return evt->getNumOfLinkageServices();
1900 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1902 ePtr<eServiceEvent> evt;
1903 if (!m_event_handler.getEvent(evt, 0))
1905 if (!evt->getLinkageService(sub, m_reference, n))
1908 sub.type=eServiceReference::idInvalid;
1912 RESULT eDVBServicePlay::startTimeshift()
1914 ePtr<iDVBDemux> demux;
1916 eDebug("Start timeshift!");
1918 if (m_timeshift_enabled)
1921 /* start recording with the data demux. */
1922 if (m_service_handler.getDataDemux(demux))
1925 demux->createTSRecorder(m_record);
1930 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1931 eDebug("could not query ts path");
1934 tspath.append("/timeshift.XXXXXX");
1936 templ = new char[tspath.length() + 1];
1937 strcpy(templ, tspath.c_str());
1939 m_timeshift_fd = mkstemp(templ);
1940 m_timeshift_file = std::string(templ);
1942 eDebug("recording to %s", templ);
1946 if (m_timeshift_fd < 0)
1952 m_record->setTargetFD(m_timeshift_fd);
1954 m_timeshift_enabled = 1;
1956 updateTimeshiftPids();
1962 RESULT eDVBServicePlay::stopTimeshift()
1964 if (!m_timeshift_enabled)
1969 m_timeshift_enabled = 0;
1974 close(m_timeshift_fd);
1975 eDebug("remove timeshift file");
1976 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1981 int eDVBServicePlay::isTimeshiftActive()
1983 return m_timeshift_enabled && m_timeshift_active;
1986 RESULT eDVBServicePlay::activateTimeshift()
1988 if (!m_timeshift_enabled)
1991 if (!m_timeshift_active)
1993 switchToTimeshift();
2000 PyObject *eDVBServicePlay::getCutList()
2002 ePyObject list = PyList_New(0);
2004 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2006 ePyObject tuple = PyTuple_New(2);
2007 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2008 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2009 PyList_Append(list, tuple);
2016 void eDVBServicePlay::setCutList(ePyObject list)
2018 if (!PyList_Check(list))
2020 int size = PyList_Size(list);
2023 m_cue_entries.clear();
2025 for (i=0; i<size; ++i)
2027 ePyObject tuple = PyList_GET_ITEM(list, i);
2028 if (!PyTuple_Check(tuple))
2030 eDebug("non-tuple in cutlist");
2033 if (PyTuple_Size(tuple) != 2)
2035 eDebug("cutlist entries need to be a 2-tuple");
2038 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2039 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2041 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2044 pts_t pts = PyLong_AsLongLong(ppts);
2045 int type = PyInt_AsLong(ptype);
2046 m_cue_entries.insert(cueEntry(pts, type));
2047 eDebug("adding %08llx, %d", pts, type);
2049 m_cuesheet_changed = 1;
2051 cutlistToCuesheet();
2052 m_event((iPlayableService*)this, evCuesheetChanged);
2055 void eDVBServicePlay::setCutListEnable(int enable)
2057 m_cutlist_enabled = enable;
2058 cutlistToCuesheet();
2061 void eDVBServicePlay::updateTimeshiftPids()
2066 eDVBServicePMTHandler::program program;
2067 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2069 if (h.getProgramInfo(program))
2073 std::set<int> pids_to_record;
2074 pids_to_record.insert(0); // PAT
2075 if (program.pmtPid != -1)
2076 pids_to_record.insert(program.pmtPid); // PMT
2078 if (program.textPid != -1)
2079 pids_to_record.insert(program.textPid); // Videotext
2081 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2082 i(program.videoStreams.begin());
2083 i != program.videoStreams.end(); ++i)
2084 pids_to_record.insert(i->pid);
2086 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2087 i(program.audioStreams.begin());
2088 i != program.audioStreams.end(); ++i)
2089 pids_to_record.insert(i->pid);
2091 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2092 i(program.subtitleStreams.begin());
2093 i != program.subtitleStreams.end(); ++i)
2094 pids_to_record.insert(i->pid);
2096 std::set<int> new_pids, obsolete_pids;
2098 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2099 m_pids_active.begin(), m_pids_active.end(),
2100 std::inserter(new_pids, new_pids.begin()));
2102 std::set_difference(
2103 m_pids_active.begin(), m_pids_active.end(),
2104 pids_to_record.begin(), pids_to_record.end(),
2105 std::inserter(new_pids, new_pids.begin())
2108 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2109 m_record->addPID(*i);
2111 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2112 m_record->removePID(*i);
2116 void eDVBServicePlay::switchToLive()
2118 if (!m_timeshift_active)
2124 m_teletext_parser = 0;
2126 m_subtitle_parser = 0;
2127 m_new_dvb_subtitle_page_connection = 0;
2128 m_new_subtitle_page_connection = 0;
2129 m_rds_decoder_event_connection = 0;
2130 m_video_event_connection = 0;
2132 /* free the timeshift service handler, we need the resources */
2133 m_service_handler_timeshift.free();
2134 m_timeshift_active = 0;
2136 m_event((iPlayableService*)this, evSeekableStatusChanged);
2141 void eDVBServicePlay::switchToTimeshift()
2143 if (m_timeshift_active)
2148 m_teletext_parser = 0;
2150 m_subtitle_parser = 0;
2151 m_new_subtitle_page_connection = 0;
2152 m_new_dvb_subtitle_page_connection = 0;
2153 m_rds_decoder_event_connection = 0;
2154 m_video_event_connection = 0;
2156 m_timeshift_active = 1;
2158 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2159 r.path = m_timeshift_file;
2161 m_cue = new eCueSheet();
2162 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2164 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2166 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2168 m_event((iPlayableService*)this, evSeekableStatusChanged);
2171 void eDVBServicePlay::updateDecoder()
2173 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2175 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2177 eDVBServicePMTHandler::program program;
2178 if (h.getProgramInfo(program))
2179 eDebug("getting program info failed.");
2182 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2183 if (!program.videoStreams.empty())
2185 eDebugNoNewLine(" (");
2186 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2187 i(program.videoStreams.begin());
2188 i != program.videoStreams.end(); ++i)
2195 if (i != program.videoStreams.begin())
2196 eDebugNoNewLine(", ");
2197 eDebugNoNewLine("%04x", i->pid);
2199 eDebugNoNewLine(")");
2201 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2202 if (!program.audioStreams.empty())
2204 eDebugNoNewLine(" (");
2205 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2206 i(program.audioStreams.begin());
2207 i != program.audioStreams.end(); ++i)
2209 if (i != program.audioStreams.begin())
2210 eDebugNoNewLine(", ");
2211 eDebugNoNewLine("%04x", i->pid);
2213 eDebugNoNewLine(")");
2215 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2216 pcrpid = program.pcrPid;
2217 eDebug(", and the text pid is %04x", program.textPid);
2218 tpid = program.textPid;
2223 h.getDecodeDemux(m_decode_demux);
2226 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2228 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2229 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2230 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2231 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2232 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2235 m_teletext_parser = 0;
2236 m_subtitle_parser = 0;
2240 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2247 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2248 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2249 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2251 else // subservice or recording
2253 eServiceReferenceDVB ref;
2254 m_service_handler.getServiceReference(ref);
2255 eServiceReferenceDVB parent = ref.getParentServiceReference();
2260 ePtr<eDVBResourceManager> res_mgr;
2261 if (!eDVBResourceManager::getInstance(res_mgr))
2263 ePtr<iDVBChannelList> db;
2264 if (!res_mgr->getChannelList(db))
2266 ePtr<eDVBService> origService;
2267 if (!db->getService(parent, origService))
2269 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2270 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2276 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2277 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2279 m_decoder->setVideoPID(vpid, vpidtype);
2280 selectAudioStream();
2282 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2283 m_decoder->setSyncPCR(pcrpid);
2285 m_decoder->setSyncPCR(-1);
2287 m_decoder->setTextPID(tpid);
2289 m_teletext_parser->start(program.textPid);
2292 m_decoder->setTrickmode(1);
2295 m_decoder->preroll();
2299 if (vpid > 0 && vpid < 0x2000)
2303 std::string radio_pic;
2304 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2305 m_decoder->setRadioPic(radio_pic);
2308 m_decoder->setAudioChannel(achannel);
2310 /* don't worry about non-existing services, nor pvr services */
2311 if (m_dvb_service && !m_is_pvr)
2313 /* (audio pid will be set in selectAudioTrack */
2314 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2315 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2316 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2317 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2320 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2323 void eDVBServicePlay::loadCuesheet()
2325 std::string filename = m_reference.path + ".cuts";
2327 m_cue_entries.clear();
2329 FILE *f = fopen(filename.c_str(), "rb");
2333 eDebug("loading cuts..");
2336 unsigned long long where;
2339 if (!fread(&where, sizeof(where), 1, f))
2341 if (!fread(&what, sizeof(what), 1, f))
2344 #if BYTE_ORDER == LITTLE_ENDIAN
2345 where = bswap_64(where);
2352 m_cue_entries.insert(cueEntry(where, what));
2355 eDebug("%d entries", m_cue_entries.size());
2357 eDebug("cutfile not found!");
2359 m_cuesheet_changed = 0;
2360 cutlistToCuesheet();
2361 m_event((iPlayableService*)this, evCuesheetChanged);
2364 void eDVBServicePlay::saveCuesheet()
2366 std::string filename = m_reference.path + ".cuts";
2368 FILE *f = fopen(filename.c_str(), "wb");
2372 unsigned long long where;
2375 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2377 #if BYTE_ORDER == BIG_ENDIAN
2380 where = bswap_64(i->where);
2382 what = htonl(i->what);
2383 fwrite(&where, sizeof(where), 1, f);
2384 fwrite(&what, sizeof(what), 1, f);
2390 m_cuesheet_changed = 0;
2393 void eDVBServicePlay::cutlistToCuesheet()
2397 eDebug("no cue sheet");
2402 if (!m_cutlist_enabled)
2404 m_cue->commitSpans();
2405 eDebug("cutlists were disabled");
2409 pts_t in = 0, out = 0, length = 0;
2413 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2417 if (i == m_cue_entries.end())
2420 if (i->what == 0) /* in */
2424 } else if (i->what == 1) /* out */
2426 else /* mark (2) or last play position (3) */
2443 m_cue->addSourceSpan(in, out);
2447 if (i == m_cue_entries.end())
2450 m_cue->commitSpans();
2453 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2455 if (m_subtitle_widget)
2456 disableSubtitles(parent);
2459 int tuplesize = PyTuple_Size(tuple);
2462 if (!PyTuple_Check(tuple))
2468 entry = PyTuple_GET_ITEM(tuple, 0);
2470 if (!PyInt_Check(entry))
2473 type = PyInt_AsLong(entry);
2475 if (type == 1) // teletext subtitles
2477 int page, magazine, pid;
2481 if (!m_teletext_parser)
2483 eDebug("enable teletext subtitles.. no parser !!!");
2487 entry = PyTuple_GET_ITEM(tuple, 1);
2488 if (!PyInt_Check(entry))
2490 pid = PyInt_AsLong(entry);
2492 entry = PyTuple_GET_ITEM(tuple, 2);
2493 if (!PyInt_Check(entry))
2495 page = PyInt_AsLong(entry);
2497 entry = PyTuple_GET_ITEM(tuple, 3);
2498 if (!PyInt_Check(entry))
2500 magazine = PyInt_AsLong(entry);
2502 m_subtitle_widget = new eSubtitleWidget(parent);
2503 m_subtitle_widget->resize(parent->size()); /* full size */
2504 m_teletext_parser->setPageAndMagazine(page, magazine);
2506 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2510 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2511 if (!m_subtitle_parser)
2513 eDebug("enable dvb subtitles.. no parser !!!");
2519 entry = PyTuple_GET_ITEM(tuple, 1);
2520 if (!PyInt_Check(entry))
2522 pid = PyInt_AsLong(entry);
2524 entry = PyTuple_GET_ITEM(tuple, 2);
2525 if (!PyInt_Check(entry))
2527 composition_page_id = PyInt_AsLong(entry);
2529 entry = PyTuple_GET_ITEM(tuple, 3);
2530 if (!PyInt_Check(entry))
2532 ancillary_page_id = PyInt_AsLong(entry);
2534 m_subtitle_widget = new eSubtitleWidget(parent);
2535 m_subtitle_widget->resize(parent->size()); /* full size */
2536 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2538 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2544 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2545 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2546 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2550 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2552 delete m_subtitle_widget;
2553 m_subtitle_widget = 0;
2554 if (m_subtitle_parser)
2556 m_subtitle_parser->stop();
2557 m_dvb_subtitle_pages.clear();
2559 if (m_teletext_parser)
2561 m_teletext_parser->setPageAndMagazine(-1, -1);
2562 m_subtitle_pages.clear();
2565 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2569 PyObject *eDVBServicePlay::getCachedSubtitle()
2573 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2576 unsigned int data = (unsigned int)tmp;
2577 int pid = (data&0xFFFF0000)>>16;
2578 ePyObject tuple = PyTuple_New(4);
2579 eDVBServicePMTHandler::program program;
2580 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2581 if (!h.getProgramInfo(program))
2583 if (program.textPid==pid) // teletext
2584 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2586 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2587 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2588 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2589 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2597 PyObject *eDVBServicePlay::getSubtitleList()
2599 if (!m_teletext_parser)
2602 ePyObject l = PyList_New(0);
2603 std::set<int> added_ttx_pages;
2605 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2606 m_teletext_parser->m_found_subtitle_pages;
2608 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2609 eDVBServicePMTHandler::program program;
2610 if (h.getProgramInfo(program))
2611 eDebug("getting program info failed.");
2614 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2615 it != program.subtitleStreams.end(); ++it)
2617 switch(it->subtitling_type)
2619 case 0x01: // ebu teletext subtitles
2621 int page_number = it->teletext_page_number & 0xFF;
2622 int magazine_number = it->teletext_magazine_number & 7;
2623 int hash = magazine_number << 8 | page_number;
2624 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2626 ePyObject tuple = PyTuple_New(5);
2627 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2628 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2629 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2630 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2631 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2632 PyList_Append(l, tuple);
2634 added_ttx_pages.insert(hash);
2639 case 0x20 ... 0x23: // dvb subtitles
2641 ePyObject tuple = PyTuple_New(5);
2642 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2643 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2644 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2645 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2646 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2647 PyList_Insert(l, 0, tuple);
2655 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2656 it != subs.end(); ++it)
2658 int page_number = it->teletext_page_number & 0xFF;
2659 int magazine_number = it->teletext_magazine_number & 7;
2660 int hash = magazine_number << 8 | page_number;
2661 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2663 ePyObject tuple = PyTuple_New(5);
2664 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2665 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2666 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2667 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2668 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2669 PyList_Append(l, tuple);
2677 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2679 if (m_subtitle_widget)
2683 m_decoder->getPTS(0, pos);
2684 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2685 m_subtitle_pages.push_back(page);
2686 checkSubtitleTiming();
2690 void eDVBServicePlay::checkSubtitleTiming()
2692 eDebug("checkSubtitleTiming");
2693 if (!m_subtitle_widget)
2697 enum { TELETEXT, DVB } type;
2698 eDVBTeletextSubtitlePage page;
2699 eDVBSubtitlePage dvb_page;
2701 if (!m_subtitle_pages.empty())
2703 page = m_subtitle_pages.front();
2705 show_time = page.m_pts;
2707 else if (!m_dvb_subtitle_pages.empty())
2709 dvb_page = m_dvb_subtitle_pages.front();
2711 show_time = dvb_page.m_show_time;
2719 m_decoder->getPTS(0, pos);
2721 eDebug("%lld %lld", pos, show_time);
2722 int diff = show_time - pos;
2725 eDebug("[late (%d ms)]", -diff / 90);
2728 // if (diff > 900000)
2730 // eDebug("[invalid]");
2736 if (type == TELETEXT)
2738 eDebug("display teletext subtitle page %lld", show_time);
2739 m_subtitle_widget->setPage(page);
2740 m_subtitle_pages.pop_front();
2744 eDebug("display dvb subtitle Page %lld", show_time);
2745 m_subtitle_widget->setPage(dvb_page);
2746 m_dvb_subtitle_pages.pop_front();
2750 eDebug("start subtitle delay %d", diff / 90);
2751 m_subtitle_sync_timer->start(diff / 90, 1);
2757 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2759 if (m_subtitle_widget)
2763 m_decoder->getPTS(0, pos);
2764 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2765 m_dvb_subtitle_pages.push_back(p);
2766 checkSubtitleTiming();
2770 int eDVBServicePlay::getAC3Delay()
2773 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2775 return m_decoder->getAC3Delay();
2780 int eDVBServicePlay::getPCMDelay()
2783 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2785 return m_decoder->getPCMDelay();
2790 void eDVBServicePlay::setAC3Delay(int delay)
2793 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2795 m_decoder->setAC3Delay(delay);
2798 void eDVBServicePlay::setPCMDelay(int delay)
2801 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2803 m_decoder->setPCMDelay(delay);
2806 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2808 switch(event.type) {
2809 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2810 m_event((iPlayableService*)this, evVideoSizeChanged);
2812 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2813 m_event((iPlayableService*)this, evVideoFramerateChanged);
2815 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2816 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2823 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2829 PyObject *eDVBServicePlay::getStreamingData()
2831 eDVBServicePMTHandler::program program;
2832 if (m_service_handler.getProgramInfo(program))
2837 ePyObject r = program.createPythonObject();
2838 ePtr<iDVBDemux> demux;
2839 if (!m_service_handler.getDataDemux(demux))
2842 if (!demux->getCADemuxID(demux_id))
2843 PutToDict(r, "demux", demux_id);
2850 DEFINE_REF(eDVBServicePlay)
2852 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2856 case iServiceInformation::sTransponderData:
2857 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2861 return iStaticServiceInformation::getInfoObject(ref, w);
2864 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");