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;
93 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
94 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
95 return res_mgr->canAllocateChannel(chid, chid_ignore);
100 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
101 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
102 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
103 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
105 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
107 if (r.type == eServiceReference::idDVB)
109 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
112 case iServiceInformation::sTransponderData:
114 ePtr<eDVBResourceManager> res;
115 if (!eDVBResourceManager::getInstance(res))
117 ePtr<iDVBChannelList> db;
118 if (!res->getChannelList(db))
121 ref.getChannelID(chid);
122 ePtr<iDVBFrontendParameters> feparm;
123 if (!db->getChannelFrontendData(chid, feparm))
126 if (!feparm->getSystem(system))
128 ePyObject dict = PyDict_New();
131 case iDVBFrontend::feSatellite:
133 eDVBFrontendParametersSatellite s;
135 PutSatelliteDataToDict(dict, s);
138 case iDVBFrontend::feTerrestrial:
140 eDVBFrontendParametersTerrestrial t;
142 PutTerrestrialDataToDict(dict, t);
145 case iDVBFrontend::feCable:
147 eDVBFrontendParametersCable c;
149 PutCableDataToDict(dict, c);
153 eDebug("unknown frontend type %d", system);
168 DEFINE_REF(eStaticServiceDVBBouquetInformation);
170 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
172 ePtr<iDVBChannelList> db;
173 ePtr<eDVBResourceManager> res;
176 if ((err = eDVBResourceManager::getInstance(res)) != 0)
178 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
181 if ((err = res->getChannelList(db)) != 0)
183 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
188 if ((err = db->getBouquet(ref, bouquet)) != 0)
190 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
194 if ( bouquet && bouquet->m_bouquet_name.length() )
196 name = bouquet->m_bouquet_name;
203 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
205 if (ref.flags & eServiceReference::isGroup)
207 ePtr<iDVBChannelList> db;
208 ePtr<eDVBResourceManager> res;
210 if (eDVBResourceManager::getInstance(res))
212 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
216 if (res->getChannelList(db))
218 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
223 if (db->getBouquet(ref, bouquet))
225 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
229 int prio_order = eDVBFrontend::getTypePriorityOrder();
231 eDVBChannelID chid, chid_ignore;
232 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
233 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
235 static unsigned char prio_map[6][3] = {
236 { 3, 2, 1 }, // -S -C -T
237 { 3, 1, 2 }, // -S -T -C
238 { 2, 3, 1 }, // -C -S -T
239 { 1, 3, 2 }, // -C -T -S
240 { 1, 2, 3 }, // -T -C -S
241 { 2, 1, 3 } // -T -S -C
243 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
244 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
249 case 30000: // cached DVB-T channel
250 case 1: // DVB-T frontend
251 tmp = prio_map[prio_order][2];
253 case 40000: // cached DVB-C channel
255 tmp = prio_map[prio_order][1];
258 tmp = prio_map[prio_order][0];
263 m_playable_service = *it;
270 m_playable_service = eServiceReference();
274 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
279 #include <lib/dvb/epgcache.h>
281 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
283 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
286 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
288 DECLARE_REF(eStaticServiceDVBPVRInformation);
289 eServiceReference m_ref;
290 eDVBMetaParser m_parser;
292 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
293 RESULT getName(const eServiceReference &ref, std::string &name);
294 int getLength(const eServiceReference &ref);
295 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
296 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
297 int getInfo(const eServiceReference &ref, int w);
298 std::string getInfoString(const eServiceReference &ref,int w);
299 PyObject *getInfoObject(const eServiceReference &r, int what);
302 DEFINE_REF(eStaticServiceDVBPVRInformation);
304 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
307 m_parser.parseFile(ref.path);
310 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
312 ASSERT(ref == m_ref);
313 if (!ref.name.empty())
315 else if (!m_parser.m_name.empty())
316 name = m_parser.m_name;
320 size_t n = name.rfind('/');
321 if (n != std::string::npos)
322 name = name.substr(n + 1);
327 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
329 ASSERT(ref == m_ref);
334 stat(ref.path.c_str(), &s);
336 if (tstools.openFile(ref.path.c_str(), 1))
339 /* check if cached data is still valid */
340 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
341 return m_parser.m_length / 90000;
343 /* open again, this time with stream info */
344 if (tstools.openFile(ref.path.c_str()))
347 /* otherwise, re-calc length and update meta file */
349 if (tstools.calcLen(len))
352 m_parser.m_length = len;
353 m_parser.m_filesize = s.st_size;
354 m_parser.updateMeta(ref.path);
355 return m_parser.m_length / 90000;
358 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
362 case iServiceInformation::sDescription:
363 return iServiceInformation::resIsString;
364 case iServiceInformation::sServiceref:
365 return iServiceInformation::resIsString;
366 case iServiceInformation::sFileSize:
367 return m_parser.m_filesize;
368 case iServiceInformation::sTimeCreate:
369 if (m_parser.m_time_create)
370 return m_parser.m_time_create;
372 return iServiceInformation::resNA;
374 return iServiceInformation::resNA;
378 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
382 case iServiceInformation::sDescription:
383 return m_parser.m_description;
384 case iServiceInformation::sServiceref:
385 return m_parser.m_ref.toString();
386 case iServiceInformation::sTags:
387 return m_parser.m_tags;
393 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
397 case iServiceInformation::sFileSize:
398 return PyLong_FromLongLong(m_parser.m_filesize);
404 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
406 if (!ref.path.empty())
408 if (ref.path.substr(0, 7) == "http://")
410 eServiceReference equivalentref(ref);
411 /* this might be a scrambled stream (id + 0x100), force equivalent dvb type */
412 equivalentref.type = eServiceFactoryDVB::id;
413 equivalentref.path.clear();
414 return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
418 ePtr<eServiceEvent> event = new eServiceEvent;
419 std::string filename = ref.path;
420 filename.erase(filename.length()-2, 2);
422 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
433 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
435 DECLARE_REF(eDVBPVRServiceOfflineOperations);
436 eServiceReferenceDVB m_ref;
438 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
440 RESULT deleteFromDisk(int simulate);
441 RESULT getListOfFilenames(std::list<std::string> &);
445 DEFINE_REF(eDVBPVRServiceOfflineOperations);
447 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
451 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
457 std::list<std::string> res;
458 if (getListOfFilenames(res))
461 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
463 eDebug("FATAL !! can't get background file eraser");
465 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
467 eDebug("Removing %s...", i->c_str());
469 eraser->erase(i->c_str());
471 ::unlink(i->c_str());
478 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
481 res.push_back(m_ref.path);
483 // handling for old splitted recordings (enigma 1)
488 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
490 if (stat(buf, &s) < 0)
495 res.push_back(m_ref.path + ".meta");
496 res.push_back(m_ref.path + ".ap");
497 res.push_back(m_ref.path + ".sc");
498 res.push_back(m_ref.path + ".cuts");
499 std::string tmp = m_ref.path;
500 tmp.erase(m_ref.path.length()-3);
501 res.push_back(tmp + ".eit");
505 RESULT eDVBPVRServiceOfflineOperations::reindex()
507 const char *filename = m_ref.path.c_str();
508 eDebug("reindexing %s...", filename);
510 eMPEGStreamInformation info;
511 eMPEGStreamParserTS parser(info);
513 info.startSave(filename);
517 int err = f.open(m_ref.path.c_str(), 0);
522 off_t length = f.length();
523 unsigned char buffer[188*256*4];
526 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
527 int r = f.read(offset, buffer, sizeof(buffer));
533 parser.parseData(offset, buffer, r);
542 DEFINE_REF(eServiceFactoryDVB)
544 eServiceFactoryDVB::eServiceFactoryDVB()
546 ePtr<eServiceCenter> sc;
548 eServiceCenter::getPrivInstance(sc);
551 std::list<std::string> extensions;
552 extensions.push_back("ts");
553 extensions.push_back("trp");
554 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
557 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
558 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
561 eServiceFactoryDVB::~eServiceFactoryDVB()
563 ePtr<eServiceCenter> sc;
565 eServiceCenter::getPrivInstance(sc);
567 sc->removeServiceFactory(eServiceFactoryDVB::id);
570 DEFINE_REF(eDVBServiceList);
572 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
576 eDVBServiceList::~eDVBServiceList()
580 RESULT eDVBServiceList::startQuery()
582 ePtr<iDVBChannelList> db;
583 ePtr<eDVBResourceManager> res;
586 if ((err = eDVBResourceManager::getInstance(res)) != 0)
588 eDebug("no resource manager");
591 if ((err = res->getChannelList(db)) != 0)
593 eDebug("no channel list");
597 ePtr<eDVBChannelQuery> q;
599 if (!m_parent.path.empty())
601 eDVBChannelQuery::compile(q, m_parent.path);
604 eDebug("compile query failed");
609 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
611 eDebug("startQuery failed");
618 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
620 eServiceReferenceDVB ref;
625 while (!m_query->getNextResult(ref))
629 list.sort(iListableServiceCompare(this));
634 // The first argument of this function is a format string to specify the order and
635 // the content of the returned list
636 // useable format options are
637 // R = Service Reference (as swig object .. this is very slow)
638 // S = Service Reference (as python string object .. same as ref.toString())
639 // C = Service Reference (as python string object .. same as ref.toCompareString())
640 // N = Service Name (as python string object)
641 // n = Short Service Name (short name brakets used) (as python string object)
642 // when exactly one return value per service is selected in the format string,
643 // then each value is directly a list entry
644 // when more than one value is returned per service, then the list is a list of
646 // unknown format string chars are returned as python None values !
647 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
650 std::list<eServiceReference> tmplist;
653 if (!format || !(retcount=strlen(format)))
654 format = "R"; // just return service reference swig object ...
656 if (!getContent(tmplist, sorted))
658 int services=tmplist.size();
659 ePtr<iStaticServiceInformation> sptr;
660 eServiceCenterPtr service_center;
662 if (strchr(format, 'N') || strchr(format, 'n'))
663 eServiceCenter::getPrivInstance(service_center);
665 ret = PyList_New(services);
666 std::list<eServiceReference>::iterator it(tmplist.begin());
668 for (int cnt=0; cnt < services; ++cnt)
670 eServiceReference &ref=*it++;
671 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
672 for (int i=0; i < retcount; ++i)
677 case 'R': // service reference (swig)object
678 tmp = NEW_eServiceReference(ref);
680 case 'C': // service reference compare string
681 tmp = PyString_FromString(ref.toCompareString().c_str());
683 case 'S': // service reference string
684 tmp = PyString_FromString(ref.toString().c_str());
686 case 'N': // service name
689 service_center->info(ref, sptr);
693 sptr->getName(ref, name);
695 // filter short name brakets
697 while((pos = name.find("\xc2\x86")) != std::string::npos)
699 while((pos = name.find("\xc2\x87")) != std::string::npos)
703 tmp = PyString_FromString(name.c_str());
707 tmp = PyString_FromString("<n/a>");
709 case 'n': // short service name
712 service_center->info(ref, sptr);
716 sptr->getName(ref, name);
717 name = buildShortName(name);
719 tmp = PyString_FromString(name.c_str());
723 tmp = PyString_FromString("<n/a>");
736 PyTuple_SET_ITEM(tuple, i, tmp);
738 PyList_SET_ITEM(ret, cnt, tmp);
742 PyList_SET_ITEM(ret, cnt, tuple);
745 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
748 RESULT eDVBServiceList::getNext(eServiceReference &ref)
753 return m_query->getNextResult((eServiceReferenceDVB&)ref);
756 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
758 if (m_parent.flags & eServiceReference::canDescent) // bouquet
760 ePtr<iDVBChannelList> db;
761 ePtr<eDVBResourceManager> resm;
763 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
766 if (db->getBouquet(m_parent, m_bouquet) != 0)
777 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
781 return m_bouquet->addService(ref, before);
784 RESULT eDVBServiceList::removeService(eServiceReference &ref)
788 return m_bouquet->removeService(ref);
791 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
795 return m_bouquet->moveService(ref, pos);
798 RESULT eDVBServiceList::flushChanges()
802 return m_bouquet->flushChanges();
805 RESULT eDVBServiceList::setListName(const std::string &name)
809 return m_bouquet->setListName(name);
812 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
814 ePtr<eDVBService> service;
815 int r = lookupService(service, ref);
818 // check resources...
819 ptr = new eDVBServicePlay(ref, service);
823 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
825 if (ref.path.empty())
827 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
831 bool isstream = ref.path.substr(0, 7) == "http://";
834 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref, isstream);
842 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
844 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
845 if (list->startQuery())
855 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
857 /* is a listable service? */
858 if (ref.flags & eServiceReference::canDescent) // bouquet
860 if ( !ref.name.empty() ) // satellites or providers list
861 ptr = m_StaticServiceDVBInfo;
862 else // a dvb bouquet
863 ptr = m_StaticServiceDVBBouquetInfo;
865 else if (!ref.path.empty()) /* do we have a PVR service? */
866 ptr = new eStaticServiceDVBPVRInformation(ref);
867 else // normal dvb service
869 ePtr<eDVBService> service;
870 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
871 ptr = m_StaticServiceDVBInfo;
873 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
879 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
881 if (ref.path.empty())
887 ptr = new eDVBPVRServiceOfflineOperations(ref);
892 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
894 if (!ref.path.empty()) // playback
896 eDVBMetaParser parser;
897 int ret=parser.parseFile(ref.path);
898 service = new eDVBService;
900 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
904 // TODO: handle the listing itself
905 // if (ref.... == -1) .. return "... bouquets ...";
906 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
908 ePtr<iDVBChannelList> db;
909 ePtr<eDVBResourceManager> res;
912 if ((err = eDVBResourceManager::getInstance(res)) != 0)
914 eDebug("no resource manager");
917 if ((err = res->getChannelList(db)) != 0)
919 eDebug("no channel list");
923 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
924 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
926 // eDebug("getService failed!");
934 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
935 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
938 m_is_stream = m_reference.path.substr(0, 7) == "http://";
939 m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
941 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
942 m_skipmode = m_fastforward = m_slowmotion = 0;
944 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
945 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
946 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
948 m_cuesheet_changed = 0;
949 m_cutlist_enabled = 1;
951 m_subtitle_widget = 0;
955 m_subtitle_sync_timer = eTimer::create(eApp);
957 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
960 eDVBServicePlay::~eDVBServicePlay()
965 int ret=meta.parseFile(m_reference.path);
969 meta.m_service_data="";
970 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
971 meta.m_service_data += tmp;
973 for (int x=0; x < eDVBService::cacheMax; ++x)
975 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
978 sprintf(tmp, ",c:%02d%04x", x, entry);
979 meta.m_service_data += tmp;
982 meta.updateMeta(m_reference.path);
985 delete m_subtitle_widget;
988 void eDVBServicePlay::gotNewEvent()
992 ePtr<eServiceEvent> m_event_now, m_event_next;
993 getEvent(m_event_now, 0);
994 getEvent(m_event_next, 1);
997 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
999 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1001 m_event((iPlayableService*)this, evUpdatedEventInfo);
1004 void eDVBServicePlay::serviceEvent(int event)
1006 m_tune_state = event;
1010 case eDVBServicePMTHandler::eventTuned:
1012 ePtr<iDVBDemux> m_demux;
1013 if (!m_service_handler.getDataDemux(m_demux))
1015 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1016 int sid = ref.getParentServiceID().get();
1018 sid = ref.getServiceID().get();
1019 if ( ref.getParentTransportStreamID().get() &&
1020 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1021 m_event_handler.startOther(m_demux, sid);
1023 m_event_handler.start(m_demux, sid);
1025 m_event((iPlayableService*)this, evTunedIn);
1028 case eDVBServicePMTHandler::eventNoResources:
1029 case eDVBServicePMTHandler::eventNoPAT:
1030 case eDVBServicePMTHandler::eventNoPATEntry:
1031 case eDVBServicePMTHandler::eventNoPMT:
1032 case eDVBServicePMTHandler::eventTuneFailed:
1033 case eDVBServicePMTHandler::eventMisconfiguration:
1035 eDebug("DVB service failed to tune - error %d", event);
1036 m_event((iPlayableService*)this, evTuneFailed);
1039 case eDVBServicePMTHandler::eventNewProgramInfo:
1041 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1042 if (m_timeshift_enabled)
1043 updateTimeshiftPids();
1044 if (!m_timeshift_active)
1046 if (m_first_program_info & 1 && m_is_pvr)
1048 m_first_program_info &= ~1;
1051 if (!m_timeshift_active)
1052 m_event((iPlayableService*)this, evUpdatedInfo);
1055 case eDVBServicePMTHandler::eventPreStart:
1058 case eDVBServicePMTHandler::eventEOF:
1059 m_event((iPlayableService*)this, evEOF);
1061 case eDVBServicePMTHandler::eventSOF:
1062 m_event((iPlayableService*)this, evSOF);
1064 case eDVBServicePMTHandler::eventHBBTVInfo:
1065 m_event((iPlayableService*)this, evHBBTVInfo);
1070 void eDVBServicePlay::serviceEventTimeshift(int event)
1074 case eDVBServicePMTHandler::eventNewProgramInfo:
1075 eDebug("eventNewProgramInfo TS");
1076 if (m_timeshift_active)
1079 if (m_first_program_info & 2)
1083 eDebug("re-apply slowmotion after timeshift file change");
1084 m_decoder->setSlowMotion(m_slowmotion);
1088 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1090 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1091 if (m_fastforward != 1)
1092 m_decoder->setFastForward(m_fastforward);
1094 m_decoder->setTrickmode();
1098 m_first_program_info &= ~2;
1100 m_event((iPlayableService*)this, evUpdatedInfo);
1103 case eDVBServicePMTHandler::eventSOF:
1105 if (!m_timeshift_file_next.empty())
1107 eDebug("timeshift SOF, switch to next file");
1110 m_first_program_info |= 2;
1112 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1113 r.path = m_timeshift_file_next;
1115 /* free the timeshift service handler, we need the resources */
1116 m_service_handler_timeshift.free();
1120 m_cue->seekTo(0, -1000);
1121 ePtr<iTsSource> source = createTsSource(r);
1122 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1124 m_event((iPlayableService*)this, evUser+1);
1128 m_event((iPlayableService*)this, evSOF);
1130 case eDVBServicePMTHandler::eventEOF:
1131 if ((!m_is_paused) && (m_skipmode >= 0))
1133 if (m_timeshift_file_next.empty())
1135 eDebug("timeshift EOF, so let's go live");
1140 eDebug("timeshift EOF, switch to next file");
1142 m_first_program_info |= 2;
1144 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1145 r.path = m_timeshift_file_next;
1147 /* free the timeshift service handler, we need the resources */
1148 m_service_handler_timeshift.free();
1151 ePtr<iTsSource> source = createTsSource(r);
1152 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 */
1154 m_event((iPlayableService*)this, evUser+1);
1161 RESULT eDVBServicePlay::start()
1163 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1165 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1166 two (one for decoding, one for data source), as we must be prepared
1167 to start recording from the data demux. */
1170 eDVBMetaParser meta;
1171 if (!meta.parseFile(m_reference.path))
1173 service = meta.m_ref;
1174 service.path = m_reference.path;
1176 m_cue = new eCueSheet();
1179 m_event(this, evStart);
1181 m_first_program_info = 1;
1182 ePtr<iTsSource> source = createTsSource(service);
1183 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1187 /* inject EIT if there is a stored one */
1188 std::string filename = service.path;
1189 filename.erase(filename.length()-2, 2);
1191 ePtr<eServiceEvent> event = new eServiceEvent;
1192 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1194 ePtr<eServiceEvent> empty;
1195 m_event_handler.inject(event, 0);
1196 m_event_handler.inject(empty, 1);
1198 m_event(this, evStart);
1203 RESULT eDVBServicePlay::stop()
1205 /* add bookmark for last play position */
1208 pts_t play_position, length;
1209 if (!getPlayPosition(play_position))
1211 /* remove last position */
1212 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1214 if (i->what == 3) /* current play position */
1216 m_cue_entries.erase(i);
1217 i = m_cue_entries.begin();
1223 if (getLength(length))
1228 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1230 m_cuesheet_changed = 1;
1234 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1236 m_service_handler_timeshift.free();
1237 m_service_handler.free();
1239 if (m_is_pvr && m_cuesheet_changed)
1242 /* save cuesheet only when main file is accessible. */
1243 if (!::stat(m_reference.path.c_str(), &s))
1246 m_event((iPlayableService*)this, evStopped);
1250 RESULT eDVBServicePlay::setTarget(int target)
1252 m_is_primary = !target;
1256 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1258 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1262 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1264 /* note: we check for timeshift to be enabled,
1265 not neccessary active. if you pause when timeshift
1266 is not active, you should activate it when unpausing */
1267 if ((!m_is_pvr) && (!m_timeshift_enabled))
1277 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1279 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1280 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1281 setFastForward_internal(0);
1284 m_slowmotion = ratio;
1285 return m_decoder->setSlowMotion(ratio);
1291 RESULT eDVBServicePlay::setFastForward(int ratio)
1293 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1295 return setFastForward_internal(ratio);
1298 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1300 int skipmode, ffratio, ret = 0;
1307 } else if (ratio > 0)
1315 } else // if (ratio < 0)
1321 if (m_skipmode != skipmode)
1323 eDebug("setting cue skipmode to %d", skipmode);
1325 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1328 m_skipmode = skipmode;
1331 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1333 m_fastforward = ffratio;
1339 ; /* return m_decoder->play(); is done in caller*/
1340 else if (ffratio != 1)
1341 ret = m_decoder->setFastForward(ffratio);
1343 ret = m_decoder->setTrickmode();
1346 eDebug("final seek after trickplay ret %d", seekTo(pos));
1351 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1353 if (m_is_pvr || m_timeshift_enabled)
1363 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1364 RESULT eDVBServicePlay::getLength(pts_t &len)
1366 ePtr<iDVBPVRChannel> pvr_channel;
1368 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1371 return pvr_channel->getLength(len);
1374 RESULT eDVBServicePlay::pause()
1376 eDebug("eDVBServicePlay::pause");
1377 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1382 return m_decoder->pause();
1387 RESULT eDVBServicePlay::unpause()
1389 eDebug("eDVBServicePlay::unpause");
1390 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1395 return m_decoder->play();
1400 RESULT eDVBServicePlay::seekTo(pts_t to)
1402 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1404 if (!m_decode_demux)
1407 ePtr<iDVBPVRChannel> pvr_channel;
1409 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1415 m_cue->seekTo(0, to);
1416 m_dvb_subtitle_pages.clear();
1417 m_subtitle_pages.clear();
1422 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1424 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1426 if (!m_decode_demux)
1429 ePtr<iDVBPVRChannel> pvr_channel;
1431 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1436 /* HACK until we have skip-AP api */
1437 if ((to > 0) && (to < 100))
1445 m_cue->seekTo(mode, to);
1446 m_dvb_subtitle_pages.clear();
1447 m_subtitle_pages.clear();
1451 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1453 ePtr<iDVBPVRChannel> pvr_channel;
1455 if (!m_decode_demux)
1458 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1463 /* if there is a decoder, use audio or video PTS */
1466 r = m_decoder->getPTS(0, pos);
1472 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1475 RESULT eDVBServicePlay::setTrickmode(int trick)
1477 /* currently unimplemented */
1481 RESULT eDVBServicePlay::isCurrentlySeekable()
1486 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1487 if (m_decoder->getVideoProgressive() == -1)
1493 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1499 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1505 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1511 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1517 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1523 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1526 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1527 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1529 if (!m_timeshift_enabled)
1531 /* query config path */
1533 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1534 eDebug("could not query ts path from config");
1538 /* we need enough diskspace */
1540 if (statfs(tspath.c_str(), &fs) < 0)
1542 eDebug("statfs failed!");
1546 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1548 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1558 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1569 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1575 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1581 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1587 RESULT eDVBServicePlay::getName(std::string &name)
1591 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1592 return i->getName(m_reference, name);
1594 else if (m_is_stream)
1596 name = m_reference.name;
1599 name = m_reference.path;
1606 else if (m_dvb_service)
1608 m_dvb_service->getName(m_reference, name);
1612 else if (!m_reference.name.empty())
1613 eStaticServiceDVBInformation().getName(m_reference, name);
1615 name = "DVB service";
1619 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1621 return m_event_handler.getEvent(evt, nownext);
1624 int eDVBServicePlay::getInfo(int w)
1626 eDVBServicePMTHandler::program program;
1628 if (w == sCAIDs || w == sCAIDPIDs)
1629 return resIsPyObject;
1631 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1633 int no_program_info = 0;
1635 if (h.getProgramInfo(program))
1636 no_program_info = 1;
1642 return m_decoder->getVideoHeight();
1646 return m_decoder->getVideoWidth();
1650 return m_decoder->getVideoFrameRate();
1654 return m_decoder->getVideoProgressive();
1660 aspect = m_decoder->getVideoAspect();
1661 if (aspect == -1 && no_program_info)
1663 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1665 ePtr<eServiceEvent> evt;
1666 if (!m_event_handler.getEvent(evt, 0))
1668 ePtr<eComponentData> data;
1669 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1671 if ( data->getStreamContent() == 1 )
1673 switch(data->getComponentType())
1676 case 1: // 4:3 SD PAL
1678 case 3: // 16:9 SD PAL
1679 case 4: // > 16:9 PAL
1680 case 5: // 4:3 SD NTSC
1682 case 7: // 16:9 SD NTSC
1683 case 8: // > 16:9 NTSC
1686 case 9: // 4:3 HD PAL
1688 case 0xB: // 16:9 HD PAL
1689 case 0xC: // > 16:9 HD PAL
1690 case 0xD: // 4:3 HD NTSC
1692 case 0xF: // 16:9 HD NTSC
1693 case 0x10: // > 16:9 HD PAL
1694 return data->getComponentType();
1704 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1708 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1712 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1713 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1717 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1720 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1724 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1728 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1732 if (no_program_info) return -1; return program.pcrPid;
1733 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1734 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1735 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1736 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1737 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1738 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1739 case sProvider: if (!m_dvb_service) return -1; return -2;
1740 case sServiceref: return resIsString;
1741 case sDVBState: return m_tune_state;
1748 std::string eDVBServicePlay::getInfoString(int w)
1753 if (!m_dvb_service) return "";
1754 return m_dvb_service->m_provider_name;
1756 return m_reference.toString();
1760 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1764 case sLiveStreamDemuxId:
1767 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1777 return iServiceInformation::getInfoString(w);
1780 PyObject *eDVBServicePlay::getInfoObject(int w)
1785 return m_service_handler.getCaIds();
1787 return m_service_handler.getCaIds(true);
1788 case sTransponderData:
1789 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1792 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1793 return h.getHbbTVApplications();
1798 return iServiceInformation::getInfoObject(w);
1801 int eDVBServicePlay::getNumberOfTracks()
1803 eDVBServicePMTHandler::program program;
1804 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1805 if (h.getProgramInfo(program))
1807 return program.audioStreams.size();
1810 int eDVBServicePlay::getCurrentTrack()
1812 eDVBServicePMTHandler::program program;
1813 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1814 if (h.getProgramInfo(program))
1817 int max = program.audioStreams.size();
1820 for (i = 0; i < max; ++i)
1821 if (program.audioStreams[i].pid == m_current_audio_pid)
1827 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1829 int ret = selectAudioStream(i);
1831 if (m_decoder->set())
1837 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1839 eDVBServicePMTHandler::program program;
1840 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1842 if (h.getProgramInfo(program))
1845 if (i >= program.audioStreams.size())
1848 info.m_pid = program.audioStreams[i].pid;
1850 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1851 info.m_description = "MPEG";
1852 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1853 info.m_description = "Dolby Digital";
1854 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1855 info.m_description = "Dolby Digital+";
1856 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1857 info.m_description = "AAC";
1858 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1859 info.m_description = "AAC-HE";
1860 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1861 info.m_description = "DTS";
1862 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1863 info.m_description = "DTS-HD";
1865 info.m_description = "???";
1867 if (program.audioStreams[i].component_tag != -1)
1869 ePtr<eServiceEvent> evt;
1870 if (!m_event_handler.getEvent(evt, 0))
1872 ePtr<eComponentData> data;
1873 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1874 info.m_language = data->getText();
1878 if (info.m_language.empty())
1879 info.m_language = program.audioStreams[i].language_code;
1884 int eDVBServicePlay::selectAudioStream(int i)
1886 eDVBServicePMTHandler::program program;
1887 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1888 pts_t position = -1;
1890 if (h.getProgramInfo(program))
1893 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1901 stream = program.defaultAudioStream;
1903 int apid = -1, apidtype = -1;
1905 if (((unsigned int)stream) < program.audioStreams.size())
1907 apid = program.audioStreams[stream].pid;
1908 apidtype = program.audioStreams[stream].type;
1911 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1912 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1914 m_current_audio_pid = apid;
1916 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1918 eDebug("set audio pid failed");
1923 eDebug("seekTo ret %d", seekTo(position));
1927 /* 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 */
1928 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1930 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1932 rdsPid = program.audioStreams[stream].rdsPid;
1933 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1936 ePtr<iDVBDemux> data_demux;
1937 if (!h.getDataDemux(data_demux))
1939 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1940 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1941 m_rds_decoder->start(rdsPid);
1946 /* store new pid as default only when:
1947 a.) we have an entry in the service db for the current service,
1948 b.) we are not playing back something,
1949 c.) we are not selecting the default entry. (we wouldn't change
1950 anything in the best case, or destroy the default setting in
1951 case the real default is not yet available.)
1953 if (m_dvb_service && ((i != -1)
1954 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1956 if (apidtype == eDVBAudio::aMPEG)
1958 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1959 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1961 else if (apidtype == eDVBAudio::aAC3)
1963 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1964 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1968 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1969 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1973 h.resetCachedProgram();
1978 int eDVBServicePlay::getCurrentChannel()
1980 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1983 RESULT eDVBServicePlay::selectChannel(int i)
1985 if (i < LEFT || i > RIGHT || i == STEREO)
1988 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1990 m_decoder->setAudioChannel(i);
1994 std::string eDVBServicePlay::getText(int x)
2000 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2002 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2007 void eDVBServicePlay::rdsDecoderEvent(int what)
2011 case eDVBRdsDecoder::RadioTextChanged:
2012 m_event((iPlayableService*)this, evUpdatedRadioText);
2014 case eDVBRdsDecoder::RtpTextChanged:
2015 m_event((iPlayableService*)this, evUpdatedRtpText);
2017 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2018 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2020 case eDVBRdsDecoder::RecvRassSlidePic:
2021 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2026 void eDVBServicePlay::showRassSlidePicture()
2032 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2033 if (rass_slide_pic.length())
2034 m_decoder->showSinglePic(rass_slide_pic.c_str());
2036 eDebug("empty filename for rass slide picture received!!");
2039 eDebug("no MPEG Decoder to show iframes avail");
2042 eDebug("showRassSlidePicture called.. but not decoder");
2045 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2051 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2052 if (rass_interactive_pic.length())
2053 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2055 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2058 eDebug("no MPEG Decoder to show iframes avail");
2061 eDebug("showRassInteractivePic called.. but not decoder");
2064 ePyObject eDVBServicePlay::getRassInteractiveMask()
2067 return m_rds_decoder->getRassPictureMask();
2071 int eDVBServiceBase::getFrontendInfo(int w)
2073 eUsePtr<iDVBChannel> channel;
2074 if(m_service_handler.getChannel(channel))
2076 ePtr<iDVBFrontend> fe;
2077 if(channel->getFrontend(fe))
2079 return fe->readFrontendData(w);
2082 PyObject *eDVBServiceBase::getFrontendData()
2084 ePyObject ret = PyDict_New();
2087 eUsePtr<iDVBChannel> channel;
2088 if(!m_service_handler.getChannel(channel))
2090 ePtr<iDVBFrontend> fe;
2091 if(!channel->getFrontend(fe))
2092 fe->getFrontendData(ret);
2100 PyObject *eDVBServiceBase::getFrontendStatus()
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->getFrontendStatus(ret);
2118 PyObject *eDVBServiceBase::getTransponderData(bool original)
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->getTransponderData(ret, original);
2136 PyObject *eDVBServiceBase::getAll(bool original)
2138 ePyObject ret = getTransponderData(original);
2141 eUsePtr<iDVBChannel> channel;
2142 if(!m_service_handler.getChannel(channel))
2144 ePtr<iDVBFrontend> fe;
2145 if(!channel->getFrontend(fe))
2147 fe->getFrontendData(ret);
2148 fe->getFrontendStatus(ret);
2155 int eDVBServicePlay::getNumberOfSubservices()
2157 ePtr<eServiceEvent> evt;
2158 if (!m_event_handler.getEvent(evt, 0))
2159 return evt->getNumOfLinkageServices();
2163 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2165 ePtr<eServiceEvent> evt;
2166 if (!m_event_handler.getEvent(evt, 0))
2168 if (!evt->getLinkageService(sub, m_reference, n))
2171 sub.type=eServiceReference::idInvalid;
2175 RESULT eDVBServicePlay::startTimeshift()
2177 ePtr<iDVBDemux> demux;
2179 eDebug("Start timeshift!");
2181 if (m_timeshift_enabled)
2184 /* start recording with the data demux. */
2185 if (m_service_handler.getDataDemux(demux))
2188 demux->createTSRecorder(m_record);
2193 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2194 eDebug("could not query ts path");
2197 tspath.append("/timeshift.XXXXXX");
2199 templ = new char[tspath.length() + 1];
2200 strcpy(templ, tspath.c_str());
2202 m_timeshift_fd = mkstemp(templ);
2203 m_timeshift_file = std::string(templ);
2205 eDebug("recording to %s", templ);
2209 if (m_timeshift_fd < 0)
2215 m_record->setTargetFD(m_timeshift_fd);
2217 m_timeshift_enabled = 1;
2219 updateTimeshiftPids();
2225 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2227 if (!m_timeshift_enabled)
2233 m_timeshift_enabled = 0;
2238 close(m_timeshift_fd);
2239 eDebug("remove timeshift file");
2240 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2245 int eDVBServicePlay::isTimeshiftActive()
2247 return m_timeshift_enabled && m_timeshift_active;
2250 RESULT eDVBServicePlay::activateTimeshift()
2252 if (!m_timeshift_enabled)
2255 if (!m_timeshift_active)
2257 switchToTimeshift();
2264 PyObject *eDVBServicePlay::getCutList()
2266 ePyObject list = PyList_New(0);
2268 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2270 ePyObject tuple = PyTuple_New(2);
2271 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2272 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2273 PyList_Append(list, tuple);
2280 void eDVBServicePlay::setCutList(ePyObject list)
2282 if (!PyList_Check(list))
2284 int size = PyList_Size(list);
2287 m_cue_entries.clear();
2289 for (i=0; i<size; ++i)
2291 ePyObject tuple = PyList_GET_ITEM(list, i);
2292 if (!PyTuple_Check(tuple))
2294 eDebug("non-tuple in cutlist");
2297 if (PyTuple_Size(tuple) != 2)
2299 eDebug("cutlist entries need to be a 2-tuple");
2302 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2303 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2305 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2308 pts_t pts = PyLong_AsLongLong(ppts);
2309 int type = PyInt_AsLong(ptype);
2310 m_cue_entries.insert(cueEntry(pts, type));
2311 eDebug("adding %08llx, %d", pts, type);
2313 m_cuesheet_changed = 1;
2315 cutlistToCuesheet();
2316 m_event((iPlayableService*)this, evCuesheetChanged);
2319 void eDVBServicePlay::setCutListEnable(int enable)
2321 m_cutlist_enabled = enable;
2322 cutlistToCuesheet();
2325 void eDVBServicePlay::updateTimeshiftPids()
2330 eDVBServicePMTHandler::program program;
2331 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2333 if (h.getProgramInfo(program))
2337 std::set<int> pids_to_record;
2338 pids_to_record.insert(0); // PAT
2339 if (program.pmtPid != -1)
2340 pids_to_record.insert(program.pmtPid); // PMT
2342 if (program.textPid != -1)
2343 pids_to_record.insert(program.textPid); // Videotext
2345 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2346 i(program.videoStreams.begin());
2347 i != program.videoStreams.end(); ++i)
2348 pids_to_record.insert(i->pid);
2350 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2351 i(program.audioStreams.begin());
2352 i != program.audioStreams.end(); ++i)
2353 pids_to_record.insert(i->pid);
2355 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2356 i(program.subtitleStreams.begin());
2357 i != program.subtitleStreams.end(); ++i)
2358 pids_to_record.insert(i->pid);
2360 std::set<int> new_pids, obsolete_pids;
2362 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2363 m_pids_active.begin(), m_pids_active.end(),
2364 std::inserter(new_pids, new_pids.begin()));
2366 std::set_difference(
2367 m_pids_active.begin(), m_pids_active.end(),
2368 pids_to_record.begin(), pids_to_record.end(),
2369 std::inserter(new_pids, new_pids.begin())
2372 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2373 m_record->addPID(*i);
2375 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2376 m_record->removePID(*i);
2380 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2382 m_timeshift_file_next = f;
2386 void eDVBServicePlay::switchToLive()
2388 if (!m_timeshift_active)
2391 eDebug("SwitchToLive");
2395 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2397 /* free the timeshift service handler, we need the resources */
2398 m_service_handler_timeshift.free();
2400 updateDecoder(true);
2403 void eDVBServicePlay::resetTimeshift(int start)
2408 m_teletext_parser = 0;
2410 m_subtitle_parser = 0;
2411 m_new_subtitle_page_connection = 0;
2412 m_new_dvb_subtitle_page_connection = 0;
2413 m_rds_decoder_event_connection = 0;
2414 m_video_event_connection = 0;
2415 m_timeshift_changed = 1;
2416 m_timeshift_file_next.clear();
2420 m_cue = new eCueSheet();
2421 m_timeshift_active = 1;
2424 m_timeshift_active = 0;
2427 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2431 eHttpStream *f = new eHttpStream();
2432 f->open(ref.path.c_str());
2433 return ePtr<iTsSource>(f);
2437 eRawFile *f = new eRawFile();
2438 f->open(ref.path.c_str());
2439 return ePtr<iTsSource>(f);
2443 void eDVBServicePlay::switchToTimeshift()
2445 if (m_timeshift_active)
2450 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2451 r.path = m_timeshift_file;
2453 m_cue->seekTo(0, -1000);
2455 ePtr<iTsSource> source = createTsSource(r);
2456 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 */
2458 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2460 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2463 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2465 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2466 bool mustPlay = false;
2468 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2470 eDVBServicePMTHandler::program program;
2471 if (h.getProgramInfo(program))
2472 eDebug("getting program info failed.");
2475 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2476 if (!program.videoStreams.empty())
2478 eDebugNoNewLine(" (");
2479 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2480 i(program.videoStreams.begin());
2481 i != program.videoStreams.end(); ++i)
2488 if (i != program.videoStreams.begin())
2489 eDebugNoNewLine(", ");
2490 eDebugNoNewLine("%04x", i->pid);
2492 eDebugNoNewLine(")");
2494 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2495 if (!program.audioStreams.empty())
2497 eDebugNoNewLine(" (");
2498 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2499 i(program.audioStreams.begin());
2500 i != program.audioStreams.end(); ++i)
2502 if (i != program.audioStreams.begin())
2503 eDebugNoNewLine(", ");
2504 eDebugNoNewLine("%04x", i->pid);
2506 eDebugNoNewLine(")");
2508 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2509 pcrpid = program.pcrPid;
2510 eDebug(", and the text pid is %04x", program.textPid);
2511 tpid = program.textPid;
2516 h.getDecodeDemux(m_decode_demux);
2519 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2521 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2524 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2525 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2526 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2527 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2528 if (m_timeshift_changed)
2530 ePyObject subs = getCachedSubtitle();
2531 if (subs != Py_None)
2533 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2534 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2535 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2536 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2537 if (type == 0) // dvb
2538 m_subtitle_parser->start(pid, comp_page, anc_page);
2539 else if (type == 1) // ttx
2540 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2547 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2551 m_timeshift_changed = 0;
2555 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2558 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2559 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2560 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2564 eServiceReferenceDVB ref;
2565 m_service_handler.getServiceReference(ref);
2566 eServiceReferenceDVB parent = ref.getParentServiceReference();
2571 ePtr<eDVBResourceManager> res_mgr;
2572 if (!eDVBResourceManager::getInstance(res_mgr))
2574 ePtr<iDVBChannelList> db;
2575 if (!res_mgr->getChannelList(db))
2577 ePtr<eDVBService> origService;
2578 if (!db->getService(parent, origService))
2580 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2581 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2588 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2589 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2591 m_decoder->setVideoPID(vpid, vpidtype);
2592 selectAudioStream();
2594 if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2595 m_decoder->setSyncPCR(pcrpid);
2597 m_decoder->setSyncPCR(-1);
2601 m_decoder->setTextPID(tpid);
2602 m_teletext_parser->start(program.textPid);
2605 if (vpid > 0 && vpid < 0x2000)
2609 std::string radio_pic;
2610 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2611 m_decoder->setRadioPic(radio_pic);
2619 m_decoder->setAudioChannel(achannel);
2621 /* don't worry about non-existing services, nor pvr services */
2624 /* (audio pid will be set in selectAudioTrack */
2625 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2626 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2627 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2628 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2630 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2631 sendSeekableStateChanged = true;
2633 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2635 if (sendSeekableStateChanged)
2636 m_event((iPlayableService*)this, evSeekableStatusChanged);
2639 void eDVBServicePlay::loadCuesheet()
2641 std::string filename = m_reference.path + ".cuts";
2643 m_cue_entries.clear();
2645 FILE *f = fopen(filename.c_str(), "rb");
2649 eDebug("loading cuts..");
2652 unsigned long long where;
2655 if (!fread(&where, sizeof(where), 1, f))
2657 if (!fread(&what, sizeof(what), 1, f))
2660 #if BYTE_ORDER == LITTLE_ENDIAN
2661 where = bswap_64(where);
2668 m_cue_entries.insert(cueEntry(where, what));
2671 eDebug("%zd entries", m_cue_entries.size());
2673 eDebug("cutfile not found!");
2675 m_cuesheet_changed = 0;
2676 cutlistToCuesheet();
2677 m_event((iPlayableService*)this, evCuesheetChanged);
2680 void eDVBServicePlay::saveCuesheet()
2682 std::string filename = m_reference.path + ".cuts";
2684 FILE *f = fopen(filename.c_str(), "wb");
2688 unsigned long long where;
2691 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2693 #if BYTE_ORDER == BIG_ENDIAN
2696 where = bswap_64(i->where);
2698 what = htonl(i->what);
2699 fwrite(&where, sizeof(where), 1, f);
2700 fwrite(&what, sizeof(what), 1, f);
2706 m_cuesheet_changed = 0;
2709 void eDVBServicePlay::cutlistToCuesheet()
2713 eDebug("no cue sheet");
2718 if (!m_cutlist_enabled)
2720 m_cue->commitSpans();
2721 eDebug("cutlists were disabled");
2725 pts_t in = 0, out = 0, length = 0;
2729 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2731 int have_any_span = 0;
2735 if (i == m_cue_entries.end())
2737 if (!have_any_span && !in)
2741 if (i->what == 0) /* in */
2745 } else if (i->what == 1) /* out */
2747 else /* mark (2) or last play position (3) */
2766 m_cue->addSourceSpan(in, out);
2772 if (i == m_cue_entries.end())
2775 m_cue->commitSpans();
2778 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2780 if (m_subtitle_widget)
2781 disableSubtitles(parent);
2784 int tuplesize = PyTuple_Size(tuple);
2787 if (!PyTuple_Check(tuple))
2793 entry = PyTuple_GET_ITEM(tuple, 0);
2795 if (!PyInt_Check(entry))
2798 type = PyInt_AsLong(entry);
2800 if (type == 1) // teletext subtitles
2802 int page, magazine, pid;
2806 if (!m_teletext_parser)
2808 eDebug("enable teletext subtitles.. no parser !!!");
2812 entry = PyTuple_GET_ITEM(tuple, 1);
2813 if (!PyInt_Check(entry))
2815 pid = PyInt_AsLong(entry);
2817 entry = PyTuple_GET_ITEM(tuple, 2);
2818 if (!PyInt_Check(entry))
2820 page = PyInt_AsLong(entry);
2822 entry = PyTuple_GET_ITEM(tuple, 3);
2823 if (!PyInt_Check(entry))
2825 magazine = PyInt_AsLong(entry);
2827 m_subtitle_widget = new eSubtitleWidget(parent);
2828 m_subtitle_widget->resize(parent->size()); /* full size */
2829 m_teletext_parser->setPageAndMagazine(page, magazine);
2831 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2835 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2836 if (!m_subtitle_parser)
2838 eDebug("enable dvb subtitles.. no parser !!!");
2844 entry = PyTuple_GET_ITEM(tuple, 1);
2845 if (!PyInt_Check(entry))
2847 pid = PyInt_AsLong(entry);
2849 entry = PyTuple_GET_ITEM(tuple, 2);
2850 if (!PyInt_Check(entry))
2852 composition_page_id = PyInt_AsLong(entry);
2854 entry = PyTuple_GET_ITEM(tuple, 3);
2855 if (!PyInt_Check(entry))
2857 ancillary_page_id = PyInt_AsLong(entry);
2859 m_subtitle_widget = new eSubtitleWidget(parent);
2860 m_subtitle_widget->resize(parent->size()); /* full size */
2861 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2863 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2869 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2870 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2871 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2875 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2877 delete m_subtitle_widget;
2878 m_subtitle_widget = 0;
2879 if (m_subtitle_parser)
2881 m_subtitle_parser->stop();
2882 m_dvb_subtitle_pages.clear();
2884 if (m_teletext_parser)
2886 m_teletext_parser->setPageAndMagazine(-1, -1);
2887 m_subtitle_pages.clear();
2890 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2894 PyObject *eDVBServicePlay::getCachedSubtitle()
2898 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2901 unsigned int data = (unsigned int)tmp;
2902 int pid = (data&0xFFFF0000)>>16;
2903 ePyObject tuple = PyTuple_New(4);
2904 eDVBServicePMTHandler::program program;
2905 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2906 if (!h.getProgramInfo(program))
2908 if (program.textPid==pid) // teletext
2909 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2911 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2912 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2913 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2914 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2922 PyObject *eDVBServicePlay::getSubtitleList()
2924 if (!m_teletext_parser)
2927 ePyObject l = PyList_New(0);
2928 std::set<int> added_ttx_pages;
2930 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2931 m_teletext_parser->m_found_subtitle_pages;
2933 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2934 eDVBServicePMTHandler::program program;
2935 if (h.getProgramInfo(program))
2936 eDebug("getting program info failed.");
2939 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2940 it != program.subtitleStreams.end(); ++it)
2942 switch(it->subtitling_type)
2944 case 0x01: // ebu teletext subtitles
2946 int page_number = it->teletext_page_number & 0xFF;
2947 int magazine_number = it->teletext_magazine_number & 7;
2948 int hash = magazine_number << 8 | page_number;
2949 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2951 ePyObject tuple = PyTuple_New(5);
2952 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2953 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2954 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2955 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2956 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2957 PyList_Append(l, tuple);
2959 added_ttx_pages.insert(hash);
2964 case 0x20 ... 0x23: // dvb subtitles
2966 ePyObject tuple = PyTuple_New(5);
2967 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2968 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2969 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2970 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2971 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2972 PyList_Insert(l, 0, tuple);
2980 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2981 it != subs.end(); ++it)
2983 int page_number = it->teletext_page_number & 0xFF;
2984 int magazine_number = it->teletext_magazine_number & 7;
2985 int hash = magazine_number << 8 | page_number;
2986 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2988 ePyObject tuple = PyTuple_New(5);
2989 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2990 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2991 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2992 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2993 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2994 PyList_Append(l, tuple);
3002 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3004 if (m_subtitle_widget)
3008 m_decoder->getPTS(0, pos);
3009 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3010 m_subtitle_pages.push_back(page);
3011 checkSubtitleTiming();
3015 void eDVBServicePlay::checkSubtitleTiming()
3017 eDebug("checkSubtitleTiming");
3018 if (!m_subtitle_widget)
3022 enum { TELETEXT, DVB } type;
3023 eDVBTeletextSubtitlePage page;
3024 eDVBSubtitlePage dvb_page;
3026 if (!m_subtitle_pages.empty())
3028 page = m_subtitle_pages.front();
3030 show_time = page.m_pts;
3032 else if (!m_dvb_subtitle_pages.empty())
3034 dvb_page = m_dvb_subtitle_pages.front();
3036 show_time = dvb_page.m_show_time;
3044 m_decoder->getPTS(0, pos);
3046 eDebug("%lld %lld", pos, show_time);
3047 int diff = show_time - pos;
3048 if (type == TELETEXT && !page.m_have_pts)
3050 eDebug("ttx subtitle page without pts... immediate show");
3055 eDebug("[late (%d ms)]", -diff / 90);
3058 if (abs(diff) > 1800000)
3060 eDebug("[invalid]... immediate show!");
3065 if (type == TELETEXT)
3067 eDebug("display teletext subtitle page %lld", show_time);
3068 m_subtitle_widget->setPage(page);
3069 m_subtitle_pages.pop_front();
3073 eDebug("display dvb subtitle Page %lld", show_time);
3074 m_subtitle_widget->setPage(dvb_page);
3075 m_dvb_subtitle_pages.pop_front();
3079 eDebug("start subtitle delay %d", diff / 90);
3080 m_subtitle_sync_timer->start(diff / 90, 1);
3086 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3088 if (m_subtitle_widget)
3092 m_decoder->getPTS(0, pos);
3093 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3094 m_dvb_subtitle_pages.push_back(p);
3095 checkSubtitleTiming();
3099 int eDVBServicePlay::getAC3Delay()
3102 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3104 return m_decoder->getAC3Delay();
3109 int eDVBServicePlay::getPCMDelay()
3112 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3114 return m_decoder->getPCMDelay();
3119 void eDVBServicePlay::setAC3Delay(int delay)
3122 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3124 std::string config_delay;
3125 int config_delay_int = 0;
3126 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3127 config_delay_int = atoi(config_delay.c_str());
3128 m_decoder->setAC3Delay(delay + config_delay_int);
3132 void eDVBServicePlay::setPCMDelay(int delay)
3135 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3137 std::string config_delay;
3138 int config_delay_int = 0;
3139 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3140 config_delay_int = atoi(config_delay.c_str());
3142 config_delay_int = 0;
3143 m_decoder->setPCMDelay(delay + config_delay_int);
3147 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3149 switch(event.type) {
3150 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3151 m_event((iPlayableService*)this, evVideoSizeChanged);
3153 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3154 m_event((iPlayableService*)this, evVideoFramerateChanged);
3156 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3157 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3164 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3170 PyObject *eDVBServicePlay::getStreamingData()
3172 eDVBServicePMTHandler::program program;
3173 if (m_service_handler.getProgramInfo(program))
3178 ePyObject r = program.createPythonObject();
3179 ePtr<iDVBDemux> demux;
3180 if (!m_service_handler.getDataDemux(demux))
3183 if (!demux->getCADemuxID(demux_id))
3184 PutToDict(r, "demux", demux_id);
3191 DEFINE_REF(eDVBServicePlay)
3193 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3197 case iServiceInformation::sTransponderData:
3198 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3202 return iStaticServiceInformation::getInfoObject(ref, w);
3205 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");