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);
507 off_t length = f.length();
508 unsigned char buffer[188*256*4];
511 off_t offset = f.lseek(0, SEEK_CUR);
512 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513 int r = f.read(buffer, sizeof(buffer));
518 parser.parseData(offset, buffer, r);
527 DEFINE_REF(eServiceFactoryDVB)
529 eServiceFactoryDVB::eServiceFactoryDVB()
531 ePtr<eServiceCenter> sc;
533 eServiceCenter::getPrivInstance(sc);
536 std::list<std::string> extensions;
537 extensions.push_back("ts");
538 extensions.push_back("trp");
539 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
542 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
543 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
546 eServiceFactoryDVB::~eServiceFactoryDVB()
548 ePtr<eServiceCenter> sc;
550 eServiceCenter::getPrivInstance(sc);
552 sc->removeServiceFactory(eServiceFactoryDVB::id);
555 DEFINE_REF(eDVBServiceList);
557 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
561 eDVBServiceList::~eDVBServiceList()
565 RESULT eDVBServiceList::startQuery()
567 ePtr<iDVBChannelList> db;
568 ePtr<eDVBResourceManager> res;
571 if ((err = eDVBResourceManager::getInstance(res)) != 0)
573 eDebug("no resource manager");
576 if ((err = res->getChannelList(db)) != 0)
578 eDebug("no channel list");
582 ePtr<eDVBChannelQuery> q;
584 if (!m_parent.path.empty())
586 eDVBChannelQuery::compile(q, m_parent.path);
589 eDebug("compile query failed");
594 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
596 eDebug("startQuery failed");
603 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
605 eServiceReferenceDVB ref;
610 while (!m_query->getNextResult(ref))
614 list.sort(iListableServiceCompare(this));
619 // The first argument of this function is a format string to specify the order and
620 // the content of the returned list
621 // useable format options are
622 // R = Service Reference (as swig object .. this is very slow)
623 // S = Service Reference (as python string object .. same as ref.toString())
624 // C = Service Reference (as python string object .. same as ref.toCompareString())
625 // N = Service Name (as python string object)
626 // n = Short Service Name (short name brakets used) (as python string object)
627 // when exactly one return value per service is selected in the format string,
628 // then each value is directly a list entry
629 // when more than one value is returned per service, then the list is a list of
631 // unknown format string chars are returned as python None values !
632 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
635 std::list<eServiceReference> tmplist;
638 if (!format || !(retcount=strlen(format)))
639 format = "R"; // just return service reference swig object ...
641 if (!getContent(tmplist, sorted))
643 int services=tmplist.size();
644 ePtr<iStaticServiceInformation> sptr;
645 eServiceCenterPtr service_center;
647 if (strchr(format, 'N') || strchr(format, 'n'))
648 eServiceCenter::getPrivInstance(service_center);
650 ret = PyList_New(services);
651 std::list<eServiceReference>::iterator it(tmplist.begin());
653 for (int cnt=0; cnt < services; ++cnt)
655 eServiceReference &ref=*it++;
656 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
657 for (int i=0; i < retcount; ++i)
662 case 'R': // service reference (swig)object
663 tmp = NEW_eServiceReference(ref);
665 case 'C': // service reference compare string
666 tmp = PyString_FromString(ref.toCompareString().c_str());
668 case 'S': // service reference string
669 tmp = PyString_FromString(ref.toString().c_str());
671 case 'N': // service name
674 service_center->info(ref, sptr);
678 sptr->getName(ref, name);
680 // filter short name brakets
682 while((pos = name.find("\xc2\x86")) != std::string::npos)
684 while((pos = name.find("\xc2\x87")) != std::string::npos)
688 tmp = PyString_FromString(name.c_str());
692 tmp = PyString_FromString("<n/a>");
694 case 'n': // short service name
697 service_center->info(ref, sptr);
701 sptr->getName(ref, name);
702 name = buildShortName(name);
704 tmp = PyString_FromString(name.c_str());
708 tmp = PyString_FromString("<n/a>");
721 PyTuple_SET_ITEM(tuple, i, tmp);
723 PyList_SET_ITEM(ret, cnt, tmp);
727 PyList_SET_ITEM(ret, cnt, tuple);
730 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
733 RESULT eDVBServiceList::getNext(eServiceReference &ref)
738 return m_query->getNextResult((eServiceReferenceDVB&)ref);
741 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
743 if (m_parent.flags & eServiceReference::canDescent) // bouquet
745 ePtr<iDVBChannelList> db;
746 ePtr<eDVBResourceManager> resm;
748 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
751 if (db->getBouquet(m_parent, m_bouquet) != 0)
762 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
766 return m_bouquet->addService(ref, before);
769 RESULT eDVBServiceList::removeService(eServiceReference &ref)
773 return m_bouquet->removeService(ref);
776 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
780 return m_bouquet->moveService(ref, pos);
783 RESULT eDVBServiceList::flushChanges()
787 return m_bouquet->flushChanges();
790 RESULT eDVBServiceList::setListName(const std::string &name)
794 return m_bouquet->setListName(name);
797 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
799 ePtr<eDVBService> service;
800 int r = lookupService(service, ref);
803 // check resources...
804 ptr = new eDVBServicePlay(ref, service);
808 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
810 if (ref.path.empty())
812 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
821 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
823 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
824 if (list->startQuery())
834 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
836 /* is a listable service? */
837 if (ref.flags & eServiceReference::canDescent) // bouquet
839 if ( !ref.name.empty() ) // satellites or providers list
840 ptr = m_StaticServiceDVBInfo;
841 else // a dvb bouquet
842 ptr = m_StaticServiceDVBBouquetInfo;
844 else if (!ref.path.empty()) /* do we have a PVR service? */
845 ptr = new eStaticServiceDVBPVRInformation(ref);
846 else // normal dvb service
848 ePtr<eDVBService> service;
849 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
850 ptr = m_StaticServiceDVBInfo;
852 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
858 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
860 if (ref.path.empty())
866 ptr = new eDVBPVRServiceOfflineOperations(ref);
871 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
873 if (!ref.path.empty()) // playback
875 eDVBMetaParser parser;
876 int ret=parser.parseFile(ref.path);
877 service = new eDVBService;
879 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
883 // TODO: handle the listing itself
884 // if (ref.... == -1) .. return "... bouquets ...";
885 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
887 ePtr<iDVBChannelList> db;
888 ePtr<eDVBResourceManager> res;
891 if ((err = eDVBResourceManager::getInstance(res)) != 0)
893 eDebug("no resource manager");
896 if ((err = res->getChannelList(db)) != 0)
898 eDebug("no channel list");
902 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
903 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
905 eDebug("getService failed!");
913 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
914 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
917 m_is_pvr = !m_reference.path.empty();
919 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
920 m_skipmode = m_fastforward = m_slowmotion = 0;
922 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
923 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
924 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
926 m_cuesheet_changed = 0;
927 m_cutlist_enabled = 1;
929 m_subtitle_widget = 0;
933 m_subtitle_sync_timer = eTimer::create(eApp);
935 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
938 eDVBServicePlay::~eDVBServicePlay()
943 int ret=meta.parseFile(m_reference.path);
947 meta.m_service_data="";
948 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
949 meta.m_service_data += tmp;
951 for (int x=0; x < eDVBService::cacheMax; ++x)
953 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
956 sprintf(tmp, ",c:%02d%04x", x, entry);
957 meta.m_service_data += tmp;
960 meta.updateMeta(m_reference.path);
963 delete m_subtitle_widget;
966 void eDVBServicePlay::gotNewEvent()
970 ePtr<eServiceEvent> m_event_now, m_event_next;
971 getEvent(m_event_now, 0);
972 getEvent(m_event_next, 1);
975 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
977 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
979 m_event((iPlayableService*)this, evUpdatedEventInfo);
982 void eDVBServicePlay::serviceEvent(int event)
984 m_tune_state = event;
988 case eDVBServicePMTHandler::eventTuned:
990 ePtr<iDVBDemux> m_demux;
991 if (!m_service_handler.getDataDemux(m_demux))
993 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
994 int sid = ref.getParentServiceID().get();
996 sid = ref.getServiceID().get();
997 if ( ref.getParentTransportStreamID().get() &&
998 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
999 m_event_handler.startOther(m_demux, sid);
1001 m_event_handler.start(m_demux, sid);
1003 m_event((iPlayableService*)this, evTunedIn);
1006 case eDVBServicePMTHandler::eventNoResources:
1007 case eDVBServicePMTHandler::eventNoPAT:
1008 case eDVBServicePMTHandler::eventNoPATEntry:
1009 case eDVBServicePMTHandler::eventNoPMT:
1010 case eDVBServicePMTHandler::eventTuneFailed:
1011 case eDVBServicePMTHandler::eventMisconfiguration:
1013 eDebug("DVB service failed to tune - error %d", event);
1014 m_event((iPlayableService*)this, evTuneFailed);
1017 case eDVBServicePMTHandler::eventNewProgramInfo:
1019 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1020 if (m_timeshift_enabled)
1021 updateTimeshiftPids();
1022 if (!m_timeshift_active)
1024 if (m_first_program_info && m_is_pvr)
1026 m_first_program_info = 0;
1029 m_event((iPlayableService*)this, evUpdatedInfo);
1032 case eDVBServicePMTHandler::eventEOF:
1033 m_event((iPlayableService*)this, evEOF);
1035 case eDVBServicePMTHandler::eventSOF:
1036 m_event((iPlayableService*)this, evSOF);
1041 void eDVBServicePlay::serviceEventTimeshift(int event)
1045 case eDVBServicePMTHandler::eventNewProgramInfo:
1046 if (m_timeshift_active)
1049 case eDVBServicePMTHandler::eventSOF:
1050 m_event((iPlayableService*)this, evSOF);
1052 case eDVBServicePMTHandler::eventEOF:
1053 if ((!m_is_paused) && (m_skipmode >= 0))
1055 eDebug("timeshift EOF, so let's go live");
1062 RESULT eDVBServicePlay::start()
1064 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1066 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1067 two (one for decoding, one for data source), as we must be prepared
1068 to start recording from the data demux. */
1071 eDVBMetaParser meta;
1072 if (!meta.parseFile(m_reference.path))
1074 service = meta.m_ref;
1075 service.path = m_reference.path;
1077 m_cue = new eCueSheet();
1080 m_event(this, evStart);
1082 m_first_program_info = 1;
1083 m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1087 /* inject EIT if there is a stored one */
1088 std::string filename = service.path;
1089 filename.erase(filename.length()-2, 2);
1091 ePtr<eServiceEvent> event = new eServiceEvent;
1092 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1094 ePtr<eServiceEvent> empty;
1095 m_event_handler.inject(event, 0);
1096 m_event_handler.inject(empty, 1);
1099 m_event(this, evStart);
1104 RESULT eDVBServicePlay::stop()
1106 /* add bookmark for last play position */
1109 pts_t play_position, length;
1110 if (!getPlayPosition(play_position))
1112 /* remove last position */
1113 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1115 if (i->what == 3) /* current play position */
1117 m_cue_entries.erase(i);
1118 i = m_cue_entries.begin();
1124 if (getLength(length))
1129 int perc = play_position * 100LL / length;
1131 /* only store last play position when between 1% and 99% */
1132 if ((1 < perc) && (perc < 99))
1133 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1135 m_cuesheet_changed = 1;
1139 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1141 m_service_handler_timeshift.free();
1142 m_service_handler.free();
1144 if (m_is_pvr && m_cuesheet_changed)
1147 /* save cuesheet only when main file is accessible. */
1148 if (!::stat(m_reference.path.c_str(), &s))
1151 m_event((iPlayableService*)this, evStopped);
1155 RESULT eDVBServicePlay::setTarget(int target)
1157 m_is_primary = !target;
1161 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1163 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1167 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1169 /* note: we check for timeshift to be enabled,
1170 not neccessary active. if you pause when timeshift
1171 is not active, you should activate it when unpausing */
1172 if ((!m_is_pvr) && (!m_timeshift_enabled))
1182 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1184 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1185 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1186 setFastForward_internal(0);
1189 m_slowmotion = ratio;
1190 return m_decoder->setSlowMotion(ratio);
1196 RESULT eDVBServicePlay::setFastForward(int ratio)
1198 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1200 return setFastForward_internal(ratio);
1203 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1205 int skipmode, ffratio, ret = 0;
1212 } else if (ratio > 0)
1220 } else // if (ratio < 0)
1226 if (m_skipmode != skipmode)
1228 eDebug("setting cue skipmode to %d", skipmode);
1230 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1233 m_skipmode = skipmode;
1236 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1238 m_fastforward = ffratio;
1244 ; /* return m_decoder->play(); is done in caller*/
1245 else if (ffratio != 1)
1246 ret = m_decoder->setFastForward(ffratio);
1248 ret = m_decoder->setTrickmode();
1251 eDebug("final seek after trickplay ret %d", seekTo(pos));
1256 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1258 if (m_is_pvr || m_timeshift_enabled)
1268 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1269 RESULT eDVBServicePlay::getLength(pts_t &len)
1271 ePtr<iDVBPVRChannel> pvr_channel;
1273 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1276 return pvr_channel->getLength(len);
1279 RESULT eDVBServicePlay::pause()
1281 eDebug("eDVBServicePlay::pause");
1282 setFastForward_internal(0);
1286 return m_decoder->pause();
1291 RESULT eDVBServicePlay::unpause()
1293 eDebug("eDVBServicePlay::unpause");
1294 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1299 return m_decoder->play();
1304 RESULT eDVBServicePlay::seekTo(pts_t to)
1306 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1308 if (!m_decode_demux)
1311 ePtr<iDVBPVRChannel> pvr_channel;
1313 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1319 m_cue->seekTo(0, to);
1320 m_dvb_subtitle_pages.clear();
1321 m_subtitle_pages.clear();
1326 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1328 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1330 if (!m_decode_demux)
1333 ePtr<iDVBPVRChannel> pvr_channel;
1335 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1340 /* HACK until we have skip-AP api */
1341 if ((to > 0) && (to < 100))
1349 m_cue->seekTo(mode, to);
1350 m_dvb_subtitle_pages.clear();
1351 m_subtitle_pages.clear();
1355 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1357 ePtr<iDVBPVRChannel> pvr_channel;
1359 if (!m_decode_demux)
1362 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1367 /* if there is a decoder, use audio or video PTS */
1370 r = m_decoder->getPTS(0, pos);
1376 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1379 RESULT eDVBServicePlay::setTrickmode(int trick)
1381 /* currently unimplemented */
1385 RESULT eDVBServicePlay::isCurrentlySeekable()
1387 return m_is_pvr || m_timeshift_active;
1390 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1396 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1402 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1408 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1414 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1420 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1423 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1424 (m_timeshift_enabled || !m_is_pvr))
1426 if (!m_timeshift_enabled)
1428 /* query config path */
1430 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1431 eDebug("could not query ts path from config");
1435 /* we need enough diskspace */
1437 if (statfs(tspath.c_str(), &fs) < 0)
1439 eDebug("statfs failed!");
1443 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1445 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1455 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1466 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1472 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1478 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1484 RESULT eDVBServicePlay::getName(std::string &name)
1488 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1489 return i->getName(m_reference, name);
1491 else if (m_dvb_service)
1493 m_dvb_service->getName(m_reference, name);
1497 else if (!m_reference.name.empty())
1498 eStaticServiceDVBInformation().getName(m_reference, name);
1500 name = "DVB service";
1504 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1506 return m_event_handler.getEvent(evt, nownext);
1509 int eDVBServicePlay::getInfo(int w)
1511 eDVBServicePMTHandler::program program;
1514 return resIsPyObject;
1516 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1518 int no_program_info = 0;
1520 if (h.getProgramInfo(program))
1521 no_program_info = 1;
1527 return m_decoder->getVideoHeight();
1531 return m_decoder->getVideoWidth();
1535 return m_decoder->getVideoFrameRate();
1539 return m_decoder->getVideoProgressive();
1545 aspect = m_decoder->getVideoAspect();
1546 if (aspect == -1 && no_program_info)
1548 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1550 ePtr<eServiceEvent> evt;
1551 if (!m_event_handler.getEvent(evt, 0))
1553 ePtr<eComponentData> data;
1554 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1556 if ( data->getStreamContent() == 1 )
1558 switch(data->getComponentType())
1561 case 1: // 4:3 SD PAL
1563 case 3: // 16:9 SD PAL
1564 case 4: // > 16:9 PAL
1565 case 5: // 4:3 SD NTSC
1567 case 7: // 16:9 SD NTSC
1568 case 8: // > 16:9 NTSC
1571 case 9: // 4:3 HD PAL
1573 case 0xB: // 16:9 HD PAL
1574 case 0xC: // > 16:9 HD PAL
1575 case 0xD: // 4:3 HD NTSC
1577 case 0xF: // 16:9 HD NTSC
1578 case 0x10: // > 16:9 HD PAL
1579 return data->getComponentType();
1589 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1593 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1597 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1598 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1602 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1605 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1609 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1613 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1617 if (no_program_info) return -1; return program.pcrPid;
1618 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1619 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1620 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1621 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1622 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1623 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1624 case sProvider: if (!m_dvb_service) return -1; return -2;
1625 case sServiceref: return resIsString;
1626 case sDVBState: return m_tune_state;
1633 std::string eDVBServicePlay::getInfoString(int w)
1638 if (!m_dvb_service) return "";
1639 return m_dvb_service->m_provider_name;
1641 return m_reference.toString();
1645 return iServiceInformation::getInfoString(w);
1648 PyObject *eDVBServicePlay::getInfoObject(int w)
1653 return m_service_handler.getCaIds();
1654 case sTransponderData:
1655 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1659 return iServiceInformation::getInfoObject(w);
1662 int eDVBServicePlay::getNumberOfTracks()
1664 eDVBServicePMTHandler::program program;
1665 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1666 if (h.getProgramInfo(program))
1668 return program.audioStreams.size();
1671 int eDVBServicePlay::getCurrentTrack()
1673 eDVBServicePMTHandler::program program;
1674 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1675 if (h.getProgramInfo(program))
1678 int max = program.audioStreams.size();
1681 for (i = 0; i < max; ++i)
1682 if (program.audioStreams[i].pid == m_current_audio_pid)
1688 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1690 int ret = selectAudioStream(i);
1692 if (m_decoder->set())
1698 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1700 eDVBServicePMTHandler::program program;
1701 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1703 if (h.getProgramInfo(program))
1706 if (i >= program.audioStreams.size())
1709 info.m_pid = program.audioStreams[i].pid;
1711 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1712 info.m_description = "MPEG";
1713 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1714 info.m_description = "AC3";
1715 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1716 info.m_description = "AAC";
1717 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1718 info.m_description = "AAC-HE";
1719 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1720 info.m_description = "DTS";
1722 info.m_description = "???";
1724 if (program.audioStreams[i].component_tag != -1)
1726 ePtr<eServiceEvent> evt;
1727 if (!m_event_handler.getEvent(evt, 0))
1729 ePtr<eComponentData> data;
1730 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1731 info.m_language = data->getText();
1735 if (info.m_language.empty())
1736 info.m_language = program.audioStreams[i].language_code;
1741 int eDVBServicePlay::selectAudioStream(int i)
1743 eDVBServicePMTHandler::program program;
1744 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1746 if (h.getProgramInfo(program))
1749 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1757 stream = program.defaultAudioStream;
1759 int apid = -1, apidtype = -1;
1761 if (((unsigned int)stream) < program.audioStreams.size())
1763 apid = program.audioStreams[stream].pid;
1764 apidtype = program.audioStreams[stream].type;
1767 m_current_audio_pid = apid;
1769 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1771 eDebug("set audio pid failed");
1777 /* 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 */
1778 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1780 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1782 rdsPid = program.audioStreams[stream].rdsPid;
1783 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1786 ePtr<iDVBDemux> data_demux;
1787 if (!h.getDataDemux(data_demux))
1789 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1790 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1791 m_rds_decoder->start(rdsPid);
1796 /* store new pid as default only when:
1797 a.) we have an entry in the service db for the current service,
1798 b.) we are not playing back something,
1799 c.) we are not selecting the default entry. (we wouldn't change
1800 anything in the best case, or destroy the default setting in
1801 case the real default is not yet available.)
1803 if (m_dvb_service && ((i != -1)
1804 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1806 if (apidtype == eDVBAudio::aMPEG)
1808 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1809 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1811 else if (apidtype == eDVBAudio::aAC3)
1813 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1814 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1818 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1819 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1823 h.resetCachedProgram();
1828 int eDVBServicePlay::getCurrentChannel()
1830 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1833 RESULT eDVBServicePlay::selectChannel(int i)
1835 if (i < LEFT || i > RIGHT || i == STEREO)
1838 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1840 m_decoder->setAudioChannel(i);
1844 std::string eDVBServicePlay::getText(int x)
1850 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1852 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1857 void eDVBServicePlay::rdsDecoderEvent(int what)
1861 case eDVBRdsDecoder::RadioTextChanged:
1862 m_event((iPlayableService*)this, evUpdatedRadioText);
1864 case eDVBRdsDecoder::RtpTextChanged:
1865 m_event((iPlayableService*)this, evUpdatedRtpText);
1867 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1868 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1870 case eDVBRdsDecoder::RecvRassSlidePic:
1871 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1876 void eDVBServicePlay::showRassSlidePicture()
1882 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1883 if (rass_slide_pic.length())
1884 m_decoder->showSinglePic(rass_slide_pic.c_str());
1886 eDebug("empty filename for rass slide picture received!!");
1889 eDebug("no MPEG Decoder to show iframes avail");
1892 eDebug("showRassSlidePicture called.. but not decoder");
1895 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1901 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1902 if (rass_interactive_pic.length())
1903 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1905 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1908 eDebug("no MPEG Decoder to show iframes avail");
1911 eDebug("showRassInteractivePic called.. but not decoder");
1914 ePyObject eDVBServicePlay::getRassInteractiveMask()
1917 return m_rds_decoder->getRassPictureMask();
1921 int eDVBServiceBase::getFrontendInfo(int w)
1923 eUsePtr<iDVBChannel> channel;
1924 if(m_service_handler.getChannel(channel))
1926 ePtr<iDVBFrontend> fe;
1927 if(channel->getFrontend(fe))
1929 return fe->readFrontendData(w);
1932 PyObject *eDVBServiceBase::getFrontendData()
1934 ePyObject ret = PyDict_New();
1937 eUsePtr<iDVBChannel> channel;
1938 if(!m_service_handler.getChannel(channel))
1940 ePtr<iDVBFrontend> fe;
1941 if(!channel->getFrontend(fe))
1942 fe->getFrontendData(ret);
1950 PyObject *eDVBServiceBase::getFrontendStatus()
1952 ePyObject ret = PyDict_New();
1955 eUsePtr<iDVBChannel> channel;
1956 if(!m_service_handler.getChannel(channel))
1958 ePtr<iDVBFrontend> fe;
1959 if(!channel->getFrontend(fe))
1960 fe->getFrontendStatus(ret);
1968 PyObject *eDVBServiceBase::getTransponderData(bool original)
1970 ePyObject ret = PyDict_New();
1973 eUsePtr<iDVBChannel> channel;
1974 if(!m_service_handler.getChannel(channel))
1976 ePtr<iDVBFrontend> fe;
1977 if(!channel->getFrontend(fe))
1978 fe->getTransponderData(ret, original);
1986 PyObject *eDVBServiceBase::getAll(bool original)
1988 ePyObject ret = getTransponderData(original);
1991 eUsePtr<iDVBChannel> channel;
1992 if(!m_service_handler.getChannel(channel))
1994 ePtr<iDVBFrontend> fe;
1995 if(!channel->getFrontend(fe))
1997 fe->getFrontendData(ret);
1998 fe->getFrontendStatus(ret);
2005 int eDVBServicePlay::getNumberOfSubservices()
2007 ePtr<eServiceEvent> evt;
2008 if (!m_event_handler.getEvent(evt, 0))
2009 return evt->getNumOfLinkageServices();
2013 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2015 ePtr<eServiceEvent> evt;
2016 if (!m_event_handler.getEvent(evt, 0))
2018 if (!evt->getLinkageService(sub, m_reference, n))
2021 sub.type=eServiceReference::idInvalid;
2025 RESULT eDVBServicePlay::startTimeshift()
2027 ePtr<iDVBDemux> demux;
2029 eDebug("Start timeshift!");
2031 if (m_timeshift_enabled)
2034 /* start recording with the data demux. */
2035 if (m_service_handler.getDataDemux(demux))
2038 demux->createTSRecorder(m_record);
2043 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2044 eDebug("could not query ts path");
2047 tspath.append("/timeshift.XXXXXX");
2049 templ = new char[tspath.length() + 1];
2050 strcpy(templ, tspath.c_str());
2052 m_timeshift_fd = mkstemp(templ);
2053 m_timeshift_file = std::string(templ);
2055 eDebug("recording to %s", templ);
2059 if (m_timeshift_fd < 0)
2065 m_record->setTargetFD(m_timeshift_fd);
2067 m_timeshift_enabled = 1;
2069 updateTimeshiftPids();
2075 RESULT eDVBServicePlay::stopTimeshift()
2077 if (!m_timeshift_enabled)
2082 m_timeshift_enabled = 0;
2087 close(m_timeshift_fd);
2088 eDebug("remove timeshift file");
2089 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2094 int eDVBServicePlay::isTimeshiftActive()
2096 return m_timeshift_enabled && m_timeshift_active;
2099 RESULT eDVBServicePlay::activateTimeshift()
2101 if (!m_timeshift_enabled)
2104 if (!m_timeshift_active)
2106 switchToTimeshift();
2113 PyObject *eDVBServicePlay::getCutList()
2115 ePyObject list = PyList_New(0);
2117 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2119 ePyObject tuple = PyTuple_New(2);
2120 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2121 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2122 PyList_Append(list, tuple);
2129 void eDVBServicePlay::setCutList(ePyObject list)
2131 if (!PyList_Check(list))
2133 int size = PyList_Size(list);
2136 m_cue_entries.clear();
2138 for (i=0; i<size; ++i)
2140 ePyObject tuple = PyList_GET_ITEM(list, i);
2141 if (!PyTuple_Check(tuple))
2143 eDebug("non-tuple in cutlist");
2146 if (PyTuple_Size(tuple) != 2)
2148 eDebug("cutlist entries need to be a 2-tuple");
2151 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2152 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2154 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2157 pts_t pts = PyLong_AsLongLong(ppts);
2158 int type = PyInt_AsLong(ptype);
2159 m_cue_entries.insert(cueEntry(pts, type));
2160 eDebug("adding %08llx, %d", pts, type);
2162 m_cuesheet_changed = 1;
2164 cutlistToCuesheet();
2165 m_event((iPlayableService*)this, evCuesheetChanged);
2168 void eDVBServicePlay::setCutListEnable(int enable)
2170 m_cutlist_enabled = enable;
2171 cutlistToCuesheet();
2174 void eDVBServicePlay::updateTimeshiftPids()
2179 eDVBServicePMTHandler::program program;
2180 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2182 if (h.getProgramInfo(program))
2186 std::set<int> pids_to_record;
2187 pids_to_record.insert(0); // PAT
2188 if (program.pmtPid != -1)
2189 pids_to_record.insert(program.pmtPid); // PMT
2191 if (program.textPid != -1)
2192 pids_to_record.insert(program.textPid); // Videotext
2194 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2195 i(program.videoStreams.begin());
2196 i != program.videoStreams.end(); ++i)
2197 pids_to_record.insert(i->pid);
2199 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2200 i(program.audioStreams.begin());
2201 i != program.audioStreams.end(); ++i)
2202 pids_to_record.insert(i->pid);
2204 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2205 i(program.subtitleStreams.begin());
2206 i != program.subtitleStreams.end(); ++i)
2207 pids_to_record.insert(i->pid);
2209 std::set<int> new_pids, obsolete_pids;
2211 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2212 m_pids_active.begin(), m_pids_active.end(),
2213 std::inserter(new_pids, new_pids.begin()));
2215 std::set_difference(
2216 m_pids_active.begin(), m_pids_active.end(),
2217 pids_to_record.begin(), pids_to_record.end(),
2218 std::inserter(new_pids, new_pids.begin())
2221 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2222 m_record->addPID(*i);
2224 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2225 m_record->removePID(*i);
2229 void eDVBServicePlay::switchToLive()
2231 if (!m_timeshift_active)
2234 eDebug("SwitchToLive");
2239 m_teletext_parser = 0;
2241 m_subtitle_parser = 0;
2242 m_new_dvb_subtitle_page_connection = 0;
2243 m_new_subtitle_page_connection = 0;
2244 m_rds_decoder_event_connection = 0;
2245 m_video_event_connection = 0;
2246 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2248 /* free the timeshift service handler, we need the resources */
2249 m_service_handler_timeshift.free();
2250 m_timeshift_active = 0;
2251 m_timeshift_changed = 1;
2253 m_event((iPlayableService*)this, evSeekableStatusChanged);
2258 void eDVBServicePlay::switchToTimeshift()
2260 if (m_timeshift_active)
2265 m_teletext_parser = 0;
2267 m_subtitle_parser = 0;
2268 m_new_subtitle_page_connection = 0;
2269 m_new_dvb_subtitle_page_connection = 0;
2270 m_rds_decoder_event_connection = 0;
2271 m_video_event_connection = 0;
2273 m_timeshift_active = 1;
2274 m_timeshift_changed = 1;
2276 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2277 r.path = m_timeshift_file;
2279 m_cue = new eCueSheet();
2280 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2282 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2284 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2286 m_event((iPlayableService*)this, evSeekableStatusChanged);
2289 void eDVBServicePlay::updateDecoder()
2291 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2293 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2295 eDVBServicePMTHandler::program program;
2296 if (h.getProgramInfo(program))
2297 eDebug("getting program info failed.");
2300 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2301 if (!program.videoStreams.empty())
2303 eDebugNoNewLine(" (");
2304 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2305 i(program.videoStreams.begin());
2306 i != program.videoStreams.end(); ++i)
2313 if (i != program.videoStreams.begin())
2314 eDebugNoNewLine(", ");
2315 eDebugNoNewLine("%04x", i->pid);
2317 eDebugNoNewLine(")");
2319 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2320 if (!program.audioStreams.empty())
2322 eDebugNoNewLine(" (");
2323 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2324 i(program.audioStreams.begin());
2325 i != program.audioStreams.end(); ++i)
2327 if (i != program.audioStreams.begin())
2328 eDebugNoNewLine(", ");
2329 eDebugNoNewLine("%04x", i->pid);
2331 eDebugNoNewLine(")");
2333 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2334 pcrpid = program.pcrPid;
2335 eDebug(", and the text pid is %04x", program.textPid);
2336 tpid = program.textPid;
2341 h.getDecodeDemux(m_decode_demux);
2342 if (m_timeshift_changed)
2346 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2348 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2351 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2352 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2353 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2354 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2355 if (m_timeshift_changed)
2357 ePyObject subs = getCachedSubtitle();
2358 if (subs != Py_None)
2360 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2361 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2362 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2363 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2364 if (type == 0) // dvb
2365 m_subtitle_parser->start(pid, comp_page, anc_page);
2366 else if (type == 1) // ttx
2367 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2372 m_decoder->play(); /* pids will be set later */
2375 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2376 m_decoder->play(); /* pids will be set later. */
2379 m_timeshift_changed = 0;
2385 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2386 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2387 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2391 eServiceReferenceDVB ref;
2392 m_service_handler.getServiceReference(ref);
2393 eServiceReferenceDVB parent = ref.getParentServiceReference();
2398 ePtr<eDVBResourceManager> res_mgr;
2399 if (!eDVBResourceManager::getInstance(res_mgr))
2401 ePtr<iDVBChannelList> db;
2402 if (!res_mgr->getChannelList(db))
2404 ePtr<eDVBService> origService;
2405 if (!db->getService(parent, origService))
2407 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2408 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2415 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2416 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2418 m_decoder->setVideoPID(vpid, vpidtype);
2419 selectAudioStream();
2421 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2422 m_decoder->setSyncPCR(pcrpid);
2424 m_decoder->setSyncPCR(-1);
2428 m_decoder->setTextPID(tpid);
2429 m_teletext_parser->start(program.textPid);
2432 if (vpid > 0 && vpid < 0x2000)
2436 std::string radio_pic;
2437 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2438 m_decoder->setRadioPic(radio_pic);
2442 m_decoder->setAudioChannel(achannel);
2444 /* don't worry about non-existing services, nor pvr services */
2447 /* (audio pid will be set in selectAudioTrack */
2448 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2449 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2450 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2451 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2454 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2457 void eDVBServicePlay::loadCuesheet()
2459 std::string filename = m_reference.path + ".cuts";
2461 m_cue_entries.clear();
2463 FILE *f = fopen(filename.c_str(), "rb");
2467 eDebug("loading cuts..");
2470 unsigned long long where;
2473 if (!fread(&where, sizeof(where), 1, f))
2475 if (!fread(&what, sizeof(what), 1, f))
2478 #if BYTE_ORDER == LITTLE_ENDIAN
2479 where = bswap_64(where);
2486 m_cue_entries.insert(cueEntry(where, what));
2489 eDebug("%d entries", m_cue_entries.size());
2491 eDebug("cutfile not found!");
2493 m_cuesheet_changed = 0;
2494 cutlistToCuesheet();
2495 m_event((iPlayableService*)this, evCuesheetChanged);
2498 void eDVBServicePlay::saveCuesheet()
2500 std::string filename = m_reference.path + ".cuts";
2502 FILE *f = fopen(filename.c_str(), "wb");
2506 unsigned long long where;
2509 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2511 #if BYTE_ORDER == BIG_ENDIAN
2514 where = bswap_64(i->where);
2516 what = htonl(i->what);
2517 fwrite(&where, sizeof(where), 1, f);
2518 fwrite(&what, sizeof(what), 1, f);
2524 m_cuesheet_changed = 0;
2527 void eDVBServicePlay::cutlistToCuesheet()
2531 eDebug("no cue sheet");
2536 if (!m_cutlist_enabled)
2538 m_cue->commitSpans();
2539 eDebug("cutlists were disabled");
2543 pts_t in = 0, out = 0, length = 0;
2547 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2549 int have_any_span = 0;
2553 if (i == m_cue_entries.end())
2559 if (i->what == 0) /* in */
2563 } else if (i->what == 1) /* out */
2565 else /* mark (2) or last play position (3) */
2584 m_cue->addSourceSpan(in, out);
2589 if (i == m_cue_entries.end())
2592 m_cue->commitSpans();
2595 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2597 if (m_subtitle_widget)
2598 disableSubtitles(parent);
2601 int tuplesize = PyTuple_Size(tuple);
2604 if (!PyTuple_Check(tuple))
2610 entry = PyTuple_GET_ITEM(tuple, 0);
2612 if (!PyInt_Check(entry))
2615 type = PyInt_AsLong(entry);
2617 if (type == 1) // teletext subtitles
2619 int page, magazine, pid;
2623 if (!m_teletext_parser)
2625 eDebug("enable teletext subtitles.. no parser !!!");
2629 entry = PyTuple_GET_ITEM(tuple, 1);
2630 if (!PyInt_Check(entry))
2632 pid = PyInt_AsLong(entry);
2634 entry = PyTuple_GET_ITEM(tuple, 2);
2635 if (!PyInt_Check(entry))
2637 page = PyInt_AsLong(entry);
2639 entry = PyTuple_GET_ITEM(tuple, 3);
2640 if (!PyInt_Check(entry))
2642 magazine = PyInt_AsLong(entry);
2644 m_subtitle_widget = new eSubtitleWidget(parent);
2645 m_subtitle_widget->resize(parent->size()); /* full size */
2646 m_teletext_parser->setPageAndMagazine(page, magazine);
2648 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2652 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2653 if (!m_subtitle_parser)
2655 eDebug("enable dvb subtitles.. no parser !!!");
2661 entry = PyTuple_GET_ITEM(tuple, 1);
2662 if (!PyInt_Check(entry))
2664 pid = PyInt_AsLong(entry);
2666 entry = PyTuple_GET_ITEM(tuple, 2);
2667 if (!PyInt_Check(entry))
2669 composition_page_id = PyInt_AsLong(entry);
2671 entry = PyTuple_GET_ITEM(tuple, 3);
2672 if (!PyInt_Check(entry))
2674 ancillary_page_id = PyInt_AsLong(entry);
2676 m_subtitle_widget = new eSubtitleWidget(parent);
2677 m_subtitle_widget->resize(parent->size()); /* full size */
2678 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2680 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2686 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2687 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2688 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2692 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2694 delete m_subtitle_widget;
2695 m_subtitle_widget = 0;
2696 if (m_subtitle_parser)
2698 m_subtitle_parser->stop();
2699 m_dvb_subtitle_pages.clear();
2701 if (m_teletext_parser)
2703 m_teletext_parser->setPageAndMagazine(-1, -1);
2704 m_subtitle_pages.clear();
2707 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2711 PyObject *eDVBServicePlay::getCachedSubtitle()
2715 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2718 unsigned int data = (unsigned int)tmp;
2719 int pid = (data&0xFFFF0000)>>16;
2720 ePyObject tuple = PyTuple_New(4);
2721 eDVBServicePMTHandler::program program;
2722 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2723 if (!h.getProgramInfo(program))
2725 if (program.textPid==pid) // teletext
2726 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2728 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2729 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2730 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2731 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2739 PyObject *eDVBServicePlay::getSubtitleList()
2741 if (!m_teletext_parser)
2744 ePyObject l = PyList_New(0);
2745 std::set<int> added_ttx_pages;
2747 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2748 m_teletext_parser->m_found_subtitle_pages;
2750 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2751 eDVBServicePMTHandler::program program;
2752 if (h.getProgramInfo(program))
2753 eDebug("getting program info failed.");
2756 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2757 it != program.subtitleStreams.end(); ++it)
2759 switch(it->subtitling_type)
2761 case 0x01: // ebu teletext subtitles
2763 int page_number = it->teletext_page_number & 0xFF;
2764 int magazine_number = it->teletext_magazine_number & 7;
2765 int hash = magazine_number << 8 | page_number;
2766 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2768 ePyObject tuple = PyTuple_New(5);
2769 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2770 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2771 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2772 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2773 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2774 PyList_Append(l, tuple);
2776 added_ttx_pages.insert(hash);
2781 case 0x20 ... 0x23: // dvb subtitles
2783 ePyObject tuple = PyTuple_New(5);
2784 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2785 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2786 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2787 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2788 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2789 PyList_Insert(l, 0, tuple);
2797 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2798 it != subs.end(); ++it)
2800 int page_number = it->teletext_page_number & 0xFF;
2801 int magazine_number = it->teletext_magazine_number & 7;
2802 int hash = magazine_number << 8 | page_number;
2803 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2805 ePyObject tuple = PyTuple_New(5);
2806 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2807 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2808 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2809 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2810 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2811 PyList_Append(l, tuple);
2819 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2821 if (m_subtitle_widget)
2825 m_decoder->getPTS(0, pos);
2826 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2827 m_subtitle_pages.push_back(page);
2828 checkSubtitleTiming();
2832 void eDVBServicePlay::checkSubtitleTiming()
2834 eDebug("checkSubtitleTiming");
2835 if (!m_subtitle_widget)
2839 enum { TELETEXT, DVB } type;
2840 eDVBTeletextSubtitlePage page;
2841 eDVBSubtitlePage dvb_page;
2843 if (!m_subtitle_pages.empty())
2845 page = m_subtitle_pages.front();
2847 show_time = page.m_pts;
2849 else if (!m_dvb_subtitle_pages.empty())
2851 dvb_page = m_dvb_subtitle_pages.front();
2853 show_time = dvb_page.m_show_time;
2861 m_decoder->getPTS(0, pos);
2863 eDebug("%lld %lld", pos, show_time);
2864 int diff = show_time - pos;
2865 if (type == TELETEXT && !page.m_have_pts)
2867 eDebug("ttx subtitle page without pts... immediate show");
2872 eDebug("[late (%d ms)]", -diff / 90);
2875 if (abs(diff) > 1800000)
2877 eDebug("[invalid]... immediate show!");
2882 if (type == TELETEXT)
2884 eDebug("display teletext subtitle page %lld", show_time);
2885 m_subtitle_widget->setPage(page);
2886 m_subtitle_pages.pop_front();
2890 eDebug("display dvb subtitle Page %lld", show_time);
2891 m_subtitle_widget->setPage(dvb_page);
2892 m_dvb_subtitle_pages.pop_front();
2896 eDebug("start subtitle delay %d", diff / 90);
2897 m_subtitle_sync_timer->start(diff / 90, 1);
2903 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2905 if (m_subtitle_widget)
2909 m_decoder->getPTS(0, pos);
2910 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2911 m_dvb_subtitle_pages.push_back(p);
2912 checkSubtitleTiming();
2916 int eDVBServicePlay::getAC3Delay()
2919 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2921 return m_decoder->getAC3Delay();
2926 int eDVBServicePlay::getPCMDelay()
2929 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2931 return m_decoder->getPCMDelay();
2936 void eDVBServicePlay::setAC3Delay(int delay)
2939 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2941 std::string config_delay;
2942 int config_delay_int = 0;
2943 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2944 config_delay_int = atoi(config_delay.c_str());
2945 m_decoder->setAC3Delay(delay + config_delay_int);
2949 void eDVBServicePlay::setPCMDelay(int delay)
2952 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2954 std::string config_delay;
2955 int config_delay_int = 0;
2956 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2957 config_delay_int = atoi(config_delay.c_str());
2959 config_delay_int = 0;
2960 m_decoder->setPCMDelay(delay + config_delay_int);
2964 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2966 switch(event.type) {
2967 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2968 m_event((iPlayableService*)this, evVideoSizeChanged);
2970 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2971 m_event((iPlayableService*)this, evVideoFramerateChanged);
2973 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2974 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2981 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2987 PyObject *eDVBServicePlay::getStreamingData()
2989 eDVBServicePMTHandler::program program;
2990 if (m_service_handler.getProgramInfo(program))
2995 ePyObject r = program.createPythonObject();
2996 ePtr<iDVBDemux> demux;
2997 if (!m_service_handler.getDataDemux(demux))
3000 if (!demux->getCADemuxID(demux_id))
3001 PutToDict(r, "demux", demux_id);
3008 DEFINE_REF(eDVBServicePlay)
3010 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3014 case iServiceInformation::sTransponderData:
3015 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3019 return iStaticServiceInformation::getInfoObject(ref, w);
3022 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");