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
20 #include <lib/base/httpstream.h>
22 #include <lib/service/servicedvbfcc.h>
25 #include <lib/gui/esubtitle.h>
31 #include <netinet/in.h>
33 #include <lib/dvb/fcc.h>
36 #error no byte order defined!
39 class eStaticServiceDVBInformation: public iStaticServiceInformation
41 DECLARE_REF(eStaticServiceDVBInformation);
43 RESULT getName(const eServiceReference &ref, std::string &name);
44 int getLength(const eServiceReference &ref);
45 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
46 PyObject *getInfoObject(const eServiceReference &ref, int);
49 DEFINE_REF(eStaticServiceDVBInformation);
51 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
53 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
54 if ( !ref.name.empty() )
56 if (service.getParentTransportStreamID().get()) // linkage subservice
58 ePtr<iServiceHandler> service_center;
59 if (!eServiceCenter::getInstance(service_center))
61 eServiceReferenceDVB parent = service;
62 parent.setTransportStreamID( service.getParentTransportStreamID() );
63 parent.setServiceID( service.getParentServiceID() );
64 parent.setParentTransportStreamID(eTransportStreamID(0));
65 parent.setParentServiceID(eServiceID(0));
67 ePtr<iStaticServiceInformation> service_info;
68 if (!service_center->info(parent, service_info))
70 if (!service_info->getName(parent, name))
71 name=buildShortName(name) + " - ";
84 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
89 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
91 ePtr<eDVBResourceManager> res_mgr;
92 if ( eDVBResourceManager::getInstance( res_mgr ) )
93 eDebug("isPlayable... no res manager!!");
96 eDVBChannelID chid, chid_ignore;
98 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
99 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
100 return res_mgr->canAllocateChannel(chid, chid_ignore, system);
105 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
106 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
107 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
108 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
110 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
112 if (r.type == eServiceReference::idDVB)
114 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
117 case iServiceInformation::sTransponderData:
119 ePtr<eDVBResourceManager> res;
120 if (!eDVBResourceManager::getInstance(res))
122 ePtr<iDVBChannelList> db;
123 if (!res->getChannelList(db))
126 ref.getChannelID(chid);
127 ePtr<iDVBFrontendParameters> feparm;
128 if (!db->getChannelFrontendData(chid, feparm))
131 if (!feparm->getSystem(system))
133 ePyObject dict = PyDict_New();
136 case iDVBFrontend::feSatellite:
138 eDVBFrontendParametersSatellite s;
140 PutSatelliteDataToDict(dict, s);
143 case iDVBFrontend::feTerrestrial:
145 eDVBFrontendParametersTerrestrial t;
147 PutTerrestrialDataToDict(dict, t);
150 case iDVBFrontend::feCable:
152 eDVBFrontendParametersCable c;
154 PutCableDataToDict(dict, c);
158 eDebug("unknown frontend type %d", system);
173 DEFINE_REF(eStaticServiceDVBBouquetInformation);
175 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
177 ePtr<iDVBChannelList> db;
178 ePtr<eDVBResourceManager> res;
181 if ((err = eDVBResourceManager::getInstance(res)) != 0)
183 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
186 if ((err = res->getChannelList(db)) != 0)
188 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
193 if ((err = db->getBouquet(ref, bouquet)) != 0)
195 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
199 if ( bouquet && bouquet->m_bouquet_name.length() )
201 name = bouquet->m_bouquet_name;
208 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
210 if (ref.flags & eServiceReference::isGroup)
212 ePtr<iDVBChannelList> db;
213 ePtr<eDVBResourceManager> res;
215 if (eDVBResourceManager::getInstance(res))
217 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
221 if (res->getChannelList(db))
223 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
228 if (db->getBouquet(ref, bouquet))
230 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
234 int prio_order = eDVBFrontend::getTypePriorityOrder();
236 eDVBChannelID chid, chid_ignore;
237 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
238 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
240 static unsigned char prio_map[6][3] = {
241 { 3, 2, 1 }, // -S -C -T
242 { 3, 1, 2 }, // -S -T -C
243 { 2, 3, 1 }, // -C -S -T
244 { 1, 3, 2 }, // -C -T -S
245 { 1, 2, 3 }, // -T -C -S
246 { 2, 1, 3 } // -T -S -C
249 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
250 int tmp = res->canAllocateChannel(chid, chid_ignore, system, simulate);
255 case iDVBFrontend::feTerrestrial:
256 tmp = prio_map[prio_order][2];
258 case iDVBFrontend::feCable:
259 tmp = prio_map[prio_order][1];
262 case iDVBFrontend::feSatellite:
263 tmp = prio_map[prio_order][0];
269 m_playable_service = *it;
276 m_playable_service = eServiceReference();
280 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
285 #include <lib/dvb/epgcache.h>
287 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
289 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
292 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
294 DECLARE_REF(eStaticServiceDVBPVRInformation);
295 eServiceReference m_ref;
296 eDVBMetaParser m_parser;
298 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
299 RESULT getName(const eServiceReference &ref, std::string &name);
300 int getLength(const eServiceReference &ref);
301 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
302 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
303 int getInfo(const eServiceReference &ref, int w);
304 std::string getInfoString(const eServiceReference &ref,int w);
305 PyObject *getInfoObject(const eServiceReference &r, int what);
308 DEFINE_REF(eStaticServiceDVBPVRInformation);
310 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
313 m_parser.parseFile(ref.path);
316 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
318 ASSERT(ref == m_ref);
319 if (!ref.name.empty())
321 else if (!m_parser.m_name.empty())
322 name = m_parser.m_name;
326 size_t n = name.rfind('/');
327 if (n != std::string::npos)
328 name = name.substr(n + 1);
333 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
335 ASSERT(ref == m_ref);
340 stat(ref.path.c_str(), &s);
342 if (tstools.openFile(ref.path.c_str(), 1))
345 /* check if cached data is still valid */
346 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
347 return m_parser.m_length / 90000;
349 /* open again, this time with stream info */
350 if (tstools.openFile(ref.path.c_str()))
353 /* otherwise, re-calc length and update meta file */
355 if (tstools.calcLen(len))
358 m_parser.m_length = len;
359 m_parser.m_filesize = s.st_size;
360 m_parser.updateMeta(ref.path);
361 return m_parser.m_length / 90000;
364 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
368 case iServiceInformation::sDescription:
369 return iServiceInformation::resIsString;
370 case iServiceInformation::sServiceref:
371 return iServiceInformation::resIsString;
372 case iServiceInformation::sFileSize:
373 return m_parser.m_filesize;
374 case iServiceInformation::sTimeCreate:
375 if (m_parser.m_time_create)
376 return m_parser.m_time_create;
378 return iServiceInformation::resNA;
379 case iServiceInformation::sIsScrambled:
380 return m_parser.m_scrambled;
382 return iServiceInformation::resNA;
386 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
390 case iServiceInformation::sDescription:
391 return m_parser.m_description;
392 case iServiceInformation::sServiceref:
393 return m_parser.m_ref.toString();
394 case iServiceInformation::sTags:
395 return m_parser.m_tags;
401 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
405 case iServiceInformation::sFileSize:
406 return PyLong_FromLongLong(m_parser.m_filesize);
412 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
414 if (!ref.path.empty())
416 if (ref.path.substr(0, 7) == "http://")
418 eServiceReference equivalentref(ref);
419 /* this might be a scrambled stream (id + 0x100), force equivalent dvb type */
420 equivalentref.type = eServiceFactoryDVB::id;
421 equivalentref.path.clear();
422 return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
426 ePtr<eServiceEvent> event = new eServiceEvent;
427 std::string filename = ref.path;
428 filename.erase(filename.length()-2, 2);
430 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
441 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
443 DECLARE_REF(eDVBPVRServiceOfflineOperations);
444 eServiceReferenceDVB m_ref;
446 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
448 RESULT deleteFromDisk(int simulate);
449 RESULT getListOfFilenames(std::list<std::string> &);
453 DEFINE_REF(eDVBPVRServiceOfflineOperations);
455 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
459 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
465 std::list<std::string> res;
466 if (getListOfFilenames(res))
469 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
471 eDebug("FATAL !! can't get background file eraser");
473 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
475 eDebug("Removing %s...", i->c_str());
477 eraser->erase(i->c_str());
479 ::unlink(i->c_str());
486 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
489 res.push_back(m_ref.path);
491 // handling for old splitted recordings (enigma 1)
496 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
498 if (stat(buf, &s) < 0)
503 res.push_back(m_ref.path + ".meta");
504 res.push_back(m_ref.path + ".ap");
505 res.push_back(m_ref.path + ".sc");
506 res.push_back(m_ref.path + ".cuts");
507 std::string tmp = m_ref.path;
508 tmp.erase(m_ref.path.length()-3);
509 res.push_back(tmp + ".eit");
513 RESULT eDVBPVRServiceOfflineOperations::reindex()
515 const char *filename = m_ref.path.c_str();
516 eDebug("reindexing %s...", filename);
518 eMPEGStreamInformation info;
519 eMPEGStreamParserTS parser(info);
521 info.startSave(filename);
525 int err = f.open(m_ref.path.c_str(), 0);
530 off_t length = f.length();
531 unsigned char buffer[188*256*4];
534 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
535 int r = f.read(offset, buffer, sizeof(buffer));
541 parser.parseData(offset, buffer, r);
550 DEFINE_REF(eServiceFactoryDVB)
552 eServiceFactoryDVB::eServiceFactoryDVB()
554 ePtr<eServiceCenter> sc;
556 eServiceCenter::getPrivInstance(sc);
559 std::list<std::string> extensions;
560 extensions.push_back("ts");
561 extensions.push_back("trp");
562 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
565 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
566 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
569 eServiceFactoryDVB::~eServiceFactoryDVB()
571 ePtr<eServiceCenter> sc;
573 eServiceCenter::getPrivInstance(sc);
575 sc->removeServiceFactory(eServiceFactoryDVB::id);
578 DEFINE_REF(eDVBServiceList);
580 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
584 eDVBServiceList::~eDVBServiceList()
588 RESULT eDVBServiceList::startQuery()
590 ePtr<iDVBChannelList> db;
591 ePtr<eDVBResourceManager> res;
594 if ((err = eDVBResourceManager::getInstance(res)) != 0)
596 eDebug("no resource manager");
599 if ((err = res->getChannelList(db)) != 0)
601 eDebug("no channel list");
605 ePtr<eDVBChannelQuery> q;
607 if (!m_parent.path.empty())
609 eDVBChannelQuery::compile(q, m_parent.path);
612 eDebug("compile query failed");
617 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
619 eDebug("startQuery failed");
626 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
628 eServiceReferenceDVB ref;
633 while (!m_query->getNextResult(ref))
637 list.sort(iListableServiceCompare(this));
642 // The first argument of this function is a format string to specify the order and
643 // the content of the returned list
644 // useable format options are
645 // R = Service Reference (as swig object .. this is very slow)
646 // S = Service Reference (as python string object .. same as ref.toString())
647 // C = Service Reference (as python string object .. same as ref.toCompareString())
648 // N = Service Name (as python string object)
649 // n = Short Service Name (short name brakets used) (as python string object)
650 // when exactly one return value per service is selected in the format string,
651 // then each value is directly a list entry
652 // when more than one value is returned per service, then the list is a list of
654 // unknown format string chars are returned as python None values !
655 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
658 std::list<eServiceReference> tmplist;
661 if (!format || !(retcount=strlen(format)))
662 format = "R"; // just return service reference swig object ...
664 if (!getContent(tmplist, sorted))
666 int services=tmplist.size();
667 ePtr<iStaticServiceInformation> sptr;
668 eServiceCenterPtr service_center;
670 if (strchr(format, 'N') || strchr(format, 'n'))
671 eServiceCenter::getPrivInstance(service_center);
673 ret = PyList_New(services);
674 std::list<eServiceReference>::iterator it(tmplist.begin());
676 for (int cnt=0; cnt < services; ++cnt)
678 eServiceReference &ref=*it++;
679 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
680 for (int i=0; i < retcount; ++i)
685 case 'R': // service reference (swig)object
686 tmp = NEW_eServiceReference(ref);
688 case 'C': // service reference compare string
689 tmp = PyString_FromString(ref.toCompareString().c_str());
691 case 'S': // service reference string
692 tmp = PyString_FromString(ref.toString().c_str());
694 case 'N': // service name
697 service_center->info(ref, sptr);
701 sptr->getName(ref, name);
703 // filter short name brakets
705 while((pos = name.find("\xc2\x86")) != std::string::npos)
707 while((pos = name.find("\xc2\x87")) != std::string::npos)
711 tmp = PyString_FromString(name.c_str());
715 tmp = PyString_FromString("<n/a>");
717 case 'n': // short service name
720 service_center->info(ref, sptr);
724 sptr->getName(ref, name);
725 name = buildShortName(name);
727 tmp = PyString_FromString(name.c_str());
731 tmp = PyString_FromString("<n/a>");
744 PyTuple_SET_ITEM(tuple, i, tmp);
746 PyList_SET_ITEM(ret, cnt, tmp);
750 PyList_SET_ITEM(ret, cnt, tuple);
753 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
756 RESULT eDVBServiceList::getNext(eServiceReference &ref)
761 return m_query->getNextResult((eServiceReferenceDVB&)ref);
764 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
766 if (m_parent.flags & eServiceReference::canDescent) // bouquet
768 ePtr<iDVBChannelList> db;
769 ePtr<eDVBResourceManager> resm;
771 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
774 if (db->getBouquet(m_parent, m_bouquet) != 0)
785 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
789 return m_bouquet->addService(ref, before);
792 RESULT eDVBServiceList::removeService(eServiceReference &ref)
796 return m_bouquet->removeService(ref);
799 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
803 return m_bouquet->moveService(ref, pos);
806 RESULT eDVBServiceList::flushChanges()
810 return m_bouquet->flushChanges();
813 RESULT eDVBServiceList::setListName(const std::string &name)
817 return m_bouquet->setListName(name);
820 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
822 ePtr<eDVBService> service;
824 int r = lookupService(service, ref);
827 // check resources...
828 if (eFCCServiceManager::checkAvailable(ref))
829 ptr = new eDVBServiceFCCPlay(ref, service);
831 ptr = new eDVBServicePlay(ref, service);
835 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
837 bool isstream = ref.path.substr(0, 7) == "http://";
838 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref, isstream);
842 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
844 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
845 if (list->startQuery())
855 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
857 /* is a listable service? */
858 if (ref.flags & eServiceReference::canDescent) // bouquet
860 if ( !ref.name.empty() ) // satellites or providers list
861 ptr = m_StaticServiceDVBInfo;
862 else // a dvb bouquet
863 ptr = m_StaticServiceDVBBouquetInfo;
865 else if (!ref.path.empty()) /* do we have a PVR service? */
866 ptr = new eStaticServiceDVBPVRInformation(ref);
867 else // normal dvb service
869 ePtr<eDVBService> service;
870 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
871 ptr = m_StaticServiceDVBInfo;
873 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
879 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
881 if (ref.path.empty())
887 ptr = new eDVBPVRServiceOfflineOperations(ref);
892 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
894 if (!ref.path.empty()) // playback
896 eDVBMetaParser parser;
897 int ret=parser.parseFile(ref.path);
898 service = new eDVBService;
900 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
904 // TODO: handle the listing itself
905 // if (ref.... == -1) .. return "... bouquets ...";
906 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
908 ePtr<iDVBChannelList> db;
909 ePtr<eDVBResourceManager> res;
912 if ((err = eDVBResourceManager::getInstance(res)) != 0)
914 eDebug("no resource manager");
917 if ((err = res->getChannelList(db)) != 0)
919 eDebug("no channel list");
923 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
924 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
926 // eDebug("getService failed!");
934 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service, bool connect_event):
935 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
939 m_is_stream = m_reference.path.substr(0, 7) == "http://";
940 m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
942 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
943 m_skipmode = m_fastforward = m_slowmotion = 0;
946 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
948 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
949 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
951 m_cuesheet_changed = 0;
952 m_cutlist_enabled = 1;
954 m_subtitle_widget = 0;
958 m_subtitle_sync_timer = eTimer::create(eApp);
960 m_current_video_pid_type = 0;
966 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
969 eDVBServicePlay::~eDVBServicePlay()
974 int ret=meta.parseFile(m_reference.path);
978 meta.m_service_data="";
979 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
980 meta.m_service_data += tmp;
982 for (int x=0; x < eDVBService::cacheMax; ++x)
984 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
987 sprintf(tmp, ",c:%02d%04x", x, entry);
988 meta.m_service_data += tmp;
991 meta.updateMeta(m_reference.path);
994 delete m_subtitle_widget;
997 void eDVBServicePlay::gotNewEvent()
1001 ePtr<eServiceEvent> m_event_now, m_event_next;
1002 getEvent(m_event_now, 0);
1003 getEvent(m_event_next, 1);
1006 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1008 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1010 m_event((iPlayableService*)this, evUpdatedEventInfo);
1013 void eDVBServicePlay::serviceEvent(int event)
1015 m_tune_state = event;
1019 case eDVBServicePMTHandler::eventTuned:
1021 ePtr<iDVBDemux> m_demux;
1022 if (!m_service_handler.getDataDemux(m_demux))
1024 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1025 int sid = ref.getParentServiceID().get();
1027 sid = ref.getServiceID().get();
1028 if ( ref.getParentTransportStreamID().get() &&
1029 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1030 m_event_handler.startOther(m_demux, sid);
1032 m_event_handler.start(m_demux, sid);
1034 m_event((iPlayableService*)this, evTunedIn);
1037 case eDVBServicePMTHandler::eventNoResources:
1038 case eDVBServicePMTHandler::eventNoPAT:
1039 case eDVBServicePMTHandler::eventNoPATEntry:
1040 case eDVBServicePMTHandler::eventNoPMT:
1041 case eDVBServicePMTHandler::eventTuneFailed:
1042 case eDVBServicePMTHandler::eventMisconfiguration:
1044 eDebug("DVB service failed to tune - error %d", event);
1045 m_event((iPlayableService*)this, evTuneFailed);
1048 case eDVBServicePMTHandler::eventNewProgramInfo:
1050 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1051 if (m_timeshift_enabled)
1052 updateTimeshiftPids();
1053 if (!m_timeshift_active)
1055 if (m_first_program_info & 1 && m_is_pvr)
1057 m_first_program_info &= ~1;
1060 if (!m_timeshift_active)
1061 m_event((iPlayableService*)this, evUpdatedInfo);
1064 case eDVBServicePMTHandler::eventPreStart:
1067 case eDVBServicePMTHandler::eventEOF:
1068 m_event((iPlayableService*)this, evEOF);
1070 case eDVBServicePMTHandler::eventSOF:
1071 m_event((iPlayableService*)this, evSOF);
1073 case eDVBServicePMTHandler::eventHBBTVInfo:
1074 m_event((iPlayableService*)this, evHBBTVInfo);
1079 void eDVBServicePlay::serviceEventTimeshift(int event)
1083 case eDVBServicePMTHandler::eventNewProgramInfo:
1084 eDebug("eventNewProgramInfo TS");
1085 if (m_timeshift_active)
1088 if (m_first_program_info & 2)
1092 eDebug("re-apply slowmotion after timeshift file change");
1093 m_decoder->setSlowMotion(m_slowmotion);
1097 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1099 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1100 if (m_fastforward != 1)
1101 m_decoder->setFastForward(m_fastforward);
1103 m_decoder->setTrickmode();
1107 m_first_program_info &= ~2;
1109 m_event((iPlayableService*)this, evUpdatedInfo);
1112 case eDVBServicePMTHandler::eventSOF:
1114 if (!m_timeshift_file_next.empty())
1116 eDebug("timeshift SOF, switch to next file");
1119 m_first_program_info |= 2;
1121 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1122 r.path = m_timeshift_file_next;
1124 /* free the timeshift service handler, we need the resources */
1125 m_service_handler_timeshift.free();
1129 m_cue->seekTo(0, -1000);
1130 ePtr<iTsSource> source = createTsSource(r);
1131 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service, false); /* use the decoder demux for everything */
1133 m_event((iPlayableService*)this, evUser+1);
1137 m_event((iPlayableService*)this, evSOF);
1139 case eDVBServicePMTHandler::eventEOF:
1140 if ((!m_is_paused) && (m_skipmode >= 0))
1142 if (m_timeshift_file_next.empty())
1144 eDebug("timeshift EOF, so let's go live");
1149 eDebug("timeshift EOF, switch to next file");
1151 m_first_program_info |= 2;
1153 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1154 r.path = m_timeshift_file_next;
1156 /* free the timeshift service handler, we need the resources */
1157 m_service_handler_timeshift.free();
1160 ePtr<iTsSource> source = createTsSource(r);
1161 int use_decode_demux = 1;
1162 eDVBServicePMTHandler::serviceType type = eDVBServicePMTHandler::timeshift_playback;
1163 m_service_handler_timeshift.tuneExt(r, use_decode_demux, source, m_timeshift_file_next.c_str(), m_cue, 0, m_dvb_service, type, false); /* use the decoder demux for everything */
1165 m_event((iPlayableService*)this, evUser+1);
1169 case eDVBServicePMTHandler::eventNoDiskSpace:
1170 eDebug("No space!");
1171 m_event((iPlayableService*)this, evUser+3);
1176 RESULT eDVBServicePlay::start()
1178 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1179 bool scrambled = true;
1180 eDVBServicePMTHandler::serviceType type = eDVBServicePMTHandler::livetv;
1182 int use_decode_demux = 0;
1184 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1185 two (one for decoding, one for data source), as we must be prepared
1186 to start recording from the data demux. */
1189 use_decode_demux = 1;
1190 eDVBMetaParser meta;
1191 if (!meta.parseFile(m_reference.path))
1193 service = meta.m_ref;
1194 service.path = m_reference.path;
1195 scrambled = meta.m_scrambled;
1199 /* when there is no meta file we need to handle ts/m2ts as descrambled */
1202 m_cue = new eCueSheet();
1203 type = eDVBServicePMTHandler::playback;
1206 m_event(this, evStart);
1211 type = eDVBServicePMTHandler::streamclient;
1214 m_first_program_info = 1;
1215 ePtr<iTsSource> source = createTsSource(service);
1216 m_service_handler.tuneExt(service, use_decode_demux, source, service.path.c_str(), m_cue, false, m_dvb_service, type, scrambled);
1220 /* inject EIT if there is a stored one */
1221 std::string filename = service.path;
1222 filename.erase(filename.length()-2, 2);
1224 ePtr<eServiceEvent> event = new eServiceEvent;
1225 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1227 ePtr<eServiceEvent> empty;
1228 m_event_handler.inject(event, 0);
1229 m_event_handler.inject(empty, 1);
1231 m_event(this, evStart);
1236 RESULT eDVBServicePlay::stop()
1238 /* add bookmark for last play position */
1241 pts_t play_position, length;
1242 if (!getPlayPosition(play_position))
1244 /* remove last position */
1245 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1247 if (i->what == 3) /* current play position */
1249 m_cue_entries.erase(i);
1250 i = m_cue_entries.begin();
1256 if (getLength(length))
1261 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1263 m_cuesheet_changed = 1;
1267 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1269 m_service_handler_timeshift.free();
1270 m_service_handler.free();
1272 if (m_is_pvr && m_cuesheet_changed)
1275 /* save cuesheet only when main file is accessible. */
1276 if (!::stat(m_reference.path.c_str(), &s))
1279 m_event((iPlayableService*)this, evStopped);
1283 RESULT eDVBServicePlay::setTarget(int target)
1285 m_is_primary = !target;
1286 m_decoder_index = target;
1290 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1292 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1296 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1298 /* note: we check for timeshift to be enabled,
1299 not neccessary active. if you pause when timeshift
1300 is not active, you should activate it when unpausing */
1301 if ((!m_is_pvr) && (!m_timeshift_enabled))
1311 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1313 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1314 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1315 setFastForward_internal(0);
1318 m_slowmotion = ratio;
1319 return m_decoder->setSlowMotion(ratio);
1325 RESULT eDVBServicePlay::setFastForward(int ratio)
1327 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1329 return setFastForward_internal(ratio);
1332 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1334 int skipmode, ffratio, ret = 0;
1341 } else if (ratio > 0)
1349 } else // if (ratio < 0)
1355 if (m_skipmode != skipmode)
1357 eDebug("setting cue skipmode to %d", skipmode);
1360 long long _skipmode = skipmode;
1361 if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1364 _skipmode = skipmode * 3;
1366 _skipmode = skipmode * 4;
1369 m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1373 m_skipmode = skipmode;
1376 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1378 m_fastforward = ffratio;
1384 ; /* return m_decoder->play(); is done in caller*/
1385 else if (ffratio != 1)
1386 ret = m_decoder->setFastForward(ffratio);
1388 ret = m_decoder->setTrickmode();
1391 eDebug("final seek after trickplay ret %d", seekTo(pos));
1396 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1398 if (m_is_pvr || m_timeshift_enabled)
1408 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1409 RESULT eDVBServicePlay::getLength(pts_t &len)
1411 ePtr<iDVBPVRChannel> pvr_channel;
1413 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1416 return pvr_channel->getLength(len);
1419 RESULT eDVBServicePlay::pause()
1421 eDebug("eDVBServicePlay::pause");
1422 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1427 return m_decoder->pause();
1432 RESULT eDVBServicePlay::unpause()
1434 eDebug("eDVBServicePlay::unpause");
1435 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1440 return m_decoder->play();
1445 RESULT eDVBServicePlay::seekTo(pts_t to)
1447 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1449 if (!m_decode_demux)
1452 ePtr<iDVBPVRChannel> pvr_channel;
1454 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1460 m_cue->seekTo(0, to);
1461 m_dvb_subtitle_pages.clear();
1462 m_subtitle_pages.clear();
1467 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1469 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1471 if (!m_decode_demux)
1474 ePtr<iDVBPVRChannel> pvr_channel;
1476 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1481 /* HACK until we have skip-AP api */
1482 if ((to > 0) && (to < 100))
1490 m_cue->seekTo(mode, to);
1491 m_dvb_subtitle_pages.clear();
1492 m_subtitle_pages.clear();
1496 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1498 ePtr<iDVBPVRChannel> pvr_channel;
1500 if (!m_decode_demux)
1503 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1508 /* if there is a decoder, use audio or video PTS */
1511 r = m_decoder->getPTS(0, pos);
1517 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1520 RESULT eDVBServicePlay::setTrickmode(int trick)
1522 /* currently unimplemented */
1526 RESULT eDVBServicePlay::isCurrentlySeekable()
1531 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1532 if (m_decoder->getVideoProgressive() == -1)
1538 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1544 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1550 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1556 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1562 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1568 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1571 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1572 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1574 if (!m_timeshift_enabled)
1576 /* query config path */
1578 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1579 eDebug("could not query ts path from config");
1583 /* we need enough diskspace */
1585 if (statfs(tspath.c_str(), &fs) < 0)
1587 eDebug("statfs failed!");
1591 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1593 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1603 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1614 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1620 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1626 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1632 RESULT eDVBServicePlay::getName(std::string &name)
1636 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1637 return i->getName(m_reference, name);
1639 else if (m_is_stream)
1641 name = m_reference.name;
1644 name = m_reference.path;
1651 else if (m_dvb_service)
1653 m_dvb_service->getName(m_reference, name);
1657 else if (!m_reference.name.empty())
1658 eStaticServiceDVBInformation().getName(m_reference, name);
1660 name = "DVB service";
1664 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1666 return m_event_handler.getEvent(evt, nownext);
1669 int eDVBServicePlay::getInfo(int w)
1671 eDVBServicePMTHandler::program program;
1673 if (w == sCAIDs || w == sCAIDPIDs)
1674 return resIsPyObject;
1676 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1678 int no_program_info = 0;
1680 if (h.getProgramInfo(program))
1681 no_program_info = 1;
1687 return m_decoder->getVideoHeight();
1691 return m_decoder->getVideoWidth();
1695 return m_decoder->getVideoFrameRate();
1699 return m_decoder->getVideoProgressive();
1705 aspect = m_decoder->getVideoAspect();
1706 if (aspect == -1 && no_program_info)
1708 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1710 ePtr<eServiceEvent> evt;
1711 if (!m_event_handler.getEvent(evt, 0))
1713 ePtr<eComponentData> data;
1714 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1716 if ( data->getStreamContent() == 1 )
1718 switch(data->getComponentType())
1721 case 1: // 4:3 SD PAL
1723 case 3: // 16:9 SD PAL
1724 case 4: // > 16:9 PAL
1725 case 5: // 4:3 SD NTSC
1727 case 7: // 16:9 SD NTSC
1728 case 8: // > 16:9 NTSC
1731 case 9: // 4:3 HD PAL
1733 case 0xB: // 16:9 HD PAL
1734 case 0xC: // > 16:9 HD PAL
1735 case 0xD: // 4:3 HD NTSC
1737 case 0xF: // 16:9 HD NTSC
1738 case 0x10: // > 16:9 HD PAL
1739 return data->getComponentType();
1749 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1753 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1757 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1758 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1762 int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
1765 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1768 apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
1771 apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
1774 apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
1778 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1782 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1786 if (no_program_info) return -1; return program.pcrPid;
1787 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1788 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1789 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1790 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1791 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1792 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1793 case sProvider: if (!m_dvb_service) return -1; return -2;
1794 case sServiceref: return resIsString;
1795 case sDVBState: return m_tune_state;
1802 std::string eDVBServicePlay::getInfoString(int w)
1807 if (!m_dvb_service) return "";
1808 return m_dvb_service->m_provider_name;
1810 return m_reference.toString();
1814 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1818 case sLiveStreamDemuxId:
1821 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1831 return iServiceInformation::getInfoString(w);
1834 PyObject *eDVBServicePlay::getInfoObject(int w)
1839 return m_service_handler.getCaIds();
1841 return m_service_handler.getCaIds(true);
1842 case sTransponderData:
1843 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1846 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1847 return h.getHbbTVApplications();
1852 return iServiceInformation::getInfoObject(w);
1855 int eDVBServicePlay::getNumberOfTracks()
1857 eDVBServicePMTHandler::program program;
1858 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1859 if (h.getProgramInfo(program))
1861 return program.audioStreams.size();
1864 int eDVBServicePlay::getCurrentTrack()
1866 eDVBServicePMTHandler::program program;
1867 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1868 if (h.getProgramInfo(program))
1871 int max = program.audioStreams.size();
1874 for (i = 0; i < max; ++i)
1875 if (program.audioStreams[i].pid == m_current_audio_pid)
1881 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1883 int ret = selectAudioStream(i);
1885 if (m_decoder->set())
1891 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1893 eDVBServicePMTHandler::program program;
1894 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1896 if (h.getProgramInfo(program))
1899 if (i >= program.audioStreams.size())
1902 info.m_pid = program.audioStreams[i].pid;
1904 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1905 info.m_description = "MPEG";
1906 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1907 info.m_description = "Dolby Digital";
1908 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1909 info.m_description = "Dolby Digital+";
1910 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1911 info.m_description = "AAC";
1912 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1913 info.m_description = "AAC-HE";
1914 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1915 info.m_description = "DTS";
1916 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1917 info.m_description = "DTS-HD";
1919 info.m_description = "???";
1921 if (program.audioStreams[i].component_tag != -1)
1923 ePtr<eServiceEvent> evt;
1924 if (!m_event_handler.getEvent(evt, 0))
1926 ePtr<eComponentData> data;
1927 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1928 info.m_language = data->getText();
1932 if (info.m_language.empty())
1933 info.m_language = program.audioStreams[i].language_code;
1938 int eDVBServicePlay::selectAudioStream(int i)
1940 eDVBServicePMTHandler::program program;
1941 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1942 pts_t position = -1;
1944 if (h.getProgramInfo(program))
1947 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1955 stream = program.defaultAudioStream;
1957 int apid = -1, apidtype = -1;
1959 if (((unsigned int)stream) < program.audioStreams.size())
1961 apid = program.audioStreams[stream].pid;
1962 apidtype = program.audioStreams[stream].type;
1965 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1966 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1968 m_current_audio_pid = apid;
1970 if ((m_is_primary || (m_qpip_mode && m_play_audio)) && m_decoder->setAudioPID(apid, apidtype))
1972 eDebug("set audio pid failed");
1977 eDebug("seekTo ret %d", seekTo(position));
1981 /* 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 */
1982 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1984 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1986 rdsPid = program.audioStreams[stream].rdsPid;
1987 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1990 ePtr<iDVBDemux> data_demux;
1991 if (!h.getDataDemux(data_demux))
1993 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1994 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1995 m_rds_decoder->start(rdsPid);
2000 /* store new pid as default only when:
2001 a.) we have an entry in the service db for the current service,
2002 b.) we are not playing back something,
2003 c.) we are not selecting the default entry. (we wouldn't change
2004 anything in the best case, or destroy the default setting in
2005 case the real default is not yet available.)
2007 if (m_dvb_service && ((i != -1)
2008 || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
2009 && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
2010 && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
2011 && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
2012 && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
2014 m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
2015 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
2016 m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
2017 m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
2018 m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
2021 h.resetCachedProgram();
2026 int eDVBServicePlay::getCurrentChannel()
2028 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
2031 RESULT eDVBServicePlay::selectChannel(int i)
2033 if (i < LEFT || i > RIGHT || i == STEREO)
2036 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2038 m_decoder->setAudioChannel(i);
2042 std::string eDVBServicePlay::getText(int x)
2048 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2050 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2055 void eDVBServicePlay::rdsDecoderEvent(int what)
2059 case eDVBRdsDecoder::RadioTextChanged:
2060 m_event((iPlayableService*)this, evUpdatedRadioText);
2062 case eDVBRdsDecoder::RtpTextChanged:
2063 m_event((iPlayableService*)this, evUpdatedRtpText);
2065 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2066 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2068 case eDVBRdsDecoder::RecvRassSlidePic:
2069 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2074 void eDVBServicePlay::showRassSlidePicture()
2080 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2081 if (rass_slide_pic.length())
2082 m_decoder->showSinglePic(rass_slide_pic.c_str());
2084 eDebug("empty filename for rass slide picture received!!");
2087 eDebug("no MPEG Decoder to show iframes avail");
2090 eDebug("showRassSlidePicture called.. but not decoder");
2093 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2099 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2100 if (rass_interactive_pic.length())
2101 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2103 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2106 eDebug("no MPEG Decoder to show iframes avail");
2109 eDebug("showRassInteractivePic called.. but not decoder");
2112 ePyObject eDVBServicePlay::getRassInteractiveMask()
2115 return m_rds_decoder->getRassPictureMask();
2119 int eDVBServiceBase::getFrontendInfo(int w)
2121 eUsePtr<iDVBChannel> channel;
2122 if(m_service_handler.getChannel(channel))
2124 ePtr<iDVBFrontend> fe;
2125 if(channel->getFrontend(fe))
2127 return fe->readFrontendData(w);
2130 PyObject *eDVBServiceBase::getFrontendData()
2132 ePyObject ret = PyDict_New();
2135 eUsePtr<iDVBChannel> channel;
2136 if(!m_service_handler.getChannel(channel))
2138 ePtr<iDVBFrontend> fe;
2139 if(!channel->getFrontend(fe))
2140 fe->getFrontendData(ret);
2148 PyObject *eDVBServiceBase::getFrontendStatus()
2150 ePyObject ret = PyDict_New();
2153 eUsePtr<iDVBChannel> channel;
2154 if(!m_service_handler.getChannel(channel))
2156 ePtr<iDVBFrontend> fe;
2157 if(!channel->getFrontend(fe))
2158 fe->getFrontendStatus(ret);
2166 PyObject *eDVBServiceBase::getTransponderData(bool original)
2168 ePyObject ret = PyDict_New();
2171 eUsePtr<iDVBChannel> channel;
2172 if(!m_service_handler.getChannel(channel))
2174 ePtr<iDVBFrontend> fe;
2175 if(!channel->getFrontend(fe))
2176 fe->getTransponderData(ret, original);
2184 PyObject *eDVBServiceBase::getAll(bool original)
2186 ePyObject ret = getTransponderData(original);
2189 eUsePtr<iDVBChannel> channel;
2190 if(!m_service_handler.getChannel(channel))
2192 ePtr<iDVBFrontend> fe;
2193 if(!channel->getFrontend(fe))
2195 fe->getFrontendData(ret);
2196 fe->getFrontendStatus(ret);
2203 int eDVBServicePlay::getNumberOfSubservices()
2205 ePtr<eServiceEvent> evt;
2206 if (!m_event_handler.getEvent(evt, 0))
2207 return evt->getNumOfLinkageServices();
2211 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2213 ePtr<eServiceEvent> evt;
2214 if (!m_event_handler.getEvent(evt, 0))
2216 if (!evt->getLinkageService(sub, m_reference, n))
2219 sub.type=eServiceReference::idInvalid;
2223 RESULT eDVBServicePlay::startTimeshift()
2225 ePtr<iDVBDemux> demux;
2227 eDebug("Start timeshift!");
2229 if (m_timeshift_enabled)
2232 /* start recording with the data demux. */
2233 if (m_service_handler.getDataDemux(demux))
2236 demux->createTSRecorder(m_record);
2241 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2242 eDebug("could not query ts path");
2245 tspath.append("/timeshift.XXXXXX");
2247 templ = new char[tspath.length() + 1];
2248 strcpy(templ, tspath.c_str());
2250 m_timeshift_fd = mkstemp(templ);
2251 m_timeshift_file = std::string(templ);
2253 eDebug("recording to %s", templ);
2257 if (m_timeshift_fd < 0)
2263 m_record->setTargetFD(m_timeshift_fd);
2264 m_record->setTargetFilename(m_timeshift_file.c_str());
2265 m_record->enableAccessPoints(false);
2266 m_record->setTimeshift(true);
2268 m_timeshift_enabled = 1;
2270 updateTimeshiftPids();
2276 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2278 if (!m_timeshift_enabled)
2284 m_timeshift_enabled = 0;
2289 close(m_timeshift_fd);
2290 eDebug("remove timeshift file");
2291 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2294 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2295 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2301 int eDVBServicePlay::isTimeshiftActive()
2303 return m_timeshift_enabled && m_timeshift_active;
2306 RESULT eDVBServicePlay::activateTimeshift()
2308 if (!m_timeshift_enabled)
2311 if (!m_timeshift_active)
2313 switchToTimeshift();
2320 PyObject *eDVBServicePlay::getCutList()
2322 ePyObject list = PyList_New(0);
2324 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2326 ePyObject tuple = PyTuple_New(2);
2327 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2328 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2329 PyList_Append(list, tuple);
2336 void eDVBServicePlay::setCutList(ePyObject list)
2338 if (!PyList_Check(list))
2340 int size = PyList_Size(list);
2343 m_cue_entries.clear();
2345 for (i=0; i<size; ++i)
2347 ePyObject tuple = PyList_GET_ITEM(list, i);
2348 if (!PyTuple_Check(tuple))
2350 eDebug("non-tuple in cutlist");
2353 if (PyTuple_Size(tuple) != 2)
2355 eDebug("cutlist entries need to be a 2-tuple");
2358 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2359 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2361 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2364 pts_t pts = PyLong_AsLongLong(ppts);
2365 int type = PyInt_AsLong(ptype);
2366 m_cue_entries.insert(cueEntry(pts, type));
2367 eDebug("adding %08llx, %d", pts, type);
2369 m_cuesheet_changed = 1;
2371 cutlistToCuesheet();
2372 m_event((iPlayableService*)this, evCuesheetChanged);
2375 void eDVBServicePlay::setCutListEnable(int enable)
2377 m_cutlist_enabled = enable;
2378 cutlistToCuesheet();
2381 void eDVBServicePlay::updateTimeshiftPids()
2386 eDVBServicePMTHandler::program program;
2387 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2389 if (h.getProgramInfo(program))
2393 int timing_pid = -1;
2394 int timing_pid_type = -1;
2395 std::set<int> pids_to_record;
2396 pids_to_record.insert(0); // PAT
2397 if (program.pmtPid != -1)
2398 pids_to_record.insert(program.pmtPid); // PMT
2400 if (program.textPid != -1)
2401 pids_to_record.insert(program.textPid); // Videotext
2403 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2404 i(program.videoStreams.begin());
2405 i != program.videoStreams.end(); ++i)
2407 pids_to_record.insert(i->pid);
2409 if (timing_pid == -1)
2411 timing_pid = i->pid;
2412 timing_pid_type = i->type;
2416 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2417 i(program.audioStreams.begin());
2418 i != program.audioStreams.end(); ++i)
2420 pids_to_record.insert(i->pid);
2422 if (timing_pid == -1)
2424 timing_pid = i->pid;
2425 timing_pid_type = -1;
2429 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2430 i(program.subtitleStreams.begin());
2431 i != program.subtitleStreams.end(); ++i)
2432 pids_to_record.insert(i->pid);
2434 std::set<int> new_pids, obsolete_pids;
2436 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2437 m_pids_active.begin(), m_pids_active.end(),
2438 std::inserter(new_pids, new_pids.begin()));
2440 std::set_difference(
2441 m_pids_active.begin(), m_pids_active.end(),
2442 pids_to_record.begin(), pids_to_record.end(),
2443 std::inserter(new_pids, new_pids.begin())
2446 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2447 m_record->addPID(*i);
2449 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2450 m_record->removePID(*i);
2452 if (timing_pid != -1)
2453 m_record->setTimingPID(timing_pid, timing_pid_type);
2457 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2459 m_timeshift_file_next = f;
2463 void eDVBServicePlay::switchToLive()
2465 if (!m_timeshift_active)
2468 eDebug("SwitchToLive");
2472 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2474 /* free the timeshift service handler, we need the resources */
2475 m_service_handler_timeshift.free();
2477 updateDecoder(true);
2480 void eDVBServicePlay::resetTimeshift(int start)
2485 m_teletext_parser = 0;
2487 m_subtitle_parser = 0;
2488 m_new_subtitle_page_connection = 0;
2489 m_new_dvb_subtitle_page_connection = 0;
2490 m_rds_decoder_event_connection = 0;
2491 m_video_event_connection = 0;
2492 m_timeshift_changed = 1;
2493 m_timeshift_file_next.clear();
2497 m_cue = new eCueSheet();
2498 m_timeshift_active = 1;
2501 m_timeshift_active = 0;
2504 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2508 eHttpStream *f = new eHttpStream();
2509 f->open(ref.path.c_str());
2510 return ePtr<iTsSource>(f);
2514 eRawFile *f = new eRawFile();
2515 f->open(ref.path.c_str());
2516 return ePtr<iTsSource>(f);
2520 void eDVBServicePlay::switchToTimeshift()
2522 if (m_timeshift_active)
2527 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2528 r.path = m_timeshift_file;
2530 m_cue->seekTo(0, -1000);
2532 ePtr<iTsSource> source = createTsSource(r);
2533 int use_decode_demux = 1;
2534 eDVBServicePMTHandler::serviceType type = eDVBServicePMTHandler::timeshift_playback;
2535 m_service_handler_timeshift.tuneExt(r, use_decode_demux, source, m_timeshift_file.c_str(), m_cue, 0, m_dvb_service, type, false); /* use the decoder demux for everything */
2537 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2539 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2542 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2544 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2545 bool mustPlay = false;
2547 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2549 eDVBServicePMTHandler::program program;
2550 if (h.getProgramInfo(program))
2551 eDebug("getting program info failed.");
2554 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2555 if (!program.videoStreams.empty())
2557 eDebugNoNewLine(" (");
2558 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2559 i(program.videoStreams.begin());
2560 i != program.videoStreams.end(); ++i)
2567 if (i != program.videoStreams.begin())
2568 eDebugNoNewLine(", ");
2569 eDebugNoNewLine("%04x", i->pid);
2571 eDebugNoNewLine(")");
2573 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2574 if (!program.audioStreams.empty())
2576 eDebugNoNewLine(" (");
2577 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2578 i(program.audioStreams.begin());
2579 i != program.audioStreams.end(); ++i)
2581 if (i != program.audioStreams.begin())
2582 eDebugNoNewLine(", ");
2583 eDebugNoNewLine("%04x", i->pid);
2585 eDebugNoNewLine(")");
2587 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2588 pcrpid = program.pcrPid;
2589 eDebug(", and the text pid is %04x", program.textPid);
2590 tpid = program.textPid;
2595 h.getDecodeDemux(m_decode_demux);
2598 m_decode_demux->getMPEGDecoder(m_decoder, m_decoder_index);
2600 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2603 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2604 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2605 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2606 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2607 if (m_timeshift_changed)
2609 ePyObject subs = getCachedSubtitle();
2610 if (subs != Py_None)
2612 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2613 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2614 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2615 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2616 if (type == 0) // dvb
2617 m_subtitle_parser->start(pid, comp_page, anc_page);
2618 else if (type == 1) // ttx
2619 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2626 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2630 m_timeshift_changed = 0;
2634 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2637 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2638 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2639 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2643 eServiceReferenceDVB ref;
2644 m_service_handler.getServiceReference(ref);
2645 eServiceReferenceDVB parent = ref.getParentServiceReference();
2650 ePtr<eDVBResourceManager> res_mgr;
2651 if (!eDVBResourceManager::getInstance(res_mgr))
2653 ePtr<iDVBChannelList> db;
2654 if (!res_mgr->getChannelList(db))
2656 ePtr<eDVBService> origService;
2657 if (!db->getService(parent, origService))
2659 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2660 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2667 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2668 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2670 m_decoder->setVideoPID(vpid, vpidtype);
2671 m_current_video_pid_type = vpidtype;
2673 if (!m_qpip_mode || m_play_audio) // 1) no qpip mode, 2) qpip mode & play audio
2674 selectAudioStream();
2676 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2677 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2678 m_decoder->setSyncPCR(pcrpid);
2680 m_decoder->setSyncPCR(-1);
2684 m_decoder->setTextPID(tpid);
2685 m_teletext_parser->start(program.textPid);
2688 if (vpid > 0 && vpid < 0x2000)
2692 std::string radio_pic;
2693 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2694 m_decoder->setRadioPic(radio_pic);
2702 m_decoder->setAudioChannel(achannel);
2704 /* don't worry about non-existing services, nor pvr services */
2707 /* (audio pid will be set in selectAudioTrack */
2708 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2709 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2710 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2711 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2713 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2714 sendSeekableStateChanged = true;
2716 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2718 if (sendSeekableStateChanged)
2719 m_event((iPlayableService*)this, evSeekableStatusChanged);
2722 void eDVBServicePlay::loadCuesheet()
2724 std::string filename = m_reference.path + ".cuts";
2726 m_cue_entries.clear();
2728 FILE *f = fopen(filename.c_str(), "rb");
2732 eDebug("loading cuts..");
2735 unsigned long long where;
2738 if (!fread(&where, sizeof(where), 1, f))
2740 if (!fread(&what, sizeof(what), 1, f))
2743 #if BYTE_ORDER == LITTLE_ENDIAN
2744 where = bswap_64(where);
2751 m_cue_entries.insert(cueEntry(where, what));
2754 eDebug("%zd entries", m_cue_entries.size());
2756 eDebug("cutfile not found!");
2758 m_cuesheet_changed = 0;
2759 cutlistToCuesheet();
2760 m_event((iPlayableService*)this, evCuesheetChanged);
2763 void eDVBServicePlay::saveCuesheet()
2765 std::string filename = m_reference.path + ".cuts";
2767 FILE *f = fopen(filename.c_str(), "wb");
2771 unsigned long long where;
2774 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2776 #if BYTE_ORDER == BIG_ENDIAN
2779 where = bswap_64(i->where);
2781 what = htonl(i->what);
2782 fwrite(&where, sizeof(where), 1, f);
2783 fwrite(&what, sizeof(what), 1, f);
2789 m_cuesheet_changed = 0;
2792 void eDVBServicePlay::cutlistToCuesheet()
2796 eDebug("no cue sheet");
2801 if (!m_cutlist_enabled)
2803 m_cue->commitSpans();
2804 eDebug("cutlists were disabled");
2808 pts_t in = 0, out = 0, length = 0;
2812 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2814 int have_any_span = 0;
2818 if (i == m_cue_entries.end())
2820 if (!have_any_span && !in)
2824 if (i->what == 0) /* in */
2828 } else if (i->what == 1) /* out */
2830 else /* mark (2) or last play position (3) */
2849 m_cue->addSourceSpan(in, out);
2855 if (i == m_cue_entries.end())
2858 m_cue->commitSpans();
2861 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2863 if (m_subtitle_widget)
2864 disableSubtitles(parent);
2867 int tuplesize = PyTuple_Size(tuple);
2870 if (!PyTuple_Check(tuple))
2876 entry = PyTuple_GET_ITEM(tuple, 0);
2878 if (!PyInt_Check(entry))
2881 type = PyInt_AsLong(entry);
2883 if (type == 1) // teletext subtitles
2885 int page, magazine, pid;
2889 if (!m_teletext_parser)
2891 eDebug("enable teletext subtitles.. no parser !!!");
2895 entry = PyTuple_GET_ITEM(tuple, 1);
2896 if (!PyInt_Check(entry))
2898 pid = PyInt_AsLong(entry);
2900 entry = PyTuple_GET_ITEM(tuple, 2);
2901 if (!PyInt_Check(entry))
2903 page = PyInt_AsLong(entry);
2905 entry = PyTuple_GET_ITEM(tuple, 3);
2906 if (!PyInt_Check(entry))
2908 magazine = PyInt_AsLong(entry);
2910 m_subtitle_widget = new eSubtitleWidget(parent);
2911 m_subtitle_widget->resize(parent->size()); /* full size */
2912 m_teletext_parser->setPageAndMagazine(page, magazine);
2914 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2918 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2919 if (!m_subtitle_parser)
2921 eDebug("enable dvb subtitles.. no parser !!!");
2927 entry = PyTuple_GET_ITEM(tuple, 1);
2928 if (!PyInt_Check(entry))
2930 pid = PyInt_AsLong(entry);
2932 entry = PyTuple_GET_ITEM(tuple, 2);
2933 if (!PyInt_Check(entry))
2935 composition_page_id = PyInt_AsLong(entry);
2937 entry = PyTuple_GET_ITEM(tuple, 3);
2938 if (!PyInt_Check(entry))
2940 ancillary_page_id = PyInt_AsLong(entry);
2942 m_subtitle_widget = new eSubtitleWidget(parent);
2943 m_subtitle_widget->resize(parent->size()); /* full size */
2944 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2946 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2952 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2953 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2954 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2958 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2960 delete m_subtitle_widget;
2961 m_subtitle_widget = 0;
2962 if (m_subtitle_parser)
2964 m_subtitle_parser->stop();
2965 m_dvb_subtitle_pages.clear();
2967 if (m_teletext_parser)
2969 m_teletext_parser->setPageAndMagazine(-1, -1);
2970 m_subtitle_pages.clear();
2973 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2977 PyObject *eDVBServicePlay::getCachedSubtitle()
2981 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2984 unsigned int data = (unsigned int)tmp;
2985 int pid = (data&0xFFFF0000)>>16;
2986 ePyObject tuple = PyTuple_New(4);
2987 eDVBServicePMTHandler::program program;
2988 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2989 if (!h.getProgramInfo(program))
2991 if (program.textPid==pid) // teletext
2992 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2994 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2995 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2996 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2997 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
3005 PyObject *eDVBServicePlay::getSubtitleList()
3007 if (!m_teletext_parser)
3010 ePyObject l = PyList_New(0);
3011 std::set<int> added_ttx_pages;
3013 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
3014 m_teletext_parser->m_found_subtitle_pages;
3016 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
3017 eDVBServicePMTHandler::program program;
3018 if (h.getProgramInfo(program))
3019 eDebug("getting program info failed.");
3022 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
3023 it != program.subtitleStreams.end(); ++it)
3025 switch(it->subtitling_type)
3027 case 0x01: // ebu teletext subtitles
3029 int page_number = it->teletext_page_number & 0xFF;
3030 int magazine_number = it->teletext_magazine_number & 7;
3031 int hash = magazine_number << 8 | page_number;
3032 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3034 ePyObject tuple = PyTuple_New(5);
3035 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3036 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3037 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3038 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3039 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3040 PyList_Append(l, tuple);
3042 added_ttx_pages.insert(hash);
3047 case 0x20 ... 0x23: // dvb subtitles
3049 ePyObject tuple = PyTuple_New(5);
3050 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3051 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3052 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3053 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3054 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3055 PyList_Insert(l, 0, tuple);
3063 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3064 it != subs.end(); ++it)
3066 int page_number = it->teletext_page_number & 0xFF;
3067 int magazine_number = it->teletext_magazine_number & 7;
3068 int hash = magazine_number << 8 | page_number;
3069 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3071 ePyObject tuple = PyTuple_New(5);
3072 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3073 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3074 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3075 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3076 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3077 PyList_Append(l, tuple);
3085 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3087 if (m_subtitle_widget)
3089 int subtitledelay = 0;
3092 m_decoder->getPTS(0, pos);
3093 if (m_is_pvr || m_timeshift_enabled)
3095 eDebug("Subtitle in recording/timeshift");
3096 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3100 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3101 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3104 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3105 eDVBTeletextSubtitlePage tmppage = page;
3106 tmppage.m_have_pts = true;
3108 if (abs(tmppage.m_pts - pos) > 20*90000)
3109 tmppage.m_pts = pos; // fix abnormal pos diffs
3111 tmppage.m_pts += subtitledelay;
3112 m_subtitle_pages.push_back(tmppage);
3113 checkSubtitleTiming();
3117 void eDVBServicePlay::checkSubtitleTiming()
3119 eDebug("checkSubtitleTiming");
3120 if (!m_subtitle_widget)
3124 enum { TELETEXT, DVB } type;
3125 eDVBTeletextSubtitlePage page;
3126 eDVBSubtitlePage dvb_page;
3128 if (!m_subtitle_pages.empty())
3130 page = m_subtitle_pages.front();
3132 show_time = page.m_pts;
3134 else if (!m_dvb_subtitle_pages.empty())
3136 dvb_page = m_dvb_subtitle_pages.front();
3138 show_time = dvb_page.m_show_time;
3146 m_decoder->getPTS(0, pos);
3148 eDebug("%lld %lld", pos, show_time);
3149 int diff = show_time - pos;
3150 if (type == TELETEXT && !page.m_have_pts)
3152 eDebug("ttx subtitle page without pts... immediate show");
3157 eDebug("[late (%d ms)]", -diff / 90);
3160 if (abs(diff) > 1800000)
3162 eDebug("[invalid]... immediate show!");
3167 if (type == TELETEXT)
3169 eDebug("display teletext subtitle page %lld", show_time);
3170 m_subtitle_widget->setPage(page);
3171 m_subtitle_pages.pop_front();
3175 eDebug("display dvb subtitle Page %lld", show_time);
3176 m_subtitle_widget->setPage(dvb_page);
3177 m_dvb_subtitle_pages.pop_front();
3181 eDebug("start subtitle delay %d", diff / 90);
3182 m_subtitle_sync_timer->start(diff / 90, 1);
3188 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3190 if (m_subtitle_widget)
3194 m_decoder->getPTS(0, pos);
3195 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3196 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3198 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3199 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3201 eDVBSubtitlePage tmppage;
3203 tmppage.m_show_time = pos + subtitledelay;
3204 m_dvb_subtitle_pages.push_back(tmppage);
3208 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3209 if (subtitledelay != 0)
3211 eDVBSubtitlePage tmppage;
3213 tmppage.m_show_time += subtitledelay;
3214 m_dvb_subtitle_pages.push_back(tmppage);
3217 m_dvb_subtitle_pages.push_back(p);
3219 checkSubtitleTiming();
3223 int eDVBServicePlay::getAC3Delay()
3226 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3228 return m_decoder->getAC3Delay();
3233 int eDVBServicePlay::getPCMDelay()
3236 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3238 return m_decoder->getPCMDelay();
3243 void eDVBServicePlay::setAC3Delay(int delay)
3246 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3248 std::string config_delay;
3249 int config_delay_int = 0;
3250 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3251 config_delay_int = atoi(config_delay.c_str());
3252 m_decoder->setAC3Delay(delay + config_delay_int);
3256 void eDVBServicePlay::setPCMDelay(int delay)
3259 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3261 std::string config_delay;
3262 int config_delay_int = 0;
3263 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3264 config_delay_int = atoi(config_delay.c_str());
3266 config_delay_int = 0;
3267 m_decoder->setPCMDelay(delay + config_delay_int);
3271 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3273 switch(event.type) {
3274 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3275 m_event((iPlayableService*)this, evVideoSizeChanged);
3277 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3278 m_event((iPlayableService*)this, evVideoFramerateChanged);
3280 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3281 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3288 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3294 PyObject *eDVBServicePlay::getStreamingData()
3296 eDVBServicePMTHandler::program program;
3297 if (m_service_handler.getProgramInfo(program))
3302 ePyObject r = program.createPythonObject();
3303 ePtr<iDVBDemux> demux;
3304 if (!m_service_handler.getDataDemux(demux))
3307 if (!demux->getCADemuxID(demux_id))
3308 PutToDict(r, "demux", demux_id);
3314 void eDVBServicePlay::setQpipMode(bool value, bool audio)
3316 m_qpip_mode = value;
3317 m_play_audio = audio;
3323 selectAudioStream();
3327 m_decoder->setAudioPID(-1, -1);
3333 DEFINE_REF(eDVBServicePlay)
3335 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3339 case iServiceInformation::sTransponderData:
3340 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3344 return iStaticServiceInformation::getInfoObject(ref, w);
3347 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");