1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
101 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
103 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
105 PutToDict(dict, "tuner_type", "DVB-S");
106 PutToDict(dict, "frequency", feparm.frequency);
107 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
108 PutToDict(dict, "orbital_position", feparm.orbital_position);
109 PutToDict(dict, "inversion", feparm.inversion);
110 PutToDict(dict, "fec_inner", feparm.fec);
111 PutToDict(dict, "modulation", feparm.modulation);
112 PutToDict(dict, "polarization", feparm.polarisation);
113 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
115 PutToDict(dict, "rolloff", feparm.rolloff);
116 PutToDict(dict, "pilot", feparm.pilot);
118 PutToDict(dict, "system", feparm.system);
121 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
123 PutToDict(dict, "tuner_type", "DVB-T");
124 PutToDict(dict, "frequency", feparm.frequency);
125 PutToDict(dict, "bandwidth", feparm.bandwidth);
126 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
127 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
128 PutToDict(dict, "constellation", feparm.modulation);
129 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
130 PutToDict(dict, "guard_interval", feparm.guard_interval);
131 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
132 PutToDict(dict, "inversion", feparm.inversion);
135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
137 PutToDict(dict, "tuner_type", "DVB-C");
138 PutToDict(dict, "frequency", feparm.frequency);
139 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
140 PutToDict(dict, "modulation", feparm.modulation);
141 PutToDict(dict, "inversion", feparm.inversion);
142 PutToDict(dict, "fec_inner", feparm.fec_inner);
145 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
147 if (r.type == eServiceReference::idDVB)
149 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
152 case iServiceInformation::sTransponderData:
154 ePtr<eDVBResourceManager> res;
155 if (!eDVBResourceManager::getInstance(res))
157 ePtr<iDVBChannelList> db;
158 if (!res->getChannelList(db))
161 ref.getChannelID(chid);
162 ePtr<iDVBFrontendParameters> feparm;
163 if (!db->getChannelFrontendData(chid, feparm))
166 if (!feparm->getSystem(system))
168 ePyObject dict = PyDict_New();
171 case iDVBFrontend::feSatellite:
173 eDVBFrontendParametersSatellite s;
175 PutSatelliteDataToDict(dict, s);
178 case iDVBFrontend::feTerrestrial:
180 eDVBFrontendParametersTerrestrial t;
182 PutTerrestrialDataToDict(dict, t);
185 case iDVBFrontend::feCable:
187 eDVBFrontendParametersCable c;
189 PutCableDataToDict(dict, c);
193 eDebug("unknown frontend type %d", system);
208 DEFINE_REF(eStaticServiceDVBBouquetInformation);
210 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
212 ePtr<iDVBChannelList> db;
213 ePtr<eDVBResourceManager> res;
216 if ((err = eDVBResourceManager::getInstance(res)) != 0)
218 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
221 if ((err = res->getChannelList(db)) != 0)
223 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
228 if ((err = db->getBouquet(ref, bouquet)) != 0)
230 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
234 if ( bouquet && bouquet->m_bouquet_name.length() )
236 name = bouquet->m_bouquet_name;
243 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
245 if (ref.flags & eServiceReference::isGroup)
247 ePtr<iDVBChannelList> db;
248 ePtr<eDVBResourceManager> res;
250 if (eDVBResourceManager::getInstance(res))
252 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
256 if (res->getChannelList(db))
258 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
263 if (db->getBouquet(ref, bouquet))
265 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
269 int prio_order = eDVBFrontend::getTypePriorityOrder();
271 eDVBChannelID chid, chid_ignore;
272 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
273 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
275 static unsigned char prio_map[6][3] = {
276 { 3, 2, 1 }, // -S -C -T
277 { 3, 1, 2 }, // -S -T -C
278 { 2, 3, 1 }, // -C -S -T
279 { 1, 3, 2 }, // -C -T -S
280 { 1, 2, 3 }, // -T -C -S
281 { 2, 1, 3 } // -T -S -C
283 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
284 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
289 case 30000: // cached DVB-T channel
290 case 1: // DVB-T frontend
291 tmp = prio_map[prio_order][2];
293 case 40000: // cached DVB-C channel
295 tmp = prio_map[prio_order][1];
298 tmp = prio_map[prio_order][0];
303 m_playable_service = *it;
310 m_playable_service = eServiceReference();
314 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
319 #include <lib/dvb/epgcache.h>
321 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
323 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
326 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
328 DECLARE_REF(eStaticServiceDVBPVRInformation);
329 eServiceReference m_ref;
330 eDVBMetaParser m_parser;
332 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
333 RESULT getName(const eServiceReference &ref, std::string &name);
334 int getLength(const eServiceReference &ref);
335 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
336 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
337 int getInfo(const eServiceReference &ref, int w);
338 std::string getInfoString(const eServiceReference &ref,int w);
341 DEFINE_REF(eStaticServiceDVBPVRInformation);
343 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
346 m_parser.parseFile(ref.path);
349 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
351 ASSERT(ref == m_ref);
352 if (m_parser.m_name.size())
353 name = m_parser.m_name;
357 size_t n = name.rfind('/');
358 if (n != std::string::npos)
359 name = name.substr(n + 1);
364 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
366 ASSERT(ref == m_ref);
371 stat(ref.path.c_str(), &s);
373 if (tstools.openFile(ref.path.c_str(), 1))
376 /* check if cached data is still valid */
377 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
378 return m_parser.m_length / 90000;
380 /* open again, this time with stream info */
381 if (tstools.openFile(ref.path.c_str()))
384 /* otherwise, re-calc length and update meta file */
386 if (tstools.calcLen(len))
389 m_parser.m_length = len;
390 m_parser.m_filesize = s.st_size;
391 m_parser.updateMeta(ref.path);
392 return m_parser.m_length / 90000;
395 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
399 case iServiceInformation::sDescription:
400 return iServiceInformation::resIsString;
401 case iServiceInformation::sServiceref:
402 return iServiceInformation::resIsString;
403 case iServiceInformation::sTimeCreate:
404 if (m_parser.m_time_create)
405 return m_parser.m_time_create;
407 return iServiceInformation::resNA;
409 return iServiceInformation::resNA;
413 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
417 case iServiceInformation::sDescription:
418 return m_parser.m_description;
419 case iServiceInformation::sServiceref:
420 return m_parser.m_ref.toString();
421 case iServiceInformation::sTags:
422 return m_parser.m_tags;
428 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
430 if (!ref.path.empty())
432 ePtr<eServiceEvent> event = new eServiceEvent;
433 std::string filename = ref.path;
434 filename.erase(filename.length()-2, 2);
436 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
446 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
448 DECLARE_REF(eDVBPVRServiceOfflineOperations);
449 eServiceReferenceDVB m_ref;
451 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
453 RESULT deleteFromDisk(int simulate);
454 RESULT getListOfFilenames(std::list<std::string> &);
457 DEFINE_REF(eDVBPVRServiceOfflineOperations);
459 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
463 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
469 std::list<std::string> res;
470 if (getListOfFilenames(res))
473 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
475 eDebug("FATAL !! can't get background file eraser");
477 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
479 eDebug("Removing %s...", i->c_str());
481 eraser->erase(i->c_str());
483 ::unlink(i->c_str());
490 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
493 res.push_back(m_ref.path);
495 // handling for old splitted recordings (enigma 1)
500 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
502 if (stat(buf, &s) < 0)
507 res.push_back(m_ref.path + ".meta");
508 res.push_back(m_ref.path + ".ap");
509 res.push_back(m_ref.path + ".cuts");
510 std::string tmp = m_ref.path;
511 tmp.erase(m_ref.path.length()-3);
512 res.push_back(tmp + ".eit");
516 DEFINE_REF(eServiceFactoryDVB)
518 eServiceFactoryDVB::eServiceFactoryDVB()
520 ePtr<eServiceCenter> sc;
522 eServiceCenter::getPrivInstance(sc);
525 std::list<std::string> extensions;
526 extensions.push_back("ts");
527 extensions.push_back("trp");
528 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
531 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
532 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
535 eServiceFactoryDVB::~eServiceFactoryDVB()
537 ePtr<eServiceCenter> sc;
539 eServiceCenter::getPrivInstance(sc);
541 sc->removeServiceFactory(eServiceFactoryDVB::id);
544 DEFINE_REF(eDVBServiceList);
546 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
550 eDVBServiceList::~eDVBServiceList()
554 RESULT eDVBServiceList::startQuery()
556 ePtr<iDVBChannelList> db;
557 ePtr<eDVBResourceManager> res;
560 if ((err = eDVBResourceManager::getInstance(res)) != 0)
562 eDebug("no resource manager");
565 if ((err = res->getChannelList(db)) != 0)
567 eDebug("no channel list");
571 ePtr<eDVBChannelQuery> q;
573 if (!m_parent.path.empty())
575 eDVBChannelQuery::compile(q, m_parent.path);
578 eDebug("compile query failed");
583 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
585 eDebug("startQuery failed");
592 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
594 eServiceReferenceDVB ref;
599 while (!m_query->getNextResult(ref))
603 list.sort(iListableServiceCompare(this));
608 // The first argument of this function is a format string to specify the order and
609 // the content of the returned list
610 // useable format options are
611 // R = Service Reference (as swig object .. this is very slow)
612 // S = Service Reference (as python string object .. same as ref.toString())
613 // C = Service Reference (as python string object .. same as ref.toCompareString())
614 // N = Service Name (as python string object)
615 // n = Short Service Name (short name brakets used) (as python string object)
616 // when exactly one return value per service is selected in the format string,
617 // then each value is directly a list entry
618 // when more than one value is returned per service, then the list is a list of
620 // unknown format string chars are returned as python None values !
621 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
624 std::list<eServiceReference> tmplist;
627 if (!format || !(retcount=strlen(format)))
628 format = "R"; // just return service reference swig object ...
630 if (!getContent(tmplist, sorted))
632 int services=tmplist.size();
633 ePtr<iStaticServiceInformation> sptr;
634 eServiceCenterPtr service_center;
636 if (strchr(format, 'N') || strchr(format, 'n'))
637 eServiceCenter::getPrivInstance(service_center);
639 ret = PyList_New(services);
640 std::list<eServiceReference>::iterator it(tmplist.begin());
642 for (int cnt=0; cnt < services; ++cnt)
644 eServiceReference &ref=*it++;
645 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
646 for (int i=0; i < retcount; ++i)
651 case 'R': // service reference (swig)object
652 tmp = NEW_eServiceReference(ref);
654 case 'C': // service reference compare string
655 tmp = PyString_FromString(ref.toCompareString().c_str());
657 case 'S': // service reference string
658 tmp = PyString_FromString(ref.toString().c_str());
660 case 'N': // service name
663 service_center->info(ref, sptr);
667 sptr->getName(ref, name);
669 // filter short name brakets
671 while((pos = name.find("\xc2\x86")) != std::string::npos)
673 while((pos = name.find("\xc2\x87")) != std::string::npos)
677 tmp = PyString_FromString(name.c_str());
681 tmp = PyString_FromString("<n/a>");
683 case 'n': // short service name
686 service_center->info(ref, sptr);
690 sptr->getName(ref, name);
691 name = buildShortName(name);
693 tmp = PyString_FromString(name.c_str());
697 tmp = PyString_FromString("<n/a>");
710 PyTuple_SET_ITEM(tuple, i, tmp);
712 PyList_SET_ITEM(ret, cnt, tmp);
716 PyList_SET_ITEM(ret, cnt, tuple);
719 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
722 RESULT eDVBServiceList::getNext(eServiceReference &ref)
727 return m_query->getNextResult((eServiceReferenceDVB&)ref);
730 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
732 if (m_parent.flags & eServiceReference::canDescent) // bouquet
734 ePtr<iDVBChannelList> db;
735 ePtr<eDVBResourceManager> resm;
737 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
740 if (db->getBouquet(m_parent, m_bouquet) != 0)
751 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
755 return m_bouquet->addService(ref, before);
758 RESULT eDVBServiceList::removeService(eServiceReference &ref)
762 return m_bouquet->removeService(ref);
765 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
769 return m_bouquet->moveService(ref, pos);
772 RESULT eDVBServiceList::flushChanges()
776 return m_bouquet->flushChanges();
779 RESULT eDVBServiceList::setListName(const std::string &name)
783 return m_bouquet->setListName(name);
786 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
788 ePtr<eDVBService> service;
789 int r = lookupService(service, ref);
792 // check resources...
793 ptr = new eDVBServicePlay(ref, service);
797 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
799 if (ref.path.empty())
801 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
810 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
812 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
813 if (list->startQuery())
823 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
825 /* is a listable service? */
826 if (ref.flags & eServiceReference::canDescent) // bouquet
828 if ( !ref.name.empty() ) // satellites or providers list
829 ptr = m_StaticServiceDVBInfo;
830 else // a dvb bouquet
831 ptr = m_StaticServiceDVBBouquetInfo;
833 else if (!ref.path.empty()) /* do we have a PVR service? */
834 ptr = new eStaticServiceDVBPVRInformation(ref);
835 else // normal dvb service
837 ePtr<eDVBService> service;
838 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
839 ptr = m_StaticServiceDVBInfo;
841 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
847 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
849 if (ref.path.empty())
855 ptr = new eDVBPVRServiceOfflineOperations(ref);
860 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
862 // TODO: handle the listing itself
863 // if (ref.... == -1) .. return "... bouquets ...";
864 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
866 ePtr<iDVBChannelList> db;
867 ePtr<eDVBResourceManager> res;
870 if ((err = eDVBResourceManager::getInstance(res)) != 0)
872 eDebug("no resource manager");
875 if ((err = res->getChannelList(db)) != 0)
877 eDebug("no channel list");
881 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
882 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
884 eDebug("getService failed!");
891 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
892 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
895 m_is_pvr = !m_reference.path.empty();
897 m_timeshift_enabled = m_timeshift_active = 0;
900 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
901 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
902 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
904 m_cuesheet_changed = 0;
905 m_cutlist_enabled = 1;
907 m_subtitle_widget = 0;
911 m_subtitle_sync_timer = eTimer::create(eApp);
913 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
916 eDVBServicePlay::~eDVBServicePlay()
918 delete m_subtitle_widget;
921 void eDVBServicePlay::gotNewEvent()
925 ePtr<eServiceEvent> m_event_now, m_event_next;
926 getEvent(m_event_now, 0);
927 getEvent(m_event_next, 1);
930 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
932 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
934 m_event((iPlayableService*)this, evUpdatedEventInfo);
937 void eDVBServicePlay::serviceEvent(int event)
939 m_tune_state = event;
943 case eDVBServicePMTHandler::eventTuned:
945 ePtr<iDVBDemux> m_demux;
946 if (!m_service_handler.getDataDemux(m_demux))
948 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
949 int sid = ref.getParentServiceID().get();
951 sid = ref.getServiceID().get();
952 if ( ref.getParentTransportStreamID().get() &&
953 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
954 m_event_handler.startOther(m_demux, sid);
956 m_event_handler.start(m_demux, sid);
958 m_event((iPlayableService*)this, evTunedIn);
961 case eDVBServicePMTHandler::eventNoResources:
962 case eDVBServicePMTHandler::eventNoPAT:
963 case eDVBServicePMTHandler::eventNoPATEntry:
964 case eDVBServicePMTHandler::eventNoPMT:
965 case eDVBServicePMTHandler::eventTuneFailed:
966 case eDVBServicePMTHandler::eventMisconfiguration:
968 eDebug("DVB service failed to tune - error %d", event);
969 m_event((iPlayableService*)this, evTuneFailed);
972 case eDVBServicePMTHandler::eventNewProgramInfo:
974 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
975 if (m_timeshift_enabled)
976 updateTimeshiftPids();
977 if (!m_timeshift_active)
979 if (m_first_program_info && m_is_pvr)
981 m_first_program_info = 0;
984 m_event((iPlayableService*)this, evUpdatedInfo);
987 case eDVBServicePMTHandler::eventEOF:
988 m_event((iPlayableService*)this, evEOF);
990 case eDVBServicePMTHandler::eventSOF:
991 m_event((iPlayableService*)this, evSOF);
996 void eDVBServicePlay::serviceEventTimeshift(int event)
1000 case eDVBServicePMTHandler::eventNewProgramInfo:
1001 if (m_timeshift_active)
1004 case eDVBServicePMTHandler::eventSOF:
1005 m_event((iPlayableService*)this, evSOF);
1007 case eDVBServicePMTHandler::eventEOF:
1008 if ((!m_is_paused) && (m_skipmode >= 0))
1014 RESULT eDVBServicePlay::start()
1017 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1018 two (one for decoding, one for data source), as we must be prepared
1019 to start recording from the data demux. */
1021 m_cue = new eCueSheet();
1023 m_event(this, evStart);
1025 m_first_program_info = 1;
1026 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1027 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1029 /* inject EIT if there is a stored one */
1032 std::string filename = service.path;
1033 filename.erase(filename.length()-2, 2);
1035 ePtr<eServiceEvent> event = new eServiceEvent;
1036 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1038 ePtr<eServiceEvent> empty;
1039 m_event_handler.inject(event, 0);
1040 m_event_handler.inject(empty, 1);
1047 m_event(this, evStart);
1052 RESULT eDVBServicePlay::stop()
1054 /* add bookmark for last play position */
1057 pts_t play_position, length;
1058 if (!getPlayPosition(play_position))
1060 /* remove last position */
1061 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1063 if (i->what == 3) /* current play position */
1065 m_cue_entries.erase(i);
1066 i = m_cue_entries.begin();
1072 if (getLength(length))
1077 int perc = play_position * 100LL / length;
1079 /* only store last play position when between 1% and 99% */
1080 if ((1 < perc) && (perc < 99))
1081 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1083 m_cuesheet_changed = 1;
1087 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1089 m_service_handler_timeshift.free();
1090 m_service_handler.free();
1092 if (m_is_pvr && m_cuesheet_changed)
1095 /* save cuesheet only when main file is accessible. */
1096 if (!::stat(m_reference.path.c_str(), &s))
1099 m_event((iPlayableService*)this, evStopped);
1103 RESULT eDVBServicePlay::setTarget(int target)
1105 m_is_primary = !target;
1109 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1111 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1115 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1117 /* note: we check for timeshift to be enabled,
1118 not neccessary active. if you pause when timeshift
1119 is not active, you should activate it when unpausing */
1120 if ((!m_is_pvr) && (!m_timeshift_enabled))
1130 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1133 return m_decoder->setSlowMotion(ratio);
1138 RESULT eDVBServicePlay::setFastForward(int ratio)
1140 int skipmode, ffratio;
1146 } else if (ratio > 0)
1154 } else // if (ratio < 0)
1160 if (m_skipmode != skipmode)
1162 eDebug("setting cue skipmode to %d", skipmode);
1164 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1167 m_skipmode = skipmode;
1172 return m_decoder->setFastForward(ffratio);
1175 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1177 if (m_is_pvr || m_timeshift_enabled)
1187 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1188 RESULT eDVBServicePlay::getLength(pts_t &len)
1190 ePtr<iDVBPVRChannel> pvr_channel;
1192 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1195 return pvr_channel->getLength(len);
1198 RESULT eDVBServicePlay::pause()
1200 if (!m_is_paused && m_decoder)
1203 return m_decoder->freeze(0);
1208 RESULT eDVBServicePlay::unpause()
1210 if (m_is_paused && m_decoder)
1213 return m_decoder->unfreeze();
1218 RESULT eDVBServicePlay::seekTo(pts_t to)
1220 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1222 if (!m_decode_demux)
1225 ePtr<iDVBPVRChannel> pvr_channel;
1227 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1233 m_cue->seekTo(0, to);
1234 m_dvb_subtitle_pages.clear();
1235 m_subtitle_pages.clear();
1240 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1242 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1244 if (!m_decode_demux)
1247 ePtr<iDVBPVRChannel> pvr_channel;
1249 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1254 /* HACK until we have skip-AP api */
1255 if ((to > 0) && (to < 100))
1263 m_cue->seekTo(mode, to);
1264 m_dvb_subtitle_pages.clear();
1265 m_subtitle_pages.clear();
1269 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1271 ePtr<iDVBPVRChannel> pvr_channel;
1273 if (!m_decode_demux)
1276 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1281 /* if there is a decoder, use audio or video PTS */
1284 r = m_decoder->getPTS(0, pos);
1290 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1293 RESULT eDVBServicePlay::setTrickmode(int trick)
1296 m_decoder->setTrickmode(trick);
1300 RESULT eDVBServicePlay::isCurrentlySeekable()
1302 return m_is_pvr || m_timeshift_active;
1305 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1311 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1317 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1323 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1329 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1335 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1338 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1339 (m_timeshift_enabled || !m_is_pvr))
1341 if (!m_timeshift_enabled)
1343 /* query config path */
1345 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1346 eDebug("could not query ts path from config");
1350 /* we need enough diskspace */
1352 if (statfs(tspath.c_str(), &fs) < 0)
1354 eDebug("statfs failed!");
1358 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1360 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1370 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1381 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1387 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1393 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1399 RESULT eDVBServicePlay::getName(std::string &name)
1403 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1404 return i->getName(m_reference, name);
1408 m_dvb_service->getName(m_reference, name);
1412 else if (!m_reference.name.empty())
1413 eStaticServiceDVBInformation().getName(m_reference, name);
1415 name = "DVB service";
1419 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1421 return m_event_handler.getEvent(evt, nownext);
1424 int eDVBServicePlay::getInfo(int w)
1426 eDVBServicePMTHandler::program program;
1429 return resIsPyObject;
1431 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1433 int no_program_info = 0;
1435 if (h.getProgramInfo(program))
1436 no_program_info = 1;
1442 return m_decoder->getVideoHeight();
1446 return m_decoder->getVideoWidth();
1450 return m_decoder->getVideoFrameRate();
1454 return m_decoder->getVideoProgressive();
1460 aspect = m_decoder->getVideoAspect();
1461 if (no_program_info)
1463 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1465 ePtr<eServiceEvent> evt;
1466 if (!m_event_handler.getEvent(evt, 0))
1468 ePtr<eComponentData> data;
1469 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1471 if ( data->getStreamContent() == 1 )
1473 switch(data->getComponentType())
1476 case 1: // 4:3 SD PAL
1478 case 3: // 16:9 SD PAL
1479 case 4: // > 16:9 PAL
1480 case 5: // 4:3 SD NTSC
1482 case 7: // 16:9 SD NTSC
1483 case 8: // > 16:9 NTSC
1486 case 9: // 4:3 HD PAL
1488 case 0xB: // 16:9 HD PAL
1489 case 0xC: // > 16:9 HD PAL
1490 case 0xD: // 4:3 HD NTSC
1492 case 0xF: // 16:9 HD NTSC
1493 case 0x10: // > 16:9 HD PAL
1494 return data->getComponentType();
1504 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1505 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1506 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1507 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1508 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1509 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1510 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1511 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1512 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1513 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1514 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1515 case sProvider: if (!m_dvb_service) return -1; return -2;
1516 case sServiceref: return resIsString;
1517 case sDVBState: return m_tune_state;
1524 std::string eDVBServicePlay::getInfoString(int w)
1529 if (!m_dvb_service) return "";
1530 return m_dvb_service->m_provider_name;
1532 return m_reference.toString();
1536 return iServiceInformation::getInfoString(w);
1539 PyObject *eDVBServicePlay::getInfoObject(int w)
1544 return m_service_handler.getCaIds();
1545 case sTransponderData:
1546 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1550 return iServiceInformation::getInfoObject(w);
1553 int eDVBServicePlay::getNumberOfTracks()
1555 eDVBServicePMTHandler::program program;
1556 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1557 if (h.getProgramInfo(program))
1559 return program.audioStreams.size();
1562 int eDVBServicePlay::getCurrentTrack()
1564 eDVBServicePMTHandler::program program;
1565 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1566 if (h.getProgramInfo(program))
1569 int max = program.audioStreams.size();
1572 for (i = 0; i < max; ++i)
1573 if (program.audioStreams[i].pid == m_current_audio_pid)
1579 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1581 int ret = selectAudioStream(i);
1583 if (m_decoder->start())
1589 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1591 eDVBServicePMTHandler::program program;
1592 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1594 if (h.getProgramInfo(program))
1597 if (i >= program.audioStreams.size())
1600 info.m_pid = program.audioStreams[i].pid;
1602 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1603 info.m_description = "MPEG";
1604 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1605 info.m_description = "AC3";
1606 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1607 info.m_description = "AAC";
1608 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1609 info.m_description = "AAC-HE";
1610 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1611 info.m_description = "DTS";
1613 info.m_description = "???";
1615 if (program.audioStreams[i].component_tag != -1)
1617 ePtr<eServiceEvent> evt;
1618 if (!m_event_handler.getEvent(evt, 0))
1620 ePtr<eComponentData> data;
1621 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1622 info.m_language = data->getText();
1626 if (info.m_language.empty())
1627 info.m_language = program.audioStreams[i].language_code;
1632 int eDVBServicePlay::selectAudioStream(int i)
1634 eDVBServicePMTHandler::program program;
1635 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1637 if (h.getProgramInfo(program))
1640 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1648 stream = program.defaultAudioStream;
1650 int apid = -1, apidtype = -1;
1652 if (((unsigned int)stream) < program.audioStreams.size())
1654 apid = program.audioStreams[stream].pid;
1655 apidtype = program.audioStreams[stream].type;
1658 m_current_audio_pid = apid;
1660 if (m_decoder->setAudioPID(apid, apidtype))
1662 eDebug("set audio pid failed");
1666 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1667 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1670 ePtr<iDVBDemux> data_demux;
1671 if (!h.getDataDemux(data_demux))
1673 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1674 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1678 /* if we decided that we need one, update the pid */
1680 m_rds_decoder->start(apid);
1682 /* store new pid as default only when:
1683 a.) we have an entry in the service db for the current service,
1684 b.) we are not playing back something,
1685 c.) we are not selecting the default entry. (we wouldn't change
1686 anything in the best case, or destroy the default setting in
1687 case the real default is not yet available.)
1689 if (m_dvb_service && !m_is_pvr && ((i != -1)
1690 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1692 if (apidtype == eDVBAudio::aMPEG)
1694 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1695 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1699 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1700 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1704 h.resetCachedProgram();
1709 int eDVBServicePlay::getCurrentChannel()
1711 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1714 RESULT eDVBServicePlay::selectChannel(int i)
1716 if (i < LEFT || i > RIGHT || i == STEREO)
1719 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1721 m_decoder->setAudioChannel(i);
1725 std::string eDVBServicePlay::getText(int x)
1731 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1733 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1738 void eDVBServicePlay::rdsDecoderEvent(int what)
1742 case eDVBRdsDecoder::RadioTextChanged:
1743 m_event((iPlayableService*)this, evUpdatedRadioText);
1745 case eDVBRdsDecoder::RtpTextChanged:
1746 m_event((iPlayableService*)this, evUpdatedRtpText);
1748 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1749 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1751 case eDVBRdsDecoder::RecvRassSlidePic:
1752 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1757 void eDVBServicePlay::showRassSlidePicture()
1763 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1764 if (rass_slide_pic.length())
1765 m_decoder->showSinglePic(rass_slide_pic.c_str());
1767 eDebug("empty filename for rass slide picture received!!");
1770 eDebug("no MPEG Decoder to show iframes avail");
1773 eDebug("showRassSlidePicture called.. but not decoder");
1776 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1782 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1783 if (rass_interactive_pic.length())
1784 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1786 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1789 eDebug("no MPEG Decoder to show iframes avail");
1792 eDebug("showRassInteractivePic called.. but not decoder");
1795 ePyObject eDVBServicePlay::getRassInteractiveMask()
1798 return m_rds_decoder->getRassPictureMask();
1802 int eDVBServiceBase::getFrontendInfo(int w)
1804 eUsePtr<iDVBChannel> channel;
1805 if(m_service_handler.getChannel(channel))
1807 ePtr<iDVBFrontend> fe;
1808 if(channel->getFrontend(fe))
1810 return fe->readFrontendData(w);
1813 PyObject *eDVBServiceBase::getFrontendData()
1815 ePyObject ret = PyDict_New();
1818 eUsePtr<iDVBChannel> channel;
1819 if(!m_service_handler.getChannel(channel))
1821 ePtr<iDVBFrontend> fe;
1822 if(!channel->getFrontend(fe))
1823 fe->getFrontendData(ret);
1831 PyObject *eDVBServiceBase::getFrontendStatus()
1833 ePyObject ret = PyDict_New();
1836 eUsePtr<iDVBChannel> channel;
1837 if(!m_service_handler.getChannel(channel))
1839 ePtr<iDVBFrontend> fe;
1840 if(!channel->getFrontend(fe))
1841 fe->getFrontendStatus(ret);
1849 PyObject *eDVBServiceBase::getTransponderData(bool original)
1851 ePyObject ret = PyDict_New();
1854 eUsePtr<iDVBChannel> channel;
1855 if(!m_service_handler.getChannel(channel))
1857 ePtr<iDVBFrontend> fe;
1858 if(!channel->getFrontend(fe))
1859 fe->getTransponderData(ret, original);
1867 PyObject *eDVBServiceBase::getAll(bool original)
1869 ePyObject ret = getTransponderData(original);
1872 eUsePtr<iDVBChannel> channel;
1873 if(!m_service_handler.getChannel(channel))
1875 ePtr<iDVBFrontend> fe;
1876 if(!channel->getFrontend(fe))
1878 fe->getFrontendData(ret);
1879 fe->getFrontendStatus(ret);
1886 int eDVBServicePlay::getNumberOfSubservices()
1888 ePtr<eServiceEvent> evt;
1889 if (!m_event_handler.getEvent(evt, 0))
1890 return evt->getNumOfLinkageServices();
1894 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1896 ePtr<eServiceEvent> evt;
1897 if (!m_event_handler.getEvent(evt, 0))
1899 if (!evt->getLinkageService(sub, m_reference, n))
1902 sub.type=eServiceReference::idInvalid;
1906 RESULT eDVBServicePlay::startTimeshift()
1908 ePtr<iDVBDemux> demux;
1910 eDebug("Start timeshift!");
1912 if (m_timeshift_enabled)
1915 /* start recording with the data demux. */
1916 if (m_service_handler.getDataDemux(demux))
1919 demux->createTSRecorder(m_record);
1924 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1925 eDebug("could not query ts path");
1928 tspath.append("/timeshift.XXXXXX");
1930 templ = new char[tspath.length() + 1];
1931 strcpy(templ, tspath.c_str());
1933 m_timeshift_fd = mkstemp(templ);
1934 m_timeshift_file = std::string(templ);
1936 eDebug("recording to %s", templ);
1940 if (m_timeshift_fd < 0)
1946 m_record->setTargetFD(m_timeshift_fd);
1948 m_timeshift_enabled = 1;
1950 updateTimeshiftPids();
1956 RESULT eDVBServicePlay::stopTimeshift()
1958 if (!m_timeshift_enabled)
1963 m_timeshift_enabled = 0;
1968 close(m_timeshift_fd);
1969 eDebug("remove timeshift file");
1970 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1975 int eDVBServicePlay::isTimeshiftActive()
1977 return m_timeshift_enabled && m_timeshift_active;
1980 RESULT eDVBServicePlay::activateTimeshift()
1982 if (!m_timeshift_enabled)
1985 if (!m_timeshift_active)
1987 switchToTimeshift();
1994 PyObject *eDVBServicePlay::getCutList()
1996 ePyObject list = PyList_New(0);
1998 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2000 ePyObject tuple = PyTuple_New(2);
2001 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2002 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2003 PyList_Append(list, tuple);
2010 void eDVBServicePlay::setCutList(ePyObject list)
2012 if (!PyList_Check(list))
2014 int size = PyList_Size(list);
2017 m_cue_entries.clear();
2019 for (i=0; i<size; ++i)
2021 ePyObject tuple = PyList_GET_ITEM(list, i);
2022 if (!PyTuple_Check(tuple))
2024 eDebug("non-tuple in cutlist");
2027 if (PyTuple_Size(tuple) != 2)
2029 eDebug("cutlist entries need to be a 2-tuple");
2032 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2033 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2035 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2038 pts_t pts = PyLong_AsLongLong(ppts);
2039 int type = PyInt_AsLong(ptype);
2040 m_cue_entries.insert(cueEntry(pts, type));
2041 eDebug("adding %08llx, %d", pts, type);
2043 m_cuesheet_changed = 1;
2045 cutlistToCuesheet();
2046 m_event((iPlayableService*)this, evCuesheetChanged);
2049 void eDVBServicePlay::setCutListEnable(int enable)
2051 m_cutlist_enabled = enable;
2052 cutlistToCuesheet();
2055 void eDVBServicePlay::updateTimeshiftPids()
2060 eDVBServicePMTHandler::program program;
2061 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2063 if (h.getProgramInfo(program))
2067 std::set<int> pids_to_record;
2068 pids_to_record.insert(0); // PAT
2069 if (program.pmtPid != -1)
2070 pids_to_record.insert(program.pmtPid); // PMT
2072 if (program.textPid != -1)
2073 pids_to_record.insert(program.textPid); // Videotext
2075 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2076 i(program.videoStreams.begin());
2077 i != program.videoStreams.end(); ++i)
2078 pids_to_record.insert(i->pid);
2080 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2081 i(program.audioStreams.begin());
2082 i != program.audioStreams.end(); ++i)
2083 pids_to_record.insert(i->pid);
2085 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2086 i(program.subtitleStreams.begin());
2087 i != program.subtitleStreams.end(); ++i)
2088 pids_to_record.insert(i->pid);
2090 std::set<int> new_pids, obsolete_pids;
2092 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2093 m_pids_active.begin(), m_pids_active.end(),
2094 std::inserter(new_pids, new_pids.begin()));
2096 std::set_difference(
2097 m_pids_active.begin(), m_pids_active.end(),
2098 pids_to_record.begin(), pids_to_record.end(),
2099 std::inserter(new_pids, new_pids.begin())
2102 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2103 m_record->addPID(*i);
2105 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2106 m_record->removePID(*i);
2110 void eDVBServicePlay::switchToLive()
2112 if (!m_timeshift_active)
2118 m_teletext_parser = 0;
2120 m_subtitle_parser = 0;
2121 m_new_dvb_subtitle_page_connection = 0;
2122 m_new_subtitle_page_connection = 0;
2123 m_rds_decoder_event_connection = 0;
2124 m_video_event_connection = 0;
2126 /* free the timeshift service handler, we need the resources */
2127 m_service_handler_timeshift.free();
2128 m_timeshift_active = 0;
2130 m_event((iPlayableService*)this, evSeekableStatusChanged);
2135 void eDVBServicePlay::switchToTimeshift()
2137 if (m_timeshift_active)
2142 m_teletext_parser = 0;
2144 m_subtitle_parser = 0;
2145 m_new_subtitle_page_connection = 0;
2146 m_new_dvb_subtitle_page_connection = 0;
2147 m_rds_decoder_event_connection = 0;
2148 m_video_event_connection = 0;
2150 m_timeshift_active = 1;
2152 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2153 r.path = m_timeshift_file;
2155 m_cue = new eCueSheet();
2156 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2158 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2160 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2162 m_event((iPlayableService*)this, evSeekableStatusChanged);
2165 void eDVBServicePlay::updateDecoder()
2167 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2169 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2171 eDVBServicePMTHandler::program program;
2172 if (h.getProgramInfo(program))
2173 eDebug("getting program info failed.");
2176 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2177 if (!program.videoStreams.empty())
2179 eDebugNoNewLine(" (");
2180 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2181 i(program.videoStreams.begin());
2182 i != program.videoStreams.end(); ++i)
2189 if (i != program.videoStreams.begin())
2190 eDebugNoNewLine(", ");
2191 eDebugNoNewLine("%04x", i->pid);
2193 eDebugNoNewLine(")");
2195 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2196 if (!program.audioStreams.empty())
2198 eDebugNoNewLine(" (");
2199 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2200 i(program.audioStreams.begin());
2201 i != program.audioStreams.end(); ++i)
2203 if (i != program.audioStreams.begin())
2204 eDebugNoNewLine(", ");
2205 eDebugNoNewLine("%04x", i->pid);
2207 eDebugNoNewLine(")");
2209 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2210 pcrpid = program.pcrPid;
2211 eDebug(", and the text pid is %04x", program.textPid);
2212 tpid = program.textPid;
2217 h.getDecodeDemux(m_decode_demux);
2220 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2222 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2223 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2224 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2225 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2226 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2229 m_teletext_parser = 0;
2230 m_subtitle_parser = 0;
2234 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2241 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2242 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2243 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2245 else // subservice or recording
2247 eServiceReferenceDVB ref;
2248 m_service_handler.getServiceReference(ref);
2249 eServiceReferenceDVB parent = ref.getParentServiceReference();
2254 ePtr<eDVBResourceManager> res_mgr;
2255 if (!eDVBResourceManager::getInstance(res_mgr))
2257 ePtr<iDVBChannelList> db;
2258 if (!res_mgr->getChannelList(db))
2260 ePtr<eDVBService> origService;
2261 if (!db->getService(parent, origService))
2263 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2264 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2271 std::string config_delay;
2272 int config_delay_int = 0;
2273 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2274 config_delay_int = atoi(config_delay.c_str());
2275 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2277 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2278 config_delay_int = atoi(config_delay.c_str());
2280 config_delay_int = 0;
2281 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2283 m_decoder->setVideoPID(vpid, vpidtype);
2284 selectAudioStream();
2286 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2287 m_decoder->setSyncPCR(pcrpid);
2289 m_decoder->setSyncPCR(-1);
2291 m_decoder->setTextPID(tpid);
2293 m_teletext_parser->start(program.textPid);
2296 m_decoder->setTrickmode(1);
2299 m_decoder->preroll();
2303 if (vpid > 0 && vpid < 0x2000)
2307 std::string radio_pic;
2308 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2309 m_decoder->setRadioPic(radio_pic);
2312 m_decoder->setAudioChannel(achannel);
2314 /* don't worry about non-existing services, nor pvr services */
2315 if (m_dvb_service && !m_is_pvr)
2317 /* (audio pid will be set in selectAudioTrack */
2318 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2319 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2320 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2321 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2324 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2327 void eDVBServicePlay::loadCuesheet()
2329 std::string filename = m_reference.path + ".cuts";
2331 m_cue_entries.clear();
2333 FILE *f = fopen(filename.c_str(), "rb");
2337 eDebug("loading cuts..");
2340 unsigned long long where;
2343 if (!fread(&where, sizeof(where), 1, f))
2345 if (!fread(&what, sizeof(what), 1, f))
2348 #if BYTE_ORDER == LITTLE_ENDIAN
2349 where = bswap_64(where);
2356 m_cue_entries.insert(cueEntry(where, what));
2359 eDebug("%d entries", m_cue_entries.size());
2361 eDebug("cutfile not found!");
2363 m_cuesheet_changed = 0;
2364 cutlistToCuesheet();
2365 m_event((iPlayableService*)this, evCuesheetChanged);
2368 void eDVBServicePlay::saveCuesheet()
2370 std::string filename = m_reference.path + ".cuts";
2372 FILE *f = fopen(filename.c_str(), "wb");
2376 unsigned long long where;
2379 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2381 #if BYTE_ORDER == BIG_ENDIAN
2384 where = bswap_64(i->where);
2386 what = htonl(i->what);
2387 fwrite(&where, sizeof(where), 1, f);
2388 fwrite(&what, sizeof(what), 1, f);
2394 m_cuesheet_changed = 0;
2397 void eDVBServicePlay::cutlistToCuesheet()
2401 eDebug("no cue sheet");
2406 if (!m_cutlist_enabled)
2408 m_cue->commitSpans();
2409 eDebug("cutlists were disabled");
2413 pts_t in = 0, out = 0, length = 0;
2417 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2421 if (i == m_cue_entries.end())
2424 if (i->what == 0) /* in */
2428 } else if (i->what == 1) /* out */
2430 else /* mark (2) or last play position (3) */
2447 m_cue->addSourceSpan(in, out);
2451 if (i == m_cue_entries.end())
2454 m_cue->commitSpans();
2457 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2459 if (m_subtitle_widget)
2460 disableSubtitles(parent);
2463 int tuplesize = PyTuple_Size(tuple);
2466 if (!PyTuple_Check(tuple))
2472 entry = PyTuple_GET_ITEM(tuple, 0);
2474 if (!PyInt_Check(entry))
2477 type = PyInt_AsLong(entry);
2479 if (type == 1) // teletext subtitles
2481 int page, magazine, pid;
2485 if (!m_teletext_parser)
2487 eDebug("enable teletext subtitles.. no parser !!!");
2491 entry = PyTuple_GET_ITEM(tuple, 1);
2492 if (!PyInt_Check(entry))
2494 pid = PyInt_AsLong(entry);
2496 entry = PyTuple_GET_ITEM(tuple, 2);
2497 if (!PyInt_Check(entry))
2499 page = PyInt_AsLong(entry);
2501 entry = PyTuple_GET_ITEM(tuple, 3);
2502 if (!PyInt_Check(entry))
2504 magazine = PyInt_AsLong(entry);
2506 m_subtitle_widget = new eSubtitleWidget(parent);
2507 m_subtitle_widget->resize(parent->size()); /* full size */
2508 m_teletext_parser->setPageAndMagazine(page, magazine);
2510 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2514 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2515 if (!m_subtitle_parser)
2517 eDebug("enable dvb subtitles.. no parser !!!");
2523 entry = PyTuple_GET_ITEM(tuple, 1);
2524 if (!PyInt_Check(entry))
2526 pid = PyInt_AsLong(entry);
2528 entry = PyTuple_GET_ITEM(tuple, 2);
2529 if (!PyInt_Check(entry))
2531 composition_page_id = PyInt_AsLong(entry);
2533 entry = PyTuple_GET_ITEM(tuple, 3);
2534 if (!PyInt_Check(entry))
2536 ancillary_page_id = PyInt_AsLong(entry);
2538 m_subtitle_widget = new eSubtitleWidget(parent);
2539 m_subtitle_widget->resize(parent->size()); /* full size */
2540 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2542 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2548 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2549 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2550 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2554 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2556 delete m_subtitle_widget;
2557 m_subtitle_widget = 0;
2558 if (m_subtitle_parser)
2560 m_subtitle_parser->stop();
2561 m_dvb_subtitle_pages.clear();
2563 if (m_teletext_parser)
2565 m_teletext_parser->setPageAndMagazine(-1, -1);
2566 m_subtitle_pages.clear();
2569 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2573 PyObject *eDVBServicePlay::getCachedSubtitle()
2577 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2580 unsigned int data = (unsigned int)tmp;
2581 int pid = (data&0xFFFF0000)>>16;
2582 ePyObject tuple = PyTuple_New(4);
2583 eDVBServicePMTHandler::program program;
2584 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2585 if (!h.getProgramInfo(program))
2587 if (program.textPid==pid) // teletext
2588 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2590 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2591 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2592 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2593 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2601 PyObject *eDVBServicePlay::getSubtitleList()
2603 if (!m_teletext_parser)
2606 ePyObject l = PyList_New(0);
2607 std::set<int> added_ttx_pages;
2609 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2610 m_teletext_parser->m_found_subtitle_pages;
2612 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2613 eDVBServicePMTHandler::program program;
2614 if (h.getProgramInfo(program))
2615 eDebug("getting program info failed.");
2618 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2619 it != program.subtitleStreams.end(); ++it)
2621 switch(it->subtitling_type)
2623 case 0x01: // ebu teletext subtitles
2625 int page_number = it->teletext_page_number & 0xFF;
2626 int magazine_number = it->teletext_magazine_number & 7;
2627 int hash = magazine_number << 8 | page_number;
2628 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2630 ePyObject tuple = PyTuple_New(5);
2631 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2632 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2633 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2634 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2635 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2636 PyList_Append(l, tuple);
2638 added_ttx_pages.insert(hash);
2643 case 0x20 ... 0x23: // dvb subtitles
2645 ePyObject tuple = PyTuple_New(5);
2646 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2647 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2648 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2649 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2650 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2651 PyList_Insert(l, 0, tuple);
2659 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2660 it != subs.end(); ++it)
2662 int page_number = it->teletext_page_number & 0xFF;
2663 int magazine_number = it->teletext_magazine_number & 7;
2664 int hash = magazine_number << 8 | page_number;
2665 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2667 ePyObject tuple = PyTuple_New(5);
2668 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2669 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2670 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2671 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2672 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2673 PyList_Append(l, tuple);
2681 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2683 if (m_subtitle_widget)
2687 m_decoder->getPTS(0, pos);
2688 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2689 m_subtitle_pages.push_back(page);
2690 checkSubtitleTiming();
2694 void eDVBServicePlay::checkSubtitleTiming()
2696 eDebug("checkSubtitleTiming");
2697 if (!m_subtitle_widget)
2701 enum { TELETEXT, DVB } type;
2702 eDVBTeletextSubtitlePage page;
2703 eDVBSubtitlePage dvb_page;
2705 if (!m_subtitle_pages.empty())
2707 page = m_subtitle_pages.front();
2709 show_time = page.m_pts;
2711 else if (!m_dvb_subtitle_pages.empty())
2713 dvb_page = m_dvb_subtitle_pages.front();
2715 show_time = dvb_page.m_show_time;
2723 m_decoder->getPTS(0, pos);
2725 eDebug("%lld %lld", pos, show_time);
2726 int diff = show_time - pos;
2729 eDebug("[late (%d ms)]", -diff / 90);
2732 // if (diff > 900000)
2734 // eDebug("[invalid]");
2740 if (type == TELETEXT)
2742 eDebug("display teletext subtitle page %lld", show_time);
2743 m_subtitle_widget->setPage(page);
2744 m_subtitle_pages.pop_front();
2748 eDebug("display dvb subtitle Page %lld", show_time);
2749 m_subtitle_widget->setPage(dvb_page);
2750 m_dvb_subtitle_pages.pop_front();
2754 eDebug("start subtitle delay %d", diff / 90);
2755 m_subtitle_sync_timer->start(diff / 90, 1);
2761 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2763 if (m_subtitle_widget)
2767 m_decoder->getPTS(0, pos);
2768 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2769 m_dvb_subtitle_pages.push_back(p);
2770 checkSubtitleTiming();
2774 int eDVBServicePlay::getAC3Delay()
2777 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2779 return m_decoder->getAC3Delay();
2784 int eDVBServicePlay::getPCMDelay()
2787 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2789 return m_decoder->getPCMDelay();
2794 void eDVBServicePlay::setAC3Delay(int delay)
2797 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2799 m_decoder->setAC3Delay(delay);
2802 void eDVBServicePlay::setPCMDelay(int delay)
2805 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2807 m_decoder->setPCMDelay(delay);
2810 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2812 switch(event.type) {
2813 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2814 m_event((iPlayableService*)this, evVideoSizeChanged);
2816 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2817 m_event((iPlayableService*)this, evVideoFramerateChanged);
2819 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2820 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2827 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2833 PyObject *eDVBServicePlay::getStreamingData()
2835 eDVBServicePMTHandler::program program;
2836 if (m_service_handler.getProgramInfo(program))
2841 ePyObject r = program.createPythonObject();
2842 ePtr<iDVBDemux> demux;
2843 if (!m_service_handler.getDataDemux(demux))
2846 if (!demux->getCADemuxID(demux_id))
2847 PutToDict(r, "demux", demux_id);
2854 DEFINE_REF(eDVBServicePlay)
2856 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2860 case iServiceInformation::sTransponderData:
2861 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2865 return iStaticServiceInformation::getInfoObject(ref, w);
2868 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");