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()
1393 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1394 if (m_decoder->getVideoWidth() == -1)
1400 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1406 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1412 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1418 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1424 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1430 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1433 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1434 (m_timeshift_enabled || !m_is_pvr))
1436 if (!m_timeshift_enabled)
1438 /* query config path */
1440 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1441 eDebug("could not query ts path from config");
1445 /* we need enough diskspace */
1447 if (statfs(tspath.c_str(), &fs) < 0)
1449 eDebug("statfs failed!");
1453 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1455 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1465 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1476 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1482 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1488 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1494 RESULT eDVBServicePlay::getName(std::string &name)
1498 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1499 return i->getName(m_reference, name);
1501 else if (m_dvb_service)
1503 m_dvb_service->getName(m_reference, name);
1507 else if (!m_reference.name.empty())
1508 eStaticServiceDVBInformation().getName(m_reference, name);
1510 name = "DVB service";
1514 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1516 return m_event_handler.getEvent(evt, nownext);
1519 int eDVBServicePlay::getInfo(int w)
1521 eDVBServicePMTHandler::program program;
1524 return resIsPyObject;
1526 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1528 int no_program_info = 0;
1530 if (h.getProgramInfo(program))
1531 no_program_info = 1;
1537 return m_decoder->getVideoHeight();
1541 return m_decoder->getVideoWidth();
1545 return m_decoder->getVideoFrameRate();
1549 return m_decoder->getVideoProgressive();
1555 aspect = m_decoder->getVideoAspect();
1556 if (aspect == -1 && no_program_info)
1558 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1560 ePtr<eServiceEvent> evt;
1561 if (!m_event_handler.getEvent(evt, 0))
1563 ePtr<eComponentData> data;
1564 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1566 if ( data->getStreamContent() == 1 )
1568 switch(data->getComponentType())
1571 case 1: // 4:3 SD PAL
1573 case 3: // 16:9 SD PAL
1574 case 4: // > 16:9 PAL
1575 case 5: // 4:3 SD NTSC
1577 case 7: // 16:9 SD NTSC
1578 case 8: // > 16:9 NTSC
1581 case 9: // 4:3 HD PAL
1583 case 0xB: // 16:9 HD PAL
1584 case 0xC: // > 16:9 HD PAL
1585 case 0xD: // 4:3 HD NTSC
1587 case 0xF: // 16:9 HD NTSC
1588 case 0x10: // > 16:9 HD PAL
1589 return data->getComponentType();
1599 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1603 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1607 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1608 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1612 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1615 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1619 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1623 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1627 if (no_program_info) return -1; return program.pcrPid;
1628 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1629 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1630 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1631 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1632 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1633 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1634 case sProvider: if (!m_dvb_service) return -1; return -2;
1635 case sServiceref: return resIsString;
1636 case sDVBState: return m_tune_state;
1643 std::string eDVBServicePlay::getInfoString(int w)
1648 if (!m_dvb_service) return "";
1649 return m_dvb_service->m_provider_name;
1651 return m_reference.toString();
1655 return iServiceInformation::getInfoString(w);
1658 PyObject *eDVBServicePlay::getInfoObject(int w)
1663 return m_service_handler.getCaIds();
1664 case sTransponderData:
1665 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1669 return iServiceInformation::getInfoObject(w);
1672 int eDVBServicePlay::getNumberOfTracks()
1674 eDVBServicePMTHandler::program program;
1675 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1676 if (h.getProgramInfo(program))
1678 return program.audioStreams.size();
1681 int eDVBServicePlay::getCurrentTrack()
1683 eDVBServicePMTHandler::program program;
1684 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1685 if (h.getProgramInfo(program))
1688 int max = program.audioStreams.size();
1691 for (i = 0; i < max; ++i)
1692 if (program.audioStreams[i].pid == m_current_audio_pid)
1698 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1700 int ret = selectAudioStream(i);
1702 if (m_decoder->set())
1708 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1710 eDVBServicePMTHandler::program program;
1711 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1713 if (h.getProgramInfo(program))
1716 if (i >= program.audioStreams.size())
1719 info.m_pid = program.audioStreams[i].pid;
1721 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1722 info.m_description = "MPEG";
1723 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1724 info.m_description = "AC3";
1725 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1726 info.m_description = "AAC";
1727 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1728 info.m_description = "AAC-HE";
1729 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1730 info.m_description = "DTS";
1732 info.m_description = "???";
1734 if (program.audioStreams[i].component_tag != -1)
1736 ePtr<eServiceEvent> evt;
1737 if (!m_event_handler.getEvent(evt, 0))
1739 ePtr<eComponentData> data;
1740 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1741 info.m_language = data->getText();
1745 if (info.m_language.empty())
1746 info.m_language = program.audioStreams[i].language_code;
1751 int eDVBServicePlay::selectAudioStream(int i)
1753 eDVBServicePMTHandler::program program;
1754 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1755 pts_t position = -1;
1757 if (h.getProgramInfo(program))
1760 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1768 stream = program.defaultAudioStream;
1770 int apid = -1, apidtype = -1;
1772 if (((unsigned int)stream) < program.audioStreams.size())
1774 apid = program.audioStreams[stream].pid;
1775 apidtype = program.audioStreams[stream].type;
1778 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1779 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1781 m_current_audio_pid = apid;
1783 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1785 eDebug("set audio pid failed");
1790 eDebug("seekTo ret %d", seekTo(position));
1794 /* 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 */
1795 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1797 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1799 rdsPid = program.audioStreams[stream].rdsPid;
1800 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1803 ePtr<iDVBDemux> data_demux;
1804 if (!h.getDataDemux(data_demux))
1806 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1807 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1808 m_rds_decoder->start(rdsPid);
1813 /* store new pid as default only when:
1814 a.) we have an entry in the service db for the current service,
1815 b.) we are not playing back something,
1816 c.) we are not selecting the default entry. (we wouldn't change
1817 anything in the best case, or destroy the default setting in
1818 case the real default is not yet available.)
1820 if (m_dvb_service && ((i != -1)
1821 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1823 if (apidtype == eDVBAudio::aMPEG)
1825 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1826 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1828 else if (apidtype == eDVBAudio::aAC3)
1830 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1831 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1835 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1836 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1840 h.resetCachedProgram();
1845 int eDVBServicePlay::getCurrentChannel()
1847 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1850 RESULT eDVBServicePlay::selectChannel(int i)
1852 if (i < LEFT || i > RIGHT || i == STEREO)
1855 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1857 m_decoder->setAudioChannel(i);
1861 std::string eDVBServicePlay::getText(int x)
1867 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1869 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1874 void eDVBServicePlay::rdsDecoderEvent(int what)
1878 case eDVBRdsDecoder::RadioTextChanged:
1879 m_event((iPlayableService*)this, evUpdatedRadioText);
1881 case eDVBRdsDecoder::RtpTextChanged:
1882 m_event((iPlayableService*)this, evUpdatedRtpText);
1884 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1885 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1887 case eDVBRdsDecoder::RecvRassSlidePic:
1888 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1893 void eDVBServicePlay::showRassSlidePicture()
1899 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1900 if (rass_slide_pic.length())
1901 m_decoder->showSinglePic(rass_slide_pic.c_str());
1903 eDebug("empty filename for rass slide picture received!!");
1906 eDebug("no MPEG Decoder to show iframes avail");
1909 eDebug("showRassSlidePicture called.. but not decoder");
1912 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1918 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1919 if (rass_interactive_pic.length())
1920 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1922 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1925 eDebug("no MPEG Decoder to show iframes avail");
1928 eDebug("showRassInteractivePic called.. but not decoder");
1931 ePyObject eDVBServicePlay::getRassInteractiveMask()
1934 return m_rds_decoder->getRassPictureMask();
1938 int eDVBServiceBase::getFrontendInfo(int w)
1940 eUsePtr<iDVBChannel> channel;
1941 if(m_service_handler.getChannel(channel))
1943 ePtr<iDVBFrontend> fe;
1944 if(channel->getFrontend(fe))
1946 return fe->readFrontendData(w);
1949 PyObject *eDVBServiceBase::getFrontendData()
1951 ePyObject ret = PyDict_New();
1954 eUsePtr<iDVBChannel> channel;
1955 if(!m_service_handler.getChannel(channel))
1957 ePtr<iDVBFrontend> fe;
1958 if(!channel->getFrontend(fe))
1959 fe->getFrontendData(ret);
1967 PyObject *eDVBServiceBase::getFrontendStatus()
1969 ePyObject ret = PyDict_New();
1972 eUsePtr<iDVBChannel> channel;
1973 if(!m_service_handler.getChannel(channel))
1975 ePtr<iDVBFrontend> fe;
1976 if(!channel->getFrontend(fe))
1977 fe->getFrontendStatus(ret);
1985 PyObject *eDVBServiceBase::getTransponderData(bool original)
1987 ePyObject ret = PyDict_New();
1990 eUsePtr<iDVBChannel> channel;
1991 if(!m_service_handler.getChannel(channel))
1993 ePtr<iDVBFrontend> fe;
1994 if(!channel->getFrontend(fe))
1995 fe->getTransponderData(ret, original);
2003 PyObject *eDVBServiceBase::getAll(bool original)
2005 ePyObject ret = getTransponderData(original);
2008 eUsePtr<iDVBChannel> channel;
2009 if(!m_service_handler.getChannel(channel))
2011 ePtr<iDVBFrontend> fe;
2012 if(!channel->getFrontend(fe))
2014 fe->getFrontendData(ret);
2015 fe->getFrontendStatus(ret);
2022 int eDVBServicePlay::getNumberOfSubservices()
2024 ePtr<eServiceEvent> evt;
2025 if (!m_event_handler.getEvent(evt, 0))
2026 return evt->getNumOfLinkageServices();
2030 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2032 ePtr<eServiceEvent> evt;
2033 if (!m_event_handler.getEvent(evt, 0))
2035 if (!evt->getLinkageService(sub, m_reference, n))
2038 sub.type=eServiceReference::idInvalid;
2042 RESULT eDVBServicePlay::startTimeshift()
2044 ePtr<iDVBDemux> demux;
2046 eDebug("Start timeshift!");
2048 if (m_timeshift_enabled)
2051 /* start recording with the data demux. */
2052 if (m_service_handler.getDataDemux(demux))
2055 demux->createTSRecorder(m_record);
2060 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2061 eDebug("could not query ts path");
2064 tspath.append("/timeshift.XXXXXX");
2066 templ = new char[tspath.length() + 1];
2067 strcpy(templ, tspath.c_str());
2069 m_timeshift_fd = mkstemp(templ);
2070 m_timeshift_file = std::string(templ);
2072 eDebug("recording to %s", templ);
2076 if (m_timeshift_fd < 0)
2082 m_record->setTargetFD(m_timeshift_fd);
2084 m_timeshift_enabled = 1;
2086 updateTimeshiftPids();
2092 RESULT eDVBServicePlay::stopTimeshift()
2094 if (!m_timeshift_enabled)
2099 m_timeshift_enabled = 0;
2104 close(m_timeshift_fd);
2105 eDebug("remove timeshift file");
2106 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2111 int eDVBServicePlay::isTimeshiftActive()
2113 return m_timeshift_enabled && m_timeshift_active;
2116 RESULT eDVBServicePlay::activateTimeshift()
2118 if (!m_timeshift_enabled)
2121 if (!m_timeshift_active)
2123 switchToTimeshift();
2130 PyObject *eDVBServicePlay::getCutList()
2132 ePyObject list = PyList_New(0);
2134 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2136 ePyObject tuple = PyTuple_New(2);
2137 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2138 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2139 PyList_Append(list, tuple);
2146 void eDVBServicePlay::setCutList(ePyObject list)
2148 if (!PyList_Check(list))
2150 int size = PyList_Size(list);
2153 m_cue_entries.clear();
2155 for (i=0; i<size; ++i)
2157 ePyObject tuple = PyList_GET_ITEM(list, i);
2158 if (!PyTuple_Check(tuple))
2160 eDebug("non-tuple in cutlist");
2163 if (PyTuple_Size(tuple) != 2)
2165 eDebug("cutlist entries need to be a 2-tuple");
2168 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2169 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2171 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2174 pts_t pts = PyLong_AsLongLong(ppts);
2175 int type = PyInt_AsLong(ptype);
2176 m_cue_entries.insert(cueEntry(pts, type));
2177 eDebug("adding %08llx, %d", pts, type);
2179 m_cuesheet_changed = 1;
2181 cutlistToCuesheet();
2182 m_event((iPlayableService*)this, evCuesheetChanged);
2185 void eDVBServicePlay::setCutListEnable(int enable)
2187 m_cutlist_enabled = enable;
2188 cutlistToCuesheet();
2191 void eDVBServicePlay::updateTimeshiftPids()
2196 eDVBServicePMTHandler::program program;
2197 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2199 if (h.getProgramInfo(program))
2203 std::set<int> pids_to_record;
2204 pids_to_record.insert(0); // PAT
2205 if (program.pmtPid != -1)
2206 pids_to_record.insert(program.pmtPid); // PMT
2208 if (program.textPid != -1)
2209 pids_to_record.insert(program.textPid); // Videotext
2211 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2212 i(program.videoStreams.begin());
2213 i != program.videoStreams.end(); ++i)
2214 pids_to_record.insert(i->pid);
2216 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2217 i(program.audioStreams.begin());
2218 i != program.audioStreams.end(); ++i)
2219 pids_to_record.insert(i->pid);
2221 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2222 i(program.subtitleStreams.begin());
2223 i != program.subtitleStreams.end(); ++i)
2224 pids_to_record.insert(i->pid);
2226 std::set<int> new_pids, obsolete_pids;
2228 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2229 m_pids_active.begin(), m_pids_active.end(),
2230 std::inserter(new_pids, new_pids.begin()));
2232 std::set_difference(
2233 m_pids_active.begin(), m_pids_active.end(),
2234 pids_to_record.begin(), pids_to_record.end(),
2235 std::inserter(new_pids, new_pids.begin())
2238 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2239 m_record->addPID(*i);
2241 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2242 m_record->removePID(*i);
2246 void eDVBServicePlay::switchToLive()
2248 if (!m_timeshift_active)
2251 eDebug("SwitchToLive");
2256 m_teletext_parser = 0;
2258 m_subtitle_parser = 0;
2259 m_new_dvb_subtitle_page_connection = 0;
2260 m_new_subtitle_page_connection = 0;
2261 m_rds_decoder_event_connection = 0;
2262 m_video_event_connection = 0;
2263 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2265 /* free the timeshift service handler, we need the resources */
2266 m_service_handler_timeshift.free();
2267 m_timeshift_active = 0;
2268 m_timeshift_changed = 1;
2270 m_event((iPlayableService*)this, evSeekableStatusChanged);
2275 void eDVBServicePlay::switchToTimeshift()
2277 if (m_timeshift_active)
2282 m_teletext_parser = 0;
2284 m_subtitle_parser = 0;
2285 m_new_subtitle_page_connection = 0;
2286 m_new_dvb_subtitle_page_connection = 0;
2287 m_rds_decoder_event_connection = 0;
2288 m_video_event_connection = 0;
2290 m_timeshift_active = 1;
2291 m_timeshift_changed = 1;
2293 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2294 r.path = m_timeshift_file;
2296 m_cue = new eCueSheet();
2297 m_cue->seekTo(0, -1000);
2298 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2300 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2302 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2304 m_event((iPlayableService*)this, evSeekableStatusChanged);
2307 void eDVBServicePlay::updateDecoder()
2309 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2311 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2313 eDVBServicePMTHandler::program program;
2314 if (h.getProgramInfo(program))
2315 eDebug("getting program info failed.");
2318 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2319 if (!program.videoStreams.empty())
2321 eDebugNoNewLine(" (");
2322 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2323 i(program.videoStreams.begin());
2324 i != program.videoStreams.end(); ++i)
2331 if (i != program.videoStreams.begin())
2332 eDebugNoNewLine(", ");
2333 eDebugNoNewLine("%04x", i->pid);
2335 eDebugNoNewLine(")");
2337 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2338 if (!program.audioStreams.empty())
2340 eDebugNoNewLine(" (");
2341 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2342 i(program.audioStreams.begin());
2343 i != program.audioStreams.end(); ++i)
2345 if (i != program.audioStreams.begin())
2346 eDebugNoNewLine(", ");
2347 eDebugNoNewLine("%04x", i->pid);
2349 eDebugNoNewLine(")");
2351 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2352 pcrpid = program.pcrPid;
2353 eDebug(", and the text pid is %04x", program.textPid);
2354 tpid = program.textPid;
2359 h.getDecodeDemux(m_decode_demux);
2360 if (m_timeshift_changed)
2364 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2366 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2369 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2370 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2371 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2372 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2373 if (m_timeshift_changed)
2375 ePyObject subs = getCachedSubtitle();
2376 if (subs != Py_None)
2378 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2379 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2380 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2381 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2382 if (type == 0) // dvb
2383 m_subtitle_parser->start(pid, comp_page, anc_page);
2384 else if (type == 1) // ttx
2385 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2390 m_decoder->play(); /* pids will be set later */
2393 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2394 m_decoder->play(); /* pids will be set later. */
2397 m_timeshift_changed = 0;
2403 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2404 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2405 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2409 eServiceReferenceDVB ref;
2410 m_service_handler.getServiceReference(ref);
2411 eServiceReferenceDVB parent = ref.getParentServiceReference();
2416 ePtr<eDVBResourceManager> res_mgr;
2417 if (!eDVBResourceManager::getInstance(res_mgr))
2419 ePtr<iDVBChannelList> db;
2420 if (!res_mgr->getChannelList(db))
2422 ePtr<eDVBService> origService;
2423 if (!db->getService(parent, origService))
2425 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2426 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2433 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2434 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2436 m_decoder->setVideoPID(vpid, vpidtype);
2437 selectAudioStream();
2439 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2440 m_decoder->setSyncPCR(pcrpid);
2442 m_decoder->setSyncPCR(-1);
2446 m_decoder->setTextPID(tpid);
2447 m_teletext_parser->start(program.textPid);
2450 if (vpid > 0 && vpid < 0x2000)
2454 std::string radio_pic;
2455 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2456 m_decoder->setRadioPic(radio_pic);
2460 m_decoder->setAudioChannel(achannel);
2462 /* don't worry about non-existing services, nor pvr services */
2465 /* (audio pid will be set in selectAudioTrack */
2466 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2467 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2468 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2469 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2472 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2475 void eDVBServicePlay::loadCuesheet()
2477 std::string filename = m_reference.path + ".cuts";
2479 m_cue_entries.clear();
2481 FILE *f = fopen(filename.c_str(), "rb");
2485 eDebug("loading cuts..");
2488 unsigned long long where;
2491 if (!fread(&where, sizeof(where), 1, f))
2493 if (!fread(&what, sizeof(what), 1, f))
2496 #if BYTE_ORDER == LITTLE_ENDIAN
2497 where = bswap_64(where);
2504 m_cue_entries.insert(cueEntry(where, what));
2507 eDebug("%d entries", m_cue_entries.size());
2509 eDebug("cutfile not found!");
2511 m_cuesheet_changed = 0;
2512 cutlistToCuesheet();
2513 m_event((iPlayableService*)this, evCuesheetChanged);
2516 void eDVBServicePlay::saveCuesheet()
2518 std::string filename = m_reference.path + ".cuts";
2520 FILE *f = fopen(filename.c_str(), "wb");
2524 unsigned long long where;
2527 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2529 #if BYTE_ORDER == BIG_ENDIAN
2532 where = bswap_64(i->where);
2534 what = htonl(i->what);
2535 fwrite(&where, sizeof(where), 1, f);
2536 fwrite(&what, sizeof(what), 1, f);
2542 m_cuesheet_changed = 0;
2545 void eDVBServicePlay::cutlistToCuesheet()
2549 eDebug("no cue sheet");
2554 if (!m_cutlist_enabled)
2556 m_cue->commitSpans();
2557 eDebug("cutlists were disabled");
2561 pts_t in = 0, out = 0, length = 0;
2565 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2567 int have_any_span = 0;
2571 if (i == m_cue_entries.end())
2577 if (i->what == 0) /* in */
2581 } else if (i->what == 1) /* out */
2583 else /* mark (2) or last play position (3) */
2602 m_cue->addSourceSpan(in, out);
2607 if (i == m_cue_entries.end())
2610 m_cue->commitSpans();
2613 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2615 if (m_subtitle_widget)
2616 disableSubtitles(parent);
2619 int tuplesize = PyTuple_Size(tuple);
2622 if (!PyTuple_Check(tuple))
2628 entry = PyTuple_GET_ITEM(tuple, 0);
2630 if (!PyInt_Check(entry))
2633 type = PyInt_AsLong(entry);
2635 if (type == 1) // teletext subtitles
2637 int page, magazine, pid;
2641 if (!m_teletext_parser)
2643 eDebug("enable teletext subtitles.. no parser !!!");
2647 entry = PyTuple_GET_ITEM(tuple, 1);
2648 if (!PyInt_Check(entry))
2650 pid = PyInt_AsLong(entry);
2652 entry = PyTuple_GET_ITEM(tuple, 2);
2653 if (!PyInt_Check(entry))
2655 page = PyInt_AsLong(entry);
2657 entry = PyTuple_GET_ITEM(tuple, 3);
2658 if (!PyInt_Check(entry))
2660 magazine = PyInt_AsLong(entry);
2662 m_subtitle_widget = new eSubtitleWidget(parent);
2663 m_subtitle_widget->resize(parent->size()); /* full size */
2664 m_teletext_parser->setPageAndMagazine(page, magazine);
2666 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2670 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2671 if (!m_subtitle_parser)
2673 eDebug("enable dvb subtitles.. no parser !!!");
2679 entry = PyTuple_GET_ITEM(tuple, 1);
2680 if (!PyInt_Check(entry))
2682 pid = PyInt_AsLong(entry);
2684 entry = PyTuple_GET_ITEM(tuple, 2);
2685 if (!PyInt_Check(entry))
2687 composition_page_id = PyInt_AsLong(entry);
2689 entry = PyTuple_GET_ITEM(tuple, 3);
2690 if (!PyInt_Check(entry))
2692 ancillary_page_id = PyInt_AsLong(entry);
2694 m_subtitle_widget = new eSubtitleWidget(parent);
2695 m_subtitle_widget->resize(parent->size()); /* full size */
2696 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2698 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2704 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2705 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2706 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2710 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2712 delete m_subtitle_widget;
2713 m_subtitle_widget = 0;
2714 if (m_subtitle_parser)
2716 m_subtitle_parser->stop();
2717 m_dvb_subtitle_pages.clear();
2719 if (m_teletext_parser)
2721 m_teletext_parser->setPageAndMagazine(-1, -1);
2722 m_subtitle_pages.clear();
2725 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2729 PyObject *eDVBServicePlay::getCachedSubtitle()
2733 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2736 unsigned int data = (unsigned int)tmp;
2737 int pid = (data&0xFFFF0000)>>16;
2738 ePyObject tuple = PyTuple_New(4);
2739 eDVBServicePMTHandler::program program;
2740 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2741 if (!h.getProgramInfo(program))
2743 if (program.textPid==pid) // teletext
2744 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2746 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2747 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2748 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2749 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2757 PyObject *eDVBServicePlay::getSubtitleList()
2759 if (!m_teletext_parser)
2762 ePyObject l = PyList_New(0);
2763 std::set<int> added_ttx_pages;
2765 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2766 m_teletext_parser->m_found_subtitle_pages;
2768 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2769 eDVBServicePMTHandler::program program;
2770 if (h.getProgramInfo(program))
2771 eDebug("getting program info failed.");
2774 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2775 it != program.subtitleStreams.end(); ++it)
2777 switch(it->subtitling_type)
2779 case 0x01: // ebu teletext subtitles
2781 int page_number = it->teletext_page_number & 0xFF;
2782 int magazine_number = it->teletext_magazine_number & 7;
2783 int hash = magazine_number << 8 | page_number;
2784 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2786 ePyObject tuple = PyTuple_New(5);
2787 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2788 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2789 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2790 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2791 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2792 PyList_Append(l, tuple);
2794 added_ttx_pages.insert(hash);
2799 case 0x20 ... 0x23: // dvb subtitles
2801 ePyObject tuple = PyTuple_New(5);
2802 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2803 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2804 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2805 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2806 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2807 PyList_Insert(l, 0, tuple);
2815 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2816 it != subs.end(); ++it)
2818 int page_number = it->teletext_page_number & 0xFF;
2819 int magazine_number = it->teletext_magazine_number & 7;
2820 int hash = magazine_number << 8 | page_number;
2821 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2823 ePyObject tuple = PyTuple_New(5);
2824 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2825 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2826 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2827 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2828 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2829 PyList_Append(l, tuple);
2837 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2839 if (m_subtitle_widget)
2843 m_decoder->getPTS(0, pos);
2844 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2845 m_subtitle_pages.push_back(page);
2846 checkSubtitleTiming();
2850 void eDVBServicePlay::checkSubtitleTiming()
2852 eDebug("checkSubtitleTiming");
2853 if (!m_subtitle_widget)
2857 enum { TELETEXT, DVB } type;
2858 eDVBTeletextSubtitlePage page;
2859 eDVBSubtitlePage dvb_page;
2861 if (!m_subtitle_pages.empty())
2863 page = m_subtitle_pages.front();
2865 show_time = page.m_pts;
2867 else if (!m_dvb_subtitle_pages.empty())
2869 dvb_page = m_dvb_subtitle_pages.front();
2871 show_time = dvb_page.m_show_time;
2879 m_decoder->getPTS(0, pos);
2881 eDebug("%lld %lld", pos, show_time);
2882 int diff = show_time - pos;
2883 if (type == TELETEXT && !page.m_have_pts)
2885 eDebug("ttx subtitle page without pts... immediate show");
2890 eDebug("[late (%d ms)]", -diff / 90);
2893 if (abs(diff) > 1800000)
2895 eDebug("[invalid]... immediate show!");
2900 if (type == TELETEXT)
2902 eDebug("display teletext subtitle page %lld", show_time);
2903 m_subtitle_widget->setPage(page);
2904 m_subtitle_pages.pop_front();
2908 eDebug("display dvb subtitle Page %lld", show_time);
2909 m_subtitle_widget->setPage(dvb_page);
2910 m_dvb_subtitle_pages.pop_front();
2914 eDebug("start subtitle delay %d", diff / 90);
2915 m_subtitle_sync_timer->start(diff / 90, 1);
2921 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2923 if (m_subtitle_widget)
2927 m_decoder->getPTS(0, pos);
2928 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2929 m_dvb_subtitle_pages.push_back(p);
2930 checkSubtitleTiming();
2934 int eDVBServicePlay::getAC3Delay()
2937 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2939 return m_decoder->getAC3Delay();
2944 int eDVBServicePlay::getPCMDelay()
2947 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2949 return m_decoder->getPCMDelay();
2954 void eDVBServicePlay::setAC3Delay(int delay)
2957 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2959 std::string config_delay;
2960 int config_delay_int = 0;
2961 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2962 config_delay_int = atoi(config_delay.c_str());
2963 m_decoder->setAC3Delay(delay + config_delay_int);
2967 void eDVBServicePlay::setPCMDelay(int delay)
2970 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2972 std::string config_delay;
2973 int config_delay_int = 0;
2974 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2975 config_delay_int = atoi(config_delay.c_str());
2977 config_delay_int = 0;
2978 m_decoder->setPCMDelay(delay + config_delay_int);
2982 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2984 switch(event.type) {
2985 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2986 m_event((iPlayableService*)this, evVideoSizeChanged);
2988 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2989 m_event((iPlayableService*)this, evVideoFramerateChanged);
2991 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2992 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2999 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3005 PyObject *eDVBServicePlay::getStreamingData()
3007 eDVBServicePMTHandler::program program;
3008 if (m_service_handler.getProgramInfo(program))
3013 ePyObject r = program.createPythonObject();
3014 ePtr<iDVBDemux> demux;
3015 if (!m_service_handler.getDataDemux(demux))
3018 if (!demux->getCADemuxID(demux_id))
3019 PutToDict(r, "demux", demux_id);
3026 DEFINE_REF(eDVBServicePlay)
3028 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3032 case iServiceInformation::sTransponderData:
3033 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3037 return iStaticServiceInformation::getInfoObject(ref, w);
3040 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");