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 extensions.push_back("trp");
529 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
532 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
533 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
536 eServiceFactoryDVB::~eServiceFactoryDVB()
538 ePtr<eServiceCenter> sc;
540 eServiceCenter::getPrivInstance(sc);
542 sc->removeServiceFactory(eServiceFactoryDVB::id);
545 DEFINE_REF(eDVBServiceList);
547 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
551 eDVBServiceList::~eDVBServiceList()
555 RESULT eDVBServiceList::startQuery()
557 ePtr<iDVBChannelList> db;
558 ePtr<eDVBResourceManager> res;
561 if ((err = eDVBResourceManager::getInstance(res)) != 0)
563 eDebug("no resource manager");
566 if ((err = res->getChannelList(db)) != 0)
568 eDebug("no channel list");
572 ePtr<eDVBChannelQuery> q;
574 if (!m_parent.path.empty())
576 eDVBChannelQuery::compile(q, m_parent.path);
579 eDebug("compile query failed");
584 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
586 eDebug("startQuery failed");
593 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
595 eServiceReferenceDVB ref;
600 while (!m_query->getNextResult(ref))
604 list.sort(iListableServiceCompare(this));
609 // The first argument of this function is a format string to specify the order and
610 // the content of the returned list
611 // useable format options are
612 // R = Service Reference (as swig object .. this is very slow)
613 // S = Service Reference (as python string object .. same as ref.toString())
614 // C = Service Reference (as python string object .. same as ref.toCompareString())
615 // N = Service Name (as python string object)
616 // n = Short Service Name (short name brakets used) (as python string object)
617 // when exactly one return value per service is selected in the format string,
618 // then each value is directly a list entry
619 // when more than one value is returned per service, then the list is a list of
621 // unknown format string chars are returned as python None values !
622 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
625 std::list<eServiceReference> tmplist;
628 if (!format || !(retcount=strlen(format)))
629 format = "R"; // just return service reference swig object ...
631 if (!getContent(tmplist, sorted))
633 int services=tmplist.size();
634 ePtr<iStaticServiceInformation> sptr;
635 eServiceCenterPtr service_center;
637 if (strchr(format, 'N') || strchr(format, 'n'))
638 eServiceCenter::getPrivInstance(service_center);
640 ret = PyList_New(services);
641 std::list<eServiceReference>::iterator it(tmplist.begin());
643 for (int cnt=0; cnt < services; ++cnt)
645 eServiceReference &ref=*it++;
646 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
647 for (int i=0; i < retcount; ++i)
652 case 'R': // service reference (swig)object
653 tmp = NEW_eServiceReference(ref);
655 case 'C': // service reference compare string
656 tmp = PyString_FromString(ref.toCompareString().c_str());
658 case 'S': // service reference string
659 tmp = PyString_FromString(ref.toString().c_str());
661 case 'N': // service name
664 service_center->info(ref, sptr);
668 sptr->getName(ref, name);
670 // filter short name brakets
672 while((pos = name.find("\xc2\x86")) != std::string::npos)
674 while((pos = name.find("\xc2\x87")) != std::string::npos)
678 tmp = PyString_FromString(name.c_str());
682 tmp = PyString_FromString("<n/a>");
684 case 'n': // short service name
687 service_center->info(ref, sptr);
691 sptr->getName(ref, name);
692 name = buildShortName(name);
694 tmp = PyString_FromString(name.c_str());
698 tmp = PyString_FromString("<n/a>");
711 PyTuple_SET_ITEM(tuple, i, tmp);
713 PyList_SET_ITEM(ret, cnt, tmp);
717 PyList_SET_ITEM(ret, cnt, tuple);
720 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
723 RESULT eDVBServiceList::getNext(eServiceReference &ref)
728 return m_query->getNextResult((eServiceReferenceDVB&)ref);
731 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
733 if (m_parent.flags & eServiceReference::canDescent) // bouquet
735 ePtr<iDVBChannelList> db;
736 ePtr<eDVBResourceManager> resm;
738 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
741 if (db->getBouquet(m_parent, m_bouquet) != 0)
752 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
756 return m_bouquet->addService(ref, before);
759 RESULT eDVBServiceList::removeService(eServiceReference &ref)
763 return m_bouquet->removeService(ref);
766 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
770 return m_bouquet->moveService(ref, pos);
773 RESULT eDVBServiceList::flushChanges()
777 return m_bouquet->flushChanges();
780 RESULT eDVBServiceList::setListName(const std::string &name)
784 return m_bouquet->setListName(name);
787 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
789 ePtr<eDVBService> service;
790 int r = lookupService(service, ref);
793 // check resources...
794 ptr = new eDVBServicePlay(ref, service);
798 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
800 if (ref.path.empty())
802 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
811 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
813 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
814 if (list->startQuery())
824 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
826 /* is a listable service? */
827 if (ref.flags & eServiceReference::canDescent) // bouquet
829 if ( !ref.name.empty() ) // satellites or providers list
830 ptr = m_StaticServiceDVBInfo;
831 else // a dvb bouquet
832 ptr = m_StaticServiceDVBBouquetInfo;
834 else if (!ref.path.empty()) /* do we have a PVR service? */
835 ptr = new eStaticServiceDVBPVRInformation(ref);
836 else // normal dvb service
838 ePtr<eDVBService> service;
839 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
840 ptr = m_StaticServiceDVBInfo;
842 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
848 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
850 if (ref.path.empty())
856 ptr = new eDVBPVRServiceOfflineOperations(ref);
861 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
863 // TODO: handle the listing itself
864 // if (ref.... == -1) .. return "... bouquets ...";
865 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
867 ePtr<iDVBChannelList> db;
868 ePtr<eDVBResourceManager> res;
871 if ((err = eDVBResourceManager::getInstance(res)) != 0)
873 eDebug("no resource manager");
876 if ((err = res->getChannelList(db)) != 0)
878 eDebug("no channel list");
882 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
883 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
885 eDebug("getService failed!");
892 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
893 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
896 m_is_pvr = !m_reference.path.empty();
898 m_timeshift_enabled = m_timeshift_active = 0;
901 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
902 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
903 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
905 m_cuesheet_changed = 0;
906 m_cutlist_enabled = 1;
908 m_subtitle_widget = 0;
912 m_subtitle_sync_timer = eTimer::create(eApp);
914 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
917 eDVBServicePlay::~eDVBServicePlay()
919 delete m_subtitle_widget;
922 void eDVBServicePlay::gotNewEvent()
926 ePtr<eServiceEvent> m_event_now, m_event_next;
927 getEvent(m_event_now, 0);
928 getEvent(m_event_next, 1);
931 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
933 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
935 m_event((iPlayableService*)this, evUpdatedEventInfo);
938 void eDVBServicePlay::serviceEvent(int event)
940 m_tune_state = event;
944 case eDVBServicePMTHandler::eventTuned:
946 ePtr<iDVBDemux> m_demux;
947 if (!m_service_handler.getDataDemux(m_demux))
949 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
950 int sid = ref.getParentServiceID().get();
952 sid = ref.getServiceID().get();
953 if ( ref.getParentTransportStreamID().get() &&
954 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
955 m_event_handler.startOther(m_demux, sid);
957 m_event_handler.start(m_demux, sid);
959 m_event((iPlayableService*)this, evTunedIn);
962 case eDVBServicePMTHandler::eventNoResources:
963 case eDVBServicePMTHandler::eventNoPAT:
964 case eDVBServicePMTHandler::eventNoPATEntry:
965 case eDVBServicePMTHandler::eventNoPMT:
966 case eDVBServicePMTHandler::eventTuneFailed:
967 case eDVBServicePMTHandler::eventMisconfiguration:
969 eDebug("DVB service failed to tune - error %d", event);
970 m_event((iPlayableService*)this, evTuneFailed);
973 case eDVBServicePMTHandler::eventNewProgramInfo:
975 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
976 if (m_timeshift_enabled)
977 updateTimeshiftPids();
978 if (!m_timeshift_active)
980 if (m_first_program_info && m_is_pvr)
982 m_first_program_info = 0;
985 m_event((iPlayableService*)this, evUpdatedInfo);
988 case eDVBServicePMTHandler::eventEOF:
989 m_event((iPlayableService*)this, evEOF);
991 case eDVBServicePMTHandler::eventSOF:
992 m_event((iPlayableService*)this, evSOF);
997 void eDVBServicePlay::serviceEventTimeshift(int event)
1001 case eDVBServicePMTHandler::eventNewProgramInfo:
1002 if (m_timeshift_active)
1005 case eDVBServicePMTHandler::eventSOF:
1006 m_event((iPlayableService*)this, evSOF);
1008 case eDVBServicePMTHandler::eventEOF:
1009 if ((!m_is_paused) && (m_skipmode >= 0))
1011 eDebug("timeshift EOF, so let's go live");
1018 RESULT eDVBServicePlay::start()
1021 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1022 two (one for decoding, one for data source), as we must be prepared
1023 to start recording from the data demux. */
1025 m_cue = new eCueSheet();
1027 m_event(this, evStart);
1029 m_first_program_info = 1;
1030 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1031 r = m_service_handler.tune(service, m_is_pvr, m_cue);
1033 /* inject EIT if there is a stored one */
1036 std::string filename = service.path;
1037 filename.erase(filename.length()-2, 2);
1039 ePtr<eServiceEvent> event = new eServiceEvent;
1040 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1042 ePtr<eServiceEvent> empty;
1043 m_event_handler.inject(event, 0);
1044 m_event_handler.inject(empty, 1);
1051 m_event(this, evStart);
1056 RESULT eDVBServicePlay::stop()
1058 /* add bookmark for last play position */
1061 pts_t play_position, length;
1062 if (!getPlayPosition(play_position))
1064 /* remove last position */
1065 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1067 if (i->what == 3) /* current play position */
1069 m_cue_entries.erase(i);
1070 i = m_cue_entries.begin();
1076 if (getLength(length))
1081 int perc = play_position * 100LL / length;
1083 /* only store last play position when between 1% and 99% */
1084 if ((1 < perc) && (perc < 99))
1085 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1087 m_cuesheet_changed = 1;
1091 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1093 m_service_handler_timeshift.free();
1094 m_service_handler.free();
1096 if (m_is_pvr && m_cuesheet_changed)
1099 /* save cuesheet only when main file is accessible. */
1100 if (!::stat(m_reference.path.c_str(), &s))
1103 m_event((iPlayableService*)this, evStopped);
1107 RESULT eDVBServicePlay::setTarget(int target)
1109 m_is_primary = !target;
1113 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1115 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1119 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1121 /* note: we check for timeshift to be enabled,
1122 not neccessary active. if you pause when timeshift
1123 is not active, you should activate it when unpausing */
1124 if ((!m_is_pvr) && (!m_timeshift_enabled))
1134 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1136 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1137 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1138 setFastForward_internal(0);
1140 return m_decoder->setSlowMotion(ratio);
1145 RESULT eDVBServicePlay::setFastForward(int ratio)
1147 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1149 return setFastForward_internal(ratio);
1152 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1154 int skipmode, ffratio;
1160 } else if (ratio > 0)
1168 } else // if (ratio < 0)
1174 if (m_skipmode != skipmode)
1176 eDebug("setting cue skipmode to %d", skipmode);
1178 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1181 m_skipmode = skipmode;
1187 ; /* return m_decoder->play(); is done in caller*/
1188 else if (ffratio != 1)
1189 return m_decoder->setFastForward(ffratio);
1191 return m_decoder->setTrickmode();
1194 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1196 if (m_is_pvr || m_timeshift_enabled)
1206 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1207 RESULT eDVBServicePlay::getLength(pts_t &len)
1209 ePtr<iDVBPVRChannel> pvr_channel;
1211 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1214 return pvr_channel->getLength(len);
1217 RESULT eDVBServicePlay::pause()
1219 eDebug("eDVBServicePlay::pause");
1220 setFastForward_internal(0);
1224 return m_decoder->pause();
1229 RESULT eDVBServicePlay::unpause()
1231 eDebug("eDVBServicePlay::unpause");
1232 setFastForward_internal(0);
1236 return m_decoder->play();
1241 RESULT eDVBServicePlay::seekTo(pts_t to)
1243 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1245 if (!m_decode_demux)
1248 ePtr<iDVBPVRChannel> pvr_channel;
1250 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1256 m_cue->seekTo(0, to);
1257 m_dvb_subtitle_pages.clear();
1258 m_subtitle_pages.clear();
1263 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1265 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1267 if (!m_decode_demux)
1270 ePtr<iDVBPVRChannel> pvr_channel;
1272 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1277 /* HACK until we have skip-AP api */
1278 if ((to > 0) && (to < 100))
1286 m_cue->seekTo(mode, to);
1287 m_dvb_subtitle_pages.clear();
1288 m_subtitle_pages.clear();
1292 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1294 ePtr<iDVBPVRChannel> pvr_channel;
1296 if (!m_decode_demux)
1299 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1304 /* if there is a decoder, use audio or video PTS */
1307 r = m_decoder->getPTS(0, pos);
1313 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1316 RESULT eDVBServicePlay::setTrickmode(int trick)
1318 /* currently unimplemented */
1322 RESULT eDVBServicePlay::isCurrentlySeekable()
1324 return m_is_pvr || m_timeshift_active;
1327 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1333 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1339 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1345 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1351 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1357 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1360 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1361 (m_timeshift_enabled || !m_is_pvr))
1363 if (!m_timeshift_enabled)
1365 /* query config path */
1367 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1368 eDebug("could not query ts path from config");
1372 /* we need enough diskspace */
1374 if (statfs(tspath.c_str(), &fs) < 0)
1376 eDebug("statfs failed!");
1380 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1382 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1392 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1403 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1409 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1415 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1421 RESULT eDVBServicePlay::getName(std::string &name)
1425 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1426 return i->getName(m_reference, name);
1430 m_dvb_service->getName(m_reference, name);
1434 else if (!m_reference.name.empty())
1435 eStaticServiceDVBInformation().getName(m_reference, name);
1437 name = "DVB service";
1441 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1443 return m_event_handler.getEvent(evt, nownext);
1446 int eDVBServicePlay::getInfo(int w)
1448 eDVBServicePMTHandler::program program;
1451 return resIsPyObject;
1453 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1455 int no_program_info = 0;
1457 if (h.getProgramInfo(program))
1458 no_program_info = 1;
1464 return m_decoder->getVideoHeight();
1468 return m_decoder->getVideoWidth();
1472 return m_decoder->getVideoFrameRate();
1476 return m_decoder->getVideoProgressive();
1482 aspect = m_decoder->getVideoAspect();
1483 if (no_program_info)
1485 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1487 ePtr<eServiceEvent> evt;
1488 if (!m_event_handler.getEvent(evt, 0))
1490 ePtr<eComponentData> data;
1491 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1493 if ( data->getStreamContent() == 1 )
1495 switch(data->getComponentType())
1498 case 1: // 4:3 SD PAL
1500 case 3: // 16:9 SD PAL
1501 case 4: // > 16:9 PAL
1502 case 5: // 4:3 SD NTSC
1504 case 7: // 16:9 SD NTSC
1505 case 8: // > 16:9 NTSC
1508 case 9: // 4:3 HD PAL
1510 case 0xB: // 16:9 HD PAL
1511 case 0xC: // > 16:9 HD PAL
1512 case 0xD: // 4:3 HD NTSC
1514 case 0xF: // 16:9 HD NTSC
1515 case 0x10: // > 16:9 HD PAL
1516 return data->getComponentType();
1526 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1527 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1528 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1529 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1530 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1531 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1532 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1533 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1534 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1535 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1536 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1537 case sProvider: if (!m_dvb_service) return -1; return -2;
1538 case sServiceref: return resIsString;
1539 case sDVBState: return m_tune_state;
1546 std::string eDVBServicePlay::getInfoString(int w)
1551 if (!m_dvb_service) return "";
1552 return m_dvb_service->m_provider_name;
1554 return m_reference.toString();
1558 return iServiceInformation::getInfoString(w);
1561 PyObject *eDVBServicePlay::getInfoObject(int w)
1566 return m_service_handler.getCaIds();
1567 case sTransponderData:
1568 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1572 return iServiceInformation::getInfoObject(w);
1575 int eDVBServicePlay::getNumberOfTracks()
1577 eDVBServicePMTHandler::program program;
1578 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1579 if (h.getProgramInfo(program))
1581 return program.audioStreams.size();
1584 int eDVBServicePlay::getCurrentTrack()
1586 eDVBServicePMTHandler::program program;
1587 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1588 if (h.getProgramInfo(program))
1591 int max = program.audioStreams.size();
1594 for (i = 0; i < max; ++i)
1595 if (program.audioStreams[i].pid == m_current_audio_pid)
1601 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1603 int ret = selectAudioStream(i);
1605 if (m_decoder->set())
1611 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1613 eDVBServicePMTHandler::program program;
1614 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1616 if (h.getProgramInfo(program))
1619 if (i >= program.audioStreams.size())
1622 info.m_pid = program.audioStreams[i].pid;
1624 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1625 info.m_description = "MPEG";
1626 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1627 info.m_description = "AC3";
1628 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1629 info.m_description = "AAC";
1630 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1631 info.m_description = "AAC-HE";
1632 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1633 info.m_description = "DTS";
1635 info.m_description = "???";
1637 if (program.audioStreams[i].component_tag != -1)
1639 ePtr<eServiceEvent> evt;
1640 if (!m_event_handler.getEvent(evt, 0))
1642 ePtr<eComponentData> data;
1643 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1644 info.m_language = data->getText();
1648 if (info.m_language.empty())
1649 info.m_language = program.audioStreams[i].language_code;
1654 int eDVBServicePlay::selectAudioStream(int i)
1656 eDVBServicePMTHandler::program program;
1657 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1659 if (h.getProgramInfo(program))
1662 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1670 stream = program.defaultAudioStream;
1672 int apid = -1, apidtype = -1;
1674 if (((unsigned int)stream) < program.audioStreams.size())
1676 apid = program.audioStreams[stream].pid;
1677 apidtype = program.audioStreams[stream].type;
1680 m_current_audio_pid = apid;
1682 if (m_decoder->setAudioPID(apid, apidtype))
1684 eDebug("set audio pid failed");
1688 /* 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 */
1689 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1692 ePtr<iDVBDemux> data_demux;
1693 if (!h.getDataDemux(data_demux))
1695 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1696 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1700 /* if we decided that we need one, update the pid */
1702 m_rds_decoder->start(apid);
1704 /* store new pid as default only when:
1705 a.) we have an entry in the service db for the current service,
1706 b.) we are not playing back something,
1707 c.) we are not selecting the default entry. (we wouldn't change
1708 anything in the best case, or destroy the default setting in
1709 case the real default is not yet available.)
1711 if (m_dvb_service && !m_is_pvr && ((i != -1)
1712 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1714 if (apidtype == eDVBAudio::aMPEG)
1716 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1717 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1721 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1722 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1726 h.resetCachedProgram();
1731 int eDVBServicePlay::getCurrentChannel()
1733 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1736 RESULT eDVBServicePlay::selectChannel(int i)
1738 if (i < LEFT || i > RIGHT || i == STEREO)
1741 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1743 m_decoder->setAudioChannel(i);
1747 std::string eDVBServicePlay::getText(int x)
1753 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1755 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1760 void eDVBServicePlay::rdsDecoderEvent(int what)
1764 case eDVBRdsDecoder::RadioTextChanged:
1765 m_event((iPlayableService*)this, evUpdatedRadioText);
1767 case eDVBRdsDecoder::RtpTextChanged:
1768 m_event((iPlayableService*)this, evUpdatedRtpText);
1770 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1771 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1773 case eDVBRdsDecoder::RecvRassSlidePic:
1774 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1779 void eDVBServicePlay::showRassSlidePicture()
1785 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1786 if (rass_slide_pic.length())
1787 m_decoder->showSinglePic(rass_slide_pic.c_str());
1789 eDebug("empty filename for rass slide picture received!!");
1792 eDebug("no MPEG Decoder to show iframes avail");
1795 eDebug("showRassSlidePicture called.. but not decoder");
1798 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1804 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1805 if (rass_interactive_pic.length())
1806 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1808 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1811 eDebug("no MPEG Decoder to show iframes avail");
1814 eDebug("showRassInteractivePic called.. but not decoder");
1817 ePyObject eDVBServicePlay::getRassInteractiveMask()
1820 return m_rds_decoder->getRassPictureMask();
1824 int eDVBServiceBase::getFrontendInfo(int w)
1826 eUsePtr<iDVBChannel> channel;
1827 if(m_service_handler.getChannel(channel))
1829 ePtr<iDVBFrontend> fe;
1830 if(channel->getFrontend(fe))
1832 return fe->readFrontendData(w);
1835 PyObject *eDVBServiceBase::getFrontendData()
1837 ePyObject ret = PyDict_New();
1840 eUsePtr<iDVBChannel> channel;
1841 if(!m_service_handler.getChannel(channel))
1843 ePtr<iDVBFrontend> fe;
1844 if(!channel->getFrontend(fe))
1845 fe->getFrontendData(ret);
1853 PyObject *eDVBServiceBase::getFrontendStatus()
1855 ePyObject ret = PyDict_New();
1858 eUsePtr<iDVBChannel> channel;
1859 if(!m_service_handler.getChannel(channel))
1861 ePtr<iDVBFrontend> fe;
1862 if(!channel->getFrontend(fe))
1863 fe->getFrontendStatus(ret);
1871 PyObject *eDVBServiceBase::getTransponderData(bool original)
1873 ePyObject ret = PyDict_New();
1876 eUsePtr<iDVBChannel> channel;
1877 if(!m_service_handler.getChannel(channel))
1879 ePtr<iDVBFrontend> fe;
1880 if(!channel->getFrontend(fe))
1881 fe->getTransponderData(ret, original);
1889 PyObject *eDVBServiceBase::getAll(bool original)
1891 ePyObject ret = getTransponderData(original);
1894 eUsePtr<iDVBChannel> channel;
1895 if(!m_service_handler.getChannel(channel))
1897 ePtr<iDVBFrontend> fe;
1898 if(!channel->getFrontend(fe))
1900 fe->getFrontendData(ret);
1901 fe->getFrontendStatus(ret);
1908 int eDVBServicePlay::getNumberOfSubservices()
1910 ePtr<eServiceEvent> evt;
1911 if (!m_event_handler.getEvent(evt, 0))
1912 return evt->getNumOfLinkageServices();
1916 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1918 ePtr<eServiceEvent> evt;
1919 if (!m_event_handler.getEvent(evt, 0))
1921 if (!evt->getLinkageService(sub, m_reference, n))
1924 sub.type=eServiceReference::idInvalid;
1928 RESULT eDVBServicePlay::startTimeshift()
1930 ePtr<iDVBDemux> demux;
1932 eDebug("Start timeshift!");
1934 if (m_timeshift_enabled)
1937 /* start recording with the data demux. */
1938 if (m_service_handler.getDataDemux(demux))
1941 demux->createTSRecorder(m_record);
1946 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1947 eDebug("could not query ts path");
1950 tspath.append("/timeshift.XXXXXX");
1952 templ = new char[tspath.length() + 1];
1953 strcpy(templ, tspath.c_str());
1955 m_timeshift_fd = mkstemp(templ);
1956 m_timeshift_file = std::string(templ);
1958 eDebug("recording to %s", templ);
1962 if (m_timeshift_fd < 0)
1968 m_record->setTargetFD(m_timeshift_fd);
1970 m_timeshift_enabled = 1;
1972 updateTimeshiftPids();
1978 RESULT eDVBServicePlay::stopTimeshift()
1980 if (!m_timeshift_enabled)
1985 m_timeshift_enabled = 0;
1990 close(m_timeshift_fd);
1991 eDebug("remove timeshift file");
1992 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1997 int eDVBServicePlay::isTimeshiftActive()
1999 return m_timeshift_enabled && m_timeshift_active;
2002 RESULT eDVBServicePlay::activateTimeshift()
2004 if (!m_timeshift_enabled)
2007 if (!m_timeshift_active)
2009 switchToTimeshift();
2016 PyObject *eDVBServicePlay::getCutList()
2018 ePyObject list = PyList_New(0);
2020 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2022 ePyObject tuple = PyTuple_New(2);
2023 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2024 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2025 PyList_Append(list, tuple);
2032 void eDVBServicePlay::setCutList(ePyObject list)
2034 if (!PyList_Check(list))
2036 int size = PyList_Size(list);
2039 m_cue_entries.clear();
2041 for (i=0; i<size; ++i)
2043 ePyObject tuple = PyList_GET_ITEM(list, i);
2044 if (!PyTuple_Check(tuple))
2046 eDebug("non-tuple in cutlist");
2049 if (PyTuple_Size(tuple) != 2)
2051 eDebug("cutlist entries need to be a 2-tuple");
2054 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2055 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2057 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2060 pts_t pts = PyLong_AsLongLong(ppts);
2061 int type = PyInt_AsLong(ptype);
2062 m_cue_entries.insert(cueEntry(pts, type));
2063 eDebug("adding %08llx, %d", pts, type);
2065 m_cuesheet_changed = 1;
2067 cutlistToCuesheet();
2068 m_event((iPlayableService*)this, evCuesheetChanged);
2071 void eDVBServicePlay::setCutListEnable(int enable)
2073 m_cutlist_enabled = enable;
2074 cutlistToCuesheet();
2077 void eDVBServicePlay::updateTimeshiftPids()
2082 eDVBServicePMTHandler::program program;
2083 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2085 if (h.getProgramInfo(program))
2089 std::set<int> pids_to_record;
2090 pids_to_record.insert(0); // PAT
2091 if (program.pmtPid != -1)
2092 pids_to_record.insert(program.pmtPid); // PMT
2094 if (program.textPid != -1)
2095 pids_to_record.insert(program.textPid); // Videotext
2097 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2098 i(program.videoStreams.begin());
2099 i != program.videoStreams.end(); ++i)
2100 pids_to_record.insert(i->pid);
2102 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2103 i(program.audioStreams.begin());
2104 i != program.audioStreams.end(); ++i)
2105 pids_to_record.insert(i->pid);
2107 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2108 i(program.subtitleStreams.begin());
2109 i != program.subtitleStreams.end(); ++i)
2110 pids_to_record.insert(i->pid);
2112 std::set<int> new_pids, obsolete_pids;
2114 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2115 m_pids_active.begin(), m_pids_active.end(),
2116 std::inserter(new_pids, new_pids.begin()));
2118 std::set_difference(
2119 m_pids_active.begin(), m_pids_active.end(),
2120 pids_to_record.begin(), pids_to_record.end(),
2121 std::inserter(new_pids, new_pids.begin())
2124 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2125 m_record->addPID(*i);
2127 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2128 m_record->removePID(*i);
2132 void eDVBServicePlay::switchToLive()
2134 if (!m_timeshift_active)
2137 eDebug("SwitchToLive");
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, 0, m_dvb_service); /* 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);
2295 std::string config_delay;
2296 int config_delay_int = 0;
2297 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2298 config_delay_int = atoi(config_delay.c_str());
2299 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2301 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2302 config_delay_int = atoi(config_delay.c_str());
2304 config_delay_int = 0;
2305 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2307 m_decoder->setVideoPID(vpid, vpidtype);
2308 selectAudioStream();
2310 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2311 m_decoder->setSyncPCR(pcrpid);
2313 m_decoder->setSyncPCR(-1);
2315 m_decoder->setTextPID(tpid);
2317 m_teletext_parser->start(program.textPid);
2319 if (vpid > 0 && vpid < 0x2000)
2323 std::string radio_pic;
2324 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2325 m_decoder->setRadioPic(radio_pic);
2328 /* if (!m_is_primary)
2329 m_decoder->setTrickmode();
2330 else */ if (m_is_paused)
2335 m_decoder->setAudioChannel(achannel);
2337 /* don't worry about non-existing services, nor pvr services */
2338 if (m_dvb_service && !m_is_pvr)
2340 /* (audio pid will be set in selectAudioTrack */
2341 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2342 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2343 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2344 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2347 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2350 void eDVBServicePlay::loadCuesheet()
2352 std::string filename = m_reference.path + ".cuts";
2354 m_cue_entries.clear();
2356 FILE *f = fopen(filename.c_str(), "rb");
2360 eDebug("loading cuts..");
2363 unsigned long long where;
2366 if (!fread(&where, sizeof(where), 1, f))
2368 if (!fread(&what, sizeof(what), 1, f))
2371 #if BYTE_ORDER == LITTLE_ENDIAN
2372 where = bswap_64(where);
2379 m_cue_entries.insert(cueEntry(where, what));
2382 eDebug("%d entries", m_cue_entries.size());
2384 eDebug("cutfile not found!");
2386 m_cuesheet_changed = 0;
2387 cutlistToCuesheet();
2388 m_event((iPlayableService*)this, evCuesheetChanged);
2391 void eDVBServicePlay::saveCuesheet()
2393 std::string filename = m_reference.path + ".cuts";
2395 FILE *f = fopen(filename.c_str(), "wb");
2399 unsigned long long where;
2402 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2404 #if BYTE_ORDER == BIG_ENDIAN
2407 where = bswap_64(i->where);
2409 what = htonl(i->what);
2410 fwrite(&where, sizeof(where), 1, f);
2411 fwrite(&what, sizeof(what), 1, f);
2417 m_cuesheet_changed = 0;
2420 void eDVBServicePlay::cutlistToCuesheet()
2424 eDebug("no cue sheet");
2429 if (!m_cutlist_enabled)
2431 m_cue->commitSpans();
2432 eDebug("cutlists were disabled");
2436 pts_t in = 0, out = 0, length = 0;
2440 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2444 if (i == m_cue_entries.end())
2447 if (i->what == 0) /* in */
2451 } else if (i->what == 1) /* out */
2453 else /* mark (2) or last play position (3) */
2470 m_cue->addSourceSpan(in, out);
2474 if (i == m_cue_entries.end())
2477 m_cue->commitSpans();
2480 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2482 if (m_subtitle_widget)
2483 disableSubtitles(parent);
2486 int tuplesize = PyTuple_Size(tuple);
2489 if (!PyTuple_Check(tuple))
2495 entry = PyTuple_GET_ITEM(tuple, 0);
2497 if (!PyInt_Check(entry))
2500 type = PyInt_AsLong(entry);
2502 if (type == 1) // teletext subtitles
2504 int page, magazine, pid;
2508 if (!m_teletext_parser)
2510 eDebug("enable teletext subtitles.. no parser !!!");
2514 entry = PyTuple_GET_ITEM(tuple, 1);
2515 if (!PyInt_Check(entry))
2517 pid = PyInt_AsLong(entry);
2519 entry = PyTuple_GET_ITEM(tuple, 2);
2520 if (!PyInt_Check(entry))
2522 page = PyInt_AsLong(entry);
2524 entry = PyTuple_GET_ITEM(tuple, 3);
2525 if (!PyInt_Check(entry))
2527 magazine = PyInt_AsLong(entry);
2529 m_subtitle_widget = new eSubtitleWidget(parent);
2530 m_subtitle_widget->resize(parent->size()); /* full size */
2531 m_teletext_parser->setPageAndMagazine(page, magazine);
2533 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2537 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2538 if (!m_subtitle_parser)
2540 eDebug("enable dvb subtitles.. no parser !!!");
2546 entry = PyTuple_GET_ITEM(tuple, 1);
2547 if (!PyInt_Check(entry))
2549 pid = PyInt_AsLong(entry);
2551 entry = PyTuple_GET_ITEM(tuple, 2);
2552 if (!PyInt_Check(entry))
2554 composition_page_id = PyInt_AsLong(entry);
2556 entry = PyTuple_GET_ITEM(tuple, 3);
2557 if (!PyInt_Check(entry))
2559 ancillary_page_id = PyInt_AsLong(entry);
2561 m_subtitle_widget = new eSubtitleWidget(parent);
2562 m_subtitle_widget->resize(parent->size()); /* full size */
2563 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2565 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2571 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2572 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2573 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2577 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2579 delete m_subtitle_widget;
2580 m_subtitle_widget = 0;
2581 if (m_subtitle_parser)
2583 m_subtitle_parser->stop();
2584 m_dvb_subtitle_pages.clear();
2586 if (m_teletext_parser)
2588 m_teletext_parser->setPageAndMagazine(-1, -1);
2589 m_subtitle_pages.clear();
2592 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2596 PyObject *eDVBServicePlay::getCachedSubtitle()
2600 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2603 unsigned int data = (unsigned int)tmp;
2604 int pid = (data&0xFFFF0000)>>16;
2605 ePyObject tuple = PyTuple_New(4);
2606 eDVBServicePMTHandler::program program;
2607 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2608 if (!h.getProgramInfo(program))
2610 if (program.textPid==pid) // teletext
2611 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2613 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2614 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2615 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2616 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2624 PyObject *eDVBServicePlay::getSubtitleList()
2626 if (!m_teletext_parser)
2629 ePyObject l = PyList_New(0);
2630 std::set<int> added_ttx_pages;
2632 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2633 m_teletext_parser->m_found_subtitle_pages;
2635 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2636 eDVBServicePMTHandler::program program;
2637 if (h.getProgramInfo(program))
2638 eDebug("getting program info failed.");
2641 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2642 it != program.subtitleStreams.end(); ++it)
2644 switch(it->subtitling_type)
2646 case 0x01: // ebu teletext subtitles
2648 int page_number = it->teletext_page_number & 0xFF;
2649 int magazine_number = it->teletext_magazine_number & 7;
2650 int hash = magazine_number << 8 | page_number;
2651 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2653 ePyObject tuple = PyTuple_New(5);
2654 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2655 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2656 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2657 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2658 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2659 PyList_Append(l, tuple);
2661 added_ttx_pages.insert(hash);
2666 case 0x20 ... 0x23: // dvb subtitles
2668 ePyObject tuple = PyTuple_New(5);
2669 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2670 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2671 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2672 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2673 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2674 PyList_Insert(l, 0, tuple);
2682 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2683 it != subs.end(); ++it)
2685 int page_number = it->teletext_page_number & 0xFF;
2686 int magazine_number = it->teletext_magazine_number & 7;
2687 int hash = magazine_number << 8 | page_number;
2688 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2690 ePyObject tuple = PyTuple_New(5);
2691 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2692 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2693 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2694 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2695 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2696 PyList_Append(l, tuple);
2704 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2706 if (m_subtitle_widget)
2710 m_decoder->getPTS(0, pos);
2711 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2712 m_subtitle_pages.push_back(page);
2713 checkSubtitleTiming();
2717 void eDVBServicePlay::checkSubtitleTiming()
2719 eDebug("checkSubtitleTiming");
2720 if (!m_subtitle_widget)
2724 enum { TELETEXT, DVB } type;
2725 eDVBTeletextSubtitlePage page;
2726 eDVBSubtitlePage dvb_page;
2728 if (!m_subtitle_pages.empty())
2730 page = m_subtitle_pages.front();
2732 show_time = page.m_pts;
2734 else if (!m_dvb_subtitle_pages.empty())
2736 dvb_page = m_dvb_subtitle_pages.front();
2738 show_time = dvb_page.m_show_time;
2746 m_decoder->getPTS(0, pos);
2748 eDebug("%lld %lld", pos, show_time);
2749 int diff = show_time - pos;
2752 eDebug("[late (%d ms)]", -diff / 90);
2755 // if (diff > 900000)
2757 // eDebug("[invalid]");
2763 if (type == TELETEXT)
2765 eDebug("display teletext subtitle page %lld", show_time);
2766 m_subtitle_widget->setPage(page);
2767 m_subtitle_pages.pop_front();
2771 eDebug("display dvb subtitle Page %lld", show_time);
2772 m_subtitle_widget->setPage(dvb_page);
2773 m_dvb_subtitle_pages.pop_front();
2777 eDebug("start subtitle delay %d", diff / 90);
2778 m_subtitle_sync_timer->start(diff / 90, 1);
2784 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2786 if (m_subtitle_widget)
2790 m_decoder->getPTS(0, pos);
2791 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2792 m_dvb_subtitle_pages.push_back(p);
2793 checkSubtitleTiming();
2797 int eDVBServicePlay::getAC3Delay()
2800 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2802 return m_decoder->getAC3Delay();
2807 int eDVBServicePlay::getPCMDelay()
2810 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2812 return m_decoder->getPCMDelay();
2817 void eDVBServicePlay::setAC3Delay(int delay)
2820 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2822 m_decoder->setAC3Delay(delay);
2825 void eDVBServicePlay::setPCMDelay(int delay)
2828 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2830 m_decoder->setPCMDelay(delay);
2833 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2835 switch(event.type) {
2836 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2837 m_event((iPlayableService*)this, evVideoSizeChanged);
2839 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2840 m_event((iPlayableService*)this, evVideoFramerateChanged);
2842 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2843 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2850 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2856 PyObject *eDVBServicePlay::getStreamingData()
2858 eDVBServicePMTHandler::program program;
2859 if (m_service_handler.getProgramInfo(program))
2864 ePyObject r = program.createPythonObject();
2865 ePtr<iDVBDemux> demux;
2866 if (!m_service_handler.getDataDemux(demux))
2869 if (!demux->getCADemuxID(demux_id))
2870 PutToDict(r, "demux", demux_id);
2877 DEFINE_REF(eDVBServicePlay)
2879 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2883 case iServiceInformation::sTransponderData:
2884 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2888 return iStaticServiceInformation::getInfoObject(ref, w);
2891 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");