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;
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);
1188 return m_decoder->setSlowMotion(ratio);
1193 RESULT eDVBServicePlay::setFastForward(int ratio)
1195 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1197 return setFastForward_internal(ratio);
1200 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1202 int skipmode, ffratio;
1208 } else if (ratio > 0)
1216 } else // if (ratio < 0)
1222 if (m_skipmode != skipmode)
1224 eDebug("setting cue skipmode to %d", skipmode);
1226 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1229 m_skipmode = skipmode;
1235 ; /* return m_decoder->play(); is done in caller*/
1236 else if (ffratio != 1)
1237 return m_decoder->setFastForward(ffratio);
1239 return m_decoder->setTrickmode();
1243 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1245 if (m_is_pvr || m_timeshift_enabled)
1255 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1256 RESULT eDVBServicePlay::getLength(pts_t &len)
1258 ePtr<iDVBPVRChannel> pvr_channel;
1260 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1263 return pvr_channel->getLength(len);
1266 RESULT eDVBServicePlay::pause()
1268 eDebug("eDVBServicePlay::pause");
1269 setFastForward_internal(0);
1273 return m_decoder->pause();
1278 RESULT eDVBServicePlay::unpause()
1280 eDebug("eDVBServicePlay::unpause");
1281 setFastForward_internal(0);
1285 return m_decoder->play();
1290 RESULT eDVBServicePlay::seekTo(pts_t to)
1292 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1294 if (!m_decode_demux)
1297 ePtr<iDVBPVRChannel> pvr_channel;
1299 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1305 m_cue->seekTo(0, to);
1306 m_dvb_subtitle_pages.clear();
1307 m_subtitle_pages.clear();
1312 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1314 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1316 if (!m_decode_demux)
1319 ePtr<iDVBPVRChannel> pvr_channel;
1321 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1326 /* HACK until we have skip-AP api */
1327 if ((to > 0) && (to < 100))
1335 m_cue->seekTo(mode, to);
1336 m_dvb_subtitle_pages.clear();
1337 m_subtitle_pages.clear();
1341 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1343 ePtr<iDVBPVRChannel> pvr_channel;
1345 if (!m_decode_demux)
1348 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1353 /* if there is a decoder, use audio or video PTS */
1356 r = m_decoder->getPTS(0, pos);
1362 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1365 RESULT eDVBServicePlay::setTrickmode(int trick)
1367 /* currently unimplemented */
1371 RESULT eDVBServicePlay::isCurrentlySeekable()
1376 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1377 if (m_decoder->getVideoWidth() == -1)
1383 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1389 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1395 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1401 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1407 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1413 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1416 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1417 (m_timeshift_enabled || !m_is_pvr))
1419 if (!m_timeshift_enabled)
1421 /* query config path */
1423 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1424 eDebug("could not query ts path from config");
1428 /* we need enough diskspace */
1430 if (statfs(tspath.c_str(), &fs) < 0)
1432 eDebug("statfs failed!");
1436 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1438 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1448 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1459 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1465 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1471 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1477 RESULT eDVBServicePlay::getName(std::string &name)
1481 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1482 return i->getName(m_reference, name);
1484 else if (m_dvb_service)
1486 m_dvb_service->getName(m_reference, name);
1490 else if (!m_reference.name.empty())
1491 eStaticServiceDVBInformation().getName(m_reference, name);
1493 name = "DVB service";
1497 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1499 return m_event_handler.getEvent(evt, nownext);
1502 int eDVBServicePlay::getInfo(int w)
1504 eDVBServicePMTHandler::program program;
1507 return resIsPyObject;
1509 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1511 int no_program_info = 0;
1513 if (h.getProgramInfo(program))
1514 no_program_info = 1;
1520 return m_decoder->getVideoHeight();
1524 return m_decoder->getVideoWidth();
1528 return m_decoder->getVideoFrameRate();
1532 return m_decoder->getVideoProgressive();
1538 aspect = m_decoder->getVideoAspect();
1539 if (aspect == -1 && no_program_info)
1541 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1543 ePtr<eServiceEvent> evt;
1544 if (!m_event_handler.getEvent(evt, 0))
1546 ePtr<eComponentData> data;
1547 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1549 if ( data->getStreamContent() == 1 )
1551 switch(data->getComponentType())
1554 case 1: // 4:3 SD PAL
1556 case 3: // 16:9 SD PAL
1557 case 4: // > 16:9 PAL
1558 case 5: // 4:3 SD NTSC
1560 case 7: // 16:9 SD NTSC
1561 case 8: // > 16:9 NTSC
1564 case 9: // 4:3 HD PAL
1566 case 0xB: // 16:9 HD PAL
1567 case 0xC: // > 16:9 HD PAL
1568 case 0xD: // 4:3 HD NTSC
1570 case 0xF: // 16:9 HD NTSC
1571 case 0x10: // > 16:9 HD PAL
1572 return data->getComponentType();
1582 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1586 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1590 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1591 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1595 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1598 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1602 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1606 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1610 if (no_program_info) return -1; return program.pcrPid;
1611 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1612 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1613 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1614 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1615 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1616 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1617 case sProvider: if (!m_dvb_service) return -1; return -2;
1618 case sServiceref: return resIsString;
1619 case sDVBState: return m_tune_state;
1626 std::string eDVBServicePlay::getInfoString(int w)
1631 if (!m_dvb_service) return "";
1632 return m_dvb_service->m_provider_name;
1634 return m_reference.toString();
1638 return iServiceInformation::getInfoString(w);
1641 PyObject *eDVBServicePlay::getInfoObject(int w)
1646 return m_service_handler.getCaIds();
1647 case sTransponderData:
1648 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1652 return iServiceInformation::getInfoObject(w);
1655 int eDVBServicePlay::getNumberOfTracks()
1657 eDVBServicePMTHandler::program program;
1658 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1659 if (h.getProgramInfo(program))
1661 return program.audioStreams.size();
1664 int eDVBServicePlay::getCurrentTrack()
1666 eDVBServicePMTHandler::program program;
1667 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1668 if (h.getProgramInfo(program))
1671 int max = program.audioStreams.size();
1674 for (i = 0; i < max; ++i)
1675 if (program.audioStreams[i].pid == m_current_audio_pid)
1681 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1683 int ret = selectAudioStream(i);
1685 if (m_decoder->set())
1691 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1693 eDVBServicePMTHandler::program program;
1694 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1696 if (h.getProgramInfo(program))
1699 if (i >= program.audioStreams.size())
1702 info.m_pid = program.audioStreams[i].pid;
1704 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1705 info.m_description = "MPEG";
1706 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1707 info.m_description = "AC3";
1708 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1709 info.m_description = "AAC";
1710 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1711 info.m_description = "AAC-HE";
1712 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1713 info.m_description = "DTS";
1715 info.m_description = "???";
1717 if (program.audioStreams[i].component_tag != -1)
1719 ePtr<eServiceEvent> evt;
1720 if (!m_event_handler.getEvent(evt, 0))
1722 ePtr<eComponentData> data;
1723 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1724 info.m_language = data->getText();
1728 if (info.m_language.empty())
1729 info.m_language = program.audioStreams[i].language_code;
1734 int eDVBServicePlay::selectAudioStream(int i)
1736 eDVBServicePMTHandler::program program;
1737 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1739 if (h.getProgramInfo(program))
1742 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1750 stream = program.defaultAudioStream;
1752 int apid = -1, apidtype = -1;
1754 if (((unsigned int)stream) < program.audioStreams.size())
1756 apid = program.audioStreams[stream].pid;
1757 apidtype = program.audioStreams[stream].type;
1760 m_current_audio_pid = apid;
1762 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1764 eDebug("set audio pid failed");
1770 /* 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 */
1771 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1773 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1775 rdsPid = program.audioStreams[stream].rdsPid;
1776 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1779 ePtr<iDVBDemux> data_demux;
1780 if (!h.getDataDemux(data_demux))
1782 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1783 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1784 m_rds_decoder->start(rdsPid);
1789 /* store new pid as default only when:
1790 a.) we have an entry in the service db for the current service,
1791 b.) we are not playing back something,
1792 c.) we are not selecting the default entry. (we wouldn't change
1793 anything in the best case, or destroy the default setting in
1794 case the real default is not yet available.)
1796 if (m_dvb_service && ((i != -1)
1797 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1799 if (apidtype == eDVBAudio::aMPEG)
1801 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1802 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1804 else if (apidtype == eDVBAudio::aAC3)
1806 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1807 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1811 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1812 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1816 h.resetCachedProgram();
1821 int eDVBServicePlay::getCurrentChannel()
1823 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1826 RESULT eDVBServicePlay::selectChannel(int i)
1828 if (i < LEFT || i > RIGHT || i == STEREO)
1831 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1833 m_decoder->setAudioChannel(i);
1837 std::string eDVBServicePlay::getText(int x)
1843 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1845 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1850 void eDVBServicePlay::rdsDecoderEvent(int what)
1854 case eDVBRdsDecoder::RadioTextChanged:
1855 m_event((iPlayableService*)this, evUpdatedRadioText);
1857 case eDVBRdsDecoder::RtpTextChanged:
1858 m_event((iPlayableService*)this, evUpdatedRtpText);
1860 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1861 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1863 case eDVBRdsDecoder::RecvRassSlidePic:
1864 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1869 void eDVBServicePlay::showRassSlidePicture()
1875 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1876 if (rass_slide_pic.length())
1877 m_decoder->showSinglePic(rass_slide_pic.c_str());
1879 eDebug("empty filename for rass slide picture received!!");
1882 eDebug("no MPEG Decoder to show iframes avail");
1885 eDebug("showRassSlidePicture called.. but not decoder");
1888 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1894 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1895 if (rass_interactive_pic.length())
1896 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1898 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1901 eDebug("no MPEG Decoder to show iframes avail");
1904 eDebug("showRassInteractivePic called.. but not decoder");
1907 ePyObject eDVBServicePlay::getRassInteractiveMask()
1910 return m_rds_decoder->getRassPictureMask();
1914 int eDVBServiceBase::getFrontendInfo(int w)
1916 eUsePtr<iDVBChannel> channel;
1917 if(m_service_handler.getChannel(channel))
1919 ePtr<iDVBFrontend> fe;
1920 if(channel->getFrontend(fe))
1922 return fe->readFrontendData(w);
1925 PyObject *eDVBServiceBase::getFrontendData()
1927 ePyObject ret = PyDict_New();
1930 eUsePtr<iDVBChannel> channel;
1931 if(!m_service_handler.getChannel(channel))
1933 ePtr<iDVBFrontend> fe;
1934 if(!channel->getFrontend(fe))
1935 fe->getFrontendData(ret);
1943 PyObject *eDVBServiceBase::getFrontendStatus()
1945 ePyObject ret = PyDict_New();
1948 eUsePtr<iDVBChannel> channel;
1949 if(!m_service_handler.getChannel(channel))
1951 ePtr<iDVBFrontend> fe;
1952 if(!channel->getFrontend(fe))
1953 fe->getFrontendStatus(ret);
1961 PyObject *eDVBServiceBase::getTransponderData(bool original)
1963 ePyObject ret = PyDict_New();
1966 eUsePtr<iDVBChannel> channel;
1967 if(!m_service_handler.getChannel(channel))
1969 ePtr<iDVBFrontend> fe;
1970 if(!channel->getFrontend(fe))
1971 fe->getTransponderData(ret, original);
1979 PyObject *eDVBServiceBase::getAll(bool original)
1981 ePyObject ret = getTransponderData(original);
1984 eUsePtr<iDVBChannel> channel;
1985 if(!m_service_handler.getChannel(channel))
1987 ePtr<iDVBFrontend> fe;
1988 if(!channel->getFrontend(fe))
1990 fe->getFrontendData(ret);
1991 fe->getFrontendStatus(ret);
1998 int eDVBServicePlay::getNumberOfSubservices()
2000 ePtr<eServiceEvent> evt;
2001 if (!m_event_handler.getEvent(evt, 0))
2002 return evt->getNumOfLinkageServices();
2006 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2008 ePtr<eServiceEvent> evt;
2009 if (!m_event_handler.getEvent(evt, 0))
2011 if (!evt->getLinkageService(sub, m_reference, n))
2014 sub.type=eServiceReference::idInvalid;
2018 RESULT eDVBServicePlay::startTimeshift()
2020 ePtr<iDVBDemux> demux;
2022 eDebug("Start timeshift!");
2024 if (m_timeshift_enabled)
2027 /* start recording with the data demux. */
2028 if (m_service_handler.getDataDemux(demux))
2031 demux->createTSRecorder(m_record);
2036 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2037 eDebug("could not query ts path");
2040 tspath.append("/timeshift.XXXXXX");
2042 templ = new char[tspath.length() + 1];
2043 strcpy(templ, tspath.c_str());
2045 m_timeshift_fd = mkstemp(templ);
2046 m_timeshift_file = std::string(templ);
2048 eDebug("recording to %s", templ);
2052 if (m_timeshift_fd < 0)
2058 m_record->setTargetFD(m_timeshift_fd);
2060 m_timeshift_enabled = 1;
2062 updateTimeshiftPids();
2068 RESULT eDVBServicePlay::stopTimeshift()
2070 if (!m_timeshift_enabled)
2075 m_timeshift_enabled = 0;
2080 close(m_timeshift_fd);
2081 eDebug("remove timeshift file");
2082 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2087 int eDVBServicePlay::isTimeshiftActive()
2089 return m_timeshift_enabled && m_timeshift_active;
2092 RESULT eDVBServicePlay::activateTimeshift()
2094 if (!m_timeshift_enabled)
2097 if (!m_timeshift_active)
2099 switchToTimeshift();
2106 PyObject *eDVBServicePlay::getCutList()
2108 ePyObject list = PyList_New(0);
2110 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2112 ePyObject tuple = PyTuple_New(2);
2113 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2114 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2115 PyList_Append(list, tuple);
2122 void eDVBServicePlay::setCutList(ePyObject list)
2124 if (!PyList_Check(list))
2126 int size = PyList_Size(list);
2129 m_cue_entries.clear();
2131 for (i=0; i<size; ++i)
2133 ePyObject tuple = PyList_GET_ITEM(list, i);
2134 if (!PyTuple_Check(tuple))
2136 eDebug("non-tuple in cutlist");
2139 if (PyTuple_Size(tuple) != 2)
2141 eDebug("cutlist entries need to be a 2-tuple");
2144 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2145 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2147 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2150 pts_t pts = PyLong_AsLongLong(ppts);
2151 int type = PyInt_AsLong(ptype);
2152 m_cue_entries.insert(cueEntry(pts, type));
2153 eDebug("adding %08llx, %d", pts, type);
2155 m_cuesheet_changed = 1;
2157 cutlistToCuesheet();
2158 m_event((iPlayableService*)this, evCuesheetChanged);
2161 void eDVBServicePlay::setCutListEnable(int enable)
2163 m_cutlist_enabled = enable;
2164 cutlistToCuesheet();
2167 void eDVBServicePlay::updateTimeshiftPids()
2172 eDVBServicePMTHandler::program program;
2173 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2175 if (h.getProgramInfo(program))
2179 std::set<int> pids_to_record;
2180 pids_to_record.insert(0); // PAT
2181 if (program.pmtPid != -1)
2182 pids_to_record.insert(program.pmtPid); // PMT
2184 if (program.textPid != -1)
2185 pids_to_record.insert(program.textPid); // Videotext
2187 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2188 i(program.videoStreams.begin());
2189 i != program.videoStreams.end(); ++i)
2190 pids_to_record.insert(i->pid);
2192 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2193 i(program.audioStreams.begin());
2194 i != program.audioStreams.end(); ++i)
2195 pids_to_record.insert(i->pid);
2197 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2198 i(program.subtitleStreams.begin());
2199 i != program.subtitleStreams.end(); ++i)
2200 pids_to_record.insert(i->pid);
2202 std::set<int> new_pids, obsolete_pids;
2204 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2205 m_pids_active.begin(), m_pids_active.end(),
2206 std::inserter(new_pids, new_pids.begin()));
2208 std::set_difference(
2209 m_pids_active.begin(), m_pids_active.end(),
2210 pids_to_record.begin(), pids_to_record.end(),
2211 std::inserter(new_pids, new_pids.begin())
2214 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2215 m_record->addPID(*i);
2217 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2218 m_record->removePID(*i);
2222 void eDVBServicePlay::switchToLive()
2224 if (!m_timeshift_active)
2227 eDebug("SwitchToLive");
2232 m_teletext_parser = 0;
2234 m_subtitle_parser = 0;
2235 m_new_dvb_subtitle_page_connection = 0;
2236 m_new_subtitle_page_connection = 0;
2237 m_rds_decoder_event_connection = 0;
2238 m_video_event_connection = 0;
2239 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2241 /* free the timeshift service handler, we need the resources */
2242 m_service_handler_timeshift.free();
2243 m_timeshift_active = 0;
2244 m_timeshift_changed = 1;
2246 m_event((iPlayableService*)this, evSeekableStatusChanged);
2251 void eDVBServicePlay::switchToTimeshift()
2253 if (m_timeshift_active)
2258 m_teletext_parser = 0;
2260 m_subtitle_parser = 0;
2261 m_new_subtitle_page_connection = 0;
2262 m_new_dvb_subtitle_page_connection = 0;
2263 m_rds_decoder_event_connection = 0;
2264 m_video_event_connection = 0;
2266 m_timeshift_active = 1;
2267 m_timeshift_changed = 1;
2269 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2270 r.path = m_timeshift_file;
2272 m_cue = new eCueSheet();
2273 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2275 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2277 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2279 m_event((iPlayableService*)this, evSeekableStatusChanged);
2282 void eDVBServicePlay::updateDecoder()
2284 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2286 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2288 eDVBServicePMTHandler::program program;
2289 if (h.getProgramInfo(program))
2290 eDebug("getting program info failed.");
2293 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2294 if (!program.videoStreams.empty())
2296 eDebugNoNewLine(" (");
2297 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2298 i(program.videoStreams.begin());
2299 i != program.videoStreams.end(); ++i)
2306 if (i != program.videoStreams.begin())
2307 eDebugNoNewLine(", ");
2308 eDebugNoNewLine("%04x", i->pid);
2310 eDebugNoNewLine(")");
2312 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2313 if (!program.audioStreams.empty())
2315 eDebugNoNewLine(" (");
2316 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2317 i(program.audioStreams.begin());
2318 i != program.audioStreams.end(); ++i)
2320 if (i != program.audioStreams.begin())
2321 eDebugNoNewLine(", ");
2322 eDebugNoNewLine("%04x", i->pid);
2324 eDebugNoNewLine(")");
2326 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2327 pcrpid = program.pcrPid;
2328 eDebug(", and the text pid is %04x", program.textPid);
2329 tpid = program.textPid;
2334 h.getDecodeDemux(m_decode_demux);
2335 if (m_timeshift_changed)
2339 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2341 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2344 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2345 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2346 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2347 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2348 if (m_timeshift_changed)
2350 ePyObject subs = getCachedSubtitle();
2351 if (subs != Py_None)
2353 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2354 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2355 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2356 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2357 if (type == 0) // dvb
2358 m_subtitle_parser->start(pid, comp_page, anc_page);
2359 else if (type == 1) // ttx
2360 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2365 m_decoder->play(); /* pids will be set later */
2368 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2369 m_decoder->play(); /* pids will be set later. */
2372 m_timeshift_changed = 0;
2378 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2379 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2380 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2384 eServiceReferenceDVB ref;
2385 m_service_handler.getServiceReference(ref);
2386 eServiceReferenceDVB parent = ref.getParentServiceReference();
2391 ePtr<eDVBResourceManager> res_mgr;
2392 if (!eDVBResourceManager::getInstance(res_mgr))
2394 ePtr<iDVBChannelList> db;
2395 if (!res_mgr->getChannelList(db))
2397 ePtr<eDVBService> origService;
2398 if (!db->getService(parent, origService))
2400 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2401 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2408 std::string config_delay;
2409 int config_delay_int = 0;
2410 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2411 config_delay_int = atoi(config_delay.c_str());
2412 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2414 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2415 config_delay_int = atoi(config_delay.c_str());
2417 config_delay_int = 0;
2418 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2420 m_decoder->setVideoPID(vpid, vpidtype);
2421 selectAudioStream();
2423 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2424 m_decoder->setSyncPCR(pcrpid);
2426 m_decoder->setSyncPCR(-1);
2430 m_decoder->setTextPID(tpid);
2431 m_teletext_parser->start(program.textPid);
2434 if (vpid > 0 && vpid < 0x2000)
2438 std::string radio_pic;
2439 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2440 m_decoder->setRadioPic(radio_pic);
2444 m_decoder->setAudioChannel(achannel);
2446 /* don't worry about non-existing services, nor pvr services */
2449 /* (audio pid will be set in selectAudioTrack */
2450 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2451 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2452 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2453 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2456 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2459 void eDVBServicePlay::loadCuesheet()
2461 std::string filename = m_reference.path + ".cuts";
2463 m_cue_entries.clear();
2465 FILE *f = fopen(filename.c_str(), "rb");
2469 eDebug("loading cuts..");
2472 unsigned long long where;
2475 if (!fread(&where, sizeof(where), 1, f))
2477 if (!fread(&what, sizeof(what), 1, f))
2480 #if BYTE_ORDER == LITTLE_ENDIAN
2481 where = bswap_64(where);
2488 m_cue_entries.insert(cueEntry(where, what));
2491 eDebug("%d entries", m_cue_entries.size());
2493 eDebug("cutfile not found!");
2495 m_cuesheet_changed = 0;
2496 cutlistToCuesheet();
2497 m_event((iPlayableService*)this, evCuesheetChanged);
2500 void eDVBServicePlay::saveCuesheet()
2502 std::string filename = m_reference.path + ".cuts";
2504 FILE *f = fopen(filename.c_str(), "wb");
2508 unsigned long long where;
2511 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2513 #if BYTE_ORDER == BIG_ENDIAN
2516 where = bswap_64(i->where);
2518 what = htonl(i->what);
2519 fwrite(&where, sizeof(where), 1, f);
2520 fwrite(&what, sizeof(what), 1, f);
2526 m_cuesheet_changed = 0;
2529 void eDVBServicePlay::cutlistToCuesheet()
2533 eDebug("no cue sheet");
2538 if (!m_cutlist_enabled)
2540 m_cue->commitSpans();
2541 eDebug("cutlists were disabled");
2545 pts_t in = 0, out = 0, length = 0;
2549 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2551 int have_any_span = 0;
2555 if (i == m_cue_entries.end())
2561 if (i->what == 0) /* in */
2565 } else if (i->what == 1) /* out */
2567 else /* mark (2) or last play position (3) */
2586 m_cue->addSourceSpan(in, out);
2591 if (i == m_cue_entries.end())
2594 m_cue->commitSpans();
2597 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2599 if (m_subtitle_widget)
2600 disableSubtitles(parent);
2603 int tuplesize = PyTuple_Size(tuple);
2606 if (!PyTuple_Check(tuple))
2612 entry = PyTuple_GET_ITEM(tuple, 0);
2614 if (!PyInt_Check(entry))
2617 type = PyInt_AsLong(entry);
2619 if (type == 1) // teletext subtitles
2621 int page, magazine, pid;
2625 if (!m_teletext_parser)
2627 eDebug("enable teletext subtitles.. no parser !!!");
2631 entry = PyTuple_GET_ITEM(tuple, 1);
2632 if (!PyInt_Check(entry))
2634 pid = PyInt_AsLong(entry);
2636 entry = PyTuple_GET_ITEM(tuple, 2);
2637 if (!PyInt_Check(entry))
2639 page = PyInt_AsLong(entry);
2641 entry = PyTuple_GET_ITEM(tuple, 3);
2642 if (!PyInt_Check(entry))
2644 magazine = PyInt_AsLong(entry);
2646 m_subtitle_widget = new eSubtitleWidget(parent);
2647 m_subtitle_widget->resize(parent->size()); /* full size */
2648 m_teletext_parser->setPageAndMagazine(page, magazine);
2650 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2654 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2655 if (!m_subtitle_parser)
2657 eDebug("enable dvb subtitles.. no parser !!!");
2663 entry = PyTuple_GET_ITEM(tuple, 1);
2664 if (!PyInt_Check(entry))
2666 pid = PyInt_AsLong(entry);
2668 entry = PyTuple_GET_ITEM(tuple, 2);
2669 if (!PyInt_Check(entry))
2671 composition_page_id = PyInt_AsLong(entry);
2673 entry = PyTuple_GET_ITEM(tuple, 3);
2674 if (!PyInt_Check(entry))
2676 ancillary_page_id = PyInt_AsLong(entry);
2678 m_subtitle_widget = new eSubtitleWidget(parent);
2679 m_subtitle_widget->resize(parent->size()); /* full size */
2680 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2682 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2688 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2689 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2690 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2694 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2696 delete m_subtitle_widget;
2697 m_subtitle_widget = 0;
2698 if (m_subtitle_parser)
2700 m_subtitle_parser->stop();
2701 m_dvb_subtitle_pages.clear();
2703 if (m_teletext_parser)
2705 m_teletext_parser->setPageAndMagazine(-1, -1);
2706 m_subtitle_pages.clear();
2709 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2713 PyObject *eDVBServicePlay::getCachedSubtitle()
2717 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2720 unsigned int data = (unsigned int)tmp;
2721 int pid = (data&0xFFFF0000)>>16;
2722 ePyObject tuple = PyTuple_New(4);
2723 eDVBServicePMTHandler::program program;
2724 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2725 if (!h.getProgramInfo(program))
2727 if (program.textPid==pid) // teletext
2728 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2730 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2731 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2732 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2733 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2741 PyObject *eDVBServicePlay::getSubtitleList()
2743 if (!m_teletext_parser)
2746 ePyObject l = PyList_New(0);
2747 std::set<int> added_ttx_pages;
2749 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2750 m_teletext_parser->m_found_subtitle_pages;
2752 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2753 eDVBServicePMTHandler::program program;
2754 if (h.getProgramInfo(program))
2755 eDebug("getting program info failed.");
2758 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2759 it != program.subtitleStreams.end(); ++it)
2761 switch(it->subtitling_type)
2763 case 0x01: // ebu teletext subtitles
2765 int page_number = it->teletext_page_number & 0xFF;
2766 int magazine_number = it->teletext_magazine_number & 7;
2767 int hash = magazine_number << 8 | page_number;
2768 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2770 ePyObject tuple = PyTuple_New(5);
2771 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2772 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2773 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2774 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2775 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2776 PyList_Append(l, tuple);
2778 added_ttx_pages.insert(hash);
2783 case 0x20 ... 0x23: // dvb subtitles
2785 ePyObject tuple = PyTuple_New(5);
2786 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2787 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2788 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2789 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2790 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2791 PyList_Insert(l, 0, tuple);
2799 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2800 it != subs.end(); ++it)
2802 int page_number = it->teletext_page_number & 0xFF;
2803 int magazine_number = it->teletext_magazine_number & 7;
2804 int hash = magazine_number << 8 | page_number;
2805 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2807 ePyObject tuple = PyTuple_New(5);
2808 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2809 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2810 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2811 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2812 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2813 PyList_Append(l, tuple);
2821 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2823 if (m_subtitle_widget)
2827 m_decoder->getPTS(0, pos);
2828 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2829 m_subtitle_pages.push_back(page);
2830 checkSubtitleTiming();
2834 void eDVBServicePlay::checkSubtitleTiming()
2836 eDebug("checkSubtitleTiming");
2837 if (!m_subtitle_widget)
2841 enum { TELETEXT, DVB } type;
2842 eDVBTeletextSubtitlePage page;
2843 eDVBSubtitlePage dvb_page;
2845 if (!m_subtitle_pages.empty())
2847 page = m_subtitle_pages.front();
2849 show_time = page.m_pts;
2851 else if (!m_dvb_subtitle_pages.empty())
2853 dvb_page = m_dvb_subtitle_pages.front();
2855 show_time = dvb_page.m_show_time;
2863 m_decoder->getPTS(0, pos);
2865 eDebug("%lld %lld", pos, show_time);
2866 int diff = show_time - pos;
2867 if (type == TELETEXT && !page.m_have_pts)
2869 eDebug("ttx subtitle page without pts... immediate show");
2874 eDebug("[late (%d ms)]", -diff / 90);
2877 if (abs(diff) > 1800000)
2879 eDebug("[invalid]... immediate show!");
2884 if (type == TELETEXT)
2886 eDebug("display teletext subtitle page %lld", show_time);
2887 m_subtitle_widget->setPage(page);
2888 m_subtitle_pages.pop_front();
2892 eDebug("display dvb subtitle Page %lld", show_time);
2893 m_subtitle_widget->setPage(dvb_page);
2894 m_dvb_subtitle_pages.pop_front();
2898 eDebug("start subtitle delay %d", diff / 90);
2899 m_subtitle_sync_timer->start(diff / 90, 1);
2905 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2907 if (m_subtitle_widget)
2911 m_decoder->getPTS(0, pos);
2912 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2913 m_dvb_subtitle_pages.push_back(p);
2914 checkSubtitleTiming();
2918 int eDVBServicePlay::getAC3Delay()
2921 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2923 return m_decoder->getAC3Delay();
2928 int eDVBServicePlay::getPCMDelay()
2931 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2933 return m_decoder->getPCMDelay();
2938 void eDVBServicePlay::setAC3Delay(int delay)
2941 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2943 m_decoder->setAC3Delay(delay);
2946 void eDVBServicePlay::setPCMDelay(int delay)
2949 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2951 m_decoder->setPCMDelay(delay);
2954 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2956 switch(event.type) {
2957 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2958 m_event((iPlayableService*)this, evVideoSizeChanged);
2960 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2961 m_event((iPlayableService*)this, evVideoFramerateChanged);
2963 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2964 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2971 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2977 PyObject *eDVBServicePlay::getStreamingData()
2979 eDVBServicePMTHandler::program program;
2980 if (m_service_handler.getProgramInfo(program))
2985 ePyObject r = program.createPythonObject();
2986 ePtr<iDVBDemux> demux;
2987 if (!m_service_handler.getDataDemux(demux))
2990 if (!demux->getCADemuxID(demux_id))
2991 PutToDict(r, "demux", demux_id);
2998 DEFINE_REF(eDVBServicePlay)
3000 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3004 case iServiceInformation::sTransponderData:
3005 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3009 return iStaticServiceInformation::getInfoObject(ref, w);
3012 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");