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 + ".sc");
510 res.push_back(m_ref.path + ".cuts");
511 std::string tmp = m_ref.path;
512 tmp.erase(m_ref.path.length()-3);
513 res.push_back(tmp + ".eit");
517 DEFINE_REF(eServiceFactoryDVB)
519 eServiceFactoryDVB::eServiceFactoryDVB()
521 ePtr<eServiceCenter> sc;
523 eServiceCenter::getPrivInstance(sc);
526 std::list<std::string> extensions;
527 extensions.push_back("ts");
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))
1010 eDebug("timeshift EOF, so let's go live");
1017 RESULT eDVBServicePlay::start()
1020 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1021 two (one for decoding, one for data source), as we must be prepared
1022 to start recording from the data demux. */
1024 m_cue = new eCueSheet();
1026 m_event(this, evStart);
1028 m_first_program_info = 1;
1029 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1030 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1032 /* inject EIT if there is a stored one */
1035 std::string filename = service.path;
1036 filename.erase(filename.length()-2, 2);
1038 ePtr<eServiceEvent> event = new eServiceEvent;
1039 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1041 ePtr<eServiceEvent> empty;
1042 m_event_handler.inject(event, 0);
1043 m_event_handler.inject(empty, 1);
1050 m_event(this, evStart);
1055 RESULT eDVBServicePlay::stop()
1057 /* add bookmark for last play position */
1060 pts_t play_position, length;
1061 if (!getPlayPosition(play_position))
1063 /* remove last position */
1064 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1066 if (i->what == 3) /* current play position */
1068 m_cue_entries.erase(i);
1069 i = m_cue_entries.begin();
1075 if (getLength(length))
1080 int perc = play_position * 100LL / length;
1082 /* only store last play position when between 1% and 99% */
1083 if ((1 < perc) && (perc < 99))
1084 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1086 m_cuesheet_changed = 1;
1090 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1092 m_service_handler_timeshift.free();
1093 m_service_handler.free();
1095 if (m_is_pvr && m_cuesheet_changed)
1098 /* save cuesheet only when main file is accessible. */
1099 if (!::stat(m_reference.path.c_str(), &s))
1102 m_event((iPlayableService*)this, evStopped);
1106 RESULT eDVBServicePlay::setTarget(int target)
1108 m_is_primary = !target;
1112 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1114 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1118 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1120 /* note: we check for timeshift to be enabled,
1121 not neccessary active. if you pause when timeshift
1122 is not active, you should activate it when unpausing */
1123 if ((!m_is_pvr) && (!m_timeshift_enabled))
1133 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1135 assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1136 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1137 setFastForward_internal(0);
1139 return m_decoder->setSlowMotion(ratio);
1144 RESULT eDVBServicePlay::setFastForward(int ratio)
1146 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1148 return setFastForward_internal(ratio);
1151 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1153 int skipmode, ffratio;
1159 } else if (ratio > 0)
1167 } else // if (ratio < 0)
1173 if (m_skipmode != skipmode)
1175 eDebug("setting cue skipmode to %d", skipmode);
1177 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1180 m_skipmode = skipmode;
1186 ; /* return m_decoder->play(); is done in caller*/
1187 else if (ffratio != 1)
1188 return m_decoder->setFastForward(ffratio);
1190 return m_decoder->setTrickmode();
1193 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1195 if (m_is_pvr || m_timeshift_enabled)
1205 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1206 RESULT eDVBServicePlay::getLength(pts_t &len)
1208 ePtr<iDVBPVRChannel> pvr_channel;
1210 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1213 return pvr_channel->getLength(len);
1216 RESULT eDVBServicePlay::pause()
1218 eDebug("eDVBServicePlay::pause");
1219 setFastForward_internal(0);
1223 return m_decoder->pause();
1228 RESULT eDVBServicePlay::unpause()
1230 eDebug("eDVBServicePlay::unpause");
1231 setFastForward_internal(0);
1235 return m_decoder->play();
1240 RESULT eDVBServicePlay::seekTo(pts_t to)
1242 eDebug("eDVBServicePlay::seekTo: jump %lld", 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))
1255 m_cue->seekTo(0, to);
1256 m_dvb_subtitle_pages.clear();
1257 m_subtitle_pages.clear();
1262 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1264 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1266 if (!m_decode_demux)
1269 ePtr<iDVBPVRChannel> pvr_channel;
1271 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1276 /* HACK until we have skip-AP api */
1277 if ((to > 0) && (to < 100))
1285 m_cue->seekTo(mode, to);
1286 m_dvb_subtitle_pages.clear();
1287 m_subtitle_pages.clear();
1291 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1293 ePtr<iDVBPVRChannel> pvr_channel;
1295 if (!m_decode_demux)
1298 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1303 /* if there is a decoder, use audio or video PTS */
1306 r = m_decoder->getPTS(0, pos);
1312 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1315 RESULT eDVBServicePlay::setTrickmode(int trick)
1317 /* currently unimplemented */
1321 RESULT eDVBServicePlay::isCurrentlySeekable()
1323 return m_is_pvr || m_timeshift_active;
1326 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1332 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1338 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1344 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1350 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1356 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1359 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1360 (m_timeshift_enabled || !m_is_pvr))
1362 if (!m_timeshift_enabled)
1364 /* query config path */
1366 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1367 eDebug("could not query ts path from config");
1371 /* we need enough diskspace */
1373 if (statfs(tspath.c_str(), &fs) < 0)
1375 eDebug("statfs failed!");
1379 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1381 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1391 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1402 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1408 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1414 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1420 RESULT eDVBServicePlay::getName(std::string &name)
1424 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1425 return i->getName(m_reference, name);
1429 m_dvb_service->getName(m_reference, name);
1433 else if (!m_reference.name.empty())
1434 eStaticServiceDVBInformation().getName(m_reference, name);
1436 name = "DVB service";
1440 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1442 return m_event_handler.getEvent(evt, nownext);
1445 int eDVBServicePlay::getInfo(int w)
1447 eDVBServicePMTHandler::program program;
1450 return resIsPyObject;
1452 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1454 int no_program_info = 0;
1456 if (h.getProgramInfo(program))
1457 no_program_info = 1;
1463 return m_decoder->getVideoHeight();
1467 return m_decoder->getVideoWidth();
1471 return m_decoder->getVideoFrameRate();
1475 return m_decoder->getVideoProgressive();
1481 aspect = m_decoder->getVideoAspect();
1482 if (no_program_info)
1484 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1486 ePtr<eServiceEvent> evt;
1487 if (!m_event_handler.getEvent(evt, 0))
1489 ePtr<eComponentData> data;
1490 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1492 if ( data->getStreamContent() == 1 )
1494 switch(data->getComponentType())
1497 case 1: // 4:3 SD PAL
1499 case 3: // 16:9 SD PAL
1500 case 4: // > 16:9 PAL
1501 case 5: // 4:3 SD NTSC
1503 case 7: // 16:9 SD NTSC
1504 case 8: // > 16:9 NTSC
1507 case 9: // 4:3 HD PAL
1509 case 0xB: // 16:9 HD PAL
1510 case 0xC: // > 16:9 HD PAL
1511 case 0xD: // 4:3 HD NTSC
1513 case 0xF: // 16:9 HD NTSC
1514 case 0x10: // > 16:9 HD PAL
1515 return data->getComponentType();
1525 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1526 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1527 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1528 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1529 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1530 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1531 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1532 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1533 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1534 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1535 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1536 case sProvider: if (!m_dvb_service) return -1; return -2;
1537 case sServiceref: return resIsString;
1538 case sDVBState: return m_tune_state;
1545 std::string eDVBServicePlay::getInfoString(int w)
1550 if (!m_dvb_service) return "";
1551 return m_dvb_service->m_provider_name;
1553 return m_reference.toString();
1557 return iServiceInformation::getInfoString(w);
1560 PyObject *eDVBServicePlay::getInfoObject(int w)
1565 return m_service_handler.getCaIds();
1566 case sTransponderData:
1567 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1571 return iServiceInformation::getInfoObject(w);
1574 int eDVBServicePlay::getNumberOfTracks()
1576 eDVBServicePMTHandler::program program;
1577 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1578 if (h.getProgramInfo(program))
1580 return program.audioStreams.size();
1583 int eDVBServicePlay::getCurrentTrack()
1585 eDVBServicePMTHandler::program program;
1586 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1587 if (h.getProgramInfo(program))
1590 int max = program.audioStreams.size();
1593 for (i = 0; i < max; ++i)
1594 if (program.audioStreams[i].pid == m_current_audio_pid)
1600 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1602 int ret = selectAudioStream(i);
1604 if (m_decoder->play())
1610 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1612 eDVBServicePMTHandler::program program;
1613 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1615 if (h.getProgramInfo(program))
1618 if (i >= program.audioStreams.size())
1621 info.m_pid = program.audioStreams[i].pid;
1623 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1624 info.m_description = "MPEG";
1625 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1626 info.m_description = "AC3";
1627 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1628 info.m_description = "AAC";
1629 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1630 info.m_description = "AAC-HE";
1631 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1632 info.m_description = "DTS";
1634 info.m_description = "???";
1636 if (program.audioStreams[i].component_tag != -1)
1638 ePtr<eServiceEvent> evt;
1639 if (!m_event_handler.getEvent(evt, 0))
1641 ePtr<eComponentData> data;
1642 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1643 info.m_language = data->getText();
1647 if (info.m_language.empty())
1648 info.m_language = program.audioStreams[i].language_code;
1653 int eDVBServicePlay::selectAudioStream(int i)
1655 eDVBServicePMTHandler::program program;
1656 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1658 if (h.getProgramInfo(program))
1661 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1669 stream = program.defaultAudioStream;
1671 int apid = -1, apidtype = -1;
1673 if (((unsigned int)stream) < program.audioStreams.size())
1675 apid = program.audioStreams[stream].pid;
1676 apidtype = program.audioStreams[stream].type;
1679 m_current_audio_pid = apid;
1681 if (m_decoder->setAudioPID(apid, apidtype))
1683 eDebug("set audio pid failed");
1687 /* 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 */
1688 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1691 ePtr<iDVBDemux> data_demux;
1692 if (!h.getDataDemux(data_demux))
1694 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1695 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1699 /* if we decided that we need one, update the pid */
1701 m_rds_decoder->start(apid);
1703 /* store new pid as default only when:
1704 a.) we have an entry in the service db for the current service,
1705 b.) we are not playing back something,
1706 c.) we are not selecting the default entry. (we wouldn't change
1707 anything in the best case, or destroy the default setting in
1708 case the real default is not yet available.)
1710 if (m_dvb_service && !m_is_pvr && ((i != -1)
1711 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1713 if (apidtype == eDVBAudio::aMPEG)
1715 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1716 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1720 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1721 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1725 h.resetCachedProgram();
1730 int eDVBServicePlay::getCurrentChannel()
1732 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1735 RESULT eDVBServicePlay::selectChannel(int i)
1737 if (i < LEFT || i > RIGHT || i == STEREO)
1740 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1742 m_decoder->setAudioChannel(i);
1746 std::string eDVBServicePlay::getText(int x)
1752 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1754 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1759 void eDVBServicePlay::rdsDecoderEvent(int what)
1763 case eDVBRdsDecoder::RadioTextChanged:
1764 m_event((iPlayableService*)this, evUpdatedRadioText);
1766 case eDVBRdsDecoder::RtpTextChanged:
1767 m_event((iPlayableService*)this, evUpdatedRtpText);
1769 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1770 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1772 case eDVBRdsDecoder::RecvRassSlidePic:
1773 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1778 void eDVBServicePlay::showRassSlidePicture()
1784 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1785 if (rass_slide_pic.length())
1786 m_decoder->showSinglePic(rass_slide_pic.c_str());
1788 eDebug("empty filename for rass slide picture received!!");
1791 eDebug("no MPEG Decoder to show iframes avail");
1794 eDebug("showRassSlidePicture called.. but not decoder");
1797 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1803 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1804 if (rass_interactive_pic.length())
1805 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1807 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1810 eDebug("no MPEG Decoder to show iframes avail");
1813 eDebug("showRassInteractivePic called.. but not decoder");
1816 ePyObject eDVBServicePlay::getRassInteractiveMask()
1819 return m_rds_decoder->getRassPictureMask();
1823 int eDVBServiceBase::getFrontendInfo(int w)
1825 eUsePtr<iDVBChannel> channel;
1826 if(m_service_handler.getChannel(channel))
1828 ePtr<iDVBFrontend> fe;
1829 if(channel->getFrontend(fe))
1831 return fe->readFrontendData(w);
1834 PyObject *eDVBServiceBase::getFrontendData()
1836 ePyObject ret = PyDict_New();
1839 eUsePtr<iDVBChannel> channel;
1840 if(!m_service_handler.getChannel(channel))
1842 ePtr<iDVBFrontend> fe;
1843 if(!channel->getFrontend(fe))
1844 fe->getFrontendData(ret);
1852 PyObject *eDVBServiceBase::getFrontendStatus()
1854 ePyObject ret = PyDict_New();
1857 eUsePtr<iDVBChannel> channel;
1858 if(!m_service_handler.getChannel(channel))
1860 ePtr<iDVBFrontend> fe;
1861 if(!channel->getFrontend(fe))
1862 fe->getFrontendStatus(ret);
1870 PyObject *eDVBServiceBase::getTransponderData(bool original)
1872 ePyObject ret = PyDict_New();
1875 eUsePtr<iDVBChannel> channel;
1876 if(!m_service_handler.getChannel(channel))
1878 ePtr<iDVBFrontend> fe;
1879 if(!channel->getFrontend(fe))
1880 fe->getTransponderData(ret, original);
1888 PyObject *eDVBServiceBase::getAll(bool original)
1890 ePyObject ret = getTransponderData(original);
1893 eUsePtr<iDVBChannel> channel;
1894 if(!m_service_handler.getChannel(channel))
1896 ePtr<iDVBFrontend> fe;
1897 if(!channel->getFrontend(fe))
1899 fe->getFrontendData(ret);
1900 fe->getFrontendStatus(ret);
1907 int eDVBServicePlay::getNumberOfSubservices()
1909 ePtr<eServiceEvent> evt;
1910 if (!m_event_handler.getEvent(evt, 0))
1911 return evt->getNumOfLinkageServices();
1915 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1917 ePtr<eServiceEvent> evt;
1918 if (!m_event_handler.getEvent(evt, 0))
1920 if (!evt->getLinkageService(sub, m_reference, n))
1923 sub.type=eServiceReference::idInvalid;
1927 RESULT eDVBServicePlay::startTimeshift()
1929 ePtr<iDVBDemux> demux;
1931 eDebug("Start timeshift!");
1933 if (m_timeshift_enabled)
1936 /* start recording with the data demux. */
1937 if (m_service_handler.getDataDemux(demux))
1940 demux->createTSRecorder(m_record);
1945 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1946 eDebug("could not query ts path");
1949 tspath.append("/timeshift.XXXXXX");
1951 templ = new char[tspath.length() + 1];
1952 strcpy(templ, tspath.c_str());
1954 m_timeshift_fd = mkstemp(templ);
1955 m_timeshift_file = std::string(templ);
1957 eDebug("recording to %s", templ);
1961 if (m_timeshift_fd < 0)
1967 m_record->setTargetFD(m_timeshift_fd);
1969 m_timeshift_enabled = 1;
1971 updateTimeshiftPids();
1977 RESULT eDVBServicePlay::stopTimeshift()
1979 if (!m_timeshift_enabled)
1984 m_timeshift_enabled = 0;
1989 close(m_timeshift_fd);
1990 eDebug("remove timeshift file");
1991 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1996 int eDVBServicePlay::isTimeshiftActive()
1998 return m_timeshift_enabled && m_timeshift_active;
2001 RESULT eDVBServicePlay::activateTimeshift()
2003 if (!m_timeshift_enabled)
2006 if (!m_timeshift_active)
2008 switchToTimeshift();
2015 PyObject *eDVBServicePlay::getCutList()
2017 ePyObject list = PyList_New(0);
2019 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2021 ePyObject tuple = PyTuple_New(2);
2022 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2023 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2024 PyList_Append(list, tuple);
2031 void eDVBServicePlay::setCutList(ePyObject list)
2033 if (!PyList_Check(list))
2035 int size = PyList_Size(list);
2038 m_cue_entries.clear();
2040 for (i=0; i<size; ++i)
2042 ePyObject tuple = PyList_GET_ITEM(list, i);
2043 if (!PyTuple_Check(tuple))
2045 eDebug("non-tuple in cutlist");
2048 if (PyTuple_Size(tuple) != 2)
2050 eDebug("cutlist entries need to be a 2-tuple");
2053 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2054 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2056 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2059 pts_t pts = PyLong_AsLongLong(ppts);
2060 int type = PyInt_AsLong(ptype);
2061 m_cue_entries.insert(cueEntry(pts, type));
2062 eDebug("adding %08llx, %d", pts, type);
2064 m_cuesheet_changed = 1;
2066 cutlistToCuesheet();
2067 m_event((iPlayableService*)this, evCuesheetChanged);
2070 void eDVBServicePlay::setCutListEnable(int enable)
2072 m_cutlist_enabled = enable;
2073 cutlistToCuesheet();
2076 void eDVBServicePlay::updateTimeshiftPids()
2081 eDVBServicePMTHandler::program program;
2082 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2084 if (h.getProgramInfo(program))
2088 std::set<int> pids_to_record;
2089 pids_to_record.insert(0); // PAT
2090 if (program.pmtPid != -1)
2091 pids_to_record.insert(program.pmtPid); // PMT
2093 if (program.textPid != -1)
2094 pids_to_record.insert(program.textPid); // Videotext
2096 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2097 i(program.videoStreams.begin());
2098 i != program.videoStreams.end(); ++i)
2099 pids_to_record.insert(i->pid);
2101 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2102 i(program.audioStreams.begin());
2103 i != program.audioStreams.end(); ++i)
2104 pids_to_record.insert(i->pid);
2106 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2107 i(program.subtitleStreams.begin());
2108 i != program.subtitleStreams.end(); ++i)
2109 pids_to_record.insert(i->pid);
2111 std::set<int> new_pids, obsolete_pids;
2113 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2114 m_pids_active.begin(), m_pids_active.end(),
2115 std::inserter(new_pids, new_pids.begin()));
2117 std::set_difference(
2118 m_pids_active.begin(), m_pids_active.end(),
2119 pids_to_record.begin(), pids_to_record.end(),
2120 std::inserter(new_pids, new_pids.begin())
2123 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2124 m_record->addPID(*i);
2126 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2127 m_record->removePID(*i);
2131 void eDVBServicePlay::switchToLive()
2133 if (!m_timeshift_active)
2136 eDebug("SwitchToLive");
2141 m_teletext_parser = 0;
2143 m_subtitle_parser = 0;
2144 m_new_dvb_subtitle_page_connection = 0;
2145 m_new_subtitle_page_connection = 0;
2146 m_rds_decoder_event_connection = 0;
2147 m_video_event_connection = 0;
2149 /* free the timeshift service handler, we need the resources */
2150 m_service_handler_timeshift.free();
2151 m_timeshift_active = 0;
2153 m_event((iPlayableService*)this, evSeekableStatusChanged);
2158 void eDVBServicePlay::switchToTimeshift()
2160 if (m_timeshift_active)
2165 m_teletext_parser = 0;
2167 m_subtitle_parser = 0;
2168 m_new_subtitle_page_connection = 0;
2169 m_new_dvb_subtitle_page_connection = 0;
2170 m_rds_decoder_event_connection = 0;
2171 m_video_event_connection = 0;
2173 m_timeshift_active = 1;
2175 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2176 r.path = m_timeshift_file;
2178 m_cue = new eCueSheet();
2179 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2181 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2183 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2185 m_event((iPlayableService*)this, evSeekableStatusChanged);
2188 void eDVBServicePlay::updateDecoder()
2190 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2192 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2194 eDVBServicePMTHandler::program program;
2195 if (h.getProgramInfo(program))
2196 eDebug("getting program info failed.");
2199 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2200 if (!program.videoStreams.empty())
2202 eDebugNoNewLine(" (");
2203 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2204 i(program.videoStreams.begin());
2205 i != program.videoStreams.end(); ++i)
2212 if (i != program.videoStreams.begin())
2213 eDebugNoNewLine(", ");
2214 eDebugNoNewLine("%04x", i->pid);
2216 eDebugNoNewLine(")");
2218 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2219 if (!program.audioStreams.empty())
2221 eDebugNoNewLine(" (");
2222 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2223 i(program.audioStreams.begin());
2224 i != program.audioStreams.end(); ++i)
2226 if (i != program.audioStreams.begin())
2227 eDebugNoNewLine(", ");
2228 eDebugNoNewLine("%04x", i->pid);
2230 eDebugNoNewLine(")");
2232 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2233 pcrpid = program.pcrPid;
2234 eDebug(", and the text pid is %04x", program.textPid);
2235 tpid = program.textPid;
2240 h.getDecodeDemux(m_decode_demux);
2243 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2245 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2246 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2247 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2248 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2249 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2252 m_teletext_parser = 0;
2253 m_subtitle_parser = 0;
2257 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2264 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2265 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2266 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2268 else // subservice or recording
2270 eServiceReferenceDVB ref;
2271 m_service_handler.getServiceReference(ref);
2272 eServiceReferenceDVB parent = ref.getParentServiceReference();
2277 ePtr<eDVBResourceManager> res_mgr;
2278 if (!eDVBResourceManager::getInstance(res_mgr))
2280 ePtr<iDVBChannelList> db;
2281 if (!res_mgr->getChannelList(db))
2283 ePtr<eDVBService> origService;
2284 if (!db->getService(parent, origService))
2286 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2287 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2293 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2294 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2296 m_decoder->setVideoPID(vpid, vpidtype);
2297 selectAudioStream();
2299 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2300 m_decoder->setSyncPCR(pcrpid);
2302 m_decoder->setSyncPCR(-1);
2304 m_decoder->setTextPID(tpid);
2306 m_teletext_parser->start(program.textPid);
2308 /* if (!m_is_primary)
2309 m_decoder->setTrickmode();
2310 else */ if (m_is_paused)
2315 if (vpid > 0 && vpid < 0x2000)
2319 std::string radio_pic;
2320 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2321 m_decoder->setRadioPic(radio_pic);
2324 m_decoder->setAudioChannel(achannel);
2326 /* don't worry about non-existing services, nor pvr services */
2327 if (m_dvb_service && !m_is_pvr)
2329 /* (audio pid will be set in selectAudioTrack */
2330 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2331 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2332 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2333 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2336 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2339 void eDVBServicePlay::loadCuesheet()
2341 std::string filename = m_reference.path + ".cuts";
2343 m_cue_entries.clear();
2345 FILE *f = fopen(filename.c_str(), "rb");
2349 eDebug("loading cuts..");
2352 unsigned long long where;
2355 if (!fread(&where, sizeof(where), 1, f))
2357 if (!fread(&what, sizeof(what), 1, f))
2360 #if BYTE_ORDER == LITTLE_ENDIAN
2361 where = bswap_64(where);
2368 m_cue_entries.insert(cueEntry(where, what));
2371 eDebug("%d entries", m_cue_entries.size());
2373 eDebug("cutfile not found!");
2375 m_cuesheet_changed = 0;
2376 cutlistToCuesheet();
2377 m_event((iPlayableService*)this, evCuesheetChanged);
2380 void eDVBServicePlay::saveCuesheet()
2382 std::string filename = m_reference.path + ".cuts";
2384 FILE *f = fopen(filename.c_str(), "wb");
2388 unsigned long long where;
2391 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2393 #if BYTE_ORDER == BIG_ENDIAN
2396 where = bswap_64(i->where);
2398 what = htonl(i->what);
2399 fwrite(&where, sizeof(where), 1, f);
2400 fwrite(&what, sizeof(what), 1, f);
2406 m_cuesheet_changed = 0;
2409 void eDVBServicePlay::cutlistToCuesheet()
2413 eDebug("no cue sheet");
2418 if (!m_cutlist_enabled)
2420 m_cue->commitSpans();
2421 eDebug("cutlists were disabled");
2425 pts_t in = 0, out = 0, length = 0;
2429 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2433 if (i == m_cue_entries.end())
2436 if (i->what == 0) /* in */
2440 } else if (i->what == 1) /* out */
2442 else /* mark (2) or last play position (3) */
2459 m_cue->addSourceSpan(in, out);
2463 if (i == m_cue_entries.end())
2466 m_cue->commitSpans();
2469 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2471 if (m_subtitle_widget)
2472 disableSubtitles(parent);
2475 int tuplesize = PyTuple_Size(tuple);
2478 if (!PyTuple_Check(tuple))
2484 entry = PyTuple_GET_ITEM(tuple, 0);
2486 if (!PyInt_Check(entry))
2489 type = PyInt_AsLong(entry);
2491 if (type == 1) // teletext subtitles
2493 int page, magazine, pid;
2497 if (!m_teletext_parser)
2499 eDebug("enable teletext subtitles.. no parser !!!");
2503 entry = PyTuple_GET_ITEM(tuple, 1);
2504 if (!PyInt_Check(entry))
2506 pid = PyInt_AsLong(entry);
2508 entry = PyTuple_GET_ITEM(tuple, 2);
2509 if (!PyInt_Check(entry))
2511 page = PyInt_AsLong(entry);
2513 entry = PyTuple_GET_ITEM(tuple, 3);
2514 if (!PyInt_Check(entry))
2516 magazine = PyInt_AsLong(entry);
2518 m_subtitle_widget = new eSubtitleWidget(parent);
2519 m_subtitle_widget->resize(parent->size()); /* full size */
2520 m_teletext_parser->setPageAndMagazine(page, magazine);
2522 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2526 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2527 if (!m_subtitle_parser)
2529 eDebug("enable dvb subtitles.. no parser !!!");
2535 entry = PyTuple_GET_ITEM(tuple, 1);
2536 if (!PyInt_Check(entry))
2538 pid = PyInt_AsLong(entry);
2540 entry = PyTuple_GET_ITEM(tuple, 2);
2541 if (!PyInt_Check(entry))
2543 composition_page_id = PyInt_AsLong(entry);
2545 entry = PyTuple_GET_ITEM(tuple, 3);
2546 if (!PyInt_Check(entry))
2548 ancillary_page_id = PyInt_AsLong(entry);
2550 m_subtitle_widget = new eSubtitleWidget(parent);
2551 m_subtitle_widget->resize(parent->size()); /* full size */
2552 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2554 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2560 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2561 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2562 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2566 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2568 delete m_subtitle_widget;
2569 m_subtitle_widget = 0;
2570 if (m_subtitle_parser)
2572 m_subtitle_parser->stop();
2573 m_dvb_subtitle_pages.clear();
2575 if (m_teletext_parser)
2577 m_teletext_parser->setPageAndMagazine(-1, -1);
2578 m_subtitle_pages.clear();
2581 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2585 PyObject *eDVBServicePlay::getCachedSubtitle()
2589 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2592 unsigned int data = (unsigned int)tmp;
2593 int pid = (data&0xFFFF0000)>>16;
2594 ePyObject tuple = PyTuple_New(4);
2595 eDVBServicePMTHandler::program program;
2596 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2597 if (!h.getProgramInfo(program))
2599 if (program.textPid==pid) // teletext
2600 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2602 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2603 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2604 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2605 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2613 PyObject *eDVBServicePlay::getSubtitleList()
2615 if (!m_teletext_parser)
2618 ePyObject l = PyList_New(0);
2619 std::set<int> added_ttx_pages;
2621 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2622 m_teletext_parser->m_found_subtitle_pages;
2624 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2625 eDVBServicePMTHandler::program program;
2626 if (h.getProgramInfo(program))
2627 eDebug("getting program info failed.");
2630 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2631 it != program.subtitleStreams.end(); ++it)
2633 switch(it->subtitling_type)
2635 case 0x01: // ebu teletext subtitles
2637 int page_number = it->teletext_page_number & 0xFF;
2638 int magazine_number = it->teletext_magazine_number & 7;
2639 int hash = magazine_number << 8 | page_number;
2640 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2642 ePyObject tuple = PyTuple_New(5);
2643 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2644 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2645 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2646 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2647 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2648 PyList_Append(l, tuple);
2650 added_ttx_pages.insert(hash);
2655 case 0x20 ... 0x23: // dvb subtitles
2657 ePyObject tuple = PyTuple_New(5);
2658 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2659 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2660 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2661 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2662 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2663 PyList_Insert(l, 0, tuple);
2671 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2672 it != subs.end(); ++it)
2674 int page_number = it->teletext_page_number & 0xFF;
2675 int magazine_number = it->teletext_magazine_number & 7;
2676 int hash = magazine_number << 8 | page_number;
2677 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2679 ePyObject tuple = PyTuple_New(5);
2680 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2681 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2682 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2683 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2684 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2685 PyList_Append(l, tuple);
2693 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2695 if (m_subtitle_widget)
2699 m_decoder->getPTS(0, pos);
2700 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2701 m_subtitle_pages.push_back(page);
2702 checkSubtitleTiming();
2706 void eDVBServicePlay::checkSubtitleTiming()
2708 eDebug("checkSubtitleTiming");
2709 if (!m_subtitle_widget)
2713 enum { TELETEXT, DVB } type;
2714 eDVBTeletextSubtitlePage page;
2715 eDVBSubtitlePage dvb_page;
2717 if (!m_subtitle_pages.empty())
2719 page = m_subtitle_pages.front();
2721 show_time = page.m_pts;
2723 else if (!m_dvb_subtitle_pages.empty())
2725 dvb_page = m_dvb_subtitle_pages.front();
2727 show_time = dvb_page.m_show_time;
2735 m_decoder->getPTS(0, pos);
2737 eDebug("%lld %lld", pos, show_time);
2738 int diff = show_time - pos;
2741 eDebug("[late (%d ms)]", -diff / 90);
2744 // if (diff > 900000)
2746 // eDebug("[invalid]");
2752 if (type == TELETEXT)
2754 eDebug("display teletext subtitle page %lld", show_time);
2755 m_subtitle_widget->setPage(page);
2756 m_subtitle_pages.pop_front();
2760 eDebug("display dvb subtitle Page %lld", show_time);
2761 m_subtitle_widget->setPage(dvb_page);
2762 m_dvb_subtitle_pages.pop_front();
2766 eDebug("start subtitle delay %d", diff / 90);
2767 m_subtitle_sync_timer->start(diff / 90, 1);
2773 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2775 if (m_subtitle_widget)
2779 m_decoder->getPTS(0, pos);
2780 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2781 m_dvb_subtitle_pages.push_back(p);
2782 checkSubtitleTiming();
2786 int eDVBServicePlay::getAC3Delay()
2789 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2791 return m_decoder->getAC3Delay();
2796 int eDVBServicePlay::getPCMDelay()
2799 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2801 return m_decoder->getPCMDelay();
2806 void eDVBServicePlay::setAC3Delay(int delay)
2809 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2811 m_decoder->setAC3Delay(delay);
2814 void eDVBServicePlay::setPCMDelay(int delay)
2817 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2819 m_decoder->setPCMDelay(delay);
2822 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2824 switch(event.type) {
2825 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2826 m_event((iPlayableService*)this, evVideoSizeChanged);
2828 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2829 m_event((iPlayableService*)this, evVideoFramerateChanged);
2831 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2832 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2839 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2845 PyObject *eDVBServicePlay::getStreamingData()
2847 eDVBServicePMTHandler::program program;
2848 if (m_service_handler.getProgramInfo(program))
2853 ePyObject r = program.createPythonObject();
2854 ePtr<iDVBDemux> demux;
2855 if (!m_service_handler.getDataDemux(demux))
2858 if (!demux->getCADemuxID(demux_id))
2859 PutToDict(r, "demux", demux_id);
2866 DEFINE_REF(eDVBServicePlay)
2868 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2872 case iServiceInformation::sTransponderData:
2873 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2877 return iStaticServiceInformation::getInfoObject(ref, w);
2880 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");