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()))
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::atAACHE)
1604 info.m_description = "AAC-HE";
1605 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1606 info.m_description = "DTS";
1608 info.m_description = "???";
1610 if (program.audioStreams[i].component_tag != -1)
1612 ePtr<eServiceEvent> evt;
1613 if (!m_event_handler.getEvent(evt, 0))
1615 ePtr<eComponentData> data;
1616 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1617 info.m_language = data->getText();
1621 if (info.m_language.empty())
1622 info.m_language = program.audioStreams[i].language_code;
1627 int eDVBServicePlay::selectAudioStream(int i)
1629 eDVBServicePMTHandler::program program;
1630 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1632 if (h.getProgramInfo(program))
1635 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1643 stream = program.defaultAudioStream;
1645 int apid = -1, apidtype = -1;
1647 if (((unsigned int)stream) < program.audioStreams.size())
1649 apid = program.audioStreams[stream].pid;
1650 apidtype = program.audioStreams[stream].type;
1653 m_current_audio_pid = apid;
1655 if (m_decoder->setAudioPID(apid, apidtype))
1657 eDebug("set audio pid failed");
1661 /* 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 */
1662 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1665 ePtr<iDVBDemux> data_demux;
1666 if (!h.getDataDemux(data_demux))
1668 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1669 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1673 /* if we decided that we need one, update the pid */
1675 m_rds_decoder->start(apid);
1677 /* store new pid as default only when:
1678 a.) we have an entry in the service db for the current service,
1679 b.) we are not playing back something,
1680 c.) we are not selecting the default entry. (we wouldn't change
1681 anything in the best case, or destroy the default setting in
1682 case the real default is not yet available.)
1684 if (m_dvb_service && !m_is_pvr && ((i != -1)
1685 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1687 if (apidtype == eDVBAudio::aMPEG)
1689 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1690 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1694 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1695 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1699 h.resetCachedProgram();
1704 int eDVBServicePlay::getCurrentChannel()
1706 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1709 RESULT eDVBServicePlay::selectChannel(int i)
1711 if (i < LEFT || i > RIGHT || i == STEREO)
1714 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1716 m_decoder->setAudioChannel(i);
1720 std::string eDVBServicePlay::getText(int x)
1726 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1728 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1733 void eDVBServicePlay::rdsDecoderEvent(int what)
1737 case eDVBRdsDecoder::RadioTextChanged:
1738 m_event((iPlayableService*)this, evUpdatedRadioText);
1740 case eDVBRdsDecoder::RtpTextChanged:
1741 m_event((iPlayableService*)this, evUpdatedRtpText);
1743 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1744 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1746 case eDVBRdsDecoder::RecvRassSlidePic:
1747 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1752 void eDVBServicePlay::showRassSlidePicture()
1758 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1759 if (rass_slide_pic.length())
1760 m_decoder->showSinglePic(rass_slide_pic.c_str());
1762 eDebug("empty filename for rass slide picture received!!");
1765 eDebug("no MPEG Decoder to show iframes avail");
1768 eDebug("showRassSlidePicture called.. but not decoder");
1771 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1777 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1778 if (rass_interactive_pic.length())
1779 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1781 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1784 eDebug("no MPEG Decoder to show iframes avail");
1787 eDebug("showRassInteractivePic called.. but not decoder");
1790 ePyObject eDVBServicePlay::getRassInteractiveMask()
1793 return m_rds_decoder->getRassPictureMask();
1797 int eDVBServiceBase::getFrontendInfo(int w)
1799 eUsePtr<iDVBChannel> channel;
1800 if(m_service_handler.getChannel(channel))
1802 ePtr<iDVBFrontend> fe;
1803 if(channel->getFrontend(fe))
1805 return fe->readFrontendData(w);
1808 PyObject *eDVBServiceBase::getFrontendData()
1810 ePyObject ret = PyDict_New();
1813 eUsePtr<iDVBChannel> channel;
1814 if(!m_service_handler.getChannel(channel))
1816 ePtr<iDVBFrontend> fe;
1817 if(!channel->getFrontend(fe))
1818 fe->getFrontendData(ret);
1826 PyObject *eDVBServiceBase::getFrontendStatus()
1828 ePyObject ret = PyDict_New();
1831 eUsePtr<iDVBChannel> channel;
1832 if(!m_service_handler.getChannel(channel))
1834 ePtr<iDVBFrontend> fe;
1835 if(!channel->getFrontend(fe))
1836 fe->getFrontendStatus(ret);
1844 PyObject *eDVBServiceBase::getTransponderData(bool original)
1846 ePyObject ret = PyDict_New();
1849 eUsePtr<iDVBChannel> channel;
1850 if(!m_service_handler.getChannel(channel))
1852 ePtr<iDVBFrontend> fe;
1853 if(!channel->getFrontend(fe))
1855 fe->getTransponderData(ret, original);
1856 ePtr<iDVBFrontendParameters> feparm;
1857 channel->getCurrentFrontendParameters(feparm);
1860 eDVBFrontendParametersSatellite osat;
1861 if (!feparm->getDVBS(osat))
1863 PutToDict(ret, "orbital_position", osat.orbital_position);
1864 PutToDict(ret, "polarization", osat.polarisation);
1875 PyObject *eDVBServiceBase::getAll(bool original)
1877 ePyObject ret = getTransponderData(original);
1880 eUsePtr<iDVBChannel> channel;
1881 if(!m_service_handler.getChannel(channel))
1883 ePtr<iDVBFrontend> fe;
1884 if(!channel->getFrontend(fe))
1886 fe->getFrontendData(ret);
1887 fe->getFrontendStatus(ret);
1894 int eDVBServicePlay::getNumberOfSubservices()
1896 ePtr<eServiceEvent> evt;
1897 if (!m_event_handler.getEvent(evt, 0))
1898 return evt->getNumOfLinkageServices();
1902 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1904 ePtr<eServiceEvent> evt;
1905 if (!m_event_handler.getEvent(evt, 0))
1907 if (!evt->getLinkageService(sub, m_reference, n))
1910 sub.type=eServiceReference::idInvalid;
1914 RESULT eDVBServicePlay::startTimeshift()
1916 ePtr<iDVBDemux> demux;
1918 eDebug("Start timeshift!");
1920 if (m_timeshift_enabled)
1923 /* start recording with the data demux. */
1924 if (m_service_handler.getDataDemux(demux))
1927 demux->createTSRecorder(m_record);
1932 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1933 eDebug("could not query ts path");
1936 tspath.append("/timeshift.XXXXXX");
1938 templ = new char[tspath.length() + 1];
1939 strcpy(templ, tspath.c_str());
1941 m_timeshift_fd = mkstemp(templ);
1942 m_timeshift_file = std::string(templ);
1944 eDebug("recording to %s", templ);
1948 if (m_timeshift_fd < 0)
1954 m_record->setTargetFD(m_timeshift_fd);
1956 m_timeshift_enabled = 1;
1958 updateTimeshiftPids();
1964 RESULT eDVBServicePlay::stopTimeshift()
1966 if (!m_timeshift_enabled)
1971 m_timeshift_enabled = 0;
1976 close(m_timeshift_fd);
1977 eDebug("remove timeshift file");
1978 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1983 int eDVBServicePlay::isTimeshiftActive()
1985 return m_timeshift_enabled && m_timeshift_active;
1988 RESULT eDVBServicePlay::activateTimeshift()
1990 if (!m_timeshift_enabled)
1993 if (!m_timeshift_active)
1995 switchToTimeshift();
2002 PyObject *eDVBServicePlay::getCutList()
2004 ePyObject list = PyList_New(0);
2006 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2008 ePyObject tuple = PyTuple_New(2);
2009 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2010 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2011 PyList_Append(list, tuple);
2018 void eDVBServicePlay::setCutList(ePyObject list)
2020 if (!PyList_Check(list))
2022 int size = PyList_Size(list);
2025 m_cue_entries.clear();
2027 for (i=0; i<size; ++i)
2029 ePyObject tuple = PyList_GET_ITEM(list, i);
2030 if (!PyTuple_Check(tuple))
2032 eDebug("non-tuple in cutlist");
2035 if (PyTuple_Size(tuple) != 2)
2037 eDebug("cutlist entries need to be a 2-tuple");
2040 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2041 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2043 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2046 pts_t pts = PyLong_AsLongLong(ppts);
2047 int type = PyInt_AsLong(ptype);
2048 m_cue_entries.insert(cueEntry(pts, type));
2049 eDebug("adding %08llx, %d", pts, type);
2051 m_cuesheet_changed = 1;
2053 cutlistToCuesheet();
2054 m_event((iPlayableService*)this, evCuesheetChanged);
2057 void eDVBServicePlay::setCutListEnable(int enable)
2059 m_cutlist_enabled = enable;
2060 cutlistToCuesheet();
2063 void eDVBServicePlay::updateTimeshiftPids()
2068 eDVBServicePMTHandler::program program;
2069 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2071 if (h.getProgramInfo(program))
2075 std::set<int> pids_to_record;
2076 pids_to_record.insert(0); // PAT
2077 if (program.pmtPid != -1)
2078 pids_to_record.insert(program.pmtPid); // PMT
2080 if (program.textPid != -1)
2081 pids_to_record.insert(program.textPid); // Videotext
2083 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2084 i(program.videoStreams.begin());
2085 i != program.videoStreams.end(); ++i)
2086 pids_to_record.insert(i->pid);
2088 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2089 i(program.audioStreams.begin());
2090 i != program.audioStreams.end(); ++i)
2091 pids_to_record.insert(i->pid);
2093 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2094 i(program.subtitleStreams.begin());
2095 i != program.subtitleStreams.end(); ++i)
2096 pids_to_record.insert(i->pid);
2098 std::set<int> new_pids, obsolete_pids;
2100 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2101 m_pids_active.begin(), m_pids_active.end(),
2102 std::inserter(new_pids, new_pids.begin()));
2104 std::set_difference(
2105 m_pids_active.begin(), m_pids_active.end(),
2106 pids_to_record.begin(), pids_to_record.end(),
2107 std::inserter(new_pids, new_pids.begin())
2110 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2111 m_record->addPID(*i);
2113 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2114 m_record->removePID(*i);
2118 void eDVBServicePlay::switchToLive()
2120 if (!m_timeshift_active)
2126 m_teletext_parser = 0;
2128 m_subtitle_parser = 0;
2129 m_new_dvb_subtitle_page_connection = 0;
2130 m_new_subtitle_page_connection = 0;
2131 m_rds_decoder_event_connection = 0;
2132 m_video_event_connection = 0;
2134 /* free the timeshift service handler, we need the resources */
2135 m_service_handler_timeshift.free();
2136 m_timeshift_active = 0;
2138 m_event((iPlayableService*)this, evSeekableStatusChanged);
2143 void eDVBServicePlay::switchToTimeshift()
2145 if (m_timeshift_active)
2150 m_teletext_parser = 0;
2152 m_subtitle_parser = 0;
2153 m_new_subtitle_page_connection = 0;
2154 m_new_dvb_subtitle_page_connection = 0;
2155 m_rds_decoder_event_connection = 0;
2156 m_video_event_connection = 0;
2158 m_timeshift_active = 1;
2160 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2161 r.path = m_timeshift_file;
2163 m_cue = new eCueSheet();
2164 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2166 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2168 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2170 m_event((iPlayableService*)this, evSeekableStatusChanged);
2173 void eDVBServicePlay::updateDecoder()
2175 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2177 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2179 eDVBServicePMTHandler::program program;
2180 if (h.getProgramInfo(program))
2181 eDebug("getting program info failed.");
2184 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2185 if (!program.videoStreams.empty())
2187 eDebugNoNewLine(" (");
2188 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2189 i(program.videoStreams.begin());
2190 i != program.videoStreams.end(); ++i)
2197 if (i != program.videoStreams.begin())
2198 eDebugNoNewLine(", ");
2199 eDebugNoNewLine("%04x", i->pid);
2201 eDebugNoNewLine(")");
2203 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2204 if (!program.audioStreams.empty())
2206 eDebugNoNewLine(" (");
2207 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2208 i(program.audioStreams.begin());
2209 i != program.audioStreams.end(); ++i)
2211 if (i != program.audioStreams.begin())
2212 eDebugNoNewLine(", ");
2213 eDebugNoNewLine("%04x", i->pid);
2215 eDebugNoNewLine(")");
2217 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2218 pcrpid = program.pcrPid;
2219 eDebug(", and the text pid is %04x", program.textPid);
2220 tpid = program.textPid;
2225 h.getDecodeDemux(m_decode_demux);
2228 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2230 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2231 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2232 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2233 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2234 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2237 m_teletext_parser = 0;
2238 m_subtitle_parser = 0;
2242 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2249 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2250 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2251 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2253 else // subservice or recording
2255 eServiceReferenceDVB ref;
2256 m_service_handler.getServiceReference(ref);
2257 eServiceReferenceDVB parent = ref.getParentServiceReference();
2262 ePtr<eDVBResourceManager> res_mgr;
2263 if (!eDVBResourceManager::getInstance(res_mgr))
2265 ePtr<iDVBChannelList> db;
2266 if (!res_mgr->getChannelList(db))
2268 ePtr<eDVBService> origService;
2269 if (!db->getService(parent, origService))
2271 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2272 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2278 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2279 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2281 m_decoder->setVideoPID(vpid, vpidtype);
2282 selectAudioStream();
2284 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2285 m_decoder->setSyncPCR(pcrpid);
2287 m_decoder->setSyncPCR(-1);
2289 m_decoder->setTextPID(tpid);
2291 m_teletext_parser->start(program.textPid);
2294 m_decoder->setTrickmode(1);
2297 m_decoder->preroll();
2301 if (vpid > 0 && vpid < 0x2000)
2305 std::string radio_pic;
2306 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2307 m_decoder->setRadioPic(radio_pic);
2310 m_decoder->setAudioChannel(achannel);
2312 /* don't worry about non-existing services, nor pvr services */
2313 if (m_dvb_service && !m_is_pvr)
2315 /* (audio pid will be set in selectAudioTrack */
2316 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2317 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2318 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2319 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2322 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2325 void eDVBServicePlay::loadCuesheet()
2327 std::string filename = m_reference.path + ".cuts";
2329 m_cue_entries.clear();
2331 FILE *f = fopen(filename.c_str(), "rb");
2335 eDebug("loading cuts..");
2338 unsigned long long where;
2341 if (!fread(&where, sizeof(where), 1, f))
2343 if (!fread(&what, sizeof(what), 1, f))
2346 #if BYTE_ORDER == LITTLE_ENDIAN
2347 where = bswap_64(where);
2354 m_cue_entries.insert(cueEntry(where, what));
2357 eDebug("%d entries", m_cue_entries.size());
2359 eDebug("cutfile not found!");
2361 m_cuesheet_changed = 0;
2362 cutlistToCuesheet();
2363 m_event((iPlayableService*)this, evCuesheetChanged);
2366 void eDVBServicePlay::saveCuesheet()
2368 std::string filename = m_reference.path + ".cuts";
2370 FILE *f = fopen(filename.c_str(), "wb");
2374 unsigned long long where;
2377 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2379 #if BYTE_ORDER == BIG_ENDIAN
2382 where = bswap_64(i->where);
2384 what = htonl(i->what);
2385 fwrite(&where, sizeof(where), 1, f);
2386 fwrite(&what, sizeof(what), 1, f);
2392 m_cuesheet_changed = 0;
2395 void eDVBServicePlay::cutlistToCuesheet()
2399 eDebug("no cue sheet");
2404 if (!m_cutlist_enabled)
2406 m_cue->commitSpans();
2407 eDebug("cutlists were disabled");
2411 pts_t in = 0, out = 0, length = 0;
2415 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2419 if (i == m_cue_entries.end())
2422 if (i->what == 0) /* in */
2426 } else if (i->what == 1) /* out */
2428 else /* mark (2) or last play position (3) */
2445 m_cue->addSourceSpan(in, out);
2449 if (i == m_cue_entries.end())
2452 m_cue->commitSpans();
2455 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2457 if (m_subtitle_widget)
2458 disableSubtitles(parent);
2461 int tuplesize = PyTuple_Size(tuple);
2464 if (!PyTuple_Check(tuple))
2470 entry = PyTuple_GET_ITEM(tuple, 0);
2472 if (!PyInt_Check(entry))
2475 type = PyInt_AsLong(entry);
2477 if (type == 1) // teletext subtitles
2479 int page, magazine, pid;
2483 if (!m_teletext_parser)
2485 eDebug("enable teletext subtitles.. no parser !!!");
2489 entry = PyTuple_GET_ITEM(tuple, 1);
2490 if (!PyInt_Check(entry))
2492 pid = PyInt_AsLong(entry);
2494 entry = PyTuple_GET_ITEM(tuple, 2);
2495 if (!PyInt_Check(entry))
2497 page = PyInt_AsLong(entry);
2499 entry = PyTuple_GET_ITEM(tuple, 3);
2500 if (!PyInt_Check(entry))
2502 magazine = PyInt_AsLong(entry);
2504 m_subtitle_widget = new eSubtitleWidget(parent);
2505 m_subtitle_widget->resize(parent->size()); /* full size */
2506 m_teletext_parser->setPageAndMagazine(page, magazine);
2508 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2512 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2513 if (!m_subtitle_parser)
2515 eDebug("enable dvb subtitles.. no parser !!!");
2521 entry = PyTuple_GET_ITEM(tuple, 1);
2522 if (!PyInt_Check(entry))
2524 pid = PyInt_AsLong(entry);
2526 entry = PyTuple_GET_ITEM(tuple, 2);
2527 if (!PyInt_Check(entry))
2529 composition_page_id = PyInt_AsLong(entry);
2531 entry = PyTuple_GET_ITEM(tuple, 3);
2532 if (!PyInt_Check(entry))
2534 ancillary_page_id = PyInt_AsLong(entry);
2536 m_subtitle_widget = new eSubtitleWidget(parent);
2537 m_subtitle_widget->resize(parent->size()); /* full size */
2538 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2540 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2546 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2547 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2548 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2552 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2554 delete m_subtitle_widget;
2555 m_subtitle_widget = 0;
2556 if (m_subtitle_parser)
2558 m_subtitle_parser->stop();
2559 m_dvb_subtitle_pages.clear();
2561 if (m_teletext_parser)
2563 m_teletext_parser->setPageAndMagazine(-1, -1);
2564 m_subtitle_pages.clear();
2567 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2571 PyObject *eDVBServicePlay::getCachedSubtitle()
2575 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2578 unsigned int data = (unsigned int)tmp;
2579 int pid = (data&0xFFFF0000)>>16;
2580 ePyObject tuple = PyTuple_New(4);
2581 eDVBServicePMTHandler::program program;
2582 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2583 if (!h.getProgramInfo(program))
2585 if (program.textPid==pid) // teletext
2586 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2588 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2589 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2590 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2591 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2599 PyObject *eDVBServicePlay::getSubtitleList()
2601 if (!m_teletext_parser)
2604 ePyObject l = PyList_New(0);
2605 std::set<int> added_ttx_pages;
2607 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2608 m_teletext_parser->m_found_subtitle_pages;
2610 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2611 eDVBServicePMTHandler::program program;
2612 if (h.getProgramInfo(program))
2613 eDebug("getting program info failed.");
2616 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2617 it != program.subtitleStreams.end(); ++it)
2619 switch(it->subtitling_type)
2621 case 0x01: // ebu teletext subtitles
2623 int page_number = it->teletext_page_number & 0xFF;
2624 int magazine_number = it->teletext_magazine_number & 7;
2625 int hash = magazine_number << 8 | page_number;
2626 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2628 ePyObject tuple = PyTuple_New(5);
2629 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2630 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2631 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2632 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2633 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2634 PyList_Append(l, tuple);
2636 added_ttx_pages.insert(hash);
2641 case 0x20 ... 0x23: // dvb subtitles
2643 ePyObject tuple = PyTuple_New(5);
2644 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2645 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2646 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2647 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2648 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2649 PyList_Insert(l, 0, tuple);
2657 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2658 it != subs.end(); ++it)
2660 int page_number = it->teletext_page_number & 0xFF;
2661 int magazine_number = it->teletext_magazine_number & 7;
2662 int hash = magazine_number << 8 | page_number;
2663 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2665 ePyObject tuple = PyTuple_New(5);
2666 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2667 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2668 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2669 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2670 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2671 PyList_Append(l, tuple);
2679 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2681 if (m_subtitle_widget)
2685 m_decoder->getPTS(0, pos);
2686 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2687 m_subtitle_pages.push_back(page);
2688 checkSubtitleTiming();
2692 void eDVBServicePlay::checkSubtitleTiming()
2694 eDebug("checkSubtitleTiming");
2695 if (!m_subtitle_widget)
2699 enum { TELETEXT, DVB } type;
2700 eDVBTeletextSubtitlePage page;
2701 eDVBSubtitlePage dvb_page;
2703 if (!m_subtitle_pages.empty())
2705 page = m_subtitle_pages.front();
2707 show_time = page.m_pts;
2709 else if (!m_dvb_subtitle_pages.empty())
2711 dvb_page = m_dvb_subtitle_pages.front();
2713 show_time = dvb_page.m_show_time;
2721 m_decoder->getPTS(0, pos);
2723 eDebug("%lld %lld", pos, show_time);
2724 int diff = show_time - pos;
2727 eDebug("[late (%d ms)]", -diff / 90);
2730 // if (diff > 900000)
2732 // eDebug("[invalid]");
2738 if (type == TELETEXT)
2740 eDebug("display teletext subtitle page %lld", show_time);
2741 m_subtitle_widget->setPage(page);
2742 m_subtitle_pages.pop_front();
2746 eDebug("display dvb subtitle Page %lld", show_time);
2747 m_subtitle_widget->setPage(dvb_page);
2748 m_dvb_subtitle_pages.pop_front();
2752 eDebug("start subtitle delay %d", diff / 90);
2753 m_subtitle_sync_timer->start(diff / 90, 1);
2759 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2761 if (m_subtitle_widget)
2765 m_decoder->getPTS(0, pos);
2766 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2767 m_dvb_subtitle_pages.push_back(p);
2768 checkSubtitleTiming();
2772 int eDVBServicePlay::getAC3Delay()
2775 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2777 return m_decoder->getAC3Delay();
2782 int eDVBServicePlay::getPCMDelay()
2785 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2787 return m_decoder->getPCMDelay();
2792 void eDVBServicePlay::setAC3Delay(int delay)
2795 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2797 m_decoder->setAC3Delay(delay);
2800 void eDVBServicePlay::setPCMDelay(int delay)
2803 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2805 m_decoder->setPCMDelay(delay);
2808 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2810 switch(event.type) {
2811 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2812 m_event((iPlayableService*)this, evVideoSizeChanged);
2814 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2815 m_event((iPlayableService*)this, evVideoFramerateChanged);
2817 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2818 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2825 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2831 PyObject *eDVBServicePlay::getStreamingData()
2833 eDVBServicePMTHandler::program program;
2834 if (m_service_handler.getProgramInfo(program))
2839 ePyObject r = program.createPythonObject();
2840 ePtr<iDVBDemux> demux;
2841 if (!m_service_handler.getDataDemux(demux))
2844 if (!demux->getCADemuxID(demux_id))
2845 PutToDict(r, "demux", demux_id);
2852 DEFINE_REF(eDVBServicePlay)
2854 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2858 case iServiceInformation::sTransponderData:
2859 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2863 return iStaticServiceInformation::getInfoObject(ref, w);
2866 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");