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
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
106 if (r.type == eServiceReference::idDVB)
108 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
111 case iServiceInformation::sTransponderData:
113 ePtr<eDVBResourceManager> res;
114 if (!eDVBResourceManager::getInstance(res))
116 ePtr<iDVBChannelList> db;
117 if (!res->getChannelList(db))
120 ref.getChannelID(chid);
121 ePtr<iDVBFrontendParameters> feparm;
122 if (!db->getChannelFrontendData(chid, feparm))
125 if (!feparm->getSystem(system))
127 ePyObject dict = PyDict_New();
130 case iDVBFrontend::feSatellite:
132 eDVBFrontendParametersSatellite s;
134 PutSatelliteDataToDict(dict, s);
137 case iDVBFrontend::feTerrestrial:
139 eDVBFrontendParametersTerrestrial t;
141 PutTerrestrialDataToDict(dict, t);
144 case iDVBFrontend::feCable:
146 eDVBFrontendParametersCable c;
148 PutCableDataToDict(dict, c);
152 eDebug("unknown frontend type %d", system);
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
171 ePtr<iDVBChannelList> db;
172 ePtr<eDVBResourceManager> res;
175 if ((err = eDVBResourceManager::getInstance(res)) != 0)
177 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
180 if ((err = res->getChannelList(db)) != 0)
182 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
187 if ((err = db->getBouquet(ref, bouquet)) != 0)
189 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
193 if ( bouquet && bouquet->m_bouquet_name.length() )
195 name = bouquet->m_bouquet_name;
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
204 if (ref.flags & eServiceReference::isGroup)
206 ePtr<iDVBChannelList> db;
207 ePtr<eDVBResourceManager> res;
209 if (eDVBResourceManager::getInstance(res))
211 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
215 if (res->getChannelList(db))
217 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
222 if (db->getBouquet(ref, bouquet))
224 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
228 int prio_order = eDVBFrontend::getTypePriorityOrder();
230 eDVBChannelID chid, chid_ignore;
231 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
234 static unsigned char prio_map[6][3] = {
235 { 3, 2, 1 }, // -S -C -T
236 { 3, 1, 2 }, // -S -T -C
237 { 2, 3, 1 }, // -C -S -T
238 { 1, 3, 2 }, // -C -T -S
239 { 1, 2, 3 }, // -T -C -S
240 { 2, 1, 3 } // -T -S -C
242 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
248 case 30000: // cached DVB-T channel
249 case 1: // DVB-T frontend
250 tmp = prio_map[prio_order][2];
252 case 40000: // cached DVB-C channel
254 tmp = prio_map[prio_order][1];
257 tmp = prio_map[prio_order][0];
262 m_playable_service = *it;
269 m_playable_service = eServiceReference();
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
278 #include <lib/dvb/epgcache.h>
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
282 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
287 DECLARE_REF(eStaticServiceDVBPVRInformation);
288 eServiceReference m_ref;
289 eDVBMetaParser m_parser;
291 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292 RESULT getName(const eServiceReference &ref, std::string &name);
293 int getLength(const eServiceReference &ref);
294 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296 int getInfo(const eServiceReference &ref, int w);
297 std::string getInfoString(const eServiceReference &ref,int w);
298 PyObject *getInfoObject(const eServiceReference &r, int what);
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
306 m_parser.parseFile(ref.path);
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
311 ASSERT(ref == m_ref);
312 if (m_parser.m_name.size())
313 name = m_parser.m_name;
317 size_t n = name.rfind('/');
318 if (n != std::string::npos)
319 name = name.substr(n + 1);
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
326 ASSERT(ref == m_ref);
331 stat(ref.path.c_str(), &s);
333 if (tstools.openFile(ref.path.c_str(), 1))
336 /* check if cached data is still valid */
337 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338 return m_parser.m_length / 90000;
340 /* open again, this time with stream info */
341 if (tstools.openFile(ref.path.c_str()))
344 /* otherwise, re-calc length and update meta file */
346 if (tstools.calcLen(len))
349 m_parser.m_length = len;
350 m_parser.m_filesize = s.st_size;
351 m_parser.updateMeta(ref.path);
352 return m_parser.m_length / 90000;
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
359 case iServiceInformation::sDescription:
360 return iServiceInformation::resIsString;
361 case iServiceInformation::sServiceref:
362 return iServiceInformation::resIsString;
363 case iServiceInformation::sFileSize:
364 return m_parser.m_filesize;
365 case iServiceInformation::sTimeCreate:
366 if (m_parser.m_time_create)
367 return m_parser.m_time_create;
369 return iServiceInformation::resNA;
371 return iServiceInformation::resNA;
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
379 case iServiceInformation::sDescription:
380 return m_parser.m_description;
381 case iServiceInformation::sServiceref:
382 return m_parser.m_ref.toString();
383 case iServiceInformation::sTags:
384 return m_parser.m_tags;
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
394 case iServiceInformation::sFileSize:
395 return PyLong_FromLongLong(m_parser.m_filesize);
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
403 if (!ref.path.empty())
405 ePtr<eServiceEvent> event = new eServiceEvent;
406 std::string filename = ref.path;
407 filename.erase(filename.length()-2, 2);
409 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
421 DECLARE_REF(eDVBPVRServiceOfflineOperations);
422 eServiceReferenceDVB m_ref;
424 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
426 RESULT deleteFromDisk(int simulate);
427 RESULT getListOfFilenames(std::list<std::string> &);
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
443 std::list<std::string> res;
444 if (getListOfFilenames(res))
447 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
449 eDebug("FATAL !! can't get background file eraser");
451 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
453 eDebug("Removing %s...", i->c_str());
455 eraser->erase(i->c_str());
457 ::unlink(i->c_str());
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
467 res.push_back(m_ref.path);
469 // handling for old splitted recordings (enigma 1)
474 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
476 if (stat(buf, &s) < 0)
481 res.push_back(m_ref.path + ".meta");
482 res.push_back(m_ref.path + ".ap");
483 res.push_back(m_ref.path + ".sc");
484 res.push_back(m_ref.path + ".cuts");
485 std::string tmp = m_ref.path;
486 tmp.erase(m_ref.path.length()-3);
487 res.push_back(tmp + ".eit");
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
493 const char *filename = m_ref.path.c_str();
494 eDebug("reindexing %s...", filename);
496 eMPEGStreamInformation info;
497 eMPEGStreamParserTS parser(info);
499 info.startSave(filename);
503 int err = f.open(m_ref.path.c_str(), 0);
508 off_t length = f.length();
509 unsigned char buffer[188*256*4];
512 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513 int r = f.read(offset, buffer, sizeof(buffer));
519 parser.parseData(offset, buffer, r);
528 DEFINE_REF(eServiceFactoryDVB)
530 eServiceFactoryDVB::eServiceFactoryDVB()
532 ePtr<eServiceCenter> sc;
534 eServiceCenter::getPrivInstance(sc);
537 std::list<std::string> extensions;
538 extensions.push_back("ts");
539 extensions.push_back("trp");
540 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
543 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
544 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
547 eServiceFactoryDVB::~eServiceFactoryDVB()
549 ePtr<eServiceCenter> sc;
551 eServiceCenter::getPrivInstance(sc);
553 sc->removeServiceFactory(eServiceFactoryDVB::id);
556 DEFINE_REF(eDVBServiceList);
558 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
562 eDVBServiceList::~eDVBServiceList()
566 RESULT eDVBServiceList::startQuery()
568 ePtr<iDVBChannelList> db;
569 ePtr<eDVBResourceManager> res;
572 if ((err = eDVBResourceManager::getInstance(res)) != 0)
574 eDebug("no resource manager");
577 if ((err = res->getChannelList(db)) != 0)
579 eDebug("no channel list");
583 ePtr<eDVBChannelQuery> q;
585 if (!m_parent.path.empty())
587 eDVBChannelQuery::compile(q, m_parent.path);
590 eDebug("compile query failed");
595 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
597 eDebug("startQuery failed");
604 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
606 eServiceReferenceDVB ref;
611 while (!m_query->getNextResult(ref))
615 list.sort(iListableServiceCompare(this));
620 // The first argument of this function is a format string to specify the order and
621 // the content of the returned list
622 // useable format options are
623 // R = Service Reference (as swig object .. this is very slow)
624 // S = Service Reference (as python string object .. same as ref.toString())
625 // C = Service Reference (as python string object .. same as ref.toCompareString())
626 // N = Service Name (as python string object)
627 // n = Short Service Name (short name brakets used) (as python string object)
628 // when exactly one return value per service is selected in the format string,
629 // then each value is directly a list entry
630 // when more than one value is returned per service, then the list is a list of
632 // unknown format string chars are returned as python None values !
633 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
636 std::list<eServiceReference> tmplist;
639 if (!format || !(retcount=strlen(format)))
640 format = "R"; // just return service reference swig object ...
642 if (!getContent(tmplist, sorted))
644 int services=tmplist.size();
645 ePtr<iStaticServiceInformation> sptr;
646 eServiceCenterPtr service_center;
648 if (strchr(format, 'N') || strchr(format, 'n'))
649 eServiceCenter::getPrivInstance(service_center);
651 ret = PyList_New(services);
652 std::list<eServiceReference>::iterator it(tmplist.begin());
654 for (int cnt=0; cnt < services; ++cnt)
656 eServiceReference &ref=*it++;
657 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
658 for (int i=0; i < retcount; ++i)
663 case 'R': // service reference (swig)object
664 tmp = NEW_eServiceReference(ref);
666 case 'C': // service reference compare string
667 tmp = PyString_FromString(ref.toCompareString().c_str());
669 case 'S': // service reference string
670 tmp = PyString_FromString(ref.toString().c_str());
672 case 'N': // service name
675 service_center->info(ref, sptr);
679 sptr->getName(ref, name);
681 // filter short name brakets
683 while((pos = name.find("\xc2\x86")) != std::string::npos)
685 while((pos = name.find("\xc2\x87")) != std::string::npos)
689 tmp = PyString_FromString(name.c_str());
693 tmp = PyString_FromString("<n/a>");
695 case 'n': // short service name
698 service_center->info(ref, sptr);
702 sptr->getName(ref, name);
703 name = buildShortName(name);
705 tmp = PyString_FromString(name.c_str());
709 tmp = PyString_FromString("<n/a>");
722 PyTuple_SET_ITEM(tuple, i, tmp);
724 PyList_SET_ITEM(ret, cnt, tmp);
728 PyList_SET_ITEM(ret, cnt, tuple);
731 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
734 RESULT eDVBServiceList::getNext(eServiceReference &ref)
739 return m_query->getNextResult((eServiceReferenceDVB&)ref);
742 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
744 if (m_parent.flags & eServiceReference::canDescent) // bouquet
746 ePtr<iDVBChannelList> db;
747 ePtr<eDVBResourceManager> resm;
749 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
752 if (db->getBouquet(m_parent, m_bouquet) != 0)
763 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
767 return m_bouquet->addService(ref, before);
770 RESULT eDVBServiceList::removeService(eServiceReference &ref)
774 return m_bouquet->removeService(ref);
777 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
781 return m_bouquet->moveService(ref, pos);
784 RESULT eDVBServiceList::flushChanges()
788 return m_bouquet->flushChanges();
791 RESULT eDVBServiceList::setListName(const std::string &name)
795 return m_bouquet->setListName(name);
798 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
800 ePtr<eDVBService> service;
801 int r = lookupService(service, ref);
804 // check resources...
805 ptr = new eDVBServicePlay(ref, service);
809 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
811 if (ref.path.empty())
813 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
822 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
824 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
825 if (list->startQuery())
835 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
837 /* is a listable service? */
838 if (ref.flags & eServiceReference::canDescent) // bouquet
840 if ( !ref.name.empty() ) // satellites or providers list
841 ptr = m_StaticServiceDVBInfo;
842 else // a dvb bouquet
843 ptr = m_StaticServiceDVBBouquetInfo;
845 else if (!ref.path.empty()) /* do we have a PVR service? */
846 ptr = new eStaticServiceDVBPVRInformation(ref);
847 else // normal dvb service
849 ePtr<eDVBService> service;
850 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
851 ptr = m_StaticServiceDVBInfo;
853 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
859 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
861 if (ref.path.empty())
867 ptr = new eDVBPVRServiceOfflineOperations(ref);
872 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
874 if (!ref.path.empty()) // playback
876 eDVBMetaParser parser;
877 int ret=parser.parseFile(ref.path);
878 service = new eDVBService;
880 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
884 // TODO: handle the listing itself
885 // if (ref.... == -1) .. return "... bouquets ...";
886 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
888 ePtr<iDVBChannelList> db;
889 ePtr<eDVBResourceManager> res;
892 if ((err = eDVBResourceManager::getInstance(res)) != 0)
894 eDebug("no resource manager");
897 if ((err = res->getChannelList(db)) != 0)
899 eDebug("no channel list");
903 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
904 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
906 eDebug("getService failed!");
914 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
915 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
918 m_is_pvr = !m_reference.path.empty();
920 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
921 m_skipmode = m_fastforward = m_slowmotion = 0;
923 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
924 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
925 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
927 m_cuesheet_changed = 0;
928 m_cutlist_enabled = 1;
930 m_subtitle_widget = 0;
934 m_subtitle_sync_timer = eTimer::create(eApp);
936 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
939 eDVBServicePlay::~eDVBServicePlay()
944 int ret=meta.parseFile(m_reference.path);
948 meta.m_service_data="";
949 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
950 meta.m_service_data += tmp;
952 for (int x=0; x < eDVBService::cacheMax; ++x)
954 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
957 sprintf(tmp, ",c:%02d%04x", x, entry);
958 meta.m_service_data += tmp;
961 meta.updateMeta(m_reference.path);
964 delete m_subtitle_widget;
967 void eDVBServicePlay::gotNewEvent()
971 ePtr<eServiceEvent> m_event_now, m_event_next;
972 getEvent(m_event_now, 0);
973 getEvent(m_event_next, 1);
976 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
978 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
980 m_event((iPlayableService*)this, evUpdatedEventInfo);
983 void eDVBServicePlay::serviceEvent(int event)
985 m_tune_state = event;
989 case eDVBServicePMTHandler::eventTuned:
991 ePtr<iDVBDemux> m_demux;
992 if (!m_service_handler.getDataDemux(m_demux))
994 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
995 int sid = ref.getParentServiceID().get();
997 sid = ref.getServiceID().get();
998 if ( ref.getParentTransportStreamID().get() &&
999 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1000 m_event_handler.startOther(m_demux, sid);
1002 m_event_handler.start(m_demux, sid);
1004 m_event((iPlayableService*)this, evTunedIn);
1007 case eDVBServicePMTHandler::eventNoResources:
1008 case eDVBServicePMTHandler::eventNoPAT:
1009 case eDVBServicePMTHandler::eventNoPATEntry:
1010 case eDVBServicePMTHandler::eventNoPMT:
1011 case eDVBServicePMTHandler::eventTuneFailed:
1012 case eDVBServicePMTHandler::eventMisconfiguration:
1014 eDebug("DVB service failed to tune - error %d", event);
1015 m_event((iPlayableService*)this, evTuneFailed);
1018 case eDVBServicePMTHandler::eventNewProgramInfo:
1020 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1021 if (m_timeshift_enabled)
1022 updateTimeshiftPids();
1023 if (!m_timeshift_active)
1025 if (m_first_program_info & 1 && m_is_pvr)
1027 m_first_program_info &= ~1;
1030 if (!m_timeshift_active)
1031 m_event((iPlayableService*)this, evUpdatedInfo);
1034 case eDVBServicePMTHandler::eventPreStart:
1037 case eDVBServicePMTHandler::eventEOF:
1038 m_event((iPlayableService*)this, evEOF);
1040 case eDVBServicePMTHandler::eventSOF:
1041 m_event((iPlayableService*)this, evSOF);
1046 void eDVBServicePlay::serviceEventTimeshift(int event)
1050 case eDVBServicePMTHandler::eventNewProgramInfo:
1051 eDebug("eventNewProgramInfo TS");
1052 if (m_timeshift_active)
1055 if (m_first_program_info & 2)
1059 eDebug("re-apply slowmotion after timeshift file change");
1060 m_decoder->setSlowMotion(m_slowmotion);
1064 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1066 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1067 if (m_fastforward != 1)
1068 m_decoder->setFastForward(m_fastforward);
1070 m_decoder->setTrickmode();
1074 m_first_program_info &= ~2;
1076 m_event((iPlayableService*)this, evUpdatedInfo);
1079 case eDVBServicePMTHandler::eventSOF:
1081 if (!m_timeshift_file_next.empty())
1083 eDebug("timeshift SOF, switch to next file");
1086 m_first_program_info |= 2;
1088 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1089 r.path = m_timeshift_file_next;
1091 /* free the timeshift service handler, we need the resources */
1092 m_service_handler_timeshift.free();
1096 m_cue->seekTo(0, -1000);
1097 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1099 m_event((iPlayableService*)this, evUser+1);
1103 m_event((iPlayableService*)this, evSOF);
1105 case eDVBServicePMTHandler::eventEOF:
1106 if ((!m_is_paused) && (m_skipmode >= 0))
1108 if (m_timeshift_file_next.empty())
1110 eDebug("timeshift EOF, so let's go live");
1115 eDebug("timeshift EOF, switch to next file");
1117 m_first_program_info |= 2;
1119 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1120 r.path = m_timeshift_file_next;
1122 /* free the timeshift service handler, we need the resources */
1123 m_service_handler_timeshift.free();
1126 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1128 m_event((iPlayableService*)this, evUser+1);
1135 RESULT eDVBServicePlay::start()
1137 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1139 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1140 two (one for decoding, one for data source), as we must be prepared
1141 to start recording from the data demux. */
1144 eDVBMetaParser meta;
1145 if (!meta.parseFile(m_reference.path))
1147 service = meta.m_ref;
1148 service.path = m_reference.path;
1150 m_cue = new eCueSheet();
1153 m_event(this, evStart);
1155 m_first_program_info = 1;
1156 m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1160 /* inject EIT if there is a stored one */
1161 std::string filename = service.path;
1162 filename.erase(filename.length()-2, 2);
1164 ePtr<eServiceEvent> event = new eServiceEvent;
1165 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1167 ePtr<eServiceEvent> empty;
1168 m_event_handler.inject(event, 0);
1169 m_event_handler.inject(empty, 1);
1171 m_event(this, evStart);
1176 RESULT eDVBServicePlay::stop()
1178 /* add bookmark for last play position */
1181 pts_t play_position, length;
1182 if (!getPlayPosition(play_position))
1184 /* remove last position */
1185 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1187 if (i->what == 3) /* current play position */
1189 m_cue_entries.erase(i);
1190 i = m_cue_entries.begin();
1196 if (getLength(length))
1201 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1203 m_cuesheet_changed = 1;
1207 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1209 m_service_handler_timeshift.free();
1210 m_service_handler.free();
1212 if (m_is_pvr && m_cuesheet_changed)
1215 /* save cuesheet only when main file is accessible. */
1216 if (!::stat(m_reference.path.c_str(), &s))
1219 m_event((iPlayableService*)this, evStopped);
1223 RESULT eDVBServicePlay::setTarget(int target)
1225 m_is_primary = !target;
1229 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1231 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1235 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1237 /* note: we check for timeshift to be enabled,
1238 not neccessary active. if you pause when timeshift
1239 is not active, you should activate it when unpausing */
1240 if ((!m_is_pvr) && (!m_timeshift_enabled))
1250 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1252 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1253 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1254 setFastForward_internal(0);
1257 m_slowmotion = ratio;
1258 return m_decoder->setSlowMotion(ratio);
1264 RESULT eDVBServicePlay::setFastForward(int ratio)
1266 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1268 return setFastForward_internal(ratio);
1271 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1273 int skipmode, ffratio, ret = 0;
1280 } else if (ratio > 0)
1288 } else // if (ratio < 0)
1294 if (m_skipmode != skipmode)
1296 eDebug("setting cue skipmode to %d", skipmode);
1298 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1301 m_skipmode = skipmode;
1304 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1306 m_fastforward = ffratio;
1312 ; /* return m_decoder->play(); is done in caller*/
1313 else if (ffratio != 1)
1314 ret = m_decoder->setFastForward(ffratio);
1316 ret = m_decoder->setTrickmode();
1319 eDebug("final seek after trickplay ret %d", seekTo(pos));
1324 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1326 if (m_is_pvr || m_timeshift_enabled)
1336 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1337 RESULT eDVBServicePlay::getLength(pts_t &len)
1339 ePtr<iDVBPVRChannel> pvr_channel;
1341 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1344 return pvr_channel->getLength(len);
1347 RESULT eDVBServicePlay::pause()
1349 eDebug("eDVBServicePlay::pause");
1350 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1355 return m_decoder->pause();
1360 RESULT eDVBServicePlay::unpause()
1362 eDebug("eDVBServicePlay::unpause");
1363 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1368 return m_decoder->play();
1373 RESULT eDVBServicePlay::seekTo(pts_t to)
1375 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1377 if (!m_decode_demux)
1380 ePtr<iDVBPVRChannel> pvr_channel;
1382 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1388 m_cue->seekTo(0, to);
1389 m_dvb_subtitle_pages.clear();
1390 m_subtitle_pages.clear();
1395 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1397 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1399 if (!m_decode_demux)
1402 ePtr<iDVBPVRChannel> pvr_channel;
1404 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1409 /* HACK until we have skip-AP api */
1410 if ((to > 0) && (to < 100))
1418 m_cue->seekTo(mode, to);
1419 m_dvb_subtitle_pages.clear();
1420 m_subtitle_pages.clear();
1424 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1426 ePtr<iDVBPVRChannel> pvr_channel;
1428 if (!m_decode_demux)
1431 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1436 /* if there is a decoder, use audio or video PTS */
1439 r = m_decoder->getPTS(0, pos);
1445 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1448 RESULT eDVBServicePlay::setTrickmode(int trick)
1450 /* currently unimplemented */
1454 RESULT eDVBServicePlay::isCurrentlySeekable()
1459 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1460 if (m_decoder->getVideoProgressive() == -1)
1466 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1472 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1478 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1484 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1490 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1496 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1499 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1500 (m_timeshift_enabled || !m_is_pvr))
1502 if (!m_timeshift_enabled)
1504 /* query config path */
1506 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1507 eDebug("could not query ts path from config");
1511 /* we need enough diskspace */
1513 if (statfs(tspath.c_str(), &fs) < 0)
1515 eDebug("statfs failed!");
1519 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1521 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1531 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1542 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1548 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1554 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1560 RESULT eDVBServicePlay::getName(std::string &name)
1564 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1565 return i->getName(m_reference, name);
1567 else if (m_dvb_service)
1569 m_dvb_service->getName(m_reference, name);
1573 else if (!m_reference.name.empty())
1574 eStaticServiceDVBInformation().getName(m_reference, name);
1576 name = "DVB service";
1580 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1582 return m_event_handler.getEvent(evt, nownext);
1585 int eDVBServicePlay::getInfo(int w)
1587 eDVBServicePMTHandler::program program;
1590 return resIsPyObject;
1592 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1594 int no_program_info = 0;
1596 if (h.getProgramInfo(program))
1597 no_program_info = 1;
1603 return m_decoder->getVideoHeight();
1607 return m_decoder->getVideoWidth();
1611 return m_decoder->getVideoFrameRate();
1615 return m_decoder->getVideoProgressive();
1621 aspect = m_decoder->getVideoAspect();
1622 if (aspect == -1 && no_program_info)
1624 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1626 ePtr<eServiceEvent> evt;
1627 if (!m_event_handler.getEvent(evt, 0))
1629 ePtr<eComponentData> data;
1630 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1632 if ( data->getStreamContent() == 1 )
1634 switch(data->getComponentType())
1637 case 1: // 4:3 SD PAL
1639 case 3: // 16:9 SD PAL
1640 case 4: // > 16:9 PAL
1641 case 5: // 4:3 SD NTSC
1643 case 7: // 16:9 SD NTSC
1644 case 8: // > 16:9 NTSC
1647 case 9: // 4:3 HD PAL
1649 case 0xB: // 16:9 HD PAL
1650 case 0xC: // > 16:9 HD PAL
1651 case 0xD: // 4:3 HD NTSC
1653 case 0xF: // 16:9 HD NTSC
1654 case 0x10: // > 16:9 HD PAL
1655 return data->getComponentType();
1665 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1669 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1673 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1674 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1678 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1681 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1685 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1689 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1693 if (no_program_info) return -1; return program.pcrPid;
1694 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1695 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1696 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1697 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1698 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1699 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1700 case sProvider: if (!m_dvb_service) return -1; return -2;
1701 case sServiceref: return resIsString;
1702 case sDVBState: return m_tune_state;
1709 std::string eDVBServicePlay::getInfoString(int w)
1714 if (!m_dvb_service) return "";
1715 return m_dvb_service->m_provider_name;
1717 return m_reference.toString();
1721 return iServiceInformation::getInfoString(w);
1724 PyObject *eDVBServicePlay::getInfoObject(int w)
1729 return m_service_handler.getCaIds();
1730 case sTransponderData:
1731 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1735 return iServiceInformation::getInfoObject(w);
1738 int eDVBServicePlay::getNumberOfTracks()
1740 eDVBServicePMTHandler::program program;
1741 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1742 if (h.getProgramInfo(program))
1744 return program.audioStreams.size();
1747 int eDVBServicePlay::getCurrentTrack()
1749 eDVBServicePMTHandler::program program;
1750 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1751 if (h.getProgramInfo(program))
1754 int max = program.audioStreams.size();
1757 for (i = 0; i < max; ++i)
1758 if (program.audioStreams[i].pid == m_current_audio_pid)
1764 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1766 int ret = selectAudioStream(i);
1768 if (m_decoder->set())
1774 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1776 eDVBServicePMTHandler::program program;
1777 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1779 if (h.getProgramInfo(program))
1782 if (i >= program.audioStreams.size())
1785 info.m_pid = program.audioStreams[i].pid;
1787 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1788 info.m_description = "MPEG";
1789 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1790 info.m_description = "AC3";
1791 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1792 info.m_description = "AAC";
1793 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1794 info.m_description = "AAC-HE";
1795 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1796 info.m_description = "DTS";
1798 info.m_description = "???";
1800 if (program.audioStreams[i].component_tag != -1)
1802 ePtr<eServiceEvent> evt;
1803 if (!m_event_handler.getEvent(evt, 0))
1805 ePtr<eComponentData> data;
1806 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1807 info.m_language = data->getText();
1811 if (info.m_language.empty())
1812 info.m_language = program.audioStreams[i].language_code;
1817 int eDVBServicePlay::selectAudioStream(int i)
1819 eDVBServicePMTHandler::program program;
1820 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1821 pts_t position = -1;
1823 if (h.getProgramInfo(program))
1826 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1834 stream = program.defaultAudioStream;
1836 int apid = -1, apidtype = -1;
1838 if (((unsigned int)stream) < program.audioStreams.size())
1840 apid = program.audioStreams[stream].pid;
1841 apidtype = program.audioStreams[stream].type;
1844 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1845 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1847 m_current_audio_pid = apid;
1849 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1851 eDebug("set audio pid failed");
1856 eDebug("seekTo ret %d", seekTo(position));
1860 /* 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 */
1861 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1863 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1865 rdsPid = program.audioStreams[stream].rdsPid;
1866 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1869 ePtr<iDVBDemux> data_demux;
1870 if (!h.getDataDemux(data_demux))
1872 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1873 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1874 m_rds_decoder->start(rdsPid);
1879 /* store new pid as default only when:
1880 a.) we have an entry in the service db for the current service,
1881 b.) we are not playing back something,
1882 c.) we are not selecting the default entry. (we wouldn't change
1883 anything in the best case, or destroy the default setting in
1884 case the real default is not yet available.)
1886 if (m_dvb_service && ((i != -1)
1887 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1889 if (apidtype == eDVBAudio::aMPEG)
1891 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1892 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1894 else if (apidtype == eDVBAudio::aAC3)
1896 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1897 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1901 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1902 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1906 h.resetCachedProgram();
1911 int eDVBServicePlay::getCurrentChannel()
1913 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1916 RESULT eDVBServicePlay::selectChannel(int i)
1918 if (i < LEFT || i > RIGHT || i == STEREO)
1921 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1923 m_decoder->setAudioChannel(i);
1927 std::string eDVBServicePlay::getText(int x)
1933 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1935 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1940 void eDVBServicePlay::rdsDecoderEvent(int what)
1944 case eDVBRdsDecoder::RadioTextChanged:
1945 m_event((iPlayableService*)this, evUpdatedRadioText);
1947 case eDVBRdsDecoder::RtpTextChanged:
1948 m_event((iPlayableService*)this, evUpdatedRtpText);
1950 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1951 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1953 case eDVBRdsDecoder::RecvRassSlidePic:
1954 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1959 void eDVBServicePlay::showRassSlidePicture()
1965 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1966 if (rass_slide_pic.length())
1967 m_decoder->showSinglePic(rass_slide_pic.c_str());
1969 eDebug("empty filename for rass slide picture received!!");
1972 eDebug("no MPEG Decoder to show iframes avail");
1975 eDebug("showRassSlidePicture called.. but not decoder");
1978 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1984 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1985 if (rass_interactive_pic.length())
1986 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1988 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1991 eDebug("no MPEG Decoder to show iframes avail");
1994 eDebug("showRassInteractivePic called.. but not decoder");
1997 ePyObject eDVBServicePlay::getRassInteractiveMask()
2000 return m_rds_decoder->getRassPictureMask();
2004 int eDVBServiceBase::getFrontendInfo(int w)
2006 eUsePtr<iDVBChannel> channel;
2007 if(m_service_handler.getChannel(channel))
2009 ePtr<iDVBFrontend> fe;
2010 if(channel->getFrontend(fe))
2012 return fe->readFrontendData(w);
2015 PyObject *eDVBServiceBase::getFrontendData()
2017 ePyObject ret = PyDict_New();
2020 eUsePtr<iDVBChannel> channel;
2021 if(!m_service_handler.getChannel(channel))
2023 ePtr<iDVBFrontend> fe;
2024 if(!channel->getFrontend(fe))
2025 fe->getFrontendData(ret);
2033 PyObject *eDVBServiceBase::getFrontendStatus()
2035 ePyObject ret = PyDict_New();
2038 eUsePtr<iDVBChannel> channel;
2039 if(!m_service_handler.getChannel(channel))
2041 ePtr<iDVBFrontend> fe;
2042 if(!channel->getFrontend(fe))
2043 fe->getFrontendStatus(ret);
2051 PyObject *eDVBServiceBase::getTransponderData(bool original)
2053 ePyObject ret = PyDict_New();
2056 eUsePtr<iDVBChannel> channel;
2057 if(!m_service_handler.getChannel(channel))
2059 ePtr<iDVBFrontend> fe;
2060 if(!channel->getFrontend(fe))
2061 fe->getTransponderData(ret, original);
2069 PyObject *eDVBServiceBase::getAll(bool original)
2071 ePyObject ret = getTransponderData(original);
2074 eUsePtr<iDVBChannel> channel;
2075 if(!m_service_handler.getChannel(channel))
2077 ePtr<iDVBFrontend> fe;
2078 if(!channel->getFrontend(fe))
2080 fe->getFrontendData(ret);
2081 fe->getFrontendStatus(ret);
2088 int eDVBServicePlay::getNumberOfSubservices()
2090 ePtr<eServiceEvent> evt;
2091 if (!m_event_handler.getEvent(evt, 0))
2092 return evt->getNumOfLinkageServices();
2096 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2098 ePtr<eServiceEvent> evt;
2099 if (!m_event_handler.getEvent(evt, 0))
2101 if (!evt->getLinkageService(sub, m_reference, n))
2104 sub.type=eServiceReference::idInvalid;
2108 RESULT eDVBServicePlay::startTimeshift()
2110 ePtr<iDVBDemux> demux;
2112 eDebug("Start timeshift!");
2114 if (m_timeshift_enabled)
2117 /* start recording with the data demux. */
2118 if (m_service_handler.getDataDemux(demux))
2121 demux->createTSRecorder(m_record);
2126 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2127 eDebug("could not query ts path");
2130 tspath.append("/timeshift.XXXXXX");
2132 templ = new char[tspath.length() + 1];
2133 strcpy(templ, tspath.c_str());
2135 m_timeshift_fd = mkstemp(templ);
2136 m_timeshift_file = std::string(templ);
2138 eDebug("recording to %s", templ);
2142 if (m_timeshift_fd < 0)
2148 m_record->setTargetFD(m_timeshift_fd);
2150 m_timeshift_enabled = 1;
2152 updateTimeshiftPids();
2158 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2160 if (!m_timeshift_enabled)
2166 m_timeshift_enabled = 0;
2171 close(m_timeshift_fd);
2172 eDebug("remove timeshift file");
2173 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2178 int eDVBServicePlay::isTimeshiftActive()
2180 return m_timeshift_enabled && m_timeshift_active;
2183 RESULT eDVBServicePlay::activateTimeshift()
2185 if (!m_timeshift_enabled)
2188 if (!m_timeshift_active)
2190 switchToTimeshift();
2197 PyObject *eDVBServicePlay::getCutList()
2199 ePyObject list = PyList_New(0);
2201 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2203 ePyObject tuple = PyTuple_New(2);
2204 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2205 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2206 PyList_Append(list, tuple);
2213 void eDVBServicePlay::setCutList(ePyObject list)
2215 if (!PyList_Check(list))
2217 int size = PyList_Size(list);
2220 m_cue_entries.clear();
2222 for (i=0; i<size; ++i)
2224 ePyObject tuple = PyList_GET_ITEM(list, i);
2225 if (!PyTuple_Check(tuple))
2227 eDebug("non-tuple in cutlist");
2230 if (PyTuple_Size(tuple) != 2)
2232 eDebug("cutlist entries need to be a 2-tuple");
2235 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2236 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2238 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2241 pts_t pts = PyLong_AsLongLong(ppts);
2242 int type = PyInt_AsLong(ptype);
2243 m_cue_entries.insert(cueEntry(pts, type));
2244 eDebug("adding %08llx, %d", pts, type);
2246 m_cuesheet_changed = 1;
2248 cutlistToCuesheet();
2249 m_event((iPlayableService*)this, evCuesheetChanged);
2252 void eDVBServicePlay::setCutListEnable(int enable)
2254 m_cutlist_enabled = enable;
2255 cutlistToCuesheet();
2258 void eDVBServicePlay::updateTimeshiftPids()
2263 eDVBServicePMTHandler::program program;
2264 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2266 if (h.getProgramInfo(program))
2270 std::set<int> pids_to_record;
2271 pids_to_record.insert(0); // PAT
2272 if (program.pmtPid != -1)
2273 pids_to_record.insert(program.pmtPid); // PMT
2275 if (program.textPid != -1)
2276 pids_to_record.insert(program.textPid); // Videotext
2278 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2279 i(program.videoStreams.begin());
2280 i != program.videoStreams.end(); ++i)
2281 pids_to_record.insert(i->pid);
2283 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2284 i(program.audioStreams.begin());
2285 i != program.audioStreams.end(); ++i)
2286 pids_to_record.insert(i->pid);
2288 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2289 i(program.subtitleStreams.begin());
2290 i != program.subtitleStreams.end(); ++i)
2291 pids_to_record.insert(i->pid);
2293 std::set<int> new_pids, obsolete_pids;
2295 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2296 m_pids_active.begin(), m_pids_active.end(),
2297 std::inserter(new_pids, new_pids.begin()));
2299 std::set_difference(
2300 m_pids_active.begin(), m_pids_active.end(),
2301 pids_to_record.begin(), pids_to_record.end(),
2302 std::inserter(new_pids, new_pids.begin())
2305 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2306 m_record->addPID(*i);
2308 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2309 m_record->removePID(*i);
2313 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2315 m_timeshift_file_next = f;
2319 void eDVBServicePlay::switchToLive()
2321 if (!m_timeshift_active)
2324 eDebug("SwitchToLive");
2328 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2330 /* free the timeshift service handler, we need the resources */
2331 m_service_handler_timeshift.free();
2333 updateDecoder(true);
2336 void eDVBServicePlay::resetTimeshift(int start)
2341 m_teletext_parser = 0;
2343 m_subtitle_parser = 0;
2344 m_new_subtitle_page_connection = 0;
2345 m_new_dvb_subtitle_page_connection = 0;
2346 m_rds_decoder_event_connection = 0;
2347 m_video_event_connection = 0;
2348 m_timeshift_changed = 1;
2349 m_timeshift_file_next.clear();
2353 m_cue = new eCueSheet();
2354 m_timeshift_active = 1;
2357 m_timeshift_active = 0;
2360 void eDVBServicePlay::switchToTimeshift()
2362 if (m_timeshift_active)
2367 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2368 r.path = m_timeshift_file;
2370 m_cue->seekTo(0, -1000);
2371 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2373 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2375 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2378 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2380 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2381 bool mustPlay = false;
2383 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2385 eDVBServicePMTHandler::program program;
2386 if (h.getProgramInfo(program))
2387 eDebug("getting program info failed.");
2390 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2391 if (!program.videoStreams.empty())
2393 eDebugNoNewLine(" (");
2394 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2395 i(program.videoStreams.begin());
2396 i != program.videoStreams.end(); ++i)
2403 if (i != program.videoStreams.begin())
2404 eDebugNoNewLine(", ");
2405 eDebugNoNewLine("%04x", i->pid);
2407 eDebugNoNewLine(")");
2409 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2410 if (!program.audioStreams.empty())
2412 eDebugNoNewLine(" (");
2413 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2414 i(program.audioStreams.begin());
2415 i != program.audioStreams.end(); ++i)
2417 if (i != program.audioStreams.begin())
2418 eDebugNoNewLine(", ");
2419 eDebugNoNewLine("%04x", i->pid);
2421 eDebugNoNewLine(")");
2423 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2424 pcrpid = program.pcrPid;
2425 eDebug(", and the text pid is %04x", program.textPid);
2426 tpid = program.textPid;
2431 h.getDecodeDemux(m_decode_demux);
2434 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2436 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2439 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2440 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2441 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2442 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2443 if (m_timeshift_changed)
2445 ePyObject subs = getCachedSubtitle();
2446 if (subs != Py_None)
2448 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2449 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2450 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2451 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2452 if (type == 0) // dvb
2453 m_subtitle_parser->start(pid, comp_page, anc_page);
2454 else if (type == 1) // ttx
2455 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2462 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2466 m_timeshift_changed = 0;
2470 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2473 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2474 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2475 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2479 eServiceReferenceDVB ref;
2480 m_service_handler.getServiceReference(ref);
2481 eServiceReferenceDVB parent = ref.getParentServiceReference();
2486 ePtr<eDVBResourceManager> res_mgr;
2487 if (!eDVBResourceManager::getInstance(res_mgr))
2489 ePtr<iDVBChannelList> db;
2490 if (!res_mgr->getChannelList(db))
2492 ePtr<eDVBService> origService;
2493 if (!db->getService(parent, origService))
2495 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2496 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2503 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2504 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2506 m_decoder->setVideoPID(vpid, vpidtype);
2507 selectAudioStream();
2509 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2510 m_decoder->setSyncPCR(pcrpid);
2512 m_decoder->setSyncPCR(-1);
2516 m_decoder->setTextPID(tpid);
2517 m_teletext_parser->start(program.textPid);
2520 if (vpid > 0 && vpid < 0x2000)
2524 std::string radio_pic;
2525 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2526 m_decoder->setRadioPic(radio_pic);
2534 m_decoder->setAudioChannel(achannel);
2536 /* don't worry about non-existing services, nor pvr services */
2539 /* (audio pid will be set in selectAudioTrack */
2540 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2541 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2542 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2543 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2545 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2546 sendSeekableStateChanged = true;
2548 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2550 if (sendSeekableStateChanged)
2551 m_event((iPlayableService*)this, evSeekableStatusChanged);
2554 void eDVBServicePlay::loadCuesheet()
2556 std::string filename = m_reference.path + ".cuts";
2558 m_cue_entries.clear();
2560 FILE *f = fopen(filename.c_str(), "rb");
2564 eDebug("loading cuts..");
2567 unsigned long long where;
2570 if (!fread(&where, sizeof(where), 1, f))
2572 if (!fread(&what, sizeof(what), 1, f))
2575 #if BYTE_ORDER == LITTLE_ENDIAN
2576 where = bswap_64(where);
2583 m_cue_entries.insert(cueEntry(where, what));
2586 eDebug("%d entries", m_cue_entries.size());
2588 eDebug("cutfile not found!");
2590 m_cuesheet_changed = 0;
2591 cutlistToCuesheet();
2592 m_event((iPlayableService*)this, evCuesheetChanged);
2595 void eDVBServicePlay::saveCuesheet()
2597 std::string filename = m_reference.path + ".cuts";
2599 FILE *f = fopen(filename.c_str(), "wb");
2603 unsigned long long where;
2606 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2608 #if BYTE_ORDER == BIG_ENDIAN
2611 where = bswap_64(i->where);
2613 what = htonl(i->what);
2614 fwrite(&where, sizeof(where), 1, f);
2615 fwrite(&what, sizeof(what), 1, f);
2621 m_cuesheet_changed = 0;
2624 void eDVBServicePlay::cutlistToCuesheet()
2628 eDebug("no cue sheet");
2633 if (!m_cutlist_enabled)
2635 m_cue->commitSpans();
2636 eDebug("cutlists were disabled");
2640 pts_t in = 0, out = 0, length = 0;
2644 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2646 int have_any_span = 0;
2650 if (i == m_cue_entries.end())
2652 if (!have_any_span && !in)
2656 if (i->what == 0) /* in */
2660 } else if (i->what == 1) /* out */
2662 else /* mark (2) or last play position (3) */
2681 m_cue->addSourceSpan(in, out);
2687 if (i == m_cue_entries.end())
2690 m_cue->commitSpans();
2693 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2695 if (m_subtitle_widget)
2696 disableSubtitles(parent);
2699 int tuplesize = PyTuple_Size(tuple);
2702 if (!PyTuple_Check(tuple))
2708 entry = PyTuple_GET_ITEM(tuple, 0);
2710 if (!PyInt_Check(entry))
2713 type = PyInt_AsLong(entry);
2715 if (type == 1) // teletext subtitles
2717 int page, magazine, pid;
2721 if (!m_teletext_parser)
2723 eDebug("enable teletext subtitles.. no parser !!!");
2727 entry = PyTuple_GET_ITEM(tuple, 1);
2728 if (!PyInt_Check(entry))
2730 pid = PyInt_AsLong(entry);
2732 entry = PyTuple_GET_ITEM(tuple, 2);
2733 if (!PyInt_Check(entry))
2735 page = PyInt_AsLong(entry);
2737 entry = PyTuple_GET_ITEM(tuple, 3);
2738 if (!PyInt_Check(entry))
2740 magazine = PyInt_AsLong(entry);
2742 m_subtitle_widget = new eSubtitleWidget(parent);
2743 m_subtitle_widget->resize(parent->size()); /* full size */
2744 m_teletext_parser->setPageAndMagazine(page, magazine);
2746 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2750 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2751 if (!m_subtitle_parser)
2753 eDebug("enable dvb subtitles.. no parser !!!");
2759 entry = PyTuple_GET_ITEM(tuple, 1);
2760 if (!PyInt_Check(entry))
2762 pid = PyInt_AsLong(entry);
2764 entry = PyTuple_GET_ITEM(tuple, 2);
2765 if (!PyInt_Check(entry))
2767 composition_page_id = PyInt_AsLong(entry);
2769 entry = PyTuple_GET_ITEM(tuple, 3);
2770 if (!PyInt_Check(entry))
2772 ancillary_page_id = PyInt_AsLong(entry);
2774 m_subtitle_widget = new eSubtitleWidget(parent);
2775 m_subtitle_widget->resize(parent->size()); /* full size */
2776 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2778 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2784 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2785 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2786 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2790 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2792 delete m_subtitle_widget;
2793 m_subtitle_widget = 0;
2794 if (m_subtitle_parser)
2796 m_subtitle_parser->stop();
2797 m_dvb_subtitle_pages.clear();
2799 if (m_teletext_parser)
2801 m_teletext_parser->setPageAndMagazine(-1, -1);
2802 m_subtitle_pages.clear();
2805 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2809 PyObject *eDVBServicePlay::getCachedSubtitle()
2813 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2816 unsigned int data = (unsigned int)tmp;
2817 int pid = (data&0xFFFF0000)>>16;
2818 ePyObject tuple = PyTuple_New(4);
2819 eDVBServicePMTHandler::program program;
2820 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2821 if (!h.getProgramInfo(program))
2823 if (program.textPid==pid) // teletext
2824 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2826 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2827 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2828 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2829 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2837 PyObject *eDVBServicePlay::getSubtitleList()
2839 if (!m_teletext_parser)
2842 ePyObject l = PyList_New(0);
2843 std::set<int> added_ttx_pages;
2845 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2846 m_teletext_parser->m_found_subtitle_pages;
2848 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2849 eDVBServicePMTHandler::program program;
2850 if (h.getProgramInfo(program))
2851 eDebug("getting program info failed.");
2854 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2855 it != program.subtitleStreams.end(); ++it)
2857 switch(it->subtitling_type)
2859 case 0x01: // ebu teletext subtitles
2861 int page_number = it->teletext_page_number & 0xFF;
2862 int magazine_number = it->teletext_magazine_number & 7;
2863 int hash = magazine_number << 8 | page_number;
2864 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2866 ePyObject tuple = PyTuple_New(5);
2867 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2868 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2869 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2870 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2871 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2872 PyList_Append(l, tuple);
2874 added_ttx_pages.insert(hash);
2879 case 0x20 ... 0x23: // dvb subtitles
2881 ePyObject tuple = PyTuple_New(5);
2882 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2883 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2884 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2885 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2886 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2887 PyList_Insert(l, 0, tuple);
2895 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2896 it != subs.end(); ++it)
2898 int page_number = it->teletext_page_number & 0xFF;
2899 int magazine_number = it->teletext_magazine_number & 7;
2900 int hash = magazine_number << 8 | page_number;
2901 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2903 ePyObject tuple = PyTuple_New(5);
2904 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2905 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2906 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2907 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2908 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2909 PyList_Append(l, tuple);
2917 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2919 if (m_subtitle_widget)
2923 m_decoder->getPTS(0, pos);
2924 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2925 m_subtitle_pages.push_back(page);
2926 checkSubtitleTiming();
2930 void eDVBServicePlay::checkSubtitleTiming()
2932 eDebug("checkSubtitleTiming");
2933 if (!m_subtitle_widget)
2937 enum { TELETEXT, DVB } type;
2938 eDVBTeletextSubtitlePage page;
2939 eDVBSubtitlePage dvb_page;
2941 if (!m_subtitle_pages.empty())
2943 page = m_subtitle_pages.front();
2945 show_time = page.m_pts;
2947 else if (!m_dvb_subtitle_pages.empty())
2949 dvb_page = m_dvb_subtitle_pages.front();
2951 show_time = dvb_page.m_show_time;
2959 m_decoder->getPTS(0, pos);
2961 eDebug("%lld %lld", pos, show_time);
2962 int diff = show_time - pos;
2963 if (type == TELETEXT && !page.m_have_pts)
2965 eDebug("ttx subtitle page without pts... immediate show");
2970 eDebug("[late (%d ms)]", -diff / 90);
2973 if (abs(diff) > 1800000)
2975 eDebug("[invalid]... immediate show!");
2980 if (type == TELETEXT)
2982 eDebug("display teletext subtitle page %lld", show_time);
2983 m_subtitle_widget->setPage(page);
2984 m_subtitle_pages.pop_front();
2988 eDebug("display dvb subtitle Page %lld", show_time);
2989 m_subtitle_widget->setPage(dvb_page);
2990 m_dvb_subtitle_pages.pop_front();
2994 eDebug("start subtitle delay %d", diff / 90);
2995 m_subtitle_sync_timer->start(diff / 90, 1);
3001 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3003 if (m_subtitle_widget)
3007 m_decoder->getPTS(0, pos);
3008 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3009 m_dvb_subtitle_pages.push_back(p);
3010 checkSubtitleTiming();
3014 int eDVBServicePlay::getAC3Delay()
3017 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3019 return m_decoder->getAC3Delay();
3024 int eDVBServicePlay::getPCMDelay()
3027 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3029 return m_decoder->getPCMDelay();
3034 void eDVBServicePlay::setAC3Delay(int delay)
3037 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3039 std::string config_delay;
3040 int config_delay_int = 0;
3041 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3042 config_delay_int = atoi(config_delay.c_str());
3043 m_decoder->setAC3Delay(delay + config_delay_int);
3047 void eDVBServicePlay::setPCMDelay(int delay)
3050 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3052 std::string config_delay;
3053 int config_delay_int = 0;
3054 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3055 config_delay_int = atoi(config_delay.c_str());
3057 config_delay_int = 0;
3058 m_decoder->setPCMDelay(delay + config_delay_int);
3062 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3064 switch(event.type) {
3065 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3066 m_event((iPlayableService*)this, evVideoSizeChanged);
3068 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3069 m_event((iPlayableService*)this, evVideoFramerateChanged);
3071 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3072 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3079 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3085 PyObject *eDVBServicePlay::getStreamingData()
3087 eDVBServicePMTHandler::program program;
3088 if (m_service_handler.getProgramInfo(program))
3093 ePyObject r = program.createPythonObject();
3094 ePtr<iDVBDemux> demux;
3095 if (!m_service_handler.getDataDemux(demux))
3098 if (!demux->getCADemuxID(demux_id))
3099 PutToDict(r, "demux", demux_id);
3106 DEFINE_REF(eDVBServicePlay)
3108 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3112 case iServiceInformation::sTransponderData:
3113 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3117 return iStaticServiceInformation::getInfoObject(ref, w);
3120 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");