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;
380 return iServiceInformation::resNA;
384 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
388 case iServiceInformation::sDescription:
389 return m_parser.m_description;
390 case iServiceInformation::sServiceref:
391 return m_parser.m_ref.toString();
392 case iServiceInformation::sTags:
393 return m_parser.m_tags;
399 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
403 case iServiceInformation::sFileSize:
404 return PyLong_FromLongLong(m_parser.m_filesize);
410 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
412 if (!ref.path.empty())
414 if (ref.path.substr(0, 7) == "http://")
416 eServiceReference equivalentref(ref);
417 /* this might be a scrambled stream (id + 0x100), force equivalent dvb type */
418 equivalentref.type = eServiceFactoryDVB::id;
419 equivalentref.path.clear();
420 return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
424 ePtr<eServiceEvent> event = new eServiceEvent;
425 std::string filename = ref.path;
426 filename.erase(filename.length()-2, 2);
428 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
439 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
441 DECLARE_REF(eDVBPVRServiceOfflineOperations);
442 eServiceReferenceDVB m_ref;
444 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
446 RESULT deleteFromDisk(int simulate);
447 RESULT getListOfFilenames(std::list<std::string> &);
451 DEFINE_REF(eDVBPVRServiceOfflineOperations);
453 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
457 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
463 std::list<std::string> res;
464 if (getListOfFilenames(res))
467 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
469 eDebug("FATAL !! can't get background file eraser");
471 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
473 eDebug("Removing %s...", i->c_str());
475 eraser->erase(i->c_str());
477 ::unlink(i->c_str());
484 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
487 res.push_back(m_ref.path);
489 // handling for old splitted recordings (enigma 1)
494 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
496 if (stat(buf, &s) < 0)
501 res.push_back(m_ref.path + ".meta");
502 res.push_back(m_ref.path + ".ap");
503 res.push_back(m_ref.path + ".sc");
504 res.push_back(m_ref.path + ".cuts");
505 std::string tmp = m_ref.path;
506 tmp.erase(m_ref.path.length()-3);
507 res.push_back(tmp + ".eit");
511 RESULT eDVBPVRServiceOfflineOperations::reindex()
513 const char *filename = m_ref.path.c_str();
514 eDebug("reindexing %s...", filename);
516 eMPEGStreamInformation info;
517 eMPEGStreamParserTS parser(info);
519 info.startSave(filename);
523 int err = f.open(m_ref.path.c_str(), 0);
528 off_t length = f.length();
529 unsigned char buffer[188*256*4];
532 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
533 int r = f.read(offset, buffer, sizeof(buffer));
539 parser.parseData(offset, buffer, r);
548 DEFINE_REF(eServiceFactoryDVB)
550 eServiceFactoryDVB::eServiceFactoryDVB()
552 ePtr<eServiceCenter> sc;
554 eServiceCenter::getPrivInstance(sc);
557 std::list<std::string> extensions;
558 extensions.push_back("ts");
559 extensions.push_back("trp");
560 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
563 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
564 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
567 eServiceFactoryDVB::~eServiceFactoryDVB()
569 ePtr<eServiceCenter> sc;
571 eServiceCenter::getPrivInstance(sc);
573 sc->removeServiceFactory(eServiceFactoryDVB::id);
576 DEFINE_REF(eDVBServiceList);
578 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
582 eDVBServiceList::~eDVBServiceList()
586 RESULT eDVBServiceList::startQuery()
588 ePtr<iDVBChannelList> db;
589 ePtr<eDVBResourceManager> res;
592 if ((err = eDVBResourceManager::getInstance(res)) != 0)
594 eDebug("no resource manager");
597 if ((err = res->getChannelList(db)) != 0)
599 eDebug("no channel list");
603 ePtr<eDVBChannelQuery> q;
605 if (!m_parent.path.empty())
607 eDVBChannelQuery::compile(q, m_parent.path);
610 eDebug("compile query failed");
615 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
617 eDebug("startQuery failed");
624 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
626 eServiceReferenceDVB ref;
631 while (!m_query->getNextResult(ref))
635 list.sort(iListableServiceCompare(this));
640 // The first argument of this function is a format string to specify the order and
641 // the content of the returned list
642 // useable format options are
643 // R = Service Reference (as swig object .. this is very slow)
644 // S = Service Reference (as python string object .. same as ref.toString())
645 // C = Service Reference (as python string object .. same as ref.toCompareString())
646 // N = Service Name (as python string object)
647 // n = Short Service Name (short name brakets used) (as python string object)
648 // when exactly one return value per service is selected in the format string,
649 // then each value is directly a list entry
650 // when more than one value is returned per service, then the list is a list of
652 // unknown format string chars are returned as python None values !
653 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
656 std::list<eServiceReference> tmplist;
659 if (!format || !(retcount=strlen(format)))
660 format = "R"; // just return service reference swig object ...
662 if (!getContent(tmplist, sorted))
664 int services=tmplist.size();
665 ePtr<iStaticServiceInformation> sptr;
666 eServiceCenterPtr service_center;
668 if (strchr(format, 'N') || strchr(format, 'n'))
669 eServiceCenter::getPrivInstance(service_center);
671 ret = PyList_New(services);
672 std::list<eServiceReference>::iterator it(tmplist.begin());
674 for (int cnt=0; cnt < services; ++cnt)
676 eServiceReference &ref=*it++;
677 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
678 for (int i=0; i < retcount; ++i)
683 case 'R': // service reference (swig)object
684 tmp = NEW_eServiceReference(ref);
686 case 'C': // service reference compare string
687 tmp = PyString_FromString(ref.toCompareString().c_str());
689 case 'S': // service reference string
690 tmp = PyString_FromString(ref.toString().c_str());
692 case 'N': // service name
695 service_center->info(ref, sptr);
699 sptr->getName(ref, name);
701 // filter short name brakets
703 while((pos = name.find("\xc2\x86")) != std::string::npos)
705 while((pos = name.find("\xc2\x87")) != std::string::npos)
709 tmp = PyString_FromString(name.c_str());
713 tmp = PyString_FromString("<n/a>");
715 case 'n': // short service name
718 service_center->info(ref, sptr);
722 sptr->getName(ref, name);
723 name = buildShortName(name);
725 tmp = PyString_FromString(name.c_str());
729 tmp = PyString_FromString("<n/a>");
742 PyTuple_SET_ITEM(tuple, i, tmp);
744 PyList_SET_ITEM(ret, cnt, tmp);
748 PyList_SET_ITEM(ret, cnt, tuple);
751 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
754 RESULT eDVBServiceList::getNext(eServiceReference &ref)
759 return m_query->getNextResult((eServiceReferenceDVB&)ref);
762 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
764 if (m_parent.flags & eServiceReference::canDescent) // bouquet
766 ePtr<iDVBChannelList> db;
767 ePtr<eDVBResourceManager> resm;
769 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
772 if (db->getBouquet(m_parent, m_bouquet) != 0)
783 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
787 return m_bouquet->addService(ref, before);
790 RESULT eDVBServiceList::removeService(eServiceReference &ref)
794 return m_bouquet->removeService(ref);
797 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
801 return m_bouquet->moveService(ref, pos);
804 RESULT eDVBServiceList::flushChanges()
808 return m_bouquet->flushChanges();
811 RESULT eDVBServiceList::setListName(const std::string &name)
815 return m_bouquet->setListName(name);
818 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
820 ePtr<eDVBService> service;
822 int r = lookupService(service, ref);
825 // check resources...
826 if (eFCCServiceManager::checkAvailable(ref))
827 ptr = new eDVBServiceFCCPlay(ref, service);
829 ptr = new eDVBServicePlay(ref, service);
833 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
835 if (ref.path.empty())
837 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
841 bool isstream = ref.path.substr(0, 7) == "http://";
844 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref, isstream);
852 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
854 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
855 if (list->startQuery())
865 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
867 /* is a listable service? */
868 if (ref.flags & eServiceReference::canDescent) // bouquet
870 if ( !ref.name.empty() ) // satellites or providers list
871 ptr = m_StaticServiceDVBInfo;
872 else // a dvb bouquet
873 ptr = m_StaticServiceDVBBouquetInfo;
875 else if (!ref.path.empty()) /* do we have a PVR service? */
876 ptr = new eStaticServiceDVBPVRInformation(ref);
877 else // normal dvb service
879 ePtr<eDVBService> service;
880 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
881 ptr = m_StaticServiceDVBInfo;
883 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
889 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
891 if (ref.path.empty())
897 ptr = new eDVBPVRServiceOfflineOperations(ref);
902 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
904 if (!ref.path.empty()) // playback
906 eDVBMetaParser parser;
907 int ret=parser.parseFile(ref.path);
908 service = new eDVBService;
910 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
914 // TODO: handle the listing itself
915 // if (ref.... == -1) .. return "... bouquets ...";
916 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
918 ePtr<iDVBChannelList> db;
919 ePtr<eDVBResourceManager> res;
922 if ((err = eDVBResourceManager::getInstance(res)) != 0)
924 eDebug("no resource manager");
927 if ((err = res->getChannelList(db)) != 0)
929 eDebug("no channel list");
933 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
934 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
936 // eDebug("getService failed!");
944 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service, bool connect_event):
945 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
948 m_is_stream = m_reference.path.substr(0, 7) == "http://";
949 m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
951 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
952 m_skipmode = m_fastforward = m_slowmotion = 0;
955 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
957 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
958 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
960 m_cuesheet_changed = 0;
961 m_cutlist_enabled = 1;
963 m_subtitle_widget = 0;
967 m_subtitle_sync_timer = eTimer::create(eApp);
969 m_current_video_pid_type = 0;
971 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
974 eDVBServicePlay::~eDVBServicePlay()
979 int ret=meta.parseFile(m_reference.path);
983 meta.m_service_data="";
984 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
985 meta.m_service_data += tmp;
987 for (int x=0; x < eDVBService::cacheMax; ++x)
989 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
992 sprintf(tmp, ",c:%02d%04x", x, entry);
993 meta.m_service_data += tmp;
996 meta.updateMeta(m_reference.path);
999 delete m_subtitle_widget;
1002 void eDVBServicePlay::gotNewEvent()
1006 ePtr<eServiceEvent> m_event_now, m_event_next;
1007 getEvent(m_event_now, 0);
1008 getEvent(m_event_next, 1);
1011 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1013 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1015 m_event((iPlayableService*)this, evUpdatedEventInfo);
1018 void eDVBServicePlay::serviceEvent(int event)
1020 m_tune_state = event;
1024 case eDVBServicePMTHandler::eventTuned:
1026 ePtr<iDVBDemux> m_demux;
1027 if (!m_service_handler.getDataDemux(m_demux))
1029 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1030 int sid = ref.getParentServiceID().get();
1032 sid = ref.getServiceID().get();
1033 if ( ref.getParentTransportStreamID().get() &&
1034 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1035 m_event_handler.startOther(m_demux, sid);
1037 m_event_handler.start(m_demux, sid);
1039 m_event((iPlayableService*)this, evTunedIn);
1042 case eDVBServicePMTHandler::eventNoResources:
1043 case eDVBServicePMTHandler::eventNoPAT:
1044 case eDVBServicePMTHandler::eventNoPATEntry:
1045 case eDVBServicePMTHandler::eventNoPMT:
1046 case eDVBServicePMTHandler::eventTuneFailed:
1047 case eDVBServicePMTHandler::eventMisconfiguration:
1049 eDebug("DVB service failed to tune - error %d", event);
1050 m_event((iPlayableService*)this, evTuneFailed);
1053 case eDVBServicePMTHandler::eventNewProgramInfo:
1055 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1056 if (m_timeshift_enabled)
1057 updateTimeshiftPids();
1058 if (!m_timeshift_active)
1060 if (m_first_program_info & 1 && m_is_pvr)
1062 m_first_program_info &= ~1;
1065 if (!m_timeshift_active)
1066 m_event((iPlayableService*)this, evUpdatedInfo);
1069 case eDVBServicePMTHandler::eventPreStart:
1072 case eDVBServicePMTHandler::eventEOF:
1073 m_event((iPlayableService*)this, evEOF);
1075 case eDVBServicePMTHandler::eventSOF:
1076 m_event((iPlayableService*)this, evSOF);
1078 case eDVBServicePMTHandler::eventHBBTVInfo:
1079 m_event((iPlayableService*)this, evHBBTVInfo);
1084 void eDVBServicePlay::serviceEventTimeshift(int event)
1088 case eDVBServicePMTHandler::eventNewProgramInfo:
1089 eDebug("eventNewProgramInfo TS");
1090 if (m_timeshift_active)
1093 if (m_first_program_info & 2)
1097 eDebug("re-apply slowmotion after timeshift file change");
1098 m_decoder->setSlowMotion(m_slowmotion);
1102 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1104 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1105 if (m_fastforward != 1)
1106 m_decoder->setFastForward(m_fastforward);
1108 m_decoder->setTrickmode();
1112 m_first_program_info &= ~2;
1114 m_event((iPlayableService*)this, evUpdatedInfo);
1117 case eDVBServicePMTHandler::eventSOF:
1119 if (!m_timeshift_file_next.empty())
1121 eDebug("timeshift SOF, switch to next file");
1124 m_first_program_info |= 2;
1126 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1127 r.path = m_timeshift_file_next;
1129 /* free the timeshift service handler, we need the resources */
1130 m_service_handler_timeshift.free();
1134 m_cue->seekTo(0, -1000);
1135 ePtr<iTsSource> source = createTsSource(r);
1136 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1138 m_event((iPlayableService*)this, evUser+1);
1142 m_event((iPlayableService*)this, evSOF);
1144 case eDVBServicePMTHandler::eventEOF:
1145 if ((!m_is_paused) && (m_skipmode >= 0))
1147 if (m_timeshift_file_next.empty())
1149 eDebug("timeshift EOF, so let's go live");
1154 eDebug("timeshift EOF, switch to next file");
1156 m_first_program_info |= 2;
1158 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1159 r.path = m_timeshift_file_next;
1161 /* free the timeshift service handler, we need the resources */
1162 m_service_handler_timeshift.free();
1165 ePtr<iTsSource> source = createTsSource(r);
1166 m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file_next.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1168 m_event((iPlayableService*)this, evUser+1);
1172 case eDVBServicePMTHandler::eventNoDiskSpace:
1173 eDebug("No space!");
1174 m_event((iPlayableService*)this, evUser+3);
1179 RESULT eDVBServicePlay::start()
1181 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1183 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1184 two (one for decoding, one for data source), as we must be prepared
1185 to start recording from the data demux. */
1188 eDVBMetaParser meta;
1189 if (!meta.parseFile(m_reference.path))
1191 service = meta.m_ref;
1192 service.path = m_reference.path;
1194 m_cue = new eCueSheet();
1197 m_event(this, evStart);
1199 m_first_program_info = 1;
1200 ePtr<iTsSource> source = createTsSource(service);
1201 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1205 /* inject EIT if there is a stored one */
1206 std::string filename = service.path;
1207 filename.erase(filename.length()-2, 2);
1209 ePtr<eServiceEvent> event = new eServiceEvent;
1210 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1212 ePtr<eServiceEvent> empty;
1213 m_event_handler.inject(event, 0);
1214 m_event_handler.inject(empty, 1);
1216 m_event(this, evStart);
1221 RESULT eDVBServicePlay::stop()
1223 /* add bookmark for last play position */
1226 pts_t play_position, length;
1227 if (!getPlayPosition(play_position))
1229 /* remove last position */
1230 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1232 if (i->what == 3) /* current play position */
1234 m_cue_entries.erase(i);
1235 i = m_cue_entries.begin();
1241 if (getLength(length))
1246 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1248 m_cuesheet_changed = 1;
1252 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1254 m_service_handler_timeshift.free();
1255 m_service_handler.free();
1257 if (m_is_pvr && m_cuesheet_changed)
1260 /* save cuesheet only when main file is accessible. */
1261 if (!::stat(m_reference.path.c_str(), &s))
1264 m_event((iPlayableService*)this, evStopped);
1268 RESULT eDVBServicePlay::setTarget(int target)
1270 m_is_primary = !target;
1274 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1276 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1280 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1282 /* note: we check for timeshift to be enabled,
1283 not neccessary active. if you pause when timeshift
1284 is not active, you should activate it when unpausing */
1285 if ((!m_is_pvr) && (!m_timeshift_enabled))
1295 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1297 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1298 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1299 setFastForward_internal(0);
1302 m_slowmotion = ratio;
1303 return m_decoder->setSlowMotion(ratio);
1309 RESULT eDVBServicePlay::setFastForward(int ratio)
1311 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1313 return setFastForward_internal(ratio);
1316 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1318 int skipmode, ffratio, ret = 0;
1325 } else if (ratio > 0)
1333 } else // if (ratio < 0)
1339 if (m_skipmode != skipmode)
1341 eDebug("setting cue skipmode to %d", skipmode);
1344 long long _skipmode = skipmode;
1345 if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1348 _skipmode = skipmode * 3;
1350 _skipmode = skipmode * 4;
1353 m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1357 m_skipmode = skipmode;
1360 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1362 m_fastforward = ffratio;
1368 ; /* return m_decoder->play(); is done in caller*/
1369 else if (ffratio != 1)
1370 ret = m_decoder->setFastForward(ffratio);
1372 ret = m_decoder->setTrickmode();
1375 eDebug("final seek after trickplay ret %d", seekTo(pos));
1380 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1382 if (m_is_pvr || m_timeshift_enabled)
1392 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1393 RESULT eDVBServicePlay::getLength(pts_t &len)
1395 ePtr<iDVBPVRChannel> pvr_channel;
1397 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1400 return pvr_channel->getLength(len);
1403 RESULT eDVBServicePlay::pause()
1405 eDebug("eDVBServicePlay::pause");
1406 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1411 return m_decoder->pause();
1416 RESULT eDVBServicePlay::unpause()
1418 eDebug("eDVBServicePlay::unpause");
1419 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1424 return m_decoder->play();
1429 RESULT eDVBServicePlay::seekTo(pts_t to)
1431 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1433 if (!m_decode_demux)
1436 ePtr<iDVBPVRChannel> pvr_channel;
1438 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1444 m_cue->seekTo(0, to);
1445 m_dvb_subtitle_pages.clear();
1446 m_subtitle_pages.clear();
1451 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1453 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1455 if (!m_decode_demux)
1458 ePtr<iDVBPVRChannel> pvr_channel;
1460 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1465 /* HACK until we have skip-AP api */
1466 if ((to > 0) && (to < 100))
1474 m_cue->seekTo(mode, to);
1475 m_dvb_subtitle_pages.clear();
1476 m_subtitle_pages.clear();
1480 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1482 ePtr<iDVBPVRChannel> pvr_channel;
1484 if (!m_decode_demux)
1487 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1492 /* if there is a decoder, use audio or video PTS */
1495 r = m_decoder->getPTS(0, pos);
1501 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1504 RESULT eDVBServicePlay::setTrickmode(int trick)
1506 /* currently unimplemented */
1510 RESULT eDVBServicePlay::isCurrentlySeekable()
1515 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1516 if (m_decoder->getVideoProgressive() == -1)
1522 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1528 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1534 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1540 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1546 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1552 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1555 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1556 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1558 if (!m_timeshift_enabled)
1560 /* query config path */
1562 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1563 eDebug("could not query ts path from config");
1567 /* we need enough diskspace */
1569 if (statfs(tspath.c_str(), &fs) < 0)
1571 eDebug("statfs failed!");
1575 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1577 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1587 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1598 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1604 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1610 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1616 RESULT eDVBServicePlay::getName(std::string &name)
1620 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1621 return i->getName(m_reference, name);
1623 else if (m_is_stream)
1625 name = m_reference.name;
1628 name = m_reference.path;
1635 else if (m_dvb_service)
1637 m_dvb_service->getName(m_reference, name);
1641 else if (!m_reference.name.empty())
1642 eStaticServiceDVBInformation().getName(m_reference, name);
1644 name = "DVB service";
1648 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1650 return m_event_handler.getEvent(evt, nownext);
1653 int eDVBServicePlay::getInfo(int w)
1655 eDVBServicePMTHandler::program program;
1657 if (w == sCAIDs || w == sCAIDPIDs)
1658 return resIsPyObject;
1660 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1662 int no_program_info = 0;
1664 if (h.getProgramInfo(program))
1665 no_program_info = 1;
1671 return m_decoder->getVideoHeight();
1675 return m_decoder->getVideoWidth();
1679 return m_decoder->getVideoFrameRate();
1683 return m_decoder->getVideoProgressive();
1689 aspect = m_decoder->getVideoAspect();
1690 if (aspect == -1 && no_program_info)
1692 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1694 ePtr<eServiceEvent> evt;
1695 if (!m_event_handler.getEvent(evt, 0))
1697 ePtr<eComponentData> data;
1698 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1700 if ( data->getStreamContent() == 1 )
1702 switch(data->getComponentType())
1705 case 1: // 4:3 SD PAL
1707 case 3: // 16:9 SD PAL
1708 case 4: // > 16:9 PAL
1709 case 5: // 4:3 SD NTSC
1711 case 7: // 16:9 SD NTSC
1712 case 8: // > 16:9 NTSC
1715 case 9: // 4:3 HD PAL
1717 case 0xB: // 16:9 HD PAL
1718 case 0xC: // > 16:9 HD PAL
1719 case 0xD: // 4:3 HD NTSC
1721 case 0xF: // 16:9 HD NTSC
1722 case 0x10: // > 16:9 HD PAL
1723 return data->getComponentType();
1733 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1737 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1741 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1742 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1746 int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
1749 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1752 apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
1755 apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
1758 apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
1762 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1766 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1770 if (no_program_info) return -1; return program.pcrPid;
1771 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1772 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1773 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1774 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1775 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1776 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1777 case sProvider: if (!m_dvb_service) return -1; return -2;
1778 case sServiceref: return resIsString;
1779 case sDVBState: return m_tune_state;
1786 std::string eDVBServicePlay::getInfoString(int w)
1791 if (!m_dvb_service) return "";
1792 return m_dvb_service->m_provider_name;
1794 return m_reference.toString();
1798 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1802 case sLiveStreamDemuxId:
1805 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1815 return iServiceInformation::getInfoString(w);
1818 PyObject *eDVBServicePlay::getInfoObject(int w)
1823 return m_service_handler.getCaIds();
1825 return m_service_handler.getCaIds(true);
1826 case sTransponderData:
1827 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1830 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1831 return h.getHbbTVApplications();
1836 return iServiceInformation::getInfoObject(w);
1839 int eDVBServicePlay::getNumberOfTracks()
1841 eDVBServicePMTHandler::program program;
1842 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1843 if (h.getProgramInfo(program))
1845 return program.audioStreams.size();
1848 int eDVBServicePlay::getCurrentTrack()
1850 eDVBServicePMTHandler::program program;
1851 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1852 if (h.getProgramInfo(program))
1855 int max = program.audioStreams.size();
1858 for (i = 0; i < max; ++i)
1859 if (program.audioStreams[i].pid == m_current_audio_pid)
1865 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1867 int ret = selectAudioStream(i);
1869 if (m_decoder->set())
1875 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1877 eDVBServicePMTHandler::program program;
1878 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1880 if (h.getProgramInfo(program))
1883 if (i >= program.audioStreams.size())
1886 info.m_pid = program.audioStreams[i].pid;
1888 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1889 info.m_description = "MPEG";
1890 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1891 info.m_description = "Dolby Digital";
1892 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1893 info.m_description = "Dolby Digital+";
1894 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1895 info.m_description = "AAC";
1896 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1897 info.m_description = "AAC-HE";
1898 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1899 info.m_description = "DTS";
1900 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1901 info.m_description = "DTS-HD";
1903 info.m_description = "???";
1905 if (program.audioStreams[i].component_tag != -1)
1907 ePtr<eServiceEvent> evt;
1908 if (!m_event_handler.getEvent(evt, 0))
1910 ePtr<eComponentData> data;
1911 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1912 info.m_language = data->getText();
1916 if (info.m_language.empty())
1917 info.m_language = program.audioStreams[i].language_code;
1922 int eDVBServicePlay::selectAudioStream(int i)
1924 eDVBServicePMTHandler::program program;
1925 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1926 pts_t position = -1;
1928 if (h.getProgramInfo(program))
1931 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1939 stream = program.defaultAudioStream;
1941 int apid = -1, apidtype = -1;
1943 if (((unsigned int)stream) < program.audioStreams.size())
1945 apid = program.audioStreams[stream].pid;
1946 apidtype = program.audioStreams[stream].type;
1949 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1950 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1952 m_current_audio_pid = apid;
1954 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1956 eDebug("set audio pid failed");
1961 eDebug("seekTo ret %d", seekTo(position));
1965 /* 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 */
1966 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1968 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1970 rdsPid = program.audioStreams[stream].rdsPid;
1971 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1974 ePtr<iDVBDemux> data_demux;
1975 if (!h.getDataDemux(data_demux))
1977 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1978 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1979 m_rds_decoder->start(rdsPid);
1984 /* store new pid as default only when:
1985 a.) we have an entry in the service db for the current service,
1986 b.) we are not playing back something,
1987 c.) we are not selecting the default entry. (we wouldn't change
1988 anything in the best case, or destroy the default setting in
1989 case the real default is not yet available.)
1991 if (m_dvb_service && ((i != -1)
1992 || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
1993 && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
1994 && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
1995 && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
1996 && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
1998 m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
1999 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
2000 m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
2001 m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
2002 m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
2005 h.resetCachedProgram();
2010 int eDVBServicePlay::getCurrentChannel()
2012 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
2015 RESULT eDVBServicePlay::selectChannel(int i)
2017 if (i < LEFT || i > RIGHT || i == STEREO)
2020 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2022 m_decoder->setAudioChannel(i);
2026 std::string eDVBServicePlay::getText(int x)
2032 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2034 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2039 void eDVBServicePlay::rdsDecoderEvent(int what)
2043 case eDVBRdsDecoder::RadioTextChanged:
2044 m_event((iPlayableService*)this, evUpdatedRadioText);
2046 case eDVBRdsDecoder::RtpTextChanged:
2047 m_event((iPlayableService*)this, evUpdatedRtpText);
2049 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2050 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2052 case eDVBRdsDecoder::RecvRassSlidePic:
2053 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2058 void eDVBServicePlay::showRassSlidePicture()
2064 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2065 if (rass_slide_pic.length())
2066 m_decoder->showSinglePic(rass_slide_pic.c_str());
2068 eDebug("empty filename for rass slide picture received!!");
2071 eDebug("no MPEG Decoder to show iframes avail");
2074 eDebug("showRassSlidePicture called.. but not decoder");
2077 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2083 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2084 if (rass_interactive_pic.length())
2085 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2087 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2090 eDebug("no MPEG Decoder to show iframes avail");
2093 eDebug("showRassInteractivePic called.. but not decoder");
2096 ePyObject eDVBServicePlay::getRassInteractiveMask()
2099 return m_rds_decoder->getRassPictureMask();
2103 int eDVBServiceBase::getFrontendInfo(int w)
2105 eUsePtr<iDVBChannel> channel;
2106 if(m_service_handler.getChannel(channel))
2108 ePtr<iDVBFrontend> fe;
2109 if(channel->getFrontend(fe))
2111 return fe->readFrontendData(w);
2114 PyObject *eDVBServiceBase::getFrontendData()
2116 ePyObject ret = PyDict_New();
2119 eUsePtr<iDVBChannel> channel;
2120 if(!m_service_handler.getChannel(channel))
2122 ePtr<iDVBFrontend> fe;
2123 if(!channel->getFrontend(fe))
2124 fe->getFrontendData(ret);
2132 PyObject *eDVBServiceBase::getFrontendStatus()
2134 ePyObject ret = PyDict_New();
2137 eUsePtr<iDVBChannel> channel;
2138 if(!m_service_handler.getChannel(channel))
2140 ePtr<iDVBFrontend> fe;
2141 if(!channel->getFrontend(fe))
2142 fe->getFrontendStatus(ret);
2150 PyObject *eDVBServiceBase::getTransponderData(bool original)
2152 ePyObject ret = PyDict_New();
2155 eUsePtr<iDVBChannel> channel;
2156 if(!m_service_handler.getChannel(channel))
2158 ePtr<iDVBFrontend> fe;
2159 if(!channel->getFrontend(fe))
2160 fe->getTransponderData(ret, original);
2168 PyObject *eDVBServiceBase::getAll(bool original)
2170 ePyObject ret = getTransponderData(original);
2173 eUsePtr<iDVBChannel> channel;
2174 if(!m_service_handler.getChannel(channel))
2176 ePtr<iDVBFrontend> fe;
2177 if(!channel->getFrontend(fe))
2179 fe->getFrontendData(ret);
2180 fe->getFrontendStatus(ret);
2187 int eDVBServicePlay::getNumberOfSubservices()
2189 ePtr<eServiceEvent> evt;
2190 if (!m_event_handler.getEvent(evt, 0))
2191 return evt->getNumOfLinkageServices();
2195 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2197 ePtr<eServiceEvent> evt;
2198 if (!m_event_handler.getEvent(evt, 0))
2200 if (!evt->getLinkageService(sub, m_reference, n))
2203 sub.type=eServiceReference::idInvalid;
2207 RESULT eDVBServicePlay::startTimeshift()
2209 ePtr<iDVBDemux> demux;
2211 eDebug("Start timeshift!");
2213 if (m_timeshift_enabled)
2216 /* start recording with the data demux. */
2217 if (m_service_handler.getDataDemux(demux))
2220 demux->createTSRecorder(m_record);
2225 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2226 eDebug("could not query ts path");
2229 tspath.append("/timeshift.XXXXXX");
2231 templ = new char[tspath.length() + 1];
2232 strcpy(templ, tspath.c_str());
2234 m_timeshift_fd = mkstemp(templ);
2235 m_timeshift_file = std::string(templ);
2237 eDebug("recording to %s", templ);
2241 if (m_timeshift_fd < 0)
2247 m_record->setTargetFD(m_timeshift_fd);
2248 m_record->setTargetFilename(m_timeshift_file.c_str());
2249 m_record->enableAccessPoints(false);
2251 m_timeshift_enabled = 1;
2253 updateTimeshiftPids();
2259 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2261 if (!m_timeshift_enabled)
2267 m_timeshift_enabled = 0;
2272 close(m_timeshift_fd);
2273 eDebug("remove timeshift file");
2274 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2277 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2278 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2284 int eDVBServicePlay::isTimeshiftActive()
2286 return m_timeshift_enabled && m_timeshift_active;
2289 RESULT eDVBServicePlay::activateTimeshift()
2291 if (!m_timeshift_enabled)
2294 if (!m_timeshift_active)
2296 switchToTimeshift();
2303 PyObject *eDVBServicePlay::getCutList()
2305 ePyObject list = PyList_New(0);
2307 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2309 ePyObject tuple = PyTuple_New(2);
2310 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2311 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2312 PyList_Append(list, tuple);
2319 void eDVBServicePlay::setCutList(ePyObject list)
2321 if (!PyList_Check(list))
2323 int size = PyList_Size(list);
2326 m_cue_entries.clear();
2328 for (i=0; i<size; ++i)
2330 ePyObject tuple = PyList_GET_ITEM(list, i);
2331 if (!PyTuple_Check(tuple))
2333 eDebug("non-tuple in cutlist");
2336 if (PyTuple_Size(tuple) != 2)
2338 eDebug("cutlist entries need to be a 2-tuple");
2341 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2342 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2344 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2347 pts_t pts = PyLong_AsLongLong(ppts);
2348 int type = PyInt_AsLong(ptype);
2349 m_cue_entries.insert(cueEntry(pts, type));
2350 eDebug("adding %08llx, %d", pts, type);
2352 m_cuesheet_changed = 1;
2354 cutlistToCuesheet();
2355 m_event((iPlayableService*)this, evCuesheetChanged);
2358 void eDVBServicePlay::setCutListEnable(int enable)
2360 m_cutlist_enabled = enable;
2361 cutlistToCuesheet();
2364 void eDVBServicePlay::updateTimeshiftPids()
2369 eDVBServicePMTHandler::program program;
2370 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2372 if (h.getProgramInfo(program))
2376 int timing_pid = -1;
2377 int timing_pid_type = -1;
2378 std::set<int> pids_to_record;
2379 pids_to_record.insert(0); // PAT
2380 if (program.pmtPid != -1)
2381 pids_to_record.insert(program.pmtPid); // PMT
2383 if (program.textPid != -1)
2384 pids_to_record.insert(program.textPid); // Videotext
2386 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2387 i(program.videoStreams.begin());
2388 i != program.videoStreams.end(); ++i)
2390 pids_to_record.insert(i->pid);
2392 if (timing_pid == -1)
2394 timing_pid = i->pid;
2395 timing_pid_type = i->type;
2399 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2400 i(program.audioStreams.begin());
2401 i != program.audioStreams.end(); ++i)
2403 pids_to_record.insert(i->pid);
2405 if (timing_pid == -1)
2407 timing_pid = i->pid;
2408 timing_pid_type = -1;
2412 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2413 i(program.subtitleStreams.begin());
2414 i != program.subtitleStreams.end(); ++i)
2415 pids_to_record.insert(i->pid);
2417 std::set<int> new_pids, obsolete_pids;
2419 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2420 m_pids_active.begin(), m_pids_active.end(),
2421 std::inserter(new_pids, new_pids.begin()));
2423 std::set_difference(
2424 m_pids_active.begin(), m_pids_active.end(),
2425 pids_to_record.begin(), pids_to_record.end(),
2426 std::inserter(new_pids, new_pids.begin())
2429 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2430 m_record->addPID(*i);
2432 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2433 m_record->removePID(*i);
2435 if (timing_pid != -1)
2436 m_record->setTimingPID(timing_pid, timing_pid_type);
2440 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2442 m_timeshift_file_next = f;
2446 void eDVBServicePlay::switchToLive()
2448 if (!m_timeshift_active)
2451 eDebug("SwitchToLive");
2455 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2457 /* free the timeshift service handler, we need the resources */
2458 m_service_handler_timeshift.free();
2460 updateDecoder(true);
2463 void eDVBServicePlay::resetTimeshift(int start)
2468 m_teletext_parser = 0;
2470 m_subtitle_parser = 0;
2471 m_new_subtitle_page_connection = 0;
2472 m_new_dvb_subtitle_page_connection = 0;
2473 m_rds_decoder_event_connection = 0;
2474 m_video_event_connection = 0;
2475 m_timeshift_changed = 1;
2476 m_timeshift_file_next.clear();
2480 m_cue = new eCueSheet();
2481 m_timeshift_active = 1;
2484 m_timeshift_active = 0;
2487 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2491 eHttpStream *f = new eHttpStream();
2492 f->open(ref.path.c_str());
2493 return ePtr<iTsSource>(f);
2497 eRawFile *f = new eRawFile();
2498 f->open(ref.path.c_str());
2499 return ePtr<iTsSource>(f);
2503 void eDVBServicePlay::switchToTimeshift()
2505 if (m_timeshift_active)
2510 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2511 r.path = m_timeshift_file;
2513 m_cue->seekTo(0, -1000);
2515 ePtr<iTsSource> source = createTsSource(r);
2516 m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2518 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2520 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2523 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2525 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2526 bool mustPlay = false;
2528 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2530 eDVBServicePMTHandler::program program;
2531 if (h.getProgramInfo(program))
2532 eDebug("getting program info failed.");
2535 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2536 if (!program.videoStreams.empty())
2538 eDebugNoNewLine(" (");
2539 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2540 i(program.videoStreams.begin());
2541 i != program.videoStreams.end(); ++i)
2548 if (i != program.videoStreams.begin())
2549 eDebugNoNewLine(", ");
2550 eDebugNoNewLine("%04x", i->pid);
2552 eDebugNoNewLine(")");
2554 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2555 if (!program.audioStreams.empty())
2557 eDebugNoNewLine(" (");
2558 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2559 i(program.audioStreams.begin());
2560 i != program.audioStreams.end(); ++i)
2562 if (i != program.audioStreams.begin())
2563 eDebugNoNewLine(", ");
2564 eDebugNoNewLine("%04x", i->pid);
2566 eDebugNoNewLine(")");
2568 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2569 pcrpid = program.pcrPid;
2570 eDebug(", and the text pid is %04x", program.textPid);
2571 tpid = program.textPid;
2576 h.getDecodeDemux(m_decode_demux);
2579 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2581 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2584 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2585 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2586 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2587 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2588 if (m_timeshift_changed)
2590 ePyObject subs = getCachedSubtitle();
2591 if (subs != Py_None)
2593 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2594 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2595 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2596 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2597 if (type == 0) // dvb
2598 m_subtitle_parser->start(pid, comp_page, anc_page);
2599 else if (type == 1) // ttx
2600 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2607 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2611 m_timeshift_changed = 0;
2615 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2618 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2619 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2620 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2624 eServiceReferenceDVB ref;
2625 m_service_handler.getServiceReference(ref);
2626 eServiceReferenceDVB parent = ref.getParentServiceReference();
2631 ePtr<eDVBResourceManager> res_mgr;
2632 if (!eDVBResourceManager::getInstance(res_mgr))
2634 ePtr<iDVBChannelList> db;
2635 if (!res_mgr->getChannelList(db))
2637 ePtr<eDVBService> origService;
2638 if (!db->getService(parent, origService))
2640 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2641 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2648 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2649 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2651 m_decoder->setVideoPID(vpid, vpidtype);
2652 m_current_video_pid_type = vpidtype;
2653 selectAudioStream();
2655 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2656 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2657 m_decoder->setSyncPCR(pcrpid);
2659 m_decoder->setSyncPCR(-1);
2663 m_decoder->setTextPID(tpid);
2664 m_teletext_parser->start(program.textPid);
2667 if (vpid > 0 && vpid < 0x2000)
2671 std::string radio_pic;
2672 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2673 m_decoder->setRadioPic(radio_pic);
2681 m_decoder->setAudioChannel(achannel);
2683 /* don't worry about non-existing services, nor pvr services */
2686 /* (audio pid will be set in selectAudioTrack */
2687 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2688 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2689 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2690 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2692 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2693 sendSeekableStateChanged = true;
2695 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2697 if (sendSeekableStateChanged)
2698 m_event((iPlayableService*)this, evSeekableStatusChanged);
2701 void eDVBServicePlay::loadCuesheet()
2703 std::string filename = m_reference.path + ".cuts";
2705 m_cue_entries.clear();
2707 FILE *f = fopen(filename.c_str(), "rb");
2711 eDebug("loading cuts..");
2714 unsigned long long where;
2717 if (!fread(&where, sizeof(where), 1, f))
2719 if (!fread(&what, sizeof(what), 1, f))
2722 #if BYTE_ORDER == LITTLE_ENDIAN
2723 where = bswap_64(where);
2730 m_cue_entries.insert(cueEntry(where, what));
2733 eDebug("%zd entries", m_cue_entries.size());
2735 eDebug("cutfile not found!");
2737 m_cuesheet_changed = 0;
2738 cutlistToCuesheet();
2739 m_event((iPlayableService*)this, evCuesheetChanged);
2742 void eDVBServicePlay::saveCuesheet()
2744 std::string filename = m_reference.path + ".cuts";
2746 FILE *f = fopen(filename.c_str(), "wb");
2750 unsigned long long where;
2753 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2755 #if BYTE_ORDER == BIG_ENDIAN
2758 where = bswap_64(i->where);
2760 what = htonl(i->what);
2761 fwrite(&where, sizeof(where), 1, f);
2762 fwrite(&what, sizeof(what), 1, f);
2768 m_cuesheet_changed = 0;
2771 void eDVBServicePlay::cutlistToCuesheet()
2775 eDebug("no cue sheet");
2780 if (!m_cutlist_enabled)
2782 m_cue->commitSpans();
2783 eDebug("cutlists were disabled");
2787 pts_t in = 0, out = 0, length = 0;
2791 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2793 int have_any_span = 0;
2797 if (i == m_cue_entries.end())
2799 if (!have_any_span && !in)
2803 if (i->what == 0) /* in */
2807 } else if (i->what == 1) /* out */
2809 else /* mark (2) or last play position (3) */
2828 m_cue->addSourceSpan(in, out);
2834 if (i == m_cue_entries.end())
2837 m_cue->commitSpans();
2840 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2842 if (m_subtitle_widget)
2843 disableSubtitles(parent);
2846 int tuplesize = PyTuple_Size(tuple);
2849 if (!PyTuple_Check(tuple))
2855 entry = PyTuple_GET_ITEM(tuple, 0);
2857 if (!PyInt_Check(entry))
2860 type = PyInt_AsLong(entry);
2862 if (type == 1) // teletext subtitles
2864 int page, magazine, pid;
2868 if (!m_teletext_parser)
2870 eDebug("enable teletext subtitles.. no parser !!!");
2874 entry = PyTuple_GET_ITEM(tuple, 1);
2875 if (!PyInt_Check(entry))
2877 pid = PyInt_AsLong(entry);
2879 entry = PyTuple_GET_ITEM(tuple, 2);
2880 if (!PyInt_Check(entry))
2882 page = PyInt_AsLong(entry);
2884 entry = PyTuple_GET_ITEM(tuple, 3);
2885 if (!PyInt_Check(entry))
2887 magazine = PyInt_AsLong(entry);
2889 m_subtitle_widget = new eSubtitleWidget(parent);
2890 m_subtitle_widget->resize(parent->size()); /* full size */
2891 m_teletext_parser->setPageAndMagazine(page, magazine);
2893 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2897 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2898 if (!m_subtitle_parser)
2900 eDebug("enable dvb subtitles.. no parser !!!");
2906 entry = PyTuple_GET_ITEM(tuple, 1);
2907 if (!PyInt_Check(entry))
2909 pid = PyInt_AsLong(entry);
2911 entry = PyTuple_GET_ITEM(tuple, 2);
2912 if (!PyInt_Check(entry))
2914 composition_page_id = PyInt_AsLong(entry);
2916 entry = PyTuple_GET_ITEM(tuple, 3);
2917 if (!PyInt_Check(entry))
2919 ancillary_page_id = PyInt_AsLong(entry);
2921 m_subtitle_widget = new eSubtitleWidget(parent);
2922 m_subtitle_widget->resize(parent->size()); /* full size */
2923 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2925 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2931 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2932 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2933 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2937 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2939 delete m_subtitle_widget;
2940 m_subtitle_widget = 0;
2941 if (m_subtitle_parser)
2943 m_subtitle_parser->stop();
2944 m_dvb_subtitle_pages.clear();
2946 if (m_teletext_parser)
2948 m_teletext_parser->setPageAndMagazine(-1, -1);
2949 m_subtitle_pages.clear();
2952 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2956 PyObject *eDVBServicePlay::getCachedSubtitle()
2960 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2963 unsigned int data = (unsigned int)tmp;
2964 int pid = (data&0xFFFF0000)>>16;
2965 ePyObject tuple = PyTuple_New(4);
2966 eDVBServicePMTHandler::program program;
2967 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2968 if (!h.getProgramInfo(program))
2970 if (program.textPid==pid) // teletext
2971 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2973 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2974 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2975 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2976 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2984 PyObject *eDVBServicePlay::getSubtitleList()
2986 if (!m_teletext_parser)
2989 ePyObject l = PyList_New(0);
2990 std::set<int> added_ttx_pages;
2992 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2993 m_teletext_parser->m_found_subtitle_pages;
2995 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2996 eDVBServicePMTHandler::program program;
2997 if (h.getProgramInfo(program))
2998 eDebug("getting program info failed.");
3001 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
3002 it != program.subtitleStreams.end(); ++it)
3004 switch(it->subtitling_type)
3006 case 0x01: // ebu teletext subtitles
3008 int page_number = it->teletext_page_number & 0xFF;
3009 int magazine_number = it->teletext_magazine_number & 7;
3010 int hash = magazine_number << 8 | page_number;
3011 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3013 ePyObject tuple = PyTuple_New(5);
3014 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3015 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3016 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3017 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3018 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3019 PyList_Append(l, tuple);
3021 added_ttx_pages.insert(hash);
3026 case 0x20 ... 0x23: // dvb subtitles
3028 ePyObject tuple = PyTuple_New(5);
3029 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3030 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3031 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3032 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3033 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3034 PyList_Insert(l, 0, tuple);
3042 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3043 it != subs.end(); ++it)
3045 int page_number = it->teletext_page_number & 0xFF;
3046 int magazine_number = it->teletext_magazine_number & 7;
3047 int hash = magazine_number << 8 | page_number;
3048 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3050 ePyObject tuple = PyTuple_New(5);
3051 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3052 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3053 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3054 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3055 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3056 PyList_Append(l, tuple);
3064 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3066 if (m_subtitle_widget)
3068 int subtitledelay = 0;
3071 m_decoder->getPTS(0, pos);
3072 if (m_is_pvr || m_timeshift_enabled)
3074 eDebug("Subtitle in recording/timeshift");
3075 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3079 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3080 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3083 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3084 eDVBTeletextSubtitlePage tmppage = page;
3085 tmppage.m_have_pts = true;
3087 if (abs(tmppage.m_pts - pos) > 20*90000)
3088 tmppage.m_pts = pos; // fix abnormal pos diffs
3090 tmppage.m_pts += subtitledelay;
3091 m_subtitle_pages.push_back(tmppage);
3092 checkSubtitleTiming();
3096 void eDVBServicePlay::checkSubtitleTiming()
3098 eDebug("checkSubtitleTiming");
3099 if (!m_subtitle_widget)
3103 enum { TELETEXT, DVB } type;
3104 eDVBTeletextSubtitlePage page;
3105 eDVBSubtitlePage dvb_page;
3107 if (!m_subtitle_pages.empty())
3109 page = m_subtitle_pages.front();
3111 show_time = page.m_pts;
3113 else if (!m_dvb_subtitle_pages.empty())
3115 dvb_page = m_dvb_subtitle_pages.front();
3117 show_time = dvb_page.m_show_time;
3125 m_decoder->getPTS(0, pos);
3127 eDebug("%lld %lld", pos, show_time);
3128 int diff = show_time - pos;
3129 if (type == TELETEXT && !page.m_have_pts)
3131 eDebug("ttx subtitle page without pts... immediate show");
3136 eDebug("[late (%d ms)]", -diff / 90);
3139 if (abs(diff) > 1800000)
3141 eDebug("[invalid]... immediate show!");
3146 if (type == TELETEXT)
3148 eDebug("display teletext subtitle page %lld", show_time);
3149 m_subtitle_widget->setPage(page);
3150 m_subtitle_pages.pop_front();
3154 eDebug("display dvb subtitle Page %lld", show_time);
3155 m_subtitle_widget->setPage(dvb_page);
3156 m_dvb_subtitle_pages.pop_front();
3160 eDebug("start subtitle delay %d", diff / 90);
3161 m_subtitle_sync_timer->start(diff / 90, 1);
3167 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3169 if (m_subtitle_widget)
3173 m_decoder->getPTS(0, pos);
3174 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3175 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3177 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3178 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3180 eDVBSubtitlePage tmppage;
3182 tmppage.m_show_time = pos + subtitledelay;
3183 m_dvb_subtitle_pages.push_back(tmppage);
3187 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3188 if (subtitledelay != 0)
3190 eDVBSubtitlePage tmppage;
3192 tmppage.m_show_time += subtitledelay;
3193 m_dvb_subtitle_pages.push_back(tmppage);
3196 m_dvb_subtitle_pages.push_back(p);
3198 checkSubtitleTiming();
3202 int eDVBServicePlay::getAC3Delay()
3205 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3207 return m_decoder->getAC3Delay();
3212 int eDVBServicePlay::getPCMDelay()
3215 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3217 return m_decoder->getPCMDelay();
3222 void eDVBServicePlay::setAC3Delay(int delay)
3225 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3227 std::string config_delay;
3228 int config_delay_int = 0;
3229 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3230 config_delay_int = atoi(config_delay.c_str());
3231 m_decoder->setAC3Delay(delay + config_delay_int);
3235 void eDVBServicePlay::setPCMDelay(int delay)
3238 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3240 std::string config_delay;
3241 int config_delay_int = 0;
3242 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3243 config_delay_int = atoi(config_delay.c_str());
3245 config_delay_int = 0;
3246 m_decoder->setPCMDelay(delay + config_delay_int);
3250 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3252 switch(event.type) {
3253 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3254 m_event((iPlayableService*)this, evVideoSizeChanged);
3256 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3257 m_event((iPlayableService*)this, evVideoFramerateChanged);
3259 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3260 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3267 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3273 PyObject *eDVBServicePlay::getStreamingData()
3275 eDVBServicePMTHandler::program program;
3276 if (m_service_handler.getProgramInfo(program))
3281 ePyObject r = program.createPythonObject();
3282 ePtr<iDVBDemux> demux;
3283 if (!m_service_handler.getDataDemux(demux))
3286 if (!demux->getCADemuxID(demux_id))
3287 PutToDict(r, "demux", demux_id);
3294 DEFINE_REF(eDVBServicePlay)
3296 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3300 case iServiceInformation::sTransponderData:
3301 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3305 return iStaticServiceInformation::getInfoObject(ref, w);
3308 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");