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);
1719 else if (apidtype == eDVBAudio::aAC3)
1721 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1722 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1726 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1727 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1731 h.resetCachedProgram();
1736 int eDVBServicePlay::getCurrentChannel()
1738 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1741 RESULT eDVBServicePlay::selectChannel(int i)
1743 if (i < LEFT || i > RIGHT || i == STEREO)
1746 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1748 m_decoder->setAudioChannel(i);
1752 std::string eDVBServicePlay::getText(int x)
1758 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1760 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1765 void eDVBServicePlay::rdsDecoderEvent(int what)
1769 case eDVBRdsDecoder::RadioTextChanged:
1770 m_event((iPlayableService*)this, evUpdatedRadioText);
1772 case eDVBRdsDecoder::RtpTextChanged:
1773 m_event((iPlayableService*)this, evUpdatedRtpText);
1775 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1776 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1778 case eDVBRdsDecoder::RecvRassSlidePic:
1779 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1784 void eDVBServicePlay::showRassSlidePicture()
1790 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1791 if (rass_slide_pic.length())
1792 m_decoder->showSinglePic(rass_slide_pic.c_str());
1794 eDebug("empty filename for rass slide picture received!!");
1797 eDebug("no MPEG Decoder to show iframes avail");
1800 eDebug("showRassSlidePicture called.. but not decoder");
1803 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1809 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1810 if (rass_interactive_pic.length())
1811 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1813 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1816 eDebug("no MPEG Decoder to show iframes avail");
1819 eDebug("showRassInteractivePic called.. but not decoder");
1822 ePyObject eDVBServicePlay::getRassInteractiveMask()
1825 return m_rds_decoder->getRassPictureMask();
1829 int eDVBServiceBase::getFrontendInfo(int w)
1831 eUsePtr<iDVBChannel> channel;
1832 if(m_service_handler.getChannel(channel))
1834 ePtr<iDVBFrontend> fe;
1835 if(channel->getFrontend(fe))
1837 return fe->readFrontendData(w);
1840 PyObject *eDVBServiceBase::getFrontendData()
1842 ePyObject ret = PyDict_New();
1845 eUsePtr<iDVBChannel> channel;
1846 if(!m_service_handler.getChannel(channel))
1848 ePtr<iDVBFrontend> fe;
1849 if(!channel->getFrontend(fe))
1850 fe->getFrontendData(ret);
1858 PyObject *eDVBServiceBase::getFrontendStatus()
1860 ePyObject ret = PyDict_New();
1863 eUsePtr<iDVBChannel> channel;
1864 if(!m_service_handler.getChannel(channel))
1866 ePtr<iDVBFrontend> fe;
1867 if(!channel->getFrontend(fe))
1868 fe->getFrontendStatus(ret);
1876 PyObject *eDVBServiceBase::getTransponderData(bool original)
1878 ePyObject ret = PyDict_New();
1881 eUsePtr<iDVBChannel> channel;
1882 if(!m_service_handler.getChannel(channel))
1884 ePtr<iDVBFrontend> fe;
1885 if(!channel->getFrontend(fe))
1886 fe->getTransponderData(ret, original);
1894 PyObject *eDVBServiceBase::getAll(bool original)
1896 ePyObject ret = getTransponderData(original);
1899 eUsePtr<iDVBChannel> channel;
1900 if(!m_service_handler.getChannel(channel))
1902 ePtr<iDVBFrontend> fe;
1903 if(!channel->getFrontend(fe))
1905 fe->getFrontendData(ret);
1906 fe->getFrontendStatus(ret);
1913 int eDVBServicePlay::getNumberOfSubservices()
1915 ePtr<eServiceEvent> evt;
1916 if (!m_event_handler.getEvent(evt, 0))
1917 return evt->getNumOfLinkageServices();
1921 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1923 ePtr<eServiceEvent> evt;
1924 if (!m_event_handler.getEvent(evt, 0))
1926 if (!evt->getLinkageService(sub, m_reference, n))
1929 sub.type=eServiceReference::idInvalid;
1933 RESULT eDVBServicePlay::startTimeshift()
1935 ePtr<iDVBDemux> demux;
1937 eDebug("Start timeshift!");
1939 if (m_timeshift_enabled)
1942 /* start recording with the data demux. */
1943 if (m_service_handler.getDataDemux(demux))
1946 demux->createTSRecorder(m_record);
1951 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1952 eDebug("could not query ts path");
1955 tspath.append("/timeshift.XXXXXX");
1957 templ = new char[tspath.length() + 1];
1958 strcpy(templ, tspath.c_str());
1960 m_timeshift_fd = mkstemp(templ);
1961 m_timeshift_file = std::string(templ);
1963 eDebug("recording to %s", templ);
1967 if (m_timeshift_fd < 0)
1973 m_record->setTargetFD(m_timeshift_fd);
1975 m_timeshift_enabled = 1;
1977 updateTimeshiftPids();
1983 RESULT eDVBServicePlay::stopTimeshift()
1985 if (!m_timeshift_enabled)
1990 m_timeshift_enabled = 0;
1995 close(m_timeshift_fd);
1996 eDebug("remove timeshift file");
1997 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2002 int eDVBServicePlay::isTimeshiftActive()
2004 return m_timeshift_enabled && m_timeshift_active;
2007 RESULT eDVBServicePlay::activateTimeshift()
2009 if (!m_timeshift_enabled)
2012 if (!m_timeshift_active)
2014 switchToTimeshift();
2021 PyObject *eDVBServicePlay::getCutList()
2023 ePyObject list = PyList_New(0);
2025 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2027 ePyObject tuple = PyTuple_New(2);
2028 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2029 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2030 PyList_Append(list, tuple);
2037 void eDVBServicePlay::setCutList(ePyObject list)
2039 if (!PyList_Check(list))
2041 int size = PyList_Size(list);
2044 m_cue_entries.clear();
2046 for (i=0; i<size; ++i)
2048 ePyObject tuple = PyList_GET_ITEM(list, i);
2049 if (!PyTuple_Check(tuple))
2051 eDebug("non-tuple in cutlist");
2054 if (PyTuple_Size(tuple) != 2)
2056 eDebug("cutlist entries need to be a 2-tuple");
2059 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2060 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2062 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2065 pts_t pts = PyLong_AsLongLong(ppts);
2066 int type = PyInt_AsLong(ptype);
2067 m_cue_entries.insert(cueEntry(pts, type));
2068 eDebug("adding %08llx, %d", pts, type);
2070 m_cuesheet_changed = 1;
2072 cutlistToCuesheet();
2073 m_event((iPlayableService*)this, evCuesheetChanged);
2076 void eDVBServicePlay::setCutListEnable(int enable)
2078 m_cutlist_enabled = enable;
2079 cutlistToCuesheet();
2082 void eDVBServicePlay::updateTimeshiftPids()
2087 eDVBServicePMTHandler::program program;
2088 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2090 if (h.getProgramInfo(program))
2094 std::set<int> pids_to_record;
2095 pids_to_record.insert(0); // PAT
2096 if (program.pmtPid != -1)
2097 pids_to_record.insert(program.pmtPid); // PMT
2099 if (program.textPid != -1)
2100 pids_to_record.insert(program.textPid); // Videotext
2102 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2103 i(program.videoStreams.begin());
2104 i != program.videoStreams.end(); ++i)
2105 pids_to_record.insert(i->pid);
2107 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2108 i(program.audioStreams.begin());
2109 i != program.audioStreams.end(); ++i)
2110 pids_to_record.insert(i->pid);
2112 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2113 i(program.subtitleStreams.begin());
2114 i != program.subtitleStreams.end(); ++i)
2115 pids_to_record.insert(i->pid);
2117 std::set<int> new_pids, obsolete_pids;
2119 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2120 m_pids_active.begin(), m_pids_active.end(),
2121 std::inserter(new_pids, new_pids.begin()));
2123 std::set_difference(
2124 m_pids_active.begin(), m_pids_active.end(),
2125 pids_to_record.begin(), pids_to_record.end(),
2126 std::inserter(new_pids, new_pids.begin())
2129 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2130 m_record->addPID(*i);
2132 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2133 m_record->removePID(*i);
2137 void eDVBServicePlay::switchToLive()
2139 if (!m_timeshift_active)
2142 eDebug("SwitchToLive");
2147 m_teletext_parser = 0;
2149 m_subtitle_parser = 0;
2150 m_new_dvb_subtitle_page_connection = 0;
2151 m_new_subtitle_page_connection = 0;
2152 m_rds_decoder_event_connection = 0;
2153 m_video_event_connection = 0;
2155 /* free the timeshift service handler, we need the resources */
2156 m_service_handler_timeshift.free();
2157 m_timeshift_active = 0;
2159 m_event((iPlayableService*)this, evSeekableStatusChanged);
2164 void eDVBServicePlay::switchToTimeshift()
2166 if (m_timeshift_active)
2171 m_teletext_parser = 0;
2173 m_subtitle_parser = 0;
2174 m_new_subtitle_page_connection = 0;
2175 m_new_dvb_subtitle_page_connection = 0;
2176 m_rds_decoder_event_connection = 0;
2177 m_video_event_connection = 0;
2179 m_timeshift_active = 1;
2181 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2182 r.path = m_timeshift_file;
2184 m_cue = new eCueSheet();
2185 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2187 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2189 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2191 m_event((iPlayableService*)this, evSeekableStatusChanged);
2194 void eDVBServicePlay::updateDecoder()
2196 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2198 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2200 eDVBServicePMTHandler::program program;
2201 if (h.getProgramInfo(program))
2202 eDebug("getting program info failed.");
2205 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2206 if (!program.videoStreams.empty())
2208 eDebugNoNewLine(" (");
2209 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2210 i(program.videoStreams.begin());
2211 i != program.videoStreams.end(); ++i)
2218 if (i != program.videoStreams.begin())
2219 eDebugNoNewLine(", ");
2220 eDebugNoNewLine("%04x", i->pid);
2222 eDebugNoNewLine(")");
2224 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2225 if (!program.audioStreams.empty())
2227 eDebugNoNewLine(" (");
2228 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2229 i(program.audioStreams.begin());
2230 i != program.audioStreams.end(); ++i)
2232 if (i != program.audioStreams.begin())
2233 eDebugNoNewLine(", ");
2234 eDebugNoNewLine("%04x", i->pid);
2236 eDebugNoNewLine(")");
2238 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2239 pcrpid = program.pcrPid;
2240 eDebug(", and the text pid is %04x", program.textPid);
2241 tpid = program.textPid;
2246 h.getDecodeDemux(m_decode_demux);
2249 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2251 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2252 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2253 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2254 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2255 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2258 m_teletext_parser = 0;
2259 m_subtitle_parser = 0;
2263 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2270 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2271 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2272 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2274 else // subservice or recording
2276 eServiceReferenceDVB ref;
2277 m_service_handler.getServiceReference(ref);
2278 eServiceReferenceDVB parent = ref.getParentServiceReference();
2283 ePtr<eDVBResourceManager> res_mgr;
2284 if (!eDVBResourceManager::getInstance(res_mgr))
2286 ePtr<iDVBChannelList> db;
2287 if (!res_mgr->getChannelList(db))
2289 ePtr<eDVBService> origService;
2290 if (!db->getService(parent, origService))
2292 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2293 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2300 std::string config_delay;
2301 int config_delay_int = 0;
2302 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2303 config_delay_int = atoi(config_delay.c_str());
2304 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2306 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2307 config_delay_int = atoi(config_delay.c_str());
2309 config_delay_int = 0;
2310 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2312 m_decoder->setVideoPID(vpid, vpidtype);
2313 selectAudioStream();
2315 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2316 m_decoder->setSyncPCR(pcrpid);
2318 m_decoder->setSyncPCR(-1);
2320 m_decoder->setTextPID(tpid);
2322 m_teletext_parser->start(program.textPid);
2324 if (vpid > 0 && vpid < 0x2000)
2328 std::string radio_pic;
2329 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2330 m_decoder->setRadioPic(radio_pic);
2333 /* if (!m_is_primary)
2334 m_decoder->setTrickmode();
2335 else */ if (m_is_paused)
2340 m_decoder->setAudioChannel(achannel);
2342 /* don't worry about non-existing services, nor pvr services */
2343 if (m_dvb_service && !m_is_pvr)
2345 /* (audio pid will be set in selectAudioTrack */
2346 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2347 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2348 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2349 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2352 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2355 void eDVBServicePlay::loadCuesheet()
2357 std::string filename = m_reference.path + ".cuts";
2359 m_cue_entries.clear();
2361 FILE *f = fopen(filename.c_str(), "rb");
2365 eDebug("loading cuts..");
2368 unsigned long long where;
2371 if (!fread(&where, sizeof(where), 1, f))
2373 if (!fread(&what, sizeof(what), 1, f))
2376 #if BYTE_ORDER == LITTLE_ENDIAN
2377 where = bswap_64(where);
2384 m_cue_entries.insert(cueEntry(where, what));
2387 eDebug("%d entries", m_cue_entries.size());
2389 eDebug("cutfile not found!");
2391 m_cuesheet_changed = 0;
2392 cutlistToCuesheet();
2393 m_event((iPlayableService*)this, evCuesheetChanged);
2396 void eDVBServicePlay::saveCuesheet()
2398 std::string filename = m_reference.path + ".cuts";
2400 FILE *f = fopen(filename.c_str(), "wb");
2404 unsigned long long where;
2407 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2409 #if BYTE_ORDER == BIG_ENDIAN
2412 where = bswap_64(i->where);
2414 what = htonl(i->what);
2415 fwrite(&where, sizeof(where), 1, f);
2416 fwrite(&what, sizeof(what), 1, f);
2422 m_cuesheet_changed = 0;
2425 void eDVBServicePlay::cutlistToCuesheet()
2429 eDebug("no cue sheet");
2434 if (!m_cutlist_enabled)
2436 m_cue->commitSpans();
2437 eDebug("cutlists were disabled");
2441 pts_t in = 0, out = 0, length = 0;
2445 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2447 int have_any_span = 0;
2451 if (i == m_cue_entries.end())
2457 if (i->what == 0) /* in */
2461 } else if (i->what == 1) /* out */
2463 else /* mark (2) or last play position (3) */
2482 m_cue->addSourceSpan(in, out);
2487 if (i == m_cue_entries.end())
2490 m_cue->commitSpans();
2493 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2495 if (m_subtitle_widget)
2496 disableSubtitles(parent);
2499 int tuplesize = PyTuple_Size(tuple);
2502 if (!PyTuple_Check(tuple))
2508 entry = PyTuple_GET_ITEM(tuple, 0);
2510 if (!PyInt_Check(entry))
2513 type = PyInt_AsLong(entry);
2515 if (type == 1) // teletext subtitles
2517 int page, magazine, pid;
2521 if (!m_teletext_parser)
2523 eDebug("enable teletext subtitles.. no parser !!!");
2527 entry = PyTuple_GET_ITEM(tuple, 1);
2528 if (!PyInt_Check(entry))
2530 pid = PyInt_AsLong(entry);
2532 entry = PyTuple_GET_ITEM(tuple, 2);
2533 if (!PyInt_Check(entry))
2535 page = PyInt_AsLong(entry);
2537 entry = PyTuple_GET_ITEM(tuple, 3);
2538 if (!PyInt_Check(entry))
2540 magazine = PyInt_AsLong(entry);
2542 m_subtitle_widget = new eSubtitleWidget(parent);
2543 m_subtitle_widget->resize(parent->size()); /* full size */
2544 m_teletext_parser->setPageAndMagazine(page, magazine);
2546 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2550 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2551 if (!m_subtitle_parser)
2553 eDebug("enable dvb subtitles.. no parser !!!");
2559 entry = PyTuple_GET_ITEM(tuple, 1);
2560 if (!PyInt_Check(entry))
2562 pid = PyInt_AsLong(entry);
2564 entry = PyTuple_GET_ITEM(tuple, 2);
2565 if (!PyInt_Check(entry))
2567 composition_page_id = PyInt_AsLong(entry);
2569 entry = PyTuple_GET_ITEM(tuple, 3);
2570 if (!PyInt_Check(entry))
2572 ancillary_page_id = PyInt_AsLong(entry);
2574 m_subtitle_widget = new eSubtitleWidget(parent);
2575 m_subtitle_widget->resize(parent->size()); /* full size */
2576 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2578 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2584 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2585 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2586 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2590 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2592 delete m_subtitle_widget;
2593 m_subtitle_widget = 0;
2594 if (m_subtitle_parser)
2596 m_subtitle_parser->stop();
2597 m_dvb_subtitle_pages.clear();
2599 if (m_teletext_parser)
2601 m_teletext_parser->setPageAndMagazine(-1, -1);
2602 m_subtitle_pages.clear();
2605 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2609 PyObject *eDVBServicePlay::getCachedSubtitle()
2613 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2616 unsigned int data = (unsigned int)tmp;
2617 int pid = (data&0xFFFF0000)>>16;
2618 ePyObject tuple = PyTuple_New(4);
2619 eDVBServicePMTHandler::program program;
2620 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2621 if (!h.getProgramInfo(program))
2623 if (program.textPid==pid) // teletext
2624 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2626 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2627 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2628 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2629 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2637 PyObject *eDVBServicePlay::getSubtitleList()
2639 if (!m_teletext_parser)
2642 ePyObject l = PyList_New(0);
2643 std::set<int> added_ttx_pages;
2645 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2646 m_teletext_parser->m_found_subtitle_pages;
2648 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2649 eDVBServicePMTHandler::program program;
2650 if (h.getProgramInfo(program))
2651 eDebug("getting program info failed.");
2654 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2655 it != program.subtitleStreams.end(); ++it)
2657 switch(it->subtitling_type)
2659 case 0x01: // ebu teletext subtitles
2661 int page_number = it->teletext_page_number & 0xFF;
2662 int magazine_number = it->teletext_magazine_number & 7;
2663 int hash = magazine_number << 8 | page_number;
2664 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2666 ePyObject tuple = PyTuple_New(5);
2667 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2668 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2669 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2670 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2671 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2672 PyList_Append(l, tuple);
2674 added_ttx_pages.insert(hash);
2679 case 0x20 ... 0x23: // dvb subtitles
2681 ePyObject tuple = PyTuple_New(5);
2682 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2683 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2684 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2685 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2686 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2687 PyList_Insert(l, 0, tuple);
2695 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2696 it != subs.end(); ++it)
2698 int page_number = it->teletext_page_number & 0xFF;
2699 int magazine_number = it->teletext_magazine_number & 7;
2700 int hash = magazine_number << 8 | page_number;
2701 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2703 ePyObject tuple = PyTuple_New(5);
2704 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2705 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2706 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2707 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2708 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2709 PyList_Append(l, tuple);
2717 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2719 if (m_subtitle_widget)
2723 m_decoder->getPTS(0, pos);
2724 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2725 m_subtitle_pages.push_back(page);
2726 checkSubtitleTiming();
2730 void eDVBServicePlay::checkSubtitleTiming()
2732 eDebug("checkSubtitleTiming");
2733 if (!m_subtitle_widget)
2737 enum { TELETEXT, DVB } type;
2738 eDVBTeletextSubtitlePage page;
2739 eDVBSubtitlePage dvb_page;
2741 if (!m_subtitle_pages.empty())
2743 page = m_subtitle_pages.front();
2745 show_time = page.m_pts;
2747 else if (!m_dvb_subtitle_pages.empty())
2749 dvb_page = m_dvb_subtitle_pages.front();
2751 show_time = dvb_page.m_show_time;
2759 m_decoder->getPTS(0, pos);
2761 eDebug("%lld %lld", pos, show_time);
2762 int diff = show_time - pos;
2765 eDebug("[late (%d ms)]", -diff / 90);
2768 // if (diff > 900000)
2770 // eDebug("[invalid]");
2776 if (type == TELETEXT)
2778 eDebug("display teletext subtitle page %lld", show_time);
2779 m_subtitle_widget->setPage(page);
2780 m_subtitle_pages.pop_front();
2784 eDebug("display dvb subtitle Page %lld", show_time);
2785 m_subtitle_widget->setPage(dvb_page);
2786 m_dvb_subtitle_pages.pop_front();
2790 eDebug("start subtitle delay %d", diff / 90);
2791 m_subtitle_sync_timer->start(diff / 90, 1);
2797 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2799 if (m_subtitle_widget)
2803 m_decoder->getPTS(0, pos);
2804 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2805 m_dvb_subtitle_pages.push_back(p);
2806 checkSubtitleTiming();
2810 int eDVBServicePlay::getAC3Delay()
2813 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2815 return m_decoder->getAC3Delay();
2820 int eDVBServicePlay::getPCMDelay()
2823 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2825 return m_decoder->getPCMDelay();
2830 void eDVBServicePlay::setAC3Delay(int delay)
2833 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2835 m_decoder->setAC3Delay(delay);
2838 void eDVBServicePlay::setPCMDelay(int delay)
2841 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2843 m_decoder->setPCMDelay(delay);
2846 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2848 switch(event.type) {
2849 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2850 m_event((iPlayableService*)this, evVideoSizeChanged);
2852 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2853 m_event((iPlayableService*)this, evVideoFramerateChanged);
2855 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2856 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2863 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2869 PyObject *eDVBServicePlay::getStreamingData()
2871 eDVBServicePMTHandler::program program;
2872 if (m_service_handler.getProgramInfo(program))
2877 ePyObject r = program.createPythonObject();
2878 ePtr<iDVBDemux> demux;
2879 if (!m_service_handler.getDataDemux(demux))
2882 if (!demux->getCADemuxID(demux_id))
2883 PutToDict(r, "demux", demux_id);
2890 DEFINE_REF(eDVBServicePlay)
2892 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2896 case iServiceInformation::sTransponderData:
2897 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2901 return iStaticServiceInformation::getInfoObject(ref, w);
2904 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");