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)
949 m_is_stream = m_reference.path.substr(0, 7) == "http://";
950 m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
952 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
953 m_skipmode = m_fastforward = m_slowmotion = 0;
956 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
958 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
959 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
961 m_cuesheet_changed = 0;
962 m_cutlist_enabled = 1;
964 m_subtitle_widget = 0;
968 m_subtitle_sync_timer = eTimer::create(eApp);
970 m_current_video_pid_type = 0;
972 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
975 eDVBServicePlay::~eDVBServicePlay()
980 int ret=meta.parseFile(m_reference.path);
984 meta.m_service_data="";
985 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
986 meta.m_service_data += tmp;
988 for (int x=0; x < eDVBService::cacheMax; ++x)
990 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
993 sprintf(tmp, ",c:%02d%04x", x, entry);
994 meta.m_service_data += tmp;
997 meta.updateMeta(m_reference.path);
1000 delete m_subtitle_widget;
1003 void eDVBServicePlay::gotNewEvent()
1007 ePtr<eServiceEvent> m_event_now, m_event_next;
1008 getEvent(m_event_now, 0);
1009 getEvent(m_event_next, 1);
1012 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1014 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1016 m_event((iPlayableService*)this, evUpdatedEventInfo);
1019 void eDVBServicePlay::serviceEvent(int event)
1021 m_tune_state = event;
1025 case eDVBServicePMTHandler::eventTuned:
1027 ePtr<iDVBDemux> m_demux;
1028 if (!m_service_handler.getDataDemux(m_demux))
1030 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1031 int sid = ref.getParentServiceID().get();
1033 sid = ref.getServiceID().get();
1034 if ( ref.getParentTransportStreamID().get() &&
1035 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1036 m_event_handler.startOther(m_demux, sid);
1038 m_event_handler.start(m_demux, sid);
1040 m_event((iPlayableService*)this, evTunedIn);
1043 case eDVBServicePMTHandler::eventNoResources:
1044 case eDVBServicePMTHandler::eventNoPAT:
1045 case eDVBServicePMTHandler::eventNoPATEntry:
1046 case eDVBServicePMTHandler::eventNoPMT:
1047 case eDVBServicePMTHandler::eventTuneFailed:
1048 case eDVBServicePMTHandler::eventMisconfiguration:
1050 eDebug("DVB service failed to tune - error %d", event);
1051 m_event((iPlayableService*)this, evTuneFailed);
1054 case eDVBServicePMTHandler::eventNewProgramInfo:
1056 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1057 if (m_timeshift_enabled)
1058 updateTimeshiftPids();
1059 if (!m_timeshift_active)
1061 if (m_first_program_info & 1 && m_is_pvr)
1063 m_first_program_info &= ~1;
1066 if (!m_timeshift_active)
1067 m_event((iPlayableService*)this, evUpdatedInfo);
1070 case eDVBServicePMTHandler::eventPreStart:
1073 case eDVBServicePMTHandler::eventEOF:
1074 m_event((iPlayableService*)this, evEOF);
1076 case eDVBServicePMTHandler::eventSOF:
1077 m_event((iPlayableService*)this, evSOF);
1079 case eDVBServicePMTHandler::eventHBBTVInfo:
1080 m_event((iPlayableService*)this, evHBBTVInfo);
1085 void eDVBServicePlay::serviceEventTimeshift(int event)
1089 case eDVBServicePMTHandler::eventNewProgramInfo:
1090 eDebug("eventNewProgramInfo TS");
1091 if (m_timeshift_active)
1094 if (m_first_program_info & 2)
1098 eDebug("re-apply slowmotion after timeshift file change");
1099 m_decoder->setSlowMotion(m_slowmotion);
1103 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1105 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1106 if (m_fastforward != 1)
1107 m_decoder->setFastForward(m_fastforward);
1109 m_decoder->setTrickmode();
1113 m_first_program_info &= ~2;
1115 m_event((iPlayableService*)this, evUpdatedInfo);
1118 case eDVBServicePMTHandler::eventSOF:
1120 if (!m_timeshift_file_next.empty())
1122 eDebug("timeshift SOF, switch to next file");
1125 m_first_program_info |= 2;
1127 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1128 r.path = m_timeshift_file_next;
1130 /* free the timeshift service handler, we need the resources */
1131 m_service_handler_timeshift.free();
1135 m_cue->seekTo(0, -1000);
1136 ePtr<iTsSource> source = createTsSource(r);
1137 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1139 m_event((iPlayableService*)this, evUser+1);
1143 m_event((iPlayableService*)this, evSOF);
1145 case eDVBServicePMTHandler::eventEOF:
1146 if ((!m_is_paused) && (m_skipmode >= 0))
1148 if (m_timeshift_file_next.empty())
1150 eDebug("timeshift EOF, so let's go live");
1155 eDebug("timeshift EOF, switch to next file");
1157 m_first_program_info |= 2;
1159 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1160 r.path = m_timeshift_file_next;
1162 /* free the timeshift service handler, we need the resources */
1163 m_service_handler_timeshift.free();
1166 ePtr<iTsSource> source = createTsSource(r);
1167 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 */
1169 m_event((iPlayableService*)this, evUser+1);
1173 case eDVBServicePMTHandler::eventNoDiskSpace:
1174 eDebug("No space!");
1175 m_event((iPlayableService*)this, evUser+3);
1180 RESULT eDVBServicePlay::start()
1182 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1184 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1185 two (one for decoding, one for data source), as we must be prepared
1186 to start recording from the data demux. */
1189 eDVBMetaParser meta;
1190 if (!meta.parseFile(m_reference.path))
1192 service = meta.m_ref;
1193 service.path = m_reference.path;
1195 m_cue = new eCueSheet();
1198 m_event(this, evStart);
1200 m_first_program_info = 1;
1201 ePtr<iTsSource> source = createTsSource(service);
1202 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1206 /* inject EIT if there is a stored one */
1207 std::string filename = service.path;
1208 filename.erase(filename.length()-2, 2);
1210 ePtr<eServiceEvent> event = new eServiceEvent;
1211 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1213 ePtr<eServiceEvent> empty;
1214 m_event_handler.inject(event, 0);
1215 m_event_handler.inject(empty, 1);
1217 m_event(this, evStart);
1222 RESULT eDVBServicePlay::stop()
1224 /* add bookmark for last play position */
1227 pts_t play_position, length;
1228 if (!getPlayPosition(play_position))
1230 /* remove last position */
1231 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1233 if (i->what == 3) /* current play position */
1235 m_cue_entries.erase(i);
1236 i = m_cue_entries.begin();
1242 if (getLength(length))
1247 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1249 m_cuesheet_changed = 1;
1253 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1255 m_service_handler_timeshift.free();
1256 m_service_handler.free();
1258 if (m_is_pvr && m_cuesheet_changed)
1261 /* save cuesheet only when main file is accessible. */
1262 if (!::stat(m_reference.path.c_str(), &s))
1265 m_event((iPlayableService*)this, evStopped);
1269 RESULT eDVBServicePlay::setTarget(int target)
1271 m_is_primary = !target;
1272 m_decoder_index = target;
1276 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1278 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1282 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1284 /* note: we check for timeshift to be enabled,
1285 not neccessary active. if you pause when timeshift
1286 is not active, you should activate it when unpausing */
1287 if ((!m_is_pvr) && (!m_timeshift_enabled))
1297 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1299 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1300 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1301 setFastForward_internal(0);
1304 m_slowmotion = ratio;
1305 return m_decoder->setSlowMotion(ratio);
1311 RESULT eDVBServicePlay::setFastForward(int ratio)
1313 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1315 return setFastForward_internal(ratio);
1318 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1320 int skipmode, ffratio, ret = 0;
1327 } else if (ratio > 0)
1335 } else // if (ratio < 0)
1341 if (m_skipmode != skipmode)
1343 eDebug("setting cue skipmode to %d", skipmode);
1346 long long _skipmode = skipmode;
1347 if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1350 _skipmode = skipmode * 3;
1352 _skipmode = skipmode * 4;
1355 m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1359 m_skipmode = skipmode;
1362 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1364 m_fastforward = ffratio;
1370 ; /* return m_decoder->play(); is done in caller*/
1371 else if (ffratio != 1)
1372 ret = m_decoder->setFastForward(ffratio);
1374 ret = m_decoder->setTrickmode();
1377 eDebug("final seek after trickplay ret %d", seekTo(pos));
1382 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1384 if (m_is_pvr || m_timeshift_enabled)
1394 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1395 RESULT eDVBServicePlay::getLength(pts_t &len)
1397 ePtr<iDVBPVRChannel> pvr_channel;
1399 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1402 return pvr_channel->getLength(len);
1405 RESULT eDVBServicePlay::pause()
1407 eDebug("eDVBServicePlay::pause");
1408 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1413 return m_decoder->pause();
1418 RESULT eDVBServicePlay::unpause()
1420 eDebug("eDVBServicePlay::unpause");
1421 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1426 return m_decoder->play();
1431 RESULT eDVBServicePlay::seekTo(pts_t to)
1433 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1435 if (!m_decode_demux)
1438 ePtr<iDVBPVRChannel> pvr_channel;
1440 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1446 m_cue->seekTo(0, to);
1447 m_dvb_subtitle_pages.clear();
1448 m_subtitle_pages.clear();
1453 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1455 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1457 if (!m_decode_demux)
1460 ePtr<iDVBPVRChannel> pvr_channel;
1462 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1467 /* HACK until we have skip-AP api */
1468 if ((to > 0) && (to < 100))
1476 m_cue->seekTo(mode, to);
1477 m_dvb_subtitle_pages.clear();
1478 m_subtitle_pages.clear();
1482 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1484 ePtr<iDVBPVRChannel> pvr_channel;
1486 if (!m_decode_demux)
1489 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1494 /* if there is a decoder, use audio or video PTS */
1497 r = m_decoder->getPTS(0, pos);
1503 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1506 RESULT eDVBServicePlay::setTrickmode(int trick)
1508 /* currently unimplemented */
1512 RESULT eDVBServicePlay::isCurrentlySeekable()
1517 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1518 if (m_decoder->getVideoProgressive() == -1)
1524 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1530 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1536 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1542 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1548 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1554 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1557 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1558 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1560 if (!m_timeshift_enabled)
1562 /* query config path */
1564 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1565 eDebug("could not query ts path from config");
1569 /* we need enough diskspace */
1571 if (statfs(tspath.c_str(), &fs) < 0)
1573 eDebug("statfs failed!");
1577 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1579 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1589 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1600 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1606 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1612 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1618 RESULT eDVBServicePlay::getName(std::string &name)
1622 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1623 return i->getName(m_reference, name);
1625 else if (m_is_stream)
1627 name = m_reference.name;
1630 name = m_reference.path;
1637 else if (m_dvb_service)
1639 m_dvb_service->getName(m_reference, name);
1643 else if (!m_reference.name.empty())
1644 eStaticServiceDVBInformation().getName(m_reference, name);
1646 name = "DVB service";
1650 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1652 return m_event_handler.getEvent(evt, nownext);
1655 int eDVBServicePlay::getInfo(int w)
1657 eDVBServicePMTHandler::program program;
1659 if (w == sCAIDs || w == sCAIDPIDs)
1660 return resIsPyObject;
1662 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1664 int no_program_info = 0;
1666 if (h.getProgramInfo(program))
1667 no_program_info = 1;
1673 return m_decoder->getVideoHeight();
1677 return m_decoder->getVideoWidth();
1681 return m_decoder->getVideoFrameRate();
1685 return m_decoder->getVideoProgressive();
1691 aspect = m_decoder->getVideoAspect();
1692 if (aspect == -1 && no_program_info)
1694 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1696 ePtr<eServiceEvent> evt;
1697 if (!m_event_handler.getEvent(evt, 0))
1699 ePtr<eComponentData> data;
1700 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1702 if ( data->getStreamContent() == 1 )
1704 switch(data->getComponentType())
1707 case 1: // 4:3 SD PAL
1709 case 3: // 16:9 SD PAL
1710 case 4: // > 16:9 PAL
1711 case 5: // 4:3 SD NTSC
1713 case 7: // 16:9 SD NTSC
1714 case 8: // > 16:9 NTSC
1717 case 9: // 4:3 HD PAL
1719 case 0xB: // 16:9 HD PAL
1720 case 0xC: // > 16:9 HD PAL
1721 case 0xD: // 4:3 HD NTSC
1723 case 0xF: // 16:9 HD NTSC
1724 case 0x10: // > 16:9 HD PAL
1725 return data->getComponentType();
1735 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1739 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1743 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1744 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1748 int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
1751 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1754 apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
1757 apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
1760 apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
1764 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1768 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1772 if (no_program_info) return -1; return program.pcrPid;
1773 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1774 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1775 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1776 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1777 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1778 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1779 case sProvider: if (!m_dvb_service) return -1; return -2;
1780 case sServiceref: return resIsString;
1781 case sDVBState: return m_tune_state;
1788 std::string eDVBServicePlay::getInfoString(int w)
1793 if (!m_dvb_service) return "";
1794 return m_dvb_service->m_provider_name;
1796 return m_reference.toString();
1800 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1804 case sLiveStreamDemuxId:
1807 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1817 return iServiceInformation::getInfoString(w);
1820 PyObject *eDVBServicePlay::getInfoObject(int w)
1825 return m_service_handler.getCaIds();
1827 return m_service_handler.getCaIds(true);
1828 case sTransponderData:
1829 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1832 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1833 return h.getHbbTVApplications();
1838 return iServiceInformation::getInfoObject(w);
1841 int eDVBServicePlay::getNumberOfTracks()
1843 eDVBServicePMTHandler::program program;
1844 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1845 if (h.getProgramInfo(program))
1847 return program.audioStreams.size();
1850 int eDVBServicePlay::getCurrentTrack()
1852 eDVBServicePMTHandler::program program;
1853 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1854 if (h.getProgramInfo(program))
1857 int max = program.audioStreams.size();
1860 for (i = 0; i < max; ++i)
1861 if (program.audioStreams[i].pid == m_current_audio_pid)
1867 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1869 int ret = selectAudioStream(i);
1871 if (m_decoder->set())
1877 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1879 eDVBServicePMTHandler::program program;
1880 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1882 if (h.getProgramInfo(program))
1885 if (i >= program.audioStreams.size())
1888 info.m_pid = program.audioStreams[i].pid;
1890 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1891 info.m_description = "MPEG";
1892 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1893 info.m_description = "Dolby Digital";
1894 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1895 info.m_description = "Dolby Digital+";
1896 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1897 info.m_description = "AAC";
1898 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1899 info.m_description = "AAC-HE";
1900 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1901 info.m_description = "DTS";
1902 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1903 info.m_description = "DTS-HD";
1905 info.m_description = "???";
1907 if (program.audioStreams[i].component_tag != -1)
1909 ePtr<eServiceEvent> evt;
1910 if (!m_event_handler.getEvent(evt, 0))
1912 ePtr<eComponentData> data;
1913 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1914 info.m_language = data->getText();
1918 if (info.m_language.empty())
1919 info.m_language = program.audioStreams[i].language_code;
1924 int eDVBServicePlay::selectAudioStream(int i)
1926 eDVBServicePMTHandler::program program;
1927 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1928 pts_t position = -1;
1930 if (h.getProgramInfo(program))
1933 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1941 stream = program.defaultAudioStream;
1943 int apid = -1, apidtype = -1;
1945 if (((unsigned int)stream) < program.audioStreams.size())
1947 apid = program.audioStreams[stream].pid;
1948 apidtype = program.audioStreams[stream].type;
1951 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1952 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1954 m_current_audio_pid = apid;
1956 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1958 eDebug("set audio pid failed");
1963 eDebug("seekTo ret %d", seekTo(position));
1967 /* 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 */
1968 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1970 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1972 rdsPid = program.audioStreams[stream].rdsPid;
1973 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1976 ePtr<iDVBDemux> data_demux;
1977 if (!h.getDataDemux(data_demux))
1979 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1980 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1981 m_rds_decoder->start(rdsPid);
1986 /* store new pid as default only when:
1987 a.) we have an entry in the service db for the current service,
1988 b.) we are not playing back something,
1989 c.) we are not selecting the default entry. (we wouldn't change
1990 anything in the best case, or destroy the default setting in
1991 case the real default is not yet available.)
1993 if (m_dvb_service && ((i != -1)
1994 || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
1995 && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
1996 && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
1997 && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
1998 && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
2000 m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
2001 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
2002 m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
2003 m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
2004 m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
2007 h.resetCachedProgram();
2012 int eDVBServicePlay::getCurrentChannel()
2014 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
2017 RESULT eDVBServicePlay::selectChannel(int i)
2019 if (i < LEFT || i > RIGHT || i == STEREO)
2022 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2024 m_decoder->setAudioChannel(i);
2028 std::string eDVBServicePlay::getText(int x)
2034 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2036 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2041 void eDVBServicePlay::rdsDecoderEvent(int what)
2045 case eDVBRdsDecoder::RadioTextChanged:
2046 m_event((iPlayableService*)this, evUpdatedRadioText);
2048 case eDVBRdsDecoder::RtpTextChanged:
2049 m_event((iPlayableService*)this, evUpdatedRtpText);
2051 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2052 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2054 case eDVBRdsDecoder::RecvRassSlidePic:
2055 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2060 void eDVBServicePlay::showRassSlidePicture()
2066 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2067 if (rass_slide_pic.length())
2068 m_decoder->showSinglePic(rass_slide_pic.c_str());
2070 eDebug("empty filename for rass slide picture received!!");
2073 eDebug("no MPEG Decoder to show iframes avail");
2076 eDebug("showRassSlidePicture called.. but not decoder");
2079 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2085 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2086 if (rass_interactive_pic.length())
2087 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2089 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2092 eDebug("no MPEG Decoder to show iframes avail");
2095 eDebug("showRassInteractivePic called.. but not decoder");
2098 ePyObject eDVBServicePlay::getRassInteractiveMask()
2101 return m_rds_decoder->getRassPictureMask();
2105 int eDVBServiceBase::getFrontendInfo(int w)
2107 eUsePtr<iDVBChannel> channel;
2108 if(m_service_handler.getChannel(channel))
2110 ePtr<iDVBFrontend> fe;
2111 if(channel->getFrontend(fe))
2113 return fe->readFrontendData(w);
2116 PyObject *eDVBServiceBase::getFrontendData()
2118 ePyObject ret = PyDict_New();
2121 eUsePtr<iDVBChannel> channel;
2122 if(!m_service_handler.getChannel(channel))
2124 ePtr<iDVBFrontend> fe;
2125 if(!channel->getFrontend(fe))
2126 fe->getFrontendData(ret);
2134 PyObject *eDVBServiceBase::getFrontendStatus()
2136 ePyObject ret = PyDict_New();
2139 eUsePtr<iDVBChannel> channel;
2140 if(!m_service_handler.getChannel(channel))
2142 ePtr<iDVBFrontend> fe;
2143 if(!channel->getFrontend(fe))
2144 fe->getFrontendStatus(ret);
2152 PyObject *eDVBServiceBase::getTransponderData(bool original)
2154 ePyObject ret = PyDict_New();
2157 eUsePtr<iDVBChannel> channel;
2158 if(!m_service_handler.getChannel(channel))
2160 ePtr<iDVBFrontend> fe;
2161 if(!channel->getFrontend(fe))
2162 fe->getTransponderData(ret, original);
2170 PyObject *eDVBServiceBase::getAll(bool original)
2172 ePyObject ret = getTransponderData(original);
2175 eUsePtr<iDVBChannel> channel;
2176 if(!m_service_handler.getChannel(channel))
2178 ePtr<iDVBFrontend> fe;
2179 if(!channel->getFrontend(fe))
2181 fe->getFrontendData(ret);
2182 fe->getFrontendStatus(ret);
2189 int eDVBServicePlay::getNumberOfSubservices()
2191 ePtr<eServiceEvent> evt;
2192 if (!m_event_handler.getEvent(evt, 0))
2193 return evt->getNumOfLinkageServices();
2197 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2199 ePtr<eServiceEvent> evt;
2200 if (!m_event_handler.getEvent(evt, 0))
2202 if (!evt->getLinkageService(sub, m_reference, n))
2205 sub.type=eServiceReference::idInvalid;
2209 RESULT eDVBServicePlay::startTimeshift()
2211 ePtr<iDVBDemux> demux;
2213 eDebug("Start timeshift!");
2215 if (m_timeshift_enabled)
2218 /* start recording with the data demux. */
2219 if (m_service_handler.getDataDemux(demux))
2222 demux->createTSRecorder(m_record);
2227 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2228 eDebug("could not query ts path");
2231 tspath.append("/timeshift.XXXXXX");
2233 templ = new char[tspath.length() + 1];
2234 strcpy(templ, tspath.c_str());
2236 m_timeshift_fd = mkstemp(templ);
2237 m_timeshift_file = std::string(templ);
2239 eDebug("recording to %s", templ);
2243 if (m_timeshift_fd < 0)
2249 m_record->setTargetFD(m_timeshift_fd);
2250 m_record->setTargetFilename(m_timeshift_file.c_str());
2251 m_record->enableAccessPoints(false);
2252 m_record->setTimeshift(true);
2254 m_timeshift_enabled = 1;
2256 updateTimeshiftPids();
2262 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2264 if (!m_timeshift_enabled)
2270 m_timeshift_enabled = 0;
2275 close(m_timeshift_fd);
2276 eDebug("remove timeshift file");
2277 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2280 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2281 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2287 int eDVBServicePlay::isTimeshiftActive()
2289 return m_timeshift_enabled && m_timeshift_active;
2292 RESULT eDVBServicePlay::activateTimeshift()
2294 if (!m_timeshift_enabled)
2297 if (!m_timeshift_active)
2299 switchToTimeshift();
2306 PyObject *eDVBServicePlay::getCutList()
2308 ePyObject list = PyList_New(0);
2310 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2312 ePyObject tuple = PyTuple_New(2);
2313 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2314 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2315 PyList_Append(list, tuple);
2322 void eDVBServicePlay::setCutList(ePyObject list)
2324 if (!PyList_Check(list))
2326 int size = PyList_Size(list);
2329 m_cue_entries.clear();
2331 for (i=0; i<size; ++i)
2333 ePyObject tuple = PyList_GET_ITEM(list, i);
2334 if (!PyTuple_Check(tuple))
2336 eDebug("non-tuple in cutlist");
2339 if (PyTuple_Size(tuple) != 2)
2341 eDebug("cutlist entries need to be a 2-tuple");
2344 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2345 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2347 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2350 pts_t pts = PyLong_AsLongLong(ppts);
2351 int type = PyInt_AsLong(ptype);
2352 m_cue_entries.insert(cueEntry(pts, type));
2353 eDebug("adding %08llx, %d", pts, type);
2355 m_cuesheet_changed = 1;
2357 cutlistToCuesheet();
2358 m_event((iPlayableService*)this, evCuesheetChanged);
2361 void eDVBServicePlay::setCutListEnable(int enable)
2363 m_cutlist_enabled = enable;
2364 cutlistToCuesheet();
2367 void eDVBServicePlay::updateTimeshiftPids()
2372 eDVBServicePMTHandler::program program;
2373 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2375 if (h.getProgramInfo(program))
2379 int timing_pid = -1;
2380 int timing_pid_type = -1;
2381 std::set<int> pids_to_record;
2382 pids_to_record.insert(0); // PAT
2383 if (program.pmtPid != -1)
2384 pids_to_record.insert(program.pmtPid); // PMT
2386 if (program.textPid != -1)
2387 pids_to_record.insert(program.textPid); // Videotext
2389 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2390 i(program.videoStreams.begin());
2391 i != program.videoStreams.end(); ++i)
2393 pids_to_record.insert(i->pid);
2395 if (timing_pid == -1)
2397 timing_pid = i->pid;
2398 timing_pid_type = i->type;
2402 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2403 i(program.audioStreams.begin());
2404 i != program.audioStreams.end(); ++i)
2406 pids_to_record.insert(i->pid);
2408 if (timing_pid == -1)
2410 timing_pid = i->pid;
2411 timing_pid_type = -1;
2415 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2416 i(program.subtitleStreams.begin());
2417 i != program.subtitleStreams.end(); ++i)
2418 pids_to_record.insert(i->pid);
2420 std::set<int> new_pids, obsolete_pids;
2422 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2423 m_pids_active.begin(), m_pids_active.end(),
2424 std::inserter(new_pids, new_pids.begin()));
2426 std::set_difference(
2427 m_pids_active.begin(), m_pids_active.end(),
2428 pids_to_record.begin(), pids_to_record.end(),
2429 std::inserter(new_pids, new_pids.begin())
2432 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2433 m_record->addPID(*i);
2435 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2436 m_record->removePID(*i);
2438 if (timing_pid != -1)
2439 m_record->setTimingPID(timing_pid, timing_pid_type);
2443 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2445 m_timeshift_file_next = f;
2449 void eDVBServicePlay::switchToLive()
2451 if (!m_timeshift_active)
2454 eDebug("SwitchToLive");
2458 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2460 /* free the timeshift service handler, we need the resources */
2461 m_service_handler_timeshift.free();
2463 updateDecoder(true);
2466 void eDVBServicePlay::resetTimeshift(int start)
2471 m_teletext_parser = 0;
2473 m_subtitle_parser = 0;
2474 m_new_subtitle_page_connection = 0;
2475 m_new_dvb_subtitle_page_connection = 0;
2476 m_rds_decoder_event_connection = 0;
2477 m_video_event_connection = 0;
2478 m_timeshift_changed = 1;
2479 m_timeshift_file_next.clear();
2483 m_cue = new eCueSheet();
2484 m_timeshift_active = 1;
2487 m_timeshift_active = 0;
2490 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2494 eHttpStream *f = new eHttpStream();
2495 f->open(ref.path.c_str());
2496 return ePtr<iTsSource>(f);
2500 eRawFile *f = new eRawFile();
2501 f->open(ref.path.c_str());
2502 return ePtr<iTsSource>(f);
2506 void eDVBServicePlay::switchToTimeshift()
2508 if (m_timeshift_active)
2513 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2514 r.path = m_timeshift_file;
2516 m_cue->seekTo(0, -1000);
2518 ePtr<iTsSource> source = createTsSource(r);
2519 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 */
2521 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2523 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2526 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2528 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2529 bool mustPlay = false;
2531 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2533 eDVBServicePMTHandler::program program;
2534 if (h.getProgramInfo(program))
2535 eDebug("getting program info failed.");
2538 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2539 if (!program.videoStreams.empty())
2541 eDebugNoNewLine(" (");
2542 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2543 i(program.videoStreams.begin());
2544 i != program.videoStreams.end(); ++i)
2551 if (i != program.videoStreams.begin())
2552 eDebugNoNewLine(", ");
2553 eDebugNoNewLine("%04x", i->pid);
2555 eDebugNoNewLine(")");
2557 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2558 if (!program.audioStreams.empty())
2560 eDebugNoNewLine(" (");
2561 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2562 i(program.audioStreams.begin());
2563 i != program.audioStreams.end(); ++i)
2565 if (i != program.audioStreams.begin())
2566 eDebugNoNewLine(", ");
2567 eDebugNoNewLine("%04x", i->pid);
2569 eDebugNoNewLine(")");
2571 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2572 pcrpid = program.pcrPid;
2573 eDebug(", and the text pid is %04x", program.textPid);
2574 tpid = program.textPid;
2579 h.getDecodeDemux(m_decode_demux);
2582 m_decode_demux->getMPEGDecoder(m_decoder, m_decoder_index);
2584 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2587 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2588 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2589 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2590 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2591 if (m_timeshift_changed)
2593 ePyObject subs = getCachedSubtitle();
2594 if (subs != Py_None)
2596 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2597 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2598 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2599 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2600 if (type == 0) // dvb
2601 m_subtitle_parser->start(pid, comp_page, anc_page);
2602 else if (type == 1) // ttx
2603 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2610 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2614 m_timeshift_changed = 0;
2618 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2621 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2622 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2623 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2627 eServiceReferenceDVB ref;
2628 m_service_handler.getServiceReference(ref);
2629 eServiceReferenceDVB parent = ref.getParentServiceReference();
2634 ePtr<eDVBResourceManager> res_mgr;
2635 if (!eDVBResourceManager::getInstance(res_mgr))
2637 ePtr<iDVBChannelList> db;
2638 if (!res_mgr->getChannelList(db))
2640 ePtr<eDVBService> origService;
2641 if (!db->getService(parent, origService))
2643 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2644 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2651 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2652 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2654 m_decoder->setVideoPID(vpid, vpidtype);
2655 m_current_video_pid_type = vpidtype;
2656 selectAudioStream();
2658 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2659 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2660 m_decoder->setSyncPCR(pcrpid);
2662 m_decoder->setSyncPCR(-1);
2666 m_decoder->setTextPID(tpid);
2667 m_teletext_parser->start(program.textPid);
2670 if (vpid > 0 && vpid < 0x2000)
2674 std::string radio_pic;
2675 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2676 m_decoder->setRadioPic(radio_pic);
2684 m_decoder->setAudioChannel(achannel);
2686 /* don't worry about non-existing services, nor pvr services */
2689 /* (audio pid will be set in selectAudioTrack */
2690 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2691 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2692 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2693 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2695 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2696 sendSeekableStateChanged = true;
2698 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2700 if (sendSeekableStateChanged)
2701 m_event((iPlayableService*)this, evSeekableStatusChanged);
2704 void eDVBServicePlay::loadCuesheet()
2706 std::string filename = m_reference.path + ".cuts";
2708 m_cue_entries.clear();
2710 FILE *f = fopen(filename.c_str(), "rb");
2714 eDebug("loading cuts..");
2717 unsigned long long where;
2720 if (!fread(&where, sizeof(where), 1, f))
2722 if (!fread(&what, sizeof(what), 1, f))
2725 #if BYTE_ORDER == LITTLE_ENDIAN
2726 where = bswap_64(where);
2733 m_cue_entries.insert(cueEntry(where, what));
2736 eDebug("%zd entries", m_cue_entries.size());
2738 eDebug("cutfile not found!");
2740 m_cuesheet_changed = 0;
2741 cutlistToCuesheet();
2742 m_event((iPlayableService*)this, evCuesheetChanged);
2745 void eDVBServicePlay::saveCuesheet()
2747 std::string filename = m_reference.path + ".cuts";
2749 FILE *f = fopen(filename.c_str(), "wb");
2753 unsigned long long where;
2756 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2758 #if BYTE_ORDER == BIG_ENDIAN
2761 where = bswap_64(i->where);
2763 what = htonl(i->what);
2764 fwrite(&where, sizeof(where), 1, f);
2765 fwrite(&what, sizeof(what), 1, f);
2771 m_cuesheet_changed = 0;
2774 void eDVBServicePlay::cutlistToCuesheet()
2778 eDebug("no cue sheet");
2783 if (!m_cutlist_enabled)
2785 m_cue->commitSpans();
2786 eDebug("cutlists were disabled");
2790 pts_t in = 0, out = 0, length = 0;
2794 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2796 int have_any_span = 0;
2800 if (i == m_cue_entries.end())
2802 if (!have_any_span && !in)
2806 if (i->what == 0) /* in */
2810 } else if (i->what == 1) /* out */
2812 else /* mark (2) or last play position (3) */
2831 m_cue->addSourceSpan(in, out);
2837 if (i == m_cue_entries.end())
2840 m_cue->commitSpans();
2843 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2845 if (m_subtitle_widget)
2846 disableSubtitles(parent);
2849 int tuplesize = PyTuple_Size(tuple);
2852 if (!PyTuple_Check(tuple))
2858 entry = PyTuple_GET_ITEM(tuple, 0);
2860 if (!PyInt_Check(entry))
2863 type = PyInt_AsLong(entry);
2865 if (type == 1) // teletext subtitles
2867 int page, magazine, pid;
2871 if (!m_teletext_parser)
2873 eDebug("enable teletext subtitles.. no parser !!!");
2877 entry = PyTuple_GET_ITEM(tuple, 1);
2878 if (!PyInt_Check(entry))
2880 pid = PyInt_AsLong(entry);
2882 entry = PyTuple_GET_ITEM(tuple, 2);
2883 if (!PyInt_Check(entry))
2885 page = PyInt_AsLong(entry);
2887 entry = PyTuple_GET_ITEM(tuple, 3);
2888 if (!PyInt_Check(entry))
2890 magazine = PyInt_AsLong(entry);
2892 m_subtitle_widget = new eSubtitleWidget(parent);
2893 m_subtitle_widget->resize(parent->size()); /* full size */
2894 m_teletext_parser->setPageAndMagazine(page, magazine);
2896 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2900 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2901 if (!m_subtitle_parser)
2903 eDebug("enable dvb subtitles.. no parser !!!");
2909 entry = PyTuple_GET_ITEM(tuple, 1);
2910 if (!PyInt_Check(entry))
2912 pid = PyInt_AsLong(entry);
2914 entry = PyTuple_GET_ITEM(tuple, 2);
2915 if (!PyInt_Check(entry))
2917 composition_page_id = PyInt_AsLong(entry);
2919 entry = PyTuple_GET_ITEM(tuple, 3);
2920 if (!PyInt_Check(entry))
2922 ancillary_page_id = PyInt_AsLong(entry);
2924 m_subtitle_widget = new eSubtitleWidget(parent);
2925 m_subtitle_widget->resize(parent->size()); /* full size */
2926 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2928 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2934 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2935 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2936 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2940 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2942 delete m_subtitle_widget;
2943 m_subtitle_widget = 0;
2944 if (m_subtitle_parser)
2946 m_subtitle_parser->stop();
2947 m_dvb_subtitle_pages.clear();
2949 if (m_teletext_parser)
2951 m_teletext_parser->setPageAndMagazine(-1, -1);
2952 m_subtitle_pages.clear();
2955 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2959 PyObject *eDVBServicePlay::getCachedSubtitle()
2963 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2966 unsigned int data = (unsigned int)tmp;
2967 int pid = (data&0xFFFF0000)>>16;
2968 ePyObject tuple = PyTuple_New(4);
2969 eDVBServicePMTHandler::program program;
2970 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2971 if (!h.getProgramInfo(program))
2973 if (program.textPid==pid) // teletext
2974 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2976 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2977 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2978 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2979 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2987 PyObject *eDVBServicePlay::getSubtitleList()
2989 if (!m_teletext_parser)
2992 ePyObject l = PyList_New(0);
2993 std::set<int> added_ttx_pages;
2995 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2996 m_teletext_parser->m_found_subtitle_pages;
2998 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2999 eDVBServicePMTHandler::program program;
3000 if (h.getProgramInfo(program))
3001 eDebug("getting program info failed.");
3004 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
3005 it != program.subtitleStreams.end(); ++it)
3007 switch(it->subtitling_type)
3009 case 0x01: // ebu teletext subtitles
3011 int page_number = it->teletext_page_number & 0xFF;
3012 int magazine_number = it->teletext_magazine_number & 7;
3013 int hash = magazine_number << 8 | page_number;
3014 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3016 ePyObject tuple = PyTuple_New(5);
3017 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3018 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3019 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3020 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3021 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3022 PyList_Append(l, tuple);
3024 added_ttx_pages.insert(hash);
3029 case 0x20 ... 0x23: // dvb subtitles
3031 ePyObject tuple = PyTuple_New(5);
3032 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3033 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3034 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3035 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3036 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3037 PyList_Insert(l, 0, tuple);
3045 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3046 it != subs.end(); ++it)
3048 int page_number = it->teletext_page_number & 0xFF;
3049 int magazine_number = it->teletext_magazine_number & 7;
3050 int hash = magazine_number << 8 | page_number;
3051 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3053 ePyObject tuple = PyTuple_New(5);
3054 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3055 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3056 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3057 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3058 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3059 PyList_Append(l, tuple);
3067 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3069 if (m_subtitle_widget)
3071 int subtitledelay = 0;
3074 m_decoder->getPTS(0, pos);
3075 if (m_is_pvr || m_timeshift_enabled)
3077 eDebug("Subtitle in recording/timeshift");
3078 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3082 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3083 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3086 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3087 eDVBTeletextSubtitlePage tmppage = page;
3088 tmppage.m_have_pts = true;
3090 if (abs(tmppage.m_pts - pos) > 20*90000)
3091 tmppage.m_pts = pos; // fix abnormal pos diffs
3093 tmppage.m_pts += subtitledelay;
3094 m_subtitle_pages.push_back(tmppage);
3095 checkSubtitleTiming();
3099 void eDVBServicePlay::checkSubtitleTiming()
3101 eDebug("checkSubtitleTiming");
3102 if (!m_subtitle_widget)
3106 enum { TELETEXT, DVB } type;
3107 eDVBTeletextSubtitlePage page;
3108 eDVBSubtitlePage dvb_page;
3110 if (!m_subtitle_pages.empty())
3112 page = m_subtitle_pages.front();
3114 show_time = page.m_pts;
3116 else if (!m_dvb_subtitle_pages.empty())
3118 dvb_page = m_dvb_subtitle_pages.front();
3120 show_time = dvb_page.m_show_time;
3128 m_decoder->getPTS(0, pos);
3130 eDebug("%lld %lld", pos, show_time);
3131 int diff = show_time - pos;
3132 if (type == TELETEXT && !page.m_have_pts)
3134 eDebug("ttx subtitle page without pts... immediate show");
3139 eDebug("[late (%d ms)]", -diff / 90);
3142 if (abs(diff) > 1800000)
3144 eDebug("[invalid]... immediate show!");
3149 if (type == TELETEXT)
3151 eDebug("display teletext subtitle page %lld", show_time);
3152 m_subtitle_widget->setPage(page);
3153 m_subtitle_pages.pop_front();
3157 eDebug("display dvb subtitle Page %lld", show_time);
3158 m_subtitle_widget->setPage(dvb_page);
3159 m_dvb_subtitle_pages.pop_front();
3163 eDebug("start subtitle delay %d", diff / 90);
3164 m_subtitle_sync_timer->start(diff / 90, 1);
3170 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3172 if (m_subtitle_widget)
3176 m_decoder->getPTS(0, pos);
3177 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3178 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3180 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3181 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3183 eDVBSubtitlePage tmppage;
3185 tmppage.m_show_time = pos + subtitledelay;
3186 m_dvb_subtitle_pages.push_back(tmppage);
3190 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3191 if (subtitledelay != 0)
3193 eDVBSubtitlePage tmppage;
3195 tmppage.m_show_time += subtitledelay;
3196 m_dvb_subtitle_pages.push_back(tmppage);
3199 m_dvb_subtitle_pages.push_back(p);
3201 checkSubtitleTiming();
3205 int eDVBServicePlay::getAC3Delay()
3208 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3210 return m_decoder->getAC3Delay();
3215 int eDVBServicePlay::getPCMDelay()
3218 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3220 return m_decoder->getPCMDelay();
3225 void eDVBServicePlay::setAC3Delay(int delay)
3228 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3230 std::string config_delay;
3231 int config_delay_int = 0;
3232 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3233 config_delay_int = atoi(config_delay.c_str());
3234 m_decoder->setAC3Delay(delay + config_delay_int);
3238 void eDVBServicePlay::setPCMDelay(int delay)
3241 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3243 std::string config_delay;
3244 int config_delay_int = 0;
3245 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3246 config_delay_int = atoi(config_delay.c_str());
3248 config_delay_int = 0;
3249 m_decoder->setPCMDelay(delay + config_delay_int);
3253 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3255 switch(event.type) {
3256 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3257 m_event((iPlayableService*)this, evVideoSizeChanged);
3259 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3260 m_event((iPlayableService*)this, evVideoFramerateChanged);
3262 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3263 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3270 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3276 PyObject *eDVBServicePlay::getStreamingData()
3278 eDVBServicePMTHandler::program program;
3279 if (m_service_handler.getProgramInfo(program))
3284 ePyObject r = program.createPythonObject();
3285 ePtr<iDVBDemux> demux;
3286 if (!m_service_handler.getDataDemux(demux))
3289 if (!demux->getCADemuxID(demux_id))
3290 PutToDict(r, "demux", demux_id);
3297 DEFINE_REF(eDVBServicePlay)
3299 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3303 case iServiceInformation::sTransponderData:
3304 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3308 return iStaticServiceInformation::getInfoObject(ref, w);
3311 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");