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);
2250 m_record->setTimeshift(true);
2252 m_timeshift_enabled = 1;
2254 updateTimeshiftPids();
2260 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2262 if (!m_timeshift_enabled)
2268 m_timeshift_enabled = 0;
2273 close(m_timeshift_fd);
2274 eDebug("remove timeshift file");
2275 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2278 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2279 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2285 int eDVBServicePlay::isTimeshiftActive()
2287 return m_timeshift_enabled && m_timeshift_active;
2290 RESULT eDVBServicePlay::activateTimeshift()
2292 if (!m_timeshift_enabled)
2295 if (!m_timeshift_active)
2297 switchToTimeshift();
2304 PyObject *eDVBServicePlay::getCutList()
2306 ePyObject list = PyList_New(0);
2308 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2310 ePyObject tuple = PyTuple_New(2);
2311 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2312 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2313 PyList_Append(list, tuple);
2320 void eDVBServicePlay::setCutList(ePyObject list)
2322 if (!PyList_Check(list))
2324 int size = PyList_Size(list);
2327 m_cue_entries.clear();
2329 for (i=0; i<size; ++i)
2331 ePyObject tuple = PyList_GET_ITEM(list, i);
2332 if (!PyTuple_Check(tuple))
2334 eDebug("non-tuple in cutlist");
2337 if (PyTuple_Size(tuple) != 2)
2339 eDebug("cutlist entries need to be a 2-tuple");
2342 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2343 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2345 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2348 pts_t pts = PyLong_AsLongLong(ppts);
2349 int type = PyInt_AsLong(ptype);
2350 m_cue_entries.insert(cueEntry(pts, type));
2351 eDebug("adding %08llx, %d", pts, type);
2353 m_cuesheet_changed = 1;
2355 cutlistToCuesheet();
2356 m_event((iPlayableService*)this, evCuesheetChanged);
2359 void eDVBServicePlay::setCutListEnable(int enable)
2361 m_cutlist_enabled = enable;
2362 cutlistToCuesheet();
2365 void eDVBServicePlay::updateTimeshiftPids()
2370 eDVBServicePMTHandler::program program;
2371 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2373 if (h.getProgramInfo(program))
2377 int timing_pid = -1;
2378 int timing_pid_type = -1;
2379 std::set<int> pids_to_record;
2380 pids_to_record.insert(0); // PAT
2381 if (program.pmtPid != -1)
2382 pids_to_record.insert(program.pmtPid); // PMT
2384 if (program.textPid != -1)
2385 pids_to_record.insert(program.textPid); // Videotext
2387 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2388 i(program.videoStreams.begin());
2389 i != program.videoStreams.end(); ++i)
2391 pids_to_record.insert(i->pid);
2393 if (timing_pid == -1)
2395 timing_pid = i->pid;
2396 timing_pid_type = i->type;
2400 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2401 i(program.audioStreams.begin());
2402 i != program.audioStreams.end(); ++i)
2404 pids_to_record.insert(i->pid);
2406 if (timing_pid == -1)
2408 timing_pid = i->pid;
2409 timing_pid_type = -1;
2413 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2414 i(program.subtitleStreams.begin());
2415 i != program.subtitleStreams.end(); ++i)
2416 pids_to_record.insert(i->pid);
2418 std::set<int> new_pids, obsolete_pids;
2420 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2421 m_pids_active.begin(), m_pids_active.end(),
2422 std::inserter(new_pids, new_pids.begin()));
2424 std::set_difference(
2425 m_pids_active.begin(), m_pids_active.end(),
2426 pids_to_record.begin(), pids_to_record.end(),
2427 std::inserter(new_pids, new_pids.begin())
2430 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2431 m_record->addPID(*i);
2433 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2434 m_record->removePID(*i);
2436 if (timing_pid != -1)
2437 m_record->setTimingPID(timing_pid, timing_pid_type);
2441 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2443 m_timeshift_file_next = f;
2447 void eDVBServicePlay::switchToLive()
2449 if (!m_timeshift_active)
2452 eDebug("SwitchToLive");
2456 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2458 /* free the timeshift service handler, we need the resources */
2459 m_service_handler_timeshift.free();
2461 updateDecoder(true);
2464 void eDVBServicePlay::resetTimeshift(int start)
2469 m_teletext_parser = 0;
2471 m_subtitle_parser = 0;
2472 m_new_subtitle_page_connection = 0;
2473 m_new_dvb_subtitle_page_connection = 0;
2474 m_rds_decoder_event_connection = 0;
2475 m_video_event_connection = 0;
2476 m_timeshift_changed = 1;
2477 m_timeshift_file_next.clear();
2481 m_cue = new eCueSheet();
2482 m_timeshift_active = 1;
2485 m_timeshift_active = 0;
2488 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2492 eHttpStream *f = new eHttpStream();
2493 f->open(ref.path.c_str());
2494 return ePtr<iTsSource>(f);
2498 eRawFile *f = new eRawFile();
2499 f->open(ref.path.c_str());
2500 return ePtr<iTsSource>(f);
2504 void eDVBServicePlay::switchToTimeshift()
2506 if (m_timeshift_active)
2511 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2512 r.path = m_timeshift_file;
2514 m_cue->seekTo(0, -1000);
2516 ePtr<iTsSource> source = createTsSource(r);
2517 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 */
2519 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2521 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2524 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2526 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2527 bool mustPlay = false;
2529 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2531 eDVBServicePMTHandler::program program;
2532 if (h.getProgramInfo(program))
2533 eDebug("getting program info failed.");
2536 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2537 if (!program.videoStreams.empty())
2539 eDebugNoNewLine(" (");
2540 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2541 i(program.videoStreams.begin());
2542 i != program.videoStreams.end(); ++i)
2549 if (i != program.videoStreams.begin())
2550 eDebugNoNewLine(", ");
2551 eDebugNoNewLine("%04x", i->pid);
2553 eDebugNoNewLine(")");
2555 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2556 if (!program.audioStreams.empty())
2558 eDebugNoNewLine(" (");
2559 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2560 i(program.audioStreams.begin());
2561 i != program.audioStreams.end(); ++i)
2563 if (i != program.audioStreams.begin())
2564 eDebugNoNewLine(", ");
2565 eDebugNoNewLine("%04x", i->pid);
2567 eDebugNoNewLine(")");
2569 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2570 pcrpid = program.pcrPid;
2571 eDebug(", and the text pid is %04x", program.textPid);
2572 tpid = program.textPid;
2577 h.getDecodeDemux(m_decode_demux);
2580 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2582 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2585 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2586 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2587 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2588 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2589 if (m_timeshift_changed)
2591 ePyObject subs = getCachedSubtitle();
2592 if (subs != Py_None)
2594 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2595 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2596 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2597 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2598 if (type == 0) // dvb
2599 m_subtitle_parser->start(pid, comp_page, anc_page);
2600 else if (type == 1) // ttx
2601 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2608 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2612 m_timeshift_changed = 0;
2616 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2619 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2620 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2621 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2625 eServiceReferenceDVB ref;
2626 m_service_handler.getServiceReference(ref);
2627 eServiceReferenceDVB parent = ref.getParentServiceReference();
2632 ePtr<eDVBResourceManager> res_mgr;
2633 if (!eDVBResourceManager::getInstance(res_mgr))
2635 ePtr<iDVBChannelList> db;
2636 if (!res_mgr->getChannelList(db))
2638 ePtr<eDVBService> origService;
2639 if (!db->getService(parent, origService))
2641 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2642 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2649 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2650 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2652 m_decoder->setVideoPID(vpid, vpidtype);
2653 m_current_video_pid_type = vpidtype;
2654 selectAudioStream();
2656 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2657 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2658 m_decoder->setSyncPCR(pcrpid);
2660 m_decoder->setSyncPCR(-1);
2664 m_decoder->setTextPID(tpid);
2665 m_teletext_parser->start(program.textPid);
2668 if (vpid > 0 && vpid < 0x2000)
2672 std::string radio_pic;
2673 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2674 m_decoder->setRadioPic(radio_pic);
2682 m_decoder->setAudioChannel(achannel);
2684 /* don't worry about non-existing services, nor pvr services */
2687 /* (audio pid will be set in selectAudioTrack */
2688 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2689 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2690 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2691 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2693 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2694 sendSeekableStateChanged = true;
2696 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2698 if (sendSeekableStateChanged)
2699 m_event((iPlayableService*)this, evSeekableStatusChanged);
2702 void eDVBServicePlay::loadCuesheet()
2704 std::string filename = m_reference.path + ".cuts";
2706 m_cue_entries.clear();
2708 FILE *f = fopen(filename.c_str(), "rb");
2712 eDebug("loading cuts..");
2715 unsigned long long where;
2718 if (!fread(&where, sizeof(where), 1, f))
2720 if (!fread(&what, sizeof(what), 1, f))
2723 #if BYTE_ORDER == LITTLE_ENDIAN
2724 where = bswap_64(where);
2731 m_cue_entries.insert(cueEntry(where, what));
2734 eDebug("%zd entries", m_cue_entries.size());
2736 eDebug("cutfile not found!");
2738 m_cuesheet_changed = 0;
2739 cutlistToCuesheet();
2740 m_event((iPlayableService*)this, evCuesheetChanged);
2743 void eDVBServicePlay::saveCuesheet()
2745 std::string filename = m_reference.path + ".cuts";
2747 FILE *f = fopen(filename.c_str(), "wb");
2751 unsigned long long where;
2754 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2756 #if BYTE_ORDER == BIG_ENDIAN
2759 where = bswap_64(i->where);
2761 what = htonl(i->what);
2762 fwrite(&where, sizeof(where), 1, f);
2763 fwrite(&what, sizeof(what), 1, f);
2769 m_cuesheet_changed = 0;
2772 void eDVBServicePlay::cutlistToCuesheet()
2776 eDebug("no cue sheet");
2781 if (!m_cutlist_enabled)
2783 m_cue->commitSpans();
2784 eDebug("cutlists were disabled");
2788 pts_t in = 0, out = 0, length = 0;
2792 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2794 int have_any_span = 0;
2798 if (i == m_cue_entries.end())
2800 if (!have_any_span && !in)
2804 if (i->what == 0) /* in */
2808 } else if (i->what == 1) /* out */
2810 else /* mark (2) or last play position (3) */
2829 m_cue->addSourceSpan(in, out);
2835 if (i == m_cue_entries.end())
2838 m_cue->commitSpans();
2841 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2843 if (m_subtitle_widget)
2844 disableSubtitles(parent);
2847 int tuplesize = PyTuple_Size(tuple);
2850 if (!PyTuple_Check(tuple))
2856 entry = PyTuple_GET_ITEM(tuple, 0);
2858 if (!PyInt_Check(entry))
2861 type = PyInt_AsLong(entry);
2863 if (type == 1) // teletext subtitles
2865 int page, magazine, pid;
2869 if (!m_teletext_parser)
2871 eDebug("enable teletext subtitles.. no parser !!!");
2875 entry = PyTuple_GET_ITEM(tuple, 1);
2876 if (!PyInt_Check(entry))
2878 pid = PyInt_AsLong(entry);
2880 entry = PyTuple_GET_ITEM(tuple, 2);
2881 if (!PyInt_Check(entry))
2883 page = PyInt_AsLong(entry);
2885 entry = PyTuple_GET_ITEM(tuple, 3);
2886 if (!PyInt_Check(entry))
2888 magazine = PyInt_AsLong(entry);
2890 m_subtitle_widget = new eSubtitleWidget(parent);
2891 m_subtitle_widget->resize(parent->size()); /* full size */
2892 m_teletext_parser->setPageAndMagazine(page, magazine);
2894 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2898 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2899 if (!m_subtitle_parser)
2901 eDebug("enable dvb subtitles.. no parser !!!");
2907 entry = PyTuple_GET_ITEM(tuple, 1);
2908 if (!PyInt_Check(entry))
2910 pid = PyInt_AsLong(entry);
2912 entry = PyTuple_GET_ITEM(tuple, 2);
2913 if (!PyInt_Check(entry))
2915 composition_page_id = PyInt_AsLong(entry);
2917 entry = PyTuple_GET_ITEM(tuple, 3);
2918 if (!PyInt_Check(entry))
2920 ancillary_page_id = PyInt_AsLong(entry);
2922 m_subtitle_widget = new eSubtitleWidget(parent);
2923 m_subtitle_widget->resize(parent->size()); /* full size */
2924 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2926 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2932 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2933 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2934 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2938 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2940 delete m_subtitle_widget;
2941 m_subtitle_widget = 0;
2942 if (m_subtitle_parser)
2944 m_subtitle_parser->stop();
2945 m_dvb_subtitle_pages.clear();
2947 if (m_teletext_parser)
2949 m_teletext_parser->setPageAndMagazine(-1, -1);
2950 m_subtitle_pages.clear();
2953 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2957 PyObject *eDVBServicePlay::getCachedSubtitle()
2961 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2964 unsigned int data = (unsigned int)tmp;
2965 int pid = (data&0xFFFF0000)>>16;
2966 ePyObject tuple = PyTuple_New(4);
2967 eDVBServicePMTHandler::program program;
2968 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2969 if (!h.getProgramInfo(program))
2971 if (program.textPid==pid) // teletext
2972 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2974 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2975 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2976 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2977 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2985 PyObject *eDVBServicePlay::getSubtitleList()
2987 if (!m_teletext_parser)
2990 ePyObject l = PyList_New(0);
2991 std::set<int> added_ttx_pages;
2993 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2994 m_teletext_parser->m_found_subtitle_pages;
2996 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2997 eDVBServicePMTHandler::program program;
2998 if (h.getProgramInfo(program))
2999 eDebug("getting program info failed.");
3002 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
3003 it != program.subtitleStreams.end(); ++it)
3005 switch(it->subtitling_type)
3007 case 0x01: // ebu teletext subtitles
3009 int page_number = it->teletext_page_number & 0xFF;
3010 int magazine_number = it->teletext_magazine_number & 7;
3011 int hash = magazine_number << 8 | page_number;
3012 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3014 ePyObject tuple = PyTuple_New(5);
3015 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3016 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3017 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3018 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3019 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3020 PyList_Append(l, tuple);
3022 added_ttx_pages.insert(hash);
3027 case 0x20 ... 0x23: // dvb subtitles
3029 ePyObject tuple = PyTuple_New(5);
3030 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3031 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3032 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3033 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3034 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3035 PyList_Insert(l, 0, tuple);
3043 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3044 it != subs.end(); ++it)
3046 int page_number = it->teletext_page_number & 0xFF;
3047 int magazine_number = it->teletext_magazine_number & 7;
3048 int hash = magazine_number << 8 | page_number;
3049 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3051 ePyObject tuple = PyTuple_New(5);
3052 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3053 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3054 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3055 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3056 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3057 PyList_Append(l, tuple);
3065 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3067 if (m_subtitle_widget)
3069 int subtitledelay = 0;
3072 m_decoder->getPTS(0, pos);
3073 if (m_is_pvr || m_timeshift_enabled)
3075 eDebug("Subtitle in recording/timeshift");
3076 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3080 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3081 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3084 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3085 eDVBTeletextSubtitlePage tmppage = page;
3086 tmppage.m_have_pts = true;
3088 if (abs(tmppage.m_pts - pos) > 20*90000)
3089 tmppage.m_pts = pos; // fix abnormal pos diffs
3091 tmppage.m_pts += subtitledelay;
3092 m_subtitle_pages.push_back(tmppage);
3093 checkSubtitleTiming();
3097 void eDVBServicePlay::checkSubtitleTiming()
3099 eDebug("checkSubtitleTiming");
3100 if (!m_subtitle_widget)
3104 enum { TELETEXT, DVB } type;
3105 eDVBTeletextSubtitlePage page;
3106 eDVBSubtitlePage dvb_page;
3108 if (!m_subtitle_pages.empty())
3110 page = m_subtitle_pages.front();
3112 show_time = page.m_pts;
3114 else if (!m_dvb_subtitle_pages.empty())
3116 dvb_page = m_dvb_subtitle_pages.front();
3118 show_time = dvb_page.m_show_time;
3126 m_decoder->getPTS(0, pos);
3128 eDebug("%lld %lld", pos, show_time);
3129 int diff = show_time - pos;
3130 if (type == TELETEXT && !page.m_have_pts)
3132 eDebug("ttx subtitle page without pts... immediate show");
3137 eDebug("[late (%d ms)]", -diff / 90);
3140 if (abs(diff) > 1800000)
3142 eDebug("[invalid]... immediate show!");
3147 if (type == TELETEXT)
3149 eDebug("display teletext subtitle page %lld", show_time);
3150 m_subtitle_widget->setPage(page);
3151 m_subtitle_pages.pop_front();
3155 eDebug("display dvb subtitle Page %lld", show_time);
3156 m_subtitle_widget->setPage(dvb_page);
3157 m_dvb_subtitle_pages.pop_front();
3161 eDebug("start subtitle delay %d", diff / 90);
3162 m_subtitle_sync_timer->start(diff / 90, 1);
3168 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3170 if (m_subtitle_widget)
3174 m_decoder->getPTS(0, pos);
3175 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3176 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3178 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3179 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3181 eDVBSubtitlePage tmppage;
3183 tmppage.m_show_time = pos + subtitledelay;
3184 m_dvb_subtitle_pages.push_back(tmppage);
3188 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3189 if (subtitledelay != 0)
3191 eDVBSubtitlePage tmppage;
3193 tmppage.m_show_time += subtitledelay;
3194 m_dvb_subtitle_pages.push_back(tmppage);
3197 m_dvb_subtitle_pages.push_back(p);
3199 checkSubtitleTiming();
3203 int eDVBServicePlay::getAC3Delay()
3206 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3208 return m_decoder->getAC3Delay();
3213 int eDVBServicePlay::getPCMDelay()
3216 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3218 return m_decoder->getPCMDelay();
3223 void eDVBServicePlay::setAC3Delay(int delay)
3226 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3228 std::string config_delay;
3229 int config_delay_int = 0;
3230 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3231 config_delay_int = atoi(config_delay.c_str());
3232 m_decoder->setAC3Delay(delay + config_delay_int);
3236 void eDVBServicePlay::setPCMDelay(int delay)
3239 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3241 std::string config_delay;
3242 int config_delay_int = 0;
3243 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3244 config_delay_int = atoi(config_delay.c_str());
3246 config_delay_int = 0;
3247 m_decoder->setPCMDelay(delay + config_delay_int);
3251 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3253 switch(event.type) {
3254 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3255 m_event((iPlayableService*)this, evVideoSizeChanged);
3257 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3258 m_event((iPlayableService*)this, evVideoFramerateChanged);
3260 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3261 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3268 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3274 PyObject *eDVBServicePlay::getStreamingData()
3276 eDVBServicePMTHandler::program program;
3277 if (m_service_handler.getProgramInfo(program))
3282 ePyObject r = program.createPythonObject();
3283 ePtr<iDVBDemux> demux;
3284 if (!m_service_handler.getDataDemux(demux))
3287 if (!demux->getCADemuxID(demux_id))
3288 PutToDict(r, "demux", demux_id);
3295 DEFINE_REF(eDVBServicePlay)
3297 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3301 case iServiceInformation::sTransponderData:
3302 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3306 return iStaticServiceInformation::getInfoObject(ref, w);
3309 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");