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::cAPID);
1735 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1739 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1743 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1747 if (no_program_info) return -1; return program.pcrPid;
1748 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1749 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1750 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1751 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1752 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1753 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1754 case sProvider: if (!m_dvb_service) return -1; return -2;
1755 case sServiceref: return resIsString;
1756 case sDVBState: return m_tune_state;
1763 std::string eDVBServicePlay::getInfoString(int w)
1768 if (!m_dvb_service) return "";
1769 return m_dvb_service->m_provider_name;
1771 return m_reference.toString();
1775 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1779 case sLiveStreamDemuxId:
1782 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1792 return iServiceInformation::getInfoString(w);
1795 PyObject *eDVBServicePlay::getInfoObject(int w)
1800 return m_service_handler.getCaIds();
1802 return m_service_handler.getCaIds(true);
1803 case sTransponderData:
1804 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1807 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1808 return h.getHbbTVApplications();
1813 return iServiceInformation::getInfoObject(w);
1816 int eDVBServicePlay::getNumberOfTracks()
1818 eDVBServicePMTHandler::program program;
1819 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1820 if (h.getProgramInfo(program))
1822 return program.audioStreams.size();
1825 int eDVBServicePlay::getCurrentTrack()
1827 eDVBServicePMTHandler::program program;
1828 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1829 if (h.getProgramInfo(program))
1832 int max = program.audioStreams.size();
1835 for (i = 0; i < max; ++i)
1836 if (program.audioStreams[i].pid == m_current_audio_pid)
1842 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1844 int ret = selectAudioStream(i);
1846 if (m_decoder->set())
1852 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1854 eDVBServicePMTHandler::program program;
1855 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1857 if (h.getProgramInfo(program))
1860 if (i >= program.audioStreams.size())
1863 info.m_pid = program.audioStreams[i].pid;
1865 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1866 info.m_description = "MPEG";
1867 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1868 info.m_description = "Dolby Digital";
1869 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1870 info.m_description = "Dolby Digital+";
1871 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1872 info.m_description = "AAC";
1873 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1874 info.m_description = "AAC-HE";
1875 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1876 info.m_description = "DTS";
1877 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1878 info.m_description = "DTS-HD";
1880 info.m_description = "???";
1882 if (program.audioStreams[i].component_tag != -1)
1884 ePtr<eServiceEvent> evt;
1885 if (!m_event_handler.getEvent(evt, 0))
1887 ePtr<eComponentData> data;
1888 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1889 info.m_language = data->getText();
1893 if (info.m_language.empty())
1894 info.m_language = program.audioStreams[i].language_code;
1899 int eDVBServicePlay::selectAudioStream(int i)
1901 eDVBServicePMTHandler::program program;
1902 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1903 pts_t position = -1;
1905 if (h.getProgramInfo(program))
1908 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1916 stream = program.defaultAudioStream;
1918 int apid = -1, apidtype = -1;
1920 if (((unsigned int)stream) < program.audioStreams.size())
1922 apid = program.audioStreams[stream].pid;
1923 apidtype = program.audioStreams[stream].type;
1926 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1927 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1929 m_current_audio_pid = apid;
1931 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1933 eDebug("set audio pid failed");
1938 eDebug("seekTo ret %d", seekTo(position));
1942 /* 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 */
1943 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1945 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1947 rdsPid = program.audioStreams[stream].rdsPid;
1948 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1951 ePtr<iDVBDemux> data_demux;
1952 if (!h.getDataDemux(data_demux))
1954 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1955 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1956 m_rds_decoder->start(rdsPid);
1961 /* store new pid as default only when:
1962 a.) we have an entry in the service db for the current service,
1963 b.) we are not playing back something,
1964 c.) we are not selecting the default entry. (we wouldn't change
1965 anything in the best case, or destroy the default setting in
1966 case the real default is not yet available.)
1968 if (m_dvb_service && ((i != -1)
1969 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1971 if (apidtype == eDVBAudio::aMPEG)
1973 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1974 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1976 else if (apidtype == eDVBAudio::aAC3)
1978 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1979 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1983 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1984 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1988 h.resetCachedProgram();
1993 int eDVBServicePlay::getCurrentChannel()
1995 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1998 RESULT eDVBServicePlay::selectChannel(int i)
2000 if (i < LEFT || i > RIGHT || i == STEREO)
2003 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2005 m_decoder->setAudioChannel(i);
2009 std::string eDVBServicePlay::getText(int x)
2015 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2017 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2022 void eDVBServicePlay::rdsDecoderEvent(int what)
2026 case eDVBRdsDecoder::RadioTextChanged:
2027 m_event((iPlayableService*)this, evUpdatedRadioText);
2029 case eDVBRdsDecoder::RtpTextChanged:
2030 m_event((iPlayableService*)this, evUpdatedRtpText);
2032 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2033 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2035 case eDVBRdsDecoder::RecvRassSlidePic:
2036 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2041 void eDVBServicePlay::showRassSlidePicture()
2047 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2048 if (rass_slide_pic.length())
2049 m_decoder->showSinglePic(rass_slide_pic.c_str());
2051 eDebug("empty filename for rass slide picture received!!");
2054 eDebug("no MPEG Decoder to show iframes avail");
2057 eDebug("showRassSlidePicture called.. but not decoder");
2060 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2066 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2067 if (rass_interactive_pic.length())
2068 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2070 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2073 eDebug("no MPEG Decoder to show iframes avail");
2076 eDebug("showRassInteractivePic called.. but not decoder");
2079 ePyObject eDVBServicePlay::getRassInteractiveMask()
2082 return m_rds_decoder->getRassPictureMask();
2086 int eDVBServiceBase::getFrontendInfo(int w)
2088 eUsePtr<iDVBChannel> channel;
2089 if(m_service_handler.getChannel(channel))
2091 ePtr<iDVBFrontend> fe;
2092 if(channel->getFrontend(fe))
2094 return fe->readFrontendData(w);
2097 PyObject *eDVBServiceBase::getFrontendData()
2099 ePyObject ret = PyDict_New();
2102 eUsePtr<iDVBChannel> channel;
2103 if(!m_service_handler.getChannel(channel))
2105 ePtr<iDVBFrontend> fe;
2106 if(!channel->getFrontend(fe))
2107 fe->getFrontendData(ret);
2115 PyObject *eDVBServiceBase::getFrontendStatus()
2117 ePyObject ret = PyDict_New();
2120 eUsePtr<iDVBChannel> channel;
2121 if(!m_service_handler.getChannel(channel))
2123 ePtr<iDVBFrontend> fe;
2124 if(!channel->getFrontend(fe))
2125 fe->getFrontendStatus(ret);
2133 PyObject *eDVBServiceBase::getTransponderData(bool original)
2135 ePyObject ret = PyDict_New();
2138 eUsePtr<iDVBChannel> channel;
2139 if(!m_service_handler.getChannel(channel))
2141 ePtr<iDVBFrontend> fe;
2142 if(!channel->getFrontend(fe))
2143 fe->getTransponderData(ret, original);
2151 PyObject *eDVBServiceBase::getAll(bool original)
2153 ePyObject ret = getTransponderData(original);
2156 eUsePtr<iDVBChannel> channel;
2157 if(!m_service_handler.getChannel(channel))
2159 ePtr<iDVBFrontend> fe;
2160 if(!channel->getFrontend(fe))
2162 fe->getFrontendData(ret);
2163 fe->getFrontendStatus(ret);
2170 int eDVBServicePlay::getNumberOfSubservices()
2172 ePtr<eServiceEvent> evt;
2173 if (!m_event_handler.getEvent(evt, 0))
2174 return evt->getNumOfLinkageServices();
2178 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2180 ePtr<eServiceEvent> evt;
2181 if (!m_event_handler.getEvent(evt, 0))
2183 if (!evt->getLinkageService(sub, m_reference, n))
2186 sub.type=eServiceReference::idInvalid;
2190 RESULT eDVBServicePlay::startTimeshift()
2192 ePtr<iDVBDemux> demux;
2194 eDebug("Start timeshift!");
2196 if (m_timeshift_enabled)
2199 /* start recording with the data demux. */
2200 if (m_service_handler.getDataDemux(demux))
2203 demux->createTSRecorder(m_record);
2208 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2209 eDebug("could not query ts path");
2212 tspath.append("/timeshift.XXXXXX");
2214 templ = new char[tspath.length() + 1];
2215 strcpy(templ, tspath.c_str());
2217 m_timeshift_fd = mkstemp(templ);
2218 m_timeshift_file = std::string(templ);
2220 eDebug("recording to %s", templ);
2224 if (m_timeshift_fd < 0)
2230 m_record->setTargetFD(m_timeshift_fd);
2231 m_record->setTargetFilename(m_timeshift_file.c_str());
2232 m_record->enableAccessPoints(false);
2234 m_timeshift_enabled = 1;
2236 updateTimeshiftPids();
2242 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2244 if (!m_timeshift_enabled)
2250 m_timeshift_enabled = 0;
2255 close(m_timeshift_fd);
2256 eDebug("remove timeshift file");
2257 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2260 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2261 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2267 int eDVBServicePlay::isTimeshiftActive()
2269 return m_timeshift_enabled && m_timeshift_active;
2272 RESULT eDVBServicePlay::activateTimeshift()
2274 if (!m_timeshift_enabled)
2277 if (!m_timeshift_active)
2279 switchToTimeshift();
2286 PyObject *eDVBServicePlay::getCutList()
2288 ePyObject list = PyList_New(0);
2290 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2292 ePyObject tuple = PyTuple_New(2);
2293 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2294 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2295 PyList_Append(list, tuple);
2302 void eDVBServicePlay::setCutList(ePyObject list)
2304 if (!PyList_Check(list))
2306 int size = PyList_Size(list);
2309 m_cue_entries.clear();
2311 for (i=0; i<size; ++i)
2313 ePyObject tuple = PyList_GET_ITEM(list, i);
2314 if (!PyTuple_Check(tuple))
2316 eDebug("non-tuple in cutlist");
2319 if (PyTuple_Size(tuple) != 2)
2321 eDebug("cutlist entries need to be a 2-tuple");
2324 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2325 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2327 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2330 pts_t pts = PyLong_AsLongLong(ppts);
2331 int type = PyInt_AsLong(ptype);
2332 m_cue_entries.insert(cueEntry(pts, type));
2333 eDebug("adding %08llx, %d", pts, type);
2335 m_cuesheet_changed = 1;
2337 cutlistToCuesheet();
2338 m_event((iPlayableService*)this, evCuesheetChanged);
2341 void eDVBServicePlay::setCutListEnable(int enable)
2343 m_cutlist_enabled = enable;
2344 cutlistToCuesheet();
2347 void eDVBServicePlay::updateTimeshiftPids()
2352 eDVBServicePMTHandler::program program;
2353 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2355 if (h.getProgramInfo(program))
2359 int timing_pid = -1;
2360 int timing_pid_type = -1;
2361 std::set<int> pids_to_record;
2362 pids_to_record.insert(0); // PAT
2363 if (program.pmtPid != -1)
2364 pids_to_record.insert(program.pmtPid); // PMT
2366 if (program.textPid != -1)
2367 pids_to_record.insert(program.textPid); // Videotext
2369 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2370 i(program.videoStreams.begin());
2371 i != program.videoStreams.end(); ++i)
2373 pids_to_record.insert(i->pid);
2375 if (timing_pid == -1)
2377 timing_pid = i->pid;
2378 timing_pid_type = i->type;
2382 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2383 i(program.audioStreams.begin());
2384 i != program.audioStreams.end(); ++i)
2386 pids_to_record.insert(i->pid);
2388 if (timing_pid == -1)
2390 timing_pid = i->pid;
2391 timing_pid_type = -1;
2395 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2396 i(program.subtitleStreams.begin());
2397 i != program.subtitleStreams.end(); ++i)
2398 pids_to_record.insert(i->pid);
2400 std::set<int> new_pids, obsolete_pids;
2402 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2403 m_pids_active.begin(), m_pids_active.end(),
2404 std::inserter(new_pids, new_pids.begin()));
2406 std::set_difference(
2407 m_pids_active.begin(), m_pids_active.end(),
2408 pids_to_record.begin(), pids_to_record.end(),
2409 std::inserter(new_pids, new_pids.begin())
2412 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2413 m_record->addPID(*i);
2415 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2416 m_record->removePID(*i);
2418 if (timing_pid != -1)
2419 m_record->setTimingPID(timing_pid, timing_pid_type);
2423 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2425 m_timeshift_file_next = f;
2429 void eDVBServicePlay::switchToLive()
2431 if (!m_timeshift_active)
2434 eDebug("SwitchToLive");
2438 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2440 /* free the timeshift service handler, we need the resources */
2441 m_service_handler_timeshift.free();
2443 updateDecoder(true);
2446 void eDVBServicePlay::resetTimeshift(int start)
2451 m_teletext_parser = 0;
2453 m_subtitle_parser = 0;
2454 m_new_subtitle_page_connection = 0;
2455 m_new_dvb_subtitle_page_connection = 0;
2456 m_rds_decoder_event_connection = 0;
2457 m_video_event_connection = 0;
2458 m_timeshift_changed = 1;
2459 m_timeshift_file_next.clear();
2463 m_cue = new eCueSheet();
2464 m_timeshift_active = 1;
2467 m_timeshift_active = 0;
2470 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2474 eHttpStream *f = new eHttpStream();
2475 f->open(ref.path.c_str());
2476 return ePtr<iTsSource>(f);
2480 eRawFile *f = new eRawFile();
2481 f->open(ref.path.c_str());
2482 return ePtr<iTsSource>(f);
2486 void eDVBServicePlay::switchToTimeshift()
2488 if (m_timeshift_active)
2493 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2494 r.path = m_timeshift_file;
2496 m_cue->seekTo(0, -1000);
2498 ePtr<iTsSource> source = createTsSource(r);
2499 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 */
2501 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2503 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2506 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2508 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2509 bool mustPlay = false;
2511 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2513 eDVBServicePMTHandler::program program;
2514 if (h.getProgramInfo(program))
2515 eDebug("getting program info failed.");
2518 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2519 if (!program.videoStreams.empty())
2521 eDebugNoNewLine(" (");
2522 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2523 i(program.videoStreams.begin());
2524 i != program.videoStreams.end(); ++i)
2531 if (i != program.videoStreams.begin())
2532 eDebugNoNewLine(", ");
2533 eDebugNoNewLine("%04x", i->pid);
2535 eDebugNoNewLine(")");
2537 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2538 if (!program.audioStreams.empty())
2540 eDebugNoNewLine(" (");
2541 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2542 i(program.audioStreams.begin());
2543 i != program.audioStreams.end(); ++i)
2545 if (i != program.audioStreams.begin())
2546 eDebugNoNewLine(", ");
2547 eDebugNoNewLine("%04x", i->pid);
2549 eDebugNoNewLine(")");
2551 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2552 pcrpid = program.pcrPid;
2553 eDebug(", and the text pid is %04x", program.textPid);
2554 tpid = program.textPid;
2559 h.getDecodeDemux(m_decode_demux);
2562 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2564 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2567 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2568 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2569 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2570 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2571 if (m_timeshift_changed)
2573 ePyObject subs = getCachedSubtitle();
2574 if (subs != Py_None)
2576 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2577 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2578 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2579 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2580 if (type == 0) // dvb
2581 m_subtitle_parser->start(pid, comp_page, anc_page);
2582 else if (type == 1) // ttx
2583 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2590 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2594 m_timeshift_changed = 0;
2598 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2601 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2602 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2603 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2607 eServiceReferenceDVB ref;
2608 m_service_handler.getServiceReference(ref);
2609 eServiceReferenceDVB parent = ref.getParentServiceReference();
2614 ePtr<eDVBResourceManager> res_mgr;
2615 if (!eDVBResourceManager::getInstance(res_mgr))
2617 ePtr<iDVBChannelList> db;
2618 if (!res_mgr->getChannelList(db))
2620 ePtr<eDVBService> origService;
2621 if (!db->getService(parent, origService))
2623 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2624 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2631 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2632 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2634 m_decoder->setVideoPID(vpid, vpidtype);
2635 m_current_video_pid_type = vpidtype;
2636 selectAudioStream();
2638 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2639 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2640 m_decoder->setSyncPCR(pcrpid);
2642 m_decoder->setSyncPCR(-1);
2646 m_decoder->setTextPID(tpid);
2647 m_teletext_parser->start(program.textPid);
2650 if (vpid > 0 && vpid < 0x2000)
2654 std::string radio_pic;
2655 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2656 m_decoder->setRadioPic(radio_pic);
2664 m_decoder->setAudioChannel(achannel);
2666 /* don't worry about non-existing services, nor pvr services */
2669 /* (audio pid will be set in selectAudioTrack */
2670 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2671 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2672 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2673 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2675 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2676 sendSeekableStateChanged = true;
2678 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2680 if (sendSeekableStateChanged)
2681 m_event((iPlayableService*)this, evSeekableStatusChanged);
2684 void eDVBServicePlay::loadCuesheet()
2686 std::string filename = m_reference.path + ".cuts";
2688 m_cue_entries.clear();
2690 FILE *f = fopen(filename.c_str(), "rb");
2694 eDebug("loading cuts..");
2697 unsigned long long where;
2700 if (!fread(&where, sizeof(where), 1, f))
2702 if (!fread(&what, sizeof(what), 1, f))
2705 #if BYTE_ORDER == LITTLE_ENDIAN
2706 where = bswap_64(where);
2713 m_cue_entries.insert(cueEntry(where, what));
2716 eDebug("%zd entries", m_cue_entries.size());
2718 eDebug("cutfile not found!");
2720 m_cuesheet_changed = 0;
2721 cutlistToCuesheet();
2722 m_event((iPlayableService*)this, evCuesheetChanged);
2725 void eDVBServicePlay::saveCuesheet()
2727 std::string filename = m_reference.path + ".cuts";
2729 FILE *f = fopen(filename.c_str(), "wb");
2733 unsigned long long where;
2736 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2738 #if BYTE_ORDER == BIG_ENDIAN
2741 where = bswap_64(i->where);
2743 what = htonl(i->what);
2744 fwrite(&where, sizeof(where), 1, f);
2745 fwrite(&what, sizeof(what), 1, f);
2751 m_cuesheet_changed = 0;
2754 void eDVBServicePlay::cutlistToCuesheet()
2758 eDebug("no cue sheet");
2763 if (!m_cutlist_enabled)
2765 m_cue->commitSpans();
2766 eDebug("cutlists were disabled");
2770 pts_t in = 0, out = 0, length = 0;
2774 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2776 int have_any_span = 0;
2780 if (i == m_cue_entries.end())
2782 if (!have_any_span && !in)
2786 if (i->what == 0) /* in */
2790 } else if (i->what == 1) /* out */
2792 else /* mark (2) or last play position (3) */
2811 m_cue->addSourceSpan(in, out);
2817 if (i == m_cue_entries.end())
2820 m_cue->commitSpans();
2823 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2825 if (m_subtitle_widget)
2826 disableSubtitles(parent);
2829 int tuplesize = PyTuple_Size(tuple);
2832 if (!PyTuple_Check(tuple))
2838 entry = PyTuple_GET_ITEM(tuple, 0);
2840 if (!PyInt_Check(entry))
2843 type = PyInt_AsLong(entry);
2845 if (type == 1) // teletext subtitles
2847 int page, magazine, pid;
2851 if (!m_teletext_parser)
2853 eDebug("enable teletext subtitles.. no parser !!!");
2857 entry = PyTuple_GET_ITEM(tuple, 1);
2858 if (!PyInt_Check(entry))
2860 pid = PyInt_AsLong(entry);
2862 entry = PyTuple_GET_ITEM(tuple, 2);
2863 if (!PyInt_Check(entry))
2865 page = PyInt_AsLong(entry);
2867 entry = PyTuple_GET_ITEM(tuple, 3);
2868 if (!PyInt_Check(entry))
2870 magazine = PyInt_AsLong(entry);
2872 m_subtitle_widget = new eSubtitleWidget(parent);
2873 m_subtitle_widget->resize(parent->size()); /* full size */
2874 m_teletext_parser->setPageAndMagazine(page, magazine);
2876 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2880 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2881 if (!m_subtitle_parser)
2883 eDebug("enable dvb subtitles.. no parser !!!");
2889 entry = PyTuple_GET_ITEM(tuple, 1);
2890 if (!PyInt_Check(entry))
2892 pid = PyInt_AsLong(entry);
2894 entry = PyTuple_GET_ITEM(tuple, 2);
2895 if (!PyInt_Check(entry))
2897 composition_page_id = PyInt_AsLong(entry);
2899 entry = PyTuple_GET_ITEM(tuple, 3);
2900 if (!PyInt_Check(entry))
2902 ancillary_page_id = PyInt_AsLong(entry);
2904 m_subtitle_widget = new eSubtitleWidget(parent);
2905 m_subtitle_widget->resize(parent->size()); /* full size */
2906 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2908 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2914 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2915 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2916 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2920 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2922 delete m_subtitle_widget;
2923 m_subtitle_widget = 0;
2924 if (m_subtitle_parser)
2926 m_subtitle_parser->stop();
2927 m_dvb_subtitle_pages.clear();
2929 if (m_teletext_parser)
2931 m_teletext_parser->setPageAndMagazine(-1, -1);
2932 m_subtitle_pages.clear();
2935 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2939 PyObject *eDVBServicePlay::getCachedSubtitle()
2943 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2946 unsigned int data = (unsigned int)tmp;
2947 int pid = (data&0xFFFF0000)>>16;
2948 ePyObject tuple = PyTuple_New(4);
2949 eDVBServicePMTHandler::program program;
2950 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2951 if (!h.getProgramInfo(program))
2953 if (program.textPid==pid) // teletext
2954 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2956 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2957 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2958 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2959 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2967 PyObject *eDVBServicePlay::getSubtitleList()
2969 if (!m_teletext_parser)
2972 ePyObject l = PyList_New(0);
2973 std::set<int> added_ttx_pages;
2975 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2976 m_teletext_parser->m_found_subtitle_pages;
2978 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2979 eDVBServicePMTHandler::program program;
2980 if (h.getProgramInfo(program))
2981 eDebug("getting program info failed.");
2984 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2985 it != program.subtitleStreams.end(); ++it)
2987 switch(it->subtitling_type)
2989 case 0x01: // ebu teletext subtitles
2991 int page_number = it->teletext_page_number & 0xFF;
2992 int magazine_number = it->teletext_magazine_number & 7;
2993 int hash = magazine_number << 8 | page_number;
2994 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2996 ePyObject tuple = PyTuple_New(5);
2997 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2998 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2999 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3000 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3001 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3002 PyList_Append(l, tuple);
3004 added_ttx_pages.insert(hash);
3009 case 0x20 ... 0x23: // dvb subtitles
3011 ePyObject tuple = PyTuple_New(5);
3012 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3013 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3014 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3015 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3016 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3017 PyList_Insert(l, 0, tuple);
3025 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3026 it != subs.end(); ++it)
3028 int page_number = it->teletext_page_number & 0xFF;
3029 int magazine_number = it->teletext_magazine_number & 7;
3030 int hash = magazine_number << 8 | page_number;
3031 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3033 ePyObject tuple = PyTuple_New(5);
3034 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3035 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3036 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3037 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3038 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
3039 PyList_Append(l, tuple);
3047 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3049 if (m_subtitle_widget)
3053 m_decoder->getPTS(0, pos);
3054 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3055 m_subtitle_pages.push_back(page);
3056 checkSubtitleTiming();
3060 void eDVBServicePlay::checkSubtitleTiming()
3062 eDebug("checkSubtitleTiming");
3063 if (!m_subtitle_widget)
3067 enum { TELETEXT, DVB } type;
3068 eDVBTeletextSubtitlePage page;
3069 eDVBSubtitlePage dvb_page;
3071 if (!m_subtitle_pages.empty())
3073 page = m_subtitle_pages.front();
3075 show_time = page.m_pts;
3077 else if (!m_dvb_subtitle_pages.empty())
3079 dvb_page = m_dvb_subtitle_pages.front();
3081 show_time = dvb_page.m_show_time;
3089 m_decoder->getPTS(0, pos);
3091 eDebug("%lld %lld", pos, show_time);
3092 int diff = show_time - pos;
3093 if (type == TELETEXT && !page.m_have_pts)
3095 eDebug("ttx subtitle page without pts... immediate show");
3100 eDebug("[late (%d ms)]", -diff / 90);
3103 if (abs(diff) > 1800000)
3105 eDebug("[invalid]... immediate show!");
3110 if (type == TELETEXT)
3112 eDebug("display teletext subtitle page %lld", show_time);
3113 m_subtitle_widget->setPage(page);
3114 m_subtitle_pages.pop_front();
3118 eDebug("display dvb subtitle Page %lld", show_time);
3119 m_subtitle_widget->setPage(dvb_page);
3120 m_dvb_subtitle_pages.pop_front();
3124 eDebug("start subtitle delay %d", diff / 90);
3125 m_subtitle_sync_timer->start(diff / 90, 1);
3131 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3133 if (m_subtitle_widget)
3137 m_decoder->getPTS(0, pos);
3138 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3139 m_dvb_subtitle_pages.push_back(p);
3140 checkSubtitleTiming();
3144 int eDVBServicePlay::getAC3Delay()
3147 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3149 return m_decoder->getAC3Delay();
3154 int eDVBServicePlay::getPCMDelay()
3157 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3159 return m_decoder->getPCMDelay();
3164 void eDVBServicePlay::setAC3Delay(int delay)
3167 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3169 std::string config_delay;
3170 int config_delay_int = 0;
3171 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3172 config_delay_int = atoi(config_delay.c_str());
3173 m_decoder->setAC3Delay(delay + config_delay_int);
3177 void eDVBServicePlay::setPCMDelay(int delay)
3180 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3182 std::string config_delay;
3183 int config_delay_int = 0;
3184 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3185 config_delay_int = atoi(config_delay.c_str());
3187 config_delay_int = 0;
3188 m_decoder->setPCMDelay(delay + config_delay_int);
3192 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3194 switch(event.type) {
3195 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3196 m_event((iPlayableService*)this, evVideoSizeChanged);
3198 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3199 m_event((iPlayableService*)this, evVideoFramerateChanged);
3201 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3202 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3209 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3215 PyObject *eDVBServicePlay::getStreamingData()
3217 eDVBServicePMTHandler::program program;
3218 if (m_service_handler.getProgramInfo(program))
3223 ePyObject r = program.createPythonObject();
3224 ePtr<iDVBDemux> demux;
3225 if (!m_service_handler.getDataDemux(demux))
3228 if (!demux->getCADemuxID(demux_id))
3229 PutToDict(r, "demux", demux_id);
3236 DEFINE_REF(eDVBServicePlay)
3238 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3242 case iServiceInformation::sTransponderData:
3243 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3247 return iStaticServiceInformation::getInfoObject(ref, w);
3250 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");