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 0; /* 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->play())
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");
1690 /* 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 */
1691 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1694 ePtr<iDVBDemux> data_demux;
1695 if (!h.getDataDemux(data_demux))
1697 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1698 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1702 /* if we decided that we need one, update the pid */
1704 m_rds_decoder->start(apid);
1706 /* store new pid as default only when:
1707 a.) we have an entry in the service db for the current service,
1708 b.) we are not playing back something,
1709 c.) we are not selecting the default entry. (we wouldn't change
1710 anything in the best case, or destroy the default setting in
1711 case the real default is not yet available.)
1713 if (m_dvb_service && !m_is_pvr && ((i != -1)
1714 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1716 if (apidtype == eDVBAudio::aMPEG)
1718 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1719 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1723 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1724 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1728 h.resetCachedProgram();
1733 int eDVBServicePlay::getCurrentChannel()
1735 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1738 RESULT eDVBServicePlay::selectChannel(int i)
1740 if (i < LEFT || i > RIGHT || i == STEREO)
1743 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1745 m_decoder->setAudioChannel(i);
1749 std::string eDVBServicePlay::getText(int x)
1755 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1757 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1762 void eDVBServicePlay::rdsDecoderEvent(int what)
1766 case eDVBRdsDecoder::RadioTextChanged:
1767 m_event((iPlayableService*)this, evUpdatedRadioText);
1769 case eDVBRdsDecoder::RtpTextChanged:
1770 m_event((iPlayableService*)this, evUpdatedRtpText);
1772 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1773 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1775 case eDVBRdsDecoder::RecvRassSlidePic:
1776 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1781 void eDVBServicePlay::showRassSlidePicture()
1787 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1788 if (rass_slide_pic.length())
1789 m_decoder->showSinglePic(rass_slide_pic.c_str());
1791 eDebug("empty filename for rass slide picture received!!");
1794 eDebug("no MPEG Decoder to show iframes avail");
1797 eDebug("showRassSlidePicture called.. but not decoder");
1800 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1806 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1807 if (rass_interactive_pic.length())
1808 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1810 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1813 eDebug("no MPEG Decoder to show iframes avail");
1816 eDebug("showRassInteractivePic called.. but not decoder");
1819 ePyObject eDVBServicePlay::getRassInteractiveMask()
1822 return m_rds_decoder->getRassPictureMask();
1826 int eDVBServiceBase::getFrontendInfo(int w)
1828 eUsePtr<iDVBChannel> channel;
1829 if(m_service_handler.getChannel(channel))
1831 ePtr<iDVBFrontend> fe;
1832 if(channel->getFrontend(fe))
1834 return fe->readFrontendData(w);
1837 PyObject *eDVBServiceBase::getFrontendData()
1839 ePyObject ret = PyDict_New();
1842 eUsePtr<iDVBChannel> channel;
1843 if(!m_service_handler.getChannel(channel))
1845 ePtr<iDVBFrontend> fe;
1846 if(!channel->getFrontend(fe))
1847 fe->getFrontendData(ret);
1855 PyObject *eDVBServiceBase::getFrontendStatus()
1857 ePyObject ret = PyDict_New();
1860 eUsePtr<iDVBChannel> channel;
1861 if(!m_service_handler.getChannel(channel))
1863 ePtr<iDVBFrontend> fe;
1864 if(!channel->getFrontend(fe))
1865 fe->getFrontendStatus(ret);
1873 PyObject *eDVBServiceBase::getTransponderData(bool original)
1875 ePyObject ret = PyDict_New();
1878 eUsePtr<iDVBChannel> channel;
1879 if(!m_service_handler.getChannel(channel))
1881 ePtr<iDVBFrontend> fe;
1882 if(!channel->getFrontend(fe))
1883 fe->getTransponderData(ret, original);
1891 PyObject *eDVBServiceBase::getAll(bool original)
1893 ePyObject ret = getTransponderData(original);
1896 eUsePtr<iDVBChannel> channel;
1897 if(!m_service_handler.getChannel(channel))
1899 ePtr<iDVBFrontend> fe;
1900 if(!channel->getFrontend(fe))
1902 fe->getFrontendData(ret);
1903 fe->getFrontendStatus(ret);
1910 int eDVBServicePlay::getNumberOfSubservices()
1912 ePtr<eServiceEvent> evt;
1913 if (!m_event_handler.getEvent(evt, 0))
1914 return evt->getNumOfLinkageServices();
1918 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1920 ePtr<eServiceEvent> evt;
1921 if (!m_event_handler.getEvent(evt, 0))
1923 if (!evt->getLinkageService(sub, m_reference, n))
1926 sub.type=eServiceReference::idInvalid;
1930 RESULT eDVBServicePlay::startTimeshift()
1932 ePtr<iDVBDemux> demux;
1934 eDebug("Start timeshift!");
1936 if (m_timeshift_enabled)
1939 /* start recording with the data demux. */
1940 if (m_service_handler.getDataDemux(demux))
1943 demux->createTSRecorder(m_record);
1948 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1949 eDebug("could not query ts path");
1952 tspath.append("/timeshift.XXXXXX");
1954 templ = new char[tspath.length() + 1];
1955 strcpy(templ, tspath.c_str());
1957 m_timeshift_fd = mkstemp(templ);
1958 m_timeshift_file = std::string(templ);
1960 eDebug("recording to %s", templ);
1964 if (m_timeshift_fd < 0)
1970 m_record->setTargetFD(m_timeshift_fd);
1972 m_timeshift_enabled = 1;
1974 updateTimeshiftPids();
1980 RESULT eDVBServicePlay::stopTimeshift()
1982 if (!m_timeshift_enabled)
1987 m_timeshift_enabled = 0;
1992 close(m_timeshift_fd);
1993 eDebug("remove timeshift file");
1994 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1999 int eDVBServicePlay::isTimeshiftActive()
2001 return m_timeshift_enabled && m_timeshift_active;
2004 RESULT eDVBServicePlay::activateTimeshift()
2006 if (!m_timeshift_enabled)
2009 if (!m_timeshift_active)
2011 switchToTimeshift();
2018 PyObject *eDVBServicePlay::getCutList()
2020 ePyObject list = PyList_New(0);
2022 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2024 ePyObject tuple = PyTuple_New(2);
2025 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2026 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2027 PyList_Append(list, tuple);
2034 void eDVBServicePlay::setCutList(ePyObject list)
2036 if (!PyList_Check(list))
2038 int size = PyList_Size(list);
2041 m_cue_entries.clear();
2043 for (i=0; i<size; ++i)
2045 ePyObject tuple = PyList_GET_ITEM(list, i);
2046 if (!PyTuple_Check(tuple))
2048 eDebug("non-tuple in cutlist");
2051 if (PyTuple_Size(tuple) != 2)
2053 eDebug("cutlist entries need to be a 2-tuple");
2056 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2057 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2059 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2062 pts_t pts = PyLong_AsLongLong(ppts);
2063 int type = PyInt_AsLong(ptype);
2064 m_cue_entries.insert(cueEntry(pts, type));
2065 eDebug("adding %08llx, %d", pts, type);
2067 m_cuesheet_changed = 1;
2069 cutlistToCuesheet();
2070 m_event((iPlayableService*)this, evCuesheetChanged);
2073 void eDVBServicePlay::setCutListEnable(int enable)
2075 m_cutlist_enabled = enable;
2076 cutlistToCuesheet();
2079 void eDVBServicePlay::updateTimeshiftPids()
2084 eDVBServicePMTHandler::program program;
2085 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2087 if (h.getProgramInfo(program))
2091 std::set<int> pids_to_record;
2092 pids_to_record.insert(0); // PAT
2093 if (program.pmtPid != -1)
2094 pids_to_record.insert(program.pmtPid); // PMT
2096 if (program.textPid != -1)
2097 pids_to_record.insert(program.textPid); // Videotext
2099 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2100 i(program.videoStreams.begin());
2101 i != program.videoStreams.end(); ++i)
2102 pids_to_record.insert(i->pid);
2104 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2105 i(program.audioStreams.begin());
2106 i != program.audioStreams.end(); ++i)
2107 pids_to_record.insert(i->pid);
2109 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2110 i(program.subtitleStreams.begin());
2111 i != program.subtitleStreams.end(); ++i)
2112 pids_to_record.insert(i->pid);
2114 std::set<int> new_pids, obsolete_pids;
2116 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2117 m_pids_active.begin(), m_pids_active.end(),
2118 std::inserter(new_pids, new_pids.begin()));
2120 std::set_difference(
2121 m_pids_active.begin(), m_pids_active.end(),
2122 pids_to_record.begin(), pids_to_record.end(),
2123 std::inserter(new_pids, new_pids.begin())
2126 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2127 m_record->addPID(*i);
2129 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2130 m_record->removePID(*i);
2134 void eDVBServicePlay::switchToLive()
2136 if (!m_timeshift_active)
2139 eDebug("SwitchToLive");
2144 m_teletext_parser = 0;
2146 m_subtitle_parser = 0;
2147 m_new_dvb_subtitle_page_connection = 0;
2148 m_new_subtitle_page_connection = 0;
2149 m_rds_decoder_event_connection = 0;
2150 m_video_event_connection = 0;
2152 /* free the timeshift service handler, we need the resources */
2153 m_service_handler_timeshift.free();
2154 m_timeshift_active = 0;
2156 m_event((iPlayableService*)this, evSeekableStatusChanged);
2161 void eDVBServicePlay::switchToTimeshift()
2163 if (m_timeshift_active)
2168 m_teletext_parser = 0;
2170 m_subtitle_parser = 0;
2171 m_new_subtitle_page_connection = 0;
2172 m_new_dvb_subtitle_page_connection = 0;
2173 m_rds_decoder_event_connection = 0;
2174 m_video_event_connection = 0;
2176 m_timeshift_active = 1;
2178 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2179 r.path = m_timeshift_file;
2181 m_cue = new eCueSheet();
2182 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2184 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2186 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2188 m_event((iPlayableService*)this, evSeekableStatusChanged);
2191 void eDVBServicePlay::updateDecoder()
2193 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2195 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2197 eDVBServicePMTHandler::program program;
2198 if (h.getProgramInfo(program))
2199 eDebug("getting program info failed.");
2202 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2203 if (!program.videoStreams.empty())
2205 eDebugNoNewLine(" (");
2206 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2207 i(program.videoStreams.begin());
2208 i != program.videoStreams.end(); ++i)
2215 if (i != program.videoStreams.begin())
2216 eDebugNoNewLine(", ");
2217 eDebugNoNewLine("%04x", i->pid);
2219 eDebugNoNewLine(")");
2221 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2222 if (!program.audioStreams.empty())
2224 eDebugNoNewLine(" (");
2225 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2226 i(program.audioStreams.begin());
2227 i != program.audioStreams.end(); ++i)
2229 if (i != program.audioStreams.begin())
2230 eDebugNoNewLine(", ");
2231 eDebugNoNewLine("%04x", i->pid);
2233 eDebugNoNewLine(")");
2235 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2236 pcrpid = program.pcrPid;
2237 eDebug(", and the text pid is %04x", program.textPid);
2238 tpid = program.textPid;
2243 h.getDecodeDemux(m_decode_demux);
2246 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2248 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2249 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2250 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2251 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2252 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2255 m_teletext_parser = 0;
2256 m_subtitle_parser = 0;
2260 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2267 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2268 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2269 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2271 else // subservice or recording
2273 eServiceReferenceDVB ref;
2274 m_service_handler.getServiceReference(ref);
2275 eServiceReferenceDVB parent = ref.getParentServiceReference();
2280 ePtr<eDVBResourceManager> res_mgr;
2281 if (!eDVBResourceManager::getInstance(res_mgr))
2283 ePtr<iDVBChannelList> db;
2284 if (!res_mgr->getChannelList(db))
2286 ePtr<eDVBService> origService;
2287 if (!db->getService(parent, origService))
2289 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2290 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2297 std::string config_delay;
2298 int config_delay_int = 0;
2299 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2300 config_delay_int = atoi(config_delay.c_str());
2301 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2303 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2304 config_delay_int = atoi(config_delay.c_str());
2306 config_delay_int = 0;
2307 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2309 m_decoder->setVideoPID(vpid, vpidtype);
2310 selectAudioStream();
2312 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2313 m_decoder->setSyncPCR(pcrpid);
2315 m_decoder->setSyncPCR(-1);
2317 m_decoder->setTextPID(tpid);
2319 m_teletext_parser->start(program.textPid);
2321 if (vpid > 0 && vpid < 0x2000)
2325 std::string radio_pic;
2326 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2327 m_decoder->setRadioPic(radio_pic);
2330 /* if (!m_is_primary)
2331 m_decoder->setTrickmode();
2332 else */ if (m_is_paused)
2337 m_decoder->setAudioChannel(achannel);
2339 /* don't worry about non-existing services, nor pvr services */
2340 if (m_dvb_service && !m_is_pvr)
2342 /* (audio pid will be set in selectAudioTrack */
2343 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2344 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2345 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2346 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2349 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2352 void eDVBServicePlay::loadCuesheet()
2354 std::string filename = m_reference.path + ".cuts";
2356 m_cue_entries.clear();
2358 FILE *f = fopen(filename.c_str(), "rb");
2362 eDebug("loading cuts..");
2365 unsigned long long where;
2368 if (!fread(&where, sizeof(where), 1, f))
2370 if (!fread(&what, sizeof(what), 1, f))
2373 #if BYTE_ORDER == LITTLE_ENDIAN
2374 where = bswap_64(where);
2381 m_cue_entries.insert(cueEntry(where, what));
2384 eDebug("%d entries", m_cue_entries.size());
2386 eDebug("cutfile not found!");
2388 m_cuesheet_changed = 0;
2389 cutlistToCuesheet();
2390 m_event((iPlayableService*)this, evCuesheetChanged);
2393 void eDVBServicePlay::saveCuesheet()
2395 std::string filename = m_reference.path + ".cuts";
2397 FILE *f = fopen(filename.c_str(), "wb");
2401 unsigned long long where;
2404 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2406 #if BYTE_ORDER == BIG_ENDIAN
2409 where = bswap_64(i->where);
2411 what = htonl(i->what);
2412 fwrite(&where, sizeof(where), 1, f);
2413 fwrite(&what, sizeof(what), 1, f);
2419 m_cuesheet_changed = 0;
2422 void eDVBServicePlay::cutlistToCuesheet()
2426 eDebug("no cue sheet");
2431 if (!m_cutlist_enabled)
2433 m_cue->commitSpans();
2434 eDebug("cutlists were disabled");
2438 pts_t in = 0, out = 0, length = 0;
2442 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2446 if (i == m_cue_entries.end())
2449 if (i->what == 0) /* in */
2453 } else if (i->what == 1) /* out */
2455 else /* mark (2) or last play position (3) */
2472 m_cue->addSourceSpan(in, out);
2476 if (i == m_cue_entries.end())
2479 m_cue->commitSpans();
2482 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2484 if (m_subtitle_widget)
2485 disableSubtitles(parent);
2488 int tuplesize = PyTuple_Size(tuple);
2491 if (!PyTuple_Check(tuple))
2497 entry = PyTuple_GET_ITEM(tuple, 0);
2499 if (!PyInt_Check(entry))
2502 type = PyInt_AsLong(entry);
2504 if (type == 1) // teletext subtitles
2506 int page, magazine, pid;
2510 if (!m_teletext_parser)
2512 eDebug("enable teletext subtitles.. no parser !!!");
2516 entry = PyTuple_GET_ITEM(tuple, 1);
2517 if (!PyInt_Check(entry))
2519 pid = PyInt_AsLong(entry);
2521 entry = PyTuple_GET_ITEM(tuple, 2);
2522 if (!PyInt_Check(entry))
2524 page = PyInt_AsLong(entry);
2526 entry = PyTuple_GET_ITEM(tuple, 3);
2527 if (!PyInt_Check(entry))
2529 magazine = PyInt_AsLong(entry);
2531 m_subtitle_widget = new eSubtitleWidget(parent);
2532 m_subtitle_widget->resize(parent->size()); /* full size */
2533 m_teletext_parser->setPageAndMagazine(page, magazine);
2535 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2539 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2540 if (!m_subtitle_parser)
2542 eDebug("enable dvb subtitles.. no parser !!!");
2548 entry = PyTuple_GET_ITEM(tuple, 1);
2549 if (!PyInt_Check(entry))
2551 pid = PyInt_AsLong(entry);
2553 entry = PyTuple_GET_ITEM(tuple, 2);
2554 if (!PyInt_Check(entry))
2556 composition_page_id = PyInt_AsLong(entry);
2558 entry = PyTuple_GET_ITEM(tuple, 3);
2559 if (!PyInt_Check(entry))
2561 ancillary_page_id = PyInt_AsLong(entry);
2563 m_subtitle_widget = new eSubtitleWidget(parent);
2564 m_subtitle_widget->resize(parent->size()); /* full size */
2565 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2567 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2573 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2574 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2575 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2579 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2581 delete m_subtitle_widget;
2582 m_subtitle_widget = 0;
2583 if (m_subtitle_parser)
2585 m_subtitle_parser->stop();
2586 m_dvb_subtitle_pages.clear();
2588 if (m_teletext_parser)
2590 m_teletext_parser->setPageAndMagazine(-1, -1);
2591 m_subtitle_pages.clear();
2594 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2598 PyObject *eDVBServicePlay::getCachedSubtitle()
2602 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2605 unsigned int data = (unsigned int)tmp;
2606 int pid = (data&0xFFFF0000)>>16;
2607 ePyObject tuple = PyTuple_New(4);
2608 eDVBServicePMTHandler::program program;
2609 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2610 if (!h.getProgramInfo(program))
2612 if (program.textPid==pid) // teletext
2613 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2615 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2616 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2617 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2618 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2626 PyObject *eDVBServicePlay::getSubtitleList()
2628 if (!m_teletext_parser)
2631 ePyObject l = PyList_New(0);
2632 std::set<int> added_ttx_pages;
2634 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2635 m_teletext_parser->m_found_subtitle_pages;
2637 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2638 eDVBServicePMTHandler::program program;
2639 if (h.getProgramInfo(program))
2640 eDebug("getting program info failed.");
2643 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2644 it != program.subtitleStreams.end(); ++it)
2646 switch(it->subtitling_type)
2648 case 0x01: // ebu teletext subtitles
2650 int page_number = it->teletext_page_number & 0xFF;
2651 int magazine_number = it->teletext_magazine_number & 7;
2652 int hash = magazine_number << 8 | page_number;
2653 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2655 ePyObject tuple = PyTuple_New(5);
2656 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2657 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2658 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2659 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2660 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2661 PyList_Append(l, tuple);
2663 added_ttx_pages.insert(hash);
2668 case 0x20 ... 0x23: // dvb subtitles
2670 ePyObject tuple = PyTuple_New(5);
2671 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2672 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2673 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2674 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2675 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2676 PyList_Insert(l, 0, tuple);
2684 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2685 it != subs.end(); ++it)
2687 int page_number = it->teletext_page_number & 0xFF;
2688 int magazine_number = it->teletext_magazine_number & 7;
2689 int hash = magazine_number << 8 | page_number;
2690 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2692 ePyObject tuple = PyTuple_New(5);
2693 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2694 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2695 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2696 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2697 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2698 PyList_Append(l, tuple);
2706 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2708 if (m_subtitle_widget)
2712 m_decoder->getPTS(0, pos);
2713 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2714 m_subtitle_pages.push_back(page);
2715 checkSubtitleTiming();
2719 void eDVBServicePlay::checkSubtitleTiming()
2721 eDebug("checkSubtitleTiming");
2722 if (!m_subtitle_widget)
2726 enum { TELETEXT, DVB } type;
2727 eDVBTeletextSubtitlePage page;
2728 eDVBSubtitlePage dvb_page;
2730 if (!m_subtitle_pages.empty())
2732 page = m_subtitle_pages.front();
2734 show_time = page.m_pts;
2736 else if (!m_dvb_subtitle_pages.empty())
2738 dvb_page = m_dvb_subtitle_pages.front();
2740 show_time = dvb_page.m_show_time;
2748 m_decoder->getPTS(0, pos);
2750 eDebug("%lld %lld", pos, show_time);
2751 int diff = show_time - pos;
2754 eDebug("[late (%d ms)]", -diff / 90);
2757 // if (diff > 900000)
2759 // eDebug("[invalid]");
2765 if (type == TELETEXT)
2767 eDebug("display teletext subtitle page %lld", show_time);
2768 m_subtitle_widget->setPage(page);
2769 m_subtitle_pages.pop_front();
2773 eDebug("display dvb subtitle Page %lld", show_time);
2774 m_subtitle_widget->setPage(dvb_page);
2775 m_dvb_subtitle_pages.pop_front();
2779 eDebug("start subtitle delay %d", diff / 90);
2780 m_subtitle_sync_timer->start(diff / 90, 1);
2786 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2788 if (m_subtitle_widget)
2792 m_decoder->getPTS(0, pos);
2793 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2794 m_dvb_subtitle_pages.push_back(p);
2795 checkSubtitleTiming();
2799 int eDVBServicePlay::getAC3Delay()
2802 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2804 return m_decoder->getAC3Delay();
2809 int eDVBServicePlay::getPCMDelay()
2812 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2814 return m_decoder->getPCMDelay();
2819 void eDVBServicePlay::setAC3Delay(int delay)
2822 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2824 m_decoder->setAC3Delay(delay);
2827 void eDVBServicePlay::setPCMDelay(int delay)
2830 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2832 m_decoder->setPCMDelay(delay);
2835 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2837 switch(event.type) {
2838 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2839 m_event((iPlayableService*)this, evVideoSizeChanged);
2841 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2842 m_event((iPlayableService*)this, evVideoFramerateChanged);
2844 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2845 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2852 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2858 PyObject *eDVBServicePlay::getStreamingData()
2860 eDVBServicePMTHandler::program program;
2861 if (m_service_handler.getProgramInfo(program))
2866 ePyObject r = program.createPythonObject();
2867 ePtr<iDVBDemux> demux;
2868 if (!m_service_handler.getDataDemux(demux))
2871 if (!demux->getCADemuxID(demux_id))
2872 PutToDict(r, "demux", demux_id);
2879 DEFINE_REF(eDVBServicePlay)
2881 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2885 case iServiceInformation::sTransponderData:
2886 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2890 return iStaticServiceInformation::getInfoObject(ref, w);
2893 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");