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;
1767 return iServiceInformation::getInfoString(w);
1770 PyObject *eDVBServicePlay::getInfoObject(int w)
1775 return m_service_handler.getCaIds();
1777 return m_service_handler.getCaIds(true);
1778 case sTransponderData:
1779 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1782 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1783 return h.getHbbTVApplications();
1788 return iServiceInformation::getInfoObject(w);
1791 int eDVBServicePlay::getNumberOfTracks()
1793 eDVBServicePMTHandler::program program;
1794 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1795 if (h.getProgramInfo(program))
1797 return program.audioStreams.size();
1800 int eDVBServicePlay::getCurrentTrack()
1802 eDVBServicePMTHandler::program program;
1803 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1804 if (h.getProgramInfo(program))
1807 int max = program.audioStreams.size();
1810 for (i = 0; i < max; ++i)
1811 if (program.audioStreams[i].pid == m_current_audio_pid)
1817 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1819 int ret = selectAudioStream(i);
1821 if (m_decoder->set())
1827 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1829 eDVBServicePMTHandler::program program;
1830 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1832 if (h.getProgramInfo(program))
1835 if (i >= program.audioStreams.size())
1838 info.m_pid = program.audioStreams[i].pid;
1840 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1841 info.m_description = "MPEG";
1842 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1843 info.m_description = "Dolby Digital";
1844 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1845 info.m_description = "Dolby Digital+";
1846 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1847 info.m_description = "AAC";
1848 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1849 info.m_description = "AAC-HE";
1850 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1851 info.m_description = "DTS";
1852 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1853 info.m_description = "DTS-HD";
1855 info.m_description = "???";
1857 if (program.audioStreams[i].component_tag != -1)
1859 ePtr<eServiceEvent> evt;
1860 if (!m_event_handler.getEvent(evt, 0))
1862 ePtr<eComponentData> data;
1863 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1864 info.m_language = data->getText();
1868 if (info.m_language.empty())
1869 info.m_language = program.audioStreams[i].language_code;
1874 int eDVBServicePlay::selectAudioStream(int i)
1876 eDVBServicePMTHandler::program program;
1877 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1878 pts_t position = -1;
1880 if (h.getProgramInfo(program))
1883 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1891 stream = program.defaultAudioStream;
1893 int apid = -1, apidtype = -1;
1895 if (((unsigned int)stream) < program.audioStreams.size())
1897 apid = program.audioStreams[stream].pid;
1898 apidtype = program.audioStreams[stream].type;
1901 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1902 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1904 m_current_audio_pid = apid;
1906 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1908 eDebug("set audio pid failed");
1913 eDebug("seekTo ret %d", seekTo(position));
1917 /* 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 */
1918 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1920 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1922 rdsPid = program.audioStreams[stream].rdsPid;
1923 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1926 ePtr<iDVBDemux> data_demux;
1927 if (!h.getDataDemux(data_demux))
1929 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1930 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1931 m_rds_decoder->start(rdsPid);
1936 /* store new pid as default only when:
1937 a.) we have an entry in the service db for the current service,
1938 b.) we are not playing back something,
1939 c.) we are not selecting the default entry. (we wouldn't change
1940 anything in the best case, or destroy the default setting in
1941 case the real default is not yet available.)
1943 if (m_dvb_service && ((i != -1)
1944 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1946 if (apidtype == eDVBAudio::aMPEG)
1948 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1949 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1951 else if (apidtype == eDVBAudio::aAC3)
1953 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1954 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1958 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1959 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1963 h.resetCachedProgram();
1968 int eDVBServicePlay::getCurrentChannel()
1970 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1973 RESULT eDVBServicePlay::selectChannel(int i)
1975 if (i < LEFT || i > RIGHT || i == STEREO)
1978 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1980 m_decoder->setAudioChannel(i);
1984 std::string eDVBServicePlay::getText(int x)
1990 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1992 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1997 void eDVBServicePlay::rdsDecoderEvent(int what)
2001 case eDVBRdsDecoder::RadioTextChanged:
2002 m_event((iPlayableService*)this, evUpdatedRadioText);
2004 case eDVBRdsDecoder::RtpTextChanged:
2005 m_event((iPlayableService*)this, evUpdatedRtpText);
2007 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2008 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2010 case eDVBRdsDecoder::RecvRassSlidePic:
2011 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2016 void eDVBServicePlay::showRassSlidePicture()
2022 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2023 if (rass_slide_pic.length())
2024 m_decoder->showSinglePic(rass_slide_pic.c_str());
2026 eDebug("empty filename for rass slide picture received!!");
2029 eDebug("no MPEG Decoder to show iframes avail");
2032 eDebug("showRassSlidePicture called.. but not decoder");
2035 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2041 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2042 if (rass_interactive_pic.length())
2043 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2045 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2048 eDebug("no MPEG Decoder to show iframes avail");
2051 eDebug("showRassInteractivePic called.. but not decoder");
2054 ePyObject eDVBServicePlay::getRassInteractiveMask()
2057 return m_rds_decoder->getRassPictureMask();
2061 int eDVBServiceBase::getFrontendInfo(int w)
2063 eUsePtr<iDVBChannel> channel;
2064 if(m_service_handler.getChannel(channel))
2066 ePtr<iDVBFrontend> fe;
2067 if(channel->getFrontend(fe))
2069 return fe->readFrontendData(w);
2072 PyObject *eDVBServiceBase::getFrontendData()
2074 ePyObject ret = PyDict_New();
2077 eUsePtr<iDVBChannel> channel;
2078 if(!m_service_handler.getChannel(channel))
2080 ePtr<iDVBFrontend> fe;
2081 if(!channel->getFrontend(fe))
2082 fe->getFrontendData(ret);
2090 PyObject *eDVBServiceBase::getFrontendStatus()
2092 ePyObject ret = PyDict_New();
2095 eUsePtr<iDVBChannel> channel;
2096 if(!m_service_handler.getChannel(channel))
2098 ePtr<iDVBFrontend> fe;
2099 if(!channel->getFrontend(fe))
2100 fe->getFrontendStatus(ret);
2108 PyObject *eDVBServiceBase::getTransponderData(bool original)
2110 ePyObject ret = PyDict_New();
2113 eUsePtr<iDVBChannel> channel;
2114 if(!m_service_handler.getChannel(channel))
2116 ePtr<iDVBFrontend> fe;
2117 if(!channel->getFrontend(fe))
2118 fe->getTransponderData(ret, original);
2126 PyObject *eDVBServiceBase::getAll(bool original)
2128 ePyObject ret = getTransponderData(original);
2131 eUsePtr<iDVBChannel> channel;
2132 if(!m_service_handler.getChannel(channel))
2134 ePtr<iDVBFrontend> fe;
2135 if(!channel->getFrontend(fe))
2137 fe->getFrontendData(ret);
2138 fe->getFrontendStatus(ret);
2145 int eDVBServicePlay::getNumberOfSubservices()
2147 ePtr<eServiceEvent> evt;
2148 if (!m_event_handler.getEvent(evt, 0))
2149 return evt->getNumOfLinkageServices();
2153 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2155 ePtr<eServiceEvent> evt;
2156 if (!m_event_handler.getEvent(evt, 0))
2158 if (!evt->getLinkageService(sub, m_reference, n))
2161 sub.type=eServiceReference::idInvalid;
2165 RESULT eDVBServicePlay::startTimeshift()
2167 ePtr<iDVBDemux> demux;
2169 eDebug("Start timeshift!");
2171 if (m_timeshift_enabled)
2174 /* start recording with the data demux. */
2175 if (m_service_handler.getDataDemux(demux))
2178 demux->createTSRecorder(m_record);
2183 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2184 eDebug("could not query ts path");
2187 tspath.append("/timeshift.XXXXXX");
2189 templ = new char[tspath.length() + 1];
2190 strcpy(templ, tspath.c_str());
2192 m_timeshift_fd = mkstemp(templ);
2193 m_timeshift_file = std::string(templ);
2195 eDebug("recording to %s", templ);
2199 if (m_timeshift_fd < 0)
2205 m_record->setTargetFD(m_timeshift_fd);
2207 m_timeshift_enabled = 1;
2209 updateTimeshiftPids();
2215 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2217 if (!m_timeshift_enabled)
2223 m_timeshift_enabled = 0;
2228 close(m_timeshift_fd);
2229 eDebug("remove timeshift file");
2230 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2235 int eDVBServicePlay::isTimeshiftActive()
2237 return m_timeshift_enabled && m_timeshift_active;
2240 RESULT eDVBServicePlay::activateTimeshift()
2242 if (!m_timeshift_enabled)
2245 if (!m_timeshift_active)
2247 switchToTimeshift();
2254 PyObject *eDVBServicePlay::getCutList()
2256 ePyObject list = PyList_New(0);
2258 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2260 ePyObject tuple = PyTuple_New(2);
2261 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2262 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2263 PyList_Append(list, tuple);
2270 void eDVBServicePlay::setCutList(ePyObject list)
2272 if (!PyList_Check(list))
2274 int size = PyList_Size(list);
2277 m_cue_entries.clear();
2279 for (i=0; i<size; ++i)
2281 ePyObject tuple = PyList_GET_ITEM(list, i);
2282 if (!PyTuple_Check(tuple))
2284 eDebug("non-tuple in cutlist");
2287 if (PyTuple_Size(tuple) != 2)
2289 eDebug("cutlist entries need to be a 2-tuple");
2292 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2293 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2295 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2298 pts_t pts = PyLong_AsLongLong(ppts);
2299 int type = PyInt_AsLong(ptype);
2300 m_cue_entries.insert(cueEntry(pts, type));
2301 eDebug("adding %08llx, %d", pts, type);
2303 m_cuesheet_changed = 1;
2305 cutlistToCuesheet();
2306 m_event((iPlayableService*)this, evCuesheetChanged);
2309 void eDVBServicePlay::setCutListEnable(int enable)
2311 m_cutlist_enabled = enable;
2312 cutlistToCuesheet();
2315 void eDVBServicePlay::updateTimeshiftPids()
2320 eDVBServicePMTHandler::program program;
2321 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2323 if (h.getProgramInfo(program))
2327 std::set<int> pids_to_record;
2328 pids_to_record.insert(0); // PAT
2329 if (program.pmtPid != -1)
2330 pids_to_record.insert(program.pmtPid); // PMT
2332 if (program.textPid != -1)
2333 pids_to_record.insert(program.textPid); // Videotext
2335 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2336 i(program.videoStreams.begin());
2337 i != program.videoStreams.end(); ++i)
2338 pids_to_record.insert(i->pid);
2340 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2341 i(program.audioStreams.begin());
2342 i != program.audioStreams.end(); ++i)
2343 pids_to_record.insert(i->pid);
2345 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2346 i(program.subtitleStreams.begin());
2347 i != program.subtitleStreams.end(); ++i)
2348 pids_to_record.insert(i->pid);
2350 std::set<int> new_pids, obsolete_pids;
2352 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2353 m_pids_active.begin(), m_pids_active.end(),
2354 std::inserter(new_pids, new_pids.begin()));
2356 std::set_difference(
2357 m_pids_active.begin(), m_pids_active.end(),
2358 pids_to_record.begin(), pids_to_record.end(),
2359 std::inserter(new_pids, new_pids.begin())
2362 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2363 m_record->addPID(*i);
2365 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2366 m_record->removePID(*i);
2370 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2372 m_timeshift_file_next = f;
2376 void eDVBServicePlay::switchToLive()
2378 if (!m_timeshift_active)
2381 eDebug("SwitchToLive");
2385 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2387 /* free the timeshift service handler, we need the resources */
2388 m_service_handler_timeshift.free();
2390 updateDecoder(true);
2393 void eDVBServicePlay::resetTimeshift(int start)
2398 m_teletext_parser = 0;
2400 m_subtitle_parser = 0;
2401 m_new_subtitle_page_connection = 0;
2402 m_new_dvb_subtitle_page_connection = 0;
2403 m_rds_decoder_event_connection = 0;
2404 m_video_event_connection = 0;
2405 m_timeshift_changed = 1;
2406 m_timeshift_file_next.clear();
2410 m_cue = new eCueSheet();
2411 m_timeshift_active = 1;
2414 m_timeshift_active = 0;
2417 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2421 eHttpStream *f = new eHttpStream();
2422 f->open(ref.path.c_str());
2423 return ePtr<iTsSource>(f);
2427 eRawFile *f = new eRawFile();
2428 f->open(ref.path.c_str());
2429 return ePtr<iTsSource>(f);
2433 void eDVBServicePlay::switchToTimeshift()
2435 if (m_timeshift_active)
2440 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2441 r.path = m_timeshift_file;
2443 m_cue->seekTo(0, -1000);
2445 ePtr<iTsSource> source = createTsSource(r);
2446 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 */
2448 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2450 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2453 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2455 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2456 bool mustPlay = false;
2458 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2460 eDVBServicePMTHandler::program program;
2461 if (h.getProgramInfo(program))
2462 eDebug("getting program info failed.");
2465 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2466 if (!program.videoStreams.empty())
2468 eDebugNoNewLine(" (");
2469 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2470 i(program.videoStreams.begin());
2471 i != program.videoStreams.end(); ++i)
2478 if (i != program.videoStreams.begin())
2479 eDebugNoNewLine(", ");
2480 eDebugNoNewLine("%04x", i->pid);
2482 eDebugNoNewLine(")");
2484 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2485 if (!program.audioStreams.empty())
2487 eDebugNoNewLine(" (");
2488 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2489 i(program.audioStreams.begin());
2490 i != program.audioStreams.end(); ++i)
2492 if (i != program.audioStreams.begin())
2493 eDebugNoNewLine(", ");
2494 eDebugNoNewLine("%04x", i->pid);
2496 eDebugNoNewLine(")");
2498 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2499 pcrpid = program.pcrPid;
2500 eDebug(", and the text pid is %04x", program.textPid);
2501 tpid = program.textPid;
2506 h.getDecodeDemux(m_decode_demux);
2509 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2511 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2514 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2515 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2516 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2517 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2518 if (m_timeshift_changed)
2520 ePyObject subs = getCachedSubtitle();
2521 if (subs != Py_None)
2523 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2524 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2525 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2526 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2527 if (type == 0) // dvb
2528 m_subtitle_parser->start(pid, comp_page, anc_page);
2529 else if (type == 1) // ttx
2530 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2537 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2541 m_timeshift_changed = 0;
2545 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2548 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2549 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2550 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2554 eServiceReferenceDVB ref;
2555 m_service_handler.getServiceReference(ref);
2556 eServiceReferenceDVB parent = ref.getParentServiceReference();
2561 ePtr<eDVBResourceManager> res_mgr;
2562 if (!eDVBResourceManager::getInstance(res_mgr))
2564 ePtr<iDVBChannelList> db;
2565 if (!res_mgr->getChannelList(db))
2567 ePtr<eDVBService> origService;
2568 if (!db->getService(parent, origService))
2570 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2571 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2578 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2579 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2581 m_decoder->setVideoPID(vpid, vpidtype);
2582 selectAudioStream();
2584 if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2585 m_decoder->setSyncPCR(pcrpid);
2587 m_decoder->setSyncPCR(-1);
2591 m_decoder->setTextPID(tpid);
2592 m_teletext_parser->start(program.textPid);
2595 if (vpid > 0 && vpid < 0x2000)
2599 std::string radio_pic;
2600 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2601 m_decoder->setRadioPic(radio_pic);
2609 m_decoder->setAudioChannel(achannel);
2611 /* don't worry about non-existing services, nor pvr services */
2614 /* (audio pid will be set in selectAudioTrack */
2615 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2616 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2617 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2618 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2620 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2621 sendSeekableStateChanged = true;
2623 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2625 if (sendSeekableStateChanged)
2626 m_event((iPlayableService*)this, evSeekableStatusChanged);
2629 void eDVBServicePlay::loadCuesheet()
2631 std::string filename = m_reference.path + ".cuts";
2633 m_cue_entries.clear();
2635 FILE *f = fopen(filename.c_str(), "rb");
2639 eDebug("loading cuts..");
2642 unsigned long long where;
2645 if (!fread(&where, sizeof(where), 1, f))
2647 if (!fread(&what, sizeof(what), 1, f))
2650 #if BYTE_ORDER == LITTLE_ENDIAN
2651 where = bswap_64(where);
2658 m_cue_entries.insert(cueEntry(where, what));
2661 eDebug("%zd entries", m_cue_entries.size());
2663 eDebug("cutfile not found!");
2665 m_cuesheet_changed = 0;
2666 cutlistToCuesheet();
2667 m_event((iPlayableService*)this, evCuesheetChanged);
2670 void eDVBServicePlay::saveCuesheet()
2672 std::string filename = m_reference.path + ".cuts";
2674 FILE *f = fopen(filename.c_str(), "wb");
2678 unsigned long long where;
2681 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2683 #if BYTE_ORDER == BIG_ENDIAN
2686 where = bswap_64(i->where);
2688 what = htonl(i->what);
2689 fwrite(&where, sizeof(where), 1, f);
2690 fwrite(&what, sizeof(what), 1, f);
2696 m_cuesheet_changed = 0;
2699 void eDVBServicePlay::cutlistToCuesheet()
2703 eDebug("no cue sheet");
2708 if (!m_cutlist_enabled)
2710 m_cue->commitSpans();
2711 eDebug("cutlists were disabled");
2715 pts_t in = 0, out = 0, length = 0;
2719 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2721 int have_any_span = 0;
2725 if (i == m_cue_entries.end())
2727 if (!have_any_span && !in)
2731 if (i->what == 0) /* in */
2735 } else if (i->what == 1) /* out */
2737 else /* mark (2) or last play position (3) */
2756 m_cue->addSourceSpan(in, out);
2762 if (i == m_cue_entries.end())
2765 m_cue->commitSpans();
2768 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2770 if (m_subtitle_widget)
2771 disableSubtitles(parent);
2774 int tuplesize = PyTuple_Size(tuple);
2777 if (!PyTuple_Check(tuple))
2783 entry = PyTuple_GET_ITEM(tuple, 0);
2785 if (!PyInt_Check(entry))
2788 type = PyInt_AsLong(entry);
2790 if (type == 1) // teletext subtitles
2792 int page, magazine, pid;
2796 if (!m_teletext_parser)
2798 eDebug("enable teletext subtitles.. no parser !!!");
2802 entry = PyTuple_GET_ITEM(tuple, 1);
2803 if (!PyInt_Check(entry))
2805 pid = PyInt_AsLong(entry);
2807 entry = PyTuple_GET_ITEM(tuple, 2);
2808 if (!PyInt_Check(entry))
2810 page = PyInt_AsLong(entry);
2812 entry = PyTuple_GET_ITEM(tuple, 3);
2813 if (!PyInt_Check(entry))
2815 magazine = PyInt_AsLong(entry);
2817 m_subtitle_widget = new eSubtitleWidget(parent);
2818 m_subtitle_widget->resize(parent->size()); /* full size */
2819 m_teletext_parser->setPageAndMagazine(page, magazine);
2821 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2825 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2826 if (!m_subtitle_parser)
2828 eDebug("enable dvb subtitles.. no parser !!!");
2834 entry = PyTuple_GET_ITEM(tuple, 1);
2835 if (!PyInt_Check(entry))
2837 pid = PyInt_AsLong(entry);
2839 entry = PyTuple_GET_ITEM(tuple, 2);
2840 if (!PyInt_Check(entry))
2842 composition_page_id = PyInt_AsLong(entry);
2844 entry = PyTuple_GET_ITEM(tuple, 3);
2845 if (!PyInt_Check(entry))
2847 ancillary_page_id = PyInt_AsLong(entry);
2849 m_subtitle_widget = new eSubtitleWidget(parent);
2850 m_subtitle_widget->resize(parent->size()); /* full size */
2851 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2853 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2859 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2860 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2861 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2865 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2867 delete m_subtitle_widget;
2868 m_subtitle_widget = 0;
2869 if (m_subtitle_parser)
2871 m_subtitle_parser->stop();
2872 m_dvb_subtitle_pages.clear();
2874 if (m_teletext_parser)
2876 m_teletext_parser->setPageAndMagazine(-1, -1);
2877 m_subtitle_pages.clear();
2880 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2884 PyObject *eDVBServicePlay::getCachedSubtitle()
2888 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2891 unsigned int data = (unsigned int)tmp;
2892 int pid = (data&0xFFFF0000)>>16;
2893 ePyObject tuple = PyTuple_New(4);
2894 eDVBServicePMTHandler::program program;
2895 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2896 if (!h.getProgramInfo(program))
2898 if (program.textPid==pid) // teletext
2899 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2901 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2902 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2903 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2904 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2912 PyObject *eDVBServicePlay::getSubtitleList()
2914 if (!m_teletext_parser)
2917 ePyObject l = PyList_New(0);
2918 std::set<int> added_ttx_pages;
2920 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2921 m_teletext_parser->m_found_subtitle_pages;
2923 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2924 eDVBServicePMTHandler::program program;
2925 if (h.getProgramInfo(program))
2926 eDebug("getting program info failed.");
2929 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2930 it != program.subtitleStreams.end(); ++it)
2932 switch(it->subtitling_type)
2934 case 0x01: // ebu teletext subtitles
2936 int page_number = it->teletext_page_number & 0xFF;
2937 int magazine_number = it->teletext_magazine_number & 7;
2938 int hash = magazine_number << 8 | page_number;
2939 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2941 ePyObject tuple = PyTuple_New(5);
2942 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2943 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2944 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2945 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2946 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2947 PyList_Append(l, tuple);
2949 added_ttx_pages.insert(hash);
2954 case 0x20 ... 0x23: // dvb subtitles
2956 ePyObject tuple = PyTuple_New(5);
2957 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2958 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2959 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2960 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2961 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2962 PyList_Insert(l, 0, tuple);
2970 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2971 it != subs.end(); ++it)
2973 int page_number = it->teletext_page_number & 0xFF;
2974 int magazine_number = it->teletext_magazine_number & 7;
2975 int hash = magazine_number << 8 | page_number;
2976 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2978 ePyObject tuple = PyTuple_New(5);
2979 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2980 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2981 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2982 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2983 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2984 PyList_Append(l, tuple);
2992 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2994 if (m_subtitle_widget)
2998 m_decoder->getPTS(0, pos);
2999 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3000 m_subtitle_pages.push_back(page);
3001 checkSubtitleTiming();
3005 void eDVBServicePlay::checkSubtitleTiming()
3007 eDebug("checkSubtitleTiming");
3008 if (!m_subtitle_widget)
3012 enum { TELETEXT, DVB } type;
3013 eDVBTeletextSubtitlePage page;
3014 eDVBSubtitlePage dvb_page;
3016 if (!m_subtitle_pages.empty())
3018 page = m_subtitle_pages.front();
3020 show_time = page.m_pts;
3022 else if (!m_dvb_subtitle_pages.empty())
3024 dvb_page = m_dvb_subtitle_pages.front();
3026 show_time = dvb_page.m_show_time;
3034 m_decoder->getPTS(0, pos);
3036 eDebug("%lld %lld", pos, show_time);
3037 int diff = show_time - pos;
3038 if (type == TELETEXT && !page.m_have_pts)
3040 eDebug("ttx subtitle page without pts... immediate show");
3045 eDebug("[late (%d ms)]", -diff / 90);
3048 if (abs(diff) > 1800000)
3050 eDebug("[invalid]... immediate show!");
3055 if (type == TELETEXT)
3057 eDebug("display teletext subtitle page %lld", show_time);
3058 m_subtitle_widget->setPage(page);
3059 m_subtitle_pages.pop_front();
3063 eDebug("display dvb subtitle Page %lld", show_time);
3064 m_subtitle_widget->setPage(dvb_page);
3065 m_dvb_subtitle_pages.pop_front();
3069 eDebug("start subtitle delay %d", diff / 90);
3070 m_subtitle_sync_timer->start(diff / 90, 1);
3076 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3078 if (m_subtitle_widget)
3082 m_decoder->getPTS(0, pos);
3083 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3084 m_dvb_subtitle_pages.push_back(p);
3085 checkSubtitleTiming();
3089 int eDVBServicePlay::getAC3Delay()
3092 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3094 return m_decoder->getAC3Delay();
3099 int eDVBServicePlay::getPCMDelay()
3102 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3104 return m_decoder->getPCMDelay();
3109 void eDVBServicePlay::setAC3Delay(int delay)
3112 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3114 std::string config_delay;
3115 int config_delay_int = 0;
3116 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3117 config_delay_int = atoi(config_delay.c_str());
3118 m_decoder->setAC3Delay(delay + config_delay_int);
3122 void eDVBServicePlay::setPCMDelay(int delay)
3125 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3127 std::string config_delay;
3128 int config_delay_int = 0;
3129 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3130 config_delay_int = atoi(config_delay.c_str());
3132 config_delay_int = 0;
3133 m_decoder->setPCMDelay(delay + config_delay_int);
3137 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3139 switch(event.type) {
3140 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3141 m_event((iPlayableService*)this, evVideoSizeChanged);
3143 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3144 m_event((iPlayableService*)this, evVideoFramerateChanged);
3146 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3147 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3154 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3160 PyObject *eDVBServicePlay::getStreamingData()
3162 eDVBServicePMTHandler::program program;
3163 if (m_service_handler.getProgramInfo(program))
3168 ePyObject r = program.createPythonObject();
3169 ePtr<iDVBDemux> demux;
3170 if (!m_service_handler.getDataDemux(demux))
3173 if (!demux->getCADemuxID(demux_id))
3174 PutToDict(r, "demux", demux_id);
3181 DEFINE_REF(eDVBServicePlay)
3183 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3187 case iServiceInformation::sTransponderData:
3188 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3192 return iStaticServiceInformation::getInfoObject(ref, w);
3195 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");