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;
962 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
965 eDVBServicePlay::~eDVBServicePlay()
970 int ret=meta.parseFile(m_reference.path);
974 meta.m_service_data="";
975 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
976 meta.m_service_data += tmp;
978 for (int x=0; x < eDVBService::cacheMax; ++x)
980 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
983 sprintf(tmp, ",c:%02d%04x", x, entry);
984 meta.m_service_data += tmp;
987 meta.updateMeta(m_reference.path);
990 delete m_subtitle_widget;
993 void eDVBServicePlay::gotNewEvent()
997 ePtr<eServiceEvent> m_event_now, m_event_next;
998 getEvent(m_event_now, 0);
999 getEvent(m_event_next, 1);
1002 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1004 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1006 m_event((iPlayableService*)this, evUpdatedEventInfo);
1009 void eDVBServicePlay::serviceEvent(int event)
1011 m_tune_state = event;
1015 case eDVBServicePMTHandler::eventTuned:
1017 ePtr<iDVBDemux> m_demux;
1018 if (!m_service_handler.getDataDemux(m_demux))
1020 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1021 int sid = ref.getParentServiceID().get();
1023 sid = ref.getServiceID().get();
1024 if ( ref.getParentTransportStreamID().get() &&
1025 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1026 m_event_handler.startOther(m_demux, sid);
1028 m_event_handler.start(m_demux, sid);
1030 m_event((iPlayableService*)this, evTunedIn);
1033 case eDVBServicePMTHandler::eventNoResources:
1034 case eDVBServicePMTHandler::eventNoPAT:
1035 case eDVBServicePMTHandler::eventNoPATEntry:
1036 case eDVBServicePMTHandler::eventNoPMT:
1037 case eDVBServicePMTHandler::eventTuneFailed:
1038 case eDVBServicePMTHandler::eventMisconfiguration:
1040 eDebug("DVB service failed to tune - error %d", event);
1041 m_event((iPlayableService*)this, evTuneFailed);
1044 case eDVBServicePMTHandler::eventNewProgramInfo:
1046 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1047 if (m_timeshift_enabled)
1048 updateTimeshiftPids();
1049 if (!m_timeshift_active)
1051 if (m_first_program_info & 1 && m_is_pvr)
1053 m_first_program_info &= ~1;
1056 if (!m_timeshift_active)
1057 m_event((iPlayableService*)this, evUpdatedInfo);
1060 case eDVBServicePMTHandler::eventPreStart:
1063 case eDVBServicePMTHandler::eventEOF:
1064 m_event((iPlayableService*)this, evEOF);
1066 case eDVBServicePMTHandler::eventSOF:
1067 m_event((iPlayableService*)this, evSOF);
1069 case eDVBServicePMTHandler::eventHBBTVInfo:
1070 m_event((iPlayableService*)this, evHBBTVInfo);
1075 void eDVBServicePlay::serviceEventTimeshift(int event)
1079 case eDVBServicePMTHandler::eventNewProgramInfo:
1080 eDebug("eventNewProgramInfo TS");
1081 if (m_timeshift_active)
1084 if (m_first_program_info & 2)
1088 eDebug("re-apply slowmotion after timeshift file change");
1089 m_decoder->setSlowMotion(m_slowmotion);
1093 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1095 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1096 if (m_fastforward != 1)
1097 m_decoder->setFastForward(m_fastforward);
1099 m_decoder->setTrickmode();
1103 m_first_program_info &= ~2;
1105 m_event((iPlayableService*)this, evUpdatedInfo);
1108 case eDVBServicePMTHandler::eventSOF:
1110 if (!m_timeshift_file_next.empty())
1112 eDebug("timeshift SOF, switch to next file");
1115 m_first_program_info |= 2;
1117 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1118 r.path = m_timeshift_file_next;
1120 /* free the timeshift service handler, we need the resources */
1121 m_service_handler_timeshift.free();
1125 m_cue->seekTo(0, -1000);
1126 ePtr<iTsSource> source = createTsSource(r);
1127 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 */
1129 m_event((iPlayableService*)this, evUser+1);
1133 m_event((iPlayableService*)this, evSOF);
1135 case eDVBServicePMTHandler::eventEOF:
1136 if ((!m_is_paused) && (m_skipmode >= 0))
1138 if (m_timeshift_file_next.empty())
1140 eDebug("timeshift EOF, so let's go live");
1145 eDebug("timeshift EOF, switch to next file");
1147 m_first_program_info |= 2;
1149 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1150 r.path = m_timeshift_file_next;
1152 /* free the timeshift service handler, we need the resources */
1153 m_service_handler_timeshift.free();
1156 ePtr<iTsSource> source = createTsSource(r);
1157 int use_decode_demux = 1;
1158 eDVBServicePMTHandler::serviceType type = eDVBServicePMTHandler::timeshift_playback;
1159 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 */
1161 m_event((iPlayableService*)this, evUser+1);
1165 case eDVBServicePMTHandler::eventNoDiskSpace:
1166 eDebug("No space!");
1167 m_event((iPlayableService*)this, evUser+3);
1172 RESULT eDVBServicePlay::start()
1174 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1175 bool scrambled = true;
1176 eDVBServicePMTHandler::serviceType type = eDVBServicePMTHandler::livetv;
1178 int use_decode_demux = 0;
1180 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1181 two (one for decoding, one for data source), as we must be prepared
1182 to start recording from the data demux. */
1185 use_decode_demux = 1;
1186 eDVBMetaParser meta;
1187 if (!meta.parseFile(m_reference.path))
1189 service = meta.m_ref;
1190 service.path = m_reference.path;
1191 scrambled = meta.m_scrambled;
1195 /* when there is no meta file we need to handle ts/m2ts as descrambled */
1198 m_cue = new eCueSheet();
1199 type = eDVBServicePMTHandler::playback;
1202 m_event(this, evStart);
1207 type = eDVBServicePMTHandler::streamclient;
1210 m_first_program_info = 1;
1211 ePtr<iTsSource> source = createTsSource(service);
1212 m_service_handler.tuneExt(service, use_decode_demux, source, service.path.c_str(), m_cue, false, m_dvb_service, type, scrambled);
1216 /* inject EIT if there is a stored one */
1217 std::string filename = service.path;
1218 filename.erase(filename.length()-2, 2);
1220 ePtr<eServiceEvent> event = new eServiceEvent;
1221 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1223 ePtr<eServiceEvent> empty;
1224 m_event_handler.inject(event, 0);
1225 m_event_handler.inject(empty, 1);
1227 m_event(this, evStart);
1232 RESULT eDVBServicePlay::stop()
1234 /* add bookmark for last play position */
1237 pts_t play_position, length;
1238 if (!getPlayPosition(play_position))
1240 /* remove last position */
1241 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1243 if (i->what == 3) /* current play position */
1245 m_cue_entries.erase(i);
1246 i = m_cue_entries.begin();
1252 if (getLength(length))
1257 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1259 m_cuesheet_changed = 1;
1263 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1265 m_service_handler_timeshift.free();
1266 m_service_handler.free();
1268 if (m_is_pvr && m_cuesheet_changed)
1271 /* save cuesheet only when main file is accessible. */
1272 if (!::stat(m_reference.path.c_str(), &s))
1275 m_event((iPlayableService*)this, evStopped);
1279 RESULT eDVBServicePlay::setTarget(int target)
1281 m_is_primary = !target;
1282 m_decoder_index = target;
1286 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1288 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1292 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1294 /* note: we check for timeshift to be enabled,
1295 not neccessary active. if you pause when timeshift
1296 is not active, you should activate it when unpausing */
1297 if ((!m_is_pvr) && (!m_timeshift_enabled))
1307 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1309 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1310 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1311 setFastForward_internal(0);
1314 m_slowmotion = ratio;
1315 return m_decoder->setSlowMotion(ratio);
1321 RESULT eDVBServicePlay::setFastForward(int ratio)
1323 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1325 return setFastForward_internal(ratio);
1328 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1330 int skipmode, ffratio, ret = 0;
1337 } else if (ratio > 0)
1345 } else // if (ratio < 0)
1351 if (m_skipmode != skipmode)
1353 eDebug("setting cue skipmode to %d", skipmode);
1356 long long _skipmode = skipmode;
1357 if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1360 _skipmode = skipmode * 3;
1362 _skipmode = skipmode * 4;
1365 m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1369 m_skipmode = skipmode;
1372 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1374 m_fastforward = ffratio;
1380 ; /* return m_decoder->play(); is done in caller*/
1381 else if (ffratio != 1)
1382 ret = m_decoder->setFastForward(ffratio);
1384 ret = m_decoder->setTrickmode();
1387 eDebug("final seek after trickplay ret %d", seekTo(pos));
1392 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1394 if (m_is_pvr || m_timeshift_enabled)
1404 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1405 RESULT eDVBServicePlay::getLength(pts_t &len)
1407 ePtr<iDVBPVRChannel> pvr_channel;
1409 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1412 return pvr_channel->getLength(len);
1415 RESULT eDVBServicePlay::pause()
1417 eDebug("eDVBServicePlay::pause");
1418 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1423 return m_decoder->pause();
1428 RESULT eDVBServicePlay::unpause()
1430 eDebug("eDVBServicePlay::unpause");
1431 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1436 return m_decoder->play();
1441 RESULT eDVBServicePlay::seekTo(pts_t to)
1443 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1445 if (!m_decode_demux)
1448 ePtr<iDVBPVRChannel> pvr_channel;
1450 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1456 m_cue->seekTo(0, to);
1457 m_dvb_subtitle_pages.clear();
1458 m_subtitle_pages.clear();
1463 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1465 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1467 if (!m_decode_demux)
1470 ePtr<iDVBPVRChannel> pvr_channel;
1472 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1477 /* HACK until we have skip-AP api */
1478 if ((to > 0) && (to < 100))
1486 m_cue->seekTo(mode, to);
1487 m_dvb_subtitle_pages.clear();
1488 m_subtitle_pages.clear();
1492 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1494 ePtr<iDVBPVRChannel> pvr_channel;
1496 if (!m_decode_demux)
1499 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1504 /* if there is a decoder, use audio or video PTS */
1507 r = m_decoder->getPTS(0, pos);
1513 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1516 RESULT eDVBServicePlay::setTrickmode(int trick)
1518 /* currently unimplemented */
1522 RESULT eDVBServicePlay::isCurrentlySeekable()
1527 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1528 if (m_decoder->getVideoProgressive() == -1)
1534 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1540 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1546 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1552 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1558 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1564 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1567 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1568 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1570 if (!m_timeshift_enabled)
1572 /* query config path */
1574 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1575 eDebug("could not query ts path from config");
1579 /* we need enough diskspace */
1581 if (statfs(tspath.c_str(), &fs) < 0)
1583 eDebug("statfs failed!");
1587 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1589 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1599 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1610 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1616 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1622 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1628 RESULT eDVBServicePlay::getName(std::string &name)
1632 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1633 return i->getName(m_reference, name);
1635 else if (m_is_stream)
1637 name = m_reference.name;
1640 name = m_reference.path;
1647 else if (m_dvb_service)
1649 m_dvb_service->getName(m_reference, name);
1653 else if (!m_reference.name.empty())
1654 eStaticServiceDVBInformation().getName(m_reference, name);
1656 name = "DVB service";
1660 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1662 return m_event_handler.getEvent(evt, nownext);
1665 int eDVBServicePlay::getInfo(int w)
1667 eDVBServicePMTHandler::program program;
1669 if (w == sCAIDs || w == sCAIDPIDs)
1670 return resIsPyObject;
1672 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1674 int no_program_info = 0;
1676 if (h.getProgramInfo(program))
1677 no_program_info = 1;
1683 return m_decoder->getVideoHeight();
1687 return m_decoder->getVideoWidth();
1691 return m_decoder->getVideoFrameRate();
1695 return m_decoder->getVideoProgressive();
1701 aspect = m_decoder->getVideoAspect();
1702 if (aspect == -1 && no_program_info)
1704 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1706 ePtr<eServiceEvent> evt;
1707 if (!m_event_handler.getEvent(evt, 0))
1709 ePtr<eComponentData> data;
1710 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1712 if ( data->getStreamContent() == 1 )
1714 switch(data->getComponentType())
1717 case 1: // 4:3 SD PAL
1719 case 3: // 16:9 SD PAL
1720 case 4: // > 16:9 PAL
1721 case 5: // 4:3 SD NTSC
1723 case 7: // 16:9 SD NTSC
1724 case 8: // > 16:9 NTSC
1727 case 9: // 4:3 HD PAL
1729 case 0xB: // 16:9 HD PAL
1730 case 0xC: // > 16:9 HD PAL
1731 case 0xD: // 4:3 HD NTSC
1733 case 0xF: // 16:9 HD NTSC
1734 case 0x10: // > 16:9 HD PAL
1735 return data->getComponentType();
1745 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1749 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1753 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1754 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1758 int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
1761 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1764 apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
1767 apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
1770 apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
1774 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1778 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1782 if (no_program_info) return -1; return program.pcrPid;
1783 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1784 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1785 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1786 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1787 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1788 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1789 case sProvider: if (!m_dvb_service) return -1; return -2;
1790 case sServiceref: return resIsString;
1791 case sDVBState: return m_tune_state;
1798 std::string eDVBServicePlay::getInfoString(int w)
1803 if (!m_dvb_service) return "";
1804 return m_dvb_service->m_provider_name;
1806 return m_reference.toString();
1810 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1814 case sLiveStreamDemuxId:
1817 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1827 return iServiceInformation::getInfoString(w);
1830 PyObject *eDVBServicePlay::getInfoObject(int w)
1835 return m_service_handler.getCaIds();
1837 return m_service_handler.getCaIds(true);
1838 case sTransponderData:
1839 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1842 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1843 return h.getHbbTVApplications();
1848 return iServiceInformation::getInfoObject(w);
1851 int eDVBServicePlay::getNumberOfTracks()
1853 eDVBServicePMTHandler::program program;
1854 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1855 if (h.getProgramInfo(program))
1857 return program.audioStreams.size();
1860 int eDVBServicePlay::getCurrentTrack()
1862 eDVBServicePMTHandler::program program;
1863 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1864 if (h.getProgramInfo(program))
1867 int max = program.audioStreams.size();
1870 for (i = 0; i < max; ++i)
1871 if (program.audioStreams[i].pid == m_current_audio_pid)
1877 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1879 int ret = selectAudioStream(i);
1881 if (m_decoder->set())
1887 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1889 eDVBServicePMTHandler::program program;
1890 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1892 if (h.getProgramInfo(program))
1895 if (i >= program.audioStreams.size())
1898 info.m_pid = program.audioStreams[i].pid;
1900 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1901 info.m_description = "MPEG";
1902 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1903 info.m_description = "Dolby Digital";
1904 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1905 info.m_description = "Dolby Digital+";
1906 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1907 info.m_description = "AAC";
1908 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1909 info.m_description = "AAC-HE";
1910 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1911 info.m_description = "DTS";
1912 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1913 info.m_description = "DTS-HD";
1915 info.m_description = "???";
1917 if (program.audioStreams[i].component_tag != -1)
1919 ePtr<eServiceEvent> evt;
1920 if (!m_event_handler.getEvent(evt, 0))
1922 ePtr<eComponentData> data;
1923 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1924 info.m_language = data->getText();
1928 if (info.m_language.empty())
1929 info.m_language = program.audioStreams[i].language_code;
1934 int eDVBServicePlay::selectAudioStream(int i)
1936 eDVBServicePMTHandler::program program;
1937 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1938 pts_t position = -1;
1940 if (h.getProgramInfo(program))
1943 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1951 stream = program.defaultAudioStream;
1953 int apid = -1, apidtype = -1;
1955 if (((unsigned int)stream) < program.audioStreams.size())
1957 apid = program.audioStreams[stream].pid;
1958 apidtype = program.audioStreams[stream].type;
1961 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1962 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1964 m_current_audio_pid = apid;
1966 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1968 eDebug("set audio pid failed");
1973 eDebug("seekTo ret %d", seekTo(position));
1977 /* 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 */
1978 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1980 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1982 rdsPid = program.audioStreams[stream].rdsPid;
1983 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1986 ePtr<iDVBDemux> data_demux;
1987 if (!h.getDataDemux(data_demux))
1989 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1990 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1991 m_rds_decoder->start(rdsPid);
1996 /* store new pid as default only when:
1997 a.) we have an entry in the service db for the current service,
1998 b.) we are not playing back something,
1999 c.) we are not selecting the default entry. (we wouldn't change
2000 anything in the best case, or destroy the default setting in
2001 case the real default is not yet available.)
2003 if (m_dvb_service && ((i != -1)
2004 || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
2005 && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
2006 && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
2007 && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
2008 && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
2010 m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
2011 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
2012 m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
2013 m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
2014 m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
2017 h.resetCachedProgram();
2022 int eDVBServicePlay::getCurrentChannel()
2024 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
2027 RESULT eDVBServicePlay::selectChannel(int i)
2029 if (i < LEFT || i > RIGHT || i == STEREO)
2032 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2034 m_decoder->setAudioChannel(i);
2038 std::string eDVBServicePlay::getText(int x)
2044 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2046 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2051 void eDVBServicePlay::rdsDecoderEvent(int what)
2055 case eDVBRdsDecoder::RadioTextChanged:
2056 m_event((iPlayableService*)this, evUpdatedRadioText);
2058 case eDVBRdsDecoder::RtpTextChanged:
2059 m_event((iPlayableService*)this, evUpdatedRtpText);
2061 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2062 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2064 case eDVBRdsDecoder::RecvRassSlidePic:
2065 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2070 void eDVBServicePlay::showRassSlidePicture()
2076 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2077 if (rass_slide_pic.length())
2078 m_decoder->showSinglePic(rass_slide_pic.c_str());
2080 eDebug("empty filename for rass slide picture received!!");
2083 eDebug("no MPEG Decoder to show iframes avail");
2086 eDebug("showRassSlidePicture called.. but not decoder");
2089 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2095 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2096 if (rass_interactive_pic.length())
2097 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2099 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2102 eDebug("no MPEG Decoder to show iframes avail");
2105 eDebug("showRassInteractivePic called.. but not decoder");
2108 ePyObject eDVBServicePlay::getRassInteractiveMask()
2111 return m_rds_decoder->getRassPictureMask();
2115 int eDVBServiceBase::getFrontendInfo(int w)
2117 eUsePtr<iDVBChannel> channel;
2118 if(m_service_handler.getChannel(channel))
2120 ePtr<iDVBFrontend> fe;
2121 if(channel->getFrontend(fe))
2123 return fe->readFrontendData(w);
2126 PyObject *eDVBServiceBase::getFrontendData()
2128 ePyObject ret = PyDict_New();
2131 eUsePtr<iDVBChannel> channel;
2132 if(!m_service_handler.getChannel(channel))
2134 ePtr<iDVBFrontend> fe;
2135 if(!channel->getFrontend(fe))
2136 fe->getFrontendData(ret);
2144 PyObject *eDVBServiceBase::getFrontendStatus()
2146 ePyObject ret = PyDict_New();
2149 eUsePtr<iDVBChannel> channel;
2150 if(!m_service_handler.getChannel(channel))
2152 ePtr<iDVBFrontend> fe;
2153 if(!channel->getFrontend(fe))
2154 fe->getFrontendStatus(ret);
2162 PyObject *eDVBServiceBase::getTransponderData(bool original)
2164 ePyObject ret = PyDict_New();
2167 eUsePtr<iDVBChannel> channel;
2168 if(!m_service_handler.getChannel(channel))
2170 ePtr<iDVBFrontend> fe;
2171 if(!channel->getFrontend(fe))
2172 fe->getTransponderData(ret, original);
2180 PyObject *eDVBServiceBase::getAll(bool original)
2182 ePyObject ret = getTransponderData(original);
2185 eUsePtr<iDVBChannel> channel;
2186 if(!m_service_handler.getChannel(channel))
2188 ePtr<iDVBFrontend> fe;
2189 if(!channel->getFrontend(fe))
2191 fe->getFrontendData(ret);
2192 fe->getFrontendStatus(ret);
2199 int eDVBServicePlay::getNumberOfSubservices()
2201 ePtr<eServiceEvent> evt;
2202 if (!m_event_handler.getEvent(evt, 0))
2203 return evt->getNumOfLinkageServices();
2207 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2209 ePtr<eServiceEvent> evt;
2210 if (!m_event_handler.getEvent(evt, 0))
2212 if (!evt->getLinkageService(sub, m_reference, n))
2215 sub.type=eServiceReference::idInvalid;
2219 RESULT eDVBServicePlay::startTimeshift()
2221 ePtr<iDVBDemux> demux;
2223 eDebug("Start timeshift!");
2225 if (m_timeshift_enabled)
2228 /* start recording with the data demux. */
2229 if (m_service_handler.getDataDemux(demux))
2232 demux->createTSRecorder(m_record);
2237 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2238 eDebug("could not query ts path");
2241 tspath.append("/timeshift.XXXXXX");
2243 templ = new char[tspath.length() + 1];
2244 strcpy(templ, tspath.c_str());
2246 m_timeshift_fd = mkstemp(templ);
2247 m_timeshift_file = std::string(templ);
2249 eDebug("recording to %s", templ);
2253 if (m_timeshift_fd < 0)
2259 m_record->setTargetFD(m_timeshift_fd);
2260 m_record->setTargetFilename(m_timeshift_file.c_str());
2261 m_record->enableAccessPoints(false);
2262 m_record->setTimeshift(true);
2264 m_timeshift_enabled = 1;
2266 updateTimeshiftPids();
2272 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2274 if (!m_timeshift_enabled)
2280 m_timeshift_enabled = 0;
2285 close(m_timeshift_fd);
2286 eDebug("remove timeshift file");
2287 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2290 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2291 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2297 int eDVBServicePlay::isTimeshiftActive()
2299 return m_timeshift_enabled && m_timeshift_active;
2302 RESULT eDVBServicePlay::activateTimeshift()
2304 if (!m_timeshift_enabled)
2307 if (!m_timeshift_active)
2309 switchToTimeshift();
2316 PyObject *eDVBServicePlay::getCutList()
2318 ePyObject list = PyList_New(0);
2320 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2322 ePyObject tuple = PyTuple_New(2);
2323 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2324 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2325 PyList_Append(list, tuple);
2332 void eDVBServicePlay::setCutList(ePyObject list)
2334 if (!PyList_Check(list))
2336 int size = PyList_Size(list);
2339 m_cue_entries.clear();
2341 for (i=0; i<size; ++i)
2343 ePyObject tuple = PyList_GET_ITEM(list, i);
2344 if (!PyTuple_Check(tuple))
2346 eDebug("non-tuple in cutlist");
2349 if (PyTuple_Size(tuple) != 2)
2351 eDebug("cutlist entries need to be a 2-tuple");
2354 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2355 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2357 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2360 pts_t pts = PyLong_AsLongLong(ppts);
2361 int type = PyInt_AsLong(ptype);
2362 m_cue_entries.insert(cueEntry(pts, type));
2363 eDebug("adding %08llx, %d", pts, type);
2365 m_cuesheet_changed = 1;
2367 cutlistToCuesheet();
2368 m_event((iPlayableService*)this, evCuesheetChanged);
2371 void eDVBServicePlay::setCutListEnable(int enable)
2373 m_cutlist_enabled = enable;
2374 cutlistToCuesheet();
2377 void eDVBServicePlay::updateTimeshiftPids()
2382 eDVBServicePMTHandler::program program;
2383 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2385 if (h.getProgramInfo(program))
2389 int timing_pid = -1;
2390 int timing_pid_type = -1;
2391 std::set<int> pids_to_record;
2392 pids_to_record.insert(0); // PAT
2393 if (program.pmtPid != -1)
2394 pids_to_record.insert(program.pmtPid); // PMT
2396 if (program.textPid != -1)
2397 pids_to_record.insert(program.textPid); // Videotext
2399 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2400 i(program.videoStreams.begin());
2401 i != program.videoStreams.end(); ++i)
2403 pids_to_record.insert(i->pid);
2405 if (timing_pid == -1)
2407 timing_pid = i->pid;
2408 timing_pid_type = i->type;
2412 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2413 i(program.audioStreams.begin());
2414 i != program.audioStreams.end(); ++i)
2416 pids_to_record.insert(i->pid);
2418 if (timing_pid == -1)
2420 timing_pid = i->pid;
2421 timing_pid_type = -1;
2425 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2426 i(program.subtitleStreams.begin());
2427 i != program.subtitleStreams.end(); ++i)
2428 pids_to_record.insert(i->pid);
2430 std::set<int> new_pids, obsolete_pids;
2432 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2433 m_pids_active.begin(), m_pids_active.end(),
2434 std::inserter(new_pids, new_pids.begin()));
2436 std::set_difference(
2437 m_pids_active.begin(), m_pids_active.end(),
2438 pids_to_record.begin(), pids_to_record.end(),
2439 std::inserter(new_pids, new_pids.begin())
2442 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2443 m_record->addPID(*i);
2445 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2446 m_record->removePID(*i);
2448 if (timing_pid != -1)
2449 m_record->setTimingPID(timing_pid, timing_pid_type);
2453 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2455 m_timeshift_file_next = f;
2459 void eDVBServicePlay::switchToLive()
2461 if (!m_timeshift_active)
2464 eDebug("SwitchToLive");
2468 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2470 /* free the timeshift service handler, we need the resources */
2471 m_service_handler_timeshift.free();
2473 updateDecoder(true);
2476 void eDVBServicePlay::resetTimeshift(int start)
2481 m_teletext_parser = 0;
2483 m_subtitle_parser = 0;
2484 m_new_subtitle_page_connection = 0;
2485 m_new_dvb_subtitle_page_connection = 0;
2486 m_rds_decoder_event_connection = 0;
2487 m_video_event_connection = 0;
2488 m_timeshift_changed = 1;
2489 m_timeshift_file_next.clear();
2493 m_cue = new eCueSheet();
2494 m_timeshift_active = 1;
2497 m_timeshift_active = 0;
2500 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2504 eHttpStream *f = new eHttpStream();
2505 f->open(ref.path.c_str());
2506 return ePtr<iTsSource>(f);
2510 eRawFile *f = new eRawFile();
2511 f->open(ref.path.c_str());
2512 return ePtr<iTsSource>(f);
2516 void eDVBServicePlay::switchToTimeshift()
2518 if (m_timeshift_active)
2523 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2524 r.path = m_timeshift_file;
2526 m_cue->seekTo(0, -1000);
2528 ePtr<iTsSource> source = createTsSource(r);
2529 int use_decode_demux = 1;
2530 eDVBServicePMTHandler::serviceType type = eDVBServicePMTHandler::timeshift_playback;
2531 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 */
2533 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2535 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2538 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2540 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2541 bool mustPlay = false;
2543 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2545 eDVBServicePMTHandler::program program;
2546 if (h.getProgramInfo(program))
2547 eDebug("getting program info failed.");
2550 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2551 if (!program.videoStreams.empty())
2553 eDebugNoNewLine(" (");
2554 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2555 i(program.videoStreams.begin());
2556 i != program.videoStreams.end(); ++i)
2563 if (i != program.videoStreams.begin())
2564 eDebugNoNewLine(", ");
2565 eDebugNoNewLine("%04x", i->pid);
2567 eDebugNoNewLine(")");
2569 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2570 if (!program.audioStreams.empty())
2572 eDebugNoNewLine(" (");
2573 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2574 i(program.audioStreams.begin());
2575 i != program.audioStreams.end(); ++i)
2577 if (i != program.audioStreams.begin())
2578 eDebugNoNewLine(", ");
2579 eDebugNoNewLine("%04x", i->pid);
2581 eDebugNoNewLine(")");
2583 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2584 pcrpid = program.pcrPid;
2585 eDebug(", and the text pid is %04x", program.textPid);
2586 tpid = program.textPid;
2591 h.getDecodeDemux(m_decode_demux);
2594 m_decode_demux->getMPEGDecoder(m_decoder, m_decoder_index);
2596 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2599 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2600 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2601 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2602 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2603 if (m_timeshift_changed)
2605 ePyObject subs = getCachedSubtitle();
2606 if (subs != Py_None)
2608 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2609 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2610 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2611 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2612 if (type == 0) // dvb
2613 m_subtitle_parser->start(pid, comp_page, anc_page);
2614 else if (type == 1) // ttx
2615 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2622 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2626 m_timeshift_changed = 0;
2630 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2633 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2634 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2635 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2639 eServiceReferenceDVB ref;
2640 m_service_handler.getServiceReference(ref);
2641 eServiceReferenceDVB parent = ref.getParentServiceReference();
2646 ePtr<eDVBResourceManager> res_mgr;
2647 if (!eDVBResourceManager::getInstance(res_mgr))
2649 ePtr<iDVBChannelList> db;
2650 if (!res_mgr->getChannelList(db))
2652 ePtr<eDVBService> origService;
2653 if (!db->getService(parent, origService))
2655 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2656 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2663 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2664 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2666 m_decoder->setVideoPID(vpid, vpidtype);
2667 m_current_video_pid_type = vpidtype;
2668 selectAudioStream();
2670 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2671 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2672 m_decoder->setSyncPCR(pcrpid);
2674 m_decoder->setSyncPCR(-1);
2678 m_decoder->setTextPID(tpid);
2679 m_teletext_parser->start(program.textPid);
2682 if (vpid > 0 && vpid < 0x2000)
2686 std::string radio_pic;
2687 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2688 m_decoder->setRadioPic(radio_pic);
2696 m_decoder->setAudioChannel(achannel);
2698 /* don't worry about non-existing services, nor pvr services */
2701 /* (audio pid will be set in selectAudioTrack */
2702 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2703 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2704 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2705 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2707 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2708 sendSeekableStateChanged = true;
2710 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2712 if (sendSeekableStateChanged)
2713 m_event((iPlayableService*)this, evSeekableStatusChanged);
2716 void eDVBServicePlay::loadCuesheet()
2718 std::string filename = m_reference.path + ".cuts";
2720 m_cue_entries.clear();
2722 FILE *f = fopen(filename.c_str(), "rb");
2726 eDebug("loading cuts..");
2729 unsigned long long where;
2732 if (!fread(&where, sizeof(where), 1, f))
2734 if (!fread(&what, sizeof(what), 1, f))
2737 #if BYTE_ORDER == LITTLE_ENDIAN
2738 where = bswap_64(where);
2745 m_cue_entries.insert(cueEntry(where, what));
2748 eDebug("%zd entries", m_cue_entries.size());
2750 eDebug("cutfile not found!");
2752 m_cuesheet_changed = 0;
2753 cutlistToCuesheet();
2754 m_event((iPlayableService*)this, evCuesheetChanged);
2757 void eDVBServicePlay::saveCuesheet()
2759 std::string filename = m_reference.path + ".cuts";
2761 FILE *f = fopen(filename.c_str(), "wb");
2765 unsigned long long where;
2768 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2770 #if BYTE_ORDER == BIG_ENDIAN
2773 where = bswap_64(i->where);
2775 what = htonl(i->what);
2776 fwrite(&where, sizeof(where), 1, f);
2777 fwrite(&what, sizeof(what), 1, f);
2783 m_cuesheet_changed = 0;
2786 void eDVBServicePlay::cutlistToCuesheet()
2790 eDebug("no cue sheet");
2795 if (!m_cutlist_enabled)
2797 m_cue->commitSpans();
2798 eDebug("cutlists were disabled");
2802 pts_t in = 0, out = 0, length = 0;
2806 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2808 int have_any_span = 0;
2812 if (i == m_cue_entries.end())
2814 if (!have_any_span && !in)
2818 if (i->what == 0) /* in */
2822 } else if (i->what == 1) /* out */
2824 else /* mark (2) or last play position (3) */
2843 m_cue->addSourceSpan(in, out);
2849 if (i == m_cue_entries.end())
2852 m_cue->commitSpans();
2855 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2857 if (m_subtitle_widget)
2858 disableSubtitles(parent);
2861 int tuplesize = PyTuple_Size(tuple);
2864 if (!PyTuple_Check(tuple))
2870 entry = PyTuple_GET_ITEM(tuple, 0);
2872 if (!PyInt_Check(entry))
2875 type = PyInt_AsLong(entry);
2877 if (type == 1) // teletext subtitles
2879 int page, magazine, pid;
2883 if (!m_teletext_parser)
2885 eDebug("enable teletext subtitles.. no parser !!!");
2889 entry = PyTuple_GET_ITEM(tuple, 1);
2890 if (!PyInt_Check(entry))
2892 pid = PyInt_AsLong(entry);
2894 entry = PyTuple_GET_ITEM(tuple, 2);
2895 if (!PyInt_Check(entry))
2897 page = PyInt_AsLong(entry);
2899 entry = PyTuple_GET_ITEM(tuple, 3);
2900 if (!PyInt_Check(entry))
2902 magazine = PyInt_AsLong(entry);
2904 m_subtitle_widget = new eSubtitleWidget(parent);
2905 m_subtitle_widget->resize(parent->size()); /* full size */
2906 m_teletext_parser->setPageAndMagazine(page, magazine);
2908 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2912 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2913 if (!m_subtitle_parser)
2915 eDebug("enable dvb subtitles.. no parser !!!");
2921 entry = PyTuple_GET_ITEM(tuple, 1);
2922 if (!PyInt_Check(entry))
2924 pid = PyInt_AsLong(entry);
2926 entry = PyTuple_GET_ITEM(tuple, 2);
2927 if (!PyInt_Check(entry))
2929 composition_page_id = PyInt_AsLong(entry);
2931 entry = PyTuple_GET_ITEM(tuple, 3);
2932 if (!PyInt_Check(entry))
2934 ancillary_page_id = PyInt_AsLong(entry);
2936 m_subtitle_widget = new eSubtitleWidget(parent);
2937 m_subtitle_widget->resize(parent->size()); /* full size */
2938 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2940 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2946 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2947 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2948 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2952 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2954 delete m_subtitle_widget;
2955 m_subtitle_widget = 0;
2956 if (m_subtitle_parser)
2958 m_subtitle_parser->stop();
2959 m_dvb_subtitle_pages.clear();
2961 if (m_teletext_parser)
2963 m_teletext_parser->setPageAndMagazine(-1, -1);
2964 m_subtitle_pages.clear();
2967 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2971 PyObject *eDVBServicePlay::getCachedSubtitle()
2975 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2978 unsigned int data = (unsigned int)tmp;
2979 int pid = (data&0xFFFF0000)>>16;
2980 ePyObject tuple = PyTuple_New(4);
2981 eDVBServicePMTHandler::program program;
2982 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2983 if (!h.getProgramInfo(program))
2985 if (program.textPid==pid) // teletext
2986 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2988 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2989 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2990 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2991 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2999 PyObject *eDVBServicePlay::getSubtitleList()
3001 if (!m_teletext_parser)
3004 ePyObject l = PyList_New(0);
3005 std::set<int> added_ttx_pages;
3007 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
3008 m_teletext_parser->m_found_subtitle_pages;
3010 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
3011 eDVBServicePMTHandler::program program;
3012 if (h.getProgramInfo(program))
3013 eDebug("getting program info failed.");
3016 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
3017 it != program.subtitleStreams.end(); ++it)
3019 switch(it->subtitling_type)
3021 case 0x01: // ebu teletext subtitles
3023 int page_number = it->teletext_page_number & 0xFF;
3024 int magazine_number = it->teletext_magazine_number & 7;
3025 int hash = magazine_number << 8 | page_number;
3026 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3028 ePyObject tuple = PyTuple_New(5);
3029 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3030 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3031 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3032 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3033 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3034 PyList_Append(l, tuple);
3036 added_ttx_pages.insert(hash);
3041 case 0x20 ... 0x23: // dvb subtitles
3043 ePyObject tuple = PyTuple_New(5);
3044 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3045 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3046 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3047 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3048 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3049 PyList_Insert(l, 0, tuple);
3057 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3058 it != subs.end(); ++it)
3060 int page_number = it->teletext_page_number & 0xFF;
3061 int magazine_number = it->teletext_magazine_number & 7;
3062 int hash = magazine_number << 8 | page_number;
3063 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3065 ePyObject tuple = PyTuple_New(5);
3066 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3067 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3068 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3069 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3070 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3071 PyList_Append(l, tuple);
3079 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3081 if (m_subtitle_widget)
3083 int subtitledelay = 0;
3086 m_decoder->getPTS(0, pos);
3087 if (m_is_pvr || m_timeshift_enabled)
3089 eDebug("Subtitle in recording/timeshift");
3090 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3094 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3095 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3098 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3099 eDVBTeletextSubtitlePage tmppage = page;
3100 tmppage.m_have_pts = true;
3102 if (abs(tmppage.m_pts - pos) > 20*90000)
3103 tmppage.m_pts = pos; // fix abnormal pos diffs
3105 tmppage.m_pts += subtitledelay;
3106 m_subtitle_pages.push_back(tmppage);
3107 checkSubtitleTiming();
3111 void eDVBServicePlay::checkSubtitleTiming()
3113 eDebug("checkSubtitleTiming");
3114 if (!m_subtitle_widget)
3118 enum { TELETEXT, DVB } type;
3119 eDVBTeletextSubtitlePage page;
3120 eDVBSubtitlePage dvb_page;
3122 if (!m_subtitle_pages.empty())
3124 page = m_subtitle_pages.front();
3126 show_time = page.m_pts;
3128 else if (!m_dvb_subtitle_pages.empty())
3130 dvb_page = m_dvb_subtitle_pages.front();
3132 show_time = dvb_page.m_show_time;
3140 m_decoder->getPTS(0, pos);
3142 eDebug("%lld %lld", pos, show_time);
3143 int diff = show_time - pos;
3144 if (type == TELETEXT && !page.m_have_pts)
3146 eDebug("ttx subtitle page without pts... immediate show");
3151 eDebug("[late (%d ms)]", -diff / 90);
3154 if (abs(diff) > 1800000)
3156 eDebug("[invalid]... immediate show!");
3161 if (type == TELETEXT)
3163 eDebug("display teletext subtitle page %lld", show_time);
3164 m_subtitle_widget->setPage(page);
3165 m_subtitle_pages.pop_front();
3169 eDebug("display dvb subtitle Page %lld", show_time);
3170 m_subtitle_widget->setPage(dvb_page);
3171 m_dvb_subtitle_pages.pop_front();
3175 eDebug("start subtitle delay %d", diff / 90);
3176 m_subtitle_sync_timer->start(diff / 90, 1);
3182 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3184 if (m_subtitle_widget)
3188 m_decoder->getPTS(0, pos);
3189 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3190 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3192 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3193 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3195 eDVBSubtitlePage tmppage;
3197 tmppage.m_show_time = pos + subtitledelay;
3198 m_dvb_subtitle_pages.push_back(tmppage);
3202 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3203 if (subtitledelay != 0)
3205 eDVBSubtitlePage tmppage;
3207 tmppage.m_show_time += subtitledelay;
3208 m_dvb_subtitle_pages.push_back(tmppage);
3211 m_dvb_subtitle_pages.push_back(p);
3213 checkSubtitleTiming();
3217 int eDVBServicePlay::getAC3Delay()
3220 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3222 return m_decoder->getAC3Delay();
3227 int eDVBServicePlay::getPCMDelay()
3230 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3232 return m_decoder->getPCMDelay();
3237 void eDVBServicePlay::setAC3Delay(int delay)
3240 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3242 std::string config_delay;
3243 int config_delay_int = 0;
3244 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3245 config_delay_int = atoi(config_delay.c_str());
3246 m_decoder->setAC3Delay(delay + config_delay_int);
3250 void eDVBServicePlay::setPCMDelay(int delay)
3253 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3255 std::string config_delay;
3256 int config_delay_int = 0;
3257 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3258 config_delay_int = atoi(config_delay.c_str());
3260 config_delay_int = 0;
3261 m_decoder->setPCMDelay(delay + config_delay_int);
3265 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3267 switch(event.type) {
3268 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3269 m_event((iPlayableService*)this, evVideoSizeChanged);
3271 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3272 m_event((iPlayableService*)this, evVideoFramerateChanged);
3274 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3275 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3282 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3288 PyObject *eDVBServicePlay::getStreamingData()
3290 eDVBServicePMTHandler::program program;
3291 if (m_service_handler.getProgramInfo(program))
3296 ePyObject r = program.createPythonObject();
3297 ePtr<iDVBDemux> demux;
3298 if (!m_service_handler.getDataDemux(demux))
3301 if (!demux->getCADemuxID(demux_id))
3302 PutToDict(r, "demux", demux_id);
3309 DEFINE_REF(eDVBServicePlay)
3311 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3315 case iServiceInformation::sTransponderData:
3316 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3320 return iStaticServiceInformation::getInfoObject(ref, w);
3323 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");