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);
339 PyObject *getInfoObject(const eServiceReference &r, int what);
342 DEFINE_REF(eStaticServiceDVBPVRInformation);
344 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
347 m_parser.parseFile(ref.path);
350 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
352 ASSERT(ref == m_ref);
353 if (m_parser.m_name.size())
354 name = m_parser.m_name;
358 size_t n = name.rfind('/');
359 if (n != std::string::npos)
360 name = name.substr(n + 1);
365 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
367 ASSERT(ref == m_ref);
372 stat(ref.path.c_str(), &s);
374 if (tstools.openFile(ref.path.c_str(), 1))
377 /* check if cached data is still valid */
378 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
379 return m_parser.m_length / 90000;
381 /* open again, this time with stream info */
382 if (tstools.openFile(ref.path.c_str()))
385 /* otherwise, re-calc length and update meta file */
387 if (tstools.calcLen(len))
390 m_parser.m_length = len;
391 m_parser.m_filesize = s.st_size;
392 m_parser.updateMeta(ref.path);
393 return m_parser.m_length / 90000;
396 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
400 case iServiceInformation::sDescription:
401 return iServiceInformation::resIsString;
402 case iServiceInformation::sServiceref:
403 return iServiceInformation::resIsString;
404 case iServiceInformation::sFileSize:
405 return m_parser.m_filesize;
406 case iServiceInformation::sTimeCreate:
407 if (m_parser.m_time_create)
408 return m_parser.m_time_create;
410 return iServiceInformation::resNA;
412 return iServiceInformation::resNA;
416 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
420 case iServiceInformation::sDescription:
421 return m_parser.m_description;
422 case iServiceInformation::sServiceref:
423 return m_parser.m_ref.toString();
424 case iServiceInformation::sTags:
425 return m_parser.m_tags;
431 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
435 case iServiceInformation::sFileSize:
436 return PyLong_FromLongLong(m_parser.m_filesize);
442 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
444 if (!ref.path.empty())
446 ePtr<eServiceEvent> event = new eServiceEvent;
447 std::string filename = ref.path;
448 filename.erase(filename.length()-2, 2);
450 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
460 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
462 DECLARE_REF(eDVBPVRServiceOfflineOperations);
463 eServiceReferenceDVB m_ref;
465 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
467 RESULT deleteFromDisk(int simulate);
468 RESULT getListOfFilenames(std::list<std::string> &);
471 DEFINE_REF(eDVBPVRServiceOfflineOperations);
473 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
477 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
483 std::list<std::string> res;
484 if (getListOfFilenames(res))
487 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
489 eDebug("FATAL !! can't get background file eraser");
491 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
493 eDebug("Removing %s...", i->c_str());
495 eraser->erase(i->c_str());
497 ::unlink(i->c_str());
504 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
507 res.push_back(m_ref.path);
509 // handling for old splitted recordings (enigma 1)
514 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
516 if (stat(buf, &s) < 0)
521 res.push_back(m_ref.path + ".meta");
522 res.push_back(m_ref.path + ".ap");
523 res.push_back(m_ref.path + ".sc");
524 res.push_back(m_ref.path + ".cuts");
525 std::string tmp = m_ref.path;
526 tmp.erase(m_ref.path.length()-3);
527 res.push_back(tmp + ".eit");
531 DEFINE_REF(eServiceFactoryDVB)
533 eServiceFactoryDVB::eServiceFactoryDVB()
535 ePtr<eServiceCenter> sc;
537 eServiceCenter::getPrivInstance(sc);
540 std::list<std::string> extensions;
541 extensions.push_back("ts");
542 extensions.push_back("trp");
543 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
546 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
547 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
550 eServiceFactoryDVB::~eServiceFactoryDVB()
552 ePtr<eServiceCenter> sc;
554 eServiceCenter::getPrivInstance(sc);
556 sc->removeServiceFactory(eServiceFactoryDVB::id);
559 DEFINE_REF(eDVBServiceList);
561 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
565 eDVBServiceList::~eDVBServiceList()
569 RESULT eDVBServiceList::startQuery()
571 ePtr<iDVBChannelList> db;
572 ePtr<eDVBResourceManager> res;
575 if ((err = eDVBResourceManager::getInstance(res)) != 0)
577 eDebug("no resource manager");
580 if ((err = res->getChannelList(db)) != 0)
582 eDebug("no channel list");
586 ePtr<eDVBChannelQuery> q;
588 if (!m_parent.path.empty())
590 eDVBChannelQuery::compile(q, m_parent.path);
593 eDebug("compile query failed");
598 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
600 eDebug("startQuery failed");
607 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
609 eServiceReferenceDVB ref;
614 while (!m_query->getNextResult(ref))
618 list.sort(iListableServiceCompare(this));
623 // The first argument of this function is a format string to specify the order and
624 // the content of the returned list
625 // useable format options are
626 // R = Service Reference (as swig object .. this is very slow)
627 // S = Service Reference (as python string object .. same as ref.toString())
628 // C = Service Reference (as python string object .. same as ref.toCompareString())
629 // N = Service Name (as python string object)
630 // n = Short Service Name (short name brakets used) (as python string object)
631 // when exactly one return value per service is selected in the format string,
632 // then each value is directly a list entry
633 // when more than one value is returned per service, then the list is a list of
635 // unknown format string chars are returned as python None values !
636 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
639 std::list<eServiceReference> tmplist;
642 if (!format || !(retcount=strlen(format)))
643 format = "R"; // just return service reference swig object ...
645 if (!getContent(tmplist, sorted))
647 int services=tmplist.size();
648 ePtr<iStaticServiceInformation> sptr;
649 eServiceCenterPtr service_center;
651 if (strchr(format, 'N') || strchr(format, 'n'))
652 eServiceCenter::getPrivInstance(service_center);
654 ret = PyList_New(services);
655 std::list<eServiceReference>::iterator it(tmplist.begin());
657 for (int cnt=0; cnt < services; ++cnt)
659 eServiceReference &ref=*it++;
660 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
661 for (int i=0; i < retcount; ++i)
666 case 'R': // service reference (swig)object
667 tmp = NEW_eServiceReference(ref);
669 case 'C': // service reference compare string
670 tmp = PyString_FromString(ref.toCompareString().c_str());
672 case 'S': // service reference string
673 tmp = PyString_FromString(ref.toString().c_str());
675 case 'N': // service name
678 service_center->info(ref, sptr);
682 sptr->getName(ref, name);
684 // filter short name brakets
686 while((pos = name.find("\xc2\x86")) != std::string::npos)
688 while((pos = name.find("\xc2\x87")) != std::string::npos)
692 tmp = PyString_FromString(name.c_str());
696 tmp = PyString_FromString("<n/a>");
698 case 'n': // short service name
701 service_center->info(ref, sptr);
705 sptr->getName(ref, name);
706 name = buildShortName(name);
708 tmp = PyString_FromString(name.c_str());
712 tmp = PyString_FromString("<n/a>");
725 PyTuple_SET_ITEM(tuple, i, tmp);
727 PyList_SET_ITEM(ret, cnt, tmp);
731 PyList_SET_ITEM(ret, cnt, tuple);
734 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
737 RESULT eDVBServiceList::getNext(eServiceReference &ref)
742 return m_query->getNextResult((eServiceReferenceDVB&)ref);
745 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
747 if (m_parent.flags & eServiceReference::canDescent) // bouquet
749 ePtr<iDVBChannelList> db;
750 ePtr<eDVBResourceManager> resm;
752 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
755 if (db->getBouquet(m_parent, m_bouquet) != 0)
766 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
770 return m_bouquet->addService(ref, before);
773 RESULT eDVBServiceList::removeService(eServiceReference &ref)
777 return m_bouquet->removeService(ref);
780 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
784 return m_bouquet->moveService(ref, pos);
787 RESULT eDVBServiceList::flushChanges()
791 return m_bouquet->flushChanges();
794 RESULT eDVBServiceList::setListName(const std::string &name)
798 return m_bouquet->setListName(name);
801 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
803 ePtr<eDVBService> service;
804 int r = lookupService(service, ref);
807 // check resources...
808 ptr = new eDVBServicePlay(ref, service);
812 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
814 if (ref.path.empty())
816 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
825 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
827 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
828 if (list->startQuery())
838 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
840 /* is a listable service? */
841 if (ref.flags & eServiceReference::canDescent) // bouquet
843 if ( !ref.name.empty() ) // satellites or providers list
844 ptr = m_StaticServiceDVBInfo;
845 else // a dvb bouquet
846 ptr = m_StaticServiceDVBBouquetInfo;
848 else if (!ref.path.empty()) /* do we have a PVR service? */
849 ptr = new eStaticServiceDVBPVRInformation(ref);
850 else // normal dvb service
852 ePtr<eDVBService> service;
853 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
854 ptr = m_StaticServiceDVBInfo;
856 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
862 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
864 if (ref.path.empty())
870 ptr = new eDVBPVRServiceOfflineOperations(ref);
875 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
877 if (!ref.path.empty()) // playback
879 eDVBMetaParser parser;
880 int ret=parser.parseFile(ref.path);
881 service = new eDVBService;
883 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
887 // TODO: handle the listing itself
888 // if (ref.... == -1) .. return "... bouquets ...";
889 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
891 ePtr<iDVBChannelList> db;
892 ePtr<eDVBResourceManager> res;
895 if ((err = eDVBResourceManager::getInstance(res)) != 0)
897 eDebug("no resource manager");
900 if ((err = res->getChannelList(db)) != 0)
902 eDebug("no channel list");
906 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
907 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
909 eDebug("getService failed!");
917 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
918 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
921 m_is_pvr = !m_reference.path.empty();
923 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
926 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
927 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
928 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
930 m_cuesheet_changed = 0;
931 m_cutlist_enabled = 1;
933 m_subtitle_widget = 0;
937 m_subtitle_sync_timer = eTimer::create(eApp);
939 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
942 eDVBServicePlay::~eDVBServicePlay()
947 int ret=meta.parseFile(m_reference.path);
951 meta.m_service_data="";
952 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
953 meta.m_service_data += tmp;
955 for (int x=0; x < eDVBService::cacheMax; ++x)
957 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
960 sprintf(tmp, ",c:%02d%04x", x, entry);
961 meta.m_service_data += tmp;
964 meta.updateMeta(m_reference.path);
967 delete m_subtitle_widget;
970 void eDVBServicePlay::gotNewEvent()
974 ePtr<eServiceEvent> m_event_now, m_event_next;
975 getEvent(m_event_now, 0);
976 getEvent(m_event_next, 1);
979 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
981 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
983 m_event((iPlayableService*)this, evUpdatedEventInfo);
986 void eDVBServicePlay::serviceEvent(int event)
988 m_tune_state = event;
992 case eDVBServicePMTHandler::eventTuned:
994 ePtr<iDVBDemux> m_demux;
995 if (!m_service_handler.getDataDemux(m_demux))
997 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
998 int sid = ref.getParentServiceID().get();
1000 sid = ref.getServiceID().get();
1001 if ( ref.getParentTransportStreamID().get() &&
1002 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1003 m_event_handler.startOther(m_demux, sid);
1005 m_event_handler.start(m_demux, sid);
1007 m_event((iPlayableService*)this, evTunedIn);
1010 case eDVBServicePMTHandler::eventNoResources:
1011 case eDVBServicePMTHandler::eventNoPAT:
1012 case eDVBServicePMTHandler::eventNoPATEntry:
1013 case eDVBServicePMTHandler::eventNoPMT:
1014 case eDVBServicePMTHandler::eventTuneFailed:
1015 case eDVBServicePMTHandler::eventMisconfiguration:
1017 eDebug("DVB service failed to tune - error %d", event);
1018 m_event((iPlayableService*)this, evTuneFailed);
1021 case eDVBServicePMTHandler::eventNewProgramInfo:
1023 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1024 if (m_timeshift_enabled)
1025 updateTimeshiftPids();
1026 if (!m_timeshift_active)
1028 if (m_first_program_info && m_is_pvr)
1030 m_first_program_info = 0;
1033 m_event((iPlayableService*)this, evUpdatedInfo);
1036 case eDVBServicePMTHandler::eventEOF:
1037 m_event((iPlayableService*)this, evEOF);
1039 case eDVBServicePMTHandler::eventSOF:
1040 m_event((iPlayableService*)this, evSOF);
1045 void eDVBServicePlay::serviceEventTimeshift(int event)
1049 case eDVBServicePMTHandler::eventNewProgramInfo:
1050 if (m_timeshift_active)
1053 case eDVBServicePMTHandler::eventSOF:
1054 m_event((iPlayableService*)this, evSOF);
1056 case eDVBServicePMTHandler::eventEOF:
1057 if ((!m_is_paused) && (m_skipmode >= 0))
1059 eDebug("timeshift EOF, so let's go live");
1066 RESULT eDVBServicePlay::start()
1069 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1070 two (one for decoding, one for data source), as we must be prepared
1071 to start recording from the data demux. */
1073 m_cue = new eCueSheet();
1075 m_event(this, evStart);
1077 m_first_program_info = 1;
1078 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1079 r = m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1081 /* inject EIT if there is a stored one */
1084 std::string filename = service.path;
1085 filename.erase(filename.length()-2, 2);
1087 ePtr<eServiceEvent> event = new eServiceEvent;
1088 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1090 ePtr<eServiceEvent> empty;
1091 m_event_handler.inject(event, 0);
1092 m_event_handler.inject(empty, 1);
1099 m_event(this, evStart);
1104 RESULT eDVBServicePlay::stop()
1106 /* add bookmark for last play position */
1109 pts_t play_position, length;
1110 if (!getPlayPosition(play_position))
1112 /* remove last position */
1113 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1115 if (i->what == 3) /* current play position */
1117 m_cue_entries.erase(i);
1118 i = m_cue_entries.begin();
1124 if (getLength(length))
1129 int perc = play_position * 100LL / length;
1131 /* only store last play position when between 1% and 99% */
1132 if ((1 < perc) && (perc < 99))
1133 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1135 m_cuesheet_changed = 1;
1139 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1141 m_service_handler_timeshift.free();
1142 m_service_handler.free();
1144 if (m_is_pvr && m_cuesheet_changed)
1147 /* save cuesheet only when main file is accessible. */
1148 if (!::stat(m_reference.path.c_str(), &s))
1151 m_event((iPlayableService*)this, evStopped);
1155 RESULT eDVBServicePlay::setTarget(int target)
1157 m_is_primary = !target;
1161 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1163 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1167 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1169 /* note: we check for timeshift to be enabled,
1170 not neccessary active. if you pause when timeshift
1171 is not active, you should activate it when unpausing */
1172 if ((!m_is_pvr) && (!m_timeshift_enabled))
1182 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1184 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1185 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1186 setFastForward_internal(0);
1188 return m_decoder->setSlowMotion(ratio);
1193 RESULT eDVBServicePlay::setFastForward(int ratio)
1195 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1197 return setFastForward_internal(ratio);
1200 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1202 int skipmode, ffratio;
1208 } else if (ratio > 0)
1216 } else // if (ratio < 0)
1222 if (m_skipmode != skipmode)
1224 eDebug("setting cue skipmode to %d", skipmode);
1226 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1229 m_skipmode = skipmode;
1235 ; /* return m_decoder->play(); is done in caller*/
1236 else if (ffratio != 1)
1237 return m_decoder->setFastForward(ffratio);
1239 return m_decoder->setTrickmode();
1243 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1245 if (m_is_pvr || m_timeshift_enabled)
1255 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1256 RESULT eDVBServicePlay::getLength(pts_t &len)
1258 ePtr<iDVBPVRChannel> pvr_channel;
1260 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1263 return pvr_channel->getLength(len);
1266 RESULT eDVBServicePlay::pause()
1268 eDebug("eDVBServicePlay::pause");
1269 setFastForward_internal(0);
1273 return m_decoder->pause();
1278 RESULT eDVBServicePlay::unpause()
1280 eDebug("eDVBServicePlay::unpause");
1281 setFastForward_internal(0);
1285 return m_decoder->play();
1290 RESULT eDVBServicePlay::seekTo(pts_t to)
1292 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1294 if (!m_decode_demux)
1297 ePtr<iDVBPVRChannel> pvr_channel;
1299 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1305 m_cue->seekTo(0, to);
1306 m_dvb_subtitle_pages.clear();
1307 m_subtitle_pages.clear();
1312 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1314 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1316 if (!m_decode_demux)
1319 ePtr<iDVBPVRChannel> pvr_channel;
1321 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1326 /* HACK until we have skip-AP api */
1327 if ((to > 0) && (to < 100))
1335 m_cue->seekTo(mode, to);
1336 m_dvb_subtitle_pages.clear();
1337 m_subtitle_pages.clear();
1341 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1343 ePtr<iDVBPVRChannel> pvr_channel;
1345 if (!m_decode_demux)
1348 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1353 /* if there is a decoder, use audio or video PTS */
1356 r = m_decoder->getPTS(0, pos);
1362 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1365 RESULT eDVBServicePlay::setTrickmode(int trick)
1367 /* currently unimplemented */
1371 RESULT eDVBServicePlay::isCurrentlySeekable()
1373 return m_is_pvr || m_timeshift_active;
1376 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1382 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1388 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1394 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1400 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1406 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1409 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1410 (m_timeshift_enabled || !m_is_pvr))
1412 if (!m_timeshift_enabled)
1414 /* query config path */
1416 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1417 eDebug("could not query ts path from config");
1421 /* we need enough diskspace */
1423 if (statfs(tspath.c_str(), &fs) < 0)
1425 eDebug("statfs failed!");
1429 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1431 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1441 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1452 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1458 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1464 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1470 RESULT eDVBServicePlay::getName(std::string &name)
1474 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1475 return i->getName(m_reference, name);
1477 else if (m_dvb_service)
1479 m_dvb_service->getName(m_reference, name);
1483 else if (!m_reference.name.empty())
1484 eStaticServiceDVBInformation().getName(m_reference, name);
1486 name = "DVB service";
1490 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1492 return m_event_handler.getEvent(evt, nownext);
1495 int eDVBServicePlay::getInfo(int w)
1497 eDVBServicePMTHandler::program program;
1500 return resIsPyObject;
1502 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1504 int no_program_info = 0;
1506 if (h.getProgramInfo(program))
1507 no_program_info = 1;
1513 return m_decoder->getVideoHeight();
1517 return m_decoder->getVideoWidth();
1521 return m_decoder->getVideoFrameRate();
1525 return m_decoder->getVideoProgressive();
1531 aspect = m_decoder->getVideoAspect();
1532 if (aspect == -1 && no_program_info)
1534 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1536 ePtr<eServiceEvent> evt;
1537 if (!m_event_handler.getEvent(evt, 0))
1539 ePtr<eComponentData> data;
1540 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1542 if ( data->getStreamContent() == 1 )
1544 switch(data->getComponentType())
1547 case 1: // 4:3 SD PAL
1549 case 3: // 16:9 SD PAL
1550 case 4: // > 16:9 PAL
1551 case 5: // 4:3 SD NTSC
1553 case 7: // 16:9 SD NTSC
1554 case 8: // > 16:9 NTSC
1557 case 9: // 4:3 HD PAL
1559 case 0xB: // 16:9 HD PAL
1560 case 0xC: // > 16:9 HD PAL
1561 case 0xD: // 4:3 HD NTSC
1563 case 0xF: // 16:9 HD NTSC
1564 case 0x10: // > 16:9 HD PAL
1565 return data->getComponentType();
1575 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1579 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1583 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1584 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1588 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1591 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1595 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1599 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1603 if (no_program_info) return -1; return program.pcrPid;
1604 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1605 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1606 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1607 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1608 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1609 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1610 case sProvider: if (!m_dvb_service) return -1; return -2;
1611 case sServiceref: return resIsString;
1612 case sDVBState: return m_tune_state;
1619 std::string eDVBServicePlay::getInfoString(int w)
1624 if (!m_dvb_service) return "";
1625 return m_dvb_service->m_provider_name;
1627 return m_reference.toString();
1631 return iServiceInformation::getInfoString(w);
1634 PyObject *eDVBServicePlay::getInfoObject(int w)
1639 return m_service_handler.getCaIds();
1640 case sTransponderData:
1641 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1645 return iServiceInformation::getInfoObject(w);
1648 int eDVBServicePlay::getNumberOfTracks()
1650 eDVBServicePMTHandler::program program;
1651 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1652 if (h.getProgramInfo(program))
1654 return program.audioStreams.size();
1657 int eDVBServicePlay::getCurrentTrack()
1659 eDVBServicePMTHandler::program program;
1660 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1661 if (h.getProgramInfo(program))
1664 int max = program.audioStreams.size();
1667 for (i = 0; i < max; ++i)
1668 if (program.audioStreams[i].pid == m_current_audio_pid)
1674 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1676 int ret = selectAudioStream(i);
1678 if (m_decoder->set())
1684 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1686 eDVBServicePMTHandler::program program;
1687 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1689 if (h.getProgramInfo(program))
1692 if (i >= program.audioStreams.size())
1695 info.m_pid = program.audioStreams[i].pid;
1697 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1698 info.m_description = "MPEG";
1699 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1700 info.m_description = "AC3";
1701 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1702 info.m_description = "AAC";
1703 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1704 info.m_description = "AAC-HE";
1705 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1706 info.m_description = "DTS";
1708 info.m_description = "???";
1710 if (program.audioStreams[i].component_tag != -1)
1712 ePtr<eServiceEvent> evt;
1713 if (!m_event_handler.getEvent(evt, 0))
1715 ePtr<eComponentData> data;
1716 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1717 info.m_language = data->getText();
1721 if (info.m_language.empty())
1722 info.m_language = program.audioStreams[i].language_code;
1727 int eDVBServicePlay::selectAudioStream(int i)
1729 eDVBServicePMTHandler::program program;
1730 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1732 if (h.getProgramInfo(program))
1735 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1743 stream = program.defaultAudioStream;
1745 int apid = -1, apidtype = -1;
1747 if (((unsigned int)stream) < program.audioStreams.size())
1749 apid = program.audioStreams[stream].pid;
1750 apidtype = program.audioStreams[stream].type;
1753 m_current_audio_pid = apid;
1755 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1757 eDebug("set audio pid failed");
1763 /* 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 */
1764 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1766 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1768 rdsPid = program.audioStreams[stream].rdsPid;
1769 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1772 ePtr<iDVBDemux> data_demux;
1773 if (!h.getDataDemux(data_demux))
1775 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1776 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1777 m_rds_decoder->start(rdsPid);
1782 /* store new pid as default only when:
1783 a.) we have an entry in the service db for the current service,
1784 b.) we are not playing back something,
1785 c.) we are not selecting the default entry. (we wouldn't change
1786 anything in the best case, or destroy the default setting in
1787 case the real default is not yet available.)
1789 if (m_dvb_service && ((i != -1)
1790 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1792 if (apidtype == eDVBAudio::aMPEG)
1794 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1795 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1797 else if (apidtype == eDVBAudio::aAC3)
1799 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1800 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1804 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1805 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1809 h.resetCachedProgram();
1814 int eDVBServicePlay::getCurrentChannel()
1816 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1819 RESULT eDVBServicePlay::selectChannel(int i)
1821 if (i < LEFT || i > RIGHT || i == STEREO)
1824 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1826 m_decoder->setAudioChannel(i);
1830 std::string eDVBServicePlay::getText(int x)
1836 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1838 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1843 void eDVBServicePlay::rdsDecoderEvent(int what)
1847 case eDVBRdsDecoder::RadioTextChanged:
1848 m_event((iPlayableService*)this, evUpdatedRadioText);
1850 case eDVBRdsDecoder::RtpTextChanged:
1851 m_event((iPlayableService*)this, evUpdatedRtpText);
1853 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1854 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1856 case eDVBRdsDecoder::RecvRassSlidePic:
1857 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1862 void eDVBServicePlay::showRassSlidePicture()
1868 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1869 if (rass_slide_pic.length())
1870 m_decoder->showSinglePic(rass_slide_pic.c_str());
1872 eDebug("empty filename for rass slide picture received!!");
1875 eDebug("no MPEG Decoder to show iframes avail");
1878 eDebug("showRassSlidePicture called.. but not decoder");
1881 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1887 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1888 if (rass_interactive_pic.length())
1889 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1891 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1894 eDebug("no MPEG Decoder to show iframes avail");
1897 eDebug("showRassInteractivePic called.. but not decoder");
1900 ePyObject eDVBServicePlay::getRassInteractiveMask()
1903 return m_rds_decoder->getRassPictureMask();
1907 int eDVBServiceBase::getFrontendInfo(int w)
1909 eUsePtr<iDVBChannel> channel;
1910 if(m_service_handler.getChannel(channel))
1912 ePtr<iDVBFrontend> fe;
1913 if(channel->getFrontend(fe))
1915 return fe->readFrontendData(w);
1918 PyObject *eDVBServiceBase::getFrontendData()
1920 ePyObject ret = PyDict_New();
1923 eUsePtr<iDVBChannel> channel;
1924 if(!m_service_handler.getChannel(channel))
1926 ePtr<iDVBFrontend> fe;
1927 if(!channel->getFrontend(fe))
1928 fe->getFrontendData(ret);
1936 PyObject *eDVBServiceBase::getFrontendStatus()
1938 ePyObject ret = PyDict_New();
1941 eUsePtr<iDVBChannel> channel;
1942 if(!m_service_handler.getChannel(channel))
1944 ePtr<iDVBFrontend> fe;
1945 if(!channel->getFrontend(fe))
1946 fe->getFrontendStatus(ret);
1954 PyObject *eDVBServiceBase::getTransponderData(bool original)
1956 ePyObject ret = PyDict_New();
1959 eUsePtr<iDVBChannel> channel;
1960 if(!m_service_handler.getChannel(channel))
1962 ePtr<iDVBFrontend> fe;
1963 if(!channel->getFrontend(fe))
1964 fe->getTransponderData(ret, original);
1972 PyObject *eDVBServiceBase::getAll(bool original)
1974 ePyObject ret = getTransponderData(original);
1977 eUsePtr<iDVBChannel> channel;
1978 if(!m_service_handler.getChannel(channel))
1980 ePtr<iDVBFrontend> fe;
1981 if(!channel->getFrontend(fe))
1983 fe->getFrontendData(ret);
1984 fe->getFrontendStatus(ret);
1991 int eDVBServicePlay::getNumberOfSubservices()
1993 ePtr<eServiceEvent> evt;
1994 if (!m_event_handler.getEvent(evt, 0))
1995 return evt->getNumOfLinkageServices();
1999 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2001 ePtr<eServiceEvent> evt;
2002 if (!m_event_handler.getEvent(evt, 0))
2004 if (!evt->getLinkageService(sub, m_reference, n))
2007 sub.type=eServiceReference::idInvalid;
2011 RESULT eDVBServicePlay::startTimeshift()
2013 ePtr<iDVBDemux> demux;
2015 eDebug("Start timeshift!");
2017 if (m_timeshift_enabled)
2020 /* start recording with the data demux. */
2021 if (m_service_handler.getDataDemux(demux))
2024 demux->createTSRecorder(m_record);
2029 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2030 eDebug("could not query ts path");
2033 tspath.append("/timeshift.XXXXXX");
2035 templ = new char[tspath.length() + 1];
2036 strcpy(templ, tspath.c_str());
2038 m_timeshift_fd = mkstemp(templ);
2039 m_timeshift_file = std::string(templ);
2041 eDebug("recording to %s", templ);
2045 if (m_timeshift_fd < 0)
2051 m_record->setTargetFD(m_timeshift_fd);
2053 m_timeshift_enabled = 1;
2055 updateTimeshiftPids();
2061 RESULT eDVBServicePlay::stopTimeshift()
2063 if (!m_timeshift_enabled)
2068 m_timeshift_enabled = 0;
2073 close(m_timeshift_fd);
2074 eDebug("remove timeshift file");
2075 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2080 int eDVBServicePlay::isTimeshiftActive()
2082 return m_timeshift_enabled && m_timeshift_active;
2085 RESULT eDVBServicePlay::activateTimeshift()
2087 if (!m_timeshift_enabled)
2090 if (!m_timeshift_active)
2092 switchToTimeshift();
2099 PyObject *eDVBServicePlay::getCutList()
2101 ePyObject list = PyList_New(0);
2103 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2105 ePyObject tuple = PyTuple_New(2);
2106 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2107 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2108 PyList_Append(list, tuple);
2115 void eDVBServicePlay::setCutList(ePyObject list)
2117 if (!PyList_Check(list))
2119 int size = PyList_Size(list);
2122 m_cue_entries.clear();
2124 for (i=0; i<size; ++i)
2126 ePyObject tuple = PyList_GET_ITEM(list, i);
2127 if (!PyTuple_Check(tuple))
2129 eDebug("non-tuple in cutlist");
2132 if (PyTuple_Size(tuple) != 2)
2134 eDebug("cutlist entries need to be a 2-tuple");
2137 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2138 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2140 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2143 pts_t pts = PyLong_AsLongLong(ppts);
2144 int type = PyInt_AsLong(ptype);
2145 m_cue_entries.insert(cueEntry(pts, type));
2146 eDebug("adding %08llx, %d", pts, type);
2148 m_cuesheet_changed = 1;
2150 cutlistToCuesheet();
2151 m_event((iPlayableService*)this, evCuesheetChanged);
2154 void eDVBServicePlay::setCutListEnable(int enable)
2156 m_cutlist_enabled = enable;
2157 cutlistToCuesheet();
2160 void eDVBServicePlay::updateTimeshiftPids()
2165 eDVBServicePMTHandler::program program;
2166 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2168 if (h.getProgramInfo(program))
2172 std::set<int> pids_to_record;
2173 pids_to_record.insert(0); // PAT
2174 if (program.pmtPid != -1)
2175 pids_to_record.insert(program.pmtPid); // PMT
2177 if (program.textPid != -1)
2178 pids_to_record.insert(program.textPid); // Videotext
2180 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2181 i(program.videoStreams.begin());
2182 i != program.videoStreams.end(); ++i)
2183 pids_to_record.insert(i->pid);
2185 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2186 i(program.audioStreams.begin());
2187 i != program.audioStreams.end(); ++i)
2188 pids_to_record.insert(i->pid);
2190 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2191 i(program.subtitleStreams.begin());
2192 i != program.subtitleStreams.end(); ++i)
2193 pids_to_record.insert(i->pid);
2195 std::set<int> new_pids, obsolete_pids;
2197 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2198 m_pids_active.begin(), m_pids_active.end(),
2199 std::inserter(new_pids, new_pids.begin()));
2201 std::set_difference(
2202 m_pids_active.begin(), m_pids_active.end(),
2203 pids_to_record.begin(), pids_to_record.end(),
2204 std::inserter(new_pids, new_pids.begin())
2207 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2208 m_record->addPID(*i);
2210 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2211 m_record->removePID(*i);
2215 void eDVBServicePlay::switchToLive()
2217 if (!m_timeshift_active)
2220 eDebug("SwitchToLive");
2225 m_teletext_parser = 0;
2227 m_subtitle_parser = 0;
2228 m_new_dvb_subtitle_page_connection = 0;
2229 m_new_subtitle_page_connection = 0;
2230 m_rds_decoder_event_connection = 0;
2231 m_video_event_connection = 0;
2232 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2234 /* free the timeshift service handler, we need the resources */
2235 m_service_handler_timeshift.free();
2236 m_timeshift_active = 0;
2237 m_timeshift_changed = 1;
2239 m_event((iPlayableService*)this, evSeekableStatusChanged);
2244 void eDVBServicePlay::switchToTimeshift()
2246 if (m_timeshift_active)
2251 m_teletext_parser = 0;
2253 m_subtitle_parser = 0;
2254 m_new_subtitle_page_connection = 0;
2255 m_new_dvb_subtitle_page_connection = 0;
2256 m_rds_decoder_event_connection = 0;
2257 m_video_event_connection = 0;
2259 m_timeshift_active = 1;
2260 m_timeshift_changed = 1;
2262 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2263 r.path = m_timeshift_file;
2265 m_cue = new eCueSheet();
2266 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2268 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2270 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2272 m_event((iPlayableService*)this, evSeekableStatusChanged);
2275 void eDVBServicePlay::updateDecoder()
2277 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2279 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2281 eDVBServicePMTHandler::program program;
2282 if (h.getProgramInfo(program))
2283 eDebug("getting program info failed.");
2286 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2287 if (!program.videoStreams.empty())
2289 eDebugNoNewLine(" (");
2290 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2291 i(program.videoStreams.begin());
2292 i != program.videoStreams.end(); ++i)
2299 if (i != program.videoStreams.begin())
2300 eDebugNoNewLine(", ");
2301 eDebugNoNewLine("%04x", i->pid);
2303 eDebugNoNewLine(")");
2305 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2306 if (!program.audioStreams.empty())
2308 eDebugNoNewLine(" (");
2309 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2310 i(program.audioStreams.begin());
2311 i != program.audioStreams.end(); ++i)
2313 if (i != program.audioStreams.begin())
2314 eDebugNoNewLine(", ");
2315 eDebugNoNewLine("%04x", i->pid);
2317 eDebugNoNewLine(")");
2319 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2320 pcrpid = program.pcrPid;
2321 eDebug(", and the text pid is %04x", program.textPid);
2322 tpid = program.textPid;
2327 h.getDecodeDemux(m_decode_demux);
2328 if (m_timeshift_changed)
2332 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2334 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2337 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2338 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2339 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2340 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2341 if (m_timeshift_changed)
2343 ePyObject subs = getCachedSubtitle();
2344 if (subs != Py_None)
2346 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2347 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2348 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2349 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2350 if (type == 0) // dvb
2351 m_subtitle_parser->start(pid, comp_page, anc_page);
2352 else if (type == 1) // ttx
2353 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2360 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2363 m_timeshift_changed = 0;
2369 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2370 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2371 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2375 eServiceReferenceDVB ref;
2376 m_service_handler.getServiceReference(ref);
2377 eServiceReferenceDVB parent = ref.getParentServiceReference();
2382 ePtr<eDVBResourceManager> res_mgr;
2383 if (!eDVBResourceManager::getInstance(res_mgr))
2385 ePtr<iDVBChannelList> db;
2386 if (!res_mgr->getChannelList(db))
2388 ePtr<eDVBService> origService;
2389 if (!db->getService(parent, origService))
2391 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2392 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2399 std::string config_delay;
2400 int config_delay_int = 0;
2401 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2402 config_delay_int = atoi(config_delay.c_str());
2403 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2405 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2406 config_delay_int = atoi(config_delay.c_str());
2408 config_delay_int = 0;
2409 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2411 m_decoder->setVideoPID(vpid, vpidtype);
2412 selectAudioStream();
2414 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2415 m_decoder->setSyncPCR(pcrpid);
2417 m_decoder->setSyncPCR(-1);
2421 m_decoder->setTextPID(tpid);
2422 m_teletext_parser->start(program.textPid);
2425 if (vpid > 0 && vpid < 0x2000)
2429 std::string radio_pic;
2430 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2431 m_decoder->setRadioPic(radio_pic);
2434 /* if (!m_is_primary)
2435 m_decoder->setTrickmode();
2436 else */ if (m_is_paused)
2441 m_decoder->setAudioChannel(achannel);
2443 /* don't worry about non-existing services, nor pvr services */
2446 /* (audio pid will be set in selectAudioTrack */
2447 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2448 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2449 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2450 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2453 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2456 void eDVBServicePlay::loadCuesheet()
2458 std::string filename = m_reference.path + ".cuts";
2460 m_cue_entries.clear();
2462 FILE *f = fopen(filename.c_str(), "rb");
2466 eDebug("loading cuts..");
2469 unsigned long long where;
2472 if (!fread(&where, sizeof(where), 1, f))
2474 if (!fread(&what, sizeof(what), 1, f))
2477 #if BYTE_ORDER == LITTLE_ENDIAN
2478 where = bswap_64(where);
2485 m_cue_entries.insert(cueEntry(where, what));
2488 eDebug("%d entries", m_cue_entries.size());
2490 eDebug("cutfile not found!");
2492 m_cuesheet_changed = 0;
2493 cutlistToCuesheet();
2494 m_event((iPlayableService*)this, evCuesheetChanged);
2497 void eDVBServicePlay::saveCuesheet()
2499 std::string filename = m_reference.path + ".cuts";
2501 FILE *f = fopen(filename.c_str(), "wb");
2505 unsigned long long where;
2508 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2510 #if BYTE_ORDER == BIG_ENDIAN
2513 where = bswap_64(i->where);
2515 what = htonl(i->what);
2516 fwrite(&where, sizeof(where), 1, f);
2517 fwrite(&what, sizeof(what), 1, f);
2523 m_cuesheet_changed = 0;
2526 void eDVBServicePlay::cutlistToCuesheet()
2530 eDebug("no cue sheet");
2535 if (!m_cutlist_enabled)
2537 m_cue->commitSpans();
2538 eDebug("cutlists were disabled");
2542 pts_t in = 0, out = 0, length = 0;
2546 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2548 int have_any_span = 0;
2552 if (i == m_cue_entries.end())
2558 if (i->what == 0) /* in */
2562 } else if (i->what == 1) /* out */
2564 else /* mark (2) or last play position (3) */
2583 m_cue->addSourceSpan(in, out);
2588 if (i == m_cue_entries.end())
2591 m_cue->commitSpans();
2594 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2596 if (m_subtitle_widget)
2597 disableSubtitles(parent);
2600 int tuplesize = PyTuple_Size(tuple);
2603 if (!PyTuple_Check(tuple))
2609 entry = PyTuple_GET_ITEM(tuple, 0);
2611 if (!PyInt_Check(entry))
2614 type = PyInt_AsLong(entry);
2616 if (type == 1) // teletext subtitles
2618 int page, magazine, pid;
2622 if (!m_teletext_parser)
2624 eDebug("enable teletext subtitles.. no parser !!!");
2628 entry = PyTuple_GET_ITEM(tuple, 1);
2629 if (!PyInt_Check(entry))
2631 pid = PyInt_AsLong(entry);
2633 entry = PyTuple_GET_ITEM(tuple, 2);
2634 if (!PyInt_Check(entry))
2636 page = PyInt_AsLong(entry);
2638 entry = PyTuple_GET_ITEM(tuple, 3);
2639 if (!PyInt_Check(entry))
2641 magazine = PyInt_AsLong(entry);
2643 m_subtitle_widget = new eSubtitleWidget(parent);
2644 m_subtitle_widget->resize(parent->size()); /* full size */
2645 m_teletext_parser->setPageAndMagazine(page, magazine);
2647 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2651 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2652 if (!m_subtitle_parser)
2654 eDebug("enable dvb subtitles.. no parser !!!");
2660 entry = PyTuple_GET_ITEM(tuple, 1);
2661 if (!PyInt_Check(entry))
2663 pid = PyInt_AsLong(entry);
2665 entry = PyTuple_GET_ITEM(tuple, 2);
2666 if (!PyInt_Check(entry))
2668 composition_page_id = PyInt_AsLong(entry);
2670 entry = PyTuple_GET_ITEM(tuple, 3);
2671 if (!PyInt_Check(entry))
2673 ancillary_page_id = PyInt_AsLong(entry);
2675 m_subtitle_widget = new eSubtitleWidget(parent);
2676 m_subtitle_widget->resize(parent->size()); /* full size */
2677 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2679 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2685 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2686 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2687 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2691 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2693 delete m_subtitle_widget;
2694 m_subtitle_widget = 0;
2695 if (m_subtitle_parser)
2697 m_subtitle_parser->stop();
2698 m_dvb_subtitle_pages.clear();
2700 if (m_teletext_parser)
2702 m_teletext_parser->setPageAndMagazine(-1, -1);
2703 m_subtitle_pages.clear();
2706 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2710 PyObject *eDVBServicePlay::getCachedSubtitle()
2714 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2717 unsigned int data = (unsigned int)tmp;
2718 int pid = (data&0xFFFF0000)>>16;
2719 ePyObject tuple = PyTuple_New(4);
2720 eDVBServicePMTHandler::program program;
2721 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2722 if (!h.getProgramInfo(program))
2724 if (program.textPid==pid) // teletext
2725 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2727 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2728 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2729 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2730 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2738 PyObject *eDVBServicePlay::getSubtitleList()
2740 if (!m_teletext_parser)
2743 ePyObject l = PyList_New(0);
2744 std::set<int> added_ttx_pages;
2746 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2747 m_teletext_parser->m_found_subtitle_pages;
2749 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2750 eDVBServicePMTHandler::program program;
2751 if (h.getProgramInfo(program))
2752 eDebug("getting program info failed.");
2755 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2756 it != program.subtitleStreams.end(); ++it)
2758 switch(it->subtitling_type)
2760 case 0x01: // ebu teletext subtitles
2762 int page_number = it->teletext_page_number & 0xFF;
2763 int magazine_number = it->teletext_magazine_number & 7;
2764 int hash = magazine_number << 8 | page_number;
2765 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2767 ePyObject tuple = PyTuple_New(5);
2768 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2769 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2770 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2771 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2772 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2773 PyList_Append(l, tuple);
2775 added_ttx_pages.insert(hash);
2780 case 0x20 ... 0x23: // dvb subtitles
2782 ePyObject tuple = PyTuple_New(5);
2783 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2784 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2785 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2786 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2787 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2788 PyList_Insert(l, 0, tuple);
2796 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2797 it != subs.end(); ++it)
2799 int page_number = it->teletext_page_number & 0xFF;
2800 int magazine_number = it->teletext_magazine_number & 7;
2801 int hash = magazine_number << 8 | page_number;
2802 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2804 ePyObject tuple = PyTuple_New(5);
2805 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2806 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2807 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2808 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2809 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2810 PyList_Append(l, tuple);
2818 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2820 if (m_subtitle_widget)
2824 m_decoder->getPTS(0, pos);
2825 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2826 m_subtitle_pages.push_back(page);
2827 checkSubtitleTiming();
2831 void eDVBServicePlay::checkSubtitleTiming()
2833 eDebug("checkSubtitleTiming");
2834 if (!m_subtitle_widget)
2838 enum { TELETEXT, DVB } type;
2839 eDVBTeletextSubtitlePage page;
2840 eDVBSubtitlePage dvb_page;
2842 if (!m_subtitle_pages.empty())
2844 page = m_subtitle_pages.front();
2846 show_time = page.m_pts;
2848 else if (!m_dvb_subtitle_pages.empty())
2850 dvb_page = m_dvb_subtitle_pages.front();
2852 show_time = dvb_page.m_show_time;
2860 m_decoder->getPTS(0, pos);
2862 eDebug("%lld %lld", pos, show_time);
2863 int diff = show_time - pos;
2864 if (type == TELETEXT && !page.m_have_pts)
2866 eDebug("ttx subtitle page without pts... immediate show");
2871 eDebug("[late (%d ms)]", -diff / 90);
2874 if (abs(diff) > 1800000)
2876 eDebug("[invalid]... immediate show!");
2881 if (type == TELETEXT)
2883 eDebug("display teletext subtitle page %lld", show_time);
2884 m_subtitle_widget->setPage(page);
2885 m_subtitle_pages.pop_front();
2889 eDebug("display dvb subtitle Page %lld", show_time);
2890 m_subtitle_widget->setPage(dvb_page);
2891 m_dvb_subtitle_pages.pop_front();
2895 eDebug("start subtitle delay %d", diff / 90);
2896 m_subtitle_sync_timer->start(diff / 90, 1);
2902 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2904 if (m_subtitle_widget)
2908 m_decoder->getPTS(0, pos);
2909 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2910 m_dvb_subtitle_pages.push_back(p);
2911 checkSubtitleTiming();
2915 int eDVBServicePlay::getAC3Delay()
2918 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2920 return m_decoder->getAC3Delay();
2925 int eDVBServicePlay::getPCMDelay()
2928 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2930 return m_decoder->getPCMDelay();
2935 void eDVBServicePlay::setAC3Delay(int delay)
2938 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2940 m_decoder->setAC3Delay(delay);
2943 void eDVBServicePlay::setPCMDelay(int delay)
2946 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2948 m_decoder->setPCMDelay(delay);
2951 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2953 switch(event.type) {
2954 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2955 m_event((iPlayableService*)this, evVideoSizeChanged);
2957 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2958 m_event((iPlayableService*)this, evVideoFramerateChanged);
2960 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2961 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2968 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2974 PyObject *eDVBServicePlay::getStreamingData()
2976 eDVBServicePMTHandler::program program;
2977 if (m_service_handler.getProgramInfo(program))
2982 ePyObject r = program.createPythonObject();
2983 ePtr<iDVBDemux> demux;
2984 if (!m_service_handler.getDataDemux(demux))
2987 if (!demux->getCADemuxID(demux_id))
2988 PutToDict(r, "demux", demux_id);
2995 DEFINE_REF(eDVBServicePlay)
2997 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3001 case iServiceInformation::sTransponderData:
3002 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3006 return iStaticServiceInformation::getInfoObject(ref, w);
3009 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");