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 if (!ref.path.empty()) // playback
865 eDVBMetaParser parser;
866 int ret=parser.parseFile(ref.path);
867 service = new eDVBService;
869 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
873 // TODO: handle the listing itself
874 // if (ref.... == -1) .. return "... bouquets ...";
875 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
877 ePtr<iDVBChannelList> db;
878 ePtr<eDVBResourceManager> res;
881 if ((err = eDVBResourceManager::getInstance(res)) != 0)
883 eDebug("no resource manager");
886 if ((err = res->getChannelList(db)) != 0)
888 eDebug("no channel list");
892 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
893 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
895 eDebug("getService failed!");
903 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
904 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
907 m_is_pvr = !m_reference.path.empty();
909 m_timeshift_enabled = m_timeshift_active = 0;
912 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
913 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
914 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
916 m_cuesheet_changed = 0;
917 m_cutlist_enabled = 1;
919 m_subtitle_widget = 0;
923 m_subtitle_sync_timer = eTimer::create(eApp);
925 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
928 eDVBServicePlay::~eDVBServicePlay()
933 int ret=meta.parseFile(m_reference.path);
937 meta.m_service_data="";
938 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
939 meta.m_service_data += tmp;
941 for (int x=0; x < eDVBService::cacheMax; ++x)
943 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
946 sprintf(tmp, ",c:%02d%04x", x, entry);
947 meta.m_service_data += tmp;
950 meta.updateMeta(m_reference.path);
953 delete m_subtitle_widget;
956 void eDVBServicePlay::gotNewEvent()
960 ePtr<eServiceEvent> m_event_now, m_event_next;
961 getEvent(m_event_now, 0);
962 getEvent(m_event_next, 1);
965 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
967 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
969 m_event((iPlayableService*)this, evUpdatedEventInfo);
972 void eDVBServicePlay::serviceEvent(int event)
974 m_tune_state = event;
978 case eDVBServicePMTHandler::eventTuned:
980 ePtr<iDVBDemux> m_demux;
981 if (!m_service_handler.getDataDemux(m_demux))
983 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
984 int sid = ref.getParentServiceID().get();
986 sid = ref.getServiceID().get();
987 if ( ref.getParentTransportStreamID().get() &&
988 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
989 m_event_handler.startOther(m_demux, sid);
991 m_event_handler.start(m_demux, sid);
993 m_event((iPlayableService*)this, evTunedIn);
996 case eDVBServicePMTHandler::eventNoResources:
997 case eDVBServicePMTHandler::eventNoPAT:
998 case eDVBServicePMTHandler::eventNoPATEntry:
999 case eDVBServicePMTHandler::eventNoPMT:
1000 case eDVBServicePMTHandler::eventTuneFailed:
1001 case eDVBServicePMTHandler::eventMisconfiguration:
1003 eDebug("DVB service failed to tune - error %d", event);
1004 m_event((iPlayableService*)this, evTuneFailed);
1007 case eDVBServicePMTHandler::eventNewProgramInfo:
1009 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1010 if (m_timeshift_enabled)
1011 updateTimeshiftPids();
1012 if (!m_timeshift_active)
1014 if (m_first_program_info && m_is_pvr)
1016 m_first_program_info = 0;
1019 m_event((iPlayableService*)this, evUpdatedInfo);
1022 case eDVBServicePMTHandler::eventEOF:
1023 m_event((iPlayableService*)this, evEOF);
1025 case eDVBServicePMTHandler::eventSOF:
1026 m_event((iPlayableService*)this, evSOF);
1031 void eDVBServicePlay::serviceEventTimeshift(int event)
1035 case eDVBServicePMTHandler::eventNewProgramInfo:
1036 if (m_timeshift_active)
1039 case eDVBServicePMTHandler::eventSOF:
1040 m_event((iPlayableService*)this, evSOF);
1042 case eDVBServicePMTHandler::eventEOF:
1043 if ((!m_is_paused) && (m_skipmode >= 0))
1045 eDebug("timeshift EOF, so let's go live");
1052 RESULT eDVBServicePlay::start()
1055 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1056 two (one for decoding, one for data source), as we must be prepared
1057 to start recording from the data demux. */
1059 m_cue = new eCueSheet();
1061 m_event(this, evStart);
1063 m_first_program_info = 1;
1064 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1065 r = m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1067 /* inject EIT if there is a stored one */
1070 std::string filename = service.path;
1071 filename.erase(filename.length()-2, 2);
1073 ePtr<eServiceEvent> event = new eServiceEvent;
1074 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1076 ePtr<eServiceEvent> empty;
1077 m_event_handler.inject(event, 0);
1078 m_event_handler.inject(empty, 1);
1085 m_event(this, evStart);
1090 RESULT eDVBServicePlay::stop()
1092 /* add bookmark for last play position */
1095 pts_t play_position, length;
1096 if (!getPlayPosition(play_position))
1098 /* remove last position */
1099 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1101 if (i->what == 3) /* current play position */
1103 m_cue_entries.erase(i);
1104 i = m_cue_entries.begin();
1110 if (getLength(length))
1115 int perc = play_position * 100LL / length;
1117 /* only store last play position when between 1% and 99% */
1118 if ((1 < perc) && (perc < 99))
1119 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1121 m_cuesheet_changed = 1;
1125 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1127 m_service_handler_timeshift.free();
1128 m_service_handler.free();
1130 if (m_is_pvr && m_cuesheet_changed)
1133 /* save cuesheet only when main file is accessible. */
1134 if (!::stat(m_reference.path.c_str(), &s))
1137 m_event((iPlayableService*)this, evStopped);
1141 RESULT eDVBServicePlay::setTarget(int target)
1143 m_is_primary = !target;
1147 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1149 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1153 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1155 /* note: we check for timeshift to be enabled,
1156 not neccessary active. if you pause when timeshift
1157 is not active, you should activate it when unpausing */
1158 if ((!m_is_pvr) && (!m_timeshift_enabled))
1168 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1170 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1171 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1172 setFastForward_internal(0);
1174 return m_decoder->setSlowMotion(ratio);
1179 RESULT eDVBServicePlay::setFastForward(int ratio)
1181 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1183 return setFastForward_internal(ratio);
1186 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1188 int skipmode, ffratio;
1194 } else if (ratio > 0)
1202 } else // if (ratio < 0)
1208 if (m_skipmode != skipmode)
1210 eDebug("setting cue skipmode to %d", skipmode);
1212 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1215 m_skipmode = skipmode;
1221 ; /* return m_decoder->play(); is done in caller*/
1222 else if (ffratio != 1)
1223 return m_decoder->setFastForward(ffratio);
1225 return m_decoder->setTrickmode();
1228 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1230 if (m_is_pvr || m_timeshift_enabled)
1240 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1241 RESULT eDVBServicePlay::getLength(pts_t &len)
1243 ePtr<iDVBPVRChannel> pvr_channel;
1245 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1248 return pvr_channel->getLength(len);
1251 RESULT eDVBServicePlay::pause()
1253 eDebug("eDVBServicePlay::pause");
1254 setFastForward_internal(0);
1258 return m_decoder->pause();
1263 RESULT eDVBServicePlay::unpause()
1265 eDebug("eDVBServicePlay::unpause");
1266 setFastForward_internal(0);
1270 return m_decoder->play();
1275 RESULT eDVBServicePlay::seekTo(pts_t to)
1277 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1279 if (!m_decode_demux)
1282 ePtr<iDVBPVRChannel> pvr_channel;
1284 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1290 m_cue->seekTo(0, to);
1291 m_dvb_subtitle_pages.clear();
1292 m_subtitle_pages.clear();
1297 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1299 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1301 if (!m_decode_demux)
1304 ePtr<iDVBPVRChannel> pvr_channel;
1306 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1311 /* HACK until we have skip-AP api */
1312 if ((to > 0) && (to < 100))
1320 m_cue->seekTo(mode, to);
1321 m_dvb_subtitle_pages.clear();
1322 m_subtitle_pages.clear();
1326 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1328 ePtr<iDVBPVRChannel> pvr_channel;
1330 if (!m_decode_demux)
1333 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1338 /* if there is a decoder, use audio or video PTS */
1341 r = m_decoder->getPTS(0, pos);
1347 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1350 RESULT eDVBServicePlay::setTrickmode(int trick)
1352 /* currently unimplemented */
1356 RESULT eDVBServicePlay::isCurrentlySeekable()
1358 return m_is_pvr || m_timeshift_active;
1361 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1367 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1373 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1379 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1385 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1391 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1394 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1395 (m_timeshift_enabled || !m_is_pvr))
1397 if (!m_timeshift_enabled)
1399 /* query config path */
1401 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1402 eDebug("could not query ts path from config");
1406 /* we need enough diskspace */
1408 if (statfs(tspath.c_str(), &fs) < 0)
1410 eDebug("statfs failed!");
1414 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1416 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1426 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1437 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1443 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1449 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1455 RESULT eDVBServicePlay::getName(std::string &name)
1459 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1460 return i->getName(m_reference, name);
1462 else if (m_dvb_service)
1464 m_dvb_service->getName(m_reference, name);
1468 else if (!m_reference.name.empty())
1469 eStaticServiceDVBInformation().getName(m_reference, name);
1471 name = "DVB service";
1475 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1477 return m_event_handler.getEvent(evt, nownext);
1480 int eDVBServicePlay::getInfo(int w)
1482 eDVBServicePMTHandler::program program;
1485 return resIsPyObject;
1487 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1489 int no_program_info = 0;
1491 if (h.getProgramInfo(program))
1492 no_program_info = 1;
1498 return m_decoder->getVideoHeight();
1502 return m_decoder->getVideoWidth();
1506 return m_decoder->getVideoFrameRate();
1510 return m_decoder->getVideoProgressive();
1516 aspect = m_decoder->getVideoAspect();
1517 if (no_program_info)
1519 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1521 ePtr<eServiceEvent> evt;
1522 if (!m_event_handler.getEvent(evt, 0))
1524 ePtr<eComponentData> data;
1525 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1527 if ( data->getStreamContent() == 1 )
1529 switch(data->getComponentType())
1532 case 1: // 4:3 SD PAL
1534 case 3: // 16:9 SD PAL
1535 case 4: // > 16:9 PAL
1536 case 5: // 4:3 SD NTSC
1538 case 7: // 16:9 SD NTSC
1539 case 8: // > 16:9 NTSC
1542 case 9: // 4:3 HD PAL
1544 case 0xB: // 16:9 HD PAL
1545 case 0xC: // > 16:9 HD PAL
1546 case 0xD: // 4:3 HD NTSC
1548 case 0xF: // 16:9 HD NTSC
1549 case 0x10: // > 16:9 HD PAL
1550 return data->getComponentType();
1560 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1561 case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1562 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1563 case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1564 case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1565 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1566 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1567 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1568 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1569 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1570 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1571 case sProvider: if (!m_dvb_service) return -1; return -2;
1572 case sServiceref: return resIsString;
1573 case sDVBState: return m_tune_state;
1580 std::string eDVBServicePlay::getInfoString(int w)
1585 if (!m_dvb_service) return "";
1586 return m_dvb_service->m_provider_name;
1588 return m_reference.toString();
1592 return iServiceInformation::getInfoString(w);
1595 PyObject *eDVBServicePlay::getInfoObject(int w)
1600 return m_service_handler.getCaIds();
1601 case sTransponderData:
1602 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1606 return iServiceInformation::getInfoObject(w);
1609 int eDVBServicePlay::getNumberOfTracks()
1611 eDVBServicePMTHandler::program program;
1612 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1613 if (h.getProgramInfo(program))
1615 return program.audioStreams.size();
1618 int eDVBServicePlay::getCurrentTrack()
1620 eDVBServicePMTHandler::program program;
1621 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1622 if (h.getProgramInfo(program))
1625 int max = program.audioStreams.size();
1628 for (i = 0; i < max; ++i)
1629 if (program.audioStreams[i].pid == m_current_audio_pid)
1635 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1637 int ret = selectAudioStream(i);
1639 if (m_decoder->set())
1645 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1647 eDVBServicePMTHandler::program program;
1648 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1650 if (h.getProgramInfo(program))
1653 if (i >= program.audioStreams.size())
1656 info.m_pid = program.audioStreams[i].pid;
1658 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1659 info.m_description = "MPEG";
1660 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1661 info.m_description = "AC3";
1662 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1663 info.m_description = "AAC";
1664 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1665 info.m_description = "AAC-HE";
1666 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1667 info.m_description = "DTS";
1669 info.m_description = "???";
1671 if (program.audioStreams[i].component_tag != -1)
1673 ePtr<eServiceEvent> evt;
1674 if (!m_event_handler.getEvent(evt, 0))
1676 ePtr<eComponentData> data;
1677 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1678 info.m_language = data->getText();
1682 if (info.m_language.empty())
1683 info.m_language = program.audioStreams[i].language_code;
1688 int eDVBServicePlay::selectAudioStream(int i)
1690 eDVBServicePMTHandler::program program;
1691 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1693 if (h.getProgramInfo(program))
1696 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1704 stream = program.defaultAudioStream;
1706 int apid = -1, apidtype = -1;
1708 if (((unsigned int)stream) < program.audioStreams.size())
1710 apid = program.audioStreams[stream].pid;
1711 apidtype = program.audioStreams[stream].type;
1714 m_current_audio_pid = apid;
1716 if (m_decoder->setAudioPID(apid, apidtype))
1718 eDebug("set audio pid failed");
1722 /* 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 */
1723 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1726 ePtr<iDVBDemux> data_demux;
1727 if (!h.getDataDemux(data_demux))
1729 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1730 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1734 /* if we decided that we need one, update the pid */
1736 m_rds_decoder->start(apid);
1738 /* store new pid as default only when:
1739 a.) we have an entry in the service db for the current service,
1740 b.) we are not playing back something,
1741 c.) we are not selecting the default entry. (we wouldn't change
1742 anything in the best case, or destroy the default setting in
1743 case the real default is not yet available.)
1745 if (m_dvb_service && ((i != -1)
1746 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1748 if (apidtype == eDVBAudio::aMPEG)
1750 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1751 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1753 else if (apidtype == eDVBAudio::aAC3)
1755 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1756 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1760 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1761 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1765 h.resetCachedProgram();
1770 int eDVBServicePlay::getCurrentChannel()
1772 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1775 RESULT eDVBServicePlay::selectChannel(int i)
1777 if (i < LEFT || i > RIGHT || i == STEREO)
1780 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1782 m_decoder->setAudioChannel(i);
1786 std::string eDVBServicePlay::getText(int x)
1792 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1794 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1799 void eDVBServicePlay::rdsDecoderEvent(int what)
1803 case eDVBRdsDecoder::RadioTextChanged:
1804 m_event((iPlayableService*)this, evUpdatedRadioText);
1806 case eDVBRdsDecoder::RtpTextChanged:
1807 m_event((iPlayableService*)this, evUpdatedRtpText);
1809 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1810 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1812 case eDVBRdsDecoder::RecvRassSlidePic:
1813 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1818 void eDVBServicePlay::showRassSlidePicture()
1824 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1825 if (rass_slide_pic.length())
1826 m_decoder->showSinglePic(rass_slide_pic.c_str());
1828 eDebug("empty filename for rass slide picture received!!");
1831 eDebug("no MPEG Decoder to show iframes avail");
1834 eDebug("showRassSlidePicture called.. but not decoder");
1837 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1843 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1844 if (rass_interactive_pic.length())
1845 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1847 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1850 eDebug("no MPEG Decoder to show iframes avail");
1853 eDebug("showRassInteractivePic called.. but not decoder");
1856 ePyObject eDVBServicePlay::getRassInteractiveMask()
1859 return m_rds_decoder->getRassPictureMask();
1863 int eDVBServiceBase::getFrontendInfo(int w)
1865 eUsePtr<iDVBChannel> channel;
1866 if(m_service_handler.getChannel(channel))
1868 ePtr<iDVBFrontend> fe;
1869 if(channel->getFrontend(fe))
1871 return fe->readFrontendData(w);
1874 PyObject *eDVBServiceBase::getFrontendData()
1876 ePyObject ret = PyDict_New();
1879 eUsePtr<iDVBChannel> channel;
1880 if(!m_service_handler.getChannel(channel))
1882 ePtr<iDVBFrontend> fe;
1883 if(!channel->getFrontend(fe))
1884 fe->getFrontendData(ret);
1892 PyObject *eDVBServiceBase::getFrontendStatus()
1894 ePyObject ret = PyDict_New();
1897 eUsePtr<iDVBChannel> channel;
1898 if(!m_service_handler.getChannel(channel))
1900 ePtr<iDVBFrontend> fe;
1901 if(!channel->getFrontend(fe))
1902 fe->getFrontendStatus(ret);
1910 PyObject *eDVBServiceBase::getTransponderData(bool original)
1912 ePyObject ret = PyDict_New();
1915 eUsePtr<iDVBChannel> channel;
1916 if(!m_service_handler.getChannel(channel))
1918 ePtr<iDVBFrontend> fe;
1919 if(!channel->getFrontend(fe))
1920 fe->getTransponderData(ret, original);
1928 PyObject *eDVBServiceBase::getAll(bool original)
1930 ePyObject ret = getTransponderData(original);
1933 eUsePtr<iDVBChannel> channel;
1934 if(!m_service_handler.getChannel(channel))
1936 ePtr<iDVBFrontend> fe;
1937 if(!channel->getFrontend(fe))
1939 fe->getFrontendData(ret);
1940 fe->getFrontendStatus(ret);
1947 int eDVBServicePlay::getNumberOfSubservices()
1949 ePtr<eServiceEvent> evt;
1950 if (!m_event_handler.getEvent(evt, 0))
1951 return evt->getNumOfLinkageServices();
1955 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1957 ePtr<eServiceEvent> evt;
1958 if (!m_event_handler.getEvent(evt, 0))
1960 if (!evt->getLinkageService(sub, m_reference, n))
1963 sub.type=eServiceReference::idInvalid;
1967 RESULT eDVBServicePlay::startTimeshift()
1969 ePtr<iDVBDemux> demux;
1971 eDebug("Start timeshift!");
1973 if (m_timeshift_enabled)
1976 /* start recording with the data demux. */
1977 if (m_service_handler.getDataDemux(demux))
1980 demux->createTSRecorder(m_record);
1985 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1986 eDebug("could not query ts path");
1989 tspath.append("/timeshift.XXXXXX");
1991 templ = new char[tspath.length() + 1];
1992 strcpy(templ, tspath.c_str());
1994 m_timeshift_fd = mkstemp(templ);
1995 m_timeshift_file = std::string(templ);
1997 eDebug("recording to %s", templ);
2001 if (m_timeshift_fd < 0)
2007 m_record->setTargetFD(m_timeshift_fd);
2009 m_timeshift_enabled = 1;
2011 updateTimeshiftPids();
2017 RESULT eDVBServicePlay::stopTimeshift()
2019 if (!m_timeshift_enabled)
2024 m_timeshift_enabled = 0;
2029 close(m_timeshift_fd);
2030 eDebug("remove timeshift file");
2031 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2036 int eDVBServicePlay::isTimeshiftActive()
2038 return m_timeshift_enabled && m_timeshift_active;
2041 RESULT eDVBServicePlay::activateTimeshift()
2043 if (!m_timeshift_enabled)
2046 if (!m_timeshift_active)
2048 switchToTimeshift();
2055 PyObject *eDVBServicePlay::getCutList()
2057 ePyObject list = PyList_New(0);
2059 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2061 ePyObject tuple = PyTuple_New(2);
2062 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2063 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2064 PyList_Append(list, tuple);
2071 void eDVBServicePlay::setCutList(ePyObject list)
2073 if (!PyList_Check(list))
2075 int size = PyList_Size(list);
2078 m_cue_entries.clear();
2080 for (i=0; i<size; ++i)
2082 ePyObject tuple = PyList_GET_ITEM(list, i);
2083 if (!PyTuple_Check(tuple))
2085 eDebug("non-tuple in cutlist");
2088 if (PyTuple_Size(tuple) != 2)
2090 eDebug("cutlist entries need to be a 2-tuple");
2093 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2094 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2096 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2099 pts_t pts = PyLong_AsLongLong(ppts);
2100 int type = PyInt_AsLong(ptype);
2101 m_cue_entries.insert(cueEntry(pts, type));
2102 eDebug("adding %08llx, %d", pts, type);
2104 m_cuesheet_changed = 1;
2106 cutlistToCuesheet();
2107 m_event((iPlayableService*)this, evCuesheetChanged);
2110 void eDVBServicePlay::setCutListEnable(int enable)
2112 m_cutlist_enabled = enable;
2113 cutlistToCuesheet();
2116 void eDVBServicePlay::updateTimeshiftPids()
2121 eDVBServicePMTHandler::program program;
2122 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2124 if (h.getProgramInfo(program))
2128 std::set<int> pids_to_record;
2129 pids_to_record.insert(0); // PAT
2130 if (program.pmtPid != -1)
2131 pids_to_record.insert(program.pmtPid); // PMT
2133 if (program.textPid != -1)
2134 pids_to_record.insert(program.textPid); // Videotext
2136 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2137 i(program.videoStreams.begin());
2138 i != program.videoStreams.end(); ++i)
2139 pids_to_record.insert(i->pid);
2141 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2142 i(program.audioStreams.begin());
2143 i != program.audioStreams.end(); ++i)
2144 pids_to_record.insert(i->pid);
2146 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2147 i(program.subtitleStreams.begin());
2148 i != program.subtitleStreams.end(); ++i)
2149 pids_to_record.insert(i->pid);
2151 std::set<int> new_pids, obsolete_pids;
2153 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2154 m_pids_active.begin(), m_pids_active.end(),
2155 std::inserter(new_pids, new_pids.begin()));
2157 std::set_difference(
2158 m_pids_active.begin(), m_pids_active.end(),
2159 pids_to_record.begin(), pids_to_record.end(),
2160 std::inserter(new_pids, new_pids.begin())
2163 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2164 m_record->addPID(*i);
2166 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2167 m_record->removePID(*i);
2171 void eDVBServicePlay::switchToLive()
2173 if (!m_timeshift_active)
2176 eDebug("SwitchToLive");
2181 m_teletext_parser = 0;
2183 m_subtitle_parser = 0;
2184 m_new_dvb_subtitle_page_connection = 0;
2185 m_new_subtitle_page_connection = 0;
2186 m_rds_decoder_event_connection = 0;
2187 m_video_event_connection = 0;
2189 /* free the timeshift service handler, we need the resources */
2190 m_service_handler_timeshift.free();
2191 m_timeshift_active = 0;
2193 m_event((iPlayableService*)this, evSeekableStatusChanged);
2198 void eDVBServicePlay::switchToTimeshift()
2200 if (m_timeshift_active)
2205 m_teletext_parser = 0;
2207 m_subtitle_parser = 0;
2208 m_new_subtitle_page_connection = 0;
2209 m_new_dvb_subtitle_page_connection = 0;
2210 m_rds_decoder_event_connection = 0;
2211 m_video_event_connection = 0;
2213 m_timeshift_active = 1;
2215 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2216 r.path = m_timeshift_file;
2218 m_cue = new eCueSheet();
2219 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2221 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2223 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2225 m_event((iPlayableService*)this, evSeekableStatusChanged);
2228 void eDVBServicePlay::updateDecoder()
2230 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2232 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2234 eDVBServicePMTHandler::program program;
2235 if (h.getProgramInfo(program))
2236 eDebug("getting program info failed.");
2239 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2240 if (!program.videoStreams.empty())
2242 eDebugNoNewLine(" (");
2243 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2244 i(program.videoStreams.begin());
2245 i != program.videoStreams.end(); ++i)
2252 if (i != program.videoStreams.begin())
2253 eDebugNoNewLine(", ");
2254 eDebugNoNewLine("%04x", i->pid);
2256 eDebugNoNewLine(")");
2258 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2259 if (!program.audioStreams.empty())
2261 eDebugNoNewLine(" (");
2262 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2263 i(program.audioStreams.begin());
2264 i != program.audioStreams.end(); ++i)
2266 if (i != program.audioStreams.begin())
2267 eDebugNoNewLine(", ");
2268 eDebugNoNewLine("%04x", i->pid);
2270 eDebugNoNewLine(")");
2272 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2273 pcrpid = program.pcrPid;
2274 eDebug(", and the text pid is %04x", program.textPid);
2275 tpid = program.textPid;
2280 h.getDecodeDemux(m_decode_demux);
2283 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2285 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2286 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2287 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2288 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2289 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2292 m_teletext_parser = 0;
2293 m_subtitle_parser = 0;
2297 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2304 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2305 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2306 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2310 eServiceReferenceDVB ref;
2311 m_service_handler.getServiceReference(ref);
2312 eServiceReferenceDVB parent = ref.getParentServiceReference();
2317 ePtr<eDVBResourceManager> res_mgr;
2318 if (!eDVBResourceManager::getInstance(res_mgr))
2320 ePtr<iDVBChannelList> db;
2321 if (!res_mgr->getChannelList(db))
2323 ePtr<eDVBService> origService;
2324 if (!db->getService(parent, origService))
2326 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2327 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2334 std::string config_delay;
2335 int config_delay_int = 0;
2336 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2337 config_delay_int = atoi(config_delay.c_str());
2338 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2340 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2341 config_delay_int = atoi(config_delay.c_str());
2343 config_delay_int = 0;
2344 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2346 m_decoder->setVideoPID(vpid, vpidtype);
2347 selectAudioStream();
2349 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2350 m_decoder->setSyncPCR(pcrpid);
2352 m_decoder->setSyncPCR(-1);
2354 m_decoder->setTextPID(tpid);
2356 m_teletext_parser->start(program.textPid);
2358 if (vpid > 0 && vpid < 0x2000)
2362 std::string radio_pic;
2363 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2364 m_decoder->setRadioPic(radio_pic);
2367 /* if (!m_is_primary)
2368 m_decoder->setTrickmode();
2369 else */ if (m_is_paused)
2374 m_decoder->setAudioChannel(achannel);
2376 /* don't worry about non-existing services, nor pvr services */
2379 /* (audio pid will be set in selectAudioTrack */
2380 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2381 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2382 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2383 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2386 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2389 void eDVBServicePlay::loadCuesheet()
2391 std::string filename = m_reference.path + ".cuts";
2393 m_cue_entries.clear();
2395 FILE *f = fopen(filename.c_str(), "rb");
2399 eDebug("loading cuts..");
2402 unsigned long long where;
2405 if (!fread(&where, sizeof(where), 1, f))
2407 if (!fread(&what, sizeof(what), 1, f))
2410 #if BYTE_ORDER == LITTLE_ENDIAN
2411 where = bswap_64(where);
2418 m_cue_entries.insert(cueEntry(where, what));
2421 eDebug("%d entries", m_cue_entries.size());
2423 eDebug("cutfile not found!");
2425 m_cuesheet_changed = 0;
2426 cutlistToCuesheet();
2427 m_event((iPlayableService*)this, evCuesheetChanged);
2430 void eDVBServicePlay::saveCuesheet()
2432 std::string filename = m_reference.path + ".cuts";
2434 FILE *f = fopen(filename.c_str(), "wb");
2438 unsigned long long where;
2441 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2443 #if BYTE_ORDER == BIG_ENDIAN
2446 where = bswap_64(i->where);
2448 what = htonl(i->what);
2449 fwrite(&where, sizeof(where), 1, f);
2450 fwrite(&what, sizeof(what), 1, f);
2456 m_cuesheet_changed = 0;
2459 void eDVBServicePlay::cutlistToCuesheet()
2463 eDebug("no cue sheet");
2468 if (!m_cutlist_enabled)
2470 m_cue->commitSpans();
2471 eDebug("cutlists were disabled");
2475 pts_t in = 0, out = 0, length = 0;
2479 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2481 int have_any_span = 0;
2485 if (i == m_cue_entries.end())
2491 if (i->what == 0) /* in */
2495 } else if (i->what == 1) /* out */
2497 else /* mark (2) or last play position (3) */
2516 m_cue->addSourceSpan(in, out);
2521 if (i == m_cue_entries.end())
2524 m_cue->commitSpans();
2527 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2529 if (m_subtitle_widget)
2530 disableSubtitles(parent);
2533 int tuplesize = PyTuple_Size(tuple);
2536 if (!PyTuple_Check(tuple))
2542 entry = PyTuple_GET_ITEM(tuple, 0);
2544 if (!PyInt_Check(entry))
2547 type = PyInt_AsLong(entry);
2549 if (type == 1) // teletext subtitles
2551 int page, magazine, pid;
2555 if (!m_teletext_parser)
2557 eDebug("enable teletext subtitles.. no parser !!!");
2561 entry = PyTuple_GET_ITEM(tuple, 1);
2562 if (!PyInt_Check(entry))
2564 pid = PyInt_AsLong(entry);
2566 entry = PyTuple_GET_ITEM(tuple, 2);
2567 if (!PyInt_Check(entry))
2569 page = PyInt_AsLong(entry);
2571 entry = PyTuple_GET_ITEM(tuple, 3);
2572 if (!PyInt_Check(entry))
2574 magazine = PyInt_AsLong(entry);
2576 m_subtitle_widget = new eSubtitleWidget(parent);
2577 m_subtitle_widget->resize(parent->size()); /* full size */
2578 m_teletext_parser->setPageAndMagazine(page, magazine);
2580 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2584 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2585 if (!m_subtitle_parser)
2587 eDebug("enable dvb subtitles.. no parser !!!");
2593 entry = PyTuple_GET_ITEM(tuple, 1);
2594 if (!PyInt_Check(entry))
2596 pid = PyInt_AsLong(entry);
2598 entry = PyTuple_GET_ITEM(tuple, 2);
2599 if (!PyInt_Check(entry))
2601 composition_page_id = PyInt_AsLong(entry);
2603 entry = PyTuple_GET_ITEM(tuple, 3);
2604 if (!PyInt_Check(entry))
2606 ancillary_page_id = PyInt_AsLong(entry);
2608 m_subtitle_widget = new eSubtitleWidget(parent);
2609 m_subtitle_widget->resize(parent->size()); /* full size */
2610 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2612 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2618 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2619 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2620 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2624 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2626 delete m_subtitle_widget;
2627 m_subtitle_widget = 0;
2628 if (m_subtitle_parser)
2630 m_subtitle_parser->stop();
2631 m_dvb_subtitle_pages.clear();
2633 if (m_teletext_parser)
2635 m_teletext_parser->setPageAndMagazine(-1, -1);
2636 m_subtitle_pages.clear();
2639 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2643 PyObject *eDVBServicePlay::getCachedSubtitle()
2647 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2650 unsigned int data = (unsigned int)tmp;
2651 int pid = (data&0xFFFF0000)>>16;
2652 ePyObject tuple = PyTuple_New(4);
2653 eDVBServicePMTHandler::program program;
2654 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2655 if (!h.getProgramInfo(program))
2657 if (program.textPid==pid) // teletext
2658 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2660 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2661 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2662 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2663 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2671 PyObject *eDVBServicePlay::getSubtitleList()
2673 if (!m_teletext_parser)
2676 ePyObject l = PyList_New(0);
2677 std::set<int> added_ttx_pages;
2679 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2680 m_teletext_parser->m_found_subtitle_pages;
2682 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2683 eDVBServicePMTHandler::program program;
2684 if (h.getProgramInfo(program))
2685 eDebug("getting program info failed.");
2688 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2689 it != program.subtitleStreams.end(); ++it)
2691 switch(it->subtitling_type)
2693 case 0x01: // ebu teletext subtitles
2695 int page_number = it->teletext_page_number & 0xFF;
2696 int magazine_number = it->teletext_magazine_number & 7;
2697 int hash = magazine_number << 8 | page_number;
2698 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2700 ePyObject tuple = PyTuple_New(5);
2701 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2702 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2703 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2704 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2705 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2706 PyList_Append(l, tuple);
2708 added_ttx_pages.insert(hash);
2713 case 0x20 ... 0x23: // dvb subtitles
2715 ePyObject tuple = PyTuple_New(5);
2716 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2717 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2718 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2719 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2720 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2721 PyList_Insert(l, 0, tuple);
2729 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2730 it != subs.end(); ++it)
2732 int page_number = it->teletext_page_number & 0xFF;
2733 int magazine_number = it->teletext_magazine_number & 7;
2734 int hash = magazine_number << 8 | page_number;
2735 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2737 ePyObject tuple = PyTuple_New(5);
2738 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2739 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2740 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2741 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2742 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2743 PyList_Append(l, tuple);
2751 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2753 if (m_subtitle_widget)
2757 m_decoder->getPTS(0, pos);
2758 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2759 m_subtitle_pages.push_back(page);
2760 checkSubtitleTiming();
2764 void eDVBServicePlay::checkSubtitleTiming()
2766 eDebug("checkSubtitleTiming");
2767 if (!m_subtitle_widget)
2771 enum { TELETEXT, DVB } type;
2772 eDVBTeletextSubtitlePage page;
2773 eDVBSubtitlePage dvb_page;
2775 if (!m_subtitle_pages.empty())
2777 page = m_subtitle_pages.front();
2779 show_time = page.m_pts;
2781 else if (!m_dvb_subtitle_pages.empty())
2783 dvb_page = m_dvb_subtitle_pages.front();
2785 show_time = dvb_page.m_show_time;
2793 m_decoder->getPTS(0, pos);
2795 eDebug("%lld %lld", pos, show_time);
2796 int diff = show_time - pos;
2799 eDebug("[late (%d ms)]", -diff / 90);
2802 // if (diff > 900000)
2804 // eDebug("[invalid]");
2810 if (type == TELETEXT)
2812 eDebug("display teletext subtitle page %lld", show_time);
2813 m_subtitle_widget->setPage(page);
2814 m_subtitle_pages.pop_front();
2818 eDebug("display dvb subtitle Page %lld", show_time);
2819 m_subtitle_widget->setPage(dvb_page);
2820 m_dvb_subtitle_pages.pop_front();
2824 eDebug("start subtitle delay %d", diff / 90);
2825 m_subtitle_sync_timer->start(diff / 90, 1);
2831 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2833 if (m_subtitle_widget)
2837 m_decoder->getPTS(0, pos);
2838 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2839 m_dvb_subtitle_pages.push_back(p);
2840 checkSubtitleTiming();
2844 int eDVBServicePlay::getAC3Delay()
2847 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2849 return m_decoder->getAC3Delay();
2854 int eDVBServicePlay::getPCMDelay()
2857 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2859 return m_decoder->getPCMDelay();
2864 void eDVBServicePlay::setAC3Delay(int delay)
2867 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2869 m_decoder->setAC3Delay(delay);
2872 void eDVBServicePlay::setPCMDelay(int delay)
2875 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2877 m_decoder->setPCMDelay(delay);
2880 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2882 switch(event.type) {
2883 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2884 m_event((iPlayableService*)this, evVideoSizeChanged);
2886 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2887 m_event((iPlayableService*)this, evVideoFramerateChanged);
2889 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2890 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2897 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2903 PyObject *eDVBServicePlay::getStreamingData()
2905 eDVBServicePMTHandler::program program;
2906 if (m_service_handler.getProgramInfo(program))
2911 ePyObject r = program.createPythonObject();
2912 ePtr<iDVBDemux> demux;
2913 if (!m_service_handler.getDataDemux(demux))
2916 if (!demux->getCADemuxID(demux_id))
2917 PutToDict(r, "demux", demux_id);
2924 DEFINE_REF(eDVBServicePlay)
2926 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2930 case iServiceInformation::sTransponderData:
2931 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2935 return iStaticServiceInformation::getInfoObject(ref, w);
2938 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");