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()
1373 return m_is_pvr || m_timeshift_active;
1376 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1382 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1388 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1394 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1400 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1406 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1409 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1410 (m_timeshift_enabled || !m_is_pvr))
1412 if (!m_timeshift_enabled)
1414 /* query config path */
1416 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1417 eDebug("could not query ts path from config");
1421 /* we need enough diskspace */
1423 if (statfs(tspath.c_str(), &fs) < 0)
1425 eDebug("statfs failed!");
1429 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1431 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1441 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1452 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1458 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1464 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1470 RESULT eDVBServicePlay::getName(std::string &name)
1474 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1475 return i->getName(m_reference, name);
1477 else if (m_dvb_service)
1479 m_dvb_service->getName(m_reference, name);
1483 else if (!m_reference.name.empty())
1484 eStaticServiceDVBInformation().getName(m_reference, name);
1486 name = "DVB service";
1490 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1492 return m_event_handler.getEvent(evt, nownext);
1495 int eDVBServicePlay::getInfo(int w)
1497 eDVBServicePMTHandler::program program;
1500 return resIsPyObject;
1502 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1504 int no_program_info = 0;
1506 if (h.getProgramInfo(program))
1507 no_program_info = 1;
1513 return m_decoder->getVideoHeight();
1517 return m_decoder->getVideoWidth();
1521 return m_decoder->getVideoFrameRate();
1525 return m_decoder->getVideoProgressive();
1531 aspect = m_decoder->getVideoAspect();
1532 if (aspect == -1 && no_program_info)
1534 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1536 ePtr<eServiceEvent> evt;
1537 if (!m_event_handler.getEvent(evt, 0))
1539 ePtr<eComponentData> data;
1540 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1542 if ( data->getStreamContent() == 1 )
1544 switch(data->getComponentType())
1547 case 1: // 4:3 SD PAL
1549 case 3: // 16:9 SD PAL
1550 case 4: // > 16:9 PAL
1551 case 5: // 4:3 SD NTSC
1553 case 7: // 16:9 SD NTSC
1554 case 8: // > 16:9 NTSC
1557 case 9: // 4:3 HD PAL
1559 case 0xB: // 16:9 HD PAL
1560 case 0xC: // > 16:9 HD PAL
1561 case 0xD: // 4:3 HD NTSC
1563 case 0xF: // 16:9 HD NTSC
1564 case 0x10: // > 16:9 HD PAL
1565 return data->getComponentType();
1575 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1579 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1583 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1584 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1588 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1591 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1595 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1599 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1603 if (no_program_info) return -1; return program.pcrPid;
1604 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1605 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1606 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1607 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1608 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1609 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1610 case sProvider: if (!m_dvb_service) return -1; return -2;
1611 case sServiceref: return resIsString;
1612 case sDVBState: return m_tune_state;
1619 std::string eDVBServicePlay::getInfoString(int w)
1624 if (!m_dvb_service) return "";
1625 return m_dvb_service->m_provider_name;
1627 return m_reference.toString();
1631 return iServiceInformation::getInfoString(w);
1634 PyObject *eDVBServicePlay::getInfoObject(int w)
1639 return m_service_handler.getCaIds();
1640 case sTransponderData:
1641 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1645 return iServiceInformation::getInfoObject(w);
1648 int eDVBServicePlay::getNumberOfTracks()
1650 eDVBServicePMTHandler::program program;
1651 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1652 if (h.getProgramInfo(program))
1654 return program.audioStreams.size();
1657 int eDVBServicePlay::getCurrentTrack()
1659 eDVBServicePMTHandler::program program;
1660 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1661 if (h.getProgramInfo(program))
1664 int max = program.audioStreams.size();
1667 for (i = 0; i < max; ++i)
1668 if (program.audioStreams[i].pid == m_current_audio_pid)
1674 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1676 int ret = selectAudioStream(i);
1678 if (m_decoder->set())
1684 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1686 eDVBServicePMTHandler::program program;
1687 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1689 if (h.getProgramInfo(program))
1692 if (i >= program.audioStreams.size())
1695 info.m_pid = program.audioStreams[i].pid;
1697 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1698 info.m_description = "MPEG";
1699 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1700 info.m_description = "AC3";
1701 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1702 info.m_description = "AAC";
1703 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1704 info.m_description = "AAC-HE";
1705 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1706 info.m_description = "DTS";
1708 info.m_description = "???";
1710 if (program.audioStreams[i].component_tag != -1)
1712 ePtr<eServiceEvent> evt;
1713 if (!m_event_handler.getEvent(evt, 0))
1715 ePtr<eComponentData> data;
1716 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1717 info.m_language = data->getText();
1721 if (info.m_language.empty())
1722 info.m_language = program.audioStreams[i].language_code;
1727 int eDVBServicePlay::selectAudioStream(int i)
1729 eDVBServicePMTHandler::program program;
1730 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1732 if (h.getProgramInfo(program))
1735 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1743 stream = program.defaultAudioStream;
1745 int apid = -1, apidtype = -1;
1747 if (((unsigned int)stream) < program.audioStreams.size())
1749 apid = program.audioStreams[stream].pid;
1750 apidtype = program.audioStreams[stream].type;
1753 m_current_audio_pid = apid;
1755 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1757 eDebug("set audio pid failed");
1763 /* 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 */
1764 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1766 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1768 rdsPid = program.audioStreams[stream].rdsPid;
1769 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1772 ePtr<iDVBDemux> data_demux;
1773 if (!h.getDataDemux(data_demux))
1775 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1776 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1777 m_rds_decoder->start(rdsPid);
1782 /* store new pid as default only when:
1783 a.) we have an entry in the service db for the current service,
1784 b.) we are not playing back something,
1785 c.) we are not selecting the default entry. (we wouldn't change
1786 anything in the best case, or destroy the default setting in
1787 case the real default is not yet available.)
1789 if (m_dvb_service && ((i != -1)
1790 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1792 if (apidtype == eDVBAudio::aMPEG)
1794 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1795 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1797 else if (apidtype == eDVBAudio::aAC3)
1799 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1800 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1804 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1805 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1809 h.resetCachedProgram();
1814 int eDVBServicePlay::getCurrentChannel()
1816 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1819 RESULT eDVBServicePlay::selectChannel(int i)
1821 if (i < LEFT || i > RIGHT || i == STEREO)
1824 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1826 m_decoder->setAudioChannel(i);
1830 std::string eDVBServicePlay::getText(int x)
1836 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1838 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1843 void eDVBServicePlay::rdsDecoderEvent(int what)
1847 case eDVBRdsDecoder::RadioTextChanged:
1848 m_event((iPlayableService*)this, evUpdatedRadioText);
1850 case eDVBRdsDecoder::RtpTextChanged:
1851 m_event((iPlayableService*)this, evUpdatedRtpText);
1853 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1854 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1856 case eDVBRdsDecoder::RecvRassSlidePic:
1857 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1862 void eDVBServicePlay::showRassSlidePicture()
1868 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1869 if (rass_slide_pic.length())
1870 m_decoder->showSinglePic(rass_slide_pic.c_str());
1872 eDebug("empty filename for rass slide picture received!!");
1875 eDebug("no MPEG Decoder to show iframes avail");
1878 eDebug("showRassSlidePicture called.. but not decoder");
1881 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1887 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1888 if (rass_interactive_pic.length())
1889 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1891 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1894 eDebug("no MPEG Decoder to show iframes avail");
1897 eDebug("showRassInteractivePic called.. but not decoder");
1900 ePyObject eDVBServicePlay::getRassInteractiveMask()
1903 return m_rds_decoder->getRassPictureMask();
1907 int eDVBServiceBase::getFrontendInfo(int w)
1909 eUsePtr<iDVBChannel> channel;
1910 if(m_service_handler.getChannel(channel))
1912 ePtr<iDVBFrontend> fe;
1913 if(channel->getFrontend(fe))
1915 return fe->readFrontendData(w);
1918 PyObject *eDVBServiceBase::getFrontendData()
1920 ePyObject ret = PyDict_New();
1923 eUsePtr<iDVBChannel> channel;
1924 if(!m_service_handler.getChannel(channel))
1926 ePtr<iDVBFrontend> fe;
1927 if(!channel->getFrontend(fe))
1928 fe->getFrontendData(ret);
1936 PyObject *eDVBServiceBase::getFrontendStatus()
1938 ePyObject ret = PyDict_New();
1941 eUsePtr<iDVBChannel> channel;
1942 if(!m_service_handler.getChannel(channel))
1944 ePtr<iDVBFrontend> fe;
1945 if(!channel->getFrontend(fe))
1946 fe->getFrontendStatus(ret);
1954 PyObject *eDVBServiceBase::getTransponderData(bool original)
1956 ePyObject ret = PyDict_New();
1959 eUsePtr<iDVBChannel> channel;
1960 if(!m_service_handler.getChannel(channel))
1962 ePtr<iDVBFrontend> fe;
1963 if(!channel->getFrontend(fe))
1964 fe->getTransponderData(ret, original);
1972 PyObject *eDVBServiceBase::getAll(bool original)
1974 ePyObject ret = getTransponderData(original);
1977 eUsePtr<iDVBChannel> channel;
1978 if(!m_service_handler.getChannel(channel))
1980 ePtr<iDVBFrontend> fe;
1981 if(!channel->getFrontend(fe))
1983 fe->getFrontendData(ret);
1984 fe->getFrontendStatus(ret);
1991 int eDVBServicePlay::getNumberOfSubservices()
1993 ePtr<eServiceEvent> evt;
1994 if (!m_event_handler.getEvent(evt, 0))
1995 return evt->getNumOfLinkageServices();
1999 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2001 ePtr<eServiceEvent> evt;
2002 if (!m_event_handler.getEvent(evt, 0))
2004 if (!evt->getLinkageService(sub, m_reference, n))
2007 sub.type=eServiceReference::idInvalid;
2011 RESULT eDVBServicePlay::startTimeshift()
2013 ePtr<iDVBDemux> demux;
2015 eDebug("Start timeshift!");
2017 if (m_timeshift_enabled)
2020 /* start recording with the data demux. */
2021 if (m_service_handler.getDataDemux(demux))
2024 demux->createTSRecorder(m_record);
2029 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2030 eDebug("could not query ts path");
2033 tspath.append("/timeshift.XXXXXX");
2035 templ = new char[tspath.length() + 1];
2036 strcpy(templ, tspath.c_str());
2038 m_timeshift_fd = mkstemp(templ);
2039 m_timeshift_file = std::string(templ);
2041 eDebug("recording to %s", templ);
2045 if (m_timeshift_fd < 0)
2051 m_record->setTargetFD(m_timeshift_fd);
2053 m_timeshift_enabled = 1;
2055 updateTimeshiftPids();
2061 RESULT eDVBServicePlay::stopTimeshift()
2063 if (!m_timeshift_enabled)
2068 m_timeshift_enabled = 0;
2073 close(m_timeshift_fd);
2074 eDebug("remove timeshift file");
2075 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2080 int eDVBServicePlay::isTimeshiftActive()
2082 return m_timeshift_enabled && m_timeshift_active;
2085 RESULT eDVBServicePlay::activateTimeshift()
2087 if (!m_timeshift_enabled)
2090 if (!m_timeshift_active)
2092 switchToTimeshift();
2099 PyObject *eDVBServicePlay::getCutList()
2101 ePyObject list = PyList_New(0);
2103 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2105 ePyObject tuple = PyTuple_New(2);
2106 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2107 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2108 PyList_Append(list, tuple);
2115 void eDVBServicePlay::setCutList(ePyObject list)
2117 if (!PyList_Check(list))
2119 int size = PyList_Size(list);
2122 m_cue_entries.clear();
2124 for (i=0; i<size; ++i)
2126 ePyObject tuple = PyList_GET_ITEM(list, i);
2127 if (!PyTuple_Check(tuple))
2129 eDebug("non-tuple in cutlist");
2132 if (PyTuple_Size(tuple) != 2)
2134 eDebug("cutlist entries need to be a 2-tuple");
2137 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2138 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2140 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2143 pts_t pts = PyLong_AsLongLong(ppts);
2144 int type = PyInt_AsLong(ptype);
2145 m_cue_entries.insert(cueEntry(pts, type));
2146 eDebug("adding %08llx, %d", pts, type);
2148 m_cuesheet_changed = 1;
2150 cutlistToCuesheet();
2151 m_event((iPlayableService*)this, evCuesheetChanged);
2154 void eDVBServicePlay::setCutListEnable(int enable)
2156 m_cutlist_enabled = enable;
2157 cutlistToCuesheet();
2160 void eDVBServicePlay::updateTimeshiftPids()
2165 eDVBServicePMTHandler::program program;
2166 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2168 if (h.getProgramInfo(program))
2172 std::set<int> pids_to_record;
2173 pids_to_record.insert(0); // PAT
2174 if (program.pmtPid != -1)
2175 pids_to_record.insert(program.pmtPid); // PMT
2177 if (program.textPid != -1)
2178 pids_to_record.insert(program.textPid); // Videotext
2180 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2181 i(program.videoStreams.begin());
2182 i != program.videoStreams.end(); ++i)
2183 pids_to_record.insert(i->pid);
2185 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2186 i(program.audioStreams.begin());
2187 i != program.audioStreams.end(); ++i)
2188 pids_to_record.insert(i->pid);
2190 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2191 i(program.subtitleStreams.begin());
2192 i != program.subtitleStreams.end(); ++i)
2193 pids_to_record.insert(i->pid);
2195 std::set<int> new_pids, obsolete_pids;
2197 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2198 m_pids_active.begin(), m_pids_active.end(),
2199 std::inserter(new_pids, new_pids.begin()));
2201 std::set_difference(
2202 m_pids_active.begin(), m_pids_active.end(),
2203 pids_to_record.begin(), pids_to_record.end(),
2204 std::inserter(new_pids, new_pids.begin())
2207 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2208 m_record->addPID(*i);
2210 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2211 m_record->removePID(*i);
2215 void eDVBServicePlay::switchToLive()
2217 if (!m_timeshift_active)
2220 eDebug("SwitchToLive");
2225 m_teletext_parser = 0;
2227 m_subtitle_parser = 0;
2228 m_new_dvb_subtitle_page_connection = 0;
2229 m_new_subtitle_page_connection = 0;
2230 m_rds_decoder_event_connection = 0;
2231 m_video_event_connection = 0;
2232 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2234 /* free the timeshift service handler, we need the resources */
2235 m_service_handler_timeshift.free();
2236 m_timeshift_active = 0;
2237 m_timeshift_changed = 1;
2239 m_event((iPlayableService*)this, evSeekableStatusChanged);
2244 void eDVBServicePlay::switchToTimeshift()
2246 if (m_timeshift_active)
2251 m_teletext_parser = 0;
2253 m_subtitle_parser = 0;
2254 m_new_subtitle_page_connection = 0;
2255 m_new_dvb_subtitle_page_connection = 0;
2256 m_rds_decoder_event_connection = 0;
2257 m_video_event_connection = 0;
2259 m_timeshift_active = 1;
2260 m_timeshift_changed = 1;
2262 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2263 r.path = m_timeshift_file;
2265 m_cue = new eCueSheet();
2266 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2268 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2270 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2272 m_event((iPlayableService*)this, evSeekableStatusChanged);
2275 void eDVBServicePlay::updateDecoder()
2277 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2279 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2281 eDVBServicePMTHandler::program program;
2282 if (h.getProgramInfo(program))
2283 eDebug("getting program info failed.");
2286 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2287 if (!program.videoStreams.empty())
2289 eDebugNoNewLine(" (");
2290 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2291 i(program.videoStreams.begin());
2292 i != program.videoStreams.end(); ++i)
2299 if (i != program.videoStreams.begin())
2300 eDebugNoNewLine(", ");
2301 eDebugNoNewLine("%04x", i->pid);
2303 eDebugNoNewLine(")");
2305 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2306 if (!program.audioStreams.empty())
2308 eDebugNoNewLine(" (");
2309 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2310 i(program.audioStreams.begin());
2311 i != program.audioStreams.end(); ++i)
2313 if (i != program.audioStreams.begin())
2314 eDebugNoNewLine(", ");
2315 eDebugNoNewLine("%04x", i->pid);
2317 eDebugNoNewLine(")");
2319 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2320 pcrpid = program.pcrPid;
2321 eDebug(", and the text pid is %04x", program.textPid);
2322 tpid = program.textPid;
2327 h.getDecodeDemux(m_decode_demux);
2328 if (m_timeshift_changed)
2332 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2334 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2337 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2338 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2339 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2340 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2341 if (m_timeshift_changed)
2343 ePyObject subs = getCachedSubtitle();
2344 if (subs != Py_None)
2346 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2347 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2348 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2349 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2350 if (type == 0) // dvb
2351 m_subtitle_parser->start(pid, comp_page, anc_page);
2352 else if (type == 1) // ttx
2353 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2358 m_decoder->play(); /* pids will be set later */
2361 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2362 m_decoder->play(); /* pids will be set later. */
2365 m_timeshift_changed = 0;
2371 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2372 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2373 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2377 eServiceReferenceDVB ref;
2378 m_service_handler.getServiceReference(ref);
2379 eServiceReferenceDVB parent = ref.getParentServiceReference();
2384 ePtr<eDVBResourceManager> res_mgr;
2385 if (!eDVBResourceManager::getInstance(res_mgr))
2387 ePtr<iDVBChannelList> db;
2388 if (!res_mgr->getChannelList(db))
2390 ePtr<eDVBService> origService;
2391 if (!db->getService(parent, origService))
2393 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2394 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2401 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2402 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2404 m_decoder->setVideoPID(vpid, vpidtype);
2405 selectAudioStream();
2407 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2408 m_decoder->setSyncPCR(pcrpid);
2410 m_decoder->setSyncPCR(-1);
2414 m_decoder->setTextPID(tpid);
2415 m_teletext_parser->start(program.textPid);
2418 if (vpid > 0 && vpid < 0x2000)
2422 std::string radio_pic;
2423 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2424 m_decoder->setRadioPic(radio_pic);
2428 m_decoder->setAudioChannel(achannel);
2430 /* don't worry about non-existing services, nor pvr services */
2433 /* (audio pid will be set in selectAudioTrack */
2434 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2435 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2436 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2437 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2440 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2443 void eDVBServicePlay::loadCuesheet()
2445 std::string filename = m_reference.path + ".cuts";
2447 m_cue_entries.clear();
2449 FILE *f = fopen(filename.c_str(), "rb");
2453 eDebug("loading cuts..");
2456 unsigned long long where;
2459 if (!fread(&where, sizeof(where), 1, f))
2461 if (!fread(&what, sizeof(what), 1, f))
2464 #if BYTE_ORDER == LITTLE_ENDIAN
2465 where = bswap_64(where);
2472 m_cue_entries.insert(cueEntry(where, what));
2475 eDebug("%d entries", m_cue_entries.size());
2477 eDebug("cutfile not found!");
2479 m_cuesheet_changed = 0;
2480 cutlistToCuesheet();
2481 m_event((iPlayableService*)this, evCuesheetChanged);
2484 void eDVBServicePlay::saveCuesheet()
2486 std::string filename = m_reference.path + ".cuts";
2488 FILE *f = fopen(filename.c_str(), "wb");
2492 unsigned long long where;
2495 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2497 #if BYTE_ORDER == BIG_ENDIAN
2500 where = bswap_64(i->where);
2502 what = htonl(i->what);
2503 fwrite(&where, sizeof(where), 1, f);
2504 fwrite(&what, sizeof(what), 1, f);
2510 m_cuesheet_changed = 0;
2513 void eDVBServicePlay::cutlistToCuesheet()
2517 eDebug("no cue sheet");
2522 if (!m_cutlist_enabled)
2524 m_cue->commitSpans();
2525 eDebug("cutlists were disabled");
2529 pts_t in = 0, out = 0, length = 0;
2533 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2535 int have_any_span = 0;
2539 if (i == m_cue_entries.end())
2545 if (i->what == 0) /* in */
2549 } else if (i->what == 1) /* out */
2551 else /* mark (2) or last play position (3) */
2570 m_cue->addSourceSpan(in, out);
2575 if (i == m_cue_entries.end())
2578 m_cue->commitSpans();
2581 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2583 if (m_subtitle_widget)
2584 disableSubtitles(parent);
2587 int tuplesize = PyTuple_Size(tuple);
2590 if (!PyTuple_Check(tuple))
2596 entry = PyTuple_GET_ITEM(tuple, 0);
2598 if (!PyInt_Check(entry))
2601 type = PyInt_AsLong(entry);
2603 if (type == 1) // teletext subtitles
2605 int page, magazine, pid;
2609 if (!m_teletext_parser)
2611 eDebug("enable teletext subtitles.. no parser !!!");
2615 entry = PyTuple_GET_ITEM(tuple, 1);
2616 if (!PyInt_Check(entry))
2618 pid = PyInt_AsLong(entry);
2620 entry = PyTuple_GET_ITEM(tuple, 2);
2621 if (!PyInt_Check(entry))
2623 page = PyInt_AsLong(entry);
2625 entry = PyTuple_GET_ITEM(tuple, 3);
2626 if (!PyInt_Check(entry))
2628 magazine = PyInt_AsLong(entry);
2630 m_subtitle_widget = new eSubtitleWidget(parent);
2631 m_subtitle_widget->resize(parent->size()); /* full size */
2632 m_teletext_parser->setPageAndMagazine(page, magazine);
2634 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2638 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2639 if (!m_subtitle_parser)
2641 eDebug("enable dvb subtitles.. no parser !!!");
2647 entry = PyTuple_GET_ITEM(tuple, 1);
2648 if (!PyInt_Check(entry))
2650 pid = PyInt_AsLong(entry);
2652 entry = PyTuple_GET_ITEM(tuple, 2);
2653 if (!PyInt_Check(entry))
2655 composition_page_id = PyInt_AsLong(entry);
2657 entry = PyTuple_GET_ITEM(tuple, 3);
2658 if (!PyInt_Check(entry))
2660 ancillary_page_id = PyInt_AsLong(entry);
2662 m_subtitle_widget = new eSubtitleWidget(parent);
2663 m_subtitle_widget->resize(parent->size()); /* full size */
2664 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2666 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2672 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2673 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2674 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2678 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2680 delete m_subtitle_widget;
2681 m_subtitle_widget = 0;
2682 if (m_subtitle_parser)
2684 m_subtitle_parser->stop();
2685 m_dvb_subtitle_pages.clear();
2687 if (m_teletext_parser)
2689 m_teletext_parser->setPageAndMagazine(-1, -1);
2690 m_subtitle_pages.clear();
2693 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2697 PyObject *eDVBServicePlay::getCachedSubtitle()
2701 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2704 unsigned int data = (unsigned int)tmp;
2705 int pid = (data&0xFFFF0000)>>16;
2706 ePyObject tuple = PyTuple_New(4);
2707 eDVBServicePMTHandler::program program;
2708 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2709 if (!h.getProgramInfo(program))
2711 if (program.textPid==pid) // teletext
2712 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2714 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2715 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2716 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2717 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2725 PyObject *eDVBServicePlay::getSubtitleList()
2727 if (!m_teletext_parser)
2730 ePyObject l = PyList_New(0);
2731 std::set<int> added_ttx_pages;
2733 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2734 m_teletext_parser->m_found_subtitle_pages;
2736 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2737 eDVBServicePMTHandler::program program;
2738 if (h.getProgramInfo(program))
2739 eDebug("getting program info failed.");
2742 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2743 it != program.subtitleStreams.end(); ++it)
2745 switch(it->subtitling_type)
2747 case 0x01: // ebu teletext subtitles
2749 int page_number = it->teletext_page_number & 0xFF;
2750 int magazine_number = it->teletext_magazine_number & 7;
2751 int hash = magazine_number << 8 | page_number;
2752 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2754 ePyObject tuple = PyTuple_New(5);
2755 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2756 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2757 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2758 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2759 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2760 PyList_Append(l, tuple);
2762 added_ttx_pages.insert(hash);
2767 case 0x20 ... 0x23: // dvb subtitles
2769 ePyObject tuple = PyTuple_New(5);
2770 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2771 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2772 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2773 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2774 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2775 PyList_Insert(l, 0, tuple);
2783 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2784 it != subs.end(); ++it)
2786 int page_number = it->teletext_page_number & 0xFF;
2787 int magazine_number = it->teletext_magazine_number & 7;
2788 int hash = magazine_number << 8 | page_number;
2789 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2791 ePyObject tuple = PyTuple_New(5);
2792 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2793 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2794 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2795 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2796 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2797 PyList_Append(l, tuple);
2805 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2807 if (m_subtitle_widget)
2811 m_decoder->getPTS(0, pos);
2812 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2813 m_subtitle_pages.push_back(page);
2814 checkSubtitleTiming();
2818 void eDVBServicePlay::checkSubtitleTiming()
2820 eDebug("checkSubtitleTiming");
2821 if (!m_subtitle_widget)
2825 enum { TELETEXT, DVB } type;
2826 eDVBTeletextSubtitlePage page;
2827 eDVBSubtitlePage dvb_page;
2829 if (!m_subtitle_pages.empty())
2831 page = m_subtitle_pages.front();
2833 show_time = page.m_pts;
2835 else if (!m_dvb_subtitle_pages.empty())
2837 dvb_page = m_dvb_subtitle_pages.front();
2839 show_time = dvb_page.m_show_time;
2847 m_decoder->getPTS(0, pos);
2849 eDebug("%lld %lld", pos, show_time);
2850 int diff = show_time - pos;
2851 if (type == TELETEXT && !page.m_have_pts)
2853 eDebug("ttx subtitle page without pts... immediate show");
2858 eDebug("[late (%d ms)]", -diff / 90);
2861 if (abs(diff) > 1800000)
2863 eDebug("[invalid]... immediate show!");
2868 if (type == TELETEXT)
2870 eDebug("display teletext subtitle page %lld", show_time);
2871 m_subtitle_widget->setPage(page);
2872 m_subtitle_pages.pop_front();
2876 eDebug("display dvb subtitle Page %lld", show_time);
2877 m_subtitle_widget->setPage(dvb_page);
2878 m_dvb_subtitle_pages.pop_front();
2882 eDebug("start subtitle delay %d", diff / 90);
2883 m_subtitle_sync_timer->start(diff / 90, 1);
2889 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2891 if (m_subtitle_widget)
2895 m_decoder->getPTS(0, pos);
2896 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2897 m_dvb_subtitle_pages.push_back(p);
2898 checkSubtitleTiming();
2902 int eDVBServicePlay::getAC3Delay()
2905 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2907 return m_decoder->getAC3Delay();
2912 int eDVBServicePlay::getPCMDelay()
2915 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2917 return m_decoder->getPCMDelay();
2922 void eDVBServicePlay::setAC3Delay(int delay)
2925 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2927 std::string config_delay;
2928 int config_delay_int = 0;
2929 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2930 config_delay_int = atoi(config_delay.c_str());
2931 m_decoder->setAC3Delay(delay + config_delay_int);
2935 void eDVBServicePlay::setPCMDelay(int delay)
2938 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2940 std::string config_delay;
2941 int config_delay_int = 0;
2942 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2943 config_delay_int = atoi(config_delay.c_str());
2945 config_delay_int = 0;
2946 m_decoder->setPCMDelay(delay + config_delay_int);
2950 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2952 switch(event.type) {
2953 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2954 m_event((iPlayableService*)this, evVideoSizeChanged);
2956 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2957 m_event((iPlayableService*)this, evVideoFramerateChanged);
2959 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2960 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2967 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2973 PyObject *eDVBServicePlay::getStreamingData()
2975 eDVBServicePMTHandler::program program;
2976 if (m_service_handler.getProgramInfo(program))
2981 ePyObject r = program.createPythonObject();
2982 ePtr<iDVBDemux> demux;
2983 if (!m_service_handler.getDataDemux(demux))
2986 if (!demux->getCADemuxID(demux_id))
2987 PutToDict(r, "demux", demux_id);
2994 DEFINE_REF(eDVBServicePlay)
2996 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3000 case iServiceInformation::sTransponderData:
3001 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3005 return iStaticServiceInformation::getInfoObject(ref, w);
3008 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");