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 (!ref.name.empty())
314 else if (!m_parser.m_name.empty())
315 name = m_parser.m_name;
319 size_t n = name.rfind('/');
320 if (n != std::string::npos)
321 name = name.substr(n + 1);
326 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
328 ASSERT(ref == m_ref);
333 stat(ref.path.c_str(), &s);
335 if (tstools.openFile(ref.path.c_str(), 1))
338 /* check if cached data is still valid */
339 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
340 return m_parser.m_length / 90000;
342 /* open again, this time with stream info */
343 if (tstools.openFile(ref.path.c_str()))
346 /* otherwise, re-calc length and update meta file */
348 if (tstools.calcLen(len))
351 m_parser.m_length = len;
352 m_parser.m_filesize = s.st_size;
353 m_parser.updateMeta(ref.path);
354 return m_parser.m_length / 90000;
357 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
361 case iServiceInformation::sDescription:
362 return iServiceInformation::resIsString;
363 case iServiceInformation::sServiceref:
364 return iServiceInformation::resIsString;
365 case iServiceInformation::sFileSize:
366 return m_parser.m_filesize;
367 case iServiceInformation::sTimeCreate:
368 if (m_parser.m_time_create)
369 return m_parser.m_time_create;
371 return iServiceInformation::resNA;
373 return iServiceInformation::resNA;
377 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
381 case iServiceInformation::sDescription:
382 return m_parser.m_description;
383 case iServiceInformation::sServiceref:
384 return m_parser.m_ref.toString();
385 case iServiceInformation::sTags:
386 return m_parser.m_tags;
392 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
396 case iServiceInformation::sFileSize:
397 return PyLong_FromLongLong(m_parser.m_filesize);
403 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
405 if (!ref.path.empty())
407 ePtr<eServiceEvent> event = new eServiceEvent;
408 std::string filename = ref.path;
409 filename.erase(filename.length()-2, 2);
411 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
421 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
423 DECLARE_REF(eDVBPVRServiceOfflineOperations);
424 eServiceReferenceDVB m_ref;
426 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
428 RESULT deleteFromDisk(int simulate);
429 RESULT getListOfFilenames(std::list<std::string> &);
433 DEFINE_REF(eDVBPVRServiceOfflineOperations);
435 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
439 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
445 std::list<std::string> res;
446 if (getListOfFilenames(res))
449 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
451 eDebug("FATAL !! can't get background file eraser");
453 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
455 eDebug("Removing %s...", i->c_str());
457 eraser->erase(i->c_str());
459 ::unlink(i->c_str());
466 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
469 res.push_back(m_ref.path);
471 // handling for old splitted recordings (enigma 1)
476 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
478 if (stat(buf, &s) < 0)
483 res.push_back(m_ref.path + ".meta");
484 res.push_back(m_ref.path + ".ap");
485 res.push_back(m_ref.path + ".sc");
486 res.push_back(m_ref.path + ".cuts");
487 std::string tmp = m_ref.path;
488 tmp.erase(m_ref.path.length()-3);
489 res.push_back(tmp + ".eit");
493 RESULT eDVBPVRServiceOfflineOperations::reindex()
495 const char *filename = m_ref.path.c_str();
496 eDebug("reindexing %s...", filename);
498 eMPEGStreamInformation info;
499 eMPEGStreamParserTS parser(info);
501 info.startSave(filename);
505 int err = f.open(m_ref.path.c_str(), 0);
510 off_t length = f.length();
511 unsigned char buffer[188*256*4];
514 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
515 int r = f.read(offset, buffer, sizeof(buffer));
521 parser.parseData(offset, buffer, r);
530 DEFINE_REF(eServiceFactoryDVB)
532 eServiceFactoryDVB::eServiceFactoryDVB()
534 ePtr<eServiceCenter> sc;
536 eServiceCenter::getPrivInstance(sc);
539 std::list<std::string> extensions;
540 extensions.push_back("ts");
541 extensions.push_back("trp");
542 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
545 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
546 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
549 eServiceFactoryDVB::~eServiceFactoryDVB()
551 ePtr<eServiceCenter> sc;
553 eServiceCenter::getPrivInstance(sc);
555 sc->removeServiceFactory(eServiceFactoryDVB::id);
558 DEFINE_REF(eDVBServiceList);
560 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
564 eDVBServiceList::~eDVBServiceList()
568 RESULT eDVBServiceList::startQuery()
570 ePtr<iDVBChannelList> db;
571 ePtr<eDVBResourceManager> res;
574 if ((err = eDVBResourceManager::getInstance(res)) != 0)
576 eDebug("no resource manager");
579 if ((err = res->getChannelList(db)) != 0)
581 eDebug("no channel list");
585 ePtr<eDVBChannelQuery> q;
587 if (!m_parent.path.empty())
589 eDVBChannelQuery::compile(q, m_parent.path);
592 eDebug("compile query failed");
597 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
599 eDebug("startQuery failed");
606 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
608 eServiceReferenceDVB ref;
613 while (!m_query->getNextResult(ref))
617 list.sort(iListableServiceCompare(this));
622 // The first argument of this function is a format string to specify the order and
623 // the content of the returned list
624 // useable format options are
625 // R = Service Reference (as swig object .. this is very slow)
626 // S = Service Reference (as python string object .. same as ref.toString())
627 // C = Service Reference (as python string object .. same as ref.toCompareString())
628 // N = Service Name (as python string object)
629 // n = Short Service Name (short name brakets used) (as python string object)
630 // when exactly one return value per service is selected in the format string,
631 // then each value is directly a list entry
632 // when more than one value is returned per service, then the list is a list of
634 // unknown format string chars are returned as python None values !
635 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
638 std::list<eServiceReference> tmplist;
641 if (!format || !(retcount=strlen(format)))
642 format = "R"; // just return service reference swig object ...
644 if (!getContent(tmplist, sorted))
646 int services=tmplist.size();
647 ePtr<iStaticServiceInformation> sptr;
648 eServiceCenterPtr service_center;
650 if (strchr(format, 'N') || strchr(format, 'n'))
651 eServiceCenter::getPrivInstance(service_center);
653 ret = PyList_New(services);
654 std::list<eServiceReference>::iterator it(tmplist.begin());
656 for (int cnt=0; cnt < services; ++cnt)
658 eServiceReference &ref=*it++;
659 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
660 for (int i=0; i < retcount; ++i)
665 case 'R': // service reference (swig)object
666 tmp = NEW_eServiceReference(ref);
668 case 'C': // service reference compare string
669 tmp = PyString_FromString(ref.toCompareString().c_str());
671 case 'S': // service reference string
672 tmp = PyString_FromString(ref.toString().c_str());
674 case 'N': // service name
677 service_center->info(ref, sptr);
681 sptr->getName(ref, name);
683 // filter short name brakets
685 while((pos = name.find("\xc2\x86")) != std::string::npos)
687 while((pos = name.find("\xc2\x87")) != std::string::npos)
691 tmp = PyString_FromString(name.c_str());
695 tmp = PyString_FromString("<n/a>");
697 case 'n': // short service name
700 service_center->info(ref, sptr);
704 sptr->getName(ref, name);
705 name = buildShortName(name);
707 tmp = PyString_FromString(name.c_str());
711 tmp = PyString_FromString("<n/a>");
724 PyTuple_SET_ITEM(tuple, i, tmp);
726 PyList_SET_ITEM(ret, cnt, tmp);
730 PyList_SET_ITEM(ret, cnt, tuple);
733 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
736 RESULT eDVBServiceList::getNext(eServiceReference &ref)
741 return m_query->getNextResult((eServiceReferenceDVB&)ref);
744 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
746 if (m_parent.flags & eServiceReference::canDescent) // bouquet
748 ePtr<iDVBChannelList> db;
749 ePtr<eDVBResourceManager> resm;
751 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
754 if (db->getBouquet(m_parent, m_bouquet) != 0)
765 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
769 return m_bouquet->addService(ref, before);
772 RESULT eDVBServiceList::removeService(eServiceReference &ref)
776 return m_bouquet->removeService(ref);
779 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
783 return m_bouquet->moveService(ref, pos);
786 RESULT eDVBServiceList::flushChanges()
790 return m_bouquet->flushChanges();
793 RESULT eDVBServiceList::setListName(const std::string &name)
797 return m_bouquet->setListName(name);
800 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
802 ePtr<eDVBService> service;
803 int r = lookupService(service, ref);
806 // check resources...
807 ptr = new eDVBServicePlay(ref, service);
811 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
813 if (ref.path.empty())
815 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
824 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
826 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
827 if (list->startQuery())
837 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
839 /* is a listable service? */
840 if (ref.flags & eServiceReference::canDescent) // bouquet
842 if ( !ref.name.empty() ) // satellites or providers list
843 ptr = m_StaticServiceDVBInfo;
844 else // a dvb bouquet
845 ptr = m_StaticServiceDVBBouquetInfo;
847 else if (!ref.path.empty()) /* do we have a PVR service? */
848 ptr = new eStaticServiceDVBPVRInformation(ref);
849 else // normal dvb service
851 ePtr<eDVBService> service;
852 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
853 ptr = m_StaticServiceDVBInfo;
855 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
861 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
863 if (ref.path.empty())
869 ptr = new eDVBPVRServiceOfflineOperations(ref);
874 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
876 if (!ref.path.empty()) // playback
878 eDVBMetaParser parser;
879 int ret=parser.parseFile(ref.path);
880 service = new eDVBService;
882 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
886 // TODO: handle the listing itself
887 // if (ref.... == -1) .. return "... bouquets ...";
888 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
890 ePtr<iDVBChannelList> db;
891 ePtr<eDVBResourceManager> res;
894 if ((err = eDVBResourceManager::getInstance(res)) != 0)
896 eDebug("no resource manager");
899 if ((err = res->getChannelList(db)) != 0)
901 eDebug("no channel list");
905 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
906 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
908 // eDebug("getService failed!");
916 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
917 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
920 m_is_pvr = !m_reference.path.empty();
922 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
923 m_skipmode = m_fastforward = m_slowmotion = 0;
925 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
926 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
927 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
929 m_cuesheet_changed = 0;
930 m_cutlist_enabled = 1;
932 m_subtitle_widget = 0;
936 m_subtitle_sync_timer = eTimer::create(eApp);
938 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
941 eDVBServicePlay::~eDVBServicePlay()
946 int ret=meta.parseFile(m_reference.path);
950 meta.m_service_data="";
951 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
952 meta.m_service_data += tmp;
954 for (int x=0; x < eDVBService::cacheMax; ++x)
956 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
959 sprintf(tmp, ",c:%02d%04x", x, entry);
960 meta.m_service_data += tmp;
963 meta.updateMeta(m_reference.path);
966 delete m_subtitle_widget;
969 void eDVBServicePlay::gotNewEvent()
973 ePtr<eServiceEvent> m_event_now, m_event_next;
974 getEvent(m_event_now, 0);
975 getEvent(m_event_next, 1);
978 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
980 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
982 m_event((iPlayableService*)this, evUpdatedEventInfo);
985 void eDVBServicePlay::serviceEvent(int event)
987 m_tune_state = event;
991 case eDVBServicePMTHandler::eventTuned:
993 ePtr<iDVBDemux> m_demux;
994 if (!m_service_handler.getDataDemux(m_demux))
996 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
997 int sid = ref.getParentServiceID().get();
999 sid = ref.getServiceID().get();
1000 if ( ref.getParentTransportStreamID().get() &&
1001 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1002 m_event_handler.startOther(m_demux, sid);
1004 m_event_handler.start(m_demux, sid);
1006 m_event((iPlayableService*)this, evTunedIn);
1009 case eDVBServicePMTHandler::eventNoResources:
1010 case eDVBServicePMTHandler::eventNoPAT:
1011 case eDVBServicePMTHandler::eventNoPATEntry:
1012 case eDVBServicePMTHandler::eventNoPMT:
1013 case eDVBServicePMTHandler::eventTuneFailed:
1014 case eDVBServicePMTHandler::eventMisconfiguration:
1016 eDebug("DVB service failed to tune - error %d", event);
1017 m_event((iPlayableService*)this, evTuneFailed);
1020 case eDVBServicePMTHandler::eventNewProgramInfo:
1022 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1023 if (m_timeshift_enabled)
1024 updateTimeshiftPids();
1025 if (!m_timeshift_active)
1027 if (m_first_program_info & 1 && m_is_pvr)
1029 m_first_program_info &= ~1;
1032 if (!m_timeshift_active)
1033 m_event((iPlayableService*)this, evUpdatedInfo);
1036 case eDVBServicePMTHandler::eventPreStart:
1039 case eDVBServicePMTHandler::eventEOF:
1040 m_event((iPlayableService*)this, evEOF);
1042 case eDVBServicePMTHandler::eventSOF:
1043 m_event((iPlayableService*)this, evSOF);
1048 void eDVBServicePlay::serviceEventTimeshift(int event)
1052 case eDVBServicePMTHandler::eventNewProgramInfo:
1053 eDebug("eventNewProgramInfo TS");
1054 if (m_timeshift_active)
1057 if (m_first_program_info & 2)
1061 eDebug("re-apply slowmotion after timeshift file change");
1062 m_decoder->setSlowMotion(m_slowmotion);
1066 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1068 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1069 if (m_fastforward != 1)
1070 m_decoder->setFastForward(m_fastforward);
1072 m_decoder->setTrickmode();
1076 m_first_program_info &= ~2;
1078 m_event((iPlayableService*)this, evUpdatedInfo);
1081 case eDVBServicePMTHandler::eventSOF:
1083 if (!m_timeshift_file_next.empty())
1085 eDebug("timeshift SOF, switch to next file");
1088 m_first_program_info |= 2;
1090 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1091 r.path = m_timeshift_file_next;
1093 /* free the timeshift service handler, we need the resources */
1094 m_service_handler_timeshift.free();
1098 m_cue->seekTo(0, -1000);
1099 ePtr<iTsSource> source = createTsSource(r);
1100 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1102 m_event((iPlayableService*)this, evUser+1);
1106 m_event((iPlayableService*)this, evSOF);
1108 case eDVBServicePMTHandler::eventEOF:
1109 if ((!m_is_paused) && (m_skipmode >= 0))
1111 if (m_timeshift_file_next.empty())
1113 eDebug("timeshift EOF, so let's go live");
1118 eDebug("timeshift EOF, switch to next file");
1120 m_first_program_info |= 2;
1122 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1123 r.path = m_timeshift_file_next;
1125 /* free the timeshift service handler, we need the resources */
1126 m_service_handler_timeshift.free();
1129 ePtr<iTsSource> source = createTsSource(r);
1130 m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file_next.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1132 m_event((iPlayableService*)this, evUser+1);
1139 RESULT eDVBServicePlay::start()
1141 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1143 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1144 two (one for decoding, one for data source), as we must be prepared
1145 to start recording from the data demux. */
1148 eDVBMetaParser meta;
1149 if (!meta.parseFile(m_reference.path))
1151 service = meta.m_ref;
1152 service.path = m_reference.path;
1154 m_cue = new eCueSheet();
1157 m_event(this, evStart);
1159 m_first_program_info = 1;
1160 ePtr<iTsSource> source = createTsSource(service);
1161 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service);
1165 /* inject EIT if there is a stored one */
1166 std::string filename = service.path;
1167 filename.erase(filename.length()-2, 2);
1169 ePtr<eServiceEvent> event = new eServiceEvent;
1170 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1172 ePtr<eServiceEvent> empty;
1173 m_event_handler.inject(event, 0);
1174 m_event_handler.inject(empty, 1);
1176 m_event(this, evStart);
1181 RESULT eDVBServicePlay::stop()
1183 /* add bookmark for last play position */
1186 pts_t play_position, length;
1187 if (!getPlayPosition(play_position))
1189 /* remove last position */
1190 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1192 if (i->what == 3) /* current play position */
1194 m_cue_entries.erase(i);
1195 i = m_cue_entries.begin();
1201 if (getLength(length))
1206 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1208 m_cuesheet_changed = 1;
1212 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1214 m_service_handler_timeshift.free();
1215 m_service_handler.free();
1217 if (m_is_pvr && m_cuesheet_changed)
1220 /* save cuesheet only when main file is accessible. */
1221 if (!::stat(m_reference.path.c_str(), &s))
1224 m_event((iPlayableService*)this, evStopped);
1228 RESULT eDVBServicePlay::setTarget(int target)
1230 m_is_primary = !target;
1234 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1236 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1240 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1242 /* note: we check for timeshift to be enabled,
1243 not neccessary active. if you pause when timeshift
1244 is not active, you should activate it when unpausing */
1245 if ((!m_is_pvr) && (!m_timeshift_enabled))
1255 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1257 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1258 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1259 setFastForward_internal(0);
1262 m_slowmotion = ratio;
1263 return m_decoder->setSlowMotion(ratio);
1269 RESULT eDVBServicePlay::setFastForward(int ratio)
1271 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1273 return setFastForward_internal(ratio);
1276 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1278 int skipmode, ffratio, ret = 0;
1285 } else if (ratio > 0)
1293 } else // if (ratio < 0)
1299 if (m_skipmode != skipmode)
1301 eDebug("setting cue skipmode to %d", skipmode);
1303 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1306 m_skipmode = skipmode;
1309 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1311 m_fastforward = ffratio;
1317 ; /* return m_decoder->play(); is done in caller*/
1318 else if (ffratio != 1)
1319 ret = m_decoder->setFastForward(ffratio);
1321 ret = m_decoder->setTrickmode();
1324 eDebug("final seek after trickplay ret %d", seekTo(pos));
1329 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1331 if (m_is_pvr || m_timeshift_enabled)
1341 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1342 RESULT eDVBServicePlay::getLength(pts_t &len)
1344 ePtr<iDVBPVRChannel> pvr_channel;
1346 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349 return pvr_channel->getLength(len);
1352 RESULT eDVBServicePlay::pause()
1354 eDebug("eDVBServicePlay::pause");
1355 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1360 return m_decoder->pause();
1365 RESULT eDVBServicePlay::unpause()
1367 eDebug("eDVBServicePlay::unpause");
1368 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1373 return m_decoder->play();
1378 RESULT eDVBServicePlay::seekTo(pts_t to)
1380 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1382 if (!m_decode_demux)
1385 ePtr<iDVBPVRChannel> pvr_channel;
1387 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1393 m_cue->seekTo(0, to);
1394 m_dvb_subtitle_pages.clear();
1395 m_subtitle_pages.clear();
1400 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1402 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1404 if (!m_decode_demux)
1407 ePtr<iDVBPVRChannel> pvr_channel;
1409 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1414 /* HACK until we have skip-AP api */
1415 if ((to > 0) && (to < 100))
1423 m_cue->seekTo(mode, to);
1424 m_dvb_subtitle_pages.clear();
1425 m_subtitle_pages.clear();
1429 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1431 ePtr<iDVBPVRChannel> pvr_channel;
1433 if (!m_decode_demux)
1436 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1441 /* if there is a decoder, use audio or video PTS */
1444 r = m_decoder->getPTS(0, pos);
1450 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1453 RESULT eDVBServicePlay::setTrickmode(int trick)
1455 /* currently unimplemented */
1459 RESULT eDVBServicePlay::isCurrentlySeekable()
1464 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1465 if (m_decoder->getVideoProgressive() == -1)
1471 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1477 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1483 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1489 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1495 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1501 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1504 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1505 (m_timeshift_enabled || !m_is_pvr))
1507 if (!m_timeshift_enabled)
1509 /* query config path */
1511 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1512 eDebug("could not query ts path from config");
1516 /* we need enough diskspace */
1518 if (statfs(tspath.c_str(), &fs) < 0)
1520 eDebug("statfs failed!");
1524 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1526 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1536 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1547 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1553 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1559 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1565 RESULT eDVBServicePlay::getName(std::string &name)
1569 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1570 return i->getName(m_reference, name);
1572 else if (m_dvb_service)
1574 m_dvb_service->getName(m_reference, name);
1578 else if (!m_reference.name.empty())
1579 eStaticServiceDVBInformation().getName(m_reference, name);
1581 name = "DVB service";
1585 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1587 return m_event_handler.getEvent(evt, nownext);
1590 int eDVBServicePlay::getInfo(int w)
1592 eDVBServicePMTHandler::program program;
1594 if (w == sCAIDs || w == sCAIDPIDs)
1595 return resIsPyObject;
1597 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1599 int no_program_info = 0;
1601 if (h.getProgramInfo(program))
1602 no_program_info = 1;
1608 return m_decoder->getVideoHeight();
1612 return m_decoder->getVideoWidth();
1616 return m_decoder->getVideoFrameRate();
1620 return m_decoder->getVideoProgressive();
1626 aspect = m_decoder->getVideoAspect();
1627 if (aspect == -1 && no_program_info)
1629 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1631 ePtr<eServiceEvent> evt;
1632 if (!m_event_handler.getEvent(evt, 0))
1634 ePtr<eComponentData> data;
1635 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1637 if ( data->getStreamContent() == 1 )
1639 switch(data->getComponentType())
1642 case 1: // 4:3 SD PAL
1644 case 3: // 16:9 SD PAL
1645 case 4: // > 16:9 PAL
1646 case 5: // 4:3 SD NTSC
1648 case 7: // 16:9 SD NTSC
1649 case 8: // > 16:9 NTSC
1652 case 9: // 4:3 HD PAL
1654 case 0xB: // 16:9 HD PAL
1655 case 0xC: // > 16:9 HD PAL
1656 case 0xD: // 4:3 HD NTSC
1658 case 0xF: // 16:9 HD NTSC
1659 case 0x10: // > 16:9 HD PAL
1660 return data->getComponentType();
1670 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1674 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1678 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1679 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1683 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1686 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1690 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1694 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1698 if (no_program_info) return -1; return program.pcrPid;
1699 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1700 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1701 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1702 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1703 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1704 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1705 case sProvider: if (!m_dvb_service) return -1; return -2;
1706 case sServiceref: return resIsString;
1707 case sDVBState: return m_tune_state;
1714 std::string eDVBServicePlay::getInfoString(int w)
1719 if (!m_dvb_service) return "";
1720 return m_dvb_service->m_provider_name;
1722 return m_reference.toString();
1726 return iServiceInformation::getInfoString(w);
1729 PyObject *eDVBServicePlay::getInfoObject(int w)
1734 return m_service_handler.getCaIds();
1736 return m_service_handler.getCaIds(true);
1737 case sTransponderData:
1738 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1742 return iServiceInformation::getInfoObject(w);
1745 int eDVBServicePlay::getNumberOfTracks()
1747 eDVBServicePMTHandler::program program;
1748 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1749 if (h.getProgramInfo(program))
1751 return program.audioStreams.size();
1754 int eDVBServicePlay::getCurrentTrack()
1756 eDVBServicePMTHandler::program program;
1757 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1758 if (h.getProgramInfo(program))
1761 int max = program.audioStreams.size();
1764 for (i = 0; i < max; ++i)
1765 if (program.audioStreams[i].pid == m_current_audio_pid)
1771 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1773 int ret = selectAudioStream(i);
1775 if (m_decoder->set())
1781 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1783 eDVBServicePMTHandler::program program;
1784 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1786 if (h.getProgramInfo(program))
1789 if (i >= program.audioStreams.size())
1792 info.m_pid = program.audioStreams[i].pid;
1794 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1795 info.m_description = "MPEG";
1796 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1797 info.m_description = "Dolby Digital";
1798 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1799 info.m_description = "Dolby Digital+";
1800 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1801 info.m_description = "AAC";
1802 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1803 info.m_description = "AAC-HE";
1804 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1805 info.m_description = "DTS";
1806 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1807 info.m_description = "DTS-HD";
1809 info.m_description = "???";
1811 if (program.audioStreams[i].component_tag != -1)
1813 ePtr<eServiceEvent> evt;
1814 if (!m_event_handler.getEvent(evt, 0))
1816 ePtr<eComponentData> data;
1817 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1818 info.m_language = data->getText();
1822 if (info.m_language.empty())
1823 info.m_language = program.audioStreams[i].language_code;
1828 int eDVBServicePlay::selectAudioStream(int i)
1830 eDVBServicePMTHandler::program program;
1831 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1832 pts_t position = -1;
1834 if (h.getProgramInfo(program))
1837 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1845 stream = program.defaultAudioStream;
1847 int apid = -1, apidtype = -1;
1849 if (((unsigned int)stream) < program.audioStreams.size())
1851 apid = program.audioStreams[stream].pid;
1852 apidtype = program.audioStreams[stream].type;
1855 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1856 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1858 m_current_audio_pid = apid;
1860 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1862 eDebug("set audio pid failed");
1867 eDebug("seekTo ret %d", seekTo(position));
1871 /* 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 */
1872 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1874 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1876 rdsPid = program.audioStreams[stream].rdsPid;
1877 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1880 ePtr<iDVBDemux> data_demux;
1881 if (!h.getDataDemux(data_demux))
1883 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1884 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1885 m_rds_decoder->start(rdsPid);
1890 /* store new pid as default only when:
1891 a.) we have an entry in the service db for the current service,
1892 b.) we are not playing back something,
1893 c.) we are not selecting the default entry. (we wouldn't change
1894 anything in the best case, or destroy the default setting in
1895 case the real default is not yet available.)
1897 if (m_dvb_service && ((i != -1)
1898 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1900 if (apidtype == eDVBAudio::aMPEG)
1902 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1903 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1905 else if (apidtype == eDVBAudio::aAC3)
1907 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1908 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1912 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1913 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1917 h.resetCachedProgram();
1922 int eDVBServicePlay::getCurrentChannel()
1924 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1927 RESULT eDVBServicePlay::selectChannel(int i)
1929 if (i < LEFT || i > RIGHT || i == STEREO)
1932 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1934 m_decoder->setAudioChannel(i);
1938 std::string eDVBServicePlay::getText(int x)
1944 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1946 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1951 void eDVBServicePlay::rdsDecoderEvent(int what)
1955 case eDVBRdsDecoder::RadioTextChanged:
1956 m_event((iPlayableService*)this, evUpdatedRadioText);
1958 case eDVBRdsDecoder::RtpTextChanged:
1959 m_event((iPlayableService*)this, evUpdatedRtpText);
1961 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1962 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1964 case eDVBRdsDecoder::RecvRassSlidePic:
1965 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1970 void eDVBServicePlay::showRassSlidePicture()
1976 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1977 if (rass_slide_pic.length())
1978 m_decoder->showSinglePic(rass_slide_pic.c_str());
1980 eDebug("empty filename for rass slide picture received!!");
1983 eDebug("no MPEG Decoder to show iframes avail");
1986 eDebug("showRassSlidePicture called.. but not decoder");
1989 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1995 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1996 if (rass_interactive_pic.length())
1997 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1999 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2002 eDebug("no MPEG Decoder to show iframes avail");
2005 eDebug("showRassInteractivePic called.. but not decoder");
2008 ePyObject eDVBServicePlay::getRassInteractiveMask()
2011 return m_rds_decoder->getRassPictureMask();
2015 int eDVBServiceBase::getFrontendInfo(int w)
2017 eUsePtr<iDVBChannel> channel;
2018 if(m_service_handler.getChannel(channel))
2020 ePtr<iDVBFrontend> fe;
2021 if(channel->getFrontend(fe))
2023 return fe->readFrontendData(w);
2026 PyObject *eDVBServiceBase::getFrontendData()
2028 ePyObject ret = PyDict_New();
2031 eUsePtr<iDVBChannel> channel;
2032 if(!m_service_handler.getChannel(channel))
2034 ePtr<iDVBFrontend> fe;
2035 if(!channel->getFrontend(fe))
2036 fe->getFrontendData(ret);
2044 PyObject *eDVBServiceBase::getFrontendStatus()
2046 ePyObject ret = PyDict_New();
2049 eUsePtr<iDVBChannel> channel;
2050 if(!m_service_handler.getChannel(channel))
2052 ePtr<iDVBFrontend> fe;
2053 if(!channel->getFrontend(fe))
2054 fe->getFrontendStatus(ret);
2062 PyObject *eDVBServiceBase::getTransponderData(bool original)
2064 ePyObject ret = PyDict_New();
2067 eUsePtr<iDVBChannel> channel;
2068 if(!m_service_handler.getChannel(channel))
2070 ePtr<iDVBFrontend> fe;
2071 if(!channel->getFrontend(fe))
2072 fe->getTransponderData(ret, original);
2080 PyObject *eDVBServiceBase::getAll(bool original)
2082 ePyObject ret = getTransponderData(original);
2085 eUsePtr<iDVBChannel> channel;
2086 if(!m_service_handler.getChannel(channel))
2088 ePtr<iDVBFrontend> fe;
2089 if(!channel->getFrontend(fe))
2091 fe->getFrontendData(ret);
2092 fe->getFrontendStatus(ret);
2099 int eDVBServicePlay::getNumberOfSubservices()
2101 ePtr<eServiceEvent> evt;
2102 if (!m_event_handler.getEvent(evt, 0))
2103 return evt->getNumOfLinkageServices();
2107 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2109 ePtr<eServiceEvent> evt;
2110 if (!m_event_handler.getEvent(evt, 0))
2112 if (!evt->getLinkageService(sub, m_reference, n))
2115 sub.type=eServiceReference::idInvalid;
2119 RESULT eDVBServicePlay::startTimeshift()
2121 ePtr<iDVBDemux> demux;
2123 eDebug("Start timeshift!");
2125 if (m_timeshift_enabled)
2128 /* start recording with the data demux. */
2129 if (m_service_handler.getDataDemux(demux))
2132 demux->createTSRecorder(m_record);
2137 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2138 eDebug("could not query ts path");
2141 tspath.append("/timeshift.XXXXXX");
2143 templ = new char[tspath.length() + 1];
2144 strcpy(templ, tspath.c_str());
2146 m_timeshift_fd = mkstemp(templ);
2147 m_timeshift_file = std::string(templ);
2149 eDebug("recording to %s", templ);
2153 if (m_timeshift_fd < 0)
2159 m_record->setTargetFD(m_timeshift_fd);
2161 m_timeshift_enabled = 1;
2163 updateTimeshiftPids();
2169 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2171 if (!m_timeshift_enabled)
2177 m_timeshift_enabled = 0;
2182 close(m_timeshift_fd);
2183 eDebug("remove timeshift file");
2184 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2189 int eDVBServicePlay::isTimeshiftActive()
2191 return m_timeshift_enabled && m_timeshift_active;
2194 RESULT eDVBServicePlay::activateTimeshift()
2196 if (!m_timeshift_enabled)
2199 if (!m_timeshift_active)
2201 switchToTimeshift();
2208 PyObject *eDVBServicePlay::getCutList()
2210 ePyObject list = PyList_New(0);
2212 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2214 ePyObject tuple = PyTuple_New(2);
2215 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2216 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2217 PyList_Append(list, tuple);
2224 void eDVBServicePlay::setCutList(ePyObject list)
2226 if (!PyList_Check(list))
2228 int size = PyList_Size(list);
2231 m_cue_entries.clear();
2233 for (i=0; i<size; ++i)
2235 ePyObject tuple = PyList_GET_ITEM(list, i);
2236 if (!PyTuple_Check(tuple))
2238 eDebug("non-tuple in cutlist");
2241 if (PyTuple_Size(tuple) != 2)
2243 eDebug("cutlist entries need to be a 2-tuple");
2246 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2247 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2249 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2252 pts_t pts = PyLong_AsLongLong(ppts);
2253 int type = PyInt_AsLong(ptype);
2254 m_cue_entries.insert(cueEntry(pts, type));
2255 eDebug("adding %08llx, %d", pts, type);
2257 m_cuesheet_changed = 1;
2259 cutlistToCuesheet();
2260 m_event((iPlayableService*)this, evCuesheetChanged);
2263 void eDVBServicePlay::setCutListEnable(int enable)
2265 m_cutlist_enabled = enable;
2266 cutlistToCuesheet();
2269 void eDVBServicePlay::updateTimeshiftPids()
2274 eDVBServicePMTHandler::program program;
2275 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2277 if (h.getProgramInfo(program))
2281 std::set<int> pids_to_record;
2282 pids_to_record.insert(0); // PAT
2283 if (program.pmtPid != -1)
2284 pids_to_record.insert(program.pmtPid); // PMT
2286 if (program.textPid != -1)
2287 pids_to_record.insert(program.textPid); // Videotext
2289 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2290 i(program.videoStreams.begin());
2291 i != program.videoStreams.end(); ++i)
2292 pids_to_record.insert(i->pid);
2294 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2295 i(program.audioStreams.begin());
2296 i != program.audioStreams.end(); ++i)
2297 pids_to_record.insert(i->pid);
2299 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2300 i(program.subtitleStreams.begin());
2301 i != program.subtitleStreams.end(); ++i)
2302 pids_to_record.insert(i->pid);
2304 std::set<int> new_pids, obsolete_pids;
2306 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2307 m_pids_active.begin(), m_pids_active.end(),
2308 std::inserter(new_pids, new_pids.begin()));
2310 std::set_difference(
2311 m_pids_active.begin(), m_pids_active.end(),
2312 pids_to_record.begin(), pids_to_record.end(),
2313 std::inserter(new_pids, new_pids.begin())
2316 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2317 m_record->addPID(*i);
2319 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2320 m_record->removePID(*i);
2324 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2326 m_timeshift_file_next = f;
2330 void eDVBServicePlay::switchToLive()
2332 if (!m_timeshift_active)
2335 eDebug("SwitchToLive");
2339 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2341 /* free the timeshift service handler, we need the resources */
2342 m_service_handler_timeshift.free();
2344 updateDecoder(true);
2347 void eDVBServicePlay::resetTimeshift(int start)
2352 m_teletext_parser = 0;
2354 m_subtitle_parser = 0;
2355 m_new_subtitle_page_connection = 0;
2356 m_new_dvb_subtitle_page_connection = 0;
2357 m_rds_decoder_event_connection = 0;
2358 m_video_event_connection = 0;
2359 m_timeshift_changed = 1;
2360 m_timeshift_file_next.clear();
2364 m_cue = new eCueSheet();
2365 m_timeshift_active = 1;
2368 m_timeshift_active = 0;
2371 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2373 eRawFile *f = new eRawFile();
2374 f->open(ref.path.c_str());
2375 return ePtr<iTsSource>(f);
2378 void eDVBServicePlay::switchToTimeshift()
2380 if (m_timeshift_active)
2385 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2386 r.path = m_timeshift_file;
2388 m_cue->seekTo(0, -1000);
2390 ePtr<iTsSource> source = createTsSource(r);
2391 m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2393 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2395 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2398 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2400 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2401 bool mustPlay = false;
2403 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2405 eDVBServicePMTHandler::program program;
2406 if (h.getProgramInfo(program))
2407 eDebug("getting program info failed.");
2410 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2411 if (!program.videoStreams.empty())
2413 eDebugNoNewLine(" (");
2414 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2415 i(program.videoStreams.begin());
2416 i != program.videoStreams.end(); ++i)
2423 if (i != program.videoStreams.begin())
2424 eDebugNoNewLine(", ");
2425 eDebugNoNewLine("%04x", i->pid);
2427 eDebugNoNewLine(")");
2429 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2430 if (!program.audioStreams.empty())
2432 eDebugNoNewLine(" (");
2433 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2434 i(program.audioStreams.begin());
2435 i != program.audioStreams.end(); ++i)
2437 if (i != program.audioStreams.begin())
2438 eDebugNoNewLine(", ");
2439 eDebugNoNewLine("%04x", i->pid);
2441 eDebugNoNewLine(")");
2443 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2444 pcrpid = program.pcrPid;
2445 eDebug(", and the text pid is %04x", program.textPid);
2446 tpid = program.textPid;
2451 h.getDecodeDemux(m_decode_demux);
2454 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2456 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2459 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2460 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2461 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2462 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2463 if (m_timeshift_changed)
2465 ePyObject subs = getCachedSubtitle();
2466 if (subs != Py_None)
2468 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2469 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2470 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2471 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2472 if (type == 0) // dvb
2473 m_subtitle_parser->start(pid, comp_page, anc_page);
2474 else if (type == 1) // ttx
2475 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2482 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2486 m_timeshift_changed = 0;
2490 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2493 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2494 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2495 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2499 eServiceReferenceDVB ref;
2500 m_service_handler.getServiceReference(ref);
2501 eServiceReferenceDVB parent = ref.getParentServiceReference();
2506 ePtr<eDVBResourceManager> res_mgr;
2507 if (!eDVBResourceManager::getInstance(res_mgr))
2509 ePtr<iDVBChannelList> db;
2510 if (!res_mgr->getChannelList(db))
2512 ePtr<eDVBService> origService;
2513 if (!db->getService(parent, origService))
2515 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2516 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2523 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2524 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2526 m_decoder->setVideoPID(vpid, vpidtype);
2527 selectAudioStream();
2529 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2530 m_decoder->setSyncPCR(pcrpid);
2532 m_decoder->setSyncPCR(-1);
2536 m_decoder->setTextPID(tpid);
2537 m_teletext_parser->start(program.textPid);
2540 if (vpid > 0 && vpid < 0x2000)
2544 std::string radio_pic;
2545 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2546 m_decoder->setRadioPic(radio_pic);
2554 m_decoder->setAudioChannel(achannel);
2556 /* don't worry about non-existing services, nor pvr services */
2559 /* (audio pid will be set in selectAudioTrack */
2560 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2561 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2562 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2563 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2565 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2566 sendSeekableStateChanged = true;
2568 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2570 if (sendSeekableStateChanged)
2571 m_event((iPlayableService*)this, evSeekableStatusChanged);
2574 void eDVBServicePlay::loadCuesheet()
2576 std::string filename = m_reference.path + ".cuts";
2578 m_cue_entries.clear();
2580 FILE *f = fopen(filename.c_str(), "rb");
2584 eDebug("loading cuts..");
2587 unsigned long long where;
2590 if (!fread(&where, sizeof(where), 1, f))
2592 if (!fread(&what, sizeof(what), 1, f))
2595 #if BYTE_ORDER == LITTLE_ENDIAN
2596 where = bswap_64(where);
2603 m_cue_entries.insert(cueEntry(where, what));
2606 eDebug("%zd entries", m_cue_entries.size());
2608 eDebug("cutfile not found!");
2610 m_cuesheet_changed = 0;
2611 cutlistToCuesheet();
2612 m_event((iPlayableService*)this, evCuesheetChanged);
2615 void eDVBServicePlay::saveCuesheet()
2617 std::string filename = m_reference.path + ".cuts";
2619 FILE *f = fopen(filename.c_str(), "wb");
2623 unsigned long long where;
2626 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2628 #if BYTE_ORDER == BIG_ENDIAN
2631 where = bswap_64(i->where);
2633 what = htonl(i->what);
2634 fwrite(&where, sizeof(where), 1, f);
2635 fwrite(&what, sizeof(what), 1, f);
2641 m_cuesheet_changed = 0;
2644 void eDVBServicePlay::cutlistToCuesheet()
2648 eDebug("no cue sheet");
2653 if (!m_cutlist_enabled)
2655 m_cue->commitSpans();
2656 eDebug("cutlists were disabled");
2660 pts_t in = 0, out = 0, length = 0;
2664 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2666 int have_any_span = 0;
2670 if (i == m_cue_entries.end())
2672 if (!have_any_span && !in)
2676 if (i->what == 0) /* in */
2680 } else if (i->what == 1) /* out */
2682 else /* mark (2) or last play position (3) */
2701 m_cue->addSourceSpan(in, out);
2707 if (i == m_cue_entries.end())
2710 m_cue->commitSpans();
2713 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2715 if (m_subtitle_widget)
2716 disableSubtitles(parent);
2719 int tuplesize = PyTuple_Size(tuple);
2722 if (!PyTuple_Check(tuple))
2728 entry = PyTuple_GET_ITEM(tuple, 0);
2730 if (!PyInt_Check(entry))
2733 type = PyInt_AsLong(entry);
2735 if (type == 1) // teletext subtitles
2737 int page, magazine, pid;
2741 if (!m_teletext_parser)
2743 eDebug("enable teletext subtitles.. no parser !!!");
2747 entry = PyTuple_GET_ITEM(tuple, 1);
2748 if (!PyInt_Check(entry))
2750 pid = PyInt_AsLong(entry);
2752 entry = PyTuple_GET_ITEM(tuple, 2);
2753 if (!PyInt_Check(entry))
2755 page = PyInt_AsLong(entry);
2757 entry = PyTuple_GET_ITEM(tuple, 3);
2758 if (!PyInt_Check(entry))
2760 magazine = PyInt_AsLong(entry);
2762 m_subtitle_widget = new eSubtitleWidget(parent);
2763 m_subtitle_widget->resize(parent->size()); /* full size */
2764 m_teletext_parser->setPageAndMagazine(page, magazine);
2766 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2770 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2771 if (!m_subtitle_parser)
2773 eDebug("enable dvb subtitles.. no parser !!!");
2779 entry = PyTuple_GET_ITEM(tuple, 1);
2780 if (!PyInt_Check(entry))
2782 pid = PyInt_AsLong(entry);
2784 entry = PyTuple_GET_ITEM(tuple, 2);
2785 if (!PyInt_Check(entry))
2787 composition_page_id = PyInt_AsLong(entry);
2789 entry = PyTuple_GET_ITEM(tuple, 3);
2790 if (!PyInt_Check(entry))
2792 ancillary_page_id = PyInt_AsLong(entry);
2794 m_subtitle_widget = new eSubtitleWidget(parent);
2795 m_subtitle_widget->resize(parent->size()); /* full size */
2796 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2798 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2804 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2805 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2806 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2810 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2812 delete m_subtitle_widget;
2813 m_subtitle_widget = 0;
2814 if (m_subtitle_parser)
2816 m_subtitle_parser->stop();
2817 m_dvb_subtitle_pages.clear();
2819 if (m_teletext_parser)
2821 m_teletext_parser->setPageAndMagazine(-1, -1);
2822 m_subtitle_pages.clear();
2825 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2829 PyObject *eDVBServicePlay::getCachedSubtitle()
2833 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2836 unsigned int data = (unsigned int)tmp;
2837 int pid = (data&0xFFFF0000)>>16;
2838 ePyObject tuple = PyTuple_New(4);
2839 eDVBServicePMTHandler::program program;
2840 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2841 if (!h.getProgramInfo(program))
2843 if (program.textPid==pid) // teletext
2844 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2846 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2847 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2848 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2849 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2857 PyObject *eDVBServicePlay::getSubtitleList()
2859 if (!m_teletext_parser)
2862 ePyObject l = PyList_New(0);
2863 std::set<int> added_ttx_pages;
2865 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2866 m_teletext_parser->m_found_subtitle_pages;
2868 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2869 eDVBServicePMTHandler::program program;
2870 if (h.getProgramInfo(program))
2871 eDebug("getting program info failed.");
2874 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2875 it != program.subtitleStreams.end(); ++it)
2877 switch(it->subtitling_type)
2879 case 0x01: // ebu teletext subtitles
2881 int page_number = it->teletext_page_number & 0xFF;
2882 int magazine_number = it->teletext_magazine_number & 7;
2883 int hash = magazine_number << 8 | page_number;
2884 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2886 ePyObject tuple = PyTuple_New(5);
2887 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2888 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2889 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2890 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2891 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2892 PyList_Append(l, tuple);
2894 added_ttx_pages.insert(hash);
2899 case 0x20 ... 0x23: // dvb subtitles
2901 ePyObject tuple = PyTuple_New(5);
2902 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2903 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2904 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2905 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2906 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2907 PyList_Insert(l, 0, tuple);
2915 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2916 it != subs.end(); ++it)
2918 int page_number = it->teletext_page_number & 0xFF;
2919 int magazine_number = it->teletext_magazine_number & 7;
2920 int hash = magazine_number << 8 | page_number;
2921 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2923 ePyObject tuple = PyTuple_New(5);
2924 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2925 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2926 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2927 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2928 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2929 PyList_Append(l, tuple);
2937 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2939 if (m_subtitle_widget)
2943 m_decoder->getPTS(0, pos);
2944 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2945 m_subtitle_pages.push_back(page);
2946 checkSubtitleTiming();
2950 void eDVBServicePlay::checkSubtitleTiming()
2952 eDebug("checkSubtitleTiming");
2953 if (!m_subtitle_widget)
2957 enum { TELETEXT, DVB } type;
2958 eDVBTeletextSubtitlePage page;
2959 eDVBSubtitlePage dvb_page;
2961 if (!m_subtitle_pages.empty())
2963 page = m_subtitle_pages.front();
2965 show_time = page.m_pts;
2967 else if (!m_dvb_subtitle_pages.empty())
2969 dvb_page = m_dvb_subtitle_pages.front();
2971 show_time = dvb_page.m_show_time;
2979 m_decoder->getPTS(0, pos);
2981 eDebug("%lld %lld", pos, show_time);
2982 int diff = show_time - pos;
2983 if (type == TELETEXT && !page.m_have_pts)
2985 eDebug("ttx subtitle page without pts... immediate show");
2990 eDebug("[late (%d ms)]", -diff / 90);
2993 if (abs(diff) > 1800000)
2995 eDebug("[invalid]... immediate show!");
3000 if (type == TELETEXT)
3002 eDebug("display teletext subtitle page %lld", show_time);
3003 m_subtitle_widget->setPage(page);
3004 m_subtitle_pages.pop_front();
3008 eDebug("display dvb subtitle Page %lld", show_time);
3009 m_subtitle_widget->setPage(dvb_page);
3010 m_dvb_subtitle_pages.pop_front();
3014 eDebug("start subtitle delay %d", diff / 90);
3015 m_subtitle_sync_timer->start(diff / 90, 1);
3021 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3023 if (m_subtitle_widget)
3027 m_decoder->getPTS(0, pos);
3028 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3029 m_dvb_subtitle_pages.push_back(p);
3030 checkSubtitleTiming();
3034 int eDVBServicePlay::getAC3Delay()
3037 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3039 return m_decoder->getAC3Delay();
3044 int eDVBServicePlay::getPCMDelay()
3047 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3049 return m_decoder->getPCMDelay();
3054 void eDVBServicePlay::setAC3Delay(int delay)
3057 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3059 std::string config_delay;
3060 int config_delay_int = 0;
3061 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3062 config_delay_int = atoi(config_delay.c_str());
3063 m_decoder->setAC3Delay(delay + config_delay_int);
3067 void eDVBServicePlay::setPCMDelay(int delay)
3070 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3072 std::string config_delay;
3073 int config_delay_int = 0;
3074 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3075 config_delay_int = atoi(config_delay.c_str());
3077 config_delay_int = 0;
3078 m_decoder->setPCMDelay(delay + config_delay_int);
3082 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3084 switch(event.type) {
3085 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3086 m_event((iPlayableService*)this, evVideoSizeChanged);
3088 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3089 m_event((iPlayableService*)this, evVideoFramerateChanged);
3091 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3092 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3099 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3105 PyObject *eDVBServicePlay::getStreamingData()
3107 eDVBServicePMTHandler::program program;
3108 if (m_service_handler.getProgramInfo(program))
3113 ePyObject r = program.createPythonObject();
3114 ePtr<iDVBDemux> demux;
3115 if (!m_service_handler.getDataDemux(demux))
3118 if (!demux->getCADemuxID(demux_id))
3119 PutToDict(r, "demux", demux_id);
3126 DEFINE_REF(eDVBServicePlay)
3128 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3132 case iServiceInformation::sTransponderData:
3133 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3137 return iStaticServiceInformation::getInfoObject(ref, w);
3140 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");