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);
1067 void eDVBServicePlay::serviceEventTimeshift(int event)
1071 case eDVBServicePMTHandler::eventNewProgramInfo:
1072 eDebug("eventNewProgramInfo TS");
1073 if (m_timeshift_active)
1076 if (m_first_program_info & 2)
1080 eDebug("re-apply slowmotion after timeshift file change");
1081 m_decoder->setSlowMotion(m_slowmotion);
1085 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1087 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1088 if (m_fastforward != 1)
1089 m_decoder->setFastForward(m_fastforward);
1091 m_decoder->setTrickmode();
1095 m_first_program_info &= ~2;
1097 m_event((iPlayableService*)this, evUpdatedInfo);
1100 case eDVBServicePMTHandler::eventSOF:
1102 if (!m_timeshift_file_next.empty())
1104 eDebug("timeshift SOF, switch to next file");
1107 m_first_program_info |= 2;
1109 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1110 r.path = m_timeshift_file_next;
1112 /* free the timeshift service handler, we need the resources */
1113 m_service_handler_timeshift.free();
1117 m_cue->seekTo(0, -1000);
1118 ePtr<iTsSource> source = createTsSource(r);
1119 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1121 m_event((iPlayableService*)this, evUser+1);
1125 m_event((iPlayableService*)this, evSOF);
1127 case eDVBServicePMTHandler::eventEOF:
1128 if ((!m_is_paused) && (m_skipmode >= 0))
1130 if (m_timeshift_file_next.empty())
1132 eDebug("timeshift EOF, so let's go live");
1137 eDebug("timeshift EOF, switch to next file");
1139 m_first_program_info |= 2;
1141 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1142 r.path = m_timeshift_file_next;
1144 /* free the timeshift service handler, we need the resources */
1145 m_service_handler_timeshift.free();
1148 ePtr<iTsSource> source = createTsSource(r);
1149 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 */
1151 m_event((iPlayableService*)this, evUser+1);
1158 RESULT eDVBServicePlay::start()
1160 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1162 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1163 two (one for decoding, one for data source), as we must be prepared
1164 to start recording from the data demux. */
1167 eDVBMetaParser meta;
1168 if (!meta.parseFile(m_reference.path))
1170 service = meta.m_ref;
1171 service.path = m_reference.path;
1173 m_cue = new eCueSheet();
1176 m_event(this, evStart);
1178 m_first_program_info = 1;
1179 ePtr<iTsSource> source = createTsSource(service);
1180 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1184 /* inject EIT if there is a stored one */
1185 std::string filename = service.path;
1186 filename.erase(filename.length()-2, 2);
1188 ePtr<eServiceEvent> event = new eServiceEvent;
1189 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1191 ePtr<eServiceEvent> empty;
1192 m_event_handler.inject(event, 0);
1193 m_event_handler.inject(empty, 1);
1195 m_event(this, evStart);
1200 RESULT eDVBServicePlay::stop()
1202 /* add bookmark for last play position */
1205 pts_t play_position, length;
1206 if (!getPlayPosition(play_position))
1208 /* remove last position */
1209 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1211 if (i->what == 3) /* current play position */
1213 m_cue_entries.erase(i);
1214 i = m_cue_entries.begin();
1220 if (getLength(length))
1225 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1227 m_cuesheet_changed = 1;
1231 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1233 m_service_handler_timeshift.free();
1234 m_service_handler.free();
1236 if (m_is_pvr && m_cuesheet_changed)
1239 /* save cuesheet only when main file is accessible. */
1240 if (!::stat(m_reference.path.c_str(), &s))
1243 m_event((iPlayableService*)this, evStopped);
1247 RESULT eDVBServicePlay::setTarget(int target)
1249 m_is_primary = !target;
1253 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1255 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1259 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1261 /* note: we check for timeshift to be enabled,
1262 not neccessary active. if you pause when timeshift
1263 is not active, you should activate it when unpausing */
1264 if ((!m_is_pvr) && (!m_timeshift_enabled))
1274 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1276 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1277 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1278 setFastForward_internal(0);
1281 m_slowmotion = ratio;
1282 return m_decoder->setSlowMotion(ratio);
1288 RESULT eDVBServicePlay::setFastForward(int ratio)
1290 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1292 return setFastForward_internal(ratio);
1295 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1297 int skipmode, ffratio, ret = 0;
1304 } else if (ratio > 0)
1312 } else // if (ratio < 0)
1318 if (m_skipmode != skipmode)
1320 eDebug("setting cue skipmode to %d", skipmode);
1322 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1325 m_skipmode = skipmode;
1328 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1330 m_fastforward = ffratio;
1336 ; /* return m_decoder->play(); is done in caller*/
1337 else if (ffratio != 1)
1338 ret = m_decoder->setFastForward(ffratio);
1340 ret = m_decoder->setTrickmode();
1343 eDebug("final seek after trickplay ret %d", seekTo(pos));
1348 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1350 if (m_is_pvr || m_timeshift_enabled)
1360 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1361 RESULT eDVBServicePlay::getLength(pts_t &len)
1363 ePtr<iDVBPVRChannel> pvr_channel;
1365 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1368 return pvr_channel->getLength(len);
1371 RESULT eDVBServicePlay::pause()
1373 eDebug("eDVBServicePlay::pause");
1374 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1379 return m_decoder->pause();
1384 RESULT eDVBServicePlay::unpause()
1386 eDebug("eDVBServicePlay::unpause");
1387 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1392 return m_decoder->play();
1397 RESULT eDVBServicePlay::seekTo(pts_t to)
1399 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1401 if (!m_decode_demux)
1404 ePtr<iDVBPVRChannel> pvr_channel;
1406 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1412 m_cue->seekTo(0, to);
1413 m_dvb_subtitle_pages.clear();
1414 m_subtitle_pages.clear();
1419 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1421 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1423 if (!m_decode_demux)
1426 ePtr<iDVBPVRChannel> pvr_channel;
1428 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1433 /* HACK until we have skip-AP api */
1434 if ((to > 0) && (to < 100))
1442 m_cue->seekTo(mode, to);
1443 m_dvb_subtitle_pages.clear();
1444 m_subtitle_pages.clear();
1448 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1450 ePtr<iDVBPVRChannel> pvr_channel;
1452 if (!m_decode_demux)
1455 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1460 /* if there is a decoder, use audio or video PTS */
1463 r = m_decoder->getPTS(0, pos);
1469 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1472 RESULT eDVBServicePlay::setTrickmode(int trick)
1474 /* currently unimplemented */
1478 RESULT eDVBServicePlay::isCurrentlySeekable()
1483 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1484 if (m_decoder->getVideoProgressive() == -1)
1490 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1496 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1502 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1508 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1514 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1520 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1523 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1524 (m_timeshift_enabled || !m_is_pvr))
1526 if (!m_timeshift_enabled)
1528 /* query config path */
1530 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1531 eDebug("could not query ts path from config");
1535 /* we need enough diskspace */
1537 if (statfs(tspath.c_str(), &fs) < 0)
1539 eDebug("statfs failed!");
1543 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1545 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1555 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1566 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1572 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1578 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1584 RESULT eDVBServicePlay::getName(std::string &name)
1588 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1589 return i->getName(m_reference, name);
1591 else if (m_is_stream)
1593 name = m_reference.name;
1596 name = m_reference.path;
1603 else if (m_dvb_service)
1605 m_dvb_service->getName(m_reference, name);
1609 else if (!m_reference.name.empty())
1610 eStaticServiceDVBInformation().getName(m_reference, name);
1612 name = "DVB service";
1616 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1618 return m_event_handler.getEvent(evt, nownext);
1621 int eDVBServicePlay::getInfo(int w)
1623 eDVBServicePMTHandler::program program;
1625 if (w == sCAIDs || w == sCAIDPIDs)
1626 return resIsPyObject;
1628 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1630 int no_program_info = 0;
1632 if (h.getProgramInfo(program))
1633 no_program_info = 1;
1639 return m_decoder->getVideoHeight();
1643 return m_decoder->getVideoWidth();
1647 return m_decoder->getVideoFrameRate();
1651 return m_decoder->getVideoProgressive();
1657 aspect = m_decoder->getVideoAspect();
1658 if (aspect == -1 && no_program_info)
1660 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1662 ePtr<eServiceEvent> evt;
1663 if (!m_event_handler.getEvent(evt, 0))
1665 ePtr<eComponentData> data;
1666 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1668 if ( data->getStreamContent() == 1 )
1670 switch(data->getComponentType())
1673 case 1: // 4:3 SD PAL
1675 case 3: // 16:9 SD PAL
1676 case 4: // > 16:9 PAL
1677 case 5: // 4:3 SD NTSC
1679 case 7: // 16:9 SD NTSC
1680 case 8: // > 16:9 NTSC
1683 case 9: // 4:3 HD PAL
1685 case 0xB: // 16:9 HD PAL
1686 case 0xC: // > 16:9 HD PAL
1687 case 0xD: // 4:3 HD NTSC
1689 case 0xF: // 16:9 HD NTSC
1690 case 0x10: // > 16:9 HD PAL
1691 return data->getComponentType();
1701 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1705 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1709 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1710 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1714 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1717 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1721 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1725 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1729 if (no_program_info) return -1; return program.pcrPid;
1730 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1731 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1732 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1733 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1734 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1735 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1736 case sProvider: if (!m_dvb_service) return -1; return -2;
1737 case sServiceref: return resIsString;
1738 case sDVBState: return m_tune_state;
1745 std::string eDVBServicePlay::getInfoString(int w)
1750 if (!m_dvb_service) return "";
1751 return m_dvb_service->m_provider_name;
1753 return m_reference.toString();
1757 return iServiceInformation::getInfoString(w);
1760 PyObject *eDVBServicePlay::getInfoObject(int w)
1765 return m_service_handler.getCaIds();
1767 return m_service_handler.getCaIds(true);
1768 case sTransponderData:
1769 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1773 return iServiceInformation::getInfoObject(w);
1776 int eDVBServicePlay::getNumberOfTracks()
1778 eDVBServicePMTHandler::program program;
1779 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1780 if (h.getProgramInfo(program))
1782 return program.audioStreams.size();
1785 int eDVBServicePlay::getCurrentTrack()
1787 eDVBServicePMTHandler::program program;
1788 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1789 if (h.getProgramInfo(program))
1792 int max = program.audioStreams.size();
1795 for (i = 0; i < max; ++i)
1796 if (program.audioStreams[i].pid == m_current_audio_pid)
1802 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1804 int ret = selectAudioStream(i);
1806 if (m_decoder->set())
1812 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1814 eDVBServicePMTHandler::program program;
1815 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1817 if (h.getProgramInfo(program))
1820 if (i >= program.audioStreams.size())
1823 info.m_pid = program.audioStreams[i].pid;
1825 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1826 info.m_description = "MPEG";
1827 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1828 info.m_description = "Dolby Digital";
1829 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1830 info.m_description = "Dolby Digital+";
1831 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1832 info.m_description = "AAC";
1833 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1834 info.m_description = "AAC-HE";
1835 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1836 info.m_description = "DTS";
1837 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1838 info.m_description = "DTS-HD";
1840 info.m_description = "???";
1842 if (program.audioStreams[i].component_tag != -1)
1844 ePtr<eServiceEvent> evt;
1845 if (!m_event_handler.getEvent(evt, 0))
1847 ePtr<eComponentData> data;
1848 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1849 info.m_language = data->getText();
1853 if (info.m_language.empty())
1854 info.m_language = program.audioStreams[i].language_code;
1859 int eDVBServicePlay::selectAudioStream(int i)
1861 eDVBServicePMTHandler::program program;
1862 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1863 pts_t position = -1;
1865 if (h.getProgramInfo(program))
1868 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1876 stream = program.defaultAudioStream;
1878 int apid = -1, apidtype = -1;
1880 if (((unsigned int)stream) < program.audioStreams.size())
1882 apid = program.audioStreams[stream].pid;
1883 apidtype = program.audioStreams[stream].type;
1886 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1887 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1889 m_current_audio_pid = apid;
1891 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1893 eDebug("set audio pid failed");
1898 eDebug("seekTo ret %d", seekTo(position));
1902 /* 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 */
1903 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1905 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1907 rdsPid = program.audioStreams[stream].rdsPid;
1908 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1911 ePtr<iDVBDemux> data_demux;
1912 if (!h.getDataDemux(data_demux))
1914 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1915 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1916 m_rds_decoder->start(rdsPid);
1921 /* store new pid as default only when:
1922 a.) we have an entry in the service db for the current service,
1923 b.) we are not playing back something,
1924 c.) we are not selecting the default entry. (we wouldn't change
1925 anything in the best case, or destroy the default setting in
1926 case the real default is not yet available.)
1928 if (m_dvb_service && ((i != -1)
1929 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1931 if (apidtype == eDVBAudio::aMPEG)
1933 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1934 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1936 else if (apidtype == eDVBAudio::aAC3)
1938 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1939 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1943 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1944 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1948 h.resetCachedProgram();
1953 int eDVBServicePlay::getCurrentChannel()
1955 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1958 RESULT eDVBServicePlay::selectChannel(int i)
1960 if (i < LEFT || i > RIGHT || i == STEREO)
1963 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1965 m_decoder->setAudioChannel(i);
1969 std::string eDVBServicePlay::getText(int x)
1975 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1977 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1982 void eDVBServicePlay::rdsDecoderEvent(int what)
1986 case eDVBRdsDecoder::RadioTextChanged:
1987 m_event((iPlayableService*)this, evUpdatedRadioText);
1989 case eDVBRdsDecoder::RtpTextChanged:
1990 m_event((iPlayableService*)this, evUpdatedRtpText);
1992 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1993 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1995 case eDVBRdsDecoder::RecvRassSlidePic:
1996 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2001 void eDVBServicePlay::showRassSlidePicture()
2007 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2008 if (rass_slide_pic.length())
2009 m_decoder->showSinglePic(rass_slide_pic.c_str());
2011 eDebug("empty filename for rass slide picture received!!");
2014 eDebug("no MPEG Decoder to show iframes avail");
2017 eDebug("showRassSlidePicture called.. but not decoder");
2020 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2026 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2027 if (rass_interactive_pic.length())
2028 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2030 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2033 eDebug("no MPEG Decoder to show iframes avail");
2036 eDebug("showRassInteractivePic called.. but not decoder");
2039 ePyObject eDVBServicePlay::getRassInteractiveMask()
2042 return m_rds_decoder->getRassPictureMask();
2046 int eDVBServiceBase::getFrontendInfo(int w)
2048 eUsePtr<iDVBChannel> channel;
2049 if(m_service_handler.getChannel(channel))
2051 ePtr<iDVBFrontend> fe;
2052 if(channel->getFrontend(fe))
2054 return fe->readFrontendData(w);
2057 PyObject *eDVBServiceBase::getFrontendData()
2059 ePyObject ret = PyDict_New();
2062 eUsePtr<iDVBChannel> channel;
2063 if(!m_service_handler.getChannel(channel))
2065 ePtr<iDVBFrontend> fe;
2066 if(!channel->getFrontend(fe))
2067 fe->getFrontendData(ret);
2075 PyObject *eDVBServiceBase::getFrontendStatus()
2077 ePyObject ret = PyDict_New();
2080 eUsePtr<iDVBChannel> channel;
2081 if(!m_service_handler.getChannel(channel))
2083 ePtr<iDVBFrontend> fe;
2084 if(!channel->getFrontend(fe))
2085 fe->getFrontendStatus(ret);
2093 PyObject *eDVBServiceBase::getTransponderData(bool original)
2095 ePyObject ret = PyDict_New();
2098 eUsePtr<iDVBChannel> channel;
2099 if(!m_service_handler.getChannel(channel))
2101 ePtr<iDVBFrontend> fe;
2102 if(!channel->getFrontend(fe))
2103 fe->getTransponderData(ret, original);
2111 PyObject *eDVBServiceBase::getAll(bool original)
2113 ePyObject ret = getTransponderData(original);
2116 eUsePtr<iDVBChannel> channel;
2117 if(!m_service_handler.getChannel(channel))
2119 ePtr<iDVBFrontend> fe;
2120 if(!channel->getFrontend(fe))
2122 fe->getFrontendData(ret);
2123 fe->getFrontendStatus(ret);
2130 int eDVBServicePlay::getNumberOfSubservices()
2132 ePtr<eServiceEvent> evt;
2133 if (!m_event_handler.getEvent(evt, 0))
2134 return evt->getNumOfLinkageServices();
2138 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2140 ePtr<eServiceEvent> evt;
2141 if (!m_event_handler.getEvent(evt, 0))
2143 if (!evt->getLinkageService(sub, m_reference, n))
2146 sub.type=eServiceReference::idInvalid;
2150 RESULT eDVBServicePlay::startTimeshift()
2152 ePtr<iDVBDemux> demux;
2154 eDebug("Start timeshift!");
2156 if (m_timeshift_enabled)
2159 /* start recording with the data demux. */
2160 if (m_service_handler.getDataDemux(demux))
2163 demux->createTSRecorder(m_record);
2168 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2169 eDebug("could not query ts path");
2172 tspath.append("/timeshift.XXXXXX");
2174 templ = new char[tspath.length() + 1];
2175 strcpy(templ, tspath.c_str());
2177 m_timeshift_fd = mkstemp(templ);
2178 m_timeshift_file = std::string(templ);
2180 eDebug("recording to %s", templ);
2184 if (m_timeshift_fd < 0)
2190 m_record->setTargetFD(m_timeshift_fd);
2192 m_timeshift_enabled = 1;
2194 updateTimeshiftPids();
2200 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2202 if (!m_timeshift_enabled)
2208 m_timeshift_enabled = 0;
2213 close(m_timeshift_fd);
2214 eDebug("remove timeshift file");
2215 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2220 int eDVBServicePlay::isTimeshiftActive()
2222 return m_timeshift_enabled && m_timeshift_active;
2225 RESULT eDVBServicePlay::activateTimeshift()
2227 if (!m_timeshift_enabled)
2230 if (!m_timeshift_active)
2232 switchToTimeshift();
2239 PyObject *eDVBServicePlay::getCutList()
2241 ePyObject list = PyList_New(0);
2243 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2245 ePyObject tuple = PyTuple_New(2);
2246 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2247 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2248 PyList_Append(list, tuple);
2255 void eDVBServicePlay::setCutList(ePyObject list)
2257 if (!PyList_Check(list))
2259 int size = PyList_Size(list);
2262 m_cue_entries.clear();
2264 for (i=0; i<size; ++i)
2266 ePyObject tuple = PyList_GET_ITEM(list, i);
2267 if (!PyTuple_Check(tuple))
2269 eDebug("non-tuple in cutlist");
2272 if (PyTuple_Size(tuple) != 2)
2274 eDebug("cutlist entries need to be a 2-tuple");
2277 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2278 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2280 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2283 pts_t pts = PyLong_AsLongLong(ppts);
2284 int type = PyInt_AsLong(ptype);
2285 m_cue_entries.insert(cueEntry(pts, type));
2286 eDebug("adding %08llx, %d", pts, type);
2288 m_cuesheet_changed = 1;
2290 cutlistToCuesheet();
2291 m_event((iPlayableService*)this, evCuesheetChanged);
2294 void eDVBServicePlay::setCutListEnable(int enable)
2296 m_cutlist_enabled = enable;
2297 cutlistToCuesheet();
2300 void eDVBServicePlay::updateTimeshiftPids()
2305 eDVBServicePMTHandler::program program;
2306 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2308 if (h.getProgramInfo(program))
2312 std::set<int> pids_to_record;
2313 pids_to_record.insert(0); // PAT
2314 if (program.pmtPid != -1)
2315 pids_to_record.insert(program.pmtPid); // PMT
2317 if (program.textPid != -1)
2318 pids_to_record.insert(program.textPid); // Videotext
2320 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2321 i(program.videoStreams.begin());
2322 i != program.videoStreams.end(); ++i)
2323 pids_to_record.insert(i->pid);
2325 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2326 i(program.audioStreams.begin());
2327 i != program.audioStreams.end(); ++i)
2328 pids_to_record.insert(i->pid);
2330 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2331 i(program.subtitleStreams.begin());
2332 i != program.subtitleStreams.end(); ++i)
2333 pids_to_record.insert(i->pid);
2335 std::set<int> new_pids, obsolete_pids;
2337 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2338 m_pids_active.begin(), m_pids_active.end(),
2339 std::inserter(new_pids, new_pids.begin()));
2341 std::set_difference(
2342 m_pids_active.begin(), m_pids_active.end(),
2343 pids_to_record.begin(), pids_to_record.end(),
2344 std::inserter(new_pids, new_pids.begin())
2347 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2348 m_record->addPID(*i);
2350 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2351 m_record->removePID(*i);
2355 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2357 m_timeshift_file_next = f;
2361 void eDVBServicePlay::switchToLive()
2363 if (!m_timeshift_active)
2366 eDebug("SwitchToLive");
2370 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2372 /* free the timeshift service handler, we need the resources */
2373 m_service_handler_timeshift.free();
2375 updateDecoder(true);
2378 void eDVBServicePlay::resetTimeshift(int start)
2383 m_teletext_parser = 0;
2385 m_subtitle_parser = 0;
2386 m_new_subtitle_page_connection = 0;
2387 m_new_dvb_subtitle_page_connection = 0;
2388 m_rds_decoder_event_connection = 0;
2389 m_video_event_connection = 0;
2390 m_timeshift_changed = 1;
2391 m_timeshift_file_next.clear();
2395 m_cue = new eCueSheet();
2396 m_timeshift_active = 1;
2399 m_timeshift_active = 0;
2402 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2406 eHttpStream *f = new eHttpStream();
2407 f->open(ref.path.c_str());
2408 return ePtr<iTsSource>(f);
2412 eRawFile *f = new eRawFile();
2413 f->open(ref.path.c_str());
2414 return ePtr<iTsSource>(f);
2418 void eDVBServicePlay::switchToTimeshift()
2420 if (m_timeshift_active)
2425 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2426 r.path = m_timeshift_file;
2428 m_cue->seekTo(0, -1000);
2430 ePtr<iTsSource> source = createTsSource(r);
2431 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 */
2433 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2435 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2438 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2440 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2441 bool mustPlay = false;
2443 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2445 eDVBServicePMTHandler::program program;
2446 if (h.getProgramInfo(program))
2447 eDebug("getting program info failed.");
2450 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2451 if (!program.videoStreams.empty())
2453 eDebugNoNewLine(" (");
2454 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2455 i(program.videoStreams.begin());
2456 i != program.videoStreams.end(); ++i)
2463 if (i != program.videoStreams.begin())
2464 eDebugNoNewLine(", ");
2465 eDebugNoNewLine("%04x", i->pid);
2467 eDebugNoNewLine(")");
2469 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2470 if (!program.audioStreams.empty())
2472 eDebugNoNewLine(" (");
2473 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2474 i(program.audioStreams.begin());
2475 i != program.audioStreams.end(); ++i)
2477 if (i != program.audioStreams.begin())
2478 eDebugNoNewLine(", ");
2479 eDebugNoNewLine("%04x", i->pid);
2481 eDebugNoNewLine(")");
2483 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2484 pcrpid = program.pcrPid;
2485 eDebug(", and the text pid is %04x", program.textPid);
2486 tpid = program.textPid;
2491 h.getDecodeDemux(m_decode_demux);
2494 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2496 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2499 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2500 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2501 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2502 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2503 if (m_timeshift_changed)
2505 ePyObject subs = getCachedSubtitle();
2506 if (subs != Py_None)
2508 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2509 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2510 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2511 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2512 if (type == 0) // dvb
2513 m_subtitle_parser->start(pid, comp_page, anc_page);
2514 else if (type == 1) // ttx
2515 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2522 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2526 m_timeshift_changed = 0;
2530 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2533 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2534 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2535 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2539 eServiceReferenceDVB ref;
2540 m_service_handler.getServiceReference(ref);
2541 eServiceReferenceDVB parent = ref.getParentServiceReference();
2546 ePtr<eDVBResourceManager> res_mgr;
2547 if (!eDVBResourceManager::getInstance(res_mgr))
2549 ePtr<iDVBChannelList> db;
2550 if (!res_mgr->getChannelList(db))
2552 ePtr<eDVBService> origService;
2553 if (!db->getService(parent, origService))
2555 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2556 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2563 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2564 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2566 m_decoder->setVideoPID(vpid, vpidtype);
2567 selectAudioStream();
2569 if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2570 m_decoder->setSyncPCR(pcrpid);
2572 m_decoder->setSyncPCR(-1);
2576 m_decoder->setTextPID(tpid);
2577 m_teletext_parser->start(program.textPid);
2580 if (vpid > 0 && vpid < 0x2000)
2584 std::string radio_pic;
2585 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2586 m_decoder->setRadioPic(radio_pic);
2594 m_decoder->setAudioChannel(achannel);
2596 /* don't worry about non-existing services, nor pvr services */
2599 /* (audio pid will be set in selectAudioTrack */
2600 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2601 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2602 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2603 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2605 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2606 sendSeekableStateChanged = true;
2608 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2610 if (sendSeekableStateChanged)
2611 m_event((iPlayableService*)this, evSeekableStatusChanged);
2614 void eDVBServicePlay::loadCuesheet()
2616 std::string filename = m_reference.path + ".cuts";
2618 m_cue_entries.clear();
2620 FILE *f = fopen(filename.c_str(), "rb");
2624 eDebug("loading cuts..");
2627 unsigned long long where;
2630 if (!fread(&where, sizeof(where), 1, f))
2632 if (!fread(&what, sizeof(what), 1, f))
2635 #if BYTE_ORDER == LITTLE_ENDIAN
2636 where = bswap_64(where);
2643 m_cue_entries.insert(cueEntry(where, what));
2646 eDebug("%zd entries", m_cue_entries.size());
2648 eDebug("cutfile not found!");
2650 m_cuesheet_changed = 0;
2651 cutlistToCuesheet();
2652 m_event((iPlayableService*)this, evCuesheetChanged);
2655 void eDVBServicePlay::saveCuesheet()
2657 std::string filename = m_reference.path + ".cuts";
2659 FILE *f = fopen(filename.c_str(), "wb");
2663 unsigned long long where;
2666 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2668 #if BYTE_ORDER == BIG_ENDIAN
2671 where = bswap_64(i->where);
2673 what = htonl(i->what);
2674 fwrite(&where, sizeof(where), 1, f);
2675 fwrite(&what, sizeof(what), 1, f);
2681 m_cuesheet_changed = 0;
2684 void eDVBServicePlay::cutlistToCuesheet()
2688 eDebug("no cue sheet");
2693 if (!m_cutlist_enabled)
2695 m_cue->commitSpans();
2696 eDebug("cutlists were disabled");
2700 pts_t in = 0, out = 0, length = 0;
2704 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2706 int have_any_span = 0;
2710 if (i == m_cue_entries.end())
2712 if (!have_any_span && !in)
2716 if (i->what == 0) /* in */
2720 } else if (i->what == 1) /* out */
2722 else /* mark (2) or last play position (3) */
2741 m_cue->addSourceSpan(in, out);
2747 if (i == m_cue_entries.end())
2750 m_cue->commitSpans();
2753 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2755 if (m_subtitle_widget)
2756 disableSubtitles(parent);
2759 int tuplesize = PyTuple_Size(tuple);
2762 if (!PyTuple_Check(tuple))
2768 entry = PyTuple_GET_ITEM(tuple, 0);
2770 if (!PyInt_Check(entry))
2773 type = PyInt_AsLong(entry);
2775 if (type == 1) // teletext subtitles
2777 int page, magazine, pid;
2781 if (!m_teletext_parser)
2783 eDebug("enable teletext subtitles.. no parser !!!");
2787 entry = PyTuple_GET_ITEM(tuple, 1);
2788 if (!PyInt_Check(entry))
2790 pid = PyInt_AsLong(entry);
2792 entry = PyTuple_GET_ITEM(tuple, 2);
2793 if (!PyInt_Check(entry))
2795 page = PyInt_AsLong(entry);
2797 entry = PyTuple_GET_ITEM(tuple, 3);
2798 if (!PyInt_Check(entry))
2800 magazine = PyInt_AsLong(entry);
2802 m_subtitle_widget = new eSubtitleWidget(parent);
2803 m_subtitle_widget->resize(parent->size()); /* full size */
2804 m_teletext_parser->setPageAndMagazine(page, magazine);
2806 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2810 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2811 if (!m_subtitle_parser)
2813 eDebug("enable dvb subtitles.. no parser !!!");
2819 entry = PyTuple_GET_ITEM(tuple, 1);
2820 if (!PyInt_Check(entry))
2822 pid = PyInt_AsLong(entry);
2824 entry = PyTuple_GET_ITEM(tuple, 2);
2825 if (!PyInt_Check(entry))
2827 composition_page_id = PyInt_AsLong(entry);
2829 entry = PyTuple_GET_ITEM(tuple, 3);
2830 if (!PyInt_Check(entry))
2832 ancillary_page_id = PyInt_AsLong(entry);
2834 m_subtitle_widget = new eSubtitleWidget(parent);
2835 m_subtitle_widget->resize(parent->size()); /* full size */
2836 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2838 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2844 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2845 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2846 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2850 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2852 delete m_subtitle_widget;
2853 m_subtitle_widget = 0;
2854 if (m_subtitle_parser)
2856 m_subtitle_parser->stop();
2857 m_dvb_subtitle_pages.clear();
2859 if (m_teletext_parser)
2861 m_teletext_parser->setPageAndMagazine(-1, -1);
2862 m_subtitle_pages.clear();
2865 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2869 PyObject *eDVBServicePlay::getCachedSubtitle()
2873 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2876 unsigned int data = (unsigned int)tmp;
2877 int pid = (data&0xFFFF0000)>>16;
2878 ePyObject tuple = PyTuple_New(4);
2879 eDVBServicePMTHandler::program program;
2880 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2881 if (!h.getProgramInfo(program))
2883 if (program.textPid==pid) // teletext
2884 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2886 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2887 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2888 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2889 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2897 PyObject *eDVBServicePlay::getSubtitleList()
2899 if (!m_teletext_parser)
2902 ePyObject l = PyList_New(0);
2903 std::set<int> added_ttx_pages;
2905 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2906 m_teletext_parser->m_found_subtitle_pages;
2908 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2909 eDVBServicePMTHandler::program program;
2910 if (h.getProgramInfo(program))
2911 eDebug("getting program info failed.");
2914 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2915 it != program.subtitleStreams.end(); ++it)
2917 switch(it->subtitling_type)
2919 case 0x01: // ebu teletext subtitles
2921 int page_number = it->teletext_page_number & 0xFF;
2922 int magazine_number = it->teletext_magazine_number & 7;
2923 int hash = magazine_number << 8 | page_number;
2924 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2926 ePyObject tuple = PyTuple_New(5);
2927 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2928 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2929 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2930 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2931 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2932 PyList_Append(l, tuple);
2934 added_ttx_pages.insert(hash);
2939 case 0x20 ... 0x23: // dvb subtitles
2941 ePyObject tuple = PyTuple_New(5);
2942 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2943 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2944 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2945 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2946 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2947 PyList_Insert(l, 0, tuple);
2955 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2956 it != subs.end(); ++it)
2958 int page_number = it->teletext_page_number & 0xFF;
2959 int magazine_number = it->teletext_magazine_number & 7;
2960 int hash = magazine_number << 8 | page_number;
2961 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2963 ePyObject tuple = PyTuple_New(5);
2964 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2965 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2966 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2967 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2968 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2969 PyList_Append(l, tuple);
2977 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2979 if (m_subtitle_widget)
2983 m_decoder->getPTS(0, pos);
2984 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2985 m_subtitle_pages.push_back(page);
2986 checkSubtitleTiming();
2990 void eDVBServicePlay::checkSubtitleTiming()
2992 eDebug("checkSubtitleTiming");
2993 if (!m_subtitle_widget)
2997 enum { TELETEXT, DVB } type;
2998 eDVBTeletextSubtitlePage page;
2999 eDVBSubtitlePage dvb_page;
3001 if (!m_subtitle_pages.empty())
3003 page = m_subtitle_pages.front();
3005 show_time = page.m_pts;
3007 else if (!m_dvb_subtitle_pages.empty())
3009 dvb_page = m_dvb_subtitle_pages.front();
3011 show_time = dvb_page.m_show_time;
3019 m_decoder->getPTS(0, pos);
3021 eDebug("%lld %lld", pos, show_time);
3022 int diff = show_time - pos;
3023 if (type == TELETEXT && !page.m_have_pts)
3025 eDebug("ttx subtitle page without pts... immediate show");
3030 eDebug("[late (%d ms)]", -diff / 90);
3033 if (abs(diff) > 1800000)
3035 eDebug("[invalid]... immediate show!");
3040 if (type == TELETEXT)
3042 eDebug("display teletext subtitle page %lld", show_time);
3043 m_subtitle_widget->setPage(page);
3044 m_subtitle_pages.pop_front();
3048 eDebug("display dvb subtitle Page %lld", show_time);
3049 m_subtitle_widget->setPage(dvb_page);
3050 m_dvb_subtitle_pages.pop_front();
3054 eDebug("start subtitle delay %d", diff / 90);
3055 m_subtitle_sync_timer->start(diff / 90, 1);
3061 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3063 if (m_subtitle_widget)
3067 m_decoder->getPTS(0, pos);
3068 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3069 m_dvb_subtitle_pages.push_back(p);
3070 checkSubtitleTiming();
3074 int eDVBServicePlay::getAC3Delay()
3077 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3079 return m_decoder->getAC3Delay();
3084 int eDVBServicePlay::getPCMDelay()
3087 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3089 return m_decoder->getPCMDelay();
3094 void eDVBServicePlay::setAC3Delay(int delay)
3097 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3099 std::string config_delay;
3100 int config_delay_int = 0;
3101 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3102 config_delay_int = atoi(config_delay.c_str());
3103 m_decoder->setAC3Delay(delay + config_delay_int);
3107 void eDVBServicePlay::setPCMDelay(int delay)
3110 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3112 std::string config_delay;
3113 int config_delay_int = 0;
3114 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3115 config_delay_int = atoi(config_delay.c_str());
3117 config_delay_int = 0;
3118 m_decoder->setPCMDelay(delay + config_delay_int);
3122 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3124 switch(event.type) {
3125 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3126 m_event((iPlayableService*)this, evVideoSizeChanged);
3128 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3129 m_event((iPlayableService*)this, evVideoFramerateChanged);
3131 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3132 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3139 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3145 PyObject *eDVBServicePlay::getStreamingData()
3147 eDVBServicePMTHandler::program program;
3148 if (m_service_handler.getProgramInfo(program))
3153 ePyObject r = program.createPythonObject();
3154 ePtr<iDVBDemux> demux;
3155 if (!m_service_handler.getDataDemux(demux))
3158 if (!demux->getCADemuxID(demux_id))
3159 PutToDict(r, "demux", demux_id);
3166 DEFINE_REF(eDVBServicePlay)
3168 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3172 case iServiceInformation::sTransponderData:
3173 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3177 return iStaticServiceInformation::getInfoObject(ref, w);
3180 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");