1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
101 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
103 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
105 PutToDict(dict, "tuner_type", "DVB-S");
106 PutToDict(dict, "frequency", feparm.frequency);
107 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
108 PutToDict(dict, "orbital_position", feparm.orbital_position);
109 PutToDict(dict, "inversion", feparm.inversion);
110 PutToDict(dict, "fec_inner", feparm.fec);
111 PutToDict(dict, "modulation", feparm.modulation);
112 PutToDict(dict, "polarization", feparm.polarisation);
113 if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
115 PutToDict(dict, "rolloff", feparm.rolloff);
116 PutToDict(dict, "pilot", feparm.pilot);
118 PutToDict(dict, "system", feparm.system);
121 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
123 PutToDict(dict, "tuner_type", "DVB-T");
124 PutToDict(dict, "frequency", feparm.frequency);
125 PutToDict(dict, "bandwidth", feparm.bandwidth);
126 PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
127 PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
128 PutToDict(dict, "constellation", feparm.modulation);
129 PutToDict(dict, "transmission_mode", feparm.transmission_mode);
130 PutToDict(dict, "guard_interval", feparm.guard_interval);
131 PutToDict(dict, "hierarchy_information", feparm.hierarchy);
132 PutToDict(dict, "inversion", feparm.inversion);
135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
137 PutToDict(dict, "tuner_type", "DVB-C");
138 PutToDict(dict, "frequency", feparm.frequency);
139 PutToDict(dict, "symbol_rate", feparm.symbol_rate);
140 PutToDict(dict, "modulation", feparm.modulation);
141 PutToDict(dict, "inversion", feparm.inversion);
142 PutToDict(dict, "fec_inner", feparm.fec_inner);
145 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
147 if (r.type == eServiceReference::idDVB)
149 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
152 case iServiceInformation::sTransponderData:
154 ePtr<eDVBResourceManager> res;
155 if (!eDVBResourceManager::getInstance(res))
157 ePtr<iDVBChannelList> db;
158 if (!res->getChannelList(db))
161 ref.getChannelID(chid);
162 ePtr<iDVBFrontendParameters> feparm;
163 if (!db->getChannelFrontendData(chid, feparm))
166 if (!feparm->getSystem(system))
168 ePyObject dict = PyDict_New();
171 case iDVBFrontend::feSatellite:
173 eDVBFrontendParametersSatellite s;
175 PutSatelliteDataToDict(dict, s);
178 case iDVBFrontend::feTerrestrial:
180 eDVBFrontendParametersTerrestrial t;
182 PutTerrestrialDataToDict(dict, t);
185 case iDVBFrontend::feCable:
187 eDVBFrontendParametersCable c;
189 PutCableDataToDict(dict, c);
193 eDebug("unknown frontend type %d", system);
208 DEFINE_REF(eStaticServiceDVBBouquetInformation);
210 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
212 ePtr<iDVBChannelList> db;
213 ePtr<eDVBResourceManager> res;
216 if ((err = eDVBResourceManager::getInstance(res)) != 0)
218 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
221 if ((err = res->getChannelList(db)) != 0)
223 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
228 if ((err = db->getBouquet(ref, bouquet)) != 0)
230 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
234 if ( bouquet && bouquet->m_bouquet_name.length() )
236 name = bouquet->m_bouquet_name;
243 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
245 if (ref.flags & eServiceReference::isGroup)
247 ePtr<iDVBChannelList> db;
248 ePtr<eDVBResourceManager> res;
250 if (eDVBResourceManager::getInstance(res))
252 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
256 if (res->getChannelList(db))
258 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
263 if (db->getBouquet(ref, bouquet))
265 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
269 int prio_order = eDVBFrontend::getTypePriorityOrder();
271 eDVBChannelID chid, chid_ignore;
272 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
273 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
275 static unsigned char prio_map[6][3] = {
276 { 3, 2, 1 }, // -S -C -T
277 { 3, 1, 2 }, // -S -T -C
278 { 2, 3, 1 }, // -C -S -T
279 { 1, 3, 2 }, // -C -T -S
280 { 1, 2, 3 }, // -T -C -S
281 { 2, 1, 3 } // -T -S -C
283 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
284 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
289 case 30000: // cached DVB-T channel
290 case 1: // DVB-T frontend
291 tmp = prio_map[prio_order][2];
293 case 40000: // cached DVB-C channel
295 tmp = prio_map[prio_order][1];
298 tmp = prio_map[prio_order][0];
303 m_playable_service = *it;
310 m_playable_service = eServiceReference();
314 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
319 #include <lib/dvb/epgcache.h>
321 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
323 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
326 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
328 DECLARE_REF(eStaticServiceDVBPVRInformation);
329 eServiceReference m_ref;
330 eDVBMetaParser m_parser;
332 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
333 RESULT getName(const eServiceReference &ref, std::string &name);
334 int getLength(const eServiceReference &ref);
335 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
336 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
337 int getInfo(const eServiceReference &ref, int w);
338 std::string getInfoString(const eServiceReference &ref,int w);
341 DEFINE_REF(eStaticServiceDVBPVRInformation);
343 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
346 m_parser.parseFile(ref.path);
349 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
351 ASSERT(ref == m_ref);
352 if (m_parser.m_name.size())
353 name = m_parser.m_name;
357 size_t n = name.rfind('/');
358 if (n != std::string::npos)
359 name = name.substr(n + 1);
364 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
366 ASSERT(ref == m_ref);
371 stat(ref.path.c_str(), &s);
373 if (tstools.openFile(ref.path.c_str()))
376 /* check if cached data is still valid */
377 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
378 return m_parser.m_length / 90000;
380 /* otherwise, re-calc length and update meta file */
382 if (tstools.calcLen(len))
385 m_parser.m_length = len;
386 m_parser.m_filesize = s.st_size;
387 m_parser.updateMeta(ref.path);
388 return m_parser.m_length / 90000;
391 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
395 case iServiceInformation::sDescription:
396 return iServiceInformation::resIsString;
397 case iServiceInformation::sServiceref:
398 return iServiceInformation::resIsString;
399 case iServiceInformation::sTimeCreate:
400 if (m_parser.m_time_create)
401 return m_parser.m_time_create;
403 return iServiceInformation::resNA;
405 return iServiceInformation::resNA;
409 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
413 case iServiceInformation::sDescription:
414 return m_parser.m_description;
415 case iServiceInformation::sServiceref:
416 return m_parser.m_ref.toString();
417 case iServiceInformation::sTags:
418 return m_parser.m_tags;
424 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
426 if (!ref.path.empty())
428 ePtr<eServiceEvent> event = new eServiceEvent;
429 std::string filename = ref.path;
430 filename.erase(filename.length()-2, 2);
432 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
442 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
444 DECLARE_REF(eDVBPVRServiceOfflineOperations);
445 eServiceReferenceDVB m_ref;
447 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
449 RESULT deleteFromDisk(int simulate);
450 RESULT getListOfFilenames(std::list<std::string> &);
453 DEFINE_REF(eDVBPVRServiceOfflineOperations);
455 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
459 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
465 std::list<std::string> res;
466 if (getListOfFilenames(res))
469 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
471 eDebug("FATAL !! can't get background file eraser");
473 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
475 eDebug("Removing %s...", i->c_str());
477 eraser->erase(i->c_str());
479 ::unlink(i->c_str());
486 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
489 res.push_back(m_ref.path);
491 // handling for old splitted recordings (enigma 1)
496 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
498 if (stat(buf, &s) < 0)
503 res.push_back(m_ref.path + ".meta");
504 res.push_back(m_ref.path + ".ap");
505 res.push_back(m_ref.path + ".cuts");
506 std::string tmp = m_ref.path;
507 tmp.erase(m_ref.path.length()-3);
508 res.push_back(tmp + ".eit");
512 DEFINE_REF(eServiceFactoryDVB)
514 eServiceFactoryDVB::eServiceFactoryDVB()
516 ePtr<eServiceCenter> sc;
518 eServiceCenter::getPrivInstance(sc);
521 std::list<std::string> extensions;
522 extensions.push_back("ts");
523 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
526 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
527 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
530 eServiceFactoryDVB::~eServiceFactoryDVB()
532 ePtr<eServiceCenter> sc;
534 eServiceCenter::getPrivInstance(sc);
536 sc->removeServiceFactory(eServiceFactoryDVB::id);
539 DEFINE_REF(eDVBServiceList);
541 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
545 eDVBServiceList::~eDVBServiceList()
549 RESULT eDVBServiceList::startQuery()
551 ePtr<iDVBChannelList> db;
552 ePtr<eDVBResourceManager> res;
555 if ((err = eDVBResourceManager::getInstance(res)) != 0)
557 eDebug("no resource manager");
560 if ((err = res->getChannelList(db)) != 0)
562 eDebug("no channel list");
566 ePtr<eDVBChannelQuery> q;
568 if (!m_parent.path.empty())
570 eDVBChannelQuery::compile(q, m_parent.path);
573 eDebug("compile query failed");
578 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
580 eDebug("startQuery failed");
587 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
589 eServiceReferenceDVB ref;
594 while (!m_query->getNextResult(ref))
598 list.sort(iListableServiceCompare(this));
603 // The first argument of this function is a format string to specify the order and
604 // the content of the returned list
605 // useable format options are
606 // R = Service Reference (as swig object .. this is very slow)
607 // S = Service Reference (as python string object .. same as ref.toString())
608 // C = Service Reference (as python string object .. same as ref.toCompareString())
609 // N = Service Name (as python string object)
610 // n = Short Service Name (short name brakets used) (as python string object)
611 // when exactly one return value per service is selected in the format string,
612 // then each value is directly a list entry
613 // when more than one value is returned per service, then the list is a list of
615 // unknown format string chars are returned as python None values !
616 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
619 std::list<eServiceReference> tmplist;
622 if (!format || !(retcount=strlen(format)))
623 format = "R"; // just return service reference swig object ...
625 if (!getContent(tmplist, sorted))
627 int services=tmplist.size();
628 ePtr<iStaticServiceInformation> sptr;
629 eServiceCenterPtr service_center;
631 if (strchr(format, 'N') || strchr(format, 'n'))
632 eServiceCenter::getPrivInstance(service_center);
634 ret = PyList_New(services);
635 std::list<eServiceReference>::iterator it(tmplist.begin());
637 for (int cnt=0; cnt < services; ++cnt)
639 eServiceReference &ref=*it++;
640 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
641 for (int i=0; i < retcount; ++i)
646 case 'R': // service reference (swig)object
647 tmp = NEW_eServiceReference(ref);
649 case 'C': // service reference compare string
650 tmp = PyString_FromString(ref.toCompareString().c_str());
652 case 'S': // service reference string
653 tmp = PyString_FromString(ref.toString().c_str());
655 case 'N': // service name
658 service_center->info(ref, sptr);
662 sptr->getName(ref, name);
664 // filter short name brakets
666 while((pos = name.find("\xc2\x86")) != std::string::npos)
668 while((pos = name.find("\xc2\x87")) != std::string::npos)
672 tmp = PyString_FromString(name.c_str());
676 tmp = PyString_FromString("<n/a>");
678 case 'n': // short service name
681 service_center->info(ref, sptr);
685 sptr->getName(ref, name);
686 name = buildShortName(name);
688 tmp = PyString_FromString(name.c_str());
692 tmp = PyString_FromString("<n/a>");
705 PyTuple_SET_ITEM(tuple, i, tmp);
707 PyList_SET_ITEM(ret, cnt, tmp);
711 PyList_SET_ITEM(ret, cnt, tuple);
714 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
717 RESULT eDVBServiceList::getNext(eServiceReference &ref)
722 return m_query->getNextResult((eServiceReferenceDVB&)ref);
725 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
727 if (m_parent.flags & eServiceReference::canDescent) // bouquet
729 ePtr<iDVBChannelList> db;
730 ePtr<eDVBResourceManager> resm;
732 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
735 if (db->getBouquet(m_parent, m_bouquet) != 0)
746 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
750 return m_bouquet->addService(ref, before);
753 RESULT eDVBServiceList::removeService(eServiceReference &ref)
757 return m_bouquet->removeService(ref);
760 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
764 return m_bouquet->moveService(ref, pos);
767 RESULT eDVBServiceList::flushChanges()
771 return m_bouquet->flushChanges();
774 RESULT eDVBServiceList::setListName(const std::string &name)
778 return m_bouquet->setListName(name);
781 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
783 ePtr<eDVBService> service;
784 int r = lookupService(service, ref);
787 // check resources...
788 ptr = new eDVBServicePlay(ref, service);
792 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
794 if (ref.path.empty())
796 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
805 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
807 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
808 if (list->startQuery())
818 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
820 /* is a listable service? */
821 if (ref.flags & eServiceReference::canDescent) // bouquet
823 if ( !ref.name.empty() ) // satellites or providers list
824 ptr = m_StaticServiceDVBInfo;
825 else // a dvb bouquet
826 ptr = m_StaticServiceDVBBouquetInfo;
828 else if (!ref.path.empty()) /* do we have a PVR service? */
829 ptr = new eStaticServiceDVBPVRInformation(ref);
830 else // normal dvb service
832 ePtr<eDVBService> service;
833 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
834 ptr = m_StaticServiceDVBInfo;
836 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
842 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
844 if (ref.path.empty())
850 ptr = new eDVBPVRServiceOfflineOperations(ref);
855 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
857 // TODO: handle the listing itself
858 // if (ref.... == -1) .. return "... bouquets ...";
859 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
861 ePtr<iDVBChannelList> db;
862 ePtr<eDVBResourceManager> res;
865 if ((err = eDVBResourceManager::getInstance(res)) != 0)
867 eDebug("no resource manager");
870 if ((err = res->getChannelList(db)) != 0)
872 eDebug("no channel list");
876 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
877 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
879 eDebug("getService failed!");
886 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
887 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
890 m_is_pvr = !m_reference.path.empty();
892 m_timeshift_enabled = m_timeshift_active = 0;
895 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
896 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
897 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
899 m_cuesheet_changed = 0;
900 m_cutlist_enabled = 1;
902 m_subtitle_widget = 0;
906 m_subtitle_sync_timer = eTimer::create(eApp);
908 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
911 eDVBServicePlay::~eDVBServicePlay()
913 delete m_subtitle_widget;
916 void eDVBServicePlay::gotNewEvent()
920 ePtr<eServiceEvent> m_event_now, m_event_next;
921 getEvent(m_event_now, 0);
922 getEvent(m_event_next, 1);
925 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
927 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
929 m_event((iPlayableService*)this, evUpdatedEventInfo);
932 void eDVBServicePlay::serviceEvent(int event)
934 m_tune_state = event;
938 case eDVBServicePMTHandler::eventTuned:
940 ePtr<iDVBDemux> m_demux;
941 if (!m_service_handler.getDataDemux(m_demux))
943 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
944 int sid = ref.getParentServiceID().get();
946 sid = ref.getServiceID().get();
947 if ( ref.getParentTransportStreamID().get() &&
948 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
949 m_event_handler.startOther(m_demux, sid);
951 m_event_handler.start(m_demux, sid);
953 m_event((iPlayableService*)this, evTunedIn);
956 case eDVBServicePMTHandler::eventNoResources:
957 case eDVBServicePMTHandler::eventNoPAT:
958 case eDVBServicePMTHandler::eventNoPATEntry:
959 case eDVBServicePMTHandler::eventNoPMT:
960 case eDVBServicePMTHandler::eventTuneFailed:
961 case eDVBServicePMTHandler::eventMisconfiguration:
963 eDebug("DVB service failed to tune - error %d", event);
964 m_event((iPlayableService*)this, evTuneFailed);
967 case eDVBServicePMTHandler::eventNewProgramInfo:
969 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
970 if (m_timeshift_enabled)
971 updateTimeshiftPids();
972 if (!m_timeshift_active)
974 if (m_first_program_info && m_is_pvr)
976 m_first_program_info = 0;
979 m_event((iPlayableService*)this, evUpdatedInfo);
982 case eDVBServicePMTHandler::eventEOF:
983 m_event((iPlayableService*)this, evEOF);
985 case eDVBServicePMTHandler::eventSOF:
986 m_event((iPlayableService*)this, evSOF);
991 void eDVBServicePlay::serviceEventTimeshift(int event)
995 case eDVBServicePMTHandler::eventNewProgramInfo:
996 if (m_timeshift_active)
999 case eDVBServicePMTHandler::eventSOF:
1000 m_event((iPlayableService*)this, evSOF);
1002 case eDVBServicePMTHandler::eventEOF:
1003 if ((!m_is_paused) && (m_skipmode >= 0))
1009 RESULT eDVBServicePlay::start()
1012 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1013 two (one for decoding, one for data source), as we must be prepared
1014 to start recording from the data demux. */
1016 m_cue = new eCueSheet();
1018 m_event(this, evStart);
1020 m_first_program_info = 1;
1021 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1022 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1024 /* inject EIT if there is a stored one */
1027 std::string filename = service.path;
1028 filename.erase(filename.length()-2, 2);
1030 ePtr<eServiceEvent> event = new eServiceEvent;
1031 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1033 ePtr<eServiceEvent> empty;
1034 m_event_handler.inject(event, 0);
1035 m_event_handler.inject(empty, 1);
1042 m_event(this, evStart);
1047 RESULT eDVBServicePlay::stop()
1049 /* add bookmark for last play position */
1052 pts_t play_position, length;
1053 if (!getPlayPosition(play_position))
1055 /* remove last position */
1056 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1058 if (i->what == 3) /* current play position */
1060 m_cue_entries.erase(i);
1061 i = m_cue_entries.begin();
1067 if (getLength(length))
1072 int perc = play_position * 100LL / length;
1074 /* only store last play position when between 1% and 99% */
1075 if ((1 < perc) && (perc < 99))
1076 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1078 m_cuesheet_changed = 1;
1082 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1084 m_service_handler_timeshift.free();
1085 m_service_handler.free();
1087 if (m_is_pvr && m_cuesheet_changed)
1090 /* save cuesheet only when main file is accessible. */
1091 if (!::stat(m_reference.path.c_str(), &s))
1094 m_event((iPlayableService*)this, evStopped);
1098 RESULT eDVBServicePlay::setTarget(int target)
1100 m_is_primary = !target;
1104 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1106 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1110 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1112 /* note: we check for timeshift to be enabled,
1113 not neccessary active. if you pause when timeshift
1114 is not active, you should activate it when unpausing */
1115 if ((!m_is_pvr) && (!m_timeshift_enabled))
1125 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1127 assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1128 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1129 setFastForward_internal(0);
1131 return m_decoder->setSlowMotion(ratio);
1136 RESULT eDVBServicePlay::setFastForward(int ratio)
1138 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1140 return setFastForward_internal(ratio);
1143 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1145 int skipmode, ffratio;
1151 } else if (ratio > 0)
1159 } else // if (ratio < 0)
1165 if (m_skipmode != skipmode)
1167 eDebug("setting cue skipmode to %d", skipmode);
1169 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1172 m_skipmode = skipmode;
1179 else if (ffratio != 1)
1180 return m_decoder->setFastForward(ffratio);
1182 return m_decoder->setTrickmode();
1185 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1187 if (m_is_pvr || m_timeshift_enabled)
1197 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1198 RESULT eDVBServicePlay::getLength(pts_t &len)
1200 ePtr<iDVBPVRChannel> pvr_channel;
1202 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1205 return pvr_channel->getLength(len);
1208 RESULT eDVBServicePlay::pause()
1210 eDebug("eDVBServicePlay::pause");
1211 setFastForward_internal(0);
1214 return m_decoder->pause();
1219 RESULT eDVBServicePlay::unpause()
1221 eDebug("eDVBServicePlay::unpause");
1222 setFastForward_internal(0);
1225 return m_decoder->play();
1230 RESULT eDVBServicePlay::seekTo(pts_t to)
1232 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1234 if (!m_decode_demux)
1237 ePtr<iDVBPVRChannel> pvr_channel;
1239 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1245 m_cue->seekTo(0, to);
1246 m_dvb_subtitle_pages.clear();
1247 m_subtitle_pages.clear();
1252 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1254 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1256 if (!m_decode_demux)
1259 ePtr<iDVBPVRChannel> pvr_channel;
1261 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1266 /* HACK until we have skip-AP api */
1267 if ((to > 0) && (to < 100))
1275 m_cue->seekTo(mode, to);
1276 m_dvb_subtitle_pages.clear();
1277 m_subtitle_pages.clear();
1281 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1283 ePtr<iDVBPVRChannel> pvr_channel;
1285 if (!m_decode_demux)
1288 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1293 /* if there is a decoder, use audio or video PTS */
1296 r = m_decoder->getPTS(0, pos);
1302 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1305 RESULT eDVBServicePlay::setTrickmode(int trick)
1307 /* currently unimplemented */
1311 RESULT eDVBServicePlay::isCurrentlySeekable()
1313 return m_is_pvr || m_timeshift_active;
1316 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1322 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1328 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1334 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1340 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1346 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1349 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1350 (m_timeshift_enabled || !m_is_pvr))
1352 if (!m_timeshift_enabled)
1354 /* query config path */
1356 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1357 eDebug("could not query ts path from config");
1361 /* we need enough diskspace */
1363 if (statfs(tspath.c_str(), &fs) < 0)
1365 eDebug("statfs failed!");
1369 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1371 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1381 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1392 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1398 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1404 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1410 RESULT eDVBServicePlay::getName(std::string &name)
1414 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1415 return i->getName(m_reference, name);
1419 m_dvb_service->getName(m_reference, name);
1423 else if (!m_reference.name.empty())
1424 eStaticServiceDVBInformation().getName(m_reference, name);
1426 name = "DVB service";
1430 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1432 return m_event_handler.getEvent(evt, nownext);
1435 int eDVBServicePlay::getInfo(int w)
1437 eDVBServicePMTHandler::program program;
1440 return resIsPyObject;
1442 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1444 int no_program_info = 0;
1446 if (h.getProgramInfo(program))
1447 no_program_info = 1;
1453 return m_decoder->getVideoHeight();
1457 return m_decoder->getVideoWidth();
1461 return m_decoder->getVideoFrameRate();
1465 return m_decoder->getVideoProgressive();
1471 aspect = m_decoder->getVideoAspect();
1472 if (no_program_info)
1474 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1476 ePtr<eServiceEvent> evt;
1477 if (!m_event_handler.getEvent(evt, 0))
1479 ePtr<eComponentData> data;
1480 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1482 if ( data->getStreamContent() == 1 )
1484 switch(data->getComponentType())
1487 case 1: // 4:3 SD PAL
1489 case 3: // 16:9 SD PAL
1490 case 4: // > 16:9 PAL
1491 case 5: // 4:3 SD NTSC
1493 case 7: // 16:9 SD NTSC
1494 case 8: // > 16:9 NTSC
1497 case 9: // 4:3 HD PAL
1499 case 0xB: // 16:9 HD PAL
1500 case 0xC: // > 16:9 HD PAL
1501 case 0xD: // 4:3 HD NTSC
1503 case 0xF: // 16:9 HD NTSC
1504 case 0x10: // > 16:9 HD PAL
1505 return data->getComponentType();
1515 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1516 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1517 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1518 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1519 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1520 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1521 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1522 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1523 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1524 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1525 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1526 case sProvider: if (!m_dvb_service) return -1; return -2;
1527 case sServiceref: return resIsString;
1528 case sDVBState: return m_tune_state;
1535 std::string eDVBServicePlay::getInfoString(int w)
1540 if (!m_dvb_service) return "";
1541 return m_dvb_service->m_provider_name;
1543 return m_reference.toString();
1547 return iServiceInformation::getInfoString(w);
1550 PyObject *eDVBServicePlay::getInfoObject(int w)
1555 return m_service_handler.getCaIds();
1556 case sTransponderData:
1557 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1561 return iServiceInformation::getInfoObject(w);
1564 int eDVBServicePlay::getNumberOfTracks()
1566 eDVBServicePMTHandler::program program;
1567 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1568 if (h.getProgramInfo(program))
1570 return program.audioStreams.size();
1573 int eDVBServicePlay::getCurrentTrack()
1575 eDVBServicePMTHandler::program program;
1576 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1577 if (h.getProgramInfo(program))
1580 int max = program.audioStreams.size();
1583 for (i = 0; i < max; ++i)
1584 if (program.audioStreams[i].pid == m_current_audio_pid)
1590 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1592 int ret = selectAudioStream(i);
1594 if (m_decoder->play())
1600 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1602 eDVBServicePMTHandler::program program;
1603 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1605 if (h.getProgramInfo(program))
1608 if (i >= program.audioStreams.size())
1611 info.m_pid = program.audioStreams[i].pid;
1613 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1614 info.m_description = "MPEG";
1615 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1616 info.m_description = "AC3";
1617 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1618 info.m_description = "AAC";
1619 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1620 info.m_description = "AAC-HE";
1621 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1622 info.m_description = "DTS";
1624 info.m_description = "???";
1626 if (program.audioStreams[i].component_tag != -1)
1628 ePtr<eServiceEvent> evt;
1629 if (!m_event_handler.getEvent(evt, 0))
1631 ePtr<eComponentData> data;
1632 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1633 info.m_language = data->getText();
1637 if (info.m_language.empty())
1638 info.m_language = program.audioStreams[i].language_code;
1643 int eDVBServicePlay::selectAudioStream(int i)
1645 eDVBServicePMTHandler::program program;
1646 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1648 if (h.getProgramInfo(program))
1651 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1659 stream = program.defaultAudioStream;
1661 int apid = -1, apidtype = -1;
1663 if (((unsigned int)stream) < program.audioStreams.size())
1665 apid = program.audioStreams[stream].pid;
1666 apidtype = program.audioStreams[stream].type;
1669 m_current_audio_pid = apid;
1671 if (m_decoder->setAudioPID(apid, apidtype))
1673 eDebug("set audio pid failed");
1677 /* 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 */
1678 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1681 ePtr<iDVBDemux> data_demux;
1682 if (!h.getDataDemux(data_demux))
1684 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1685 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1689 /* if we decided that we need one, update the pid */
1691 m_rds_decoder->start(apid);
1693 /* store new pid as default only when:
1694 a.) we have an entry in the service db for the current service,
1695 b.) we are not playing back something,
1696 c.) we are not selecting the default entry. (we wouldn't change
1697 anything in the best case, or destroy the default setting in
1698 case the real default is not yet available.)
1700 if (m_dvb_service && !m_is_pvr && ((i != -1)
1701 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1703 if (apidtype == eDVBAudio::aMPEG)
1705 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1706 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1710 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1711 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1715 h.resetCachedProgram();
1720 int eDVBServicePlay::getCurrentChannel()
1722 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1725 RESULT eDVBServicePlay::selectChannel(int i)
1727 if (i < LEFT || i > RIGHT || i == STEREO)
1730 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1732 m_decoder->setAudioChannel(i);
1736 std::string eDVBServicePlay::getText(int x)
1742 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1744 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1749 void eDVBServicePlay::rdsDecoderEvent(int what)
1753 case eDVBRdsDecoder::RadioTextChanged:
1754 m_event((iPlayableService*)this, evUpdatedRadioText);
1756 case eDVBRdsDecoder::RtpTextChanged:
1757 m_event((iPlayableService*)this, evUpdatedRtpText);
1759 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1760 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1762 case eDVBRdsDecoder::RecvRassSlidePic:
1763 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1768 void eDVBServicePlay::showRassSlidePicture()
1774 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1775 if (rass_slide_pic.length())
1776 m_decoder->showSinglePic(rass_slide_pic.c_str());
1778 eDebug("empty filename for rass slide picture received!!");
1781 eDebug("no MPEG Decoder to show iframes avail");
1784 eDebug("showRassSlidePicture called.. but not decoder");
1787 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1793 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1794 if (rass_interactive_pic.length())
1795 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1797 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1800 eDebug("no MPEG Decoder to show iframes avail");
1803 eDebug("showRassInteractivePic called.. but not decoder");
1806 ePyObject eDVBServicePlay::getRassInteractiveMask()
1809 return m_rds_decoder->getRassPictureMask();
1813 int eDVBServiceBase::getFrontendInfo(int w)
1815 eUsePtr<iDVBChannel> channel;
1816 if(m_service_handler.getChannel(channel))
1818 ePtr<iDVBFrontend> fe;
1819 if(channel->getFrontend(fe))
1821 return fe->readFrontendData(w);
1824 PyObject *eDVBServiceBase::getFrontendData()
1826 ePyObject ret = PyDict_New();
1829 eUsePtr<iDVBChannel> channel;
1830 if(!m_service_handler.getChannel(channel))
1832 ePtr<iDVBFrontend> fe;
1833 if(!channel->getFrontend(fe))
1834 fe->getFrontendData(ret);
1842 PyObject *eDVBServiceBase::getFrontendStatus()
1844 ePyObject ret = PyDict_New();
1847 eUsePtr<iDVBChannel> channel;
1848 if(!m_service_handler.getChannel(channel))
1850 ePtr<iDVBFrontend> fe;
1851 if(!channel->getFrontend(fe))
1852 fe->getFrontendStatus(ret);
1860 PyObject *eDVBServiceBase::getTransponderData(bool original)
1862 ePyObject ret = PyDict_New();
1865 eUsePtr<iDVBChannel> channel;
1866 if(!m_service_handler.getChannel(channel))
1868 ePtr<iDVBFrontend> fe;
1869 if(!channel->getFrontend(fe))
1871 fe->getTransponderData(ret, original);
1872 ePtr<iDVBFrontendParameters> feparm;
1873 channel->getCurrentFrontendParameters(feparm);
1876 eDVBFrontendParametersSatellite osat;
1877 if (!feparm->getDVBS(osat))
1879 PutToDict(ret, "orbital_position", osat.orbital_position);
1880 PutToDict(ret, "polarization", osat.polarisation);
1891 PyObject *eDVBServiceBase::getAll(bool original)
1893 ePyObject ret = getTransponderData(original);
1896 eUsePtr<iDVBChannel> channel;
1897 if(!m_service_handler.getChannel(channel))
1899 ePtr<iDVBFrontend> fe;
1900 if(!channel->getFrontend(fe))
1902 fe->getFrontendData(ret);
1903 fe->getFrontendStatus(ret);
1910 int eDVBServicePlay::getNumberOfSubservices()
1912 ePtr<eServiceEvent> evt;
1913 if (!m_event_handler.getEvent(evt, 0))
1914 return evt->getNumOfLinkageServices();
1918 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1920 ePtr<eServiceEvent> evt;
1921 if (!m_event_handler.getEvent(evt, 0))
1923 if (!evt->getLinkageService(sub, m_reference, n))
1926 sub.type=eServiceReference::idInvalid;
1930 RESULT eDVBServicePlay::startTimeshift()
1932 ePtr<iDVBDemux> demux;
1934 eDebug("Start timeshift!");
1936 if (m_timeshift_enabled)
1939 /* start recording with the data demux. */
1940 if (m_service_handler.getDataDemux(demux))
1943 demux->createTSRecorder(m_record);
1948 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1949 eDebug("could not query ts path");
1952 tspath.append("/timeshift.XXXXXX");
1954 templ = new char[tspath.length() + 1];
1955 strcpy(templ, tspath.c_str());
1957 m_timeshift_fd = mkstemp(templ);
1958 m_timeshift_file = std::string(templ);
1960 eDebug("recording to %s", templ);
1964 if (m_timeshift_fd < 0)
1970 m_record->setTargetFD(m_timeshift_fd);
1972 m_timeshift_enabled = 1;
1974 updateTimeshiftPids();
1980 RESULT eDVBServicePlay::stopTimeshift()
1982 if (!m_timeshift_enabled)
1987 m_timeshift_enabled = 0;
1992 close(m_timeshift_fd);
1993 eDebug("remove timeshift file");
1994 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1999 int eDVBServicePlay::isTimeshiftActive()
2001 return m_timeshift_enabled && m_timeshift_active;
2004 RESULT eDVBServicePlay::activateTimeshift()
2006 if (!m_timeshift_enabled)
2009 if (!m_timeshift_active)
2011 switchToTimeshift();
2018 PyObject *eDVBServicePlay::getCutList()
2020 ePyObject list = PyList_New(0);
2022 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2024 ePyObject tuple = PyTuple_New(2);
2025 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2026 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2027 PyList_Append(list, tuple);
2034 void eDVBServicePlay::setCutList(ePyObject list)
2036 if (!PyList_Check(list))
2038 int size = PyList_Size(list);
2041 m_cue_entries.clear();
2043 for (i=0; i<size; ++i)
2045 ePyObject tuple = PyList_GET_ITEM(list, i);
2046 if (!PyTuple_Check(tuple))
2048 eDebug("non-tuple in cutlist");
2051 if (PyTuple_Size(tuple) != 2)
2053 eDebug("cutlist entries need to be a 2-tuple");
2056 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2057 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2059 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2062 pts_t pts = PyLong_AsLongLong(ppts);
2063 int type = PyInt_AsLong(ptype);
2064 m_cue_entries.insert(cueEntry(pts, type));
2065 eDebug("adding %08llx, %d", pts, type);
2067 m_cuesheet_changed = 1;
2069 cutlistToCuesheet();
2070 m_event((iPlayableService*)this, evCuesheetChanged);
2073 void eDVBServicePlay::setCutListEnable(int enable)
2075 m_cutlist_enabled = enable;
2076 cutlistToCuesheet();
2079 void eDVBServicePlay::updateTimeshiftPids()
2084 eDVBServicePMTHandler::program program;
2085 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2087 if (h.getProgramInfo(program))
2091 std::set<int> pids_to_record;
2092 pids_to_record.insert(0); // PAT
2093 if (program.pmtPid != -1)
2094 pids_to_record.insert(program.pmtPid); // PMT
2096 if (program.textPid != -1)
2097 pids_to_record.insert(program.textPid); // Videotext
2099 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2100 i(program.videoStreams.begin());
2101 i != program.videoStreams.end(); ++i)
2102 pids_to_record.insert(i->pid);
2104 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2105 i(program.audioStreams.begin());
2106 i != program.audioStreams.end(); ++i)
2107 pids_to_record.insert(i->pid);
2109 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2110 i(program.subtitleStreams.begin());
2111 i != program.subtitleStreams.end(); ++i)
2112 pids_to_record.insert(i->pid);
2114 std::set<int> new_pids, obsolete_pids;
2116 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2117 m_pids_active.begin(), m_pids_active.end(),
2118 std::inserter(new_pids, new_pids.begin()));
2120 std::set_difference(
2121 m_pids_active.begin(), m_pids_active.end(),
2122 pids_to_record.begin(), pids_to_record.end(),
2123 std::inserter(new_pids, new_pids.begin())
2126 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2127 m_record->addPID(*i);
2129 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2130 m_record->removePID(*i);
2134 void eDVBServicePlay::switchToLive()
2136 if (!m_timeshift_active)
2142 m_teletext_parser = 0;
2144 m_subtitle_parser = 0;
2145 m_new_dvb_subtitle_page_connection = 0;
2146 m_new_subtitle_page_connection = 0;
2147 m_rds_decoder_event_connection = 0;
2148 m_video_event_connection = 0;
2150 /* free the timeshift service handler, we need the resources */
2151 m_service_handler_timeshift.free();
2152 m_timeshift_active = 0;
2154 m_event((iPlayableService*)this, evSeekableStatusChanged);
2159 void eDVBServicePlay::switchToTimeshift()
2161 if (m_timeshift_active)
2166 m_teletext_parser = 0;
2168 m_subtitle_parser = 0;
2169 m_new_subtitle_page_connection = 0;
2170 m_new_dvb_subtitle_page_connection = 0;
2171 m_rds_decoder_event_connection = 0;
2172 m_video_event_connection = 0;
2174 m_timeshift_active = 1;
2176 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2177 r.path = m_timeshift_file;
2179 m_cue = new eCueSheet();
2180 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2182 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2184 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2186 m_event((iPlayableService*)this, evSeekableStatusChanged);
2189 void eDVBServicePlay::updateDecoder()
2191 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2193 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2195 eDVBServicePMTHandler::program program;
2196 if (h.getProgramInfo(program))
2197 eDebug("getting program info failed.");
2200 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2201 if (!program.videoStreams.empty())
2203 eDebugNoNewLine(" (");
2204 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2205 i(program.videoStreams.begin());
2206 i != program.videoStreams.end(); ++i)
2213 if (i != program.videoStreams.begin())
2214 eDebugNoNewLine(", ");
2215 eDebugNoNewLine("%04x", i->pid);
2217 eDebugNoNewLine(")");
2219 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2220 if (!program.audioStreams.empty())
2222 eDebugNoNewLine(" (");
2223 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2224 i(program.audioStreams.begin());
2225 i != program.audioStreams.end(); ++i)
2227 if (i != program.audioStreams.begin())
2228 eDebugNoNewLine(", ");
2229 eDebugNoNewLine("%04x", i->pid);
2231 eDebugNoNewLine(")");
2233 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2234 pcrpid = program.pcrPid;
2235 eDebug(", and the text pid is %04x", program.textPid);
2236 tpid = program.textPid;
2241 h.getDecodeDemux(m_decode_demux);
2244 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2246 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2247 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2248 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2249 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2250 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2253 m_teletext_parser = 0;
2254 m_subtitle_parser = 0;
2258 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2265 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2266 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2267 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2269 else // subservice or recording
2271 eServiceReferenceDVB ref;
2272 m_service_handler.getServiceReference(ref);
2273 eServiceReferenceDVB parent = ref.getParentServiceReference();
2278 ePtr<eDVBResourceManager> res_mgr;
2279 if (!eDVBResourceManager::getInstance(res_mgr))
2281 ePtr<iDVBChannelList> db;
2282 if (!res_mgr->getChannelList(db))
2284 ePtr<eDVBService> origService;
2285 if (!db->getService(parent, origService))
2287 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2288 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2294 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2295 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2297 m_decoder->setVideoPID(vpid, vpidtype);
2298 selectAudioStream();
2300 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2301 m_decoder->setSyncPCR(pcrpid);
2303 m_decoder->setSyncPCR(-1);
2305 m_decoder->setTextPID(tpid);
2307 m_teletext_parser->start(program.textPid);
2310 m_decoder->setTrickmode();
2317 if (vpid > 0 && vpid < 0x2000)
2321 std::string radio_pic;
2322 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2323 m_decoder->setRadioPic(radio_pic);
2326 m_decoder->setAudioChannel(achannel);
2328 /* don't worry about non-existing services, nor pvr services */
2329 if (m_dvb_service && !m_is_pvr)
2331 /* (audio pid will be set in selectAudioTrack */
2332 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2333 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2334 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2335 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2338 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2341 void eDVBServicePlay::loadCuesheet()
2343 std::string filename = m_reference.path + ".cuts";
2345 m_cue_entries.clear();
2347 FILE *f = fopen(filename.c_str(), "rb");
2351 eDebug("loading cuts..");
2354 unsigned long long where;
2357 if (!fread(&where, sizeof(where), 1, f))
2359 if (!fread(&what, sizeof(what), 1, f))
2362 #if BYTE_ORDER == LITTLE_ENDIAN
2363 where = bswap_64(where);
2370 m_cue_entries.insert(cueEntry(where, what));
2373 eDebug("%d entries", m_cue_entries.size());
2375 eDebug("cutfile not found!");
2377 m_cuesheet_changed = 0;
2378 cutlistToCuesheet();
2379 m_event((iPlayableService*)this, evCuesheetChanged);
2382 void eDVBServicePlay::saveCuesheet()
2384 std::string filename = m_reference.path + ".cuts";
2386 FILE *f = fopen(filename.c_str(), "wb");
2390 unsigned long long where;
2393 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2395 #if BYTE_ORDER == BIG_ENDIAN
2398 where = bswap_64(i->where);
2400 what = htonl(i->what);
2401 fwrite(&where, sizeof(where), 1, f);
2402 fwrite(&what, sizeof(what), 1, f);
2408 m_cuesheet_changed = 0;
2411 void eDVBServicePlay::cutlistToCuesheet()
2415 eDebug("no cue sheet");
2420 if (!m_cutlist_enabled)
2422 m_cue->commitSpans();
2423 eDebug("cutlists were disabled");
2427 pts_t in = 0, out = 0, length = 0;
2431 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2435 if (i == m_cue_entries.end())
2438 if (i->what == 0) /* in */
2442 } else if (i->what == 1) /* out */
2444 else /* mark (2) or last play position (3) */
2461 m_cue->addSourceSpan(in, out);
2465 if (i == m_cue_entries.end())
2468 m_cue->commitSpans();
2471 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2473 if (m_subtitle_widget)
2474 disableSubtitles(parent);
2477 int tuplesize = PyTuple_Size(tuple);
2480 if (!PyTuple_Check(tuple))
2486 entry = PyTuple_GET_ITEM(tuple, 0);
2488 if (!PyInt_Check(entry))
2491 type = PyInt_AsLong(entry);
2493 if (type == 1) // teletext subtitles
2495 int page, magazine, pid;
2499 if (!m_teletext_parser)
2501 eDebug("enable teletext subtitles.. no parser !!!");
2505 entry = PyTuple_GET_ITEM(tuple, 1);
2506 if (!PyInt_Check(entry))
2508 pid = PyInt_AsLong(entry);
2510 entry = PyTuple_GET_ITEM(tuple, 2);
2511 if (!PyInt_Check(entry))
2513 page = PyInt_AsLong(entry);
2515 entry = PyTuple_GET_ITEM(tuple, 3);
2516 if (!PyInt_Check(entry))
2518 magazine = PyInt_AsLong(entry);
2520 m_subtitle_widget = new eSubtitleWidget(parent);
2521 m_subtitle_widget->resize(parent->size()); /* full size */
2522 m_teletext_parser->setPageAndMagazine(page, magazine);
2524 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2528 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2529 if (!m_subtitle_parser)
2531 eDebug("enable dvb subtitles.. no parser !!!");
2537 entry = PyTuple_GET_ITEM(tuple, 1);
2538 if (!PyInt_Check(entry))
2540 pid = PyInt_AsLong(entry);
2542 entry = PyTuple_GET_ITEM(tuple, 2);
2543 if (!PyInt_Check(entry))
2545 composition_page_id = PyInt_AsLong(entry);
2547 entry = PyTuple_GET_ITEM(tuple, 3);
2548 if (!PyInt_Check(entry))
2550 ancillary_page_id = PyInt_AsLong(entry);
2552 m_subtitle_widget = new eSubtitleWidget(parent);
2553 m_subtitle_widget->resize(parent->size()); /* full size */
2554 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2556 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2562 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2563 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2564 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2568 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2570 delete m_subtitle_widget;
2571 m_subtitle_widget = 0;
2572 if (m_subtitle_parser)
2574 m_subtitle_parser->stop();
2575 m_dvb_subtitle_pages.clear();
2577 if (m_teletext_parser)
2579 m_teletext_parser->setPageAndMagazine(-1, -1);
2580 m_subtitle_pages.clear();
2583 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2587 PyObject *eDVBServicePlay::getCachedSubtitle()
2591 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2594 unsigned int data = (unsigned int)tmp;
2595 int pid = (data&0xFFFF0000)>>16;
2596 ePyObject tuple = PyTuple_New(4);
2597 eDVBServicePMTHandler::program program;
2598 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2599 if (!h.getProgramInfo(program))
2601 if (program.textPid==pid) // teletext
2602 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2604 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2605 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2606 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2607 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2615 PyObject *eDVBServicePlay::getSubtitleList()
2617 if (!m_teletext_parser)
2620 ePyObject l = PyList_New(0);
2621 std::set<int> added_ttx_pages;
2623 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2624 m_teletext_parser->m_found_subtitle_pages;
2626 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2627 eDVBServicePMTHandler::program program;
2628 if (h.getProgramInfo(program))
2629 eDebug("getting program info failed.");
2632 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2633 it != program.subtitleStreams.end(); ++it)
2635 switch(it->subtitling_type)
2637 case 0x01: // ebu teletext subtitles
2639 int page_number = it->teletext_page_number & 0xFF;
2640 int magazine_number = it->teletext_magazine_number & 7;
2641 int hash = magazine_number << 8 | page_number;
2642 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2644 ePyObject tuple = PyTuple_New(5);
2645 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2646 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2647 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2648 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2649 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2650 PyList_Append(l, tuple);
2652 added_ttx_pages.insert(hash);
2657 case 0x20 ... 0x23: // dvb subtitles
2659 ePyObject tuple = PyTuple_New(5);
2660 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2661 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2662 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2663 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2664 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2665 PyList_Insert(l, 0, tuple);
2673 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2674 it != subs.end(); ++it)
2676 int page_number = it->teletext_page_number & 0xFF;
2677 int magazine_number = it->teletext_magazine_number & 7;
2678 int hash = magazine_number << 8 | page_number;
2679 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2681 ePyObject tuple = PyTuple_New(5);
2682 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2683 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2684 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2685 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2686 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2687 PyList_Append(l, tuple);
2695 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2697 if (m_subtitle_widget)
2701 m_decoder->getPTS(0, pos);
2702 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2703 m_subtitle_pages.push_back(page);
2704 checkSubtitleTiming();
2708 void eDVBServicePlay::checkSubtitleTiming()
2710 eDebug("checkSubtitleTiming");
2711 if (!m_subtitle_widget)
2715 enum { TELETEXT, DVB } type;
2716 eDVBTeletextSubtitlePage page;
2717 eDVBSubtitlePage dvb_page;
2719 if (!m_subtitle_pages.empty())
2721 page = m_subtitle_pages.front();
2723 show_time = page.m_pts;
2725 else if (!m_dvb_subtitle_pages.empty())
2727 dvb_page = m_dvb_subtitle_pages.front();
2729 show_time = dvb_page.m_show_time;
2737 m_decoder->getPTS(0, pos);
2739 eDebug("%lld %lld", pos, show_time);
2740 int diff = show_time - pos;
2743 eDebug("[late (%d ms)]", -diff / 90);
2746 // if (diff > 900000)
2748 // eDebug("[invalid]");
2754 if (type == TELETEXT)
2756 eDebug("display teletext subtitle page %lld", show_time);
2757 m_subtitle_widget->setPage(page);
2758 m_subtitle_pages.pop_front();
2762 eDebug("display dvb subtitle Page %lld", show_time);
2763 m_subtitle_widget->setPage(dvb_page);
2764 m_dvb_subtitle_pages.pop_front();
2768 eDebug("start subtitle delay %d", diff / 90);
2769 m_subtitle_sync_timer->start(diff / 90, 1);
2775 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2777 if (m_subtitle_widget)
2781 m_decoder->getPTS(0, pos);
2782 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2783 m_dvb_subtitle_pages.push_back(p);
2784 checkSubtitleTiming();
2788 int eDVBServicePlay::getAC3Delay()
2791 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2793 return m_decoder->getAC3Delay();
2798 int eDVBServicePlay::getPCMDelay()
2801 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2803 return m_decoder->getPCMDelay();
2808 void eDVBServicePlay::setAC3Delay(int delay)
2811 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2813 m_decoder->setAC3Delay(delay);
2816 void eDVBServicePlay::setPCMDelay(int delay)
2819 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2821 m_decoder->setPCMDelay(delay);
2824 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2826 switch(event.type) {
2827 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2828 m_event((iPlayableService*)this, evVideoSizeChanged);
2830 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2831 m_event((iPlayableService*)this, evVideoFramerateChanged);
2833 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2834 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2841 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2847 PyObject *eDVBServicePlay::getStreamingData()
2849 eDVBServicePMTHandler::program program;
2850 if (m_service_handler.getProgramInfo(program))
2855 ePyObject r = program.createPythonObject();
2856 ePtr<iDVBDemux> demux;
2857 if (!m_service_handler.getDataDemux(demux))
2860 if (!demux->getCADemuxID(demux_id))
2861 PutToDict(r, "demux", demux_id);
2868 DEFINE_REF(eDVBServicePlay)
2870 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2874 case iServiceInformation::sTransponderData:
2875 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2879 return iStaticServiceInformation::getInfoObject(ref, w);
2882 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");