1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
106 if (r.type == eServiceReference::idDVB)
108 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
111 case iServiceInformation::sTransponderData:
113 ePtr<eDVBResourceManager> res;
114 if (!eDVBResourceManager::getInstance(res))
116 ePtr<iDVBChannelList> db;
117 if (!res->getChannelList(db))
120 ref.getChannelID(chid);
121 ePtr<iDVBFrontendParameters> feparm;
122 if (!db->getChannelFrontendData(chid, feparm))
125 if (!feparm->getSystem(system))
127 ePyObject dict = PyDict_New();
130 case iDVBFrontend::feSatellite:
132 eDVBFrontendParametersSatellite s;
134 PutSatelliteDataToDict(dict, s);
137 case iDVBFrontend::feTerrestrial:
139 eDVBFrontendParametersTerrestrial t;
141 PutTerrestrialDataToDict(dict, t);
144 case iDVBFrontend::feCable:
146 eDVBFrontendParametersCable c;
148 PutCableDataToDict(dict, c);
152 eDebug("unknown frontend type %d", system);
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
171 ePtr<iDVBChannelList> db;
172 ePtr<eDVBResourceManager> res;
175 if ((err = eDVBResourceManager::getInstance(res)) != 0)
177 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
180 if ((err = res->getChannelList(db)) != 0)
182 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
187 if ((err = db->getBouquet(ref, bouquet)) != 0)
189 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
193 if ( bouquet && bouquet->m_bouquet_name.length() )
195 name = bouquet->m_bouquet_name;
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
204 if (ref.flags & eServiceReference::isGroup)
206 ePtr<iDVBChannelList> db;
207 ePtr<eDVBResourceManager> res;
209 if (eDVBResourceManager::getInstance(res))
211 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
215 if (res->getChannelList(db))
217 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
222 if (db->getBouquet(ref, bouquet))
224 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
228 int prio_order = eDVBFrontend::getTypePriorityOrder();
230 eDVBChannelID chid, chid_ignore;
231 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
234 static unsigned char prio_map[6][3] = {
235 { 3, 2, 1 }, // -S -C -T
236 { 3, 1, 2 }, // -S -T -C
237 { 2, 3, 1 }, // -C -S -T
238 { 1, 3, 2 }, // -C -T -S
239 { 1, 2, 3 }, // -T -C -S
240 { 2, 1, 3 } // -T -S -C
242 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
248 case 30000: // cached DVB-T channel
249 case 1: // DVB-T frontend
250 tmp = prio_map[prio_order][2];
252 case 40000: // cached DVB-C channel
254 tmp = prio_map[prio_order][1];
257 tmp = prio_map[prio_order][0];
262 m_playable_service = *it;
269 m_playable_service = eServiceReference();
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
278 #include <lib/dvb/epgcache.h>
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
282 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
287 DECLARE_REF(eStaticServiceDVBPVRInformation);
288 eServiceReference m_ref;
289 eDVBMetaParser m_parser;
291 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292 RESULT getName(const eServiceReference &ref, std::string &name);
293 int getLength(const eServiceReference &ref);
294 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296 int getInfo(const eServiceReference &ref, int w);
297 std::string getInfoString(const eServiceReference &ref,int w);
298 PyObject *getInfoObject(const eServiceReference &r, int what);
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
306 m_parser.parseFile(ref.path);
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
311 ASSERT(ref == m_ref);
312 if (m_parser.m_name.size())
313 name = m_parser.m_name;
317 size_t n = name.rfind('/');
318 if (n != std::string::npos)
319 name = name.substr(n + 1);
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
326 ASSERT(ref == m_ref);
331 stat(ref.path.c_str(), &s);
333 if (tstools.openFile(ref.path.c_str(), 1))
336 /* check if cached data is still valid */
337 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338 return m_parser.m_length / 90000;
340 /* open again, this time with stream info */
341 if (tstools.openFile(ref.path.c_str()))
344 /* otherwise, re-calc length and update meta file */
346 if (tstools.calcLen(len))
349 m_parser.m_length = len;
350 m_parser.m_filesize = s.st_size;
351 m_parser.updateMeta(ref.path);
352 return m_parser.m_length / 90000;
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
359 case iServiceInformation::sDescription:
360 return iServiceInformation::resIsString;
361 case iServiceInformation::sServiceref:
362 return iServiceInformation::resIsString;
363 case iServiceInformation::sFileSize:
364 return m_parser.m_filesize;
365 case iServiceInformation::sTimeCreate:
366 if (m_parser.m_time_create)
367 return m_parser.m_time_create;
369 return iServiceInformation::resNA;
371 return iServiceInformation::resNA;
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
379 case iServiceInformation::sDescription:
380 return m_parser.m_description;
381 case iServiceInformation::sServiceref:
382 return m_parser.m_ref.toString();
383 case iServiceInformation::sTags:
384 return m_parser.m_tags;
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
394 case iServiceInformation::sFileSize:
395 return PyLong_FromLongLong(m_parser.m_filesize);
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
403 if (!ref.path.empty())
405 ePtr<eServiceEvent> event = new eServiceEvent;
406 std::string filename = ref.path;
407 filename.erase(filename.length()-2, 2);
409 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
421 DECLARE_REF(eDVBPVRServiceOfflineOperations);
422 eServiceReferenceDVB m_ref;
424 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
426 RESULT deleteFromDisk(int simulate);
427 RESULT getListOfFilenames(std::list<std::string> &);
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
443 std::list<std::string> res;
444 if (getListOfFilenames(res))
447 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
449 eDebug("FATAL !! can't get background file eraser");
451 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
453 eDebug("Removing %s...", i->c_str());
455 eraser->erase(i->c_str());
457 ::unlink(i->c_str());
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
467 res.push_back(m_ref.path);
469 // handling for old splitted recordings (enigma 1)
474 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
476 if (stat(buf, &s) < 0)
481 res.push_back(m_ref.path + ".meta");
482 res.push_back(m_ref.path + ".ap");
483 res.push_back(m_ref.path + ".sc");
484 res.push_back(m_ref.path + ".cuts");
485 std::string tmp = m_ref.path;
486 tmp.erase(m_ref.path.length()-3);
487 res.push_back(tmp + ".eit");
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
493 const char *filename = m_ref.path.c_str();
494 eDebug("reindexing %s...", filename);
496 eMPEGStreamInformation info;
497 eMPEGStreamParserTS parser(info);
499 info.startSave(filename);
503 int err = f.open(m_ref.path.c_str(), 0);
507 off_t length = f.length();
508 unsigned char buffer[188*256*4];
511 off_t offset = f.lseek(0, SEEK_CUR);
512 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513 int r = f.read(buffer, sizeof(buffer));
518 parser.parseData(offset, buffer, r);
527 DEFINE_REF(eServiceFactoryDVB)
529 eServiceFactoryDVB::eServiceFactoryDVB()
531 ePtr<eServiceCenter> sc;
533 eServiceCenter::getPrivInstance(sc);
536 std::list<std::string> extensions;
537 extensions.push_back("ts");
538 extensions.push_back("trp");
539 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
542 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
543 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
546 eServiceFactoryDVB::~eServiceFactoryDVB()
548 ePtr<eServiceCenter> sc;
550 eServiceCenter::getPrivInstance(sc);
552 sc->removeServiceFactory(eServiceFactoryDVB::id);
555 DEFINE_REF(eDVBServiceList);
557 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
561 eDVBServiceList::~eDVBServiceList()
565 RESULT eDVBServiceList::startQuery()
567 ePtr<iDVBChannelList> db;
568 ePtr<eDVBResourceManager> res;
571 if ((err = eDVBResourceManager::getInstance(res)) != 0)
573 eDebug("no resource manager");
576 if ((err = res->getChannelList(db)) != 0)
578 eDebug("no channel list");
582 ePtr<eDVBChannelQuery> q;
584 if (!m_parent.path.empty())
586 eDVBChannelQuery::compile(q, m_parent.path);
589 eDebug("compile query failed");
594 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
596 eDebug("startQuery failed");
603 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
605 eServiceReferenceDVB ref;
610 while (!m_query->getNextResult(ref))
614 list.sort(iListableServiceCompare(this));
619 // The first argument of this function is a format string to specify the order and
620 // the content of the returned list
621 // useable format options are
622 // R = Service Reference (as swig object .. this is very slow)
623 // S = Service Reference (as python string object .. same as ref.toString())
624 // C = Service Reference (as python string object .. same as ref.toCompareString())
625 // N = Service Name (as python string object)
626 // n = Short Service Name (short name brakets used) (as python string object)
627 // when exactly one return value per service is selected in the format string,
628 // then each value is directly a list entry
629 // when more than one value is returned per service, then the list is a list of
631 // unknown format string chars are returned as python None values !
632 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
635 std::list<eServiceReference> tmplist;
638 if (!format || !(retcount=strlen(format)))
639 format = "R"; // just return service reference swig object ...
641 if (!getContent(tmplist, sorted))
643 int services=tmplist.size();
644 ePtr<iStaticServiceInformation> sptr;
645 eServiceCenterPtr service_center;
647 if (strchr(format, 'N') || strchr(format, 'n'))
648 eServiceCenter::getPrivInstance(service_center);
650 ret = PyList_New(services);
651 std::list<eServiceReference>::iterator it(tmplist.begin());
653 for (int cnt=0; cnt < services; ++cnt)
655 eServiceReference &ref=*it++;
656 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
657 for (int i=0; i < retcount; ++i)
662 case 'R': // service reference (swig)object
663 tmp = NEW_eServiceReference(ref);
665 case 'C': // service reference compare string
666 tmp = PyString_FromString(ref.toCompareString().c_str());
668 case 'S': // service reference string
669 tmp = PyString_FromString(ref.toString().c_str());
671 case 'N': // service name
674 service_center->info(ref, sptr);
678 sptr->getName(ref, name);
680 // filter short name brakets
682 while((pos = name.find("\xc2\x86")) != std::string::npos)
684 while((pos = name.find("\xc2\x87")) != std::string::npos)
688 tmp = PyString_FromString(name.c_str());
692 tmp = PyString_FromString("<n/a>");
694 case 'n': // short service name
697 service_center->info(ref, sptr);
701 sptr->getName(ref, name);
702 name = buildShortName(name);
704 tmp = PyString_FromString(name.c_str());
708 tmp = PyString_FromString("<n/a>");
721 PyTuple_SET_ITEM(tuple, i, tmp);
723 PyList_SET_ITEM(ret, cnt, tmp);
727 PyList_SET_ITEM(ret, cnt, tuple);
730 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
733 RESULT eDVBServiceList::getNext(eServiceReference &ref)
738 return m_query->getNextResult((eServiceReferenceDVB&)ref);
741 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
743 if (m_parent.flags & eServiceReference::canDescent) // bouquet
745 ePtr<iDVBChannelList> db;
746 ePtr<eDVBResourceManager> resm;
748 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
751 if (db->getBouquet(m_parent, m_bouquet) != 0)
762 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
766 return m_bouquet->addService(ref, before);
769 RESULT eDVBServiceList::removeService(eServiceReference &ref)
773 return m_bouquet->removeService(ref);
776 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
780 return m_bouquet->moveService(ref, pos);
783 RESULT eDVBServiceList::flushChanges()
787 return m_bouquet->flushChanges();
790 RESULT eDVBServiceList::setListName(const std::string &name)
794 return m_bouquet->setListName(name);
797 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
799 ePtr<eDVBService> service;
800 int r = lookupService(service, ref);
803 // check resources...
804 ptr = new eDVBServicePlay(ref, service);
808 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
810 if (ref.path.empty())
812 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
821 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
823 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
824 if (list->startQuery())
834 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
836 /* is a listable service? */
837 if (ref.flags & eServiceReference::canDescent) // bouquet
839 if ( !ref.name.empty() ) // satellites or providers list
840 ptr = m_StaticServiceDVBInfo;
841 else // a dvb bouquet
842 ptr = m_StaticServiceDVBBouquetInfo;
844 else if (!ref.path.empty()) /* do we have a PVR service? */
845 ptr = new eStaticServiceDVBPVRInformation(ref);
846 else // normal dvb service
848 ePtr<eDVBService> service;
849 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
850 ptr = m_StaticServiceDVBInfo;
852 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
858 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
860 if (ref.path.empty())
866 ptr = new eDVBPVRServiceOfflineOperations(ref);
871 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
873 if (!ref.path.empty()) // playback
875 eDVBMetaParser parser;
876 int ret=parser.parseFile(ref.path);
877 service = new eDVBService;
879 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
883 // TODO: handle the listing itself
884 // if (ref.... == -1) .. return "... bouquets ...";
885 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
887 ePtr<iDVBChannelList> db;
888 ePtr<eDVBResourceManager> res;
891 if ((err = eDVBResourceManager::getInstance(res)) != 0)
893 eDebug("no resource manager");
896 if ((err = res->getChannelList(db)) != 0)
898 eDebug("no channel list");
902 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
903 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
905 eDebug("getService failed!");
913 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
914 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
917 m_is_pvr = !m_reference.path.empty();
919 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
920 m_skipmode = m_fastforward = m_slowmotion = 0;
922 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
923 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
924 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
926 m_cuesheet_changed = 0;
927 m_cutlist_enabled = 1;
929 m_subtitle_widget = 0;
933 m_subtitle_sync_timer = eTimer::create(eApp);
935 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
938 eDVBServicePlay::~eDVBServicePlay()
943 int ret=meta.parseFile(m_reference.path);
947 meta.m_service_data="";
948 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
949 meta.m_service_data += tmp;
951 for (int x=0; x < eDVBService::cacheMax; ++x)
953 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
956 sprintf(tmp, ",c:%02d%04x", x, entry);
957 meta.m_service_data += tmp;
960 meta.updateMeta(m_reference.path);
963 delete m_subtitle_widget;
966 void eDVBServicePlay::gotNewEvent()
970 ePtr<eServiceEvent> m_event_now, m_event_next;
971 getEvent(m_event_now, 0);
972 getEvent(m_event_next, 1);
975 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
977 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
979 m_event((iPlayableService*)this, evUpdatedEventInfo);
982 void eDVBServicePlay::serviceEvent(int event)
984 m_tune_state = event;
988 case eDVBServicePMTHandler::eventTuned:
990 ePtr<iDVBDemux> m_demux;
991 if (!m_service_handler.getDataDemux(m_demux))
993 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
994 int sid = ref.getParentServiceID().get();
996 sid = ref.getServiceID().get();
997 if ( ref.getParentTransportStreamID().get() &&
998 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
999 m_event_handler.startOther(m_demux, sid);
1001 m_event_handler.start(m_demux, sid);
1003 m_event((iPlayableService*)this, evTunedIn);
1006 case eDVBServicePMTHandler::eventNoResources:
1007 case eDVBServicePMTHandler::eventNoPAT:
1008 case eDVBServicePMTHandler::eventNoPATEntry:
1009 case eDVBServicePMTHandler::eventNoPMT:
1010 case eDVBServicePMTHandler::eventTuneFailed:
1011 case eDVBServicePMTHandler::eventMisconfiguration:
1013 eDebug("DVB service failed to tune - error %d", event);
1014 m_event((iPlayableService*)this, evTuneFailed);
1017 case eDVBServicePMTHandler::eventNewProgramInfo:
1019 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1020 if (m_timeshift_enabled)
1021 updateTimeshiftPids();
1022 if (!m_timeshift_active)
1024 if (m_first_program_info && m_is_pvr)
1026 m_first_program_info = 0;
1029 m_event((iPlayableService*)this, evUpdatedInfo);
1032 case eDVBServicePMTHandler::eventPreStart:
1035 case eDVBServicePMTHandler::eventEOF:
1036 m_event((iPlayableService*)this, evEOF);
1038 case eDVBServicePMTHandler::eventSOF:
1039 m_event((iPlayableService*)this, evSOF);
1044 void eDVBServicePlay::serviceEventTimeshift(int event)
1048 case eDVBServicePMTHandler::eventNewProgramInfo:
1049 if (m_timeshift_active)
1052 case eDVBServicePMTHandler::eventSOF:
1053 m_event((iPlayableService*)this, evSOF);
1055 case eDVBServicePMTHandler::eventEOF:
1056 if ((!m_is_paused) && (m_skipmode >= 0))
1058 eDebug("timeshift EOF, so let's go live");
1065 RESULT eDVBServicePlay::start()
1067 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1069 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1070 two (one for decoding, one for data source), as we must be prepared
1071 to start recording from the data demux. */
1074 eDVBMetaParser meta;
1075 if (!meta.parseFile(m_reference.path))
1077 service = meta.m_ref;
1078 service.path = m_reference.path;
1080 m_cue = new eCueSheet();
1083 m_event(this, evStart);
1085 m_first_program_info = 1;
1086 m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1090 /* inject EIT if there is a stored one */
1091 std::string filename = service.path;
1092 filename.erase(filename.length()-2, 2);
1094 ePtr<eServiceEvent> event = new eServiceEvent;
1095 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1097 ePtr<eServiceEvent> empty;
1098 m_event_handler.inject(event, 0);
1099 m_event_handler.inject(empty, 1);
1101 m_event(this, evStart);
1106 RESULT eDVBServicePlay::stop()
1108 /* add bookmark for last play position */
1111 pts_t play_position, length;
1112 if (!getPlayPosition(play_position))
1114 /* remove last position */
1115 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1117 if (i->what == 3) /* current play position */
1119 m_cue_entries.erase(i);
1120 i = m_cue_entries.begin();
1126 if (getLength(length))
1131 int perc = play_position * 100LL / length;
1133 /* only store last play position when between 1% and 99% */
1134 if ((1 < perc) && (perc < 99))
1135 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1137 m_cuesheet_changed = 1;
1141 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1143 m_service_handler_timeshift.free();
1144 m_service_handler.free();
1146 if (m_is_pvr && m_cuesheet_changed)
1149 /* save cuesheet only when main file is accessible. */
1150 if (!::stat(m_reference.path.c_str(), &s))
1153 m_event((iPlayableService*)this, evStopped);
1157 RESULT eDVBServicePlay::setTarget(int target)
1159 m_is_primary = !target;
1163 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1165 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1169 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1171 /* note: we check for timeshift to be enabled,
1172 not neccessary active. if you pause when timeshift
1173 is not active, you should activate it when unpausing */
1174 if ((!m_is_pvr) && (!m_timeshift_enabled))
1184 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1186 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1187 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1188 setFastForward_internal(0);
1191 m_slowmotion = ratio;
1192 return m_decoder->setSlowMotion(ratio);
1198 RESULT eDVBServicePlay::setFastForward(int ratio)
1200 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1202 return setFastForward_internal(ratio);
1205 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1207 int skipmode, ffratio, ret = 0;
1214 } else if (ratio > 0)
1222 } else // if (ratio < 0)
1228 if (m_skipmode != skipmode)
1230 eDebug("setting cue skipmode to %d", skipmode);
1232 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1235 m_skipmode = skipmode;
1238 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1240 m_fastforward = ffratio;
1246 ; /* return m_decoder->play(); is done in caller*/
1247 else if (ffratio != 1)
1248 ret = m_decoder->setFastForward(ffratio);
1250 ret = m_decoder->setTrickmode();
1253 eDebug("final seek after trickplay ret %d", seekTo(pos));
1258 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1260 if (m_is_pvr || m_timeshift_enabled)
1270 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1271 RESULT eDVBServicePlay::getLength(pts_t &len)
1273 ePtr<iDVBPVRChannel> pvr_channel;
1275 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1278 return pvr_channel->getLength(len);
1281 RESULT eDVBServicePlay::pause()
1283 eDebug("eDVBServicePlay::pause");
1284 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1289 return m_decoder->pause();
1294 RESULT eDVBServicePlay::unpause()
1296 eDebug("eDVBServicePlay::unpause");
1297 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1302 return m_decoder->play();
1307 RESULT eDVBServicePlay::seekTo(pts_t to)
1309 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1311 if (!m_decode_demux)
1314 ePtr<iDVBPVRChannel> pvr_channel;
1316 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1322 m_cue->seekTo(0, to);
1323 m_dvb_subtitle_pages.clear();
1324 m_subtitle_pages.clear();
1329 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1331 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1333 if (!m_decode_demux)
1336 ePtr<iDVBPVRChannel> pvr_channel;
1338 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1343 /* HACK until we have skip-AP api */
1344 if ((to > 0) && (to < 100))
1352 m_cue->seekTo(mode, to);
1353 m_dvb_subtitle_pages.clear();
1354 m_subtitle_pages.clear();
1358 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1360 ePtr<iDVBPVRChannel> pvr_channel;
1362 if (!m_decode_demux)
1365 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1370 /* if there is a decoder, use audio or video PTS */
1373 r = m_decoder->getPTS(0, pos);
1379 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1382 RESULT eDVBServicePlay::setTrickmode(int trick)
1384 /* currently unimplemented */
1388 RESULT eDVBServicePlay::isCurrentlySeekable()
1390 return m_is_pvr || m_timeshift_active;
1393 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1399 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1405 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1411 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1417 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1423 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1426 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1427 (m_timeshift_enabled || !m_is_pvr))
1429 if (!m_timeshift_enabled)
1431 /* query config path */
1433 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1434 eDebug("could not query ts path from config");
1438 /* we need enough diskspace */
1440 if (statfs(tspath.c_str(), &fs) < 0)
1442 eDebug("statfs failed!");
1446 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1448 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1458 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1469 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1475 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1481 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1487 RESULT eDVBServicePlay::getName(std::string &name)
1491 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1492 return i->getName(m_reference, name);
1494 else if (m_dvb_service)
1496 m_dvb_service->getName(m_reference, name);
1500 else if (!m_reference.name.empty())
1501 eStaticServiceDVBInformation().getName(m_reference, name);
1503 name = "DVB service";
1507 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1509 return m_event_handler.getEvent(evt, nownext);
1512 int eDVBServicePlay::getInfo(int w)
1514 eDVBServicePMTHandler::program program;
1517 return resIsPyObject;
1519 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1521 int no_program_info = 0;
1523 if (h.getProgramInfo(program))
1524 no_program_info = 1;
1530 return m_decoder->getVideoHeight();
1534 return m_decoder->getVideoWidth();
1538 return m_decoder->getVideoFrameRate();
1542 return m_decoder->getVideoProgressive();
1548 aspect = m_decoder->getVideoAspect();
1549 if (aspect == -1 && no_program_info)
1551 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1553 ePtr<eServiceEvent> evt;
1554 if (!m_event_handler.getEvent(evt, 0))
1556 ePtr<eComponentData> data;
1557 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1559 if ( data->getStreamContent() == 1 )
1561 switch(data->getComponentType())
1564 case 1: // 4:3 SD PAL
1566 case 3: // 16:9 SD PAL
1567 case 4: // > 16:9 PAL
1568 case 5: // 4:3 SD NTSC
1570 case 7: // 16:9 SD NTSC
1571 case 8: // > 16:9 NTSC
1574 case 9: // 4:3 HD PAL
1576 case 0xB: // 16:9 HD PAL
1577 case 0xC: // > 16:9 HD PAL
1578 case 0xD: // 4:3 HD NTSC
1580 case 0xF: // 16:9 HD NTSC
1581 case 0x10: // > 16:9 HD PAL
1582 return data->getComponentType();
1592 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1596 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1600 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1601 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1605 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1608 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1612 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1616 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1620 if (no_program_info) return -1; return program.pcrPid;
1621 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1622 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1623 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1624 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1625 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1626 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1627 case sProvider: if (!m_dvb_service) return -1; return -2;
1628 case sServiceref: return resIsString;
1629 case sDVBState: return m_tune_state;
1636 std::string eDVBServicePlay::getInfoString(int w)
1641 if (!m_dvb_service) return "";
1642 return m_dvb_service->m_provider_name;
1644 return m_reference.toString();
1648 return iServiceInformation::getInfoString(w);
1651 PyObject *eDVBServicePlay::getInfoObject(int w)
1656 return m_service_handler.getCaIds();
1657 case sTransponderData:
1658 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1662 return iServiceInformation::getInfoObject(w);
1665 int eDVBServicePlay::getNumberOfTracks()
1667 eDVBServicePMTHandler::program program;
1668 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1669 if (h.getProgramInfo(program))
1671 return program.audioStreams.size();
1674 int eDVBServicePlay::getCurrentTrack()
1676 eDVBServicePMTHandler::program program;
1677 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1678 if (h.getProgramInfo(program))
1681 int max = program.audioStreams.size();
1684 for (i = 0; i < max; ++i)
1685 if (program.audioStreams[i].pid == m_current_audio_pid)
1691 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1693 int ret = selectAudioStream(i);
1695 if (m_decoder->set())
1701 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1703 eDVBServicePMTHandler::program program;
1704 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1706 if (h.getProgramInfo(program))
1709 if (i >= program.audioStreams.size())
1712 info.m_pid = program.audioStreams[i].pid;
1714 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1715 info.m_description = "MPEG";
1716 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1717 info.m_description = "AC3";
1718 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1719 info.m_description = "AAC";
1720 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1721 info.m_description = "AAC-HE";
1722 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1723 info.m_description = "DTS";
1725 info.m_description = "???";
1727 if (program.audioStreams[i].component_tag != -1)
1729 ePtr<eServiceEvent> evt;
1730 if (!m_event_handler.getEvent(evt, 0))
1732 ePtr<eComponentData> data;
1733 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1734 info.m_language = data->getText();
1738 if (info.m_language.empty())
1739 info.m_language = program.audioStreams[i].language_code;
1744 int eDVBServicePlay::selectAudioStream(int i)
1746 eDVBServicePMTHandler::program program;
1747 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1748 pts_t position = -1;
1750 if (h.getProgramInfo(program))
1753 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1761 stream = program.defaultAudioStream;
1763 int apid = -1, apidtype = -1;
1765 if (((unsigned int)stream) < program.audioStreams.size())
1767 apid = program.audioStreams[stream].pid;
1768 apidtype = program.audioStreams[stream].type;
1771 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1772 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1774 m_current_audio_pid = apid;
1776 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1778 eDebug("set audio pid failed");
1783 eDebug("seekTo ret %d", seekTo(position));
1787 /* 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 */
1788 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1790 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1792 rdsPid = program.audioStreams[stream].rdsPid;
1793 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1796 ePtr<iDVBDemux> data_demux;
1797 if (!h.getDataDemux(data_demux))
1799 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1800 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1801 m_rds_decoder->start(rdsPid);
1806 /* store new pid as default only when:
1807 a.) we have an entry in the service db for the current service,
1808 b.) we are not playing back something,
1809 c.) we are not selecting the default entry. (we wouldn't change
1810 anything in the best case, or destroy the default setting in
1811 case the real default is not yet available.)
1813 if (m_dvb_service && ((i != -1)
1814 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1816 if (apidtype == eDVBAudio::aMPEG)
1818 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1819 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1821 else if (apidtype == eDVBAudio::aAC3)
1823 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1824 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1828 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1829 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1833 h.resetCachedProgram();
1838 int eDVBServicePlay::getCurrentChannel()
1840 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1843 RESULT eDVBServicePlay::selectChannel(int i)
1845 if (i < LEFT || i > RIGHT || i == STEREO)
1848 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1850 m_decoder->setAudioChannel(i);
1854 std::string eDVBServicePlay::getText(int x)
1860 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1862 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1867 void eDVBServicePlay::rdsDecoderEvent(int what)
1871 case eDVBRdsDecoder::RadioTextChanged:
1872 m_event((iPlayableService*)this, evUpdatedRadioText);
1874 case eDVBRdsDecoder::RtpTextChanged:
1875 m_event((iPlayableService*)this, evUpdatedRtpText);
1877 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1878 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1880 case eDVBRdsDecoder::RecvRassSlidePic:
1881 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1886 void eDVBServicePlay::showRassSlidePicture()
1892 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1893 if (rass_slide_pic.length())
1894 m_decoder->showSinglePic(rass_slide_pic.c_str());
1896 eDebug("empty filename for rass slide picture received!!");
1899 eDebug("no MPEG Decoder to show iframes avail");
1902 eDebug("showRassSlidePicture called.. but not decoder");
1905 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1911 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1912 if (rass_interactive_pic.length())
1913 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1915 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1918 eDebug("no MPEG Decoder to show iframes avail");
1921 eDebug("showRassInteractivePic called.. but not decoder");
1924 ePyObject eDVBServicePlay::getRassInteractiveMask()
1927 return m_rds_decoder->getRassPictureMask();
1931 int eDVBServiceBase::getFrontendInfo(int w)
1933 eUsePtr<iDVBChannel> channel;
1934 if(m_service_handler.getChannel(channel))
1936 ePtr<iDVBFrontend> fe;
1937 if(channel->getFrontend(fe))
1939 return fe->readFrontendData(w);
1942 PyObject *eDVBServiceBase::getFrontendData()
1944 ePyObject ret = PyDict_New();
1947 eUsePtr<iDVBChannel> channel;
1948 if(!m_service_handler.getChannel(channel))
1950 ePtr<iDVBFrontend> fe;
1951 if(!channel->getFrontend(fe))
1952 fe->getFrontendData(ret);
1960 PyObject *eDVBServiceBase::getFrontendStatus()
1962 ePyObject ret = PyDict_New();
1965 eUsePtr<iDVBChannel> channel;
1966 if(!m_service_handler.getChannel(channel))
1968 ePtr<iDVBFrontend> fe;
1969 if(!channel->getFrontend(fe))
1970 fe->getFrontendStatus(ret);
1978 PyObject *eDVBServiceBase::getTransponderData(bool original)
1980 ePyObject ret = PyDict_New();
1983 eUsePtr<iDVBChannel> channel;
1984 if(!m_service_handler.getChannel(channel))
1986 ePtr<iDVBFrontend> fe;
1987 if(!channel->getFrontend(fe))
1988 fe->getTransponderData(ret, original);
1996 PyObject *eDVBServiceBase::getAll(bool original)
1998 ePyObject ret = getTransponderData(original);
2001 eUsePtr<iDVBChannel> channel;
2002 if(!m_service_handler.getChannel(channel))
2004 ePtr<iDVBFrontend> fe;
2005 if(!channel->getFrontend(fe))
2007 fe->getFrontendData(ret);
2008 fe->getFrontendStatus(ret);
2015 int eDVBServicePlay::getNumberOfSubservices()
2017 ePtr<eServiceEvent> evt;
2018 if (!m_event_handler.getEvent(evt, 0))
2019 return evt->getNumOfLinkageServices();
2023 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2025 ePtr<eServiceEvent> evt;
2026 if (!m_event_handler.getEvent(evt, 0))
2028 if (!evt->getLinkageService(sub, m_reference, n))
2031 sub.type=eServiceReference::idInvalid;
2035 RESULT eDVBServicePlay::startTimeshift()
2037 ePtr<iDVBDemux> demux;
2039 eDebug("Start timeshift!");
2041 if (m_timeshift_enabled)
2044 /* start recording with the data demux. */
2045 if (m_service_handler.getDataDemux(demux))
2048 demux->createTSRecorder(m_record);
2053 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2054 eDebug("could not query ts path");
2057 tspath.append("/timeshift.XXXXXX");
2059 templ = new char[tspath.length() + 1];
2060 strcpy(templ, tspath.c_str());
2062 m_timeshift_fd = mkstemp(templ);
2063 m_timeshift_file = std::string(templ);
2065 eDebug("recording to %s", templ);
2069 if (m_timeshift_fd < 0)
2075 m_record->setTargetFD(m_timeshift_fd);
2077 m_timeshift_enabled = 1;
2079 updateTimeshiftPids();
2085 RESULT eDVBServicePlay::stopTimeshift()
2087 if (!m_timeshift_enabled)
2092 m_timeshift_enabled = 0;
2097 close(m_timeshift_fd);
2098 eDebug("remove timeshift file");
2099 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2104 int eDVBServicePlay::isTimeshiftActive()
2106 return m_timeshift_enabled && m_timeshift_active;
2109 RESULT eDVBServicePlay::activateTimeshift()
2111 if (!m_timeshift_enabled)
2114 if (!m_timeshift_active)
2116 switchToTimeshift();
2123 PyObject *eDVBServicePlay::getCutList()
2125 ePyObject list = PyList_New(0);
2127 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2129 ePyObject tuple = PyTuple_New(2);
2130 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2131 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2132 PyList_Append(list, tuple);
2139 void eDVBServicePlay::setCutList(ePyObject list)
2141 if (!PyList_Check(list))
2143 int size = PyList_Size(list);
2146 m_cue_entries.clear();
2148 for (i=0; i<size; ++i)
2150 ePyObject tuple = PyList_GET_ITEM(list, i);
2151 if (!PyTuple_Check(tuple))
2153 eDebug("non-tuple in cutlist");
2156 if (PyTuple_Size(tuple) != 2)
2158 eDebug("cutlist entries need to be a 2-tuple");
2161 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2162 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2164 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2167 pts_t pts = PyLong_AsLongLong(ppts);
2168 int type = PyInt_AsLong(ptype);
2169 m_cue_entries.insert(cueEntry(pts, type));
2170 eDebug("adding %08llx, %d", pts, type);
2172 m_cuesheet_changed = 1;
2174 cutlistToCuesheet();
2175 m_event((iPlayableService*)this, evCuesheetChanged);
2178 void eDVBServicePlay::setCutListEnable(int enable)
2180 m_cutlist_enabled = enable;
2181 cutlistToCuesheet();
2184 void eDVBServicePlay::updateTimeshiftPids()
2189 eDVBServicePMTHandler::program program;
2190 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2192 if (h.getProgramInfo(program))
2196 std::set<int> pids_to_record;
2197 pids_to_record.insert(0); // PAT
2198 if (program.pmtPid != -1)
2199 pids_to_record.insert(program.pmtPid); // PMT
2201 if (program.textPid != -1)
2202 pids_to_record.insert(program.textPid); // Videotext
2204 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2205 i(program.videoStreams.begin());
2206 i != program.videoStreams.end(); ++i)
2207 pids_to_record.insert(i->pid);
2209 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2210 i(program.audioStreams.begin());
2211 i != program.audioStreams.end(); ++i)
2212 pids_to_record.insert(i->pid);
2214 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2215 i(program.subtitleStreams.begin());
2216 i != program.subtitleStreams.end(); ++i)
2217 pids_to_record.insert(i->pid);
2219 std::set<int> new_pids, obsolete_pids;
2221 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2222 m_pids_active.begin(), m_pids_active.end(),
2223 std::inserter(new_pids, new_pids.begin()));
2225 std::set_difference(
2226 m_pids_active.begin(), m_pids_active.end(),
2227 pids_to_record.begin(), pids_to_record.end(),
2228 std::inserter(new_pids, new_pids.begin())
2231 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2232 m_record->addPID(*i);
2234 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2235 m_record->removePID(*i);
2239 void eDVBServicePlay::switchToLive()
2241 if (!m_timeshift_active)
2244 eDebug("SwitchToLive");
2249 m_teletext_parser = 0;
2251 m_subtitle_parser = 0;
2252 m_new_dvb_subtitle_page_connection = 0;
2253 m_new_subtitle_page_connection = 0;
2254 m_rds_decoder_event_connection = 0;
2255 m_video_event_connection = 0;
2256 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2258 /* free the timeshift service handler, we need the resources */
2259 m_service_handler_timeshift.free();
2260 m_timeshift_active = 0;
2261 m_timeshift_changed = 1;
2263 m_event((iPlayableService*)this, evSeekableStatusChanged);
2268 void eDVBServicePlay::switchToTimeshift()
2270 if (m_timeshift_active)
2275 m_teletext_parser = 0;
2277 m_subtitle_parser = 0;
2278 m_new_subtitle_page_connection = 0;
2279 m_new_dvb_subtitle_page_connection = 0;
2280 m_rds_decoder_event_connection = 0;
2281 m_video_event_connection = 0;
2283 m_timeshift_active = 1;
2284 m_timeshift_changed = 1;
2286 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2287 r.path = m_timeshift_file;
2289 m_cue = new eCueSheet();
2290 m_cue->seekTo(0, -1000);
2291 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2293 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2295 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2297 m_event((iPlayableService*)this, evSeekableStatusChanged);
2300 void eDVBServicePlay::updateDecoder()
2302 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2304 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2306 eDVBServicePMTHandler::program program;
2307 if (h.getProgramInfo(program))
2308 eDebug("getting program info failed.");
2311 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2312 if (!program.videoStreams.empty())
2314 eDebugNoNewLine(" (");
2315 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2316 i(program.videoStreams.begin());
2317 i != program.videoStreams.end(); ++i)
2324 if (i != program.videoStreams.begin())
2325 eDebugNoNewLine(", ");
2326 eDebugNoNewLine("%04x", i->pid);
2328 eDebugNoNewLine(")");
2330 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2331 if (!program.audioStreams.empty())
2333 eDebugNoNewLine(" (");
2334 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2335 i(program.audioStreams.begin());
2336 i != program.audioStreams.end(); ++i)
2338 if (i != program.audioStreams.begin())
2339 eDebugNoNewLine(", ");
2340 eDebugNoNewLine("%04x", i->pid);
2342 eDebugNoNewLine(")");
2344 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2345 pcrpid = program.pcrPid;
2346 eDebug(", and the text pid is %04x", program.textPid);
2347 tpid = program.textPid;
2352 h.getDecodeDemux(m_decode_demux);
2353 if (m_timeshift_changed)
2357 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2359 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2362 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2363 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2364 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2365 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2366 if (m_timeshift_changed)
2368 ePyObject subs = getCachedSubtitle();
2369 if (subs != Py_None)
2371 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2372 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2373 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2374 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2375 if (type == 0) // dvb
2376 m_subtitle_parser->start(pid, comp_page, anc_page);
2377 else if (type == 1) // ttx
2378 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2383 m_decoder->play(); /* pids will be set later */
2386 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2387 m_decoder->play(); /* pids will be set later. */
2390 m_timeshift_changed = 0;
2396 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2397 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2398 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2402 eServiceReferenceDVB ref;
2403 m_service_handler.getServiceReference(ref);
2404 eServiceReferenceDVB parent = ref.getParentServiceReference();
2409 ePtr<eDVBResourceManager> res_mgr;
2410 if (!eDVBResourceManager::getInstance(res_mgr))
2412 ePtr<iDVBChannelList> db;
2413 if (!res_mgr->getChannelList(db))
2415 ePtr<eDVBService> origService;
2416 if (!db->getService(parent, origService))
2418 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2419 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2426 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2427 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2429 m_decoder->setVideoPID(vpid, vpidtype);
2430 selectAudioStream();
2432 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2433 m_decoder->setSyncPCR(pcrpid);
2435 m_decoder->setSyncPCR(-1);
2439 m_decoder->setTextPID(tpid);
2440 m_teletext_parser->start(program.textPid);
2443 if (vpid > 0 && vpid < 0x2000)
2447 std::string radio_pic;
2448 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2449 m_decoder->setRadioPic(radio_pic);
2453 m_decoder->setAudioChannel(achannel);
2455 /* don't worry about non-existing services, nor pvr services */
2458 /* (audio pid will be set in selectAudioTrack */
2459 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2460 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2461 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2462 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2465 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2468 void eDVBServicePlay::loadCuesheet()
2470 std::string filename = m_reference.path + ".cuts";
2472 m_cue_entries.clear();
2474 FILE *f = fopen(filename.c_str(), "rb");
2478 eDebug("loading cuts..");
2481 unsigned long long where;
2484 if (!fread(&where, sizeof(where), 1, f))
2486 if (!fread(&what, sizeof(what), 1, f))
2489 #if BYTE_ORDER == LITTLE_ENDIAN
2490 where = bswap_64(where);
2497 m_cue_entries.insert(cueEntry(where, what));
2500 eDebug("%d entries", m_cue_entries.size());
2502 eDebug("cutfile not found!");
2504 m_cuesheet_changed = 0;
2505 cutlistToCuesheet();
2506 m_event((iPlayableService*)this, evCuesheetChanged);
2509 void eDVBServicePlay::saveCuesheet()
2511 std::string filename = m_reference.path + ".cuts";
2513 FILE *f = fopen(filename.c_str(), "wb");
2517 unsigned long long where;
2520 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2522 #if BYTE_ORDER == BIG_ENDIAN
2525 where = bswap_64(i->where);
2527 what = htonl(i->what);
2528 fwrite(&where, sizeof(where), 1, f);
2529 fwrite(&what, sizeof(what), 1, f);
2535 m_cuesheet_changed = 0;
2538 void eDVBServicePlay::cutlistToCuesheet()
2542 eDebug("no cue sheet");
2547 if (!m_cutlist_enabled)
2549 m_cue->commitSpans();
2550 eDebug("cutlists were disabled");
2554 pts_t in = 0, out = 0, length = 0;
2558 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2560 int have_any_span = 0;
2564 if (i == m_cue_entries.end())
2570 if (i->what == 0) /* in */
2574 } else if (i->what == 1) /* out */
2576 else /* mark (2) or last play position (3) */
2595 m_cue->addSourceSpan(in, out);
2600 if (i == m_cue_entries.end())
2603 m_cue->commitSpans();
2606 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2608 if (m_subtitle_widget)
2609 disableSubtitles(parent);
2612 int tuplesize = PyTuple_Size(tuple);
2615 if (!PyTuple_Check(tuple))
2621 entry = PyTuple_GET_ITEM(tuple, 0);
2623 if (!PyInt_Check(entry))
2626 type = PyInt_AsLong(entry);
2628 if (type == 1) // teletext subtitles
2630 int page, magazine, pid;
2634 if (!m_teletext_parser)
2636 eDebug("enable teletext subtitles.. no parser !!!");
2640 entry = PyTuple_GET_ITEM(tuple, 1);
2641 if (!PyInt_Check(entry))
2643 pid = PyInt_AsLong(entry);
2645 entry = PyTuple_GET_ITEM(tuple, 2);
2646 if (!PyInt_Check(entry))
2648 page = PyInt_AsLong(entry);
2650 entry = PyTuple_GET_ITEM(tuple, 3);
2651 if (!PyInt_Check(entry))
2653 magazine = PyInt_AsLong(entry);
2655 m_subtitle_widget = new eSubtitleWidget(parent);
2656 m_subtitle_widget->resize(parent->size()); /* full size */
2657 m_teletext_parser->setPageAndMagazine(page, magazine);
2659 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2663 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2664 if (!m_subtitle_parser)
2666 eDebug("enable dvb subtitles.. no parser !!!");
2672 entry = PyTuple_GET_ITEM(tuple, 1);
2673 if (!PyInt_Check(entry))
2675 pid = PyInt_AsLong(entry);
2677 entry = PyTuple_GET_ITEM(tuple, 2);
2678 if (!PyInt_Check(entry))
2680 composition_page_id = PyInt_AsLong(entry);
2682 entry = PyTuple_GET_ITEM(tuple, 3);
2683 if (!PyInt_Check(entry))
2685 ancillary_page_id = PyInt_AsLong(entry);
2687 m_subtitle_widget = new eSubtitleWidget(parent);
2688 m_subtitle_widget->resize(parent->size()); /* full size */
2689 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2691 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2697 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2698 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2699 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2703 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2705 delete m_subtitle_widget;
2706 m_subtitle_widget = 0;
2707 if (m_subtitle_parser)
2709 m_subtitle_parser->stop();
2710 m_dvb_subtitle_pages.clear();
2712 if (m_teletext_parser)
2714 m_teletext_parser->setPageAndMagazine(-1, -1);
2715 m_subtitle_pages.clear();
2718 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2722 PyObject *eDVBServicePlay::getCachedSubtitle()
2726 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2729 unsigned int data = (unsigned int)tmp;
2730 int pid = (data&0xFFFF0000)>>16;
2731 ePyObject tuple = PyTuple_New(4);
2732 eDVBServicePMTHandler::program program;
2733 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2734 if (!h.getProgramInfo(program))
2736 if (program.textPid==pid) // teletext
2737 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2739 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2740 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2741 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2742 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2750 PyObject *eDVBServicePlay::getSubtitleList()
2752 if (!m_teletext_parser)
2755 ePyObject l = PyList_New(0);
2756 std::set<int> added_ttx_pages;
2758 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2759 m_teletext_parser->m_found_subtitle_pages;
2761 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2762 eDVBServicePMTHandler::program program;
2763 if (h.getProgramInfo(program))
2764 eDebug("getting program info failed.");
2767 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2768 it != program.subtitleStreams.end(); ++it)
2770 switch(it->subtitling_type)
2772 case 0x01: // ebu teletext subtitles
2774 int page_number = it->teletext_page_number & 0xFF;
2775 int magazine_number = it->teletext_magazine_number & 7;
2776 int hash = magazine_number << 8 | page_number;
2777 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2779 ePyObject tuple = PyTuple_New(5);
2780 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2781 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2782 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2783 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2784 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2785 PyList_Append(l, tuple);
2787 added_ttx_pages.insert(hash);
2792 case 0x20 ... 0x23: // dvb subtitles
2794 ePyObject tuple = PyTuple_New(5);
2795 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2796 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2797 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2798 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2799 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2800 PyList_Insert(l, 0, tuple);
2808 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2809 it != subs.end(); ++it)
2811 int page_number = it->teletext_page_number & 0xFF;
2812 int magazine_number = it->teletext_magazine_number & 7;
2813 int hash = magazine_number << 8 | page_number;
2814 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2816 ePyObject tuple = PyTuple_New(5);
2817 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2818 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2819 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2820 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2821 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2822 PyList_Append(l, tuple);
2830 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2832 if (m_subtitle_widget)
2836 m_decoder->getPTS(0, pos);
2837 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2838 m_subtitle_pages.push_back(page);
2839 checkSubtitleTiming();
2843 void eDVBServicePlay::checkSubtitleTiming()
2845 eDebug("checkSubtitleTiming");
2846 if (!m_subtitle_widget)
2850 enum { TELETEXT, DVB } type;
2851 eDVBTeletextSubtitlePage page;
2852 eDVBSubtitlePage dvb_page;
2854 if (!m_subtitle_pages.empty())
2856 page = m_subtitle_pages.front();
2858 show_time = page.m_pts;
2860 else if (!m_dvb_subtitle_pages.empty())
2862 dvb_page = m_dvb_subtitle_pages.front();
2864 show_time = dvb_page.m_show_time;
2872 m_decoder->getPTS(0, pos);
2874 eDebug("%lld %lld", pos, show_time);
2875 int diff = show_time - pos;
2876 if (type == TELETEXT && !page.m_have_pts)
2878 eDebug("ttx subtitle page without pts... immediate show");
2883 eDebug("[late (%d ms)]", -diff / 90);
2886 if (abs(diff) > 1800000)
2888 eDebug("[invalid]... immediate show!");
2893 if (type == TELETEXT)
2895 eDebug("display teletext subtitle page %lld", show_time);
2896 m_subtitle_widget->setPage(page);
2897 m_subtitle_pages.pop_front();
2901 eDebug("display dvb subtitle Page %lld", show_time);
2902 m_subtitle_widget->setPage(dvb_page);
2903 m_dvb_subtitle_pages.pop_front();
2907 eDebug("start subtitle delay %d", diff / 90);
2908 m_subtitle_sync_timer->start(diff / 90, 1);
2914 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2916 if (m_subtitle_widget)
2920 m_decoder->getPTS(0, pos);
2921 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2922 m_dvb_subtitle_pages.push_back(p);
2923 checkSubtitleTiming();
2927 int eDVBServicePlay::getAC3Delay()
2930 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2932 return m_decoder->getAC3Delay();
2937 int eDVBServicePlay::getPCMDelay()
2940 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2942 return m_decoder->getPCMDelay();
2947 void eDVBServicePlay::setAC3Delay(int delay)
2950 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2952 std::string config_delay;
2953 int config_delay_int = 0;
2954 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2955 config_delay_int = atoi(config_delay.c_str());
2956 m_decoder->setAC3Delay(delay + config_delay_int);
2960 void eDVBServicePlay::setPCMDelay(int delay)
2963 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2965 std::string config_delay;
2966 int config_delay_int = 0;
2967 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2968 config_delay_int = atoi(config_delay.c_str());
2970 config_delay_int = 0;
2971 m_decoder->setPCMDelay(delay + config_delay_int);
2975 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2977 switch(event.type) {
2978 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2979 m_event((iPlayableService*)this, evVideoSizeChanged);
2981 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2982 m_event((iPlayableService*)this, evVideoFramerateChanged);
2984 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2985 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2992 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2998 PyObject *eDVBServicePlay::getStreamingData()
3000 eDVBServicePMTHandler::program program;
3001 if (m_service_handler.getProgramInfo(program))
3006 ePyObject r = program.createPythonObject();
3007 ePtr<iDVBDemux> demux;
3008 if (!m_service_handler.getDataDemux(demux))
3011 if (!demux->getCADemuxID(demux_id))
3012 PutToDict(r, "demux", demux_id);
3019 DEFINE_REF(eDVBServicePlay)
3021 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3025 case iServiceInformation::sTransponderData:
3026 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3030 return iStaticServiceInformation::getInfoObject(ref, w);
3033 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");