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> &);
472 DEFINE_REF(eDVBPVRServiceOfflineOperations);
474 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
478 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
484 std::list<std::string> res;
485 if (getListOfFilenames(res))
488 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
490 eDebug("FATAL !! can't get background file eraser");
492 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
494 eDebug("Removing %s...", i->c_str());
496 eraser->erase(i->c_str());
498 ::unlink(i->c_str());
505 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
508 res.push_back(m_ref.path);
510 // handling for old splitted recordings (enigma 1)
515 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
517 if (stat(buf, &s) < 0)
522 res.push_back(m_ref.path + ".meta");
523 res.push_back(m_ref.path + ".ap");
524 res.push_back(m_ref.path + ".sc");
525 res.push_back(m_ref.path + ".cuts");
526 std::string tmp = m_ref.path;
527 tmp.erase(m_ref.path.length()-3);
528 res.push_back(tmp + ".eit");
532 RESULT eDVBPVRServiceOfflineOperations::reindex()
534 const char *filename = m_ref.path.c_str();
535 eDebug("reindexing %s...", filename);
537 eMPEGStreamInformation info;
538 eMPEGStreamParserTS parser(info);
540 info.startSave(filename);
544 int err = f.open(m_ref.path.c_str(), 0);
548 off_t length = f.length();
549 unsigned char buffer[188*256*4];
552 off_t offset = f.lseek(0, SEEK_CUR);
553 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
554 int r = f.read(buffer, sizeof(buffer));
559 parser.parseData(offset, buffer, r);
568 DEFINE_REF(eServiceFactoryDVB)
570 eServiceFactoryDVB::eServiceFactoryDVB()
572 ePtr<eServiceCenter> sc;
574 eServiceCenter::getPrivInstance(sc);
577 std::list<std::string> extensions;
578 extensions.push_back("ts");
579 extensions.push_back("trp");
580 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
583 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
584 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
587 eServiceFactoryDVB::~eServiceFactoryDVB()
589 ePtr<eServiceCenter> sc;
591 eServiceCenter::getPrivInstance(sc);
593 sc->removeServiceFactory(eServiceFactoryDVB::id);
596 DEFINE_REF(eDVBServiceList);
598 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
602 eDVBServiceList::~eDVBServiceList()
606 RESULT eDVBServiceList::startQuery()
608 ePtr<iDVBChannelList> db;
609 ePtr<eDVBResourceManager> res;
612 if ((err = eDVBResourceManager::getInstance(res)) != 0)
614 eDebug("no resource manager");
617 if ((err = res->getChannelList(db)) != 0)
619 eDebug("no channel list");
623 ePtr<eDVBChannelQuery> q;
625 if (!m_parent.path.empty())
627 eDVBChannelQuery::compile(q, m_parent.path);
630 eDebug("compile query failed");
635 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
637 eDebug("startQuery failed");
644 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
646 eServiceReferenceDVB ref;
651 while (!m_query->getNextResult(ref))
655 list.sort(iListableServiceCompare(this));
660 // The first argument of this function is a format string to specify the order and
661 // the content of the returned list
662 // useable format options are
663 // R = Service Reference (as swig object .. this is very slow)
664 // S = Service Reference (as python string object .. same as ref.toString())
665 // C = Service Reference (as python string object .. same as ref.toCompareString())
666 // N = Service Name (as python string object)
667 // n = Short Service Name (short name brakets used) (as python string object)
668 // when exactly one return value per service is selected in the format string,
669 // then each value is directly a list entry
670 // when more than one value is returned per service, then the list is a list of
672 // unknown format string chars are returned as python None values !
673 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
676 std::list<eServiceReference> tmplist;
679 if (!format || !(retcount=strlen(format)))
680 format = "R"; // just return service reference swig object ...
682 if (!getContent(tmplist, sorted))
684 int services=tmplist.size();
685 ePtr<iStaticServiceInformation> sptr;
686 eServiceCenterPtr service_center;
688 if (strchr(format, 'N') || strchr(format, 'n'))
689 eServiceCenter::getPrivInstance(service_center);
691 ret = PyList_New(services);
692 std::list<eServiceReference>::iterator it(tmplist.begin());
694 for (int cnt=0; cnt < services; ++cnt)
696 eServiceReference &ref=*it++;
697 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
698 for (int i=0; i < retcount; ++i)
703 case 'R': // service reference (swig)object
704 tmp = NEW_eServiceReference(ref);
706 case 'C': // service reference compare string
707 tmp = PyString_FromString(ref.toCompareString().c_str());
709 case 'S': // service reference string
710 tmp = PyString_FromString(ref.toString().c_str());
712 case 'N': // service name
715 service_center->info(ref, sptr);
719 sptr->getName(ref, name);
721 // filter short name brakets
723 while((pos = name.find("\xc2\x86")) != std::string::npos)
725 while((pos = name.find("\xc2\x87")) != std::string::npos)
729 tmp = PyString_FromString(name.c_str());
733 tmp = PyString_FromString("<n/a>");
735 case 'n': // short service name
738 service_center->info(ref, sptr);
742 sptr->getName(ref, name);
743 name = buildShortName(name);
745 tmp = PyString_FromString(name.c_str());
749 tmp = PyString_FromString("<n/a>");
762 PyTuple_SET_ITEM(tuple, i, tmp);
764 PyList_SET_ITEM(ret, cnt, tmp);
768 PyList_SET_ITEM(ret, cnt, tuple);
771 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
774 RESULT eDVBServiceList::getNext(eServiceReference &ref)
779 return m_query->getNextResult((eServiceReferenceDVB&)ref);
782 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
784 if (m_parent.flags & eServiceReference::canDescent) // bouquet
786 ePtr<iDVBChannelList> db;
787 ePtr<eDVBResourceManager> resm;
789 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
792 if (db->getBouquet(m_parent, m_bouquet) != 0)
803 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
807 return m_bouquet->addService(ref, before);
810 RESULT eDVBServiceList::removeService(eServiceReference &ref)
814 return m_bouquet->removeService(ref);
817 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
821 return m_bouquet->moveService(ref, pos);
824 RESULT eDVBServiceList::flushChanges()
828 return m_bouquet->flushChanges();
831 RESULT eDVBServiceList::setListName(const std::string &name)
835 return m_bouquet->setListName(name);
838 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
840 ePtr<eDVBService> service;
841 int r = lookupService(service, ref);
844 // check resources...
845 ptr = new eDVBServicePlay(ref, service);
849 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
851 if (ref.path.empty())
853 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
862 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
864 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
865 if (list->startQuery())
875 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
877 /* is a listable service? */
878 if (ref.flags & eServiceReference::canDescent) // bouquet
880 if ( !ref.name.empty() ) // satellites or providers list
881 ptr = m_StaticServiceDVBInfo;
882 else // a dvb bouquet
883 ptr = m_StaticServiceDVBBouquetInfo;
885 else if (!ref.path.empty()) /* do we have a PVR service? */
886 ptr = new eStaticServiceDVBPVRInformation(ref);
887 else // normal dvb service
889 ePtr<eDVBService> service;
890 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
891 ptr = m_StaticServiceDVBInfo;
893 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
899 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
901 if (ref.path.empty())
907 ptr = new eDVBPVRServiceOfflineOperations(ref);
912 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
914 if (!ref.path.empty()) // playback
916 eDVBMetaParser parser;
917 int ret=parser.parseFile(ref.path);
918 service = new eDVBService;
920 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
924 // TODO: handle the listing itself
925 // if (ref.... == -1) .. return "... bouquets ...";
926 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
928 ePtr<iDVBChannelList> db;
929 ePtr<eDVBResourceManager> res;
932 if ((err = eDVBResourceManager::getInstance(res)) != 0)
934 eDebug("no resource manager");
937 if ((err = res->getChannelList(db)) != 0)
939 eDebug("no channel list");
943 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
944 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
946 eDebug("getService failed!");
954 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
955 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
958 m_is_pvr = !m_reference.path.empty();
960 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
963 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
964 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
965 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
967 m_cuesheet_changed = 0;
968 m_cutlist_enabled = 1;
970 m_subtitle_widget = 0;
974 m_subtitle_sync_timer = eTimer::create(eApp);
976 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
979 eDVBServicePlay::~eDVBServicePlay()
984 int ret=meta.parseFile(m_reference.path);
988 meta.m_service_data="";
989 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
990 meta.m_service_data += tmp;
992 for (int x=0; x < eDVBService::cacheMax; ++x)
994 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
997 sprintf(tmp, ",c:%02d%04x", x, entry);
998 meta.m_service_data += tmp;
1001 meta.updateMeta(m_reference.path);
1004 delete m_subtitle_widget;
1007 void eDVBServicePlay::gotNewEvent()
1011 ePtr<eServiceEvent> m_event_now, m_event_next;
1012 getEvent(m_event_now, 0);
1013 getEvent(m_event_next, 1);
1016 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1018 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1020 m_event((iPlayableService*)this, evUpdatedEventInfo);
1023 void eDVBServicePlay::serviceEvent(int event)
1025 m_tune_state = event;
1029 case eDVBServicePMTHandler::eventTuned:
1031 ePtr<iDVBDemux> m_demux;
1032 if (!m_service_handler.getDataDemux(m_demux))
1034 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1035 int sid = ref.getParentServiceID().get();
1037 sid = ref.getServiceID().get();
1038 if ( ref.getParentTransportStreamID().get() &&
1039 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1040 m_event_handler.startOther(m_demux, sid);
1042 m_event_handler.start(m_demux, sid);
1044 m_event((iPlayableService*)this, evTunedIn);
1047 case eDVBServicePMTHandler::eventNoResources:
1048 case eDVBServicePMTHandler::eventNoPAT:
1049 case eDVBServicePMTHandler::eventNoPATEntry:
1050 case eDVBServicePMTHandler::eventNoPMT:
1051 case eDVBServicePMTHandler::eventTuneFailed:
1052 case eDVBServicePMTHandler::eventMisconfiguration:
1054 eDebug("DVB service failed to tune - error %d", event);
1055 m_event((iPlayableService*)this, evTuneFailed);
1058 case eDVBServicePMTHandler::eventNewProgramInfo:
1060 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1061 if (m_timeshift_enabled)
1062 updateTimeshiftPids();
1063 if (!m_timeshift_active)
1065 if (m_first_program_info && m_is_pvr)
1067 m_first_program_info = 0;
1070 m_event((iPlayableService*)this, evUpdatedInfo);
1073 case eDVBServicePMTHandler::eventEOF:
1074 m_event((iPlayableService*)this, evEOF);
1076 case eDVBServicePMTHandler::eventSOF:
1077 m_event((iPlayableService*)this, evSOF);
1082 void eDVBServicePlay::serviceEventTimeshift(int event)
1086 case eDVBServicePMTHandler::eventNewProgramInfo:
1087 if (m_timeshift_active)
1090 case eDVBServicePMTHandler::eventSOF:
1091 m_event((iPlayableService*)this, evSOF);
1093 case eDVBServicePMTHandler::eventEOF:
1094 if ((!m_is_paused) && (m_skipmode >= 0))
1096 eDebug("timeshift EOF, so let's go live");
1103 RESULT eDVBServicePlay::start()
1106 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1107 two (one for decoding, one for data source), as we must be prepared
1108 to start recording from the data demux. */
1110 m_cue = new eCueSheet();
1112 m_event(this, evStart);
1114 m_first_program_info = 1;
1115 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1116 r = m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1118 /* inject EIT if there is a stored one */
1121 std::string filename = service.path;
1122 filename.erase(filename.length()-2, 2);
1124 ePtr<eServiceEvent> event = new eServiceEvent;
1125 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1127 ePtr<eServiceEvent> empty;
1128 m_event_handler.inject(event, 0);
1129 m_event_handler.inject(empty, 1);
1136 m_event(this, evStart);
1141 RESULT eDVBServicePlay::stop()
1143 /* add bookmark for last play position */
1146 pts_t play_position, length;
1147 if (!getPlayPosition(play_position))
1149 /* remove last position */
1150 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1152 if (i->what == 3) /* current play position */
1154 m_cue_entries.erase(i);
1155 i = m_cue_entries.begin();
1161 if (getLength(length))
1166 int perc = play_position * 100LL / length;
1168 /* only store last play position when between 1% and 99% */
1169 if ((1 < perc) && (perc < 99))
1170 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1172 m_cuesheet_changed = 1;
1176 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1178 m_service_handler_timeshift.free();
1179 m_service_handler.free();
1181 if (m_is_pvr && m_cuesheet_changed)
1184 /* save cuesheet only when main file is accessible. */
1185 if (!::stat(m_reference.path.c_str(), &s))
1188 m_event((iPlayableService*)this, evStopped);
1192 RESULT eDVBServicePlay::setTarget(int target)
1194 m_is_primary = !target;
1198 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1200 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1204 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1206 /* note: we check for timeshift to be enabled,
1207 not neccessary active. if you pause when timeshift
1208 is not active, you should activate it when unpausing */
1209 if ((!m_is_pvr) && (!m_timeshift_enabled))
1219 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1221 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1222 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1223 setFastForward_internal(0);
1225 return m_decoder->setSlowMotion(ratio);
1230 RESULT eDVBServicePlay::setFastForward(int ratio)
1232 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1234 return setFastForward_internal(ratio);
1237 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1239 int skipmode, ffratio;
1245 } else if (ratio > 0)
1253 } else // if (ratio < 0)
1259 if (m_skipmode != skipmode)
1261 eDebug("setting cue skipmode to %d", skipmode);
1263 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1266 m_skipmode = skipmode;
1272 ; /* return m_decoder->play(); is done in caller*/
1273 else if (ffratio != 1)
1274 return m_decoder->setFastForward(ffratio);
1276 return m_decoder->setTrickmode();
1280 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1282 if (m_is_pvr || m_timeshift_enabled)
1292 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1293 RESULT eDVBServicePlay::getLength(pts_t &len)
1295 ePtr<iDVBPVRChannel> pvr_channel;
1297 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1300 return pvr_channel->getLength(len);
1303 RESULT eDVBServicePlay::pause()
1305 eDebug("eDVBServicePlay::pause");
1306 setFastForward_internal(0);
1310 return m_decoder->pause();
1315 RESULT eDVBServicePlay::unpause()
1317 eDebug("eDVBServicePlay::unpause");
1318 setFastForward_internal(0);
1322 return m_decoder->play();
1327 RESULT eDVBServicePlay::seekTo(pts_t to)
1329 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1331 if (!m_decode_demux)
1334 ePtr<iDVBPVRChannel> pvr_channel;
1336 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1342 m_cue->seekTo(0, to);
1343 m_dvb_subtitle_pages.clear();
1344 m_subtitle_pages.clear();
1349 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1351 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1353 if (!m_decode_demux)
1356 ePtr<iDVBPVRChannel> pvr_channel;
1358 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1363 /* HACK until we have skip-AP api */
1364 if ((to > 0) && (to < 100))
1372 m_cue->seekTo(mode, to);
1373 m_dvb_subtitle_pages.clear();
1374 m_subtitle_pages.clear();
1378 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1380 ePtr<iDVBPVRChannel> pvr_channel;
1382 if (!m_decode_demux)
1385 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1390 /* if there is a decoder, use audio or video PTS */
1393 r = m_decoder->getPTS(0, pos);
1399 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1402 RESULT eDVBServicePlay::setTrickmode(int trick)
1404 /* currently unimplemented */
1408 RESULT eDVBServicePlay::isCurrentlySeekable()
1410 return m_is_pvr || m_timeshift_active;
1413 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1419 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1425 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1431 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1437 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1443 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1446 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1447 (m_timeshift_enabled || !m_is_pvr))
1449 if (!m_timeshift_enabled)
1451 /* query config path */
1453 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1454 eDebug("could not query ts path from config");
1458 /* we need enough diskspace */
1460 if (statfs(tspath.c_str(), &fs) < 0)
1462 eDebug("statfs failed!");
1466 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1468 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1478 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1489 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1495 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1501 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1507 RESULT eDVBServicePlay::getName(std::string &name)
1511 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1512 return i->getName(m_reference, name);
1514 else if (m_dvb_service)
1516 m_dvb_service->getName(m_reference, name);
1520 else if (!m_reference.name.empty())
1521 eStaticServiceDVBInformation().getName(m_reference, name);
1523 name = "DVB service";
1527 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1529 return m_event_handler.getEvent(evt, nownext);
1532 int eDVBServicePlay::getInfo(int w)
1534 eDVBServicePMTHandler::program program;
1537 return resIsPyObject;
1539 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1541 int no_program_info = 0;
1543 if (h.getProgramInfo(program))
1544 no_program_info = 1;
1550 return m_decoder->getVideoHeight();
1554 return m_decoder->getVideoWidth();
1558 return m_decoder->getVideoFrameRate();
1562 return m_decoder->getVideoProgressive();
1568 aspect = m_decoder->getVideoAspect();
1569 if (aspect == -1 && no_program_info)
1571 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1573 ePtr<eServiceEvent> evt;
1574 if (!m_event_handler.getEvent(evt, 0))
1576 ePtr<eComponentData> data;
1577 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1579 if ( data->getStreamContent() == 1 )
1581 switch(data->getComponentType())
1584 case 1: // 4:3 SD PAL
1586 case 3: // 16:9 SD PAL
1587 case 4: // > 16:9 PAL
1588 case 5: // 4:3 SD NTSC
1590 case 7: // 16:9 SD NTSC
1591 case 8: // > 16:9 NTSC
1594 case 9: // 4:3 HD PAL
1596 case 0xB: // 16:9 HD PAL
1597 case 0xC: // > 16:9 HD PAL
1598 case 0xD: // 4:3 HD NTSC
1600 case 0xF: // 16:9 HD NTSC
1601 case 0x10: // > 16:9 HD PAL
1602 return data->getComponentType();
1612 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1616 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1620 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1621 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1625 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1628 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1632 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1636 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1640 if (no_program_info) return -1; return program.pcrPid;
1641 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1642 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1643 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1644 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1645 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1646 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1647 case sProvider: if (!m_dvb_service) return -1; return -2;
1648 case sServiceref: return resIsString;
1649 case sDVBState: return m_tune_state;
1656 std::string eDVBServicePlay::getInfoString(int w)
1661 if (!m_dvb_service) return "";
1662 return m_dvb_service->m_provider_name;
1664 return m_reference.toString();
1668 return iServiceInformation::getInfoString(w);
1671 PyObject *eDVBServicePlay::getInfoObject(int w)
1676 return m_service_handler.getCaIds();
1677 case sTransponderData:
1678 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1682 return iServiceInformation::getInfoObject(w);
1685 int eDVBServicePlay::getNumberOfTracks()
1687 eDVBServicePMTHandler::program program;
1688 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1689 if (h.getProgramInfo(program))
1691 return program.audioStreams.size();
1694 int eDVBServicePlay::getCurrentTrack()
1696 eDVBServicePMTHandler::program program;
1697 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1698 if (h.getProgramInfo(program))
1701 int max = program.audioStreams.size();
1704 for (i = 0; i < max; ++i)
1705 if (program.audioStreams[i].pid == m_current_audio_pid)
1711 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1713 int ret = selectAudioStream(i);
1715 if (m_decoder->set())
1721 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1723 eDVBServicePMTHandler::program program;
1724 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1726 if (h.getProgramInfo(program))
1729 if (i >= program.audioStreams.size())
1732 info.m_pid = program.audioStreams[i].pid;
1734 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1735 info.m_description = "MPEG";
1736 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1737 info.m_description = "AC3";
1738 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1739 info.m_description = "AAC";
1740 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1741 info.m_description = "AAC-HE";
1742 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1743 info.m_description = "DTS";
1745 info.m_description = "???";
1747 if (program.audioStreams[i].component_tag != -1)
1749 ePtr<eServiceEvent> evt;
1750 if (!m_event_handler.getEvent(evt, 0))
1752 ePtr<eComponentData> data;
1753 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1754 info.m_language = data->getText();
1758 if (info.m_language.empty())
1759 info.m_language = program.audioStreams[i].language_code;
1764 int eDVBServicePlay::selectAudioStream(int i)
1766 eDVBServicePMTHandler::program program;
1767 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1769 if (h.getProgramInfo(program))
1772 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1780 stream = program.defaultAudioStream;
1782 int apid = -1, apidtype = -1;
1784 if (((unsigned int)stream) < program.audioStreams.size())
1786 apid = program.audioStreams[stream].pid;
1787 apidtype = program.audioStreams[stream].type;
1790 m_current_audio_pid = apid;
1792 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1794 eDebug("set audio pid failed");
1800 /* 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 */
1801 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1803 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1805 rdsPid = program.audioStreams[stream].rdsPid;
1806 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1809 ePtr<iDVBDemux> data_demux;
1810 if (!h.getDataDemux(data_demux))
1812 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1813 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1814 m_rds_decoder->start(rdsPid);
1819 /* store new pid as default only when:
1820 a.) we have an entry in the service db for the current service,
1821 b.) we are not playing back something,
1822 c.) we are not selecting the default entry. (we wouldn't change
1823 anything in the best case, or destroy the default setting in
1824 case the real default is not yet available.)
1826 if (m_dvb_service && ((i != -1)
1827 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1829 if (apidtype == eDVBAudio::aMPEG)
1831 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1832 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1834 else if (apidtype == eDVBAudio::aAC3)
1836 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1837 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1841 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1842 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1846 h.resetCachedProgram();
1851 int eDVBServicePlay::getCurrentChannel()
1853 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1856 RESULT eDVBServicePlay::selectChannel(int i)
1858 if (i < LEFT || i > RIGHT || i == STEREO)
1861 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1863 m_decoder->setAudioChannel(i);
1867 std::string eDVBServicePlay::getText(int x)
1873 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1875 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1880 void eDVBServicePlay::rdsDecoderEvent(int what)
1884 case eDVBRdsDecoder::RadioTextChanged:
1885 m_event((iPlayableService*)this, evUpdatedRadioText);
1887 case eDVBRdsDecoder::RtpTextChanged:
1888 m_event((iPlayableService*)this, evUpdatedRtpText);
1890 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1891 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1893 case eDVBRdsDecoder::RecvRassSlidePic:
1894 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1899 void eDVBServicePlay::showRassSlidePicture()
1905 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1906 if (rass_slide_pic.length())
1907 m_decoder->showSinglePic(rass_slide_pic.c_str());
1909 eDebug("empty filename for rass slide picture received!!");
1912 eDebug("no MPEG Decoder to show iframes avail");
1915 eDebug("showRassSlidePicture called.. but not decoder");
1918 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1924 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1925 if (rass_interactive_pic.length())
1926 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1928 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1931 eDebug("no MPEG Decoder to show iframes avail");
1934 eDebug("showRassInteractivePic called.. but not decoder");
1937 ePyObject eDVBServicePlay::getRassInteractiveMask()
1940 return m_rds_decoder->getRassPictureMask();
1944 int eDVBServiceBase::getFrontendInfo(int w)
1946 eUsePtr<iDVBChannel> channel;
1947 if(m_service_handler.getChannel(channel))
1949 ePtr<iDVBFrontend> fe;
1950 if(channel->getFrontend(fe))
1952 return fe->readFrontendData(w);
1955 PyObject *eDVBServiceBase::getFrontendData()
1957 ePyObject ret = PyDict_New();
1960 eUsePtr<iDVBChannel> channel;
1961 if(!m_service_handler.getChannel(channel))
1963 ePtr<iDVBFrontend> fe;
1964 if(!channel->getFrontend(fe))
1965 fe->getFrontendData(ret);
1973 PyObject *eDVBServiceBase::getFrontendStatus()
1975 ePyObject ret = PyDict_New();
1978 eUsePtr<iDVBChannel> channel;
1979 if(!m_service_handler.getChannel(channel))
1981 ePtr<iDVBFrontend> fe;
1982 if(!channel->getFrontend(fe))
1983 fe->getFrontendStatus(ret);
1991 PyObject *eDVBServiceBase::getTransponderData(bool original)
1993 ePyObject ret = PyDict_New();
1996 eUsePtr<iDVBChannel> channel;
1997 if(!m_service_handler.getChannel(channel))
1999 ePtr<iDVBFrontend> fe;
2000 if(!channel->getFrontend(fe))
2001 fe->getTransponderData(ret, original);
2009 PyObject *eDVBServiceBase::getAll(bool original)
2011 ePyObject ret = getTransponderData(original);
2014 eUsePtr<iDVBChannel> channel;
2015 if(!m_service_handler.getChannel(channel))
2017 ePtr<iDVBFrontend> fe;
2018 if(!channel->getFrontend(fe))
2020 fe->getFrontendData(ret);
2021 fe->getFrontendStatus(ret);
2028 int eDVBServicePlay::getNumberOfSubservices()
2030 ePtr<eServiceEvent> evt;
2031 if (!m_event_handler.getEvent(evt, 0))
2032 return evt->getNumOfLinkageServices();
2036 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2038 ePtr<eServiceEvent> evt;
2039 if (!m_event_handler.getEvent(evt, 0))
2041 if (!evt->getLinkageService(sub, m_reference, n))
2044 sub.type=eServiceReference::idInvalid;
2048 RESULT eDVBServicePlay::startTimeshift()
2050 ePtr<iDVBDemux> demux;
2052 eDebug("Start timeshift!");
2054 if (m_timeshift_enabled)
2057 /* start recording with the data demux. */
2058 if (m_service_handler.getDataDemux(demux))
2061 demux->createTSRecorder(m_record);
2066 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2067 eDebug("could not query ts path");
2070 tspath.append("/timeshift.XXXXXX");
2072 templ = new char[tspath.length() + 1];
2073 strcpy(templ, tspath.c_str());
2075 m_timeshift_fd = mkstemp(templ);
2076 m_timeshift_file = std::string(templ);
2078 eDebug("recording to %s", templ);
2082 if (m_timeshift_fd < 0)
2088 m_record->setTargetFD(m_timeshift_fd);
2090 m_timeshift_enabled = 1;
2092 updateTimeshiftPids();
2098 RESULT eDVBServicePlay::stopTimeshift()
2100 if (!m_timeshift_enabled)
2105 m_timeshift_enabled = 0;
2110 close(m_timeshift_fd);
2111 eDebug("remove timeshift file");
2112 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2117 int eDVBServicePlay::isTimeshiftActive()
2119 return m_timeshift_enabled && m_timeshift_active;
2122 RESULT eDVBServicePlay::activateTimeshift()
2124 if (!m_timeshift_enabled)
2127 if (!m_timeshift_active)
2129 switchToTimeshift();
2136 PyObject *eDVBServicePlay::getCutList()
2138 ePyObject list = PyList_New(0);
2140 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2142 ePyObject tuple = PyTuple_New(2);
2143 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2144 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2145 PyList_Append(list, tuple);
2152 void eDVBServicePlay::setCutList(ePyObject list)
2154 if (!PyList_Check(list))
2156 int size = PyList_Size(list);
2159 m_cue_entries.clear();
2161 for (i=0; i<size; ++i)
2163 ePyObject tuple = PyList_GET_ITEM(list, i);
2164 if (!PyTuple_Check(tuple))
2166 eDebug("non-tuple in cutlist");
2169 if (PyTuple_Size(tuple) != 2)
2171 eDebug("cutlist entries need to be a 2-tuple");
2174 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2175 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2177 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2180 pts_t pts = PyLong_AsLongLong(ppts);
2181 int type = PyInt_AsLong(ptype);
2182 m_cue_entries.insert(cueEntry(pts, type));
2183 eDebug("adding %08llx, %d", pts, type);
2185 m_cuesheet_changed = 1;
2187 cutlistToCuesheet();
2188 m_event((iPlayableService*)this, evCuesheetChanged);
2191 void eDVBServicePlay::setCutListEnable(int enable)
2193 m_cutlist_enabled = enable;
2194 cutlistToCuesheet();
2197 void eDVBServicePlay::updateTimeshiftPids()
2202 eDVBServicePMTHandler::program program;
2203 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2205 if (h.getProgramInfo(program))
2209 std::set<int> pids_to_record;
2210 pids_to_record.insert(0); // PAT
2211 if (program.pmtPid != -1)
2212 pids_to_record.insert(program.pmtPid); // PMT
2214 if (program.textPid != -1)
2215 pids_to_record.insert(program.textPid); // Videotext
2217 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2218 i(program.videoStreams.begin());
2219 i != program.videoStreams.end(); ++i)
2220 pids_to_record.insert(i->pid);
2222 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2223 i(program.audioStreams.begin());
2224 i != program.audioStreams.end(); ++i)
2225 pids_to_record.insert(i->pid);
2227 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2228 i(program.subtitleStreams.begin());
2229 i != program.subtitleStreams.end(); ++i)
2230 pids_to_record.insert(i->pid);
2232 std::set<int> new_pids, obsolete_pids;
2234 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2235 m_pids_active.begin(), m_pids_active.end(),
2236 std::inserter(new_pids, new_pids.begin()));
2238 std::set_difference(
2239 m_pids_active.begin(), m_pids_active.end(),
2240 pids_to_record.begin(), pids_to_record.end(),
2241 std::inserter(new_pids, new_pids.begin())
2244 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2245 m_record->addPID(*i);
2247 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2248 m_record->removePID(*i);
2252 void eDVBServicePlay::switchToLive()
2254 if (!m_timeshift_active)
2257 eDebug("SwitchToLive");
2262 m_teletext_parser = 0;
2264 m_subtitle_parser = 0;
2265 m_new_dvb_subtitle_page_connection = 0;
2266 m_new_subtitle_page_connection = 0;
2267 m_rds_decoder_event_connection = 0;
2268 m_video_event_connection = 0;
2269 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2271 /* free the timeshift service handler, we need the resources */
2272 m_service_handler_timeshift.free();
2273 m_timeshift_active = 0;
2274 m_timeshift_changed = 1;
2276 m_event((iPlayableService*)this, evSeekableStatusChanged);
2281 void eDVBServicePlay::switchToTimeshift()
2283 if (m_timeshift_active)
2288 m_teletext_parser = 0;
2290 m_subtitle_parser = 0;
2291 m_new_subtitle_page_connection = 0;
2292 m_new_dvb_subtitle_page_connection = 0;
2293 m_rds_decoder_event_connection = 0;
2294 m_video_event_connection = 0;
2296 m_timeshift_active = 1;
2297 m_timeshift_changed = 1;
2299 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2300 r.path = m_timeshift_file;
2302 m_cue = new eCueSheet();
2303 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2305 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2307 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2309 m_event((iPlayableService*)this, evSeekableStatusChanged);
2312 void eDVBServicePlay::updateDecoder()
2314 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2316 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2318 eDVBServicePMTHandler::program program;
2319 if (h.getProgramInfo(program))
2320 eDebug("getting program info failed.");
2323 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2324 if (!program.videoStreams.empty())
2326 eDebugNoNewLine(" (");
2327 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2328 i(program.videoStreams.begin());
2329 i != program.videoStreams.end(); ++i)
2336 if (i != program.videoStreams.begin())
2337 eDebugNoNewLine(", ");
2338 eDebugNoNewLine("%04x", i->pid);
2340 eDebugNoNewLine(")");
2342 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2343 if (!program.audioStreams.empty())
2345 eDebugNoNewLine(" (");
2346 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2347 i(program.audioStreams.begin());
2348 i != program.audioStreams.end(); ++i)
2350 if (i != program.audioStreams.begin())
2351 eDebugNoNewLine(", ");
2352 eDebugNoNewLine("%04x", i->pid);
2354 eDebugNoNewLine(")");
2356 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2357 pcrpid = program.pcrPid;
2358 eDebug(", and the text pid is %04x", program.textPid);
2359 tpid = program.textPid;
2364 h.getDecodeDemux(m_decode_demux);
2365 if (m_timeshift_changed)
2369 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2371 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2374 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2375 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2376 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2377 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2378 if (m_timeshift_changed)
2380 ePyObject subs = getCachedSubtitle();
2381 if (subs != Py_None)
2383 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2384 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2385 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2386 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2387 if (type == 0) // dvb
2388 m_subtitle_parser->start(pid, comp_page, anc_page);
2389 else if (type == 1) // ttx
2390 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2395 m_decoder->play(); /* pids will be set later */
2398 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2399 m_decoder->play(); /* pids will be set later. */
2402 m_timeshift_changed = 0;
2408 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2409 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2410 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2414 eServiceReferenceDVB ref;
2415 m_service_handler.getServiceReference(ref);
2416 eServiceReferenceDVB parent = ref.getParentServiceReference();
2421 ePtr<eDVBResourceManager> res_mgr;
2422 if (!eDVBResourceManager::getInstance(res_mgr))
2424 ePtr<iDVBChannelList> db;
2425 if (!res_mgr->getChannelList(db))
2427 ePtr<eDVBService> origService;
2428 if (!db->getService(parent, origService))
2430 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2431 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2438 std::string config_delay;
2439 int config_delay_int = 0;
2440 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2441 config_delay_int = atoi(config_delay.c_str());
2442 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2444 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2445 config_delay_int = atoi(config_delay.c_str());
2447 config_delay_int = 0;
2448 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2450 m_decoder->setVideoPID(vpid, vpidtype);
2451 selectAudioStream();
2453 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2454 m_decoder->setSyncPCR(pcrpid);
2456 m_decoder->setSyncPCR(-1);
2460 m_decoder->setTextPID(tpid);
2461 m_teletext_parser->start(program.textPid);
2464 if (vpid > 0 && vpid < 0x2000)
2468 std::string radio_pic;
2469 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2470 m_decoder->setRadioPic(radio_pic);
2474 m_decoder->setAudioChannel(achannel);
2476 /* don't worry about non-existing services, nor pvr services */
2479 /* (audio pid will be set in selectAudioTrack */
2480 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2481 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2482 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2483 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2486 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2489 void eDVBServicePlay::loadCuesheet()
2491 std::string filename = m_reference.path + ".cuts";
2493 m_cue_entries.clear();
2495 FILE *f = fopen(filename.c_str(), "rb");
2499 eDebug("loading cuts..");
2502 unsigned long long where;
2505 if (!fread(&where, sizeof(where), 1, f))
2507 if (!fread(&what, sizeof(what), 1, f))
2510 #if BYTE_ORDER == LITTLE_ENDIAN
2511 where = bswap_64(where);
2518 m_cue_entries.insert(cueEntry(where, what));
2521 eDebug("%d entries", m_cue_entries.size());
2523 eDebug("cutfile not found!");
2525 m_cuesheet_changed = 0;
2526 cutlistToCuesheet();
2527 m_event((iPlayableService*)this, evCuesheetChanged);
2530 void eDVBServicePlay::saveCuesheet()
2532 std::string filename = m_reference.path + ".cuts";
2534 FILE *f = fopen(filename.c_str(), "wb");
2538 unsigned long long where;
2541 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2543 #if BYTE_ORDER == BIG_ENDIAN
2546 where = bswap_64(i->where);
2548 what = htonl(i->what);
2549 fwrite(&where, sizeof(where), 1, f);
2550 fwrite(&what, sizeof(what), 1, f);
2556 m_cuesheet_changed = 0;
2559 void eDVBServicePlay::cutlistToCuesheet()
2563 eDebug("no cue sheet");
2568 if (!m_cutlist_enabled)
2570 m_cue->commitSpans();
2571 eDebug("cutlists were disabled");
2575 pts_t in = 0, out = 0, length = 0;
2579 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2581 int have_any_span = 0;
2585 if (i == m_cue_entries.end())
2591 if (i->what == 0) /* in */
2595 } else if (i->what == 1) /* out */
2597 else /* mark (2) or last play position (3) */
2616 m_cue->addSourceSpan(in, out);
2621 if (i == m_cue_entries.end())
2624 m_cue->commitSpans();
2627 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2629 if (m_subtitle_widget)
2630 disableSubtitles(parent);
2633 int tuplesize = PyTuple_Size(tuple);
2636 if (!PyTuple_Check(tuple))
2642 entry = PyTuple_GET_ITEM(tuple, 0);
2644 if (!PyInt_Check(entry))
2647 type = PyInt_AsLong(entry);
2649 if (type == 1) // teletext subtitles
2651 int page, magazine, pid;
2655 if (!m_teletext_parser)
2657 eDebug("enable teletext subtitles.. no parser !!!");
2661 entry = PyTuple_GET_ITEM(tuple, 1);
2662 if (!PyInt_Check(entry))
2664 pid = PyInt_AsLong(entry);
2666 entry = PyTuple_GET_ITEM(tuple, 2);
2667 if (!PyInt_Check(entry))
2669 page = PyInt_AsLong(entry);
2671 entry = PyTuple_GET_ITEM(tuple, 3);
2672 if (!PyInt_Check(entry))
2674 magazine = PyInt_AsLong(entry);
2676 m_subtitle_widget = new eSubtitleWidget(parent);
2677 m_subtitle_widget->resize(parent->size()); /* full size */
2678 m_teletext_parser->setPageAndMagazine(page, magazine);
2680 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2684 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2685 if (!m_subtitle_parser)
2687 eDebug("enable dvb subtitles.. no parser !!!");
2693 entry = PyTuple_GET_ITEM(tuple, 1);
2694 if (!PyInt_Check(entry))
2696 pid = PyInt_AsLong(entry);
2698 entry = PyTuple_GET_ITEM(tuple, 2);
2699 if (!PyInt_Check(entry))
2701 composition_page_id = PyInt_AsLong(entry);
2703 entry = PyTuple_GET_ITEM(tuple, 3);
2704 if (!PyInt_Check(entry))
2706 ancillary_page_id = PyInt_AsLong(entry);
2708 m_subtitle_widget = new eSubtitleWidget(parent);
2709 m_subtitle_widget->resize(parent->size()); /* full size */
2710 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2712 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2718 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2719 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2720 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2724 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2726 delete m_subtitle_widget;
2727 m_subtitle_widget = 0;
2728 if (m_subtitle_parser)
2730 m_subtitle_parser->stop();
2731 m_dvb_subtitle_pages.clear();
2733 if (m_teletext_parser)
2735 m_teletext_parser->setPageAndMagazine(-1, -1);
2736 m_subtitle_pages.clear();
2739 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2743 PyObject *eDVBServicePlay::getCachedSubtitle()
2747 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2750 unsigned int data = (unsigned int)tmp;
2751 int pid = (data&0xFFFF0000)>>16;
2752 ePyObject tuple = PyTuple_New(4);
2753 eDVBServicePMTHandler::program program;
2754 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2755 if (!h.getProgramInfo(program))
2757 if (program.textPid==pid) // teletext
2758 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2760 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2761 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2762 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2763 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2771 PyObject *eDVBServicePlay::getSubtitleList()
2773 if (!m_teletext_parser)
2776 ePyObject l = PyList_New(0);
2777 std::set<int> added_ttx_pages;
2779 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2780 m_teletext_parser->m_found_subtitle_pages;
2782 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2783 eDVBServicePMTHandler::program program;
2784 if (h.getProgramInfo(program))
2785 eDebug("getting program info failed.");
2788 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2789 it != program.subtitleStreams.end(); ++it)
2791 switch(it->subtitling_type)
2793 case 0x01: // ebu teletext subtitles
2795 int page_number = it->teletext_page_number & 0xFF;
2796 int magazine_number = it->teletext_magazine_number & 7;
2797 int hash = magazine_number << 8 | page_number;
2798 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2800 ePyObject tuple = PyTuple_New(5);
2801 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2802 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2803 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2804 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2805 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2806 PyList_Append(l, tuple);
2808 added_ttx_pages.insert(hash);
2813 case 0x20 ... 0x23: // dvb subtitles
2815 ePyObject tuple = PyTuple_New(5);
2816 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2817 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2818 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2819 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2820 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2821 PyList_Insert(l, 0, tuple);
2829 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2830 it != subs.end(); ++it)
2832 int page_number = it->teletext_page_number & 0xFF;
2833 int magazine_number = it->teletext_magazine_number & 7;
2834 int hash = magazine_number << 8 | page_number;
2835 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2837 ePyObject tuple = PyTuple_New(5);
2838 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2839 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2840 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2841 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2842 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2843 PyList_Append(l, tuple);
2851 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2853 if (m_subtitle_widget)
2857 m_decoder->getPTS(0, pos);
2858 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2859 m_subtitle_pages.push_back(page);
2860 checkSubtitleTiming();
2864 void eDVBServicePlay::checkSubtitleTiming()
2866 eDebug("checkSubtitleTiming");
2867 if (!m_subtitle_widget)
2871 enum { TELETEXT, DVB } type;
2872 eDVBTeletextSubtitlePage page;
2873 eDVBSubtitlePage dvb_page;
2875 if (!m_subtitle_pages.empty())
2877 page = m_subtitle_pages.front();
2879 show_time = page.m_pts;
2881 else if (!m_dvb_subtitle_pages.empty())
2883 dvb_page = m_dvb_subtitle_pages.front();
2885 show_time = dvb_page.m_show_time;
2893 m_decoder->getPTS(0, pos);
2895 eDebug("%lld %lld", pos, show_time);
2896 int diff = show_time - pos;
2897 if (type == TELETEXT && !page.m_have_pts)
2899 eDebug("ttx subtitle page without pts... immediate show");
2904 eDebug("[late (%d ms)]", -diff / 90);
2907 if (abs(diff) > 1800000)
2909 eDebug("[invalid]... immediate show!");
2914 if (type == TELETEXT)
2916 eDebug("display teletext subtitle page %lld", show_time);
2917 m_subtitle_widget->setPage(page);
2918 m_subtitle_pages.pop_front();
2922 eDebug("display dvb subtitle Page %lld", show_time);
2923 m_subtitle_widget->setPage(dvb_page);
2924 m_dvb_subtitle_pages.pop_front();
2928 eDebug("start subtitle delay %d", diff / 90);
2929 m_subtitle_sync_timer->start(diff / 90, 1);
2935 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2937 if (m_subtitle_widget)
2941 m_decoder->getPTS(0, pos);
2942 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2943 m_dvb_subtitle_pages.push_back(p);
2944 checkSubtitleTiming();
2948 int eDVBServicePlay::getAC3Delay()
2951 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2953 return m_decoder->getAC3Delay();
2958 int eDVBServicePlay::getPCMDelay()
2961 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2963 return m_decoder->getPCMDelay();
2968 void eDVBServicePlay::setAC3Delay(int delay)
2971 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2973 m_decoder->setAC3Delay(delay);
2976 void eDVBServicePlay::setPCMDelay(int delay)
2979 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2981 m_decoder->setPCMDelay(delay);
2984 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2986 switch(event.type) {
2987 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2988 m_event((iPlayableService*)this, evVideoSizeChanged);
2990 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2991 m_event((iPlayableService*)this, evVideoFramerateChanged);
2993 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2994 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3001 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3007 PyObject *eDVBServicePlay::getStreamingData()
3009 eDVBServicePMTHandler::program program;
3010 if (m_service_handler.getProgramInfo(program))
3015 ePyObject r = program.createPythonObject();
3016 ePtr<iDVBDemux> demux;
3017 if (!m_service_handler.getDataDemux(demux))
3020 if (!demux->getCADemuxID(demux_id))
3021 PutToDict(r, "demux", demux_id);
3028 DEFINE_REF(eDVBServicePlay)
3030 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3034 case iServiceInformation::sTransponderData:
3035 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3039 return iStaticServiceInformation::getInfoObject(ref, w);
3042 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");