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::eventEOF:
1033 m_event((iPlayableService*)this, evEOF);
1035 case eDVBServicePMTHandler::eventSOF:
1036 m_event((iPlayableService*)this, evSOF);
1041 void eDVBServicePlay::serviceEventTimeshift(int event)
1045 case eDVBServicePMTHandler::eventNewProgramInfo:
1046 if (m_timeshift_active)
1049 case eDVBServicePMTHandler::eventSOF:
1050 m_event((iPlayableService*)this, evSOF);
1052 case eDVBServicePMTHandler::eventEOF:
1053 if ((!m_is_paused) && (m_skipmode >= 0))
1055 eDebug("timeshift EOF, so let's go live");
1062 RESULT eDVBServicePlay::start()
1064 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1066 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1067 two (one for decoding, one for data source), as we must be prepared
1068 to start recording from the data demux. */
1071 eDVBMetaParser meta;
1072 if (!meta.parseFile(m_reference.path))
1074 service = meta.m_ref;
1075 service.path = m_reference.path;
1077 m_cue = new eCueSheet();
1080 m_event(this, evStart);
1082 m_first_program_info = 1;
1083 m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1087 /* inject EIT if there is a stored one */
1088 std::string filename = service.path;
1089 filename.erase(filename.length()-2, 2);
1091 ePtr<eServiceEvent> event = new eServiceEvent;
1092 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1094 ePtr<eServiceEvent> empty;
1095 m_event_handler.inject(event, 0);
1096 m_event_handler.inject(empty, 1);
1099 m_event(this, evStart);
1104 RESULT eDVBServicePlay::stop()
1106 /* add bookmark for last play position */
1109 pts_t play_position, length;
1110 if (!getPlayPosition(play_position))
1112 /* remove last position */
1113 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1115 if (i->what == 3) /* current play position */
1117 m_cue_entries.erase(i);
1118 i = m_cue_entries.begin();
1124 if (getLength(length))
1129 int perc = play_position * 100LL / length;
1131 /* only store last play position when between 1% and 99% */
1132 if ((1 < perc) && (perc < 99))
1133 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1135 m_cuesheet_changed = 1;
1139 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1141 m_service_handler_timeshift.free();
1142 m_service_handler.free();
1144 if (m_is_pvr && m_cuesheet_changed)
1147 /* save cuesheet only when main file is accessible. */
1148 if (!::stat(m_reference.path.c_str(), &s))
1151 m_event((iPlayableService*)this, evStopped);
1155 RESULT eDVBServicePlay::setTarget(int target)
1157 m_is_primary = !target;
1161 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1163 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1167 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1169 /* note: we check for timeshift to be enabled,
1170 not neccessary active. if you pause when timeshift
1171 is not active, you should activate it when unpausing */
1172 if ((!m_is_pvr) && (!m_timeshift_enabled))
1182 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1184 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1185 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1186 setFastForward_internal(0);
1189 m_slowmotion = ratio;
1190 return m_decoder->setSlowMotion(ratio);
1196 RESULT eDVBServicePlay::setFastForward(int ratio)
1198 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1200 return setFastForward_internal(ratio);
1203 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1205 int skipmode, ffratio, ret = 0;
1212 } else if (ratio > 0)
1220 } else // if (ratio < 0)
1226 if (m_skipmode != skipmode)
1228 eDebug("setting cue skipmode to %d", skipmode);
1230 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1233 m_skipmode = skipmode;
1236 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1238 m_fastforward = ffratio;
1244 ; /* return m_decoder->play(); is done in caller*/
1245 else if (ffratio != 1)
1246 ret = m_decoder->setFastForward(ffratio);
1248 ret = m_decoder->setTrickmode();
1251 eDebug("final seek after trickplay ret %d", seekTo(pos));
1256 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1258 if (m_is_pvr || m_timeshift_enabled)
1268 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1269 RESULT eDVBServicePlay::getLength(pts_t &len)
1271 ePtr<iDVBPVRChannel> pvr_channel;
1273 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1276 return pvr_channel->getLength(len);
1279 RESULT eDVBServicePlay::pause()
1281 eDebug("eDVBServicePlay::pause");
1282 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1287 return m_decoder->pause();
1292 RESULT eDVBServicePlay::unpause()
1294 eDebug("eDVBServicePlay::unpause");
1295 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1300 return m_decoder->play();
1305 RESULT eDVBServicePlay::seekTo(pts_t to)
1307 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1309 if (!m_decode_demux)
1312 ePtr<iDVBPVRChannel> pvr_channel;
1314 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1320 m_cue->seekTo(0, to);
1321 m_dvb_subtitle_pages.clear();
1322 m_subtitle_pages.clear();
1327 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1329 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1331 if (!m_decode_demux)
1334 ePtr<iDVBPVRChannel> pvr_channel;
1336 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1341 /* HACK until we have skip-AP api */
1342 if ((to > 0) && (to < 100))
1350 m_cue->seekTo(mode, to);
1351 m_dvb_subtitle_pages.clear();
1352 m_subtitle_pages.clear();
1356 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1358 ePtr<iDVBPVRChannel> pvr_channel;
1360 if (!m_decode_demux)
1363 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1368 /* if there is a decoder, use audio or video PTS */
1371 r = m_decoder->getPTS(0, pos);
1377 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1380 RESULT eDVBServicePlay::setTrickmode(int trick)
1382 /* currently unimplemented */
1386 RESULT eDVBServicePlay::isCurrentlySeekable()
1388 return m_is_pvr || m_timeshift_active ? 3 : 0; // fast forward/backward possible and seeking possible
1391 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1397 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1403 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1409 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1415 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1421 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1424 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1425 (m_timeshift_enabled || !m_is_pvr))
1427 if (!m_timeshift_enabled)
1429 /* query config path */
1431 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1432 eDebug("could not query ts path from config");
1436 /* we need enough diskspace */
1438 if (statfs(tspath.c_str(), &fs) < 0)
1440 eDebug("statfs failed!");
1444 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1446 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1456 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1467 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1473 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1479 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1485 RESULT eDVBServicePlay::getName(std::string &name)
1489 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1490 return i->getName(m_reference, name);
1492 else if (m_dvb_service)
1494 m_dvb_service->getName(m_reference, name);
1498 else if (!m_reference.name.empty())
1499 eStaticServiceDVBInformation().getName(m_reference, name);
1501 name = "DVB service";
1505 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1507 return m_event_handler.getEvent(evt, nownext);
1510 int eDVBServicePlay::getInfo(int w)
1512 eDVBServicePMTHandler::program program;
1515 return resIsPyObject;
1517 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1519 int no_program_info = 0;
1521 if (h.getProgramInfo(program))
1522 no_program_info = 1;
1528 return m_decoder->getVideoHeight();
1532 return m_decoder->getVideoWidth();
1536 return m_decoder->getVideoFrameRate();
1540 return m_decoder->getVideoProgressive();
1546 aspect = m_decoder->getVideoAspect();
1547 if (aspect == -1 && no_program_info)
1549 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1551 ePtr<eServiceEvent> evt;
1552 if (!m_event_handler.getEvent(evt, 0))
1554 ePtr<eComponentData> data;
1555 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1557 if ( data->getStreamContent() == 1 )
1559 switch(data->getComponentType())
1562 case 1: // 4:3 SD PAL
1564 case 3: // 16:9 SD PAL
1565 case 4: // > 16:9 PAL
1566 case 5: // 4:3 SD NTSC
1568 case 7: // 16:9 SD NTSC
1569 case 8: // > 16:9 NTSC
1572 case 9: // 4:3 HD PAL
1574 case 0xB: // 16:9 HD PAL
1575 case 0xC: // > 16:9 HD PAL
1576 case 0xD: // 4:3 HD NTSC
1578 case 0xF: // 16:9 HD NTSC
1579 case 0x10: // > 16:9 HD PAL
1580 return data->getComponentType();
1590 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1594 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1598 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1599 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1603 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1606 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1610 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1614 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1618 if (no_program_info) return -1; return program.pcrPid;
1619 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1620 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1621 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1622 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1623 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1624 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1625 case sProvider: if (!m_dvb_service) return -1; return -2;
1626 case sServiceref: return resIsString;
1627 case sDVBState: return m_tune_state;
1634 std::string eDVBServicePlay::getInfoString(int w)
1639 if (!m_dvb_service) return "";
1640 return m_dvb_service->m_provider_name;
1642 return m_reference.toString();
1646 return iServiceInformation::getInfoString(w);
1649 PyObject *eDVBServicePlay::getInfoObject(int w)
1654 return m_service_handler.getCaIds();
1655 case sTransponderData:
1656 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1660 return iServiceInformation::getInfoObject(w);
1663 int eDVBServicePlay::getNumberOfTracks()
1665 eDVBServicePMTHandler::program program;
1666 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1667 if (h.getProgramInfo(program))
1669 return program.audioStreams.size();
1672 int eDVBServicePlay::getCurrentTrack()
1674 eDVBServicePMTHandler::program program;
1675 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1676 if (h.getProgramInfo(program))
1679 int max = program.audioStreams.size();
1682 for (i = 0; i < max; ++i)
1683 if (program.audioStreams[i].pid == m_current_audio_pid)
1689 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1691 int ret = selectAudioStream(i);
1693 if (m_decoder->set())
1699 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1701 eDVBServicePMTHandler::program program;
1702 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1704 if (h.getProgramInfo(program))
1707 if (i >= program.audioStreams.size())
1710 info.m_pid = program.audioStreams[i].pid;
1712 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1713 info.m_description = "MPEG";
1714 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1715 info.m_description = "AC3";
1716 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1717 info.m_description = "AAC";
1718 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1719 info.m_description = "AAC-HE";
1720 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1721 info.m_description = "DTS";
1723 info.m_description = "???";
1725 if (program.audioStreams[i].component_tag != -1)
1727 ePtr<eServiceEvent> evt;
1728 if (!m_event_handler.getEvent(evt, 0))
1730 ePtr<eComponentData> data;
1731 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1732 info.m_language = data->getText();
1736 if (info.m_language.empty())
1737 info.m_language = program.audioStreams[i].language_code;
1742 int eDVBServicePlay::selectAudioStream(int i)
1744 eDVBServicePMTHandler::program program;
1745 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1746 pts_t position = -1;
1748 if (h.getProgramInfo(program))
1751 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1759 stream = program.defaultAudioStream;
1761 int apid = -1, apidtype = -1;
1763 if (((unsigned int)stream) < program.audioStreams.size())
1765 apid = program.audioStreams[stream].pid;
1766 apidtype = program.audioStreams[stream].type;
1769 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1770 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1772 m_current_audio_pid = apid;
1774 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1776 eDebug("set audio pid failed");
1781 eDebug("seekTo ret %d", seekTo(position));
1785 /* 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 */
1786 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1788 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1790 rdsPid = program.audioStreams[stream].rdsPid;
1791 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1794 ePtr<iDVBDemux> data_demux;
1795 if (!h.getDataDemux(data_demux))
1797 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1798 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1799 m_rds_decoder->start(rdsPid);
1804 /* store new pid as default only when:
1805 a.) we have an entry in the service db for the current service,
1806 b.) we are not playing back something,
1807 c.) we are not selecting the default entry. (we wouldn't change
1808 anything in the best case, or destroy the default setting in
1809 case the real default is not yet available.)
1811 if (m_dvb_service && ((i != -1)
1812 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1814 if (apidtype == eDVBAudio::aMPEG)
1816 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1817 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1819 else if (apidtype == eDVBAudio::aAC3)
1821 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1822 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1826 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1827 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1831 h.resetCachedProgram();
1836 int eDVBServicePlay::getCurrentChannel()
1838 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1841 RESULT eDVBServicePlay::selectChannel(int i)
1843 if (i < LEFT || i > RIGHT || i == STEREO)
1846 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1848 m_decoder->setAudioChannel(i);
1852 std::string eDVBServicePlay::getText(int x)
1858 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1860 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1865 void eDVBServicePlay::rdsDecoderEvent(int what)
1869 case eDVBRdsDecoder::RadioTextChanged:
1870 m_event((iPlayableService*)this, evUpdatedRadioText);
1872 case eDVBRdsDecoder::RtpTextChanged:
1873 m_event((iPlayableService*)this, evUpdatedRtpText);
1875 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1876 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1878 case eDVBRdsDecoder::RecvRassSlidePic:
1879 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1884 void eDVBServicePlay::showRassSlidePicture()
1890 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1891 if (rass_slide_pic.length())
1892 m_decoder->showSinglePic(rass_slide_pic.c_str());
1894 eDebug("empty filename for rass slide picture received!!");
1897 eDebug("no MPEG Decoder to show iframes avail");
1900 eDebug("showRassSlidePicture called.. but not decoder");
1903 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1909 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1910 if (rass_interactive_pic.length())
1911 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1913 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1916 eDebug("no MPEG Decoder to show iframes avail");
1919 eDebug("showRassInteractivePic called.. but not decoder");
1922 ePyObject eDVBServicePlay::getRassInteractiveMask()
1925 return m_rds_decoder->getRassPictureMask();
1929 int eDVBServiceBase::getFrontendInfo(int w)
1931 eUsePtr<iDVBChannel> channel;
1932 if(m_service_handler.getChannel(channel))
1934 ePtr<iDVBFrontend> fe;
1935 if(channel->getFrontend(fe))
1937 return fe->readFrontendData(w);
1940 PyObject *eDVBServiceBase::getFrontendData()
1942 ePyObject ret = PyDict_New();
1945 eUsePtr<iDVBChannel> channel;
1946 if(!m_service_handler.getChannel(channel))
1948 ePtr<iDVBFrontend> fe;
1949 if(!channel->getFrontend(fe))
1950 fe->getFrontendData(ret);
1958 PyObject *eDVBServiceBase::getFrontendStatus()
1960 ePyObject ret = PyDict_New();
1963 eUsePtr<iDVBChannel> channel;
1964 if(!m_service_handler.getChannel(channel))
1966 ePtr<iDVBFrontend> fe;
1967 if(!channel->getFrontend(fe))
1968 fe->getFrontendStatus(ret);
1976 PyObject *eDVBServiceBase::getTransponderData(bool original)
1978 ePyObject ret = PyDict_New();
1981 eUsePtr<iDVBChannel> channel;
1982 if(!m_service_handler.getChannel(channel))
1984 ePtr<iDVBFrontend> fe;
1985 if(!channel->getFrontend(fe))
1986 fe->getTransponderData(ret, original);
1994 PyObject *eDVBServiceBase::getAll(bool original)
1996 ePyObject ret = getTransponderData(original);
1999 eUsePtr<iDVBChannel> channel;
2000 if(!m_service_handler.getChannel(channel))
2002 ePtr<iDVBFrontend> fe;
2003 if(!channel->getFrontend(fe))
2005 fe->getFrontendData(ret);
2006 fe->getFrontendStatus(ret);
2013 int eDVBServicePlay::getNumberOfSubservices()
2015 ePtr<eServiceEvent> evt;
2016 if (!m_event_handler.getEvent(evt, 0))
2017 return evt->getNumOfLinkageServices();
2021 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2023 ePtr<eServiceEvent> evt;
2024 if (!m_event_handler.getEvent(evt, 0))
2026 if (!evt->getLinkageService(sub, m_reference, n))
2029 sub.type=eServiceReference::idInvalid;
2033 RESULT eDVBServicePlay::startTimeshift()
2035 ePtr<iDVBDemux> demux;
2037 eDebug("Start timeshift!");
2039 if (m_timeshift_enabled)
2042 /* start recording with the data demux. */
2043 if (m_service_handler.getDataDemux(demux))
2046 demux->createTSRecorder(m_record);
2051 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2052 eDebug("could not query ts path");
2055 tspath.append("/timeshift.XXXXXX");
2057 templ = new char[tspath.length() + 1];
2058 strcpy(templ, tspath.c_str());
2060 m_timeshift_fd = mkstemp(templ);
2061 m_timeshift_file = std::string(templ);
2063 eDebug("recording to %s", templ);
2067 if (m_timeshift_fd < 0)
2073 m_record->setTargetFD(m_timeshift_fd);
2075 m_timeshift_enabled = 1;
2077 updateTimeshiftPids();
2083 RESULT eDVBServicePlay::stopTimeshift()
2085 if (!m_timeshift_enabled)
2090 m_timeshift_enabled = 0;
2095 close(m_timeshift_fd);
2096 eDebug("remove timeshift file");
2097 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2102 int eDVBServicePlay::isTimeshiftActive()
2104 return m_timeshift_enabled && m_timeshift_active;
2107 RESULT eDVBServicePlay::activateTimeshift()
2109 if (!m_timeshift_enabled)
2112 if (!m_timeshift_active)
2114 switchToTimeshift();
2121 PyObject *eDVBServicePlay::getCutList()
2123 ePyObject list = PyList_New(0);
2125 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2127 ePyObject tuple = PyTuple_New(2);
2128 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2129 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2130 PyList_Append(list, tuple);
2137 void eDVBServicePlay::setCutList(ePyObject list)
2139 if (!PyList_Check(list))
2141 int size = PyList_Size(list);
2144 m_cue_entries.clear();
2146 for (i=0; i<size; ++i)
2148 ePyObject tuple = PyList_GET_ITEM(list, i);
2149 if (!PyTuple_Check(tuple))
2151 eDebug("non-tuple in cutlist");
2154 if (PyTuple_Size(tuple) != 2)
2156 eDebug("cutlist entries need to be a 2-tuple");
2159 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2160 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2162 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2165 pts_t pts = PyLong_AsLongLong(ppts);
2166 int type = PyInt_AsLong(ptype);
2167 m_cue_entries.insert(cueEntry(pts, type));
2168 eDebug("adding %08llx, %d", pts, type);
2170 m_cuesheet_changed = 1;
2172 cutlistToCuesheet();
2173 m_event((iPlayableService*)this, evCuesheetChanged);
2176 void eDVBServicePlay::setCutListEnable(int enable)
2178 m_cutlist_enabled = enable;
2179 cutlistToCuesheet();
2182 void eDVBServicePlay::updateTimeshiftPids()
2187 eDVBServicePMTHandler::program program;
2188 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2190 if (h.getProgramInfo(program))
2194 std::set<int> pids_to_record;
2195 pids_to_record.insert(0); // PAT
2196 if (program.pmtPid != -1)
2197 pids_to_record.insert(program.pmtPid); // PMT
2199 if (program.textPid != -1)
2200 pids_to_record.insert(program.textPid); // Videotext
2202 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2203 i(program.videoStreams.begin());
2204 i != program.videoStreams.end(); ++i)
2205 pids_to_record.insert(i->pid);
2207 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2208 i(program.audioStreams.begin());
2209 i != program.audioStreams.end(); ++i)
2210 pids_to_record.insert(i->pid);
2212 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2213 i(program.subtitleStreams.begin());
2214 i != program.subtitleStreams.end(); ++i)
2215 pids_to_record.insert(i->pid);
2217 std::set<int> new_pids, obsolete_pids;
2219 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2220 m_pids_active.begin(), m_pids_active.end(),
2221 std::inserter(new_pids, new_pids.begin()));
2223 std::set_difference(
2224 m_pids_active.begin(), m_pids_active.end(),
2225 pids_to_record.begin(), pids_to_record.end(),
2226 std::inserter(new_pids, new_pids.begin())
2229 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2230 m_record->addPID(*i);
2232 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2233 m_record->removePID(*i);
2237 void eDVBServicePlay::switchToLive()
2239 if (!m_timeshift_active)
2242 eDebug("SwitchToLive");
2247 m_teletext_parser = 0;
2249 m_subtitle_parser = 0;
2250 m_new_dvb_subtitle_page_connection = 0;
2251 m_new_subtitle_page_connection = 0;
2252 m_rds_decoder_event_connection = 0;
2253 m_video_event_connection = 0;
2254 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2256 /* free the timeshift service handler, we need the resources */
2257 m_service_handler_timeshift.free();
2258 m_timeshift_active = 0;
2259 m_timeshift_changed = 1;
2261 m_event((iPlayableService*)this, evSeekableStatusChanged);
2266 void eDVBServicePlay::switchToTimeshift()
2268 if (m_timeshift_active)
2273 m_teletext_parser = 0;
2275 m_subtitle_parser = 0;
2276 m_new_subtitle_page_connection = 0;
2277 m_new_dvb_subtitle_page_connection = 0;
2278 m_rds_decoder_event_connection = 0;
2279 m_video_event_connection = 0;
2281 m_timeshift_active = 1;
2282 m_timeshift_changed = 1;
2284 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2285 r.path = m_timeshift_file;
2287 m_cue = new eCueSheet();
2288 m_cue->seekTo(0, -1000);
2289 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2291 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2293 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2295 m_event((iPlayableService*)this, evSeekableStatusChanged);
2298 void eDVBServicePlay::updateDecoder()
2300 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2302 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2304 eDVBServicePMTHandler::program program;
2305 if (h.getProgramInfo(program))
2306 eDebug("getting program info failed.");
2309 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2310 if (!program.videoStreams.empty())
2312 eDebugNoNewLine(" (");
2313 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2314 i(program.videoStreams.begin());
2315 i != program.videoStreams.end(); ++i)
2322 if (i != program.videoStreams.begin())
2323 eDebugNoNewLine(", ");
2324 eDebugNoNewLine("%04x", i->pid);
2326 eDebugNoNewLine(")");
2328 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2329 if (!program.audioStreams.empty())
2331 eDebugNoNewLine(" (");
2332 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2333 i(program.audioStreams.begin());
2334 i != program.audioStreams.end(); ++i)
2336 if (i != program.audioStreams.begin())
2337 eDebugNoNewLine(", ");
2338 eDebugNoNewLine("%04x", i->pid);
2340 eDebugNoNewLine(")");
2342 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2343 pcrpid = program.pcrPid;
2344 eDebug(", and the text pid is %04x", program.textPid);
2345 tpid = program.textPid;
2350 h.getDecodeDemux(m_decode_demux);
2351 if (m_timeshift_changed)
2355 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2357 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2360 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2361 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2362 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2363 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2364 if (m_timeshift_changed)
2366 ePyObject subs = getCachedSubtitle();
2367 if (subs != Py_None)
2369 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2370 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2371 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2372 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2373 if (type == 0) // dvb
2374 m_subtitle_parser->start(pid, comp_page, anc_page);
2375 else if (type == 1) // ttx
2376 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2381 m_decoder->play(); /* pids will be set later */
2384 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2385 m_decoder->play(); /* pids will be set later. */
2388 m_timeshift_changed = 0;
2394 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2395 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2396 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2400 eServiceReferenceDVB ref;
2401 m_service_handler.getServiceReference(ref);
2402 eServiceReferenceDVB parent = ref.getParentServiceReference();
2407 ePtr<eDVBResourceManager> res_mgr;
2408 if (!eDVBResourceManager::getInstance(res_mgr))
2410 ePtr<iDVBChannelList> db;
2411 if (!res_mgr->getChannelList(db))
2413 ePtr<eDVBService> origService;
2414 if (!db->getService(parent, origService))
2416 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2417 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2424 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2425 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2427 m_decoder->setVideoPID(vpid, vpidtype);
2428 selectAudioStream();
2430 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2431 m_decoder->setSyncPCR(pcrpid);
2433 m_decoder->setSyncPCR(-1);
2437 m_decoder->setTextPID(tpid);
2438 m_teletext_parser->start(program.textPid);
2441 if (vpid > 0 && vpid < 0x2000)
2445 std::string radio_pic;
2446 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2447 m_decoder->setRadioPic(radio_pic);
2451 m_decoder->setAudioChannel(achannel);
2453 /* don't worry about non-existing services, nor pvr services */
2456 /* (audio pid will be set in selectAudioTrack */
2457 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2458 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2459 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2460 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2463 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2466 void eDVBServicePlay::loadCuesheet()
2468 std::string filename = m_reference.path + ".cuts";
2470 m_cue_entries.clear();
2472 FILE *f = fopen(filename.c_str(), "rb");
2476 eDebug("loading cuts..");
2479 unsigned long long where;
2482 if (!fread(&where, sizeof(where), 1, f))
2484 if (!fread(&what, sizeof(what), 1, f))
2487 #if BYTE_ORDER == LITTLE_ENDIAN
2488 where = bswap_64(where);
2495 m_cue_entries.insert(cueEntry(where, what));
2498 eDebug("%d entries", m_cue_entries.size());
2500 eDebug("cutfile not found!");
2502 m_cuesheet_changed = 0;
2503 cutlistToCuesheet();
2504 m_event((iPlayableService*)this, evCuesheetChanged);
2507 void eDVBServicePlay::saveCuesheet()
2509 std::string filename = m_reference.path + ".cuts";
2511 FILE *f = fopen(filename.c_str(), "wb");
2515 unsigned long long where;
2518 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2520 #if BYTE_ORDER == BIG_ENDIAN
2523 where = bswap_64(i->where);
2525 what = htonl(i->what);
2526 fwrite(&where, sizeof(where), 1, f);
2527 fwrite(&what, sizeof(what), 1, f);
2533 m_cuesheet_changed = 0;
2536 void eDVBServicePlay::cutlistToCuesheet()
2540 eDebug("no cue sheet");
2545 if (!m_cutlist_enabled)
2547 m_cue->commitSpans();
2548 eDebug("cutlists were disabled");
2552 pts_t in = 0, out = 0, length = 0;
2556 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2558 int have_any_span = 0;
2562 if (i == m_cue_entries.end())
2568 if (i->what == 0) /* in */
2572 } else if (i->what == 1) /* out */
2574 else /* mark (2) or last play position (3) */
2593 m_cue->addSourceSpan(in, out);
2598 if (i == m_cue_entries.end())
2601 m_cue->commitSpans();
2604 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2606 if (m_subtitle_widget)
2607 disableSubtitles(parent);
2610 int tuplesize = PyTuple_Size(tuple);
2613 if (!PyTuple_Check(tuple))
2619 entry = PyTuple_GET_ITEM(tuple, 0);
2621 if (!PyInt_Check(entry))
2624 type = PyInt_AsLong(entry);
2626 if (type == 1) // teletext subtitles
2628 int page, magazine, pid;
2632 if (!m_teletext_parser)
2634 eDebug("enable teletext subtitles.. no parser !!!");
2638 entry = PyTuple_GET_ITEM(tuple, 1);
2639 if (!PyInt_Check(entry))
2641 pid = PyInt_AsLong(entry);
2643 entry = PyTuple_GET_ITEM(tuple, 2);
2644 if (!PyInt_Check(entry))
2646 page = PyInt_AsLong(entry);
2648 entry = PyTuple_GET_ITEM(tuple, 3);
2649 if (!PyInt_Check(entry))
2651 magazine = PyInt_AsLong(entry);
2653 m_subtitle_widget = new eSubtitleWidget(parent);
2654 m_subtitle_widget->resize(parent->size()); /* full size */
2655 m_teletext_parser->setPageAndMagazine(page, magazine);
2657 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2661 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2662 if (!m_subtitle_parser)
2664 eDebug("enable dvb subtitles.. no parser !!!");
2670 entry = PyTuple_GET_ITEM(tuple, 1);
2671 if (!PyInt_Check(entry))
2673 pid = PyInt_AsLong(entry);
2675 entry = PyTuple_GET_ITEM(tuple, 2);
2676 if (!PyInt_Check(entry))
2678 composition_page_id = PyInt_AsLong(entry);
2680 entry = PyTuple_GET_ITEM(tuple, 3);
2681 if (!PyInt_Check(entry))
2683 ancillary_page_id = PyInt_AsLong(entry);
2685 m_subtitle_widget = new eSubtitleWidget(parent);
2686 m_subtitle_widget->resize(parent->size()); /* full size */
2687 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2689 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2695 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2696 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2697 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2701 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2703 delete m_subtitle_widget;
2704 m_subtitle_widget = 0;
2705 if (m_subtitle_parser)
2707 m_subtitle_parser->stop();
2708 m_dvb_subtitle_pages.clear();
2710 if (m_teletext_parser)
2712 m_teletext_parser->setPageAndMagazine(-1, -1);
2713 m_subtitle_pages.clear();
2716 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2720 PyObject *eDVBServicePlay::getCachedSubtitle()
2724 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2727 unsigned int data = (unsigned int)tmp;
2728 int pid = (data&0xFFFF0000)>>16;
2729 ePyObject tuple = PyTuple_New(4);
2730 eDVBServicePMTHandler::program program;
2731 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2732 if (!h.getProgramInfo(program))
2734 if (program.textPid==pid) // teletext
2735 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2737 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2738 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2739 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2740 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2748 PyObject *eDVBServicePlay::getSubtitleList()
2750 if (!m_teletext_parser)
2753 ePyObject l = PyList_New(0);
2754 std::set<int> added_ttx_pages;
2756 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2757 m_teletext_parser->m_found_subtitle_pages;
2759 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2760 eDVBServicePMTHandler::program program;
2761 if (h.getProgramInfo(program))
2762 eDebug("getting program info failed.");
2765 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2766 it != program.subtitleStreams.end(); ++it)
2768 switch(it->subtitling_type)
2770 case 0x01: // ebu teletext subtitles
2772 int page_number = it->teletext_page_number & 0xFF;
2773 int magazine_number = it->teletext_magazine_number & 7;
2774 int hash = magazine_number << 8 | page_number;
2775 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2777 ePyObject tuple = PyTuple_New(5);
2778 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2779 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2780 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2781 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2782 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2783 PyList_Append(l, tuple);
2785 added_ttx_pages.insert(hash);
2790 case 0x20 ... 0x23: // dvb subtitles
2792 ePyObject tuple = PyTuple_New(5);
2793 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2794 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2795 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2796 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2797 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2798 PyList_Insert(l, 0, tuple);
2806 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2807 it != subs.end(); ++it)
2809 int page_number = it->teletext_page_number & 0xFF;
2810 int magazine_number = it->teletext_magazine_number & 7;
2811 int hash = magazine_number << 8 | page_number;
2812 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2814 ePyObject tuple = PyTuple_New(5);
2815 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2816 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2817 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2818 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2819 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2820 PyList_Append(l, tuple);
2828 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2830 if (m_subtitle_widget)
2834 m_decoder->getPTS(0, pos);
2835 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2836 m_subtitle_pages.push_back(page);
2837 checkSubtitleTiming();
2841 void eDVBServicePlay::checkSubtitleTiming()
2843 eDebug("checkSubtitleTiming");
2844 if (!m_subtitle_widget)
2848 enum { TELETEXT, DVB } type;
2849 eDVBTeletextSubtitlePage page;
2850 eDVBSubtitlePage dvb_page;
2852 if (!m_subtitle_pages.empty())
2854 page = m_subtitle_pages.front();
2856 show_time = page.m_pts;
2858 else if (!m_dvb_subtitle_pages.empty())
2860 dvb_page = m_dvb_subtitle_pages.front();
2862 show_time = dvb_page.m_show_time;
2870 m_decoder->getPTS(0, pos);
2872 eDebug("%lld %lld", pos, show_time);
2873 int diff = show_time - pos;
2874 if (type == TELETEXT && !page.m_have_pts)
2876 eDebug("ttx subtitle page without pts... immediate show");
2881 eDebug("[late (%d ms)]", -diff / 90);
2884 if (abs(diff) > 1800000)
2886 eDebug("[invalid]... immediate show!");
2891 if (type == TELETEXT)
2893 eDebug("display teletext subtitle page %lld", show_time);
2894 m_subtitle_widget->setPage(page);
2895 m_subtitle_pages.pop_front();
2899 eDebug("display dvb subtitle Page %lld", show_time);
2900 m_subtitle_widget->setPage(dvb_page);
2901 m_dvb_subtitle_pages.pop_front();
2905 eDebug("start subtitle delay %d", diff / 90);
2906 m_subtitle_sync_timer->start(diff / 90, 1);
2912 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2914 if (m_subtitle_widget)
2918 m_decoder->getPTS(0, pos);
2919 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2920 m_dvb_subtitle_pages.push_back(p);
2921 checkSubtitleTiming();
2925 int eDVBServicePlay::getAC3Delay()
2928 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2930 return m_decoder->getAC3Delay();
2935 int eDVBServicePlay::getPCMDelay()
2938 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2940 return m_decoder->getPCMDelay();
2945 void eDVBServicePlay::setAC3Delay(int delay)
2948 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2950 std::string config_delay;
2951 int config_delay_int = 0;
2952 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2953 config_delay_int = atoi(config_delay.c_str());
2954 m_decoder->setAC3Delay(delay + config_delay_int);
2958 void eDVBServicePlay::setPCMDelay(int delay)
2961 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2963 std::string config_delay;
2964 int config_delay_int = 0;
2965 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2966 config_delay_int = atoi(config_delay.c_str());
2968 config_delay_int = 0;
2969 m_decoder->setPCMDelay(delay + config_delay_int);
2973 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2975 switch(event.type) {
2976 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2977 m_event((iPlayableService*)this, evVideoSizeChanged);
2979 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2980 m_event((iPlayableService*)this, evVideoFramerateChanged);
2982 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2983 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2990 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2996 PyObject *eDVBServicePlay::getStreamingData()
2998 eDVBServicePMTHandler::program program;
2999 if (m_service_handler.getProgramInfo(program))
3004 ePyObject r = program.createPythonObject();
3005 ePtr<iDVBDemux> demux;
3006 if (!m_service_handler.getDataDemux(demux))
3009 if (!demux->getCADemuxID(demux_id))
3010 PutToDict(r, "demux", demux_id);
3017 DEFINE_REF(eDVBServicePlay)
3019 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3023 case iServiceInformation::sTransponderData:
3024 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3028 return iStaticServiceInformation::getInfoObject(ref, w);
3031 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");