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()
1065 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1066 two (one for decoding, one for data source), as we must be prepared
1067 to start recording from the data demux. */
1069 m_cue = new eCueSheet();
1071 m_event(this, evStart);
1073 m_first_program_info = 1;
1074 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1075 r = m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1077 /* inject EIT if there is a stored one */
1080 std::string filename = service.path;
1081 filename.erase(filename.length()-2, 2);
1083 ePtr<eServiceEvent> event = new eServiceEvent;
1084 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1086 ePtr<eServiceEvent> empty;
1087 m_event_handler.inject(event, 0);
1088 m_event_handler.inject(empty, 1);
1095 m_event(this, evStart);
1100 RESULT eDVBServicePlay::stop()
1102 /* add bookmark for last play position */
1105 pts_t play_position, length;
1106 if (!getPlayPosition(play_position))
1108 /* remove last position */
1109 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1111 if (i->what == 3) /* current play position */
1113 m_cue_entries.erase(i);
1114 i = m_cue_entries.begin();
1120 if (getLength(length))
1125 int perc = play_position * 100LL / length;
1127 /* only store last play position when between 1% and 99% */
1128 if ((1 < perc) && (perc < 99))
1129 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1131 m_cuesheet_changed = 1;
1135 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1137 m_service_handler_timeshift.free();
1138 m_service_handler.free();
1140 if (m_is_pvr && m_cuesheet_changed)
1143 /* save cuesheet only when main file is accessible. */
1144 if (!::stat(m_reference.path.c_str(), &s))
1147 m_event((iPlayableService*)this, evStopped);
1151 RESULT eDVBServicePlay::setTarget(int target)
1153 m_is_primary = !target;
1157 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1159 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1163 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1165 /* note: we check for timeshift to be enabled,
1166 not neccessary active. if you pause when timeshift
1167 is not active, you should activate it when unpausing */
1168 if ((!m_is_pvr) && (!m_timeshift_enabled))
1178 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1180 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1181 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1182 setFastForward_internal(0);
1184 return m_decoder->setSlowMotion(ratio);
1189 RESULT eDVBServicePlay::setFastForward(int ratio)
1191 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1193 return setFastForward_internal(ratio);
1196 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1198 int skipmode, ffratio;
1204 } else if (ratio > 0)
1212 } else // if (ratio < 0)
1218 if (m_skipmode != skipmode)
1220 eDebug("setting cue skipmode to %d", skipmode);
1222 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1225 m_skipmode = skipmode;
1231 ; /* return m_decoder->play(); is done in caller*/
1232 else if (ffratio != 1)
1233 return m_decoder->setFastForward(ffratio);
1235 return m_decoder->setTrickmode();
1239 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1241 if (m_is_pvr || m_timeshift_enabled)
1251 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1252 RESULT eDVBServicePlay::getLength(pts_t &len)
1254 ePtr<iDVBPVRChannel> pvr_channel;
1256 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1259 return pvr_channel->getLength(len);
1262 RESULT eDVBServicePlay::pause()
1264 eDebug("eDVBServicePlay::pause");
1265 setFastForward_internal(0);
1269 return m_decoder->pause();
1274 RESULT eDVBServicePlay::unpause()
1276 eDebug("eDVBServicePlay::unpause");
1277 setFastForward_internal(0);
1281 return m_decoder->play();
1286 RESULT eDVBServicePlay::seekTo(pts_t to)
1288 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1290 if (!m_decode_demux)
1293 ePtr<iDVBPVRChannel> pvr_channel;
1295 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1301 m_cue->seekTo(0, to);
1302 m_dvb_subtitle_pages.clear();
1303 m_subtitle_pages.clear();
1308 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1310 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1312 if (!m_decode_demux)
1315 ePtr<iDVBPVRChannel> pvr_channel;
1317 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1322 /* HACK until we have skip-AP api */
1323 if ((to > 0) && (to < 100))
1331 m_cue->seekTo(mode, to);
1332 m_dvb_subtitle_pages.clear();
1333 m_subtitle_pages.clear();
1337 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1339 ePtr<iDVBPVRChannel> pvr_channel;
1341 if (!m_decode_demux)
1344 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349 /* if there is a decoder, use audio or video PTS */
1352 r = m_decoder->getPTS(0, pos);
1358 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1361 RESULT eDVBServicePlay::setTrickmode(int trick)
1363 /* currently unimplemented */
1367 RESULT eDVBServicePlay::isCurrentlySeekable()
1369 return m_is_pvr || m_timeshift_active;
1372 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1378 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1384 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1390 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1396 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1402 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1405 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1406 (m_timeshift_enabled || !m_is_pvr))
1408 if (!m_timeshift_enabled)
1410 /* query config path */
1412 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1413 eDebug("could not query ts path from config");
1417 /* we need enough diskspace */
1419 if (statfs(tspath.c_str(), &fs) < 0)
1421 eDebug("statfs failed!");
1425 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1427 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1437 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1448 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1454 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1460 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1466 RESULT eDVBServicePlay::getName(std::string &name)
1470 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1471 return i->getName(m_reference, name);
1473 else if (m_dvb_service)
1475 m_dvb_service->getName(m_reference, name);
1479 else if (!m_reference.name.empty())
1480 eStaticServiceDVBInformation().getName(m_reference, name);
1482 name = "DVB service";
1486 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1488 return m_event_handler.getEvent(evt, nownext);
1491 int eDVBServicePlay::getInfo(int w)
1493 eDVBServicePMTHandler::program program;
1496 return resIsPyObject;
1498 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1500 int no_program_info = 0;
1502 if (h.getProgramInfo(program))
1503 no_program_info = 1;
1509 return m_decoder->getVideoHeight();
1513 return m_decoder->getVideoWidth();
1517 return m_decoder->getVideoFrameRate();
1521 return m_decoder->getVideoProgressive();
1527 aspect = m_decoder->getVideoAspect();
1528 if (aspect == -1 && no_program_info)
1530 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1532 ePtr<eServiceEvent> evt;
1533 if (!m_event_handler.getEvent(evt, 0))
1535 ePtr<eComponentData> data;
1536 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1538 if ( data->getStreamContent() == 1 )
1540 switch(data->getComponentType())
1543 case 1: // 4:3 SD PAL
1545 case 3: // 16:9 SD PAL
1546 case 4: // > 16:9 PAL
1547 case 5: // 4:3 SD NTSC
1549 case 7: // 16:9 SD NTSC
1550 case 8: // > 16:9 NTSC
1553 case 9: // 4:3 HD PAL
1555 case 0xB: // 16:9 HD PAL
1556 case 0xC: // > 16:9 HD PAL
1557 case 0xD: // 4:3 HD NTSC
1559 case 0xF: // 16:9 HD NTSC
1560 case 0x10: // > 16:9 HD PAL
1561 return data->getComponentType();
1571 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1575 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1579 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1580 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1584 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1587 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1591 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1595 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1599 if (no_program_info) return -1; return program.pcrPid;
1600 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1601 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1602 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1603 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1604 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1605 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1606 case sProvider: if (!m_dvb_service) return -1; return -2;
1607 case sServiceref: return resIsString;
1608 case sDVBState: return m_tune_state;
1615 std::string eDVBServicePlay::getInfoString(int w)
1620 if (!m_dvb_service) return "";
1621 return m_dvb_service->m_provider_name;
1623 return m_reference.toString();
1627 return iServiceInformation::getInfoString(w);
1630 PyObject *eDVBServicePlay::getInfoObject(int w)
1635 return m_service_handler.getCaIds();
1636 case sTransponderData:
1637 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1641 return iServiceInformation::getInfoObject(w);
1644 int eDVBServicePlay::getNumberOfTracks()
1646 eDVBServicePMTHandler::program program;
1647 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1648 if (h.getProgramInfo(program))
1650 return program.audioStreams.size();
1653 int eDVBServicePlay::getCurrentTrack()
1655 eDVBServicePMTHandler::program program;
1656 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1657 if (h.getProgramInfo(program))
1660 int max = program.audioStreams.size();
1663 for (i = 0; i < max; ++i)
1664 if (program.audioStreams[i].pid == m_current_audio_pid)
1670 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1672 int ret = selectAudioStream(i);
1674 if (m_decoder->set())
1680 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1682 eDVBServicePMTHandler::program program;
1683 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1685 if (h.getProgramInfo(program))
1688 if (i >= program.audioStreams.size())
1691 info.m_pid = program.audioStreams[i].pid;
1693 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1694 info.m_description = "MPEG";
1695 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1696 info.m_description = "AC3";
1697 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1698 info.m_description = "AAC";
1699 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1700 info.m_description = "AAC-HE";
1701 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1702 info.m_description = "DTS";
1704 info.m_description = "???";
1706 if (program.audioStreams[i].component_tag != -1)
1708 ePtr<eServiceEvent> evt;
1709 if (!m_event_handler.getEvent(evt, 0))
1711 ePtr<eComponentData> data;
1712 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1713 info.m_language = data->getText();
1717 if (info.m_language.empty())
1718 info.m_language = program.audioStreams[i].language_code;
1723 int eDVBServicePlay::selectAudioStream(int i)
1725 eDVBServicePMTHandler::program program;
1726 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1728 if (h.getProgramInfo(program))
1731 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1739 stream = program.defaultAudioStream;
1741 int apid = -1, apidtype = -1;
1743 if (((unsigned int)stream) < program.audioStreams.size())
1745 apid = program.audioStreams[stream].pid;
1746 apidtype = program.audioStreams[stream].type;
1749 m_current_audio_pid = apid;
1751 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1753 eDebug("set audio pid failed");
1759 /* 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 */
1760 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1762 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1764 rdsPid = program.audioStreams[stream].rdsPid;
1765 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1768 ePtr<iDVBDemux> data_demux;
1769 if (!h.getDataDemux(data_demux))
1771 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1772 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1773 m_rds_decoder->start(rdsPid);
1778 /* store new pid as default only when:
1779 a.) we have an entry in the service db for the current service,
1780 b.) we are not playing back something,
1781 c.) we are not selecting the default entry. (we wouldn't change
1782 anything in the best case, or destroy the default setting in
1783 case the real default is not yet available.)
1785 if (m_dvb_service && ((i != -1)
1786 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1788 if (apidtype == eDVBAudio::aMPEG)
1790 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1791 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1793 else if (apidtype == eDVBAudio::aAC3)
1795 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1796 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1800 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1801 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1805 h.resetCachedProgram();
1810 int eDVBServicePlay::getCurrentChannel()
1812 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1815 RESULT eDVBServicePlay::selectChannel(int i)
1817 if (i < LEFT || i > RIGHT || i == STEREO)
1820 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1822 m_decoder->setAudioChannel(i);
1826 std::string eDVBServicePlay::getText(int x)
1832 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1834 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1839 void eDVBServicePlay::rdsDecoderEvent(int what)
1843 case eDVBRdsDecoder::RadioTextChanged:
1844 m_event((iPlayableService*)this, evUpdatedRadioText);
1846 case eDVBRdsDecoder::RtpTextChanged:
1847 m_event((iPlayableService*)this, evUpdatedRtpText);
1849 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1850 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1852 case eDVBRdsDecoder::RecvRassSlidePic:
1853 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1858 void eDVBServicePlay::showRassSlidePicture()
1864 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1865 if (rass_slide_pic.length())
1866 m_decoder->showSinglePic(rass_slide_pic.c_str());
1868 eDebug("empty filename for rass slide picture received!!");
1871 eDebug("no MPEG Decoder to show iframes avail");
1874 eDebug("showRassSlidePicture called.. but not decoder");
1877 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1883 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1884 if (rass_interactive_pic.length())
1885 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1887 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1890 eDebug("no MPEG Decoder to show iframes avail");
1893 eDebug("showRassInteractivePic called.. but not decoder");
1896 ePyObject eDVBServicePlay::getRassInteractiveMask()
1899 return m_rds_decoder->getRassPictureMask();
1903 int eDVBServiceBase::getFrontendInfo(int w)
1905 eUsePtr<iDVBChannel> channel;
1906 if(m_service_handler.getChannel(channel))
1908 ePtr<iDVBFrontend> fe;
1909 if(channel->getFrontend(fe))
1911 return fe->readFrontendData(w);
1914 PyObject *eDVBServiceBase::getFrontendData()
1916 ePyObject ret = PyDict_New();
1919 eUsePtr<iDVBChannel> channel;
1920 if(!m_service_handler.getChannel(channel))
1922 ePtr<iDVBFrontend> fe;
1923 if(!channel->getFrontend(fe))
1924 fe->getFrontendData(ret);
1932 PyObject *eDVBServiceBase::getFrontendStatus()
1934 ePyObject ret = PyDict_New();
1937 eUsePtr<iDVBChannel> channel;
1938 if(!m_service_handler.getChannel(channel))
1940 ePtr<iDVBFrontend> fe;
1941 if(!channel->getFrontend(fe))
1942 fe->getFrontendStatus(ret);
1950 PyObject *eDVBServiceBase::getTransponderData(bool original)
1952 ePyObject ret = PyDict_New();
1955 eUsePtr<iDVBChannel> channel;
1956 if(!m_service_handler.getChannel(channel))
1958 ePtr<iDVBFrontend> fe;
1959 if(!channel->getFrontend(fe))
1960 fe->getTransponderData(ret, original);
1968 PyObject *eDVBServiceBase::getAll(bool original)
1970 ePyObject ret = getTransponderData(original);
1973 eUsePtr<iDVBChannel> channel;
1974 if(!m_service_handler.getChannel(channel))
1976 ePtr<iDVBFrontend> fe;
1977 if(!channel->getFrontend(fe))
1979 fe->getFrontendData(ret);
1980 fe->getFrontendStatus(ret);
1987 int eDVBServicePlay::getNumberOfSubservices()
1989 ePtr<eServiceEvent> evt;
1990 if (!m_event_handler.getEvent(evt, 0))
1991 return evt->getNumOfLinkageServices();
1995 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1997 ePtr<eServiceEvent> evt;
1998 if (!m_event_handler.getEvent(evt, 0))
2000 if (!evt->getLinkageService(sub, m_reference, n))
2003 sub.type=eServiceReference::idInvalid;
2007 RESULT eDVBServicePlay::startTimeshift()
2009 ePtr<iDVBDemux> demux;
2011 eDebug("Start timeshift!");
2013 if (m_timeshift_enabled)
2016 /* start recording with the data demux. */
2017 if (m_service_handler.getDataDemux(demux))
2020 demux->createTSRecorder(m_record);
2025 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2026 eDebug("could not query ts path");
2029 tspath.append("/timeshift.XXXXXX");
2031 templ = new char[tspath.length() + 1];
2032 strcpy(templ, tspath.c_str());
2034 m_timeshift_fd = mkstemp(templ);
2035 m_timeshift_file = std::string(templ);
2037 eDebug("recording to %s", templ);
2041 if (m_timeshift_fd < 0)
2047 m_record->setTargetFD(m_timeshift_fd);
2049 m_timeshift_enabled = 1;
2051 updateTimeshiftPids();
2057 RESULT eDVBServicePlay::stopTimeshift()
2059 if (!m_timeshift_enabled)
2064 m_timeshift_enabled = 0;
2069 close(m_timeshift_fd);
2070 eDebug("remove timeshift file");
2071 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2076 int eDVBServicePlay::isTimeshiftActive()
2078 return m_timeshift_enabled && m_timeshift_active;
2081 RESULT eDVBServicePlay::activateTimeshift()
2083 if (!m_timeshift_enabled)
2086 if (!m_timeshift_active)
2088 switchToTimeshift();
2095 PyObject *eDVBServicePlay::getCutList()
2097 ePyObject list = PyList_New(0);
2099 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2101 ePyObject tuple = PyTuple_New(2);
2102 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2103 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2104 PyList_Append(list, tuple);
2111 void eDVBServicePlay::setCutList(ePyObject list)
2113 if (!PyList_Check(list))
2115 int size = PyList_Size(list);
2118 m_cue_entries.clear();
2120 for (i=0; i<size; ++i)
2122 ePyObject tuple = PyList_GET_ITEM(list, i);
2123 if (!PyTuple_Check(tuple))
2125 eDebug("non-tuple in cutlist");
2128 if (PyTuple_Size(tuple) != 2)
2130 eDebug("cutlist entries need to be a 2-tuple");
2133 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2134 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2136 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2139 pts_t pts = PyLong_AsLongLong(ppts);
2140 int type = PyInt_AsLong(ptype);
2141 m_cue_entries.insert(cueEntry(pts, type));
2142 eDebug("adding %08llx, %d", pts, type);
2144 m_cuesheet_changed = 1;
2146 cutlistToCuesheet();
2147 m_event((iPlayableService*)this, evCuesheetChanged);
2150 void eDVBServicePlay::setCutListEnable(int enable)
2152 m_cutlist_enabled = enable;
2153 cutlistToCuesheet();
2156 void eDVBServicePlay::updateTimeshiftPids()
2161 eDVBServicePMTHandler::program program;
2162 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2164 if (h.getProgramInfo(program))
2168 std::set<int> pids_to_record;
2169 pids_to_record.insert(0); // PAT
2170 if (program.pmtPid != -1)
2171 pids_to_record.insert(program.pmtPid); // PMT
2173 if (program.textPid != -1)
2174 pids_to_record.insert(program.textPid); // Videotext
2176 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2177 i(program.videoStreams.begin());
2178 i != program.videoStreams.end(); ++i)
2179 pids_to_record.insert(i->pid);
2181 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2182 i(program.audioStreams.begin());
2183 i != program.audioStreams.end(); ++i)
2184 pids_to_record.insert(i->pid);
2186 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2187 i(program.subtitleStreams.begin());
2188 i != program.subtitleStreams.end(); ++i)
2189 pids_to_record.insert(i->pid);
2191 std::set<int> new_pids, obsolete_pids;
2193 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2194 m_pids_active.begin(), m_pids_active.end(),
2195 std::inserter(new_pids, new_pids.begin()));
2197 std::set_difference(
2198 m_pids_active.begin(), m_pids_active.end(),
2199 pids_to_record.begin(), pids_to_record.end(),
2200 std::inserter(new_pids, new_pids.begin())
2203 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2204 m_record->addPID(*i);
2206 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2207 m_record->removePID(*i);
2211 void eDVBServicePlay::switchToLive()
2213 if (!m_timeshift_active)
2216 eDebug("SwitchToLive");
2221 m_teletext_parser = 0;
2223 m_subtitle_parser = 0;
2224 m_new_dvb_subtitle_page_connection = 0;
2225 m_new_subtitle_page_connection = 0;
2226 m_rds_decoder_event_connection = 0;
2227 m_video_event_connection = 0;
2228 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2230 /* free the timeshift service handler, we need the resources */
2231 m_service_handler_timeshift.free();
2232 m_timeshift_active = 0;
2233 m_timeshift_changed = 1;
2235 m_event((iPlayableService*)this, evSeekableStatusChanged);
2240 void eDVBServicePlay::switchToTimeshift()
2242 if (m_timeshift_active)
2247 m_teletext_parser = 0;
2249 m_subtitle_parser = 0;
2250 m_new_subtitle_page_connection = 0;
2251 m_new_dvb_subtitle_page_connection = 0;
2252 m_rds_decoder_event_connection = 0;
2253 m_video_event_connection = 0;
2255 m_timeshift_active = 1;
2256 m_timeshift_changed = 1;
2258 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2259 r.path = m_timeshift_file;
2261 m_cue = new eCueSheet();
2262 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2264 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2266 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2268 m_event((iPlayableService*)this, evSeekableStatusChanged);
2271 void eDVBServicePlay::updateDecoder()
2273 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2275 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2277 eDVBServicePMTHandler::program program;
2278 if (h.getProgramInfo(program))
2279 eDebug("getting program info failed.");
2282 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2283 if (!program.videoStreams.empty())
2285 eDebugNoNewLine(" (");
2286 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2287 i(program.videoStreams.begin());
2288 i != program.videoStreams.end(); ++i)
2295 if (i != program.videoStreams.begin())
2296 eDebugNoNewLine(", ");
2297 eDebugNoNewLine("%04x", i->pid);
2299 eDebugNoNewLine(")");
2301 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2302 if (!program.audioStreams.empty())
2304 eDebugNoNewLine(" (");
2305 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2306 i(program.audioStreams.begin());
2307 i != program.audioStreams.end(); ++i)
2309 if (i != program.audioStreams.begin())
2310 eDebugNoNewLine(", ");
2311 eDebugNoNewLine("%04x", i->pid);
2313 eDebugNoNewLine(")");
2315 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2316 pcrpid = program.pcrPid;
2317 eDebug(", and the text pid is %04x", program.textPid);
2318 tpid = program.textPid;
2323 h.getDecodeDemux(m_decode_demux);
2324 if (m_timeshift_changed)
2328 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2330 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2333 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2334 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2335 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2336 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2337 if (m_timeshift_changed)
2339 ePyObject subs = getCachedSubtitle();
2340 if (subs != Py_None)
2342 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2343 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2344 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2345 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2346 if (type == 0) // dvb
2347 m_subtitle_parser->start(pid, comp_page, anc_page);
2348 else if (type == 1) // ttx
2349 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2354 m_decoder->play(); /* pids will be set later */
2357 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2358 m_decoder->play(); /* pids will be set later. */
2361 m_timeshift_changed = 0;
2367 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2368 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2369 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2373 eServiceReferenceDVB ref;
2374 m_service_handler.getServiceReference(ref);
2375 eServiceReferenceDVB parent = ref.getParentServiceReference();
2380 ePtr<eDVBResourceManager> res_mgr;
2381 if (!eDVBResourceManager::getInstance(res_mgr))
2383 ePtr<iDVBChannelList> db;
2384 if (!res_mgr->getChannelList(db))
2386 ePtr<eDVBService> origService;
2387 if (!db->getService(parent, origService))
2389 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2390 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2397 std::string config_delay;
2398 int config_delay_int = 0;
2399 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2400 config_delay_int = atoi(config_delay.c_str());
2401 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2403 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2404 config_delay_int = atoi(config_delay.c_str());
2406 config_delay_int = 0;
2407 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2409 m_decoder->setVideoPID(vpid, vpidtype);
2410 selectAudioStream();
2412 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2413 m_decoder->setSyncPCR(pcrpid);
2415 m_decoder->setSyncPCR(-1);
2419 m_decoder->setTextPID(tpid);
2420 m_teletext_parser->start(program.textPid);
2423 if (vpid > 0 && vpid < 0x2000)
2427 std::string radio_pic;
2428 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2429 m_decoder->setRadioPic(radio_pic);
2433 m_decoder->setAudioChannel(achannel);
2435 /* don't worry about non-existing services, nor pvr services */
2438 /* (audio pid will be set in selectAudioTrack */
2439 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2440 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2441 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2442 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2445 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2448 void eDVBServicePlay::loadCuesheet()
2450 std::string filename = m_reference.path + ".cuts";
2452 m_cue_entries.clear();
2454 FILE *f = fopen(filename.c_str(), "rb");
2458 eDebug("loading cuts..");
2461 unsigned long long where;
2464 if (!fread(&where, sizeof(where), 1, f))
2466 if (!fread(&what, sizeof(what), 1, f))
2469 #if BYTE_ORDER == LITTLE_ENDIAN
2470 where = bswap_64(where);
2477 m_cue_entries.insert(cueEntry(where, what));
2480 eDebug("%d entries", m_cue_entries.size());
2482 eDebug("cutfile not found!");
2484 m_cuesheet_changed = 0;
2485 cutlistToCuesheet();
2486 m_event((iPlayableService*)this, evCuesheetChanged);
2489 void eDVBServicePlay::saveCuesheet()
2491 std::string filename = m_reference.path + ".cuts";
2493 FILE *f = fopen(filename.c_str(), "wb");
2497 unsigned long long where;
2500 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2502 #if BYTE_ORDER == BIG_ENDIAN
2505 where = bswap_64(i->where);
2507 what = htonl(i->what);
2508 fwrite(&where, sizeof(where), 1, f);
2509 fwrite(&what, sizeof(what), 1, f);
2515 m_cuesheet_changed = 0;
2518 void eDVBServicePlay::cutlistToCuesheet()
2522 eDebug("no cue sheet");
2527 if (!m_cutlist_enabled)
2529 m_cue->commitSpans();
2530 eDebug("cutlists were disabled");
2534 pts_t in = 0, out = 0, length = 0;
2538 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2540 int have_any_span = 0;
2544 if (i == m_cue_entries.end())
2550 if (i->what == 0) /* in */
2554 } else if (i->what == 1) /* out */
2556 else /* mark (2) or last play position (3) */
2575 m_cue->addSourceSpan(in, out);
2580 if (i == m_cue_entries.end())
2583 m_cue->commitSpans();
2586 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2588 if (m_subtitle_widget)
2589 disableSubtitles(parent);
2592 int tuplesize = PyTuple_Size(tuple);
2595 if (!PyTuple_Check(tuple))
2601 entry = PyTuple_GET_ITEM(tuple, 0);
2603 if (!PyInt_Check(entry))
2606 type = PyInt_AsLong(entry);
2608 if (type == 1) // teletext subtitles
2610 int page, magazine, pid;
2614 if (!m_teletext_parser)
2616 eDebug("enable teletext subtitles.. no parser !!!");
2620 entry = PyTuple_GET_ITEM(tuple, 1);
2621 if (!PyInt_Check(entry))
2623 pid = PyInt_AsLong(entry);
2625 entry = PyTuple_GET_ITEM(tuple, 2);
2626 if (!PyInt_Check(entry))
2628 page = PyInt_AsLong(entry);
2630 entry = PyTuple_GET_ITEM(tuple, 3);
2631 if (!PyInt_Check(entry))
2633 magazine = PyInt_AsLong(entry);
2635 m_subtitle_widget = new eSubtitleWidget(parent);
2636 m_subtitle_widget->resize(parent->size()); /* full size */
2637 m_teletext_parser->setPageAndMagazine(page, magazine);
2639 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2643 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2644 if (!m_subtitle_parser)
2646 eDebug("enable dvb subtitles.. no parser !!!");
2652 entry = PyTuple_GET_ITEM(tuple, 1);
2653 if (!PyInt_Check(entry))
2655 pid = PyInt_AsLong(entry);
2657 entry = PyTuple_GET_ITEM(tuple, 2);
2658 if (!PyInt_Check(entry))
2660 composition_page_id = PyInt_AsLong(entry);
2662 entry = PyTuple_GET_ITEM(tuple, 3);
2663 if (!PyInt_Check(entry))
2665 ancillary_page_id = PyInt_AsLong(entry);
2667 m_subtitle_widget = new eSubtitleWidget(parent);
2668 m_subtitle_widget->resize(parent->size()); /* full size */
2669 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2671 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2677 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2678 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2679 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2683 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2685 delete m_subtitle_widget;
2686 m_subtitle_widget = 0;
2687 if (m_subtitle_parser)
2689 m_subtitle_parser->stop();
2690 m_dvb_subtitle_pages.clear();
2692 if (m_teletext_parser)
2694 m_teletext_parser->setPageAndMagazine(-1, -1);
2695 m_subtitle_pages.clear();
2698 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2702 PyObject *eDVBServicePlay::getCachedSubtitle()
2706 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2709 unsigned int data = (unsigned int)tmp;
2710 int pid = (data&0xFFFF0000)>>16;
2711 ePyObject tuple = PyTuple_New(4);
2712 eDVBServicePMTHandler::program program;
2713 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2714 if (!h.getProgramInfo(program))
2716 if (program.textPid==pid) // teletext
2717 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2719 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2720 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2721 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2722 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2730 PyObject *eDVBServicePlay::getSubtitleList()
2732 if (!m_teletext_parser)
2735 ePyObject l = PyList_New(0);
2736 std::set<int> added_ttx_pages;
2738 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2739 m_teletext_parser->m_found_subtitle_pages;
2741 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2742 eDVBServicePMTHandler::program program;
2743 if (h.getProgramInfo(program))
2744 eDebug("getting program info failed.");
2747 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2748 it != program.subtitleStreams.end(); ++it)
2750 switch(it->subtitling_type)
2752 case 0x01: // ebu teletext subtitles
2754 int page_number = it->teletext_page_number & 0xFF;
2755 int magazine_number = it->teletext_magazine_number & 7;
2756 int hash = magazine_number << 8 | page_number;
2757 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2759 ePyObject tuple = PyTuple_New(5);
2760 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2761 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2762 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2763 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2764 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2765 PyList_Append(l, tuple);
2767 added_ttx_pages.insert(hash);
2772 case 0x20 ... 0x23: // dvb subtitles
2774 ePyObject tuple = PyTuple_New(5);
2775 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2776 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2777 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2778 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2779 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2780 PyList_Insert(l, 0, tuple);
2788 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2789 it != subs.end(); ++it)
2791 int page_number = it->teletext_page_number & 0xFF;
2792 int magazine_number = it->teletext_magazine_number & 7;
2793 int hash = magazine_number << 8 | page_number;
2794 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2796 ePyObject tuple = PyTuple_New(5);
2797 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2798 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2799 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2800 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2801 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2802 PyList_Append(l, tuple);
2810 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2812 if (m_subtitle_widget)
2816 m_decoder->getPTS(0, pos);
2817 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2818 m_subtitle_pages.push_back(page);
2819 checkSubtitleTiming();
2823 void eDVBServicePlay::checkSubtitleTiming()
2825 eDebug("checkSubtitleTiming");
2826 if (!m_subtitle_widget)
2830 enum { TELETEXT, DVB } type;
2831 eDVBTeletextSubtitlePage page;
2832 eDVBSubtitlePage dvb_page;
2834 if (!m_subtitle_pages.empty())
2836 page = m_subtitle_pages.front();
2838 show_time = page.m_pts;
2840 else if (!m_dvb_subtitle_pages.empty())
2842 dvb_page = m_dvb_subtitle_pages.front();
2844 show_time = dvb_page.m_show_time;
2852 m_decoder->getPTS(0, pos);
2854 eDebug("%lld %lld", pos, show_time);
2855 int diff = show_time - pos;
2856 if (type == TELETEXT && !page.m_have_pts)
2858 eDebug("ttx subtitle page without pts... immediate show");
2863 eDebug("[late (%d ms)]", -diff / 90);
2866 if (abs(diff) > 1800000)
2868 eDebug("[invalid]... immediate show!");
2873 if (type == TELETEXT)
2875 eDebug("display teletext subtitle page %lld", show_time);
2876 m_subtitle_widget->setPage(page);
2877 m_subtitle_pages.pop_front();
2881 eDebug("display dvb subtitle Page %lld", show_time);
2882 m_subtitle_widget->setPage(dvb_page);
2883 m_dvb_subtitle_pages.pop_front();
2887 eDebug("start subtitle delay %d", diff / 90);
2888 m_subtitle_sync_timer->start(diff / 90, 1);
2894 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2896 if (m_subtitle_widget)
2900 m_decoder->getPTS(0, pos);
2901 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2902 m_dvb_subtitle_pages.push_back(p);
2903 checkSubtitleTiming();
2907 int eDVBServicePlay::getAC3Delay()
2910 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2912 return m_decoder->getAC3Delay();
2917 int eDVBServicePlay::getPCMDelay()
2920 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2922 return m_decoder->getPCMDelay();
2927 void eDVBServicePlay::setAC3Delay(int delay)
2930 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2932 m_decoder->setAC3Delay(delay);
2935 void eDVBServicePlay::setPCMDelay(int delay)
2938 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2940 m_decoder->setPCMDelay(delay);
2943 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2945 switch(event.type) {
2946 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2947 m_event((iPlayableService*)this, evVideoSizeChanged);
2949 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2950 m_event((iPlayableService*)this, evVideoFramerateChanged);
2952 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2953 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2960 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2966 PyObject *eDVBServicePlay::getStreamingData()
2968 eDVBServicePMTHandler::program program;
2969 if (m_service_handler.getProgramInfo(program))
2974 ePyObject r = program.createPythonObject();
2975 ePtr<iDVBDemux> demux;
2976 if (!m_service_handler.getDataDemux(demux))
2979 if (!demux->getCADemuxID(demux_id))
2980 PutToDict(r, "demux", demux_id);
2987 DEFINE_REF(eDVBServicePlay)
2989 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2993 case iServiceInformation::sTransponderData:
2994 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2998 return iStaticServiceInformation::getInfoObject(ref, w);
3001 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");