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);
1175 RESULT eDVBServicePlay::start()
1177 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1179 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1180 two (one for decoding, one for data source), as we must be prepared
1181 to start recording from the data demux. */
1184 eDVBMetaParser meta;
1185 if (!meta.parseFile(m_reference.path))
1187 service = meta.m_ref;
1188 service.path = m_reference.path;
1190 m_cue = new eCueSheet();
1193 m_event(this, evStart);
1195 m_first_program_info = 1;
1196 ePtr<iTsSource> source = createTsSource(service);
1197 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1201 /* inject EIT if there is a stored one */
1202 std::string filename = service.path;
1203 filename.erase(filename.length()-2, 2);
1205 ePtr<eServiceEvent> event = new eServiceEvent;
1206 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1208 ePtr<eServiceEvent> empty;
1209 m_event_handler.inject(event, 0);
1210 m_event_handler.inject(empty, 1);
1212 m_event(this, evStart);
1217 RESULT eDVBServicePlay::stop()
1219 /* add bookmark for last play position */
1222 pts_t play_position, length;
1223 if (!getPlayPosition(play_position))
1225 /* remove last position */
1226 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1228 if (i->what == 3) /* current play position */
1230 m_cue_entries.erase(i);
1231 i = m_cue_entries.begin();
1237 if (getLength(length))
1242 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1244 m_cuesheet_changed = 1;
1248 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1250 m_service_handler_timeshift.free();
1251 m_service_handler.free();
1253 if (m_is_pvr && m_cuesheet_changed)
1256 /* save cuesheet only when main file is accessible. */
1257 if (!::stat(m_reference.path.c_str(), &s))
1260 m_event((iPlayableService*)this, evStopped);
1264 RESULT eDVBServicePlay::setTarget(int target)
1266 m_is_primary = !target;
1270 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1272 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1276 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1278 /* note: we check for timeshift to be enabled,
1279 not neccessary active. if you pause when timeshift
1280 is not active, you should activate it when unpausing */
1281 if ((!m_is_pvr) && (!m_timeshift_enabled))
1291 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1293 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1294 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1295 setFastForward_internal(0);
1298 m_slowmotion = ratio;
1299 return m_decoder->setSlowMotion(ratio);
1305 RESULT eDVBServicePlay::setFastForward(int ratio)
1307 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1309 return setFastForward_internal(ratio);
1312 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1314 int skipmode, ffratio, ret = 0;
1321 } else if (ratio > 0)
1329 } else // if (ratio < 0)
1335 if (m_skipmode != skipmode)
1337 eDebug("setting cue skipmode to %d", skipmode);
1340 long long _skipmode = skipmode;
1341 if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1344 _skipmode = skipmode * 3;
1346 _skipmode = skipmode * 4;
1349 m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1353 m_skipmode = skipmode;
1356 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1358 m_fastforward = ffratio;
1364 ; /* return m_decoder->play(); is done in caller*/
1365 else if (ffratio != 1)
1366 ret = m_decoder->setFastForward(ffratio);
1368 ret = m_decoder->setTrickmode();
1371 eDebug("final seek after trickplay ret %d", seekTo(pos));
1376 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1378 if (m_is_pvr || m_timeshift_enabled)
1388 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1389 RESULT eDVBServicePlay::getLength(pts_t &len)
1391 ePtr<iDVBPVRChannel> pvr_channel;
1393 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1396 return pvr_channel->getLength(len);
1399 RESULT eDVBServicePlay::pause()
1401 eDebug("eDVBServicePlay::pause");
1402 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1407 return m_decoder->pause();
1412 RESULT eDVBServicePlay::unpause()
1414 eDebug("eDVBServicePlay::unpause");
1415 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1420 return m_decoder->play();
1425 RESULT eDVBServicePlay::seekTo(pts_t to)
1427 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1429 if (!m_decode_demux)
1432 ePtr<iDVBPVRChannel> pvr_channel;
1434 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1440 m_cue->seekTo(0, to);
1441 m_dvb_subtitle_pages.clear();
1442 m_subtitle_pages.clear();
1447 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1449 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1451 if (!m_decode_demux)
1454 ePtr<iDVBPVRChannel> pvr_channel;
1456 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1461 /* HACK until we have skip-AP api */
1462 if ((to > 0) && (to < 100))
1470 m_cue->seekTo(mode, to);
1471 m_dvb_subtitle_pages.clear();
1472 m_subtitle_pages.clear();
1476 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1478 ePtr<iDVBPVRChannel> pvr_channel;
1480 if (!m_decode_demux)
1483 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1488 /* if there is a decoder, use audio or video PTS */
1491 r = m_decoder->getPTS(0, pos);
1497 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1500 RESULT eDVBServicePlay::setTrickmode(int trick)
1502 /* currently unimplemented */
1506 RESULT eDVBServicePlay::isCurrentlySeekable()
1511 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1512 if (m_decoder->getVideoProgressive() == -1)
1518 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1524 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1530 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1536 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1542 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1548 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1551 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1552 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1554 if (!m_timeshift_enabled)
1556 /* query config path */
1558 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1559 eDebug("could not query ts path from config");
1563 /* we need enough diskspace */
1565 if (statfs(tspath.c_str(), &fs) < 0)
1567 eDebug("statfs failed!");
1571 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1573 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1583 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1594 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1600 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1606 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1612 RESULT eDVBServicePlay::getName(std::string &name)
1616 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1617 return i->getName(m_reference, name);
1619 else if (m_is_stream)
1621 name = m_reference.name;
1624 name = m_reference.path;
1631 else if (m_dvb_service)
1633 m_dvb_service->getName(m_reference, name);
1637 else if (!m_reference.name.empty())
1638 eStaticServiceDVBInformation().getName(m_reference, name);
1640 name = "DVB service";
1644 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1646 return m_event_handler.getEvent(evt, nownext);
1649 int eDVBServicePlay::getInfo(int w)
1651 eDVBServicePMTHandler::program program;
1653 if (w == sCAIDs || w == sCAIDPIDs)
1654 return resIsPyObject;
1656 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1658 int no_program_info = 0;
1660 if (h.getProgramInfo(program))
1661 no_program_info = 1;
1667 return m_decoder->getVideoHeight();
1671 return m_decoder->getVideoWidth();
1675 return m_decoder->getVideoFrameRate();
1679 return m_decoder->getVideoProgressive();
1685 aspect = m_decoder->getVideoAspect();
1686 if (aspect == -1 && no_program_info)
1688 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1690 ePtr<eServiceEvent> evt;
1691 if (!m_event_handler.getEvent(evt, 0))
1693 ePtr<eComponentData> data;
1694 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1696 if ( data->getStreamContent() == 1 )
1698 switch(data->getComponentType())
1701 case 1: // 4:3 SD PAL
1703 case 3: // 16:9 SD PAL
1704 case 4: // > 16:9 PAL
1705 case 5: // 4:3 SD NTSC
1707 case 7: // 16:9 SD NTSC
1708 case 8: // > 16:9 NTSC
1711 case 9: // 4:3 HD PAL
1713 case 0xB: // 16:9 HD PAL
1714 case 0xC: // > 16:9 HD PAL
1715 case 0xD: // 4:3 HD NTSC
1717 case 0xF: // 16:9 HD NTSC
1718 case 0x10: // > 16:9 HD PAL
1719 return data->getComponentType();
1729 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1733 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1737 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1738 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1742 int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
1745 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1748 apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
1751 apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
1754 apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
1758 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1762 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1766 if (no_program_info) return -1; return program.pcrPid;
1767 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1768 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1769 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1770 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1771 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1772 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1773 case sProvider: if (!m_dvb_service) return -1; return -2;
1774 case sServiceref: return resIsString;
1775 case sDVBState: return m_tune_state;
1782 std::string eDVBServicePlay::getInfoString(int w)
1787 if (!m_dvb_service) return "";
1788 return m_dvb_service->m_provider_name;
1790 return m_reference.toString();
1794 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1798 case sLiveStreamDemuxId:
1801 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1811 return iServiceInformation::getInfoString(w);
1814 PyObject *eDVBServicePlay::getInfoObject(int w)
1819 return m_service_handler.getCaIds();
1821 return m_service_handler.getCaIds(true);
1822 case sTransponderData:
1823 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1826 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1827 return h.getHbbTVApplications();
1832 return iServiceInformation::getInfoObject(w);
1835 int eDVBServicePlay::getNumberOfTracks()
1837 eDVBServicePMTHandler::program program;
1838 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1839 if (h.getProgramInfo(program))
1841 return program.audioStreams.size();
1844 int eDVBServicePlay::getCurrentTrack()
1846 eDVBServicePMTHandler::program program;
1847 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1848 if (h.getProgramInfo(program))
1851 int max = program.audioStreams.size();
1854 for (i = 0; i < max; ++i)
1855 if (program.audioStreams[i].pid == m_current_audio_pid)
1861 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1863 int ret = selectAudioStream(i);
1865 if (m_decoder->set())
1871 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1873 eDVBServicePMTHandler::program program;
1874 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1876 if (h.getProgramInfo(program))
1879 if (i >= program.audioStreams.size())
1882 info.m_pid = program.audioStreams[i].pid;
1884 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1885 info.m_description = "MPEG";
1886 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1887 info.m_description = "Dolby Digital";
1888 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1889 info.m_description = "Dolby Digital+";
1890 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1891 info.m_description = "AAC";
1892 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1893 info.m_description = "AAC-HE";
1894 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1895 info.m_description = "DTS";
1896 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1897 info.m_description = "DTS-HD";
1899 info.m_description = "???";
1901 if (program.audioStreams[i].component_tag != -1)
1903 ePtr<eServiceEvent> evt;
1904 if (!m_event_handler.getEvent(evt, 0))
1906 ePtr<eComponentData> data;
1907 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1908 info.m_language = data->getText();
1912 if (info.m_language.empty())
1913 info.m_language = program.audioStreams[i].language_code;
1918 int eDVBServicePlay::selectAudioStream(int i)
1920 eDVBServicePMTHandler::program program;
1921 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1922 pts_t position = -1;
1924 if (h.getProgramInfo(program))
1927 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1935 stream = program.defaultAudioStream;
1937 int apid = -1, apidtype = -1;
1939 if (((unsigned int)stream) < program.audioStreams.size())
1941 apid = program.audioStreams[stream].pid;
1942 apidtype = program.audioStreams[stream].type;
1945 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1946 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1948 m_current_audio_pid = apid;
1950 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1952 eDebug("set audio pid failed");
1957 eDebug("seekTo ret %d", seekTo(position));
1961 /* 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 */
1962 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1964 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1966 rdsPid = program.audioStreams[stream].rdsPid;
1967 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1970 ePtr<iDVBDemux> data_demux;
1971 if (!h.getDataDemux(data_demux))
1973 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1974 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1975 m_rds_decoder->start(rdsPid);
1980 /* store new pid as default only when:
1981 a.) we have an entry in the service db for the current service,
1982 b.) we are not playing back something,
1983 c.) we are not selecting the default entry. (we wouldn't change
1984 anything in the best case, or destroy the default setting in
1985 case the real default is not yet available.)
1987 if (m_dvb_service && ((i != -1)
1988 || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
1989 && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
1990 && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
1991 && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
1992 && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
1994 m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
1995 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
1996 m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
1997 m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
1998 m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
2001 h.resetCachedProgram();
2006 int eDVBServicePlay::getCurrentChannel()
2008 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
2011 RESULT eDVBServicePlay::selectChannel(int i)
2013 if (i < LEFT || i > RIGHT || i == STEREO)
2016 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2018 m_decoder->setAudioChannel(i);
2022 std::string eDVBServicePlay::getText(int x)
2028 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2030 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2035 void eDVBServicePlay::rdsDecoderEvent(int what)
2039 case eDVBRdsDecoder::RadioTextChanged:
2040 m_event((iPlayableService*)this, evUpdatedRadioText);
2042 case eDVBRdsDecoder::RtpTextChanged:
2043 m_event((iPlayableService*)this, evUpdatedRtpText);
2045 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2046 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2048 case eDVBRdsDecoder::RecvRassSlidePic:
2049 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2054 void eDVBServicePlay::showRassSlidePicture()
2060 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2061 if (rass_slide_pic.length())
2062 m_decoder->showSinglePic(rass_slide_pic.c_str());
2064 eDebug("empty filename for rass slide picture received!!");
2067 eDebug("no MPEG Decoder to show iframes avail");
2070 eDebug("showRassSlidePicture called.. but not decoder");
2073 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2079 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2080 if (rass_interactive_pic.length())
2081 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2083 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2086 eDebug("no MPEG Decoder to show iframes avail");
2089 eDebug("showRassInteractivePic called.. but not decoder");
2092 ePyObject eDVBServicePlay::getRassInteractiveMask()
2095 return m_rds_decoder->getRassPictureMask();
2099 int eDVBServiceBase::getFrontendInfo(int w)
2101 eUsePtr<iDVBChannel> channel;
2102 if(m_service_handler.getChannel(channel))
2104 ePtr<iDVBFrontend> fe;
2105 if(channel->getFrontend(fe))
2107 return fe->readFrontendData(w);
2110 PyObject *eDVBServiceBase::getFrontendData()
2112 ePyObject ret = PyDict_New();
2115 eUsePtr<iDVBChannel> channel;
2116 if(!m_service_handler.getChannel(channel))
2118 ePtr<iDVBFrontend> fe;
2119 if(!channel->getFrontend(fe))
2120 fe->getFrontendData(ret);
2128 PyObject *eDVBServiceBase::getFrontendStatus()
2130 ePyObject ret = PyDict_New();
2133 eUsePtr<iDVBChannel> channel;
2134 if(!m_service_handler.getChannel(channel))
2136 ePtr<iDVBFrontend> fe;
2137 if(!channel->getFrontend(fe))
2138 fe->getFrontendStatus(ret);
2146 PyObject *eDVBServiceBase::getTransponderData(bool original)
2148 ePyObject ret = PyDict_New();
2151 eUsePtr<iDVBChannel> channel;
2152 if(!m_service_handler.getChannel(channel))
2154 ePtr<iDVBFrontend> fe;
2155 if(!channel->getFrontend(fe))
2156 fe->getTransponderData(ret, original);
2164 PyObject *eDVBServiceBase::getAll(bool original)
2166 ePyObject ret = getTransponderData(original);
2169 eUsePtr<iDVBChannel> channel;
2170 if(!m_service_handler.getChannel(channel))
2172 ePtr<iDVBFrontend> fe;
2173 if(!channel->getFrontend(fe))
2175 fe->getFrontendData(ret);
2176 fe->getFrontendStatus(ret);
2183 int eDVBServicePlay::getNumberOfSubservices()
2185 ePtr<eServiceEvent> evt;
2186 if (!m_event_handler.getEvent(evt, 0))
2187 return evt->getNumOfLinkageServices();
2191 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2193 ePtr<eServiceEvent> evt;
2194 if (!m_event_handler.getEvent(evt, 0))
2196 if (!evt->getLinkageService(sub, m_reference, n))
2199 sub.type=eServiceReference::idInvalid;
2203 RESULT eDVBServicePlay::startTimeshift()
2205 ePtr<iDVBDemux> demux;
2207 eDebug("Start timeshift!");
2209 if (m_timeshift_enabled)
2212 /* start recording with the data demux. */
2213 if (m_service_handler.getDataDemux(demux))
2216 demux->createTSRecorder(m_record);
2221 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2222 eDebug("could not query ts path");
2225 tspath.append("/timeshift.XXXXXX");
2227 templ = new char[tspath.length() + 1];
2228 strcpy(templ, tspath.c_str());
2230 m_timeshift_fd = mkstemp(templ);
2231 m_timeshift_file = std::string(templ);
2233 eDebug("recording to %s", templ);
2237 if (m_timeshift_fd < 0)
2243 m_record->setTargetFD(m_timeshift_fd);
2244 m_record->setTargetFilename(m_timeshift_file.c_str());
2245 m_record->enableAccessPoints(false);
2247 m_timeshift_enabled = 1;
2249 updateTimeshiftPids();
2255 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2257 if (!m_timeshift_enabled)
2263 m_timeshift_enabled = 0;
2268 close(m_timeshift_fd);
2269 eDebug("remove timeshift file");
2270 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2273 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2274 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2280 int eDVBServicePlay::isTimeshiftActive()
2282 return m_timeshift_enabled && m_timeshift_active;
2285 RESULT eDVBServicePlay::activateTimeshift()
2287 if (!m_timeshift_enabled)
2290 if (!m_timeshift_active)
2292 switchToTimeshift();
2299 PyObject *eDVBServicePlay::getCutList()
2301 ePyObject list = PyList_New(0);
2303 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2305 ePyObject tuple = PyTuple_New(2);
2306 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2307 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2308 PyList_Append(list, tuple);
2315 void eDVBServicePlay::setCutList(ePyObject list)
2317 if (!PyList_Check(list))
2319 int size = PyList_Size(list);
2322 m_cue_entries.clear();
2324 for (i=0; i<size; ++i)
2326 ePyObject tuple = PyList_GET_ITEM(list, i);
2327 if (!PyTuple_Check(tuple))
2329 eDebug("non-tuple in cutlist");
2332 if (PyTuple_Size(tuple) != 2)
2334 eDebug("cutlist entries need to be a 2-tuple");
2337 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2338 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2340 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2343 pts_t pts = PyLong_AsLongLong(ppts);
2344 int type = PyInt_AsLong(ptype);
2345 m_cue_entries.insert(cueEntry(pts, type));
2346 eDebug("adding %08llx, %d", pts, type);
2348 m_cuesheet_changed = 1;
2350 cutlistToCuesheet();
2351 m_event((iPlayableService*)this, evCuesheetChanged);
2354 void eDVBServicePlay::setCutListEnable(int enable)
2356 m_cutlist_enabled = enable;
2357 cutlistToCuesheet();
2360 void eDVBServicePlay::updateTimeshiftPids()
2365 eDVBServicePMTHandler::program program;
2366 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2368 if (h.getProgramInfo(program))
2372 int timing_pid = -1;
2373 int timing_pid_type = -1;
2374 std::set<int> pids_to_record;
2375 pids_to_record.insert(0); // PAT
2376 if (program.pmtPid != -1)
2377 pids_to_record.insert(program.pmtPid); // PMT
2379 if (program.textPid != -1)
2380 pids_to_record.insert(program.textPid); // Videotext
2382 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2383 i(program.videoStreams.begin());
2384 i != program.videoStreams.end(); ++i)
2386 pids_to_record.insert(i->pid);
2388 if (timing_pid == -1)
2390 timing_pid = i->pid;
2391 timing_pid_type = i->type;
2395 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2396 i(program.audioStreams.begin());
2397 i != program.audioStreams.end(); ++i)
2399 pids_to_record.insert(i->pid);
2401 if (timing_pid == -1)
2403 timing_pid = i->pid;
2404 timing_pid_type = -1;
2408 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2409 i(program.subtitleStreams.begin());
2410 i != program.subtitleStreams.end(); ++i)
2411 pids_to_record.insert(i->pid);
2413 std::set<int> new_pids, obsolete_pids;
2415 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2416 m_pids_active.begin(), m_pids_active.end(),
2417 std::inserter(new_pids, new_pids.begin()));
2419 std::set_difference(
2420 m_pids_active.begin(), m_pids_active.end(),
2421 pids_to_record.begin(), pids_to_record.end(),
2422 std::inserter(new_pids, new_pids.begin())
2425 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2426 m_record->addPID(*i);
2428 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2429 m_record->removePID(*i);
2431 if (timing_pid != -1)
2432 m_record->setTimingPID(timing_pid, timing_pid_type);
2436 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2438 m_timeshift_file_next = f;
2442 void eDVBServicePlay::switchToLive()
2444 if (!m_timeshift_active)
2447 eDebug("SwitchToLive");
2451 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2453 /* free the timeshift service handler, we need the resources */
2454 m_service_handler_timeshift.free();
2456 updateDecoder(true);
2459 void eDVBServicePlay::resetTimeshift(int start)
2464 m_teletext_parser = 0;
2466 m_subtitle_parser = 0;
2467 m_new_subtitle_page_connection = 0;
2468 m_new_dvb_subtitle_page_connection = 0;
2469 m_rds_decoder_event_connection = 0;
2470 m_video_event_connection = 0;
2471 m_timeshift_changed = 1;
2472 m_timeshift_file_next.clear();
2476 m_cue = new eCueSheet();
2477 m_timeshift_active = 1;
2480 m_timeshift_active = 0;
2483 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2487 eHttpStream *f = new eHttpStream();
2488 f->open(ref.path.c_str());
2489 return ePtr<iTsSource>(f);
2493 eRawFile *f = new eRawFile();
2494 f->open(ref.path.c_str());
2495 return ePtr<iTsSource>(f);
2499 void eDVBServicePlay::switchToTimeshift()
2501 if (m_timeshift_active)
2506 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2507 r.path = m_timeshift_file;
2509 m_cue->seekTo(0, -1000);
2511 ePtr<iTsSource> source = createTsSource(r);
2512 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 */
2514 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2516 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2519 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2521 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2522 bool mustPlay = false;
2524 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2526 eDVBServicePMTHandler::program program;
2527 if (h.getProgramInfo(program))
2528 eDebug("getting program info failed.");
2531 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2532 if (!program.videoStreams.empty())
2534 eDebugNoNewLine(" (");
2535 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2536 i(program.videoStreams.begin());
2537 i != program.videoStreams.end(); ++i)
2544 if (i != program.videoStreams.begin())
2545 eDebugNoNewLine(", ");
2546 eDebugNoNewLine("%04x", i->pid);
2548 eDebugNoNewLine(")");
2550 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2551 if (!program.audioStreams.empty())
2553 eDebugNoNewLine(" (");
2554 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2555 i(program.audioStreams.begin());
2556 i != program.audioStreams.end(); ++i)
2558 if (i != program.audioStreams.begin())
2559 eDebugNoNewLine(", ");
2560 eDebugNoNewLine("%04x", i->pid);
2562 eDebugNoNewLine(")");
2564 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2565 pcrpid = program.pcrPid;
2566 eDebug(", and the text pid is %04x", program.textPid);
2567 tpid = program.textPid;
2572 h.getDecodeDemux(m_decode_demux);
2575 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2577 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2580 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2581 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2582 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2583 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2584 if (m_timeshift_changed)
2586 ePyObject subs = getCachedSubtitle();
2587 if (subs != Py_None)
2589 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2590 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2591 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2592 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2593 if (type == 0) // dvb
2594 m_subtitle_parser->start(pid, comp_page, anc_page);
2595 else if (type == 1) // ttx
2596 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2603 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2607 m_timeshift_changed = 0;
2611 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2614 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2615 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2616 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2620 eServiceReferenceDVB ref;
2621 m_service_handler.getServiceReference(ref);
2622 eServiceReferenceDVB parent = ref.getParentServiceReference();
2627 ePtr<eDVBResourceManager> res_mgr;
2628 if (!eDVBResourceManager::getInstance(res_mgr))
2630 ePtr<iDVBChannelList> db;
2631 if (!res_mgr->getChannelList(db))
2633 ePtr<eDVBService> origService;
2634 if (!db->getService(parent, origService))
2636 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2637 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2644 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2645 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2647 m_decoder->setVideoPID(vpid, vpidtype);
2648 m_current_video_pid_type = vpidtype;
2649 selectAudioStream();
2651 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2652 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2653 m_decoder->setSyncPCR(pcrpid);
2655 m_decoder->setSyncPCR(-1);
2659 m_decoder->setTextPID(tpid);
2660 m_teletext_parser->start(program.textPid);
2663 if (vpid > 0 && vpid < 0x2000)
2667 std::string radio_pic;
2668 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2669 m_decoder->setRadioPic(radio_pic);
2677 m_decoder->setAudioChannel(achannel);
2679 /* don't worry about non-existing services, nor pvr services */
2682 /* (audio pid will be set in selectAudioTrack */
2683 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2684 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2685 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2686 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2688 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2689 sendSeekableStateChanged = true;
2691 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2693 if (sendSeekableStateChanged)
2694 m_event((iPlayableService*)this, evSeekableStatusChanged);
2697 void eDVBServicePlay::loadCuesheet()
2699 std::string filename = m_reference.path + ".cuts";
2701 m_cue_entries.clear();
2703 FILE *f = fopen(filename.c_str(), "rb");
2707 eDebug("loading cuts..");
2710 unsigned long long where;
2713 if (!fread(&where, sizeof(where), 1, f))
2715 if (!fread(&what, sizeof(what), 1, f))
2718 #if BYTE_ORDER == LITTLE_ENDIAN
2719 where = bswap_64(where);
2726 m_cue_entries.insert(cueEntry(where, what));
2729 eDebug("%zd entries", m_cue_entries.size());
2731 eDebug("cutfile not found!");
2733 m_cuesheet_changed = 0;
2734 cutlistToCuesheet();
2735 m_event((iPlayableService*)this, evCuesheetChanged);
2738 void eDVBServicePlay::saveCuesheet()
2740 std::string filename = m_reference.path + ".cuts";
2742 FILE *f = fopen(filename.c_str(), "wb");
2746 unsigned long long where;
2749 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2751 #if BYTE_ORDER == BIG_ENDIAN
2754 where = bswap_64(i->where);
2756 what = htonl(i->what);
2757 fwrite(&where, sizeof(where), 1, f);
2758 fwrite(&what, sizeof(what), 1, f);
2764 m_cuesheet_changed = 0;
2767 void eDVBServicePlay::cutlistToCuesheet()
2771 eDebug("no cue sheet");
2776 if (!m_cutlist_enabled)
2778 m_cue->commitSpans();
2779 eDebug("cutlists were disabled");
2783 pts_t in = 0, out = 0, length = 0;
2787 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2789 int have_any_span = 0;
2793 if (i == m_cue_entries.end())
2795 if (!have_any_span && !in)
2799 if (i->what == 0) /* in */
2803 } else if (i->what == 1) /* out */
2805 else /* mark (2) or last play position (3) */
2824 m_cue->addSourceSpan(in, out);
2830 if (i == m_cue_entries.end())
2833 m_cue->commitSpans();
2836 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2838 if (m_subtitle_widget)
2839 disableSubtitles(parent);
2842 int tuplesize = PyTuple_Size(tuple);
2845 if (!PyTuple_Check(tuple))
2851 entry = PyTuple_GET_ITEM(tuple, 0);
2853 if (!PyInt_Check(entry))
2856 type = PyInt_AsLong(entry);
2858 if (type == 1) // teletext subtitles
2860 int page, magazine, pid;
2864 if (!m_teletext_parser)
2866 eDebug("enable teletext subtitles.. no parser !!!");
2870 entry = PyTuple_GET_ITEM(tuple, 1);
2871 if (!PyInt_Check(entry))
2873 pid = PyInt_AsLong(entry);
2875 entry = PyTuple_GET_ITEM(tuple, 2);
2876 if (!PyInt_Check(entry))
2878 page = PyInt_AsLong(entry);
2880 entry = PyTuple_GET_ITEM(tuple, 3);
2881 if (!PyInt_Check(entry))
2883 magazine = PyInt_AsLong(entry);
2885 m_subtitle_widget = new eSubtitleWidget(parent);
2886 m_subtitle_widget->resize(parent->size()); /* full size */
2887 m_teletext_parser->setPageAndMagazine(page, magazine);
2889 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2893 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2894 if (!m_subtitle_parser)
2896 eDebug("enable dvb subtitles.. no parser !!!");
2902 entry = PyTuple_GET_ITEM(tuple, 1);
2903 if (!PyInt_Check(entry))
2905 pid = PyInt_AsLong(entry);
2907 entry = PyTuple_GET_ITEM(tuple, 2);
2908 if (!PyInt_Check(entry))
2910 composition_page_id = PyInt_AsLong(entry);
2912 entry = PyTuple_GET_ITEM(tuple, 3);
2913 if (!PyInt_Check(entry))
2915 ancillary_page_id = PyInt_AsLong(entry);
2917 m_subtitle_widget = new eSubtitleWidget(parent);
2918 m_subtitle_widget->resize(parent->size()); /* full size */
2919 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2921 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2927 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2928 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2929 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2933 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2935 delete m_subtitle_widget;
2936 m_subtitle_widget = 0;
2937 if (m_subtitle_parser)
2939 m_subtitle_parser->stop();
2940 m_dvb_subtitle_pages.clear();
2942 if (m_teletext_parser)
2944 m_teletext_parser->setPageAndMagazine(-1, -1);
2945 m_subtitle_pages.clear();
2948 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2952 PyObject *eDVBServicePlay::getCachedSubtitle()
2956 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2959 unsigned int data = (unsigned int)tmp;
2960 int pid = (data&0xFFFF0000)>>16;
2961 ePyObject tuple = PyTuple_New(4);
2962 eDVBServicePMTHandler::program program;
2963 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2964 if (!h.getProgramInfo(program))
2966 if (program.textPid==pid) // teletext
2967 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2969 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2970 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2971 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2972 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2980 PyObject *eDVBServicePlay::getSubtitleList()
2982 if (!m_teletext_parser)
2985 ePyObject l = PyList_New(0);
2986 std::set<int> added_ttx_pages;
2988 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2989 m_teletext_parser->m_found_subtitle_pages;
2991 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2992 eDVBServicePMTHandler::program program;
2993 if (h.getProgramInfo(program))
2994 eDebug("getting program info failed.");
2997 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2998 it != program.subtitleStreams.end(); ++it)
3000 switch(it->subtitling_type)
3002 case 0x01: // ebu teletext subtitles
3004 int page_number = it->teletext_page_number & 0xFF;
3005 int magazine_number = it->teletext_magazine_number & 7;
3006 int hash = magazine_number << 8 | page_number;
3007 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3009 ePyObject tuple = PyTuple_New(5);
3010 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3011 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3012 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3013 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3014 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3015 PyList_Append(l, tuple);
3017 added_ttx_pages.insert(hash);
3022 case 0x20 ... 0x23: // dvb subtitles
3024 ePyObject tuple = PyTuple_New(5);
3025 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3026 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3027 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3028 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3029 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3030 PyList_Insert(l, 0, tuple);
3038 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3039 it != subs.end(); ++it)
3041 int page_number = it->teletext_page_number & 0xFF;
3042 int magazine_number = it->teletext_magazine_number & 7;
3043 int hash = magazine_number << 8 | page_number;
3044 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3046 ePyObject tuple = PyTuple_New(5);
3047 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3048 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3049 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3050 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3051 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3052 PyList_Append(l, tuple);
3060 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3062 if (m_subtitle_widget)
3064 int subtitledelay = 0;
3067 m_decoder->getPTS(0, pos);
3068 if (m_is_pvr || m_timeshift_enabled)
3070 eDebug("Subtitle in recording/timeshift");
3071 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3075 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3076 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3079 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3080 eDVBTeletextSubtitlePage tmppage = page;
3081 tmppage.m_have_pts = true;
3083 if (abs(tmppage.m_pts - pos) > 20*90000)
3084 tmppage.m_pts = pos; // fix abnormal pos diffs
3086 tmppage.m_pts += subtitledelay;
3087 m_subtitle_pages.push_back(tmppage);
3088 checkSubtitleTiming();
3092 void eDVBServicePlay::checkSubtitleTiming()
3094 eDebug("checkSubtitleTiming");
3095 if (!m_subtitle_widget)
3099 enum { TELETEXT, DVB } type;
3100 eDVBTeletextSubtitlePage page;
3101 eDVBSubtitlePage dvb_page;
3103 if (!m_subtitle_pages.empty())
3105 page = m_subtitle_pages.front();
3107 show_time = page.m_pts;
3109 else if (!m_dvb_subtitle_pages.empty())
3111 dvb_page = m_dvb_subtitle_pages.front();
3113 show_time = dvb_page.m_show_time;
3121 m_decoder->getPTS(0, pos);
3123 eDebug("%lld %lld", pos, show_time);
3124 int diff = show_time - pos;
3125 if (type == TELETEXT && !page.m_have_pts)
3127 eDebug("ttx subtitle page without pts... immediate show");
3132 eDebug("[late (%d ms)]", -diff / 90);
3135 if (abs(diff) > 1800000)
3137 eDebug("[invalid]... immediate show!");
3142 if (type == TELETEXT)
3144 eDebug("display teletext subtitle page %lld", show_time);
3145 m_subtitle_widget->setPage(page);
3146 m_subtitle_pages.pop_front();
3150 eDebug("display dvb subtitle Page %lld", show_time);
3151 m_subtitle_widget->setPage(dvb_page);
3152 m_dvb_subtitle_pages.pop_front();
3156 eDebug("start subtitle delay %d", diff / 90);
3157 m_subtitle_sync_timer->start(diff / 90, 1);
3163 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3165 if (m_subtitle_widget)
3169 m_decoder->getPTS(0, pos);
3170 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3171 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3173 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3174 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3176 eDVBSubtitlePage tmppage;
3178 tmppage.m_show_time = pos + subtitledelay;
3179 m_dvb_subtitle_pages.push_back(tmppage);
3183 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3184 if (subtitledelay != 0)
3186 eDVBSubtitlePage tmppage;
3188 tmppage.m_show_time += subtitledelay;
3189 m_dvb_subtitle_pages.push_back(tmppage);
3192 m_dvb_subtitle_pages.push_back(p);
3194 checkSubtitleTiming();
3198 int eDVBServicePlay::getAC3Delay()
3201 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3203 return m_decoder->getAC3Delay();
3208 int eDVBServicePlay::getPCMDelay()
3211 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3213 return m_decoder->getPCMDelay();
3218 void eDVBServicePlay::setAC3Delay(int delay)
3221 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3223 std::string config_delay;
3224 int config_delay_int = 0;
3225 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3226 config_delay_int = atoi(config_delay.c_str());
3227 m_decoder->setAC3Delay(delay + config_delay_int);
3231 void eDVBServicePlay::setPCMDelay(int delay)
3234 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3236 std::string config_delay;
3237 int config_delay_int = 0;
3238 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3239 config_delay_int = atoi(config_delay.c_str());
3241 config_delay_int = 0;
3242 m_decoder->setPCMDelay(delay + config_delay_int);
3246 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3248 switch(event.type) {
3249 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3250 m_event((iPlayableService*)this, evVideoSizeChanged);
3252 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3253 m_event((iPlayableService*)this, evVideoFramerateChanged);
3255 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3256 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3263 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3269 PyObject *eDVBServicePlay::getStreamingData()
3271 eDVBServicePMTHandler::program program;
3272 if (m_service_handler.getProgramInfo(program))
3277 ePyObject r = program.createPythonObject();
3278 ePtr<iDVBDemux> demux;
3279 if (!m_service_handler.getDataDemux(demux))
3282 if (!demux->getCADemuxID(demux_id))
3283 PutToDict(r, "demux", demux_id);
3290 DEFINE_REF(eDVBServicePlay)
3292 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3296 case iServiceInformation::sTransponderData:
3297 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3301 return iStaticServiceInformation::getInfoObject(ref, w);
3304 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");