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>
23 #include <lib/gui/esubtitle.h>
29 #include <netinet/in.h>
32 #error no byte order defined!
35 class eStaticServiceDVBInformation: public iStaticServiceInformation
37 DECLARE_REF(eStaticServiceDVBInformation);
39 RESULT getName(const eServiceReference &ref, std::string &name);
40 int getLength(const eServiceReference &ref);
41 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
42 PyObject *getInfoObject(const eServiceReference &ref, int);
45 DEFINE_REF(eStaticServiceDVBInformation);
47 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
49 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
50 if ( !ref.name.empty() )
52 if (service.getParentTransportStreamID().get()) // linkage subservice
54 ePtr<iServiceHandler> service_center;
55 if (!eServiceCenter::getInstance(service_center))
57 eServiceReferenceDVB parent = service;
58 parent.setTransportStreamID( service.getParentTransportStreamID() );
59 parent.setServiceID( service.getParentServiceID() );
60 parent.setParentTransportStreamID(eTransportStreamID(0));
61 parent.setParentServiceID(eServiceID(0));
63 ePtr<iStaticServiceInformation> service_info;
64 if (!service_center->info(parent, service_info))
66 if (!service_info->getName(parent, name))
67 name=buildShortName(name) + " - ";
80 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
85 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
87 ePtr<eDVBResourceManager> res_mgr;
88 if ( eDVBResourceManager::getInstance( res_mgr ) )
89 eDebug("isPlayable... no res manager!!");
92 eDVBChannelID chid, chid_ignore;
94 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
95 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
96 return res_mgr->canAllocateChannel(chid, chid_ignore, system);
101 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
102 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
103 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
104 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
106 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
108 if (r.type == eServiceReference::idDVB)
110 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
113 case iServiceInformation::sTransponderData:
115 ePtr<eDVBResourceManager> res;
116 if (!eDVBResourceManager::getInstance(res))
118 ePtr<iDVBChannelList> db;
119 if (!res->getChannelList(db))
122 ref.getChannelID(chid);
123 ePtr<iDVBFrontendParameters> feparm;
124 if (!db->getChannelFrontendData(chid, feparm))
127 if (!feparm->getSystem(system))
129 ePyObject dict = PyDict_New();
132 case iDVBFrontend::feSatellite:
134 eDVBFrontendParametersSatellite s;
136 PutSatelliteDataToDict(dict, s);
139 case iDVBFrontend::feTerrestrial:
141 eDVBFrontendParametersTerrestrial t;
143 PutTerrestrialDataToDict(dict, t);
146 case iDVBFrontend::feCable:
148 eDVBFrontendParametersCable c;
150 PutCableDataToDict(dict, c);
154 eDebug("unknown frontend type %d", system);
169 DEFINE_REF(eStaticServiceDVBBouquetInformation);
171 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
173 ePtr<iDVBChannelList> db;
174 ePtr<eDVBResourceManager> res;
177 if ((err = eDVBResourceManager::getInstance(res)) != 0)
179 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
182 if ((err = res->getChannelList(db)) != 0)
184 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
189 if ((err = db->getBouquet(ref, bouquet)) != 0)
191 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
195 if ( bouquet && bouquet->m_bouquet_name.length() )
197 name = bouquet->m_bouquet_name;
204 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
206 if (ref.flags & eServiceReference::isGroup)
208 ePtr<iDVBChannelList> db;
209 ePtr<eDVBResourceManager> res;
211 if (eDVBResourceManager::getInstance(res))
213 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
217 if (res->getChannelList(db))
219 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
224 if (db->getBouquet(ref, bouquet))
226 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
230 int prio_order = eDVBFrontend::getTypePriorityOrder();
232 eDVBChannelID chid, chid_ignore;
233 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
234 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
236 static unsigned char prio_map[6][3] = {
237 { 3, 2, 1 }, // -S -C -T
238 { 3, 1, 2 }, // -S -T -C
239 { 2, 3, 1 }, // -C -S -T
240 { 1, 3, 2 }, // -C -T -S
241 { 1, 2, 3 }, // -T -C -S
242 { 2, 1, 3 } // -T -S -C
245 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
246 int tmp = res->canAllocateChannel(chid, chid_ignore, system, simulate);
251 case iDVBFrontend::feTerrestrial:
252 tmp = prio_map[prio_order][2];
254 case iDVBFrontend::feCable:
255 tmp = prio_map[prio_order][1];
258 case iDVBFrontend::feSatellite:
259 tmp = prio_map[prio_order][0];
265 m_playable_service = *it;
272 m_playable_service = eServiceReference();
276 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
281 #include <lib/dvb/epgcache.h>
283 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
285 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
288 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
290 DECLARE_REF(eStaticServiceDVBPVRInformation);
291 eServiceReference m_ref;
292 eDVBMetaParser m_parser;
294 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
295 RESULT getName(const eServiceReference &ref, std::string &name);
296 int getLength(const eServiceReference &ref);
297 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
298 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
299 int getInfo(const eServiceReference &ref, int w);
300 std::string getInfoString(const eServiceReference &ref,int w);
301 PyObject *getInfoObject(const eServiceReference &r, int what);
304 DEFINE_REF(eStaticServiceDVBPVRInformation);
306 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
309 m_parser.parseFile(ref.path);
312 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
314 ASSERT(ref == m_ref);
315 if (!ref.name.empty())
317 else if (!m_parser.m_name.empty())
318 name = m_parser.m_name;
322 size_t n = name.rfind('/');
323 if (n != std::string::npos)
324 name = name.substr(n + 1);
329 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
331 ASSERT(ref == m_ref);
336 stat(ref.path.c_str(), &s);
338 if (tstools.openFile(ref.path.c_str(), 1))
341 /* check if cached data is still valid */
342 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
343 return m_parser.m_length / 90000;
345 /* open again, this time with stream info */
346 if (tstools.openFile(ref.path.c_str()))
349 /* otherwise, re-calc length and update meta file */
351 if (tstools.calcLen(len))
354 m_parser.m_length = len;
355 m_parser.m_filesize = s.st_size;
356 m_parser.updateMeta(ref.path);
357 return m_parser.m_length / 90000;
360 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
364 case iServiceInformation::sDescription:
365 return iServiceInformation::resIsString;
366 case iServiceInformation::sServiceref:
367 return iServiceInformation::resIsString;
368 case iServiceInformation::sFileSize:
369 return m_parser.m_filesize;
370 case iServiceInformation::sTimeCreate:
371 if (m_parser.m_time_create)
372 return m_parser.m_time_create;
374 return iServiceInformation::resNA;
376 return iServiceInformation::resNA;
380 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
384 case iServiceInformation::sDescription:
385 return m_parser.m_description;
386 case iServiceInformation::sServiceref:
387 return m_parser.m_ref.toString();
388 case iServiceInformation::sTags:
389 return m_parser.m_tags;
395 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
399 case iServiceInformation::sFileSize:
400 return PyLong_FromLongLong(m_parser.m_filesize);
406 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
408 if (!ref.path.empty())
410 if (ref.path.substr(0, 7) == "http://")
412 eServiceReference equivalentref(ref);
413 /* this might be a scrambled stream (id + 0x100), force equivalent dvb type */
414 equivalentref.type = eServiceFactoryDVB::id;
415 equivalentref.path.clear();
416 return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
420 ePtr<eServiceEvent> event = new eServiceEvent;
421 std::string filename = ref.path;
422 filename.erase(filename.length()-2, 2);
424 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
435 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
437 DECLARE_REF(eDVBPVRServiceOfflineOperations);
438 eServiceReferenceDVB m_ref;
440 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
442 RESULT deleteFromDisk(int simulate);
443 RESULT getListOfFilenames(std::list<std::string> &);
447 DEFINE_REF(eDVBPVRServiceOfflineOperations);
449 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
453 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
459 std::list<std::string> res;
460 if (getListOfFilenames(res))
463 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
465 eDebug("FATAL !! can't get background file eraser");
467 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
469 eDebug("Removing %s...", i->c_str());
471 eraser->erase(i->c_str());
473 ::unlink(i->c_str());
480 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
483 res.push_back(m_ref.path);
485 // handling for old splitted recordings (enigma 1)
490 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
492 if (stat(buf, &s) < 0)
497 res.push_back(m_ref.path + ".meta");
498 res.push_back(m_ref.path + ".ap");
499 res.push_back(m_ref.path + ".sc");
500 res.push_back(m_ref.path + ".cuts");
501 std::string tmp = m_ref.path;
502 tmp.erase(m_ref.path.length()-3);
503 res.push_back(tmp + ".eit");
507 RESULT eDVBPVRServiceOfflineOperations::reindex()
509 const char *filename = m_ref.path.c_str();
510 eDebug("reindexing %s...", filename);
512 eMPEGStreamInformation info;
513 eMPEGStreamParserTS parser(info);
515 info.startSave(filename);
519 int err = f.open(m_ref.path.c_str(), 0);
524 off_t length = f.length();
525 unsigned char buffer[188*256*4];
528 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
529 int r = f.read(offset, buffer, sizeof(buffer));
535 parser.parseData(offset, buffer, r);
544 DEFINE_REF(eServiceFactoryDVB)
546 eServiceFactoryDVB::eServiceFactoryDVB()
548 ePtr<eServiceCenter> sc;
550 eServiceCenter::getPrivInstance(sc);
553 std::list<std::string> extensions;
554 extensions.push_back("ts");
555 extensions.push_back("trp");
556 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
559 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
560 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
563 eServiceFactoryDVB::~eServiceFactoryDVB()
565 ePtr<eServiceCenter> sc;
567 eServiceCenter::getPrivInstance(sc);
569 sc->removeServiceFactory(eServiceFactoryDVB::id);
572 DEFINE_REF(eDVBServiceList);
574 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
578 eDVBServiceList::~eDVBServiceList()
582 RESULT eDVBServiceList::startQuery()
584 ePtr<iDVBChannelList> db;
585 ePtr<eDVBResourceManager> res;
588 if ((err = eDVBResourceManager::getInstance(res)) != 0)
590 eDebug("no resource manager");
593 if ((err = res->getChannelList(db)) != 0)
595 eDebug("no channel list");
599 ePtr<eDVBChannelQuery> q;
601 if (!m_parent.path.empty())
603 eDVBChannelQuery::compile(q, m_parent.path);
606 eDebug("compile query failed");
611 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
613 eDebug("startQuery failed");
620 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
622 eServiceReferenceDVB ref;
627 while (!m_query->getNextResult(ref))
631 list.sort(iListableServiceCompare(this));
636 // The first argument of this function is a format string to specify the order and
637 // the content of the returned list
638 // useable format options are
639 // R = Service Reference (as swig object .. this is very slow)
640 // S = Service Reference (as python string object .. same as ref.toString())
641 // C = Service Reference (as python string object .. same as ref.toCompareString())
642 // N = Service Name (as python string object)
643 // n = Short Service Name (short name brakets used) (as python string object)
644 // when exactly one return value per service is selected in the format string,
645 // then each value is directly a list entry
646 // when more than one value is returned per service, then the list is a list of
648 // unknown format string chars are returned as python None values !
649 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
652 std::list<eServiceReference> tmplist;
655 if (!format || !(retcount=strlen(format)))
656 format = "R"; // just return service reference swig object ...
658 if (!getContent(tmplist, sorted))
660 int services=tmplist.size();
661 ePtr<iStaticServiceInformation> sptr;
662 eServiceCenterPtr service_center;
664 if (strchr(format, 'N') || strchr(format, 'n'))
665 eServiceCenter::getPrivInstance(service_center);
667 ret = PyList_New(services);
668 std::list<eServiceReference>::iterator it(tmplist.begin());
670 for (int cnt=0; cnt < services; ++cnt)
672 eServiceReference &ref=*it++;
673 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
674 for (int i=0; i < retcount; ++i)
679 case 'R': // service reference (swig)object
680 tmp = NEW_eServiceReference(ref);
682 case 'C': // service reference compare string
683 tmp = PyString_FromString(ref.toCompareString().c_str());
685 case 'S': // service reference string
686 tmp = PyString_FromString(ref.toString().c_str());
688 case 'N': // service name
691 service_center->info(ref, sptr);
695 sptr->getName(ref, name);
697 // filter short name brakets
699 while((pos = name.find("\xc2\x86")) != std::string::npos)
701 while((pos = name.find("\xc2\x87")) != std::string::npos)
705 tmp = PyString_FromString(name.c_str());
709 tmp = PyString_FromString("<n/a>");
711 case 'n': // short service name
714 service_center->info(ref, sptr);
718 sptr->getName(ref, name);
719 name = buildShortName(name);
721 tmp = PyString_FromString(name.c_str());
725 tmp = PyString_FromString("<n/a>");
738 PyTuple_SET_ITEM(tuple, i, tmp);
740 PyList_SET_ITEM(ret, cnt, tmp);
744 PyList_SET_ITEM(ret, cnt, tuple);
747 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
750 RESULT eDVBServiceList::getNext(eServiceReference &ref)
755 return m_query->getNextResult((eServiceReferenceDVB&)ref);
758 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
760 if (m_parent.flags & eServiceReference::canDescent) // bouquet
762 ePtr<iDVBChannelList> db;
763 ePtr<eDVBResourceManager> resm;
765 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
768 if (db->getBouquet(m_parent, m_bouquet) != 0)
779 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
783 return m_bouquet->addService(ref, before);
786 RESULT eDVBServiceList::removeService(eServiceReference &ref)
790 return m_bouquet->removeService(ref);
793 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
797 return m_bouquet->moveService(ref, pos);
800 RESULT eDVBServiceList::flushChanges()
804 return m_bouquet->flushChanges();
807 RESULT eDVBServiceList::setListName(const std::string &name)
811 return m_bouquet->setListName(name);
814 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
816 ePtr<eDVBService> service;
817 int r = lookupService(service, ref);
820 // check resources...
821 ptr = new eDVBServicePlay(ref, service);
825 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
827 if (ref.path.empty())
829 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
833 bool isstream = ref.path.substr(0, 7) == "http://";
836 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref, isstream);
844 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
846 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
847 if (list->startQuery())
857 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
859 /* is a listable service? */
860 if (ref.flags & eServiceReference::canDescent) // bouquet
862 if ( !ref.name.empty() ) // satellites or providers list
863 ptr = m_StaticServiceDVBInfo;
864 else // a dvb bouquet
865 ptr = m_StaticServiceDVBBouquetInfo;
867 else if (!ref.path.empty()) /* do we have a PVR service? */
868 ptr = new eStaticServiceDVBPVRInformation(ref);
869 else // normal dvb service
871 ePtr<eDVBService> service;
872 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
873 ptr = m_StaticServiceDVBInfo;
875 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
881 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
883 if (ref.path.empty())
889 ptr = new eDVBPVRServiceOfflineOperations(ref);
894 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
896 if (!ref.path.empty()) // playback
898 eDVBMetaParser parser;
899 int ret=parser.parseFile(ref.path);
900 service = new eDVBService;
902 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
906 // TODO: handle the listing itself
907 // if (ref.... == -1) .. return "... bouquets ...";
908 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
910 ePtr<iDVBChannelList> db;
911 ePtr<eDVBResourceManager> res;
914 if ((err = eDVBResourceManager::getInstance(res)) != 0)
916 eDebug("no resource manager");
919 if ((err = res->getChannelList(db)) != 0)
921 eDebug("no channel list");
925 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
926 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
928 // eDebug("getService failed!");
936 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
937 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
940 m_is_stream = m_reference.path.substr(0, 7) == "http://";
941 m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
943 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
944 m_skipmode = m_fastforward = m_slowmotion = 0;
946 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
947 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
948 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
950 m_cuesheet_changed = 0;
951 m_cutlist_enabled = 1;
953 m_subtitle_widget = 0;
957 m_subtitle_sync_timer = eTimer::create(eApp);
959 m_current_video_pid_type = 0;
961 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
964 eDVBServicePlay::~eDVBServicePlay()
969 int ret=meta.parseFile(m_reference.path);
973 meta.m_service_data="";
974 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
975 meta.m_service_data += tmp;
977 for (int x=0; x < eDVBService::cacheMax; ++x)
979 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
982 sprintf(tmp, ",c:%02d%04x", x, entry);
983 meta.m_service_data += tmp;
986 meta.updateMeta(m_reference.path);
989 delete m_subtitle_widget;
992 void eDVBServicePlay::gotNewEvent()
996 ePtr<eServiceEvent> m_event_now, m_event_next;
997 getEvent(m_event_now, 0);
998 getEvent(m_event_next, 1);
1001 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1003 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1005 m_event((iPlayableService*)this, evUpdatedEventInfo);
1008 void eDVBServicePlay::serviceEvent(int event)
1010 m_tune_state = event;
1014 case eDVBServicePMTHandler::eventTuned:
1016 ePtr<iDVBDemux> m_demux;
1017 if (!m_service_handler.getDataDemux(m_demux))
1019 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1020 int sid = ref.getParentServiceID().get();
1022 sid = ref.getServiceID().get();
1023 if ( ref.getParentTransportStreamID().get() &&
1024 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1025 m_event_handler.startOther(m_demux, sid);
1027 m_event_handler.start(m_demux, sid);
1029 m_event((iPlayableService*)this, evTunedIn);
1032 case eDVBServicePMTHandler::eventNoResources:
1033 case eDVBServicePMTHandler::eventNoPAT:
1034 case eDVBServicePMTHandler::eventNoPATEntry:
1035 case eDVBServicePMTHandler::eventNoPMT:
1036 case eDVBServicePMTHandler::eventTuneFailed:
1037 case eDVBServicePMTHandler::eventMisconfiguration:
1039 eDebug("DVB service failed to tune - error %d", event);
1040 m_event((iPlayableService*)this, evTuneFailed);
1043 case eDVBServicePMTHandler::eventNewProgramInfo:
1045 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1046 if (m_timeshift_enabled)
1047 updateTimeshiftPids();
1048 if (!m_timeshift_active)
1050 if (m_first_program_info & 1 && m_is_pvr)
1052 m_first_program_info &= ~1;
1055 if (!m_timeshift_active)
1056 m_event((iPlayableService*)this, evUpdatedInfo);
1059 case eDVBServicePMTHandler::eventPreStart:
1062 case eDVBServicePMTHandler::eventEOF:
1063 m_event((iPlayableService*)this, evEOF);
1065 case eDVBServicePMTHandler::eventSOF:
1066 m_event((iPlayableService*)this, evSOF);
1068 case eDVBServicePMTHandler::eventHBBTVInfo:
1069 m_event((iPlayableService*)this, evHBBTVInfo);
1074 void eDVBServicePlay::serviceEventTimeshift(int event)
1078 case eDVBServicePMTHandler::eventNewProgramInfo:
1079 eDebug("eventNewProgramInfo TS");
1080 if (m_timeshift_active)
1083 if (m_first_program_info & 2)
1087 eDebug("re-apply slowmotion after timeshift file change");
1088 m_decoder->setSlowMotion(m_slowmotion);
1092 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1094 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1095 if (m_fastforward != 1)
1096 m_decoder->setFastForward(m_fastforward);
1098 m_decoder->setTrickmode();
1102 m_first_program_info &= ~2;
1104 m_event((iPlayableService*)this, evUpdatedInfo);
1107 case eDVBServicePMTHandler::eventSOF:
1109 if (!m_timeshift_file_next.empty())
1111 eDebug("timeshift SOF, switch to next file");
1114 m_first_program_info |= 2;
1116 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1117 r.path = m_timeshift_file_next;
1119 /* free the timeshift service handler, we need the resources */
1120 m_service_handler_timeshift.free();
1124 m_cue->seekTo(0, -1000);
1125 ePtr<iTsSource> source = createTsSource(r);
1126 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1128 m_event((iPlayableService*)this, evUser+1);
1132 m_event((iPlayableService*)this, evSOF);
1134 case eDVBServicePMTHandler::eventEOF:
1135 if ((!m_is_paused) && (m_skipmode >= 0))
1137 if (m_timeshift_file_next.empty())
1139 eDebug("timeshift EOF, so let's go live");
1144 eDebug("timeshift EOF, switch to next file");
1146 m_first_program_info |= 2;
1148 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1149 r.path = m_timeshift_file_next;
1151 /* free the timeshift service handler, we need the resources */
1152 m_service_handler_timeshift.free();
1155 ePtr<iTsSource> source = createTsSource(r);
1156 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 */
1158 m_event((iPlayableService*)this, evUser+1);
1165 RESULT eDVBServicePlay::start()
1167 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1169 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1170 two (one for decoding, one for data source), as we must be prepared
1171 to start recording from the data demux. */
1174 eDVBMetaParser meta;
1175 if (!meta.parseFile(m_reference.path))
1177 service = meta.m_ref;
1178 service.path = m_reference.path;
1180 m_cue = new eCueSheet();
1183 m_event(this, evStart);
1185 m_first_program_info = 1;
1186 ePtr<iTsSource> source = createTsSource(service);
1187 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1191 /* inject EIT if there is a stored one */
1192 std::string filename = service.path;
1193 filename.erase(filename.length()-2, 2);
1195 ePtr<eServiceEvent> event = new eServiceEvent;
1196 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1198 ePtr<eServiceEvent> empty;
1199 m_event_handler.inject(event, 0);
1200 m_event_handler.inject(empty, 1);
1202 m_event(this, evStart);
1207 RESULT eDVBServicePlay::stop()
1209 /* add bookmark for last play position */
1212 pts_t play_position, length;
1213 if (!getPlayPosition(play_position))
1215 /* remove last position */
1216 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1218 if (i->what == 3) /* current play position */
1220 m_cue_entries.erase(i);
1221 i = m_cue_entries.begin();
1227 if (getLength(length))
1232 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1234 m_cuesheet_changed = 1;
1238 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1240 m_service_handler_timeshift.free();
1241 m_service_handler.free();
1243 if (m_is_pvr && m_cuesheet_changed)
1246 /* save cuesheet only when main file is accessible. */
1247 if (!::stat(m_reference.path.c_str(), &s))
1250 m_event((iPlayableService*)this, evStopped);
1254 RESULT eDVBServicePlay::setTarget(int target)
1256 m_is_primary = !target;
1260 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1262 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1266 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1268 /* note: we check for timeshift to be enabled,
1269 not neccessary active. if you pause when timeshift
1270 is not active, you should activate it when unpausing */
1271 if ((!m_is_pvr) && (!m_timeshift_enabled))
1281 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1283 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1284 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1285 setFastForward_internal(0);
1288 m_slowmotion = ratio;
1289 return m_decoder->setSlowMotion(ratio);
1295 RESULT eDVBServicePlay::setFastForward(int ratio)
1297 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1299 return setFastForward_internal(ratio);
1302 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1304 int skipmode, ffratio, ret = 0;
1311 } else if (ratio > 0)
1319 } else // if (ratio < 0)
1325 if (m_skipmode != skipmode)
1327 eDebug("setting cue skipmode to %d", skipmode);
1330 long long _skipmode = skipmode;
1331 if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1334 _skipmode = skipmode * 3;
1336 _skipmode = skipmode * 4;
1339 m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1343 m_skipmode = skipmode;
1346 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1348 m_fastforward = ffratio;
1354 ; /* return m_decoder->play(); is done in caller*/
1355 else if (ffratio != 1)
1356 ret = m_decoder->setFastForward(ffratio);
1358 ret = m_decoder->setTrickmode();
1361 eDebug("final seek after trickplay ret %d", seekTo(pos));
1366 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1368 if (m_is_pvr || m_timeshift_enabled)
1378 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1379 RESULT eDVBServicePlay::getLength(pts_t &len)
1381 ePtr<iDVBPVRChannel> pvr_channel;
1383 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1386 return pvr_channel->getLength(len);
1389 RESULT eDVBServicePlay::pause()
1391 eDebug("eDVBServicePlay::pause");
1392 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1397 return m_decoder->pause();
1402 RESULT eDVBServicePlay::unpause()
1404 eDebug("eDVBServicePlay::unpause");
1405 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1410 return m_decoder->play();
1415 RESULT eDVBServicePlay::seekTo(pts_t to)
1417 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1419 if (!m_decode_demux)
1422 ePtr<iDVBPVRChannel> pvr_channel;
1424 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1430 m_cue->seekTo(0, to);
1431 m_dvb_subtitle_pages.clear();
1432 m_subtitle_pages.clear();
1437 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1439 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1441 if (!m_decode_demux)
1444 ePtr<iDVBPVRChannel> pvr_channel;
1446 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1451 /* HACK until we have skip-AP api */
1452 if ((to > 0) && (to < 100))
1460 m_cue->seekTo(mode, to);
1461 m_dvb_subtitle_pages.clear();
1462 m_subtitle_pages.clear();
1466 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1468 ePtr<iDVBPVRChannel> pvr_channel;
1470 if (!m_decode_demux)
1473 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1478 /* if there is a decoder, use audio or video PTS */
1481 r = m_decoder->getPTS(0, pos);
1487 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1490 RESULT eDVBServicePlay::setTrickmode(int trick)
1492 /* currently unimplemented */
1496 RESULT eDVBServicePlay::isCurrentlySeekable()
1501 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1502 if (m_decoder->getVideoProgressive() == -1)
1508 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1514 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1520 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1526 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1532 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1538 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1541 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1542 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1544 if (!m_timeshift_enabled)
1546 /* query config path */
1548 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1549 eDebug("could not query ts path from config");
1553 /* we need enough diskspace */
1555 if (statfs(tspath.c_str(), &fs) < 0)
1557 eDebug("statfs failed!");
1561 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1563 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1573 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1584 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1590 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1596 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1602 RESULT eDVBServicePlay::getName(std::string &name)
1606 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1607 return i->getName(m_reference, name);
1609 else if (m_is_stream)
1611 name = m_reference.name;
1614 name = m_reference.path;
1621 else if (m_dvb_service)
1623 m_dvb_service->getName(m_reference, name);
1627 else if (!m_reference.name.empty())
1628 eStaticServiceDVBInformation().getName(m_reference, name);
1630 name = "DVB service";
1634 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1636 return m_event_handler.getEvent(evt, nownext);
1639 int eDVBServicePlay::getInfo(int w)
1641 eDVBServicePMTHandler::program program;
1643 if (w == sCAIDs || w == sCAIDPIDs)
1644 return resIsPyObject;
1646 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1648 int no_program_info = 0;
1650 if (h.getProgramInfo(program))
1651 no_program_info = 1;
1657 return m_decoder->getVideoHeight();
1661 return m_decoder->getVideoWidth();
1665 return m_decoder->getVideoFrameRate();
1669 return m_decoder->getVideoProgressive();
1675 aspect = m_decoder->getVideoAspect();
1676 if (aspect == -1 && no_program_info)
1678 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1680 ePtr<eServiceEvent> evt;
1681 if (!m_event_handler.getEvent(evt, 0))
1683 ePtr<eComponentData> data;
1684 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1686 if ( data->getStreamContent() == 1 )
1688 switch(data->getComponentType())
1691 case 1: // 4:3 SD PAL
1693 case 3: // 16:9 SD PAL
1694 case 4: // > 16:9 PAL
1695 case 5: // 4:3 SD NTSC
1697 case 7: // 16:9 SD NTSC
1698 case 8: // > 16:9 NTSC
1701 case 9: // 4:3 HD PAL
1703 case 0xB: // 16:9 HD PAL
1704 case 0xC: // > 16:9 HD PAL
1705 case 0xD: // 4:3 HD NTSC
1707 case 0xF: // 16:9 HD NTSC
1708 case 0x10: // > 16:9 HD PAL
1709 return data->getComponentType();
1719 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1723 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1727 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1728 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1732 int apid = m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID);
1735 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1738 apid = m_dvb_service->getCacheEntry(eDVBService::cDDPPID);
1741 apid = m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID);
1744 apid = m_dvb_service->getCacheEntry(eDVBService::cAACAPID);
1748 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1752 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1756 if (no_program_info) return -1; return program.pcrPid;
1757 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1758 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1759 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1760 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1761 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1762 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1763 case sProvider: if (!m_dvb_service) return -1; return -2;
1764 case sServiceref: return resIsString;
1765 case sDVBState: return m_tune_state;
1772 std::string eDVBServicePlay::getInfoString(int w)
1777 if (!m_dvb_service) return "";
1778 return m_dvb_service->m_provider_name;
1780 return m_reference.toString();
1784 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1788 case sLiveStreamDemuxId:
1791 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1801 return iServiceInformation::getInfoString(w);
1804 PyObject *eDVBServicePlay::getInfoObject(int w)
1809 return m_service_handler.getCaIds();
1811 return m_service_handler.getCaIds(true);
1812 case sTransponderData:
1813 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1816 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1817 return h.getHbbTVApplications();
1822 return iServiceInformation::getInfoObject(w);
1825 int eDVBServicePlay::getNumberOfTracks()
1827 eDVBServicePMTHandler::program program;
1828 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1829 if (h.getProgramInfo(program))
1831 return program.audioStreams.size();
1834 int eDVBServicePlay::getCurrentTrack()
1836 eDVBServicePMTHandler::program program;
1837 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1838 if (h.getProgramInfo(program))
1841 int max = program.audioStreams.size();
1844 for (i = 0; i < max; ++i)
1845 if (program.audioStreams[i].pid == m_current_audio_pid)
1851 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1853 int ret = selectAudioStream(i);
1855 if (m_decoder->set())
1861 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1863 eDVBServicePMTHandler::program program;
1864 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1866 if (h.getProgramInfo(program))
1869 if (i >= program.audioStreams.size())
1872 info.m_pid = program.audioStreams[i].pid;
1874 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1875 info.m_description = "MPEG";
1876 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1877 info.m_description = "Dolby Digital";
1878 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1879 info.m_description = "Dolby Digital+";
1880 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1881 info.m_description = "AAC";
1882 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1883 info.m_description = "AAC-HE";
1884 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1885 info.m_description = "DTS";
1886 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1887 info.m_description = "DTS-HD";
1889 info.m_description = "???";
1891 if (program.audioStreams[i].component_tag != -1)
1893 ePtr<eServiceEvent> evt;
1894 if (!m_event_handler.getEvent(evt, 0))
1896 ePtr<eComponentData> data;
1897 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1898 info.m_language = data->getText();
1902 if (info.m_language.empty())
1903 info.m_language = program.audioStreams[i].language_code;
1908 int eDVBServicePlay::selectAudioStream(int i)
1910 eDVBServicePMTHandler::program program;
1911 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1912 pts_t position = -1;
1914 if (h.getProgramInfo(program))
1917 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1925 stream = program.defaultAudioStream;
1927 int apid = -1, apidtype = -1;
1929 if (((unsigned int)stream) < program.audioStreams.size())
1931 apid = program.audioStreams[stream].pid;
1932 apidtype = program.audioStreams[stream].type;
1935 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1936 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1938 m_current_audio_pid = apid;
1940 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1942 eDebug("set audio pid failed");
1947 eDebug("seekTo ret %d", seekTo(position));
1951 /* 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 */
1952 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1954 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1956 rdsPid = program.audioStreams[stream].rdsPid;
1957 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1960 ePtr<iDVBDemux> data_demux;
1961 if (!h.getDataDemux(data_demux))
1963 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1964 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1965 m_rds_decoder->start(rdsPid);
1970 /* store new pid as default only when:
1971 a.) we have an entry in the service db for the current service,
1972 b.) we are not playing back something,
1973 c.) we are not selecting the default entry. (we wouldn't change
1974 anything in the best case, or destroy the default setting in
1975 case the real default is not yet available.)
1977 if (m_dvb_service && ((i != -1)
1978 || ((m_dvb_service->getCacheEntry(eDVBService::cMPEGAPID) == -1)
1979 && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)
1980 && (m_dvb_service->getCacheEntry(eDVBService::cDDPPID)==-1)
1981 && (m_dvb_service->getCacheEntry(eDVBService::cAACHEAPID)==-1)
1982 && (m_dvb_service->getCacheEntry(eDVBService::cAACAPID)==-1))))
1984 m_dvb_service->setCacheEntry(eDVBService::cMPEGAPID, apidtype == eDVBAudio::aMPEG ? apid : -1);
1985 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apidtype == eDVBAudio::aAC3 ? apid : -1);
1986 m_dvb_service->setCacheEntry(eDVBService::cDDPPID, apidtype == eDVBAudio::aDDP ? apid : -1);
1987 m_dvb_service->setCacheEntry(eDVBService::cAACHEAPID, apidtype == eDVBAudio::aAACHE ? apid : -1);
1988 m_dvb_service->setCacheEntry(eDVBService::cAACAPID, apidtype == eDVBAudio::aAAC ? apid : -1);
1991 h.resetCachedProgram();
1996 int eDVBServicePlay::getCurrentChannel()
1998 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
2001 RESULT eDVBServicePlay::selectChannel(int i)
2003 if (i < LEFT || i > RIGHT || i == STEREO)
2006 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2008 m_decoder->setAudioChannel(i);
2012 std::string eDVBServicePlay::getText(int x)
2018 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2020 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2025 void eDVBServicePlay::rdsDecoderEvent(int what)
2029 case eDVBRdsDecoder::RadioTextChanged:
2030 m_event((iPlayableService*)this, evUpdatedRadioText);
2032 case eDVBRdsDecoder::RtpTextChanged:
2033 m_event((iPlayableService*)this, evUpdatedRtpText);
2035 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2036 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2038 case eDVBRdsDecoder::RecvRassSlidePic:
2039 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2044 void eDVBServicePlay::showRassSlidePicture()
2050 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2051 if (rass_slide_pic.length())
2052 m_decoder->showSinglePic(rass_slide_pic.c_str());
2054 eDebug("empty filename for rass slide picture received!!");
2057 eDebug("no MPEG Decoder to show iframes avail");
2060 eDebug("showRassSlidePicture called.. but not decoder");
2063 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2069 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2070 if (rass_interactive_pic.length())
2071 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2073 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2076 eDebug("no MPEG Decoder to show iframes avail");
2079 eDebug("showRassInteractivePic called.. but not decoder");
2082 ePyObject eDVBServicePlay::getRassInteractiveMask()
2085 return m_rds_decoder->getRassPictureMask();
2089 int eDVBServiceBase::getFrontendInfo(int w)
2091 eUsePtr<iDVBChannel> channel;
2092 if(m_service_handler.getChannel(channel))
2094 ePtr<iDVBFrontend> fe;
2095 if(channel->getFrontend(fe))
2097 return fe->readFrontendData(w);
2100 PyObject *eDVBServiceBase::getFrontendData()
2102 ePyObject ret = PyDict_New();
2105 eUsePtr<iDVBChannel> channel;
2106 if(!m_service_handler.getChannel(channel))
2108 ePtr<iDVBFrontend> fe;
2109 if(!channel->getFrontend(fe))
2110 fe->getFrontendData(ret);
2118 PyObject *eDVBServiceBase::getFrontendStatus()
2120 ePyObject ret = PyDict_New();
2123 eUsePtr<iDVBChannel> channel;
2124 if(!m_service_handler.getChannel(channel))
2126 ePtr<iDVBFrontend> fe;
2127 if(!channel->getFrontend(fe))
2128 fe->getFrontendStatus(ret);
2136 PyObject *eDVBServiceBase::getTransponderData(bool original)
2138 ePyObject ret = PyDict_New();
2141 eUsePtr<iDVBChannel> channel;
2142 if(!m_service_handler.getChannel(channel))
2144 ePtr<iDVBFrontend> fe;
2145 if(!channel->getFrontend(fe))
2146 fe->getTransponderData(ret, original);
2154 PyObject *eDVBServiceBase::getAll(bool original)
2156 ePyObject ret = getTransponderData(original);
2159 eUsePtr<iDVBChannel> channel;
2160 if(!m_service_handler.getChannel(channel))
2162 ePtr<iDVBFrontend> fe;
2163 if(!channel->getFrontend(fe))
2165 fe->getFrontendData(ret);
2166 fe->getFrontendStatus(ret);
2173 int eDVBServicePlay::getNumberOfSubservices()
2175 ePtr<eServiceEvent> evt;
2176 if (!m_event_handler.getEvent(evt, 0))
2177 return evt->getNumOfLinkageServices();
2181 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2183 ePtr<eServiceEvent> evt;
2184 if (!m_event_handler.getEvent(evt, 0))
2186 if (!evt->getLinkageService(sub, m_reference, n))
2189 sub.type=eServiceReference::idInvalid;
2193 RESULT eDVBServicePlay::startTimeshift()
2195 ePtr<iDVBDemux> demux;
2197 eDebug("Start timeshift!");
2199 if (m_timeshift_enabled)
2202 /* start recording with the data demux. */
2203 if (m_service_handler.getDataDemux(demux))
2206 demux->createTSRecorder(m_record);
2211 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2212 eDebug("could not query ts path");
2215 tspath.append("/timeshift.XXXXXX");
2217 templ = new char[tspath.length() + 1];
2218 strcpy(templ, tspath.c_str());
2220 m_timeshift_fd = mkstemp(templ);
2221 m_timeshift_file = std::string(templ);
2223 eDebug("recording to %s", templ);
2227 if (m_timeshift_fd < 0)
2233 m_record->setTargetFD(m_timeshift_fd);
2234 m_record->setTargetFilename(m_timeshift_file.c_str());
2235 m_record->enableAccessPoints(false);
2237 m_timeshift_enabled = 1;
2239 updateTimeshiftPids();
2245 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2247 if (!m_timeshift_enabled)
2253 m_timeshift_enabled = 0;
2258 close(m_timeshift_fd);
2259 eDebug("remove timeshift file");
2260 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2263 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2264 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2270 int eDVBServicePlay::isTimeshiftActive()
2272 return m_timeshift_enabled && m_timeshift_active;
2275 RESULT eDVBServicePlay::activateTimeshift()
2277 if (!m_timeshift_enabled)
2280 if (!m_timeshift_active)
2282 switchToTimeshift();
2289 PyObject *eDVBServicePlay::getCutList()
2291 ePyObject list = PyList_New(0);
2293 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2295 ePyObject tuple = PyTuple_New(2);
2296 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2297 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2298 PyList_Append(list, tuple);
2305 void eDVBServicePlay::setCutList(ePyObject list)
2307 if (!PyList_Check(list))
2309 int size = PyList_Size(list);
2312 m_cue_entries.clear();
2314 for (i=0; i<size; ++i)
2316 ePyObject tuple = PyList_GET_ITEM(list, i);
2317 if (!PyTuple_Check(tuple))
2319 eDebug("non-tuple in cutlist");
2322 if (PyTuple_Size(tuple) != 2)
2324 eDebug("cutlist entries need to be a 2-tuple");
2327 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2328 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2330 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2333 pts_t pts = PyLong_AsLongLong(ppts);
2334 int type = PyInt_AsLong(ptype);
2335 m_cue_entries.insert(cueEntry(pts, type));
2336 eDebug("adding %08llx, %d", pts, type);
2338 m_cuesheet_changed = 1;
2340 cutlistToCuesheet();
2341 m_event((iPlayableService*)this, evCuesheetChanged);
2344 void eDVBServicePlay::setCutListEnable(int enable)
2346 m_cutlist_enabled = enable;
2347 cutlistToCuesheet();
2350 void eDVBServicePlay::updateTimeshiftPids()
2355 eDVBServicePMTHandler::program program;
2356 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2358 if (h.getProgramInfo(program))
2362 int timing_pid = -1;
2363 int timing_pid_type = -1;
2364 std::set<int> pids_to_record;
2365 pids_to_record.insert(0); // PAT
2366 if (program.pmtPid != -1)
2367 pids_to_record.insert(program.pmtPid); // PMT
2369 if (program.textPid != -1)
2370 pids_to_record.insert(program.textPid); // Videotext
2372 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2373 i(program.videoStreams.begin());
2374 i != program.videoStreams.end(); ++i)
2376 pids_to_record.insert(i->pid);
2378 if (timing_pid == -1)
2380 timing_pid = i->pid;
2381 timing_pid_type = i->type;
2385 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2386 i(program.audioStreams.begin());
2387 i != program.audioStreams.end(); ++i)
2389 pids_to_record.insert(i->pid);
2391 if (timing_pid == -1)
2393 timing_pid = i->pid;
2394 timing_pid_type = -1;
2398 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2399 i(program.subtitleStreams.begin());
2400 i != program.subtitleStreams.end(); ++i)
2401 pids_to_record.insert(i->pid);
2403 std::set<int> new_pids, obsolete_pids;
2405 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2406 m_pids_active.begin(), m_pids_active.end(),
2407 std::inserter(new_pids, new_pids.begin()));
2409 std::set_difference(
2410 m_pids_active.begin(), m_pids_active.end(),
2411 pids_to_record.begin(), pids_to_record.end(),
2412 std::inserter(new_pids, new_pids.begin())
2415 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2416 m_record->addPID(*i);
2418 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2419 m_record->removePID(*i);
2421 if (timing_pid != -1)
2422 m_record->setTimingPID(timing_pid, timing_pid_type);
2426 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2428 m_timeshift_file_next = f;
2432 void eDVBServicePlay::switchToLive()
2434 if (!m_timeshift_active)
2437 eDebug("SwitchToLive");
2441 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2443 /* free the timeshift service handler, we need the resources */
2444 m_service_handler_timeshift.free();
2446 updateDecoder(true);
2449 void eDVBServicePlay::resetTimeshift(int start)
2454 m_teletext_parser = 0;
2456 m_subtitle_parser = 0;
2457 m_new_subtitle_page_connection = 0;
2458 m_new_dvb_subtitle_page_connection = 0;
2459 m_rds_decoder_event_connection = 0;
2460 m_video_event_connection = 0;
2461 m_timeshift_changed = 1;
2462 m_timeshift_file_next.clear();
2466 m_cue = new eCueSheet();
2467 m_timeshift_active = 1;
2470 m_timeshift_active = 0;
2473 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2477 eHttpStream *f = new eHttpStream();
2478 f->open(ref.path.c_str());
2479 return ePtr<iTsSource>(f);
2483 eRawFile *f = new eRawFile();
2484 f->open(ref.path.c_str());
2485 return ePtr<iTsSource>(f);
2489 void eDVBServicePlay::switchToTimeshift()
2491 if (m_timeshift_active)
2496 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2497 r.path = m_timeshift_file;
2499 m_cue->seekTo(0, -1000);
2501 ePtr<iTsSource> source = createTsSource(r);
2502 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 */
2504 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2506 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2509 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2511 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2512 bool mustPlay = false;
2514 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2516 eDVBServicePMTHandler::program program;
2517 if (h.getProgramInfo(program))
2518 eDebug("getting program info failed.");
2521 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2522 if (!program.videoStreams.empty())
2524 eDebugNoNewLine(" (");
2525 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2526 i(program.videoStreams.begin());
2527 i != program.videoStreams.end(); ++i)
2534 if (i != program.videoStreams.begin())
2535 eDebugNoNewLine(", ");
2536 eDebugNoNewLine("%04x", i->pid);
2538 eDebugNoNewLine(")");
2540 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2541 if (!program.audioStreams.empty())
2543 eDebugNoNewLine(" (");
2544 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2545 i(program.audioStreams.begin());
2546 i != program.audioStreams.end(); ++i)
2548 if (i != program.audioStreams.begin())
2549 eDebugNoNewLine(", ");
2550 eDebugNoNewLine("%04x", i->pid);
2552 eDebugNoNewLine(")");
2554 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2555 pcrpid = program.pcrPid;
2556 eDebug(", and the text pid is %04x", program.textPid);
2557 tpid = program.textPid;
2562 h.getDecodeDemux(m_decode_demux);
2565 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2567 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2570 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2571 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2572 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2573 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2574 if (m_timeshift_changed)
2576 ePyObject subs = getCachedSubtitle();
2577 if (subs != Py_None)
2579 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2580 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2581 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2582 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2583 if (type == 0) // dvb
2584 m_subtitle_parser->start(pid, comp_page, anc_page);
2585 else if (type == 1) // ttx
2586 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2593 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2597 m_timeshift_changed = 0;
2601 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2604 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2605 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2606 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2610 eServiceReferenceDVB ref;
2611 m_service_handler.getServiceReference(ref);
2612 eServiceReferenceDVB parent = ref.getParentServiceReference();
2617 ePtr<eDVBResourceManager> res_mgr;
2618 if (!eDVBResourceManager::getInstance(res_mgr))
2620 ePtr<iDVBChannelList> db;
2621 if (!res_mgr->getChannelList(db))
2623 ePtr<eDVBService> origService;
2624 if (!db->getService(parent, origService))
2626 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2627 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2634 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2635 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2637 m_decoder->setVideoPID(vpid, vpidtype);
2638 m_current_video_pid_type = vpidtype;
2639 selectAudioStream();
2641 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2642 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2643 m_decoder->setSyncPCR(pcrpid);
2645 m_decoder->setSyncPCR(-1);
2649 m_decoder->setTextPID(tpid);
2650 m_teletext_parser->start(program.textPid);
2653 if (vpid > 0 && vpid < 0x2000)
2657 std::string radio_pic;
2658 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2659 m_decoder->setRadioPic(radio_pic);
2667 m_decoder->setAudioChannel(achannel);
2669 /* don't worry about non-existing services, nor pvr services */
2672 /* (audio pid will be set in selectAudioTrack */
2673 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2674 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2675 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2676 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2678 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2679 sendSeekableStateChanged = true;
2681 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2683 if (sendSeekableStateChanged)
2684 m_event((iPlayableService*)this, evSeekableStatusChanged);
2687 void eDVBServicePlay::loadCuesheet()
2689 std::string filename = m_reference.path + ".cuts";
2691 m_cue_entries.clear();
2693 FILE *f = fopen(filename.c_str(), "rb");
2697 eDebug("loading cuts..");
2700 unsigned long long where;
2703 if (!fread(&where, sizeof(where), 1, f))
2705 if (!fread(&what, sizeof(what), 1, f))
2708 #if BYTE_ORDER == LITTLE_ENDIAN
2709 where = bswap_64(where);
2716 m_cue_entries.insert(cueEntry(where, what));
2719 eDebug("%zd entries", m_cue_entries.size());
2721 eDebug("cutfile not found!");
2723 m_cuesheet_changed = 0;
2724 cutlistToCuesheet();
2725 m_event((iPlayableService*)this, evCuesheetChanged);
2728 void eDVBServicePlay::saveCuesheet()
2730 std::string filename = m_reference.path + ".cuts";
2732 FILE *f = fopen(filename.c_str(), "wb");
2736 unsigned long long where;
2739 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2741 #if BYTE_ORDER == BIG_ENDIAN
2744 where = bswap_64(i->where);
2746 what = htonl(i->what);
2747 fwrite(&where, sizeof(where), 1, f);
2748 fwrite(&what, sizeof(what), 1, f);
2754 m_cuesheet_changed = 0;
2757 void eDVBServicePlay::cutlistToCuesheet()
2761 eDebug("no cue sheet");
2766 if (!m_cutlist_enabled)
2768 m_cue->commitSpans();
2769 eDebug("cutlists were disabled");
2773 pts_t in = 0, out = 0, length = 0;
2777 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2779 int have_any_span = 0;
2783 if (i == m_cue_entries.end())
2785 if (!have_any_span && !in)
2789 if (i->what == 0) /* in */
2793 } else if (i->what == 1) /* out */
2795 else /* mark (2) or last play position (3) */
2814 m_cue->addSourceSpan(in, out);
2820 if (i == m_cue_entries.end())
2823 m_cue->commitSpans();
2826 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2828 if (m_subtitle_widget)
2829 disableSubtitles(parent);
2832 int tuplesize = PyTuple_Size(tuple);
2835 if (!PyTuple_Check(tuple))
2841 entry = PyTuple_GET_ITEM(tuple, 0);
2843 if (!PyInt_Check(entry))
2846 type = PyInt_AsLong(entry);
2848 if (type == 1) // teletext subtitles
2850 int page, magazine, pid;
2854 if (!m_teletext_parser)
2856 eDebug("enable teletext subtitles.. no parser !!!");
2860 entry = PyTuple_GET_ITEM(tuple, 1);
2861 if (!PyInt_Check(entry))
2863 pid = PyInt_AsLong(entry);
2865 entry = PyTuple_GET_ITEM(tuple, 2);
2866 if (!PyInt_Check(entry))
2868 page = PyInt_AsLong(entry);
2870 entry = PyTuple_GET_ITEM(tuple, 3);
2871 if (!PyInt_Check(entry))
2873 magazine = PyInt_AsLong(entry);
2875 m_subtitle_widget = new eSubtitleWidget(parent);
2876 m_subtitle_widget->resize(parent->size()); /* full size */
2877 m_teletext_parser->setPageAndMagazine(page, magazine);
2879 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2883 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2884 if (!m_subtitle_parser)
2886 eDebug("enable dvb subtitles.. no parser !!!");
2892 entry = PyTuple_GET_ITEM(tuple, 1);
2893 if (!PyInt_Check(entry))
2895 pid = PyInt_AsLong(entry);
2897 entry = PyTuple_GET_ITEM(tuple, 2);
2898 if (!PyInt_Check(entry))
2900 composition_page_id = PyInt_AsLong(entry);
2902 entry = PyTuple_GET_ITEM(tuple, 3);
2903 if (!PyInt_Check(entry))
2905 ancillary_page_id = PyInt_AsLong(entry);
2907 m_subtitle_widget = new eSubtitleWidget(parent);
2908 m_subtitle_widget->resize(parent->size()); /* full size */
2909 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2911 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2917 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2918 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2919 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2923 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2925 delete m_subtitle_widget;
2926 m_subtitle_widget = 0;
2927 if (m_subtitle_parser)
2929 m_subtitle_parser->stop();
2930 m_dvb_subtitle_pages.clear();
2932 if (m_teletext_parser)
2934 m_teletext_parser->setPageAndMagazine(-1, -1);
2935 m_subtitle_pages.clear();
2938 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2942 PyObject *eDVBServicePlay::getCachedSubtitle()
2946 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2949 unsigned int data = (unsigned int)tmp;
2950 int pid = (data&0xFFFF0000)>>16;
2951 ePyObject tuple = PyTuple_New(4);
2952 eDVBServicePMTHandler::program program;
2953 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2954 if (!h.getProgramInfo(program))
2956 if (program.textPid==pid) // teletext
2957 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2959 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2960 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2961 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2962 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2970 PyObject *eDVBServicePlay::getSubtitleList()
2972 if (!m_teletext_parser)
2975 ePyObject l = PyList_New(0);
2976 std::set<int> added_ttx_pages;
2978 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2979 m_teletext_parser->m_found_subtitle_pages;
2981 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2982 eDVBServicePMTHandler::program program;
2983 if (h.getProgramInfo(program))
2984 eDebug("getting program info failed.");
2987 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2988 it != program.subtitleStreams.end(); ++it)
2990 switch(it->subtitling_type)
2992 case 0x01: // ebu teletext subtitles
2994 int page_number = it->teletext_page_number & 0xFF;
2995 int magazine_number = it->teletext_magazine_number & 7;
2996 int hash = magazine_number << 8 | page_number;
2997 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2999 ePyObject tuple = PyTuple_New(5);
3000 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3001 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3002 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3003 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3004 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3005 PyList_Append(l, tuple);
3007 added_ttx_pages.insert(hash);
3012 case 0x20 ... 0x23: // dvb subtitles
3014 ePyObject tuple = PyTuple_New(5);
3015 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3016 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3017 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3018 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3019 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3020 PyList_Insert(l, 0, tuple);
3028 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3029 it != subs.end(); ++it)
3031 int page_number = it->teletext_page_number & 0xFF;
3032 int magazine_number = it->teletext_magazine_number & 7;
3033 int hash = magazine_number << 8 | page_number;
3034 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3036 ePyObject tuple = PyTuple_New(5);
3037 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3038 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3039 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3040 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3041 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3042 PyList_Append(l, tuple);
3050 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3052 if (m_subtitle_widget)
3054 int subtitledelay = 0;
3057 m_decoder->getPTS(0, pos);
3058 if (m_is_pvr || m_timeshift_enabled)
3060 eDebug("Subtitle in recording/timeshift");
3061 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3065 /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3066 subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3069 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3070 eDVBTeletextSubtitlePage tmppage = page;
3071 tmppage.m_have_pts = true;
3073 if (abs(tmppage.m_pts - pos) > 20*90000)
3074 tmppage.m_pts = pos; // fix abnormal pos diffs
3076 tmppage.m_pts += subtitledelay;
3077 m_subtitle_pages.push_back(tmppage);
3078 checkSubtitleTiming();
3082 void eDVBServicePlay::checkSubtitleTiming()
3084 eDebug("checkSubtitleTiming");
3085 if (!m_subtitle_widget)
3089 enum { TELETEXT, DVB } type;
3090 eDVBTeletextSubtitlePage page;
3091 eDVBSubtitlePage dvb_page;
3093 if (!m_subtitle_pages.empty())
3095 page = m_subtitle_pages.front();
3097 show_time = page.m_pts;
3099 else if (!m_dvb_subtitle_pages.empty())
3101 dvb_page = m_dvb_subtitle_pages.front();
3103 show_time = dvb_page.m_show_time;
3111 m_decoder->getPTS(0, pos);
3113 eDebug("%lld %lld", pos, show_time);
3114 int diff = show_time - pos;
3115 if (type == TELETEXT && !page.m_have_pts)
3117 eDebug("ttx subtitle page without pts... immediate show");
3122 eDebug("[late (%d ms)]", -diff / 90);
3125 if (abs(diff) > 1800000)
3127 eDebug("[invalid]... immediate show!");
3132 if (type == TELETEXT)
3134 eDebug("display teletext subtitle page %lld", show_time);
3135 m_subtitle_widget->setPage(page);
3136 m_subtitle_pages.pop_front();
3140 eDebug("display dvb subtitle Page %lld", show_time);
3141 m_subtitle_widget->setPage(dvb_page);
3142 m_dvb_subtitle_pages.pop_front();
3146 eDebug("start subtitle delay %d", diff / 90);
3147 m_subtitle_sync_timer->start(diff / 90, 1);
3153 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3155 if (m_subtitle_widget)
3159 m_decoder->getPTS(0, pos);
3160 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3161 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3163 eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3164 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3166 eDVBSubtitlePage tmppage;
3168 tmppage.m_show_time = pos + subtitledelay;
3169 m_dvb_subtitle_pages.push_back(tmppage);
3173 int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3174 if (subtitledelay != 0)
3176 eDVBSubtitlePage tmppage;
3178 tmppage.m_show_time += subtitledelay;
3179 m_dvb_subtitle_pages.push_back(tmppage);
3182 m_dvb_subtitle_pages.push_back(p);
3184 checkSubtitleTiming();
3188 int eDVBServicePlay::getAC3Delay()
3191 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3193 return m_decoder->getAC3Delay();
3198 int eDVBServicePlay::getPCMDelay()
3201 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3203 return m_decoder->getPCMDelay();
3208 void eDVBServicePlay::setAC3Delay(int delay)
3211 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3213 std::string config_delay;
3214 int config_delay_int = 0;
3215 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3216 config_delay_int = atoi(config_delay.c_str());
3217 m_decoder->setAC3Delay(delay + config_delay_int);
3221 void eDVBServicePlay::setPCMDelay(int delay)
3224 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3226 std::string config_delay;
3227 int config_delay_int = 0;
3228 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3229 config_delay_int = atoi(config_delay.c_str());
3231 config_delay_int = 0;
3232 m_decoder->setPCMDelay(delay + config_delay_int);
3236 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3238 switch(event.type) {
3239 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3240 m_event((iPlayableService*)this, evVideoSizeChanged);
3242 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3243 m_event((iPlayableService*)this, evVideoFramerateChanged);
3245 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3246 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3253 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3259 PyObject *eDVBServicePlay::getStreamingData()
3261 eDVBServicePMTHandler::program program;
3262 if (m_service_handler.getProgramInfo(program))
3267 ePyObject r = program.createPythonObject();
3268 ePtr<iDVBDemux> demux;
3269 if (!m_service_handler.getDataDemux(demux))
3272 if (!demux->getCADemuxID(demux_id))
3273 PutToDict(r, "demux", demux_id);
3280 DEFINE_REF(eDVBServicePlay)
3282 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3286 case iServiceInformation::sTransponderData:
3287 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3291 return iStaticServiceInformation::getInfoObject(ref, w);
3294 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");