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::sFileSize:
404 return m_parser.m_filesize;
405 case iServiceInformation::sTimeCreate:
406 if (m_parser.m_time_create)
407 return m_parser.m_time_create;
409 return iServiceInformation::resNA;
411 return iServiceInformation::resNA;
415 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
419 case iServiceInformation::sDescription:
420 return m_parser.m_description;
421 case iServiceInformation::sServiceref:
422 return m_parser.m_ref.toString();
423 case iServiceInformation::sTags:
424 return m_parser.m_tags;
430 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
432 if (!ref.path.empty())
434 ePtr<eServiceEvent> event = new eServiceEvent;
435 std::string filename = ref.path;
436 filename.erase(filename.length()-2, 2);
438 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
448 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
450 DECLARE_REF(eDVBPVRServiceOfflineOperations);
451 eServiceReferenceDVB m_ref;
453 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
455 RESULT deleteFromDisk(int simulate);
456 RESULT getListOfFilenames(std::list<std::string> &);
459 DEFINE_REF(eDVBPVRServiceOfflineOperations);
461 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
465 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
471 std::list<std::string> res;
472 if (getListOfFilenames(res))
475 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
477 eDebug("FATAL !! can't get background file eraser");
479 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
481 eDebug("Removing %s...", i->c_str());
483 eraser->erase(i->c_str());
485 ::unlink(i->c_str());
492 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
495 res.push_back(m_ref.path);
497 // handling for old splitted recordings (enigma 1)
502 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
504 if (stat(buf, &s) < 0)
509 res.push_back(m_ref.path + ".meta");
510 res.push_back(m_ref.path + ".ap");
511 res.push_back(m_ref.path + ".sc");
512 res.push_back(m_ref.path + ".cuts");
513 std::string tmp = m_ref.path;
514 tmp.erase(m_ref.path.length()-3);
515 res.push_back(tmp + ".eit");
519 DEFINE_REF(eServiceFactoryDVB)
521 eServiceFactoryDVB::eServiceFactoryDVB()
523 ePtr<eServiceCenter> sc;
525 eServiceCenter::getPrivInstance(sc);
528 std::list<std::string> extensions;
529 extensions.push_back("ts");
530 extensions.push_back("trp");
531 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
534 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
535 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
538 eServiceFactoryDVB::~eServiceFactoryDVB()
540 ePtr<eServiceCenter> sc;
542 eServiceCenter::getPrivInstance(sc);
544 sc->removeServiceFactory(eServiceFactoryDVB::id);
547 DEFINE_REF(eDVBServiceList);
549 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
553 eDVBServiceList::~eDVBServiceList()
557 RESULT eDVBServiceList::startQuery()
559 ePtr<iDVBChannelList> db;
560 ePtr<eDVBResourceManager> res;
563 if ((err = eDVBResourceManager::getInstance(res)) != 0)
565 eDebug("no resource manager");
568 if ((err = res->getChannelList(db)) != 0)
570 eDebug("no channel list");
574 ePtr<eDVBChannelQuery> q;
576 if (!m_parent.path.empty())
578 eDVBChannelQuery::compile(q, m_parent.path);
581 eDebug("compile query failed");
586 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
588 eDebug("startQuery failed");
595 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
597 eServiceReferenceDVB ref;
602 while (!m_query->getNextResult(ref))
606 list.sort(iListableServiceCompare(this));
611 // The first argument of this function is a format string to specify the order and
612 // the content of the returned list
613 // useable format options are
614 // R = Service Reference (as swig object .. this is very slow)
615 // S = Service Reference (as python string object .. same as ref.toString())
616 // C = Service Reference (as python string object .. same as ref.toCompareString())
617 // N = Service Name (as python string object)
618 // n = Short Service Name (short name brakets used) (as python string object)
619 // when exactly one return value per service is selected in the format string,
620 // then each value is directly a list entry
621 // when more than one value is returned per service, then the list is a list of
623 // unknown format string chars are returned as python None values !
624 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
627 std::list<eServiceReference> tmplist;
630 if (!format || !(retcount=strlen(format)))
631 format = "R"; // just return service reference swig object ...
633 if (!getContent(tmplist, sorted))
635 int services=tmplist.size();
636 ePtr<iStaticServiceInformation> sptr;
637 eServiceCenterPtr service_center;
639 if (strchr(format, 'N') || strchr(format, 'n'))
640 eServiceCenter::getPrivInstance(service_center);
642 ret = PyList_New(services);
643 std::list<eServiceReference>::iterator it(tmplist.begin());
645 for (int cnt=0; cnt < services; ++cnt)
647 eServiceReference &ref=*it++;
648 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
649 for (int i=0; i < retcount; ++i)
654 case 'R': // service reference (swig)object
655 tmp = NEW_eServiceReference(ref);
657 case 'C': // service reference compare string
658 tmp = PyString_FromString(ref.toCompareString().c_str());
660 case 'S': // service reference string
661 tmp = PyString_FromString(ref.toString().c_str());
663 case 'N': // service name
666 service_center->info(ref, sptr);
670 sptr->getName(ref, name);
672 // filter short name brakets
674 while((pos = name.find("\xc2\x86")) != std::string::npos)
676 while((pos = name.find("\xc2\x87")) != std::string::npos)
680 tmp = PyString_FromString(name.c_str());
684 tmp = PyString_FromString("<n/a>");
686 case 'n': // short service name
689 service_center->info(ref, sptr);
693 sptr->getName(ref, name);
694 name = buildShortName(name);
696 tmp = PyString_FromString(name.c_str());
700 tmp = PyString_FromString("<n/a>");
713 PyTuple_SET_ITEM(tuple, i, tmp);
715 PyList_SET_ITEM(ret, cnt, tmp);
719 PyList_SET_ITEM(ret, cnt, tuple);
722 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
725 RESULT eDVBServiceList::getNext(eServiceReference &ref)
730 return m_query->getNextResult((eServiceReferenceDVB&)ref);
733 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
735 if (m_parent.flags & eServiceReference::canDescent) // bouquet
737 ePtr<iDVBChannelList> db;
738 ePtr<eDVBResourceManager> resm;
740 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
743 if (db->getBouquet(m_parent, m_bouquet) != 0)
754 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
758 return m_bouquet->addService(ref, before);
761 RESULT eDVBServiceList::removeService(eServiceReference &ref)
765 return m_bouquet->removeService(ref);
768 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
772 return m_bouquet->moveService(ref, pos);
775 RESULT eDVBServiceList::flushChanges()
779 return m_bouquet->flushChanges();
782 RESULT eDVBServiceList::setListName(const std::string &name)
786 return m_bouquet->setListName(name);
789 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
791 ePtr<eDVBService> service;
792 int r = lookupService(service, ref);
795 // check resources...
796 ptr = new eDVBServicePlay(ref, service);
800 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
802 if (ref.path.empty())
804 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
813 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
815 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
816 if (list->startQuery())
826 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
828 /* is a listable service? */
829 if (ref.flags & eServiceReference::canDescent) // bouquet
831 if ( !ref.name.empty() ) // satellites or providers list
832 ptr = m_StaticServiceDVBInfo;
833 else // a dvb bouquet
834 ptr = m_StaticServiceDVBBouquetInfo;
836 else if (!ref.path.empty()) /* do we have a PVR service? */
837 ptr = new eStaticServiceDVBPVRInformation(ref);
838 else // normal dvb service
840 ePtr<eDVBService> service;
841 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
842 ptr = m_StaticServiceDVBInfo;
844 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
850 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
852 if (ref.path.empty())
858 ptr = new eDVBPVRServiceOfflineOperations(ref);
863 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
865 if (!ref.path.empty()) // playback
867 eDVBMetaParser parser;
868 int ret=parser.parseFile(ref.path);
869 service = new eDVBService;
871 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
875 // TODO: handle the listing itself
876 // if (ref.... == -1) .. return "... bouquets ...";
877 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
879 ePtr<iDVBChannelList> db;
880 ePtr<eDVBResourceManager> res;
883 if ((err = eDVBResourceManager::getInstance(res)) != 0)
885 eDebug("no resource manager");
888 if ((err = res->getChannelList(db)) != 0)
890 eDebug("no channel list");
894 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
895 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
897 eDebug("getService failed!");
905 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
906 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
909 m_is_pvr = !m_reference.path.empty();
911 m_timeshift_enabled = m_timeshift_active = 0;
914 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
915 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
916 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
918 m_cuesheet_changed = 0;
919 m_cutlist_enabled = 1;
921 m_subtitle_widget = 0;
925 m_subtitle_sync_timer = eTimer::create(eApp);
927 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
930 eDVBServicePlay::~eDVBServicePlay()
935 int ret=meta.parseFile(m_reference.path);
939 meta.m_service_data="";
940 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
941 meta.m_service_data += tmp;
943 for (int x=0; x < eDVBService::cacheMax; ++x)
945 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
948 sprintf(tmp, ",c:%02d%04x", x, entry);
949 meta.m_service_data += tmp;
952 meta.updateMeta(m_reference.path);
955 delete m_subtitle_widget;
958 void eDVBServicePlay::gotNewEvent()
962 ePtr<eServiceEvent> m_event_now, m_event_next;
963 getEvent(m_event_now, 0);
964 getEvent(m_event_next, 1);
967 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
969 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
971 m_event((iPlayableService*)this, evUpdatedEventInfo);
974 void eDVBServicePlay::serviceEvent(int event)
976 m_tune_state = event;
980 case eDVBServicePMTHandler::eventTuned:
982 ePtr<iDVBDemux> m_demux;
983 if (!m_service_handler.getDataDemux(m_demux))
985 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
986 int sid = ref.getParentServiceID().get();
988 sid = ref.getServiceID().get();
989 if ( ref.getParentTransportStreamID().get() &&
990 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
991 m_event_handler.startOther(m_demux, sid);
993 m_event_handler.start(m_demux, sid);
995 m_event((iPlayableService*)this, evTunedIn);
998 case eDVBServicePMTHandler::eventNoResources:
999 case eDVBServicePMTHandler::eventNoPAT:
1000 case eDVBServicePMTHandler::eventNoPATEntry:
1001 case eDVBServicePMTHandler::eventNoPMT:
1002 case eDVBServicePMTHandler::eventTuneFailed:
1003 case eDVBServicePMTHandler::eventMisconfiguration:
1005 eDebug("DVB service failed to tune - error %d", event);
1006 m_event((iPlayableService*)this, evTuneFailed);
1009 case eDVBServicePMTHandler::eventNewProgramInfo:
1011 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1012 if (m_timeshift_enabled)
1013 updateTimeshiftPids();
1014 if (!m_timeshift_active)
1016 if (m_first_program_info && m_is_pvr)
1018 m_first_program_info = 0;
1021 m_event((iPlayableService*)this, evUpdatedInfo);
1024 case eDVBServicePMTHandler::eventEOF:
1025 m_event((iPlayableService*)this, evEOF);
1027 case eDVBServicePMTHandler::eventSOF:
1028 m_event((iPlayableService*)this, evSOF);
1033 void eDVBServicePlay::serviceEventTimeshift(int event)
1037 case eDVBServicePMTHandler::eventNewProgramInfo:
1038 if (m_timeshift_active)
1041 case eDVBServicePMTHandler::eventSOF:
1042 m_event((iPlayableService*)this, evSOF);
1044 case eDVBServicePMTHandler::eventEOF:
1045 if ((!m_is_paused) && (m_skipmode >= 0))
1047 eDebug("timeshift EOF, so let's go live");
1054 RESULT eDVBServicePlay::start()
1057 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1058 two (one for decoding, one for data source), as we must be prepared
1059 to start recording from the data demux. */
1061 m_cue = new eCueSheet();
1063 m_event(this, evStart);
1065 m_first_program_info = 1;
1066 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1067 r = m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1069 /* inject EIT if there is a stored one */
1072 std::string filename = service.path;
1073 filename.erase(filename.length()-2, 2);
1075 ePtr<eServiceEvent> event = new eServiceEvent;
1076 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1078 ePtr<eServiceEvent> empty;
1079 m_event_handler.inject(event, 0);
1080 m_event_handler.inject(empty, 1);
1087 m_event(this, evStart);
1092 RESULT eDVBServicePlay::stop()
1094 /* add bookmark for last play position */
1097 pts_t play_position, length;
1098 if (!getPlayPosition(play_position))
1100 /* remove last position */
1101 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1103 if (i->what == 3) /* current play position */
1105 m_cue_entries.erase(i);
1106 i = m_cue_entries.begin();
1112 if (getLength(length))
1117 int perc = play_position * 100LL / length;
1119 /* only store last play position when between 1% and 99% */
1120 if ((1 < perc) && (perc < 99))
1121 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1123 m_cuesheet_changed = 1;
1127 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1129 m_service_handler_timeshift.free();
1130 m_service_handler.free();
1132 if (m_is_pvr && m_cuesheet_changed)
1135 /* save cuesheet only when main file is accessible. */
1136 if (!::stat(m_reference.path.c_str(), &s))
1139 m_event((iPlayableService*)this, evStopped);
1143 RESULT eDVBServicePlay::setTarget(int target)
1145 m_is_primary = !target;
1149 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1151 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1155 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1157 /* note: we check for timeshift to be enabled,
1158 not neccessary active. if you pause when timeshift
1159 is not active, you should activate it when unpausing */
1160 if ((!m_is_pvr) && (!m_timeshift_enabled))
1170 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1172 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1173 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1174 setFastForward_internal(0);
1176 return m_decoder->setSlowMotion(ratio);
1181 RESULT eDVBServicePlay::setFastForward(int ratio)
1183 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1185 return setFastForward_internal(ratio);
1188 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1190 int skipmode, ffratio;
1196 } else if (ratio > 0)
1204 } else // if (ratio < 0)
1210 if (m_skipmode != skipmode)
1212 eDebug("setting cue skipmode to %d", skipmode);
1214 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1217 m_skipmode = skipmode;
1223 ; /* return m_decoder->play(); is done in caller*/
1224 else if (ffratio != 1)
1225 return m_decoder->setFastForward(ffratio);
1227 return m_decoder->setTrickmode();
1231 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1233 if (m_is_pvr || m_timeshift_enabled)
1243 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1244 RESULT eDVBServicePlay::getLength(pts_t &len)
1246 ePtr<iDVBPVRChannel> pvr_channel;
1248 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1251 return pvr_channel->getLength(len);
1254 RESULT eDVBServicePlay::pause()
1256 eDebug("eDVBServicePlay::pause");
1257 setFastForward_internal(0);
1261 return m_decoder->pause();
1266 RESULT eDVBServicePlay::unpause()
1268 eDebug("eDVBServicePlay::unpause");
1269 setFastForward_internal(0);
1273 return m_decoder->play();
1278 RESULT eDVBServicePlay::seekTo(pts_t to)
1280 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1282 if (!m_decode_demux)
1285 ePtr<iDVBPVRChannel> pvr_channel;
1287 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1293 m_cue->seekTo(0, to);
1294 m_dvb_subtitle_pages.clear();
1295 m_subtitle_pages.clear();
1300 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1302 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1304 if (!m_decode_demux)
1307 ePtr<iDVBPVRChannel> pvr_channel;
1309 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1314 /* HACK until we have skip-AP api */
1315 if ((to > 0) && (to < 100))
1323 m_cue->seekTo(mode, to);
1324 m_dvb_subtitle_pages.clear();
1325 m_subtitle_pages.clear();
1329 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1331 ePtr<iDVBPVRChannel> pvr_channel;
1333 if (!m_decode_demux)
1336 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1341 /* if there is a decoder, use audio or video PTS */
1344 r = m_decoder->getPTS(0, pos);
1350 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1353 RESULT eDVBServicePlay::setTrickmode(int trick)
1355 /* currently unimplemented */
1359 RESULT eDVBServicePlay::isCurrentlySeekable()
1361 return m_is_pvr || m_timeshift_active;
1364 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1370 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1376 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1382 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1388 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1394 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1397 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1398 (m_timeshift_enabled || !m_is_pvr))
1400 if (!m_timeshift_enabled)
1402 /* query config path */
1404 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1405 eDebug("could not query ts path from config");
1409 /* we need enough diskspace */
1411 if (statfs(tspath.c_str(), &fs) < 0)
1413 eDebug("statfs failed!");
1417 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1419 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1429 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1440 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1446 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1452 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1458 RESULT eDVBServicePlay::getName(std::string &name)
1462 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1463 return i->getName(m_reference, name);
1465 else if (m_dvb_service)
1467 m_dvb_service->getName(m_reference, name);
1471 else if (!m_reference.name.empty())
1472 eStaticServiceDVBInformation().getName(m_reference, name);
1474 name = "DVB service";
1478 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1480 return m_event_handler.getEvent(evt, nownext);
1483 int eDVBServicePlay::getInfo(int w)
1485 eDVBServicePMTHandler::program program;
1488 return resIsPyObject;
1490 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1492 int no_program_info = 0;
1494 if (h.getProgramInfo(program))
1495 no_program_info = 1;
1501 return m_decoder->getVideoHeight();
1505 return m_decoder->getVideoWidth();
1509 return m_decoder->getVideoFrameRate();
1513 return m_decoder->getVideoProgressive();
1519 aspect = m_decoder->getVideoAspect();
1520 if (no_program_info)
1522 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1524 ePtr<eServiceEvent> evt;
1525 if (!m_event_handler.getEvent(evt, 0))
1527 ePtr<eComponentData> data;
1528 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1530 if ( data->getStreamContent() == 1 )
1532 switch(data->getComponentType())
1535 case 1: // 4:3 SD PAL
1537 case 3: // 16:9 SD PAL
1538 case 4: // > 16:9 PAL
1539 case 5: // 4:3 SD NTSC
1541 case 7: // 16:9 SD NTSC
1542 case 8: // > 16:9 NTSC
1545 case 9: // 4:3 HD PAL
1547 case 0xB: // 16:9 HD PAL
1548 case 0xC: // > 16:9 HD PAL
1549 case 0xD: // 4:3 HD NTSC
1551 case 0xF: // 16:9 HD NTSC
1552 case 0x10: // > 16:9 HD PAL
1553 return data->getComponentType();
1563 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1567 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1571 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1572 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1576 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1579 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1583 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1587 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1591 if (no_program_info) return -1; return program.pcrPid;
1592 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1593 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1594 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1595 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1596 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1597 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1598 case sProvider: if (!m_dvb_service) return -1; return -2;
1599 case sServiceref: return resIsString;
1600 case sDVBState: return m_tune_state;
1607 std::string eDVBServicePlay::getInfoString(int w)
1612 if (!m_dvb_service) return "";
1613 return m_dvb_service->m_provider_name;
1615 return m_reference.toString();
1619 return iServiceInformation::getInfoString(w);
1622 PyObject *eDVBServicePlay::getInfoObject(int w)
1627 return m_service_handler.getCaIds();
1628 case sTransponderData:
1629 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1633 return iServiceInformation::getInfoObject(w);
1636 int eDVBServicePlay::getNumberOfTracks()
1638 eDVBServicePMTHandler::program program;
1639 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1640 if (h.getProgramInfo(program))
1642 return program.audioStreams.size();
1645 int eDVBServicePlay::getCurrentTrack()
1647 eDVBServicePMTHandler::program program;
1648 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1649 if (h.getProgramInfo(program))
1652 int max = program.audioStreams.size();
1655 for (i = 0; i < max; ++i)
1656 if (program.audioStreams[i].pid == m_current_audio_pid)
1662 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1664 int ret = selectAudioStream(i);
1666 if (m_decoder->set())
1672 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1674 eDVBServicePMTHandler::program program;
1675 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1677 if (h.getProgramInfo(program))
1680 if (i >= program.audioStreams.size())
1683 info.m_pid = program.audioStreams[i].pid;
1685 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1686 info.m_description = "MPEG";
1687 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1688 info.m_description = "AC3";
1689 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1690 info.m_description = "AAC";
1691 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1692 info.m_description = "AAC-HE";
1693 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1694 info.m_description = "DTS";
1696 info.m_description = "???";
1698 if (program.audioStreams[i].component_tag != -1)
1700 ePtr<eServiceEvent> evt;
1701 if (!m_event_handler.getEvent(evt, 0))
1703 ePtr<eComponentData> data;
1704 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1705 info.m_language = data->getText();
1709 if (info.m_language.empty())
1710 info.m_language = program.audioStreams[i].language_code;
1715 int eDVBServicePlay::selectAudioStream(int i)
1717 eDVBServicePMTHandler::program program;
1718 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1720 if (h.getProgramInfo(program))
1723 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1731 stream = program.defaultAudioStream;
1733 int apid = -1, apidtype = -1;
1735 if (((unsigned int)stream) < program.audioStreams.size())
1737 apid = program.audioStreams[stream].pid;
1738 apidtype = program.audioStreams[stream].type;
1741 m_current_audio_pid = apid;
1743 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1745 eDebug("set audio pid failed");
1749 /* 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 */
1750 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1753 ePtr<iDVBDemux> data_demux;
1754 if (!h.getDataDemux(data_demux))
1756 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1757 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1761 /* if we decided that we need one, update the pid */
1763 m_rds_decoder->start(apid);
1765 /* store new pid as default only when:
1766 a.) we have an entry in the service db for the current service,
1767 b.) we are not playing back something,
1768 c.) we are not selecting the default entry. (we wouldn't change
1769 anything in the best case, or destroy the default setting in
1770 case the real default is not yet available.)
1772 if (m_dvb_service && ((i != -1)
1773 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1775 if (apidtype == eDVBAudio::aMPEG)
1777 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1778 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1780 else if (apidtype == eDVBAudio::aAC3)
1782 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1783 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1787 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1788 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1792 h.resetCachedProgram();
1797 int eDVBServicePlay::getCurrentChannel()
1799 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1802 RESULT eDVBServicePlay::selectChannel(int i)
1804 if (i < LEFT || i > RIGHT || i == STEREO)
1807 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1809 m_decoder->setAudioChannel(i);
1813 std::string eDVBServicePlay::getText(int x)
1819 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1821 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1826 void eDVBServicePlay::rdsDecoderEvent(int what)
1830 case eDVBRdsDecoder::RadioTextChanged:
1831 m_event((iPlayableService*)this, evUpdatedRadioText);
1833 case eDVBRdsDecoder::RtpTextChanged:
1834 m_event((iPlayableService*)this, evUpdatedRtpText);
1836 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1837 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1839 case eDVBRdsDecoder::RecvRassSlidePic:
1840 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1845 void eDVBServicePlay::showRassSlidePicture()
1851 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1852 if (rass_slide_pic.length())
1853 m_decoder->showSinglePic(rass_slide_pic.c_str());
1855 eDebug("empty filename for rass slide picture received!!");
1858 eDebug("no MPEG Decoder to show iframes avail");
1861 eDebug("showRassSlidePicture called.. but not decoder");
1864 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1870 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1871 if (rass_interactive_pic.length())
1872 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1874 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1877 eDebug("no MPEG Decoder to show iframes avail");
1880 eDebug("showRassInteractivePic called.. but not decoder");
1883 ePyObject eDVBServicePlay::getRassInteractiveMask()
1886 return m_rds_decoder->getRassPictureMask();
1890 int eDVBServiceBase::getFrontendInfo(int w)
1892 eUsePtr<iDVBChannel> channel;
1893 if(m_service_handler.getChannel(channel))
1895 ePtr<iDVBFrontend> fe;
1896 if(channel->getFrontend(fe))
1898 return fe->readFrontendData(w);
1901 PyObject *eDVBServiceBase::getFrontendData()
1903 ePyObject ret = PyDict_New();
1906 eUsePtr<iDVBChannel> channel;
1907 if(!m_service_handler.getChannel(channel))
1909 ePtr<iDVBFrontend> fe;
1910 if(!channel->getFrontend(fe))
1911 fe->getFrontendData(ret);
1919 PyObject *eDVBServiceBase::getFrontendStatus()
1921 ePyObject ret = PyDict_New();
1924 eUsePtr<iDVBChannel> channel;
1925 if(!m_service_handler.getChannel(channel))
1927 ePtr<iDVBFrontend> fe;
1928 if(!channel->getFrontend(fe))
1929 fe->getFrontendStatus(ret);
1937 PyObject *eDVBServiceBase::getTransponderData(bool original)
1939 ePyObject ret = PyDict_New();
1942 eUsePtr<iDVBChannel> channel;
1943 if(!m_service_handler.getChannel(channel))
1945 ePtr<iDVBFrontend> fe;
1946 if(!channel->getFrontend(fe))
1947 fe->getTransponderData(ret, original);
1955 PyObject *eDVBServiceBase::getAll(bool original)
1957 ePyObject ret = getTransponderData(original);
1960 eUsePtr<iDVBChannel> channel;
1961 if(!m_service_handler.getChannel(channel))
1963 ePtr<iDVBFrontend> fe;
1964 if(!channel->getFrontend(fe))
1966 fe->getFrontendData(ret);
1967 fe->getFrontendStatus(ret);
1974 int eDVBServicePlay::getNumberOfSubservices()
1976 ePtr<eServiceEvent> evt;
1977 if (!m_event_handler.getEvent(evt, 0))
1978 return evt->getNumOfLinkageServices();
1982 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1984 ePtr<eServiceEvent> evt;
1985 if (!m_event_handler.getEvent(evt, 0))
1987 if (!evt->getLinkageService(sub, m_reference, n))
1990 sub.type=eServiceReference::idInvalid;
1994 RESULT eDVBServicePlay::startTimeshift()
1996 ePtr<iDVBDemux> demux;
1998 eDebug("Start timeshift!");
2000 if (m_timeshift_enabled)
2003 /* start recording with the data demux. */
2004 if (m_service_handler.getDataDemux(demux))
2007 demux->createTSRecorder(m_record);
2012 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2013 eDebug("could not query ts path");
2016 tspath.append("/timeshift.XXXXXX");
2018 templ = new char[tspath.length() + 1];
2019 strcpy(templ, tspath.c_str());
2021 m_timeshift_fd = mkstemp(templ);
2022 m_timeshift_file = std::string(templ);
2024 eDebug("recording to %s", templ);
2028 if (m_timeshift_fd < 0)
2034 m_record->setTargetFD(m_timeshift_fd);
2036 m_timeshift_enabled = 1;
2038 updateTimeshiftPids();
2044 RESULT eDVBServicePlay::stopTimeshift()
2046 if (!m_timeshift_enabled)
2051 m_timeshift_enabled = 0;
2056 close(m_timeshift_fd);
2057 eDebug("remove timeshift file");
2058 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2063 int eDVBServicePlay::isTimeshiftActive()
2065 return m_timeshift_enabled && m_timeshift_active;
2068 RESULT eDVBServicePlay::activateTimeshift()
2070 if (!m_timeshift_enabled)
2073 if (!m_timeshift_active)
2075 switchToTimeshift();
2082 PyObject *eDVBServicePlay::getCutList()
2084 ePyObject list = PyList_New(0);
2086 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2088 ePyObject tuple = PyTuple_New(2);
2089 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2090 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2091 PyList_Append(list, tuple);
2098 void eDVBServicePlay::setCutList(ePyObject list)
2100 if (!PyList_Check(list))
2102 int size = PyList_Size(list);
2105 m_cue_entries.clear();
2107 for (i=0; i<size; ++i)
2109 ePyObject tuple = PyList_GET_ITEM(list, i);
2110 if (!PyTuple_Check(tuple))
2112 eDebug("non-tuple in cutlist");
2115 if (PyTuple_Size(tuple) != 2)
2117 eDebug("cutlist entries need to be a 2-tuple");
2120 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2121 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2123 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2126 pts_t pts = PyLong_AsLongLong(ppts);
2127 int type = PyInt_AsLong(ptype);
2128 m_cue_entries.insert(cueEntry(pts, type));
2129 eDebug("adding %08llx, %d", pts, type);
2131 m_cuesheet_changed = 1;
2133 cutlistToCuesheet();
2134 m_event((iPlayableService*)this, evCuesheetChanged);
2137 void eDVBServicePlay::setCutListEnable(int enable)
2139 m_cutlist_enabled = enable;
2140 cutlistToCuesheet();
2143 void eDVBServicePlay::updateTimeshiftPids()
2148 eDVBServicePMTHandler::program program;
2149 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2151 if (h.getProgramInfo(program))
2155 std::set<int> pids_to_record;
2156 pids_to_record.insert(0); // PAT
2157 if (program.pmtPid != -1)
2158 pids_to_record.insert(program.pmtPid); // PMT
2160 if (program.textPid != -1)
2161 pids_to_record.insert(program.textPid); // Videotext
2163 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2164 i(program.videoStreams.begin());
2165 i != program.videoStreams.end(); ++i)
2166 pids_to_record.insert(i->pid);
2168 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2169 i(program.audioStreams.begin());
2170 i != program.audioStreams.end(); ++i)
2171 pids_to_record.insert(i->pid);
2173 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2174 i(program.subtitleStreams.begin());
2175 i != program.subtitleStreams.end(); ++i)
2176 pids_to_record.insert(i->pid);
2178 std::set<int> new_pids, obsolete_pids;
2180 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2181 m_pids_active.begin(), m_pids_active.end(),
2182 std::inserter(new_pids, new_pids.begin()));
2184 std::set_difference(
2185 m_pids_active.begin(), m_pids_active.end(),
2186 pids_to_record.begin(), pids_to_record.end(),
2187 std::inserter(new_pids, new_pids.begin())
2190 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2191 m_record->addPID(*i);
2193 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2194 m_record->removePID(*i);
2198 void eDVBServicePlay::switchToLive()
2200 if (!m_timeshift_active)
2203 eDebug("SwitchToLive");
2208 m_teletext_parser = 0;
2210 m_subtitle_parser = 0;
2211 m_new_dvb_subtitle_page_connection = 0;
2212 m_new_subtitle_page_connection = 0;
2213 m_rds_decoder_event_connection = 0;
2214 m_video_event_connection = 0;
2215 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2217 /* free the timeshift service handler, we need the resources */
2218 m_service_handler_timeshift.free();
2219 m_timeshift_active = 0;
2221 m_event((iPlayableService*)this, evSeekableStatusChanged);
2226 void eDVBServicePlay::switchToTimeshift()
2228 if (m_timeshift_active)
2233 m_teletext_parser = 0;
2235 m_subtitle_parser = 0;
2236 m_new_subtitle_page_connection = 0;
2237 m_new_dvb_subtitle_page_connection = 0;
2238 m_rds_decoder_event_connection = 0;
2239 m_video_event_connection = 0;
2241 m_timeshift_active = 1;
2243 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2244 r.path = m_timeshift_file;
2246 m_cue = new eCueSheet();
2247 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2249 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2251 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2253 m_event((iPlayableService*)this, evSeekableStatusChanged);
2256 void eDVBServicePlay::updateDecoder()
2258 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2260 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2262 eDVBServicePMTHandler::program program;
2263 if (h.getProgramInfo(program))
2264 eDebug("getting program info failed.");
2267 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2268 if (!program.videoStreams.empty())
2270 eDebugNoNewLine(" (");
2271 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2272 i(program.videoStreams.begin());
2273 i != program.videoStreams.end(); ++i)
2280 if (i != program.videoStreams.begin())
2281 eDebugNoNewLine(", ");
2282 eDebugNoNewLine("%04x", i->pid);
2284 eDebugNoNewLine(")");
2286 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2287 if (!program.audioStreams.empty())
2289 eDebugNoNewLine(" (");
2290 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2291 i(program.audioStreams.begin());
2292 i != program.audioStreams.end(); ++i)
2294 if (i != program.audioStreams.begin())
2295 eDebugNoNewLine(", ");
2296 eDebugNoNewLine("%04x", i->pid);
2298 eDebugNoNewLine(")");
2300 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2301 pcrpid = program.pcrPid;
2302 eDebug(", and the text pid is %04x", program.textPid);
2303 tpid = program.textPid;
2308 h.getDecodeDemux(m_decode_demux);
2311 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2313 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2315 if (m_decode_demux && m_is_primary)
2317 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2318 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2319 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2320 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2323 m_teletext_parser = 0;
2324 m_subtitle_parser = 0;
2328 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2335 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2336 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2337 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2341 eServiceReferenceDVB ref;
2342 m_service_handler.getServiceReference(ref);
2343 eServiceReferenceDVB parent = ref.getParentServiceReference();
2348 ePtr<eDVBResourceManager> res_mgr;
2349 if (!eDVBResourceManager::getInstance(res_mgr))
2351 ePtr<iDVBChannelList> db;
2352 if (!res_mgr->getChannelList(db))
2354 ePtr<eDVBService> origService;
2355 if (!db->getService(parent, origService))
2357 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2358 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2365 std::string config_delay;
2366 int config_delay_int = 0;
2367 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2368 config_delay_int = atoi(config_delay.c_str());
2369 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2371 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2372 config_delay_int = atoi(config_delay.c_str());
2374 config_delay_int = 0;
2375 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2377 m_decoder->setVideoPID(vpid, vpidtype);
2378 selectAudioStream();
2380 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2381 m_decoder->setSyncPCR(pcrpid);
2383 m_decoder->setSyncPCR(-1);
2387 m_decoder->setTextPID(tpid);
2388 m_teletext_parser->start(program.textPid);
2391 if (vpid > 0 && vpid < 0x2000)
2395 std::string radio_pic;
2396 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2397 m_decoder->setRadioPic(radio_pic);
2400 /* if (!m_is_primary)
2401 m_decoder->setTrickmode();
2402 else */ if (m_is_paused)
2407 m_decoder->setAudioChannel(achannel);
2409 /* don't worry about non-existing services, nor pvr services */
2412 /* (audio pid will be set in selectAudioTrack */
2413 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2414 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2415 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2416 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2419 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2422 void eDVBServicePlay::loadCuesheet()
2424 std::string filename = m_reference.path + ".cuts";
2426 m_cue_entries.clear();
2428 FILE *f = fopen(filename.c_str(), "rb");
2432 eDebug("loading cuts..");
2435 unsigned long long where;
2438 if (!fread(&where, sizeof(where), 1, f))
2440 if (!fread(&what, sizeof(what), 1, f))
2443 #if BYTE_ORDER == LITTLE_ENDIAN
2444 where = bswap_64(where);
2451 m_cue_entries.insert(cueEntry(where, what));
2454 eDebug("%d entries", m_cue_entries.size());
2456 eDebug("cutfile not found!");
2458 m_cuesheet_changed = 0;
2459 cutlistToCuesheet();
2460 m_event((iPlayableService*)this, evCuesheetChanged);
2463 void eDVBServicePlay::saveCuesheet()
2465 std::string filename = m_reference.path + ".cuts";
2467 FILE *f = fopen(filename.c_str(), "wb");
2471 unsigned long long where;
2474 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2476 #if BYTE_ORDER == BIG_ENDIAN
2479 where = bswap_64(i->where);
2481 what = htonl(i->what);
2482 fwrite(&where, sizeof(where), 1, f);
2483 fwrite(&what, sizeof(what), 1, f);
2489 m_cuesheet_changed = 0;
2492 void eDVBServicePlay::cutlistToCuesheet()
2496 eDebug("no cue sheet");
2501 if (!m_cutlist_enabled)
2503 m_cue->commitSpans();
2504 eDebug("cutlists were disabled");
2508 pts_t in = 0, out = 0, length = 0;
2512 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2514 int have_any_span = 0;
2518 if (i == m_cue_entries.end())
2524 if (i->what == 0) /* in */
2528 } else if (i->what == 1) /* out */
2530 else /* mark (2) or last play position (3) */
2549 m_cue->addSourceSpan(in, out);
2554 if (i == m_cue_entries.end())
2557 m_cue->commitSpans();
2560 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2562 if (m_subtitle_widget)
2563 disableSubtitles(parent);
2566 int tuplesize = PyTuple_Size(tuple);
2569 if (!PyTuple_Check(tuple))
2575 entry = PyTuple_GET_ITEM(tuple, 0);
2577 if (!PyInt_Check(entry))
2580 type = PyInt_AsLong(entry);
2582 if (type == 1) // teletext subtitles
2584 int page, magazine, pid;
2588 if (!m_teletext_parser)
2590 eDebug("enable teletext subtitles.. no parser !!!");
2594 entry = PyTuple_GET_ITEM(tuple, 1);
2595 if (!PyInt_Check(entry))
2597 pid = PyInt_AsLong(entry);
2599 entry = PyTuple_GET_ITEM(tuple, 2);
2600 if (!PyInt_Check(entry))
2602 page = PyInt_AsLong(entry);
2604 entry = PyTuple_GET_ITEM(tuple, 3);
2605 if (!PyInt_Check(entry))
2607 magazine = PyInt_AsLong(entry);
2609 m_subtitle_widget = new eSubtitleWidget(parent);
2610 m_subtitle_widget->resize(parent->size()); /* full size */
2611 m_teletext_parser->setPageAndMagazine(page, magazine);
2613 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2617 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2618 if (!m_subtitle_parser)
2620 eDebug("enable dvb subtitles.. no parser !!!");
2626 entry = PyTuple_GET_ITEM(tuple, 1);
2627 if (!PyInt_Check(entry))
2629 pid = PyInt_AsLong(entry);
2631 entry = PyTuple_GET_ITEM(tuple, 2);
2632 if (!PyInt_Check(entry))
2634 composition_page_id = PyInt_AsLong(entry);
2636 entry = PyTuple_GET_ITEM(tuple, 3);
2637 if (!PyInt_Check(entry))
2639 ancillary_page_id = PyInt_AsLong(entry);
2641 m_subtitle_widget = new eSubtitleWidget(parent);
2642 m_subtitle_widget->resize(parent->size()); /* full size */
2643 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2645 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2651 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2652 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2653 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2657 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2659 delete m_subtitle_widget;
2660 m_subtitle_widget = 0;
2661 if (m_subtitle_parser)
2663 m_subtitle_parser->stop();
2664 m_dvb_subtitle_pages.clear();
2666 if (m_teletext_parser)
2668 m_teletext_parser->setPageAndMagazine(-1, -1);
2669 m_subtitle_pages.clear();
2672 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2676 PyObject *eDVBServicePlay::getCachedSubtitle()
2680 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2683 unsigned int data = (unsigned int)tmp;
2684 int pid = (data&0xFFFF0000)>>16;
2685 ePyObject tuple = PyTuple_New(4);
2686 eDVBServicePMTHandler::program program;
2687 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2688 if (!h.getProgramInfo(program))
2690 if (program.textPid==pid) // teletext
2691 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2693 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2694 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2695 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2696 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2704 PyObject *eDVBServicePlay::getSubtitleList()
2706 if (!m_teletext_parser)
2709 ePyObject l = PyList_New(0);
2710 std::set<int> added_ttx_pages;
2712 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2713 m_teletext_parser->m_found_subtitle_pages;
2715 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2716 eDVBServicePMTHandler::program program;
2717 if (h.getProgramInfo(program))
2718 eDebug("getting program info failed.");
2721 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2722 it != program.subtitleStreams.end(); ++it)
2724 switch(it->subtitling_type)
2726 case 0x01: // ebu teletext subtitles
2728 int page_number = it->teletext_page_number & 0xFF;
2729 int magazine_number = it->teletext_magazine_number & 7;
2730 int hash = magazine_number << 8 | page_number;
2731 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2733 ePyObject tuple = PyTuple_New(5);
2734 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2735 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2736 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2737 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2738 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2739 PyList_Append(l, tuple);
2741 added_ttx_pages.insert(hash);
2746 case 0x20 ... 0x23: // dvb subtitles
2748 ePyObject tuple = PyTuple_New(5);
2749 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2750 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2751 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2752 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2753 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2754 PyList_Insert(l, 0, tuple);
2762 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2763 it != subs.end(); ++it)
2765 int page_number = it->teletext_page_number & 0xFF;
2766 int magazine_number = it->teletext_magazine_number & 7;
2767 int hash = magazine_number << 8 | page_number;
2768 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2770 ePyObject tuple = PyTuple_New(5);
2771 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2772 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2773 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2774 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2775 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2776 PyList_Append(l, tuple);
2784 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2786 if (m_subtitle_widget)
2790 m_decoder->getPTS(0, pos);
2791 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2792 m_subtitle_pages.push_back(page);
2793 checkSubtitleTiming();
2797 void eDVBServicePlay::checkSubtitleTiming()
2799 eDebug("checkSubtitleTiming");
2800 if (!m_subtitle_widget)
2804 enum { TELETEXT, DVB } type;
2805 eDVBTeletextSubtitlePage page;
2806 eDVBSubtitlePage dvb_page;
2808 if (!m_subtitle_pages.empty())
2810 page = m_subtitle_pages.front();
2812 show_time = page.m_pts;
2814 else if (!m_dvb_subtitle_pages.empty())
2816 dvb_page = m_dvb_subtitle_pages.front();
2818 show_time = dvb_page.m_show_time;
2826 m_decoder->getPTS(0, pos);
2828 eDebug("%lld %lld", pos, show_time);
2829 int diff = show_time - pos;
2830 if (type == TELETEXT && !page.m_have_pts)
2832 eDebug("ttx subtitle page without pts... immediate show");
2837 eDebug("[late (%d ms)]", -diff / 90);
2840 if (abs(diff) > 1800000)
2842 eDebug("[invalid]... immediate show!");
2847 if (type == TELETEXT)
2849 eDebug("display teletext subtitle page %lld", show_time);
2850 m_subtitle_widget->setPage(page);
2851 m_subtitle_pages.pop_front();
2855 eDebug("display dvb subtitle Page %lld", show_time);
2856 m_subtitle_widget->setPage(dvb_page);
2857 m_dvb_subtitle_pages.pop_front();
2861 eDebug("start subtitle delay %d", diff / 90);
2862 m_subtitle_sync_timer->start(diff / 90, 1);
2868 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2870 if (m_subtitle_widget)
2874 m_decoder->getPTS(0, pos);
2875 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2876 m_dvb_subtitle_pages.push_back(p);
2877 checkSubtitleTiming();
2881 int eDVBServicePlay::getAC3Delay()
2884 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2886 return m_decoder->getAC3Delay();
2891 int eDVBServicePlay::getPCMDelay()
2894 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2896 return m_decoder->getPCMDelay();
2901 void eDVBServicePlay::setAC3Delay(int delay)
2904 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2906 m_decoder->setAC3Delay(delay);
2909 void eDVBServicePlay::setPCMDelay(int delay)
2912 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2914 m_decoder->setPCMDelay(delay);
2917 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2919 switch(event.type) {
2920 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2921 m_event((iPlayableService*)this, evVideoSizeChanged);
2923 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2924 m_event((iPlayableService*)this, evVideoFramerateChanged);
2926 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2927 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2934 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2940 PyObject *eDVBServicePlay::getStreamingData()
2942 eDVBServicePMTHandler::program program;
2943 if (m_service_handler.getProgramInfo(program))
2948 ePyObject r = program.createPythonObject();
2949 ePtr<iDVBDemux> demux;
2950 if (!m_service_handler.getDataDemux(demux))
2953 if (!demux->getCADemuxID(demux_id))
2954 PutToDict(r, "demux", demux_id);
2961 DEFINE_REF(eDVBServicePlay)
2963 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2967 case iServiceInformation::sTransponderData:
2968 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2972 return iStaticServiceInformation::getInfoObject(ref, w);
2975 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");