1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
101 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
103 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
105 PutToDict(dict, "tuner_type", "DVB-S");
106 PutToDict(dict, "frequency", feparm.frequency);
107 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
108 PutToDict(dict, "orbital_position", feparm.orbital_position);
109 PutToDict(dict, "inversion", feparm.inversion);
110 PutToDict(dict, "fec_inner", feparm.fec);
111 PutToDict(dict, "modulation", feparm.modulation);
112 PutToDict(dict, "polarization", feparm.polarisation);
113 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
115 PutToDict(dict, "rolloff", feparm.rolloff);
116 PutToDict(dict, "pilot", feparm.pilot);
118 PutToDict(dict, "system", feparm.system);
121 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
123 PutToDict(dict, "tuner_type", "DVB-T");
124 PutToDict(dict, "frequency", feparm.frequency);
125 PutToDict(dict, "bandwidth", feparm.bandwidth);
126 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
127 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
128 PutToDict(dict, "constellation", feparm.modulation);
129 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
130 PutToDict(dict, "guard_interval", feparm.guard_interval);
131 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
132 PutToDict(dict, "inversion", feparm.inversion);
135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
137 PutToDict(dict, "tuner_type", "DVB-C");
138 PutToDict(dict, "frequency", feparm.frequency);
139 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
140 PutToDict(dict, "modulation", feparm.modulation);
141 PutToDict(dict, "inversion", feparm.inversion);
142 PutToDict(dict, "fec_inner", feparm.fec_inner);
145 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
147 if (r.type == eServiceReference::idDVB)
149 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
152 case iServiceInformation::sTransponderData:
154 ePtr<eDVBResourceManager> res;
155 if (!eDVBResourceManager::getInstance(res))
157 ePtr<iDVBChannelList> db;
158 if (!res->getChannelList(db))
161 ref.getChannelID(chid);
162 ePtr<iDVBFrontendParameters> feparm;
163 if (!db->getChannelFrontendData(chid, feparm))
166 if (!feparm->getSystem(system))
168 ePyObject dict = PyDict_New();
171 case iDVBFrontend::feSatellite:
173 eDVBFrontendParametersSatellite s;
175 PutSatelliteDataToDict(dict, s);
178 case iDVBFrontend::feTerrestrial:
180 eDVBFrontendParametersTerrestrial t;
182 PutTerrestrialDataToDict(dict, t);
185 case iDVBFrontend::feCable:
187 eDVBFrontendParametersCable c;
189 PutCableDataToDict(dict, c);
193 eDebug("unknown frontend type %d", system);
208 DEFINE_REF(eStaticServiceDVBBouquetInformation);
210 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
212 ePtr<iDVBChannelList> db;
213 ePtr<eDVBResourceManager> res;
216 if ((err = eDVBResourceManager::getInstance(res)) != 0)
218 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
221 if ((err = res->getChannelList(db)) != 0)
223 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
228 if ((err = db->getBouquet(ref, bouquet)) != 0)
230 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
234 if ( bouquet && bouquet->m_bouquet_name.length() )
236 name = bouquet->m_bouquet_name;
243 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
245 if (ref.flags & eServiceReference::isGroup)
247 ePtr<iDVBChannelList> db;
248 ePtr<eDVBResourceManager> res;
250 if (eDVBResourceManager::getInstance(res))
252 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
256 if (res->getChannelList(db))
258 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
263 if (db->getBouquet(ref, bouquet))
265 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
269 int prio_order = eDVBFrontend::getTypePriorityOrder();
271 eDVBChannelID chid, chid_ignore;
272 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
273 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
275 static unsigned char prio_map[6][3] = {
276 { 3, 2, 1 }, // -S -C -T
277 { 3, 1, 2 }, // -S -T -C
278 { 2, 3, 1 }, // -C -S -T
279 { 1, 3, 2 }, // -C -T -S
280 { 1, 2, 3 }, // -T -C -S
281 { 2, 1, 3 } // -T -S -C
283 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
284 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
289 case 30000: // cached DVB-T channel
290 case 1: // DVB-T frontend
291 tmp = prio_map[prio_order][2];
293 case 40000: // cached DVB-C channel
295 tmp = prio_map[prio_order][1];
298 tmp = prio_map[prio_order][0];
303 m_playable_service = *it;
310 m_playable_service = eServiceReference();
314 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
319 #include <lib/dvb/epgcache.h>
321 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
323 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
326 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
328 DECLARE_REF(eStaticServiceDVBPVRInformation);
329 eServiceReference m_ref;
330 eDVBMetaParser m_parser;
332 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
333 RESULT getName(const eServiceReference &ref, std::string &name);
334 int getLength(const eServiceReference &ref);
335 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
336 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
337 int getInfo(const eServiceReference &ref, int w);
338 std::string getInfoString(const eServiceReference &ref,int w);
341 DEFINE_REF(eStaticServiceDVBPVRInformation);
343 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
346 m_parser.parseFile(ref.path);
349 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
351 ASSERT(ref == m_ref);
352 if (m_parser.m_name.size())
353 name = m_parser.m_name;
357 size_t n = name.rfind('/');
358 if (n != std::string::npos)
359 name = name.substr(n + 1);
364 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
366 ASSERT(ref == m_ref);
371 stat(ref.path.c_str(), &s);
373 if (tstools.openFile(ref.path.c_str(), 1))
376 /* check if cached data is still valid */
377 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
378 return m_parser.m_length / 90000;
380 /* open again, this time with stream info */
381 if (tstools.openFile(ref.path.c_str()))
384 /* otherwise, re-calc length and update meta file */
386 if (tstools.calcLen(len))
389 m_parser.m_length = len;
390 m_parser.m_filesize = s.st_size;
391 m_parser.updateMeta(ref.path);
392 return m_parser.m_length / 90000;
395 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
399 case iServiceInformation::sDescription:
400 return iServiceInformation::resIsString;
401 case iServiceInformation::sServiceref:
402 return iServiceInformation::resIsString;
403 case iServiceInformation::sTimeCreate:
404 if (m_parser.m_time_create)
405 return m_parser.m_time_create;
407 return iServiceInformation::resNA;
409 return iServiceInformation::resNA;
413 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
417 case iServiceInformation::sDescription:
418 return m_parser.m_description;
419 case iServiceInformation::sServiceref:
420 return m_parser.m_ref.toString();
421 case iServiceInformation::sTags:
422 return m_parser.m_tags;
428 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
430 if (!ref.path.empty())
432 ePtr<eServiceEvent> event = new eServiceEvent;
433 std::string filename = ref.path;
434 filename.erase(filename.length()-2, 2);
436 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
446 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
448 DECLARE_REF(eDVBPVRServiceOfflineOperations);
449 eServiceReferenceDVB m_ref;
451 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
453 RESULT deleteFromDisk(int simulate);
454 RESULT getListOfFilenames(std::list<std::string> &);
457 DEFINE_REF(eDVBPVRServiceOfflineOperations);
459 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
463 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
469 std::list<std::string> res;
470 if (getListOfFilenames(res))
473 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
475 eDebug("FATAL !! can't get background file eraser");
477 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
479 eDebug("Removing %s...", i->c_str());
481 eraser->erase(i->c_str());
483 ::unlink(i->c_str());
490 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
493 res.push_back(m_ref.path);
495 // handling for old splitted recordings (enigma 1)
500 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
502 if (stat(buf, &s) < 0)
507 res.push_back(m_ref.path + ".meta");
508 res.push_back(m_ref.path + ".ap");
509 res.push_back(m_ref.path + ".cuts");
510 std::string tmp = m_ref.path;
511 tmp.erase(m_ref.path.length()-3);
512 res.push_back(tmp + ".eit");
516 DEFINE_REF(eServiceFactoryDVB)
518 eServiceFactoryDVB::eServiceFactoryDVB()
520 ePtr<eServiceCenter> sc;
522 eServiceCenter::getPrivInstance(sc);
525 std::list<std::string> extensions;
526 extensions.push_back("ts");
527 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
530 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
531 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
534 eServiceFactoryDVB::~eServiceFactoryDVB()
536 ePtr<eServiceCenter> sc;
538 eServiceCenter::getPrivInstance(sc);
540 sc->removeServiceFactory(eServiceFactoryDVB::id);
543 DEFINE_REF(eDVBServiceList);
545 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
549 eDVBServiceList::~eDVBServiceList()
553 RESULT eDVBServiceList::startQuery()
555 ePtr<iDVBChannelList> db;
556 ePtr<eDVBResourceManager> res;
559 if ((err = eDVBResourceManager::getInstance(res)) != 0)
561 eDebug("no resource manager");
564 if ((err = res->getChannelList(db)) != 0)
566 eDebug("no channel list");
570 ePtr<eDVBChannelQuery> q;
572 if (!m_parent.path.empty())
574 eDVBChannelQuery::compile(q, m_parent.path);
577 eDebug("compile query failed");
582 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
584 eDebug("startQuery failed");
591 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
593 eServiceReferenceDVB ref;
598 while (!m_query->getNextResult(ref))
602 list.sort(iListableServiceCompare(this));
607 // The first argument of this function is a format string to specify the order and
608 // the content of the returned list
609 // useable format options are
610 // R = Service Reference (as swig object .. this is very slow)
611 // S = Service Reference (as python string object .. same as ref.toString())
612 // C = Service Reference (as python string object .. same as ref.toCompareString())
613 // N = Service Name (as python string object)
614 // n = Short Service Name (short name brakets used) (as python string object)
615 // when exactly one return value per service is selected in the format string,
616 // then each value is directly a list entry
617 // when more than one value is returned per service, then the list is a list of
619 // unknown format string chars are returned as python None values !
620 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
623 std::list<eServiceReference> tmplist;
626 if (!format || !(retcount=strlen(format)))
627 format = "R"; // just return service reference swig object ...
629 if (!getContent(tmplist, sorted))
631 int services=tmplist.size();
632 ePtr<iStaticServiceInformation> sptr;
633 eServiceCenterPtr service_center;
635 if (strchr(format, 'N') || strchr(format, 'n'))
636 eServiceCenter::getPrivInstance(service_center);
638 ret = PyList_New(services);
639 std::list<eServiceReference>::iterator it(tmplist.begin());
641 for (int cnt=0; cnt < services; ++cnt)
643 eServiceReference &ref=*it++;
644 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
645 for (int i=0; i < retcount; ++i)
650 case 'R': // service reference (swig)object
651 tmp = NEW_eServiceReference(ref);
653 case 'C': // service reference compare string
654 tmp = PyString_FromString(ref.toCompareString().c_str());
656 case 'S': // service reference string
657 tmp = PyString_FromString(ref.toString().c_str());
659 case 'N': // service name
662 service_center->info(ref, sptr);
666 sptr->getName(ref, name);
668 // filter short name brakets
670 while((pos = name.find("\xc2\x86")) != std::string::npos)
672 while((pos = name.find("\xc2\x87")) != std::string::npos)
676 tmp = PyString_FromString(name.c_str());
680 tmp = PyString_FromString("<n/a>");
682 case 'n': // short service name
685 service_center->info(ref, sptr);
689 sptr->getName(ref, name);
690 name = buildShortName(name);
692 tmp = PyString_FromString(name.c_str());
696 tmp = PyString_FromString("<n/a>");
709 PyTuple_SET_ITEM(tuple, i, tmp);
711 PyList_SET_ITEM(ret, cnt, tmp);
715 PyList_SET_ITEM(ret, cnt, tuple);
718 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
721 RESULT eDVBServiceList::getNext(eServiceReference &ref)
726 return m_query->getNextResult((eServiceReferenceDVB&)ref);
729 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
731 if (m_parent.flags & eServiceReference::canDescent) // bouquet
733 ePtr<iDVBChannelList> db;
734 ePtr<eDVBResourceManager> resm;
736 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
739 if (db->getBouquet(m_parent, m_bouquet) != 0)
750 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
754 return m_bouquet->addService(ref, before);
757 RESULT eDVBServiceList::removeService(eServiceReference &ref)
761 return m_bouquet->removeService(ref);
764 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
768 return m_bouquet->moveService(ref, pos);
771 RESULT eDVBServiceList::flushChanges()
775 return m_bouquet->flushChanges();
778 RESULT eDVBServiceList::setListName(const std::string &name)
782 return m_bouquet->setListName(name);
785 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
787 ePtr<eDVBService> service;
788 int r = lookupService(service, ref);
791 // check resources...
792 ptr = new eDVBServicePlay(ref, service);
796 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
798 if (ref.path.empty())
800 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
809 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
811 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
812 if (list->startQuery())
822 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
824 /* is a listable service? */
825 if (ref.flags & eServiceReference::canDescent) // bouquet
827 if ( !ref.name.empty() ) // satellites or providers list
828 ptr = m_StaticServiceDVBInfo;
829 else // a dvb bouquet
830 ptr = m_StaticServiceDVBBouquetInfo;
832 else if (!ref.path.empty()) /* do we have a PVR service? */
833 ptr = new eStaticServiceDVBPVRInformation(ref);
834 else // normal dvb service
836 ePtr<eDVBService> service;
837 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
838 ptr = m_StaticServiceDVBInfo;
840 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
846 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
848 if (ref.path.empty())
854 ptr = new eDVBPVRServiceOfflineOperations(ref);
859 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
861 // TODO: handle the listing itself
862 // if (ref.... == -1) .. return "... bouquets ...";
863 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
865 ePtr<iDVBChannelList> db;
866 ePtr<eDVBResourceManager> res;
869 if ((err = eDVBResourceManager::getInstance(res)) != 0)
871 eDebug("no resource manager");
874 if ((err = res->getChannelList(db)) != 0)
876 eDebug("no channel list");
880 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
881 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
883 eDebug("getService failed!");
890 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
891 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
894 m_is_pvr = !m_reference.path.empty();
896 m_timeshift_enabled = m_timeshift_active = 0;
899 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
900 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
901 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
903 m_cuesheet_changed = 0;
904 m_cutlist_enabled = 1;
906 m_subtitle_widget = 0;
910 m_subtitle_sync_timer = eTimer::create(eApp);
912 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
915 eDVBServicePlay::~eDVBServicePlay()
917 delete m_subtitle_widget;
920 void eDVBServicePlay::gotNewEvent()
924 ePtr<eServiceEvent> m_event_now, m_event_next;
925 getEvent(m_event_now, 0);
926 getEvent(m_event_next, 1);
929 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
931 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
933 m_event((iPlayableService*)this, evUpdatedEventInfo);
936 void eDVBServicePlay::serviceEvent(int event)
938 m_tune_state = event;
942 case eDVBServicePMTHandler::eventTuned:
944 ePtr<iDVBDemux> m_demux;
945 if (!m_service_handler.getDataDemux(m_demux))
947 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
948 int sid = ref.getParentServiceID().get();
950 sid = ref.getServiceID().get();
951 if ( ref.getParentTransportStreamID().get() &&
952 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
953 m_event_handler.startOther(m_demux, sid);
955 m_event_handler.start(m_demux, sid);
957 m_event((iPlayableService*)this, evTunedIn);
960 case eDVBServicePMTHandler::eventNoResources:
961 case eDVBServicePMTHandler::eventNoPAT:
962 case eDVBServicePMTHandler::eventNoPATEntry:
963 case eDVBServicePMTHandler::eventNoPMT:
964 case eDVBServicePMTHandler::eventTuneFailed:
965 case eDVBServicePMTHandler::eventMisconfiguration:
967 eDebug("DVB service failed to tune - error %d", event);
968 m_event((iPlayableService*)this, evTuneFailed);
971 case eDVBServicePMTHandler::eventNewProgramInfo:
973 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
974 if (m_timeshift_enabled)
975 updateTimeshiftPids();
976 if (!m_timeshift_active)
978 if (m_first_program_info && m_is_pvr)
980 m_first_program_info = 0;
983 m_event((iPlayableService*)this, evUpdatedInfo);
986 case eDVBServicePMTHandler::eventEOF:
987 m_event((iPlayableService*)this, evEOF);
989 case eDVBServicePMTHandler::eventSOF:
990 m_event((iPlayableService*)this, evSOF);
995 void eDVBServicePlay::serviceEventTimeshift(int event)
999 case eDVBServicePMTHandler::eventNewProgramInfo:
1000 if (m_timeshift_active)
1003 case eDVBServicePMTHandler::eventSOF:
1004 m_event((iPlayableService*)this, evSOF);
1006 case eDVBServicePMTHandler::eventEOF:
1007 if ((!m_is_paused) && (m_skipmode >= 0))
1013 RESULT eDVBServicePlay::start()
1016 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1017 two (one for decoding, one for data source), as we must be prepared
1018 to start recording from the data demux. */
1020 m_cue = new eCueSheet();
1022 m_event(this, evStart);
1024 m_first_program_info = 1;
1025 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1026 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1028 /* inject EIT if there is a stored one */
1031 std::string filename = service.path;
1032 filename.erase(filename.length()-2, 2);
1034 ePtr<eServiceEvent> event = new eServiceEvent;
1035 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1037 ePtr<eServiceEvent> empty;
1038 m_event_handler.inject(event, 0);
1039 m_event_handler.inject(empty, 1);
1046 m_event(this, evStart);
1051 RESULT eDVBServicePlay::stop()
1053 /* add bookmark for last play position */
1056 pts_t play_position, length;
1057 if (!getPlayPosition(play_position))
1059 /* remove last position */
1060 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1062 if (i->what == 3) /* current play position */
1064 m_cue_entries.erase(i);
1065 i = m_cue_entries.begin();
1071 if (getLength(length))
1076 int perc = play_position * 100LL / length;
1078 /* only store last play position when between 1% and 99% */
1079 if ((1 < perc) && (perc < 99))
1080 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1082 m_cuesheet_changed = 1;
1086 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1088 m_service_handler_timeshift.free();
1089 m_service_handler.free();
1091 if (m_is_pvr && m_cuesheet_changed)
1094 /* save cuesheet only when main file is accessible. */
1095 if (!::stat(m_reference.path.c_str(), &s))
1098 m_event((iPlayableService*)this, evStopped);
1102 RESULT eDVBServicePlay::setTarget(int target)
1104 m_is_primary = !target;
1108 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1110 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1114 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1116 /* note: we check for timeshift to be enabled,
1117 not neccessary active. if you pause when timeshift
1118 is not active, you should activate it when unpausing */
1119 if ((!m_is_pvr) && (!m_timeshift_enabled))
1129 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1132 return m_decoder->setSlowMotion(ratio);
1137 RESULT eDVBServicePlay::setFastForward(int ratio)
1139 int skipmode, ffratio;
1145 } else if (ratio > 0)
1153 } else // if (ratio < 0)
1159 if (m_skipmode != skipmode)
1161 eDebug("setting cue skipmode to %d", skipmode);
1163 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1166 m_skipmode = skipmode;
1171 return m_decoder->setFastForward(ffratio);
1174 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1176 if (m_is_pvr || m_timeshift_enabled)
1186 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1187 RESULT eDVBServicePlay::getLength(pts_t &len)
1189 ePtr<iDVBPVRChannel> pvr_channel;
1191 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1194 return pvr_channel->getLength(len);
1197 RESULT eDVBServicePlay::pause()
1199 if (!m_is_paused && m_decoder)
1202 return m_decoder->freeze(0);
1207 RESULT eDVBServicePlay::unpause()
1209 if (m_is_paused && m_decoder)
1212 return m_decoder->unfreeze();
1217 RESULT eDVBServicePlay::seekTo(pts_t to)
1219 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1221 if (!m_decode_demux)
1224 ePtr<iDVBPVRChannel> pvr_channel;
1226 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1232 m_cue->seekTo(0, to);
1233 m_dvb_subtitle_pages.clear();
1234 m_subtitle_pages.clear();
1239 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1241 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1243 if (!m_decode_demux)
1246 ePtr<iDVBPVRChannel> pvr_channel;
1248 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1253 /* HACK until we have skip-AP api */
1254 if ((to > 0) && (to < 100))
1262 m_cue->seekTo(mode, to);
1263 m_dvb_subtitle_pages.clear();
1264 m_subtitle_pages.clear();
1268 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1270 ePtr<iDVBPVRChannel> pvr_channel;
1272 if (!m_decode_demux)
1275 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1280 /* if there is a decoder, use audio or video PTS */
1283 r = m_decoder->getPTS(0, pos);
1289 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1292 RESULT eDVBServicePlay::setTrickmode(int trick)
1295 m_decoder->setTrickmode(trick);
1299 RESULT eDVBServicePlay::isCurrentlySeekable()
1301 return m_is_pvr || m_timeshift_active;
1304 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1310 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1316 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1322 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1328 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1334 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1337 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1338 (m_timeshift_enabled || !m_is_pvr))
1340 if (!m_timeshift_enabled)
1342 /* query config path */
1344 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1345 eDebug("could not query ts path from config");
1349 /* we need enough diskspace */
1351 if (statfs(tspath.c_str(), &fs) < 0)
1353 eDebug("statfs failed!");
1357 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1359 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1369 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1380 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1386 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1392 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1398 RESULT eDVBServicePlay::getName(std::string &name)
1402 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1403 return i->getName(m_reference, name);
1407 m_dvb_service->getName(m_reference, name);
1411 else if (!m_reference.name.empty())
1412 eStaticServiceDVBInformation().getName(m_reference, name);
1414 name = "DVB service";
1418 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1420 return m_event_handler.getEvent(evt, nownext);
1423 int eDVBServicePlay::getInfo(int w)
1425 eDVBServicePMTHandler::program program;
1428 return resIsPyObject;
1430 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1432 int no_program_info = 0;
1434 if (h.getProgramInfo(program))
1435 no_program_info = 1;
1441 return m_decoder->getVideoHeight();
1445 return m_decoder->getVideoWidth();
1449 return m_decoder->getVideoFrameRate();
1453 return m_decoder->getVideoProgressive();
1459 aspect = m_decoder->getVideoAspect();
1460 if (no_program_info)
1462 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1464 ePtr<eServiceEvent> evt;
1465 if (!m_event_handler.getEvent(evt, 0))
1467 ePtr<eComponentData> data;
1468 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1470 if ( data->getStreamContent() == 1 )
1472 switch(data->getComponentType())
1475 case 1: // 4:3 SD PAL
1477 case 3: // 16:9 SD PAL
1478 case 4: // > 16:9 PAL
1479 case 5: // 4:3 SD NTSC
1481 case 7: // 16:9 SD NTSC
1482 case 8: // > 16:9 NTSC
1485 case 9: // 4:3 HD PAL
1487 case 0xB: // 16:9 HD PAL
1488 case 0xC: // > 16:9 HD PAL
1489 case 0xD: // 4:3 HD NTSC
1491 case 0xF: // 16:9 HD NTSC
1492 case 0x10: // > 16:9 HD PAL
1493 return data->getComponentType();
1503 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1504 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1505 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1506 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1507 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1508 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1509 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1510 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1511 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1512 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1513 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1514 case sProvider: if (!m_dvb_service) return -1; return -2;
1515 case sServiceref: return resIsString;
1516 case sDVBState: return m_tune_state;
1523 std::string eDVBServicePlay::getInfoString(int w)
1528 if (!m_dvb_service) return "";
1529 return m_dvb_service->m_provider_name;
1531 return m_reference.toString();
1535 return iServiceInformation::getInfoString(w);
1538 PyObject *eDVBServicePlay::getInfoObject(int w)
1543 return m_service_handler.getCaIds();
1544 case sTransponderData:
1545 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1549 return iServiceInformation::getInfoObject(w);
1552 int eDVBServicePlay::getNumberOfTracks()
1554 eDVBServicePMTHandler::program program;
1555 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1556 if (h.getProgramInfo(program))
1558 return program.audioStreams.size();
1561 int eDVBServicePlay::getCurrentTrack()
1563 eDVBServicePMTHandler::program program;
1564 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1565 if (h.getProgramInfo(program))
1568 int max = program.audioStreams.size();
1571 for (i = 0; i < max; ++i)
1572 if (program.audioStreams[i].pid == m_current_audio_pid)
1578 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1580 int ret = selectAudioStream(i);
1582 if (m_decoder->start())
1588 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1590 eDVBServicePMTHandler::program program;
1591 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1593 if (h.getProgramInfo(program))
1596 if (i >= program.audioStreams.size())
1599 info.m_pid = program.audioStreams[i].pid;
1601 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1602 info.m_description = "MPEG";
1603 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1604 info.m_description = "AC3";
1605 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1606 info.m_description = "AAC";
1607 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1608 info.m_description = "AAC-HE";
1609 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1610 info.m_description = "DTS";
1612 info.m_description = "???";
1614 if (program.audioStreams[i].component_tag != -1)
1616 ePtr<eServiceEvent> evt;
1617 if (!m_event_handler.getEvent(evt, 0))
1619 ePtr<eComponentData> data;
1620 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1621 info.m_language = data->getText();
1625 if (info.m_language.empty())
1626 info.m_language = program.audioStreams[i].language_code;
1631 int eDVBServicePlay::selectAudioStream(int i)
1633 eDVBServicePMTHandler::program program;
1634 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1636 if (h.getProgramInfo(program))
1639 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1647 stream = program.defaultAudioStream;
1649 int apid = -1, apidtype = -1;
1651 if (((unsigned int)stream) < program.audioStreams.size())
1653 apid = program.audioStreams[stream].pid;
1654 apidtype = program.audioStreams[stream].type;
1657 m_current_audio_pid = apid;
1659 if (m_decoder->setAudioPID(apid, apidtype))
1661 eDebug("set audio pid failed");
1665 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1666 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1669 ePtr<iDVBDemux> data_demux;
1670 if (!h.getDataDemux(data_demux))
1672 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1673 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1677 /* if we decided that we need one, update the pid */
1679 m_rds_decoder->start(apid);
1681 /* store new pid as default only when:
1682 a.) we have an entry in the service db for the current service,
1683 b.) we are not playing back something,
1684 c.) we are not selecting the default entry. (we wouldn't change
1685 anything in the best case, or destroy the default setting in
1686 case the real default is not yet available.)
1688 if (m_dvb_service && !m_is_pvr && ((i != -1)
1689 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1691 if (apidtype == eDVBAudio::aMPEG)
1693 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1694 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1698 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1699 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1703 h.resetCachedProgram();
1708 int eDVBServicePlay::getCurrentChannel()
1710 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1713 RESULT eDVBServicePlay::selectChannel(int i)
1715 if (i < LEFT || i > RIGHT || i == STEREO)
1718 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1720 m_decoder->setAudioChannel(i);
1724 std::string eDVBServicePlay::getText(int x)
1730 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1732 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1737 void eDVBServicePlay::rdsDecoderEvent(int what)
1741 case eDVBRdsDecoder::RadioTextChanged:
1742 m_event((iPlayableService*)this, evUpdatedRadioText);
1744 case eDVBRdsDecoder::RtpTextChanged:
1745 m_event((iPlayableService*)this, evUpdatedRtpText);
1747 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1748 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1750 case eDVBRdsDecoder::RecvRassSlidePic:
1751 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1756 void eDVBServicePlay::showRassSlidePicture()
1762 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1763 if (rass_slide_pic.length())
1764 m_decoder->showSinglePic(rass_slide_pic.c_str());
1766 eDebug("empty filename for rass slide picture received!!");
1769 eDebug("no MPEG Decoder to show iframes avail");
1772 eDebug("showRassSlidePicture called.. but not decoder");
1775 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1781 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1782 if (rass_interactive_pic.length())
1783 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1785 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1788 eDebug("no MPEG Decoder to show iframes avail");
1791 eDebug("showRassInteractivePic called.. but not decoder");
1794 ePyObject eDVBServicePlay::getRassInteractiveMask()
1797 return m_rds_decoder->getRassPictureMask();
1801 int eDVBServiceBase::getFrontendInfo(int w)
1803 eUsePtr<iDVBChannel> channel;
1804 if(m_service_handler.getChannel(channel))
1806 ePtr<iDVBFrontend> fe;
1807 if(channel->getFrontend(fe))
1809 return fe->readFrontendData(w);
1812 PyObject *eDVBServiceBase::getFrontendData()
1814 ePyObject ret = PyDict_New();
1817 eUsePtr<iDVBChannel> channel;
1818 if(!m_service_handler.getChannel(channel))
1820 ePtr<iDVBFrontend> fe;
1821 if(!channel->getFrontend(fe))
1822 fe->getFrontendData(ret);
1830 PyObject *eDVBServiceBase::getFrontendStatus()
1832 ePyObject ret = PyDict_New();
1835 eUsePtr<iDVBChannel> channel;
1836 if(!m_service_handler.getChannel(channel))
1838 ePtr<iDVBFrontend> fe;
1839 if(!channel->getFrontend(fe))
1840 fe->getFrontendStatus(ret);
1848 PyObject *eDVBServiceBase::getTransponderData(bool original)
1850 ePyObject ret = PyDict_New();
1853 eUsePtr<iDVBChannel> channel;
1854 if(!m_service_handler.getChannel(channel))
1856 ePtr<iDVBFrontend> fe;
1857 if(!channel->getFrontend(fe))
1859 fe->getTransponderData(ret, original);
1860 ePtr<iDVBFrontendParameters> feparm;
1861 channel->getCurrentFrontendParameters(feparm);
1864 eDVBFrontendParametersSatellite osat;
1865 if (!feparm->getDVBS(osat))
1867 PutToDict(ret, "orbital_position", osat.orbital_position);
1868 PutToDict(ret, "polarization", osat.polarisation);
1879 PyObject *eDVBServiceBase::getAll(bool original)
1881 ePyObject ret = getTransponderData(original);
1884 eUsePtr<iDVBChannel> channel;
1885 if(!m_service_handler.getChannel(channel))
1887 ePtr<iDVBFrontend> fe;
1888 if(!channel->getFrontend(fe))
1890 fe->getFrontendData(ret);
1891 fe->getFrontendStatus(ret);
1898 int eDVBServicePlay::getNumberOfSubservices()
1900 ePtr<eServiceEvent> evt;
1901 if (!m_event_handler.getEvent(evt, 0))
1902 return evt->getNumOfLinkageServices();
1906 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1908 ePtr<eServiceEvent> evt;
1909 if (!m_event_handler.getEvent(evt, 0))
1911 if (!evt->getLinkageService(sub, m_reference, n))
1914 sub.type=eServiceReference::idInvalid;
1918 RESULT eDVBServicePlay::startTimeshift()
1920 ePtr<iDVBDemux> demux;
1922 eDebug("Start timeshift!");
1924 if (m_timeshift_enabled)
1927 /* start recording with the data demux. */
1928 if (m_service_handler.getDataDemux(demux))
1931 demux->createTSRecorder(m_record);
1936 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1937 eDebug("could not query ts path");
1940 tspath.append("/timeshift.XXXXXX");
1942 templ = new char[tspath.length() + 1];
1943 strcpy(templ, tspath.c_str());
1945 m_timeshift_fd = mkstemp(templ);
1946 m_timeshift_file = std::string(templ);
1948 eDebug("recording to %s", templ);
1952 if (m_timeshift_fd < 0)
1958 m_record->setTargetFD(m_timeshift_fd);
1960 m_timeshift_enabled = 1;
1962 updateTimeshiftPids();
1968 RESULT eDVBServicePlay::stopTimeshift()
1970 if (!m_timeshift_enabled)
1975 m_timeshift_enabled = 0;
1980 close(m_timeshift_fd);
1981 eDebug("remove timeshift file");
1982 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1987 int eDVBServicePlay::isTimeshiftActive()
1989 return m_timeshift_enabled && m_timeshift_active;
1992 RESULT eDVBServicePlay::activateTimeshift()
1994 if (!m_timeshift_enabled)
1997 if (!m_timeshift_active)
1999 switchToTimeshift();
2006 PyObject *eDVBServicePlay::getCutList()
2008 ePyObject list = PyList_New(0);
2010 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2012 ePyObject tuple = PyTuple_New(2);
2013 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2014 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2015 PyList_Append(list, tuple);
2022 void eDVBServicePlay::setCutList(ePyObject list)
2024 if (!PyList_Check(list))
2026 int size = PyList_Size(list);
2029 m_cue_entries.clear();
2031 for (i=0; i<size; ++i)
2033 ePyObject tuple = PyList_GET_ITEM(list, i);
2034 if (!PyTuple_Check(tuple))
2036 eDebug("non-tuple in cutlist");
2039 if (PyTuple_Size(tuple) != 2)
2041 eDebug("cutlist entries need to be a 2-tuple");
2044 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2045 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2047 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2050 pts_t pts = PyLong_AsLongLong(ppts);
2051 int type = PyInt_AsLong(ptype);
2052 m_cue_entries.insert(cueEntry(pts, type));
2053 eDebug("adding %08llx, %d", pts, type);
2055 m_cuesheet_changed = 1;
2057 cutlistToCuesheet();
2058 m_event((iPlayableService*)this, evCuesheetChanged);
2061 void eDVBServicePlay::setCutListEnable(int enable)
2063 m_cutlist_enabled = enable;
2064 cutlistToCuesheet();
2067 void eDVBServicePlay::updateTimeshiftPids()
2072 eDVBServicePMTHandler::program program;
2073 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2075 if (h.getProgramInfo(program))
2079 std::set<int> pids_to_record;
2080 pids_to_record.insert(0); // PAT
2081 if (program.pmtPid != -1)
2082 pids_to_record.insert(program.pmtPid); // PMT
2084 if (program.textPid != -1)
2085 pids_to_record.insert(program.textPid); // Videotext
2087 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2088 i(program.videoStreams.begin());
2089 i != program.videoStreams.end(); ++i)
2090 pids_to_record.insert(i->pid);
2092 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2093 i(program.audioStreams.begin());
2094 i != program.audioStreams.end(); ++i)
2095 pids_to_record.insert(i->pid);
2097 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2098 i(program.subtitleStreams.begin());
2099 i != program.subtitleStreams.end(); ++i)
2100 pids_to_record.insert(i->pid);
2102 std::set<int> new_pids, obsolete_pids;
2104 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2105 m_pids_active.begin(), m_pids_active.end(),
2106 std::inserter(new_pids, new_pids.begin()));
2108 std::set_difference(
2109 m_pids_active.begin(), m_pids_active.end(),
2110 pids_to_record.begin(), pids_to_record.end(),
2111 std::inserter(new_pids, new_pids.begin())
2114 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2115 m_record->addPID(*i);
2117 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2118 m_record->removePID(*i);
2122 void eDVBServicePlay::switchToLive()
2124 if (!m_timeshift_active)
2130 m_teletext_parser = 0;
2132 m_subtitle_parser = 0;
2133 m_new_dvb_subtitle_page_connection = 0;
2134 m_new_subtitle_page_connection = 0;
2135 m_rds_decoder_event_connection = 0;
2136 m_video_event_connection = 0;
2138 /* free the timeshift service handler, we need the resources */
2139 m_service_handler_timeshift.free();
2140 m_timeshift_active = 0;
2142 m_event((iPlayableService*)this, evSeekableStatusChanged);
2147 void eDVBServicePlay::switchToTimeshift()
2149 if (m_timeshift_active)
2154 m_teletext_parser = 0;
2156 m_subtitle_parser = 0;
2157 m_new_subtitle_page_connection = 0;
2158 m_new_dvb_subtitle_page_connection = 0;
2159 m_rds_decoder_event_connection = 0;
2160 m_video_event_connection = 0;
2162 m_timeshift_active = 1;
2164 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2165 r.path = m_timeshift_file;
2167 m_cue = new eCueSheet();
2168 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2170 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2172 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2174 m_event((iPlayableService*)this, evSeekableStatusChanged);
2177 void eDVBServicePlay::updateDecoder()
2179 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2181 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2183 eDVBServicePMTHandler::program program;
2184 if (h.getProgramInfo(program))
2185 eDebug("getting program info failed.");
2188 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2189 if (!program.videoStreams.empty())
2191 eDebugNoNewLine(" (");
2192 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2193 i(program.videoStreams.begin());
2194 i != program.videoStreams.end(); ++i)
2201 if (i != program.videoStreams.begin())
2202 eDebugNoNewLine(", ");
2203 eDebugNoNewLine("%04x", i->pid);
2205 eDebugNoNewLine(")");
2207 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2208 if (!program.audioStreams.empty())
2210 eDebugNoNewLine(" (");
2211 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2212 i(program.audioStreams.begin());
2213 i != program.audioStreams.end(); ++i)
2215 if (i != program.audioStreams.begin())
2216 eDebugNoNewLine(", ");
2217 eDebugNoNewLine("%04x", i->pid);
2219 eDebugNoNewLine(")");
2221 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2222 pcrpid = program.pcrPid;
2223 eDebug(", and the text pid is %04x", program.textPid);
2224 tpid = program.textPid;
2229 h.getDecodeDemux(m_decode_demux);
2232 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2234 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2235 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2236 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2237 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2238 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2241 m_teletext_parser = 0;
2242 m_subtitle_parser = 0;
2246 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2253 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2254 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2255 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2257 else // subservice or recording
2259 eServiceReferenceDVB ref;
2260 m_service_handler.getServiceReference(ref);
2261 eServiceReferenceDVB parent = ref.getParentServiceReference();
2266 ePtr<eDVBResourceManager> res_mgr;
2267 if (!eDVBResourceManager::getInstance(res_mgr))
2269 ePtr<iDVBChannelList> db;
2270 if (!res_mgr->getChannelList(db))
2272 ePtr<eDVBService> origService;
2273 if (!db->getService(parent, origService))
2275 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2276 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2282 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2283 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2285 m_decoder->setVideoPID(vpid, vpidtype);
2286 selectAudioStream();
2288 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2289 m_decoder->setSyncPCR(pcrpid);
2291 m_decoder->setSyncPCR(-1);
2293 m_decoder->setTextPID(tpid);
2295 m_teletext_parser->start(program.textPid);
2298 m_decoder->setTrickmode(1);
2301 m_decoder->preroll();
2305 if (vpid > 0 && vpid < 0x2000)
2309 std::string radio_pic;
2310 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2311 m_decoder->setRadioPic(radio_pic);
2314 m_decoder->setAudioChannel(achannel);
2316 /* don't worry about non-existing services, nor pvr services */
2317 if (m_dvb_service && !m_is_pvr)
2319 /* (audio pid will be set in selectAudioTrack */
2320 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2321 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2322 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2323 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2326 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2329 void eDVBServicePlay::loadCuesheet()
2331 std::string filename = m_reference.path + ".cuts";
2333 m_cue_entries.clear();
2335 FILE *f = fopen(filename.c_str(), "rb");
2339 eDebug("loading cuts..");
2342 unsigned long long where;
2345 if (!fread(&where, sizeof(where), 1, f))
2347 if (!fread(&what, sizeof(what), 1, f))
2350 #if BYTE_ORDER == LITTLE_ENDIAN
2351 where = bswap_64(where);
2358 m_cue_entries.insert(cueEntry(where, what));
2361 eDebug("%d entries", m_cue_entries.size());
2363 eDebug("cutfile not found!");
2365 m_cuesheet_changed = 0;
2366 cutlistToCuesheet();
2367 m_event((iPlayableService*)this, evCuesheetChanged);
2370 void eDVBServicePlay::saveCuesheet()
2372 std::string filename = m_reference.path + ".cuts";
2374 FILE *f = fopen(filename.c_str(), "wb");
2378 unsigned long long where;
2381 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2383 #if BYTE_ORDER == BIG_ENDIAN
2386 where = bswap_64(i->where);
2388 what = htonl(i->what);
2389 fwrite(&where, sizeof(where), 1, f);
2390 fwrite(&what, sizeof(what), 1, f);
2396 m_cuesheet_changed = 0;
2399 void eDVBServicePlay::cutlistToCuesheet()
2403 eDebug("no cue sheet");
2408 if (!m_cutlist_enabled)
2410 m_cue->commitSpans();
2411 eDebug("cutlists were disabled");
2415 pts_t in = 0, out = 0, length = 0;
2419 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2423 if (i == m_cue_entries.end())
2426 if (i->what == 0) /* in */
2430 } else if (i->what == 1) /* out */
2432 else /* mark (2) or last play position (3) */
2449 m_cue->addSourceSpan(in, out);
2453 if (i == m_cue_entries.end())
2456 m_cue->commitSpans();
2459 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2461 if (m_subtitle_widget)
2462 disableSubtitles(parent);
2465 int tuplesize = PyTuple_Size(tuple);
2468 if (!PyTuple_Check(tuple))
2474 entry = PyTuple_GET_ITEM(tuple, 0);
2476 if (!PyInt_Check(entry))
2479 type = PyInt_AsLong(entry);
2481 if (type == 1) // teletext subtitles
2483 int page, magazine, pid;
2487 if (!m_teletext_parser)
2489 eDebug("enable teletext subtitles.. no parser !!!");
2493 entry = PyTuple_GET_ITEM(tuple, 1);
2494 if (!PyInt_Check(entry))
2496 pid = PyInt_AsLong(entry);
2498 entry = PyTuple_GET_ITEM(tuple, 2);
2499 if (!PyInt_Check(entry))
2501 page = PyInt_AsLong(entry);
2503 entry = PyTuple_GET_ITEM(tuple, 3);
2504 if (!PyInt_Check(entry))
2506 magazine = PyInt_AsLong(entry);
2508 m_subtitle_widget = new eSubtitleWidget(parent);
2509 m_subtitle_widget->resize(parent->size()); /* full size */
2510 m_teletext_parser->setPageAndMagazine(page, magazine);
2512 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2516 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2517 if (!m_subtitle_parser)
2519 eDebug("enable dvb subtitles.. no parser !!!");
2525 entry = PyTuple_GET_ITEM(tuple, 1);
2526 if (!PyInt_Check(entry))
2528 pid = PyInt_AsLong(entry);
2530 entry = PyTuple_GET_ITEM(tuple, 2);
2531 if (!PyInt_Check(entry))
2533 composition_page_id = PyInt_AsLong(entry);
2535 entry = PyTuple_GET_ITEM(tuple, 3);
2536 if (!PyInt_Check(entry))
2538 ancillary_page_id = PyInt_AsLong(entry);
2540 m_subtitle_widget = new eSubtitleWidget(parent);
2541 m_subtitle_widget->resize(parent->size()); /* full size */
2542 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2544 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2550 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2551 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2552 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2556 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2558 delete m_subtitle_widget;
2559 m_subtitle_widget = 0;
2560 if (m_subtitle_parser)
2562 m_subtitle_parser->stop();
2563 m_dvb_subtitle_pages.clear();
2565 if (m_teletext_parser)
2567 m_teletext_parser->setPageAndMagazine(-1, -1);
2568 m_subtitle_pages.clear();
2571 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2575 PyObject *eDVBServicePlay::getCachedSubtitle()
2579 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2582 unsigned int data = (unsigned int)tmp;
2583 int pid = (data&0xFFFF0000)>>16;
2584 ePyObject tuple = PyTuple_New(4);
2585 eDVBServicePMTHandler::program program;
2586 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2587 if (!h.getProgramInfo(program))
2589 if (program.textPid==pid) // teletext
2590 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2592 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2593 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2594 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2595 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2603 PyObject *eDVBServicePlay::getSubtitleList()
2605 if (!m_teletext_parser)
2608 ePyObject l = PyList_New(0);
2609 std::set<int> added_ttx_pages;
2611 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2612 m_teletext_parser->m_found_subtitle_pages;
2614 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2615 eDVBServicePMTHandler::program program;
2616 if (h.getProgramInfo(program))
2617 eDebug("getting program info failed.");
2620 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2621 it != program.subtitleStreams.end(); ++it)
2623 switch(it->subtitling_type)
2625 case 0x01: // ebu teletext subtitles
2627 int page_number = it->teletext_page_number & 0xFF;
2628 int magazine_number = it->teletext_magazine_number & 7;
2629 int hash = magazine_number << 8 | page_number;
2630 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2632 ePyObject tuple = PyTuple_New(5);
2633 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2634 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2635 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2636 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2637 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2638 PyList_Append(l, tuple);
2640 added_ttx_pages.insert(hash);
2645 case 0x20 ... 0x23: // dvb subtitles
2647 ePyObject tuple = PyTuple_New(5);
2648 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2649 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2650 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2651 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2652 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2653 PyList_Insert(l, 0, tuple);
2661 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2662 it != subs.end(); ++it)
2664 int page_number = it->teletext_page_number & 0xFF;
2665 int magazine_number = it->teletext_magazine_number & 7;
2666 int hash = magazine_number << 8 | page_number;
2667 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2669 ePyObject tuple = PyTuple_New(5);
2670 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2671 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2672 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2673 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2674 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2675 PyList_Append(l, tuple);
2683 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2685 if (m_subtitle_widget)
2689 m_decoder->getPTS(0, pos);
2690 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2691 m_subtitle_pages.push_back(page);
2692 checkSubtitleTiming();
2696 void eDVBServicePlay::checkSubtitleTiming()
2698 eDebug("checkSubtitleTiming");
2699 if (!m_subtitle_widget)
2703 enum { TELETEXT, DVB } type;
2704 eDVBTeletextSubtitlePage page;
2705 eDVBSubtitlePage dvb_page;
2707 if (!m_subtitle_pages.empty())
2709 page = m_subtitle_pages.front();
2711 show_time = page.m_pts;
2713 else if (!m_dvb_subtitle_pages.empty())
2715 dvb_page = m_dvb_subtitle_pages.front();
2717 show_time = dvb_page.m_show_time;
2725 m_decoder->getPTS(0, pos);
2727 eDebug("%lld %lld", pos, show_time);
2728 int diff = show_time - pos;
2731 eDebug("[late (%d ms)]", -diff / 90);
2734 // if (diff > 900000)
2736 // eDebug("[invalid]");
2742 if (type == TELETEXT)
2744 eDebug("display teletext subtitle page %lld", show_time);
2745 m_subtitle_widget->setPage(page);
2746 m_subtitle_pages.pop_front();
2750 eDebug("display dvb subtitle Page %lld", show_time);
2751 m_subtitle_widget->setPage(dvb_page);
2752 m_dvb_subtitle_pages.pop_front();
2756 eDebug("start subtitle delay %d", diff / 90);
2757 m_subtitle_sync_timer->start(diff / 90, 1);
2763 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2765 if (m_subtitle_widget)
2769 m_decoder->getPTS(0, pos);
2770 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2771 m_dvb_subtitle_pages.push_back(p);
2772 checkSubtitleTiming();
2776 int eDVBServicePlay::getAC3Delay()
2779 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2781 return m_decoder->getAC3Delay();
2786 int eDVBServicePlay::getPCMDelay()
2789 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2791 return m_decoder->getPCMDelay();
2796 void eDVBServicePlay::setAC3Delay(int delay)
2799 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2801 m_decoder->setAC3Delay(delay);
2804 void eDVBServicePlay::setPCMDelay(int delay)
2807 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2809 m_decoder->setPCMDelay(delay);
2812 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2814 switch(event.type) {
2815 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2816 m_event((iPlayableService*)this, evVideoSizeChanged);
2818 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2819 m_event((iPlayableService*)this, evVideoFramerateChanged);
2821 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2822 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2829 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2835 PyObject *eDVBServicePlay::getStreamingData()
2837 eDVBServicePMTHandler::program program;
2838 if (m_service_handler.getProgramInfo(program))
2843 ePyObject r = program.createPythonObject();
2844 ePtr<iDVBDemux> demux;
2845 if (!m_service_handler.getDataDemux(demux))
2848 if (!demux->getCADemuxID(demux_id))
2849 PutToDict(r, "demux", demux_id);
2856 DEFINE_REF(eDVBServicePlay)
2858 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2862 case iServiceInformation::sTransponderData:
2863 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2867 return iStaticServiceInformation::getInfoObject(ref, w);
2870 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");