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");
1798 /* 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 */
1799 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1802 ePtr<iDVBDemux> data_demux;
1803 if (!h.getDataDemux(data_demux))
1805 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1806 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1810 /* if we decided that we need one, update the pid */
1812 m_rds_decoder->start(apid);
1814 /* store new pid as default only when:
1815 a.) we have an entry in the service db for the current service,
1816 b.) we are not playing back something,
1817 c.) we are not selecting the default entry. (we wouldn't change
1818 anything in the best case, or destroy the default setting in
1819 case the real default is not yet available.)
1821 if (m_dvb_service && ((i != -1)
1822 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1824 if (apidtype == eDVBAudio::aMPEG)
1826 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1827 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1829 else if (apidtype == eDVBAudio::aAC3)
1831 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1832 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1836 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1837 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1841 h.resetCachedProgram();
1846 int eDVBServicePlay::getCurrentChannel()
1848 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1851 RESULT eDVBServicePlay::selectChannel(int i)
1853 if (i < LEFT || i > RIGHT || i == STEREO)
1856 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1858 m_decoder->setAudioChannel(i);
1862 std::string eDVBServicePlay::getText(int x)
1868 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1870 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1875 void eDVBServicePlay::rdsDecoderEvent(int what)
1879 case eDVBRdsDecoder::RadioTextChanged:
1880 m_event((iPlayableService*)this, evUpdatedRadioText);
1882 case eDVBRdsDecoder::RtpTextChanged:
1883 m_event((iPlayableService*)this, evUpdatedRtpText);
1885 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1886 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1888 case eDVBRdsDecoder::RecvRassSlidePic:
1889 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1894 void eDVBServicePlay::showRassSlidePicture()
1900 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1901 if (rass_slide_pic.length())
1902 m_decoder->showSinglePic(rass_slide_pic.c_str());
1904 eDebug("empty filename for rass slide picture received!!");
1907 eDebug("no MPEG Decoder to show iframes avail");
1910 eDebug("showRassSlidePicture called.. but not decoder");
1913 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1919 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1920 if (rass_interactive_pic.length())
1921 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1923 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1926 eDebug("no MPEG Decoder to show iframes avail");
1929 eDebug("showRassInteractivePic called.. but not decoder");
1932 ePyObject eDVBServicePlay::getRassInteractiveMask()
1935 return m_rds_decoder->getRassPictureMask();
1939 int eDVBServiceBase::getFrontendInfo(int w)
1941 eUsePtr<iDVBChannel> channel;
1942 if(m_service_handler.getChannel(channel))
1944 ePtr<iDVBFrontend> fe;
1945 if(channel->getFrontend(fe))
1947 return fe->readFrontendData(w);
1950 PyObject *eDVBServiceBase::getFrontendData()
1952 ePyObject ret = PyDict_New();
1955 eUsePtr<iDVBChannel> channel;
1956 if(!m_service_handler.getChannel(channel))
1958 ePtr<iDVBFrontend> fe;
1959 if(!channel->getFrontend(fe))
1960 fe->getFrontendData(ret);
1968 PyObject *eDVBServiceBase::getFrontendStatus()
1970 ePyObject ret = PyDict_New();
1973 eUsePtr<iDVBChannel> channel;
1974 if(!m_service_handler.getChannel(channel))
1976 ePtr<iDVBFrontend> fe;
1977 if(!channel->getFrontend(fe))
1978 fe->getFrontendStatus(ret);
1986 PyObject *eDVBServiceBase::getTransponderData(bool original)
1988 ePyObject ret = PyDict_New();
1991 eUsePtr<iDVBChannel> channel;
1992 if(!m_service_handler.getChannel(channel))
1994 ePtr<iDVBFrontend> fe;
1995 if(!channel->getFrontend(fe))
1996 fe->getTransponderData(ret, original);
2004 PyObject *eDVBServiceBase::getAll(bool original)
2006 ePyObject ret = getTransponderData(original);
2009 eUsePtr<iDVBChannel> channel;
2010 if(!m_service_handler.getChannel(channel))
2012 ePtr<iDVBFrontend> fe;
2013 if(!channel->getFrontend(fe))
2015 fe->getFrontendData(ret);
2016 fe->getFrontendStatus(ret);
2023 int eDVBServicePlay::getNumberOfSubservices()
2025 ePtr<eServiceEvent> evt;
2026 if (!m_event_handler.getEvent(evt, 0))
2027 return evt->getNumOfLinkageServices();
2031 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2033 ePtr<eServiceEvent> evt;
2034 if (!m_event_handler.getEvent(evt, 0))
2036 if (!evt->getLinkageService(sub, m_reference, n))
2039 sub.type=eServiceReference::idInvalid;
2043 RESULT eDVBServicePlay::startTimeshift()
2045 ePtr<iDVBDemux> demux;
2047 eDebug("Start timeshift!");
2049 if (m_timeshift_enabled)
2052 /* start recording with the data demux. */
2053 if (m_service_handler.getDataDemux(demux))
2056 demux->createTSRecorder(m_record);
2061 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2062 eDebug("could not query ts path");
2065 tspath.append("/timeshift.XXXXXX");
2067 templ = new char[tspath.length() + 1];
2068 strcpy(templ, tspath.c_str());
2070 m_timeshift_fd = mkstemp(templ);
2071 m_timeshift_file = std::string(templ);
2073 eDebug("recording to %s", templ);
2077 if (m_timeshift_fd < 0)
2083 m_record->setTargetFD(m_timeshift_fd);
2085 m_timeshift_enabled = 1;
2087 updateTimeshiftPids();
2093 RESULT eDVBServicePlay::stopTimeshift()
2095 if (!m_timeshift_enabled)
2100 m_timeshift_enabled = 0;
2105 close(m_timeshift_fd);
2106 eDebug("remove timeshift file");
2107 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2112 int eDVBServicePlay::isTimeshiftActive()
2114 return m_timeshift_enabled && m_timeshift_active;
2117 RESULT eDVBServicePlay::activateTimeshift()
2119 if (!m_timeshift_enabled)
2122 if (!m_timeshift_active)
2124 switchToTimeshift();
2131 PyObject *eDVBServicePlay::getCutList()
2133 ePyObject list = PyList_New(0);
2135 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2137 ePyObject tuple = PyTuple_New(2);
2138 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2139 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2140 PyList_Append(list, tuple);
2147 void eDVBServicePlay::setCutList(ePyObject list)
2149 if (!PyList_Check(list))
2151 int size = PyList_Size(list);
2154 m_cue_entries.clear();
2156 for (i=0; i<size; ++i)
2158 ePyObject tuple = PyList_GET_ITEM(list, i);
2159 if (!PyTuple_Check(tuple))
2161 eDebug("non-tuple in cutlist");
2164 if (PyTuple_Size(tuple) != 2)
2166 eDebug("cutlist entries need to be a 2-tuple");
2169 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2170 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2172 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2175 pts_t pts = PyLong_AsLongLong(ppts);
2176 int type = PyInt_AsLong(ptype);
2177 m_cue_entries.insert(cueEntry(pts, type));
2178 eDebug("adding %08llx, %d", pts, type);
2180 m_cuesheet_changed = 1;
2182 cutlistToCuesheet();
2183 m_event((iPlayableService*)this, evCuesheetChanged);
2186 void eDVBServicePlay::setCutListEnable(int enable)
2188 m_cutlist_enabled = enable;
2189 cutlistToCuesheet();
2192 void eDVBServicePlay::updateTimeshiftPids()
2197 eDVBServicePMTHandler::program program;
2198 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2200 if (h.getProgramInfo(program))
2204 std::set<int> pids_to_record;
2205 pids_to_record.insert(0); // PAT
2206 if (program.pmtPid != -1)
2207 pids_to_record.insert(program.pmtPid); // PMT
2209 if (program.textPid != -1)
2210 pids_to_record.insert(program.textPid); // Videotext
2212 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2213 i(program.videoStreams.begin());
2214 i != program.videoStreams.end(); ++i)
2215 pids_to_record.insert(i->pid);
2217 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2218 i(program.audioStreams.begin());
2219 i != program.audioStreams.end(); ++i)
2220 pids_to_record.insert(i->pid);
2222 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2223 i(program.subtitleStreams.begin());
2224 i != program.subtitleStreams.end(); ++i)
2225 pids_to_record.insert(i->pid);
2227 std::set<int> new_pids, obsolete_pids;
2229 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2230 m_pids_active.begin(), m_pids_active.end(),
2231 std::inserter(new_pids, new_pids.begin()));
2233 std::set_difference(
2234 m_pids_active.begin(), m_pids_active.end(),
2235 pids_to_record.begin(), pids_to_record.end(),
2236 std::inserter(new_pids, new_pids.begin())
2239 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2240 m_record->addPID(*i);
2242 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2243 m_record->removePID(*i);
2247 void eDVBServicePlay::switchToLive()
2249 if (!m_timeshift_active)
2252 eDebug("SwitchToLive");
2257 m_teletext_parser = 0;
2259 m_subtitle_parser = 0;
2260 m_new_dvb_subtitle_page_connection = 0;
2261 m_new_subtitle_page_connection = 0;
2262 m_rds_decoder_event_connection = 0;
2263 m_video_event_connection = 0;
2264 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2266 /* free the timeshift service handler, we need the resources */
2267 m_service_handler_timeshift.free();
2268 m_timeshift_active = 0;
2269 m_timeshift_changed = 1;
2271 m_event((iPlayableService*)this, evSeekableStatusChanged);
2276 void eDVBServicePlay::switchToTimeshift()
2278 if (m_timeshift_active)
2283 m_teletext_parser = 0;
2285 m_subtitle_parser = 0;
2286 m_new_subtitle_page_connection = 0;
2287 m_new_dvb_subtitle_page_connection = 0;
2288 m_rds_decoder_event_connection = 0;
2289 m_video_event_connection = 0;
2291 m_timeshift_active = 1;
2292 m_timeshift_changed = 1;
2294 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2295 r.path = m_timeshift_file;
2297 m_cue = new eCueSheet();
2298 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2300 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2302 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2304 m_event((iPlayableService*)this, evSeekableStatusChanged);
2307 void eDVBServicePlay::updateDecoder()
2309 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2311 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2313 eDVBServicePMTHandler::program program;
2314 if (h.getProgramInfo(program))
2315 eDebug("getting program info failed.");
2318 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2319 if (!program.videoStreams.empty())
2321 eDebugNoNewLine(" (");
2322 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2323 i(program.videoStreams.begin());
2324 i != program.videoStreams.end(); ++i)
2331 if (i != program.videoStreams.begin())
2332 eDebugNoNewLine(", ");
2333 eDebugNoNewLine("%04x", i->pid);
2335 eDebugNoNewLine(")");
2337 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2338 if (!program.audioStreams.empty())
2340 eDebugNoNewLine(" (");
2341 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2342 i(program.audioStreams.begin());
2343 i != program.audioStreams.end(); ++i)
2345 if (i != program.audioStreams.begin())
2346 eDebugNoNewLine(", ");
2347 eDebugNoNewLine("%04x", i->pid);
2349 eDebugNoNewLine(")");
2351 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2352 pcrpid = program.pcrPid;
2353 eDebug(", and the text pid is %04x", program.textPid);
2354 tpid = program.textPid;
2359 h.getDecodeDemux(m_decode_demux);
2360 if (m_timeshift_changed)
2364 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2366 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2369 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2370 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2371 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2372 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2373 if (m_timeshift_changed)
2375 ePyObject subs = getCachedSubtitle();
2376 if (subs != Py_None)
2378 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2379 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2380 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2381 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2382 if (type == 0) // dvb
2383 m_subtitle_parser->start(pid, comp_page, anc_page);
2384 else if (type == 1) // ttx
2385 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2390 m_decoder->play(); /* pids will be set later */
2393 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2394 m_decoder->play(); /* pids will be set later. */
2397 m_timeshift_changed = 0;
2403 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2404 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2405 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2409 eServiceReferenceDVB ref;
2410 m_service_handler.getServiceReference(ref);
2411 eServiceReferenceDVB parent = ref.getParentServiceReference();
2416 ePtr<eDVBResourceManager> res_mgr;
2417 if (!eDVBResourceManager::getInstance(res_mgr))
2419 ePtr<iDVBChannelList> db;
2420 if (!res_mgr->getChannelList(db))
2422 ePtr<eDVBService> origService;
2423 if (!db->getService(parent, origService))
2425 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2426 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2433 std::string config_delay;
2434 int config_delay_int = 0;
2435 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2436 config_delay_int = atoi(config_delay.c_str());
2437 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2439 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2440 config_delay_int = atoi(config_delay.c_str());
2442 config_delay_int = 0;
2443 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2445 m_decoder->setVideoPID(vpid, vpidtype);
2446 selectAudioStream();
2448 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2449 m_decoder->setSyncPCR(pcrpid);
2451 m_decoder->setSyncPCR(-1);
2455 m_decoder->setTextPID(tpid);
2456 m_teletext_parser->start(program.textPid);
2459 if (vpid > 0 && vpid < 0x2000)
2463 std::string radio_pic;
2464 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2465 m_decoder->setRadioPic(radio_pic);
2469 m_decoder->setAudioChannel(achannel);
2471 /* don't worry about non-existing services, nor pvr services */
2474 /* (audio pid will be set in selectAudioTrack */
2475 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2476 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2477 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2478 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2481 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2484 void eDVBServicePlay::loadCuesheet()
2486 std::string filename = m_reference.path + ".cuts";
2488 m_cue_entries.clear();
2490 FILE *f = fopen(filename.c_str(), "rb");
2494 eDebug("loading cuts..");
2497 unsigned long long where;
2500 if (!fread(&where, sizeof(where), 1, f))
2502 if (!fread(&what, sizeof(what), 1, f))
2505 #if BYTE_ORDER == LITTLE_ENDIAN
2506 where = bswap_64(where);
2513 m_cue_entries.insert(cueEntry(where, what));
2516 eDebug("%d entries", m_cue_entries.size());
2518 eDebug("cutfile not found!");
2520 m_cuesheet_changed = 0;
2521 cutlistToCuesheet();
2522 m_event((iPlayableService*)this, evCuesheetChanged);
2525 void eDVBServicePlay::saveCuesheet()
2527 std::string filename = m_reference.path + ".cuts";
2529 FILE *f = fopen(filename.c_str(), "wb");
2533 unsigned long long where;
2536 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2538 #if BYTE_ORDER == BIG_ENDIAN
2541 where = bswap_64(i->where);
2543 what = htonl(i->what);
2544 fwrite(&where, sizeof(where), 1, f);
2545 fwrite(&what, sizeof(what), 1, f);
2551 m_cuesheet_changed = 0;
2554 void eDVBServicePlay::cutlistToCuesheet()
2558 eDebug("no cue sheet");
2563 if (!m_cutlist_enabled)
2565 m_cue->commitSpans();
2566 eDebug("cutlists were disabled");
2570 pts_t in = 0, out = 0, length = 0;
2574 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2576 int have_any_span = 0;
2580 if (i == m_cue_entries.end())
2586 if (i->what == 0) /* in */
2590 } else if (i->what == 1) /* out */
2592 else /* mark (2) or last play position (3) */
2611 m_cue->addSourceSpan(in, out);
2616 if (i == m_cue_entries.end())
2619 m_cue->commitSpans();
2622 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2624 if (m_subtitle_widget)
2625 disableSubtitles(parent);
2628 int tuplesize = PyTuple_Size(tuple);
2631 if (!PyTuple_Check(tuple))
2637 entry = PyTuple_GET_ITEM(tuple, 0);
2639 if (!PyInt_Check(entry))
2642 type = PyInt_AsLong(entry);
2644 if (type == 1) // teletext subtitles
2646 int page, magazine, pid;
2650 if (!m_teletext_parser)
2652 eDebug("enable teletext subtitles.. no parser !!!");
2656 entry = PyTuple_GET_ITEM(tuple, 1);
2657 if (!PyInt_Check(entry))
2659 pid = PyInt_AsLong(entry);
2661 entry = PyTuple_GET_ITEM(tuple, 2);
2662 if (!PyInt_Check(entry))
2664 page = PyInt_AsLong(entry);
2666 entry = PyTuple_GET_ITEM(tuple, 3);
2667 if (!PyInt_Check(entry))
2669 magazine = PyInt_AsLong(entry);
2671 m_subtitle_widget = new eSubtitleWidget(parent);
2672 m_subtitle_widget->resize(parent->size()); /* full size */
2673 m_teletext_parser->setPageAndMagazine(page, magazine);
2675 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2679 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2680 if (!m_subtitle_parser)
2682 eDebug("enable dvb subtitles.. no parser !!!");
2688 entry = PyTuple_GET_ITEM(tuple, 1);
2689 if (!PyInt_Check(entry))
2691 pid = PyInt_AsLong(entry);
2693 entry = PyTuple_GET_ITEM(tuple, 2);
2694 if (!PyInt_Check(entry))
2696 composition_page_id = PyInt_AsLong(entry);
2698 entry = PyTuple_GET_ITEM(tuple, 3);
2699 if (!PyInt_Check(entry))
2701 ancillary_page_id = PyInt_AsLong(entry);
2703 m_subtitle_widget = new eSubtitleWidget(parent);
2704 m_subtitle_widget->resize(parent->size()); /* full size */
2705 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2707 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2713 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2714 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2715 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2719 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2721 delete m_subtitle_widget;
2722 m_subtitle_widget = 0;
2723 if (m_subtitle_parser)
2725 m_subtitle_parser->stop();
2726 m_dvb_subtitle_pages.clear();
2728 if (m_teletext_parser)
2730 m_teletext_parser->setPageAndMagazine(-1, -1);
2731 m_subtitle_pages.clear();
2734 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2738 PyObject *eDVBServicePlay::getCachedSubtitle()
2742 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2745 unsigned int data = (unsigned int)tmp;
2746 int pid = (data&0xFFFF0000)>>16;
2747 ePyObject tuple = PyTuple_New(4);
2748 eDVBServicePMTHandler::program program;
2749 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2750 if (!h.getProgramInfo(program))
2752 if (program.textPid==pid) // teletext
2753 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2755 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2756 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2757 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2758 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2766 PyObject *eDVBServicePlay::getSubtitleList()
2768 if (!m_teletext_parser)
2771 ePyObject l = PyList_New(0);
2772 std::set<int> added_ttx_pages;
2774 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2775 m_teletext_parser->m_found_subtitle_pages;
2777 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2778 eDVBServicePMTHandler::program program;
2779 if (h.getProgramInfo(program))
2780 eDebug("getting program info failed.");
2783 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2784 it != program.subtitleStreams.end(); ++it)
2786 switch(it->subtitling_type)
2788 case 0x01: // ebu teletext subtitles
2790 int page_number = it->teletext_page_number & 0xFF;
2791 int magazine_number = it->teletext_magazine_number & 7;
2792 int hash = magazine_number << 8 | page_number;
2793 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2795 ePyObject tuple = PyTuple_New(5);
2796 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2797 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2798 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2799 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2800 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2801 PyList_Append(l, tuple);
2803 added_ttx_pages.insert(hash);
2808 case 0x20 ... 0x23: // dvb subtitles
2810 ePyObject tuple = PyTuple_New(5);
2811 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2812 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2813 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2814 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2815 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2816 PyList_Insert(l, 0, tuple);
2824 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2825 it != subs.end(); ++it)
2827 int page_number = it->teletext_page_number & 0xFF;
2828 int magazine_number = it->teletext_magazine_number & 7;
2829 int hash = magazine_number << 8 | page_number;
2830 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2832 ePyObject tuple = PyTuple_New(5);
2833 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2834 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2835 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2836 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2837 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2838 PyList_Append(l, tuple);
2846 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2848 if (m_subtitle_widget)
2852 m_decoder->getPTS(0, pos);
2853 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2854 m_subtitle_pages.push_back(page);
2855 checkSubtitleTiming();
2859 void eDVBServicePlay::checkSubtitleTiming()
2861 eDebug("checkSubtitleTiming");
2862 if (!m_subtitle_widget)
2866 enum { TELETEXT, DVB } type;
2867 eDVBTeletextSubtitlePage page;
2868 eDVBSubtitlePage dvb_page;
2870 if (!m_subtitle_pages.empty())
2872 page = m_subtitle_pages.front();
2874 show_time = page.m_pts;
2876 else if (!m_dvb_subtitle_pages.empty())
2878 dvb_page = m_dvb_subtitle_pages.front();
2880 show_time = dvb_page.m_show_time;
2888 m_decoder->getPTS(0, pos);
2890 eDebug("%lld %lld", pos, show_time);
2891 int diff = show_time - pos;
2892 if (type == TELETEXT && !page.m_have_pts)
2894 eDebug("ttx subtitle page without pts... immediate show");
2899 eDebug("[late (%d ms)]", -diff / 90);
2902 if (abs(diff) > 1800000)
2904 eDebug("[invalid]... immediate show!");
2909 if (type == TELETEXT)
2911 eDebug("display teletext subtitle page %lld", show_time);
2912 m_subtitle_widget->setPage(page);
2913 m_subtitle_pages.pop_front();
2917 eDebug("display dvb subtitle Page %lld", show_time);
2918 m_subtitle_widget->setPage(dvb_page);
2919 m_dvb_subtitle_pages.pop_front();
2923 eDebug("start subtitle delay %d", diff / 90);
2924 m_subtitle_sync_timer->start(diff / 90, 1);
2930 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2932 if (m_subtitle_widget)
2936 m_decoder->getPTS(0, pos);
2937 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2938 m_dvb_subtitle_pages.push_back(p);
2939 checkSubtitleTiming();
2943 int eDVBServicePlay::getAC3Delay()
2946 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2948 return m_decoder->getAC3Delay();
2953 int eDVBServicePlay::getPCMDelay()
2956 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2958 return m_decoder->getPCMDelay();
2963 void eDVBServicePlay::setAC3Delay(int delay)
2966 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2968 m_decoder->setAC3Delay(delay);
2971 void eDVBServicePlay::setPCMDelay(int delay)
2974 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2976 m_decoder->setPCMDelay(delay);
2979 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2981 switch(event.type) {
2982 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2983 m_event((iPlayableService*)this, evVideoSizeChanged);
2985 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2986 m_event((iPlayableService*)this, evVideoFramerateChanged);
2988 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2989 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2996 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3002 PyObject *eDVBServicePlay::getStreamingData()
3004 eDVBServicePMTHandler::program program;
3005 if (m_service_handler.getProgramInfo(program))
3010 ePyObject r = program.createPythonObject();
3011 ePtr<iDVBDemux> demux;
3012 if (!m_service_handler.getDataDemux(demux))
3015 if (!demux->getCADemuxID(demux_id))
3016 PutToDict(r, "demux", demux_id);
3023 DEFINE_REF(eDVBServicePlay)
3025 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3029 case iServiceInformation::sTransponderData:
3030 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3034 return iStaticServiceInformation::getInfoObject(ref, w);
3037 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");