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
20 #include <lib/base/httpstream.h>
23 #include <lib/gui/esubtitle.h>
29 #include <netinet/in.h>
32 #error no byte order defined!
35 class eStaticServiceDVBInformation: public iStaticServiceInformation
37 DECLARE_REF(eStaticServiceDVBInformation);
39 RESULT getName(const eServiceReference &ref, std::string &name);
40 int getLength(const eServiceReference &ref);
41 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
42 PyObject *getInfoObject(const eServiceReference &ref, int);
45 DEFINE_REF(eStaticServiceDVBInformation);
47 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
49 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
50 if ( !ref.name.empty() )
52 if (service.getParentTransportStreamID().get()) // linkage subservice
54 ePtr<iServiceHandler> service_center;
55 if (!eServiceCenter::getInstance(service_center))
57 eServiceReferenceDVB parent = service;
58 parent.setTransportStreamID( service.getParentTransportStreamID() );
59 parent.setServiceID( service.getParentServiceID() );
60 parent.setParentTransportStreamID(eTransportStreamID(0));
61 parent.setParentServiceID(eServiceID(0));
63 ePtr<iStaticServiceInformation> service_info;
64 if (!service_center->info(parent, service_info))
66 if (!service_info->getName(parent, name))
67 name=buildShortName(name) + " - ";
80 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
85 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
87 ePtr<eDVBResourceManager> res_mgr;
88 if ( eDVBResourceManager::getInstance( res_mgr ) )
89 eDebug("isPlayable... no res manager!!");
92 eDVBChannelID chid, chid_ignore;
94 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
95 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
96 return res_mgr->canAllocateChannel(chid, chid_ignore, system);
101 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
102 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
103 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
104 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
106 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
108 if (r.type == eServiceReference::idDVB)
110 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
113 case iServiceInformation::sTransponderData:
115 ePtr<eDVBResourceManager> res;
116 if (!eDVBResourceManager::getInstance(res))
118 ePtr<iDVBChannelList> db;
119 if (!res->getChannelList(db))
122 ref.getChannelID(chid);
123 ePtr<iDVBFrontendParameters> feparm;
124 if (!db->getChannelFrontendData(chid, feparm))
127 if (!feparm->getSystem(system))
129 ePyObject dict = PyDict_New();
132 case iDVBFrontend::feSatellite:
134 eDVBFrontendParametersSatellite s;
136 PutSatelliteDataToDict(dict, s);
139 case iDVBFrontend::feTerrestrial:
141 eDVBFrontendParametersTerrestrial t;
143 PutTerrestrialDataToDict(dict, t);
146 case iDVBFrontend::feCable:
148 eDVBFrontendParametersCable c;
150 PutCableDataToDict(dict, c);
154 eDebug("unknown frontend type %d", system);
169 DEFINE_REF(eStaticServiceDVBBouquetInformation);
171 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
173 ePtr<iDVBChannelList> db;
174 ePtr<eDVBResourceManager> res;
177 if ((err = eDVBResourceManager::getInstance(res)) != 0)
179 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
182 if ((err = res->getChannelList(db)) != 0)
184 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
189 if ((err = db->getBouquet(ref, bouquet)) != 0)
191 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
195 if ( bouquet && bouquet->m_bouquet_name.length() )
197 name = bouquet->m_bouquet_name;
204 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
206 if (ref.flags & eServiceReference::isGroup)
208 ePtr<iDVBChannelList> db;
209 ePtr<eDVBResourceManager> res;
211 if (eDVBResourceManager::getInstance(res))
213 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
217 if (res->getChannelList(db))
219 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
224 if (db->getBouquet(ref, bouquet))
226 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
230 int prio_order = eDVBFrontend::getTypePriorityOrder();
232 eDVBChannelID chid, chid_ignore;
233 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
234 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
236 static unsigned char prio_map[6][3] = {
237 { 3, 2, 1 }, // -S -C -T
238 { 3, 1, 2 }, // -S -T -C
239 { 2, 3, 1 }, // -C -S -T
240 { 1, 3, 2 }, // -C -T -S
241 { 1, 2, 3 }, // -T -C -S
242 { 2, 1, 3 } // -T -S -C
245 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
246 int tmp = res->canAllocateChannel(chid, chid_ignore, system, simulate);
251 case iDVBFrontend::feTerrestrial:
252 tmp = prio_map[prio_order][2];
254 case iDVBFrontend::feCable:
255 tmp = prio_map[prio_order][1];
258 case iDVBFrontend::feSatellite:
259 tmp = prio_map[prio_order][0];
265 m_playable_service = *it;
272 m_playable_service = eServiceReference();
276 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
281 #include <lib/dvb/epgcache.h>
283 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
285 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
288 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
290 DECLARE_REF(eStaticServiceDVBPVRInformation);
291 eServiceReference m_ref;
292 eDVBMetaParser m_parser;
294 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
295 RESULT getName(const eServiceReference &ref, std::string &name);
296 int getLength(const eServiceReference &ref);
297 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
298 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
299 int getInfo(const eServiceReference &ref, int w);
300 std::string getInfoString(const eServiceReference &ref,int w);
301 PyObject *getInfoObject(const eServiceReference &r, int what);
304 DEFINE_REF(eStaticServiceDVBPVRInformation);
306 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
309 m_parser.parseFile(ref.path);
312 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
314 ASSERT(ref == m_ref);
315 if (!ref.name.empty())
317 else if (!m_parser.m_name.empty())
318 name = m_parser.m_name;
322 size_t n = name.rfind('/');
323 if (n != std::string::npos)
324 name = name.substr(n + 1);
329 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
331 ASSERT(ref == m_ref);
336 stat(ref.path.c_str(), &s);
338 if (tstools.openFile(ref.path.c_str(), 1))
341 /* check if cached data is still valid */
342 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
343 return m_parser.m_length / 90000;
345 /* open again, this time with stream info */
346 if (tstools.openFile(ref.path.c_str()))
349 /* otherwise, re-calc length and update meta file */
351 if (tstools.calcLen(len))
354 m_parser.m_length = len;
355 m_parser.m_filesize = s.st_size;
356 m_parser.updateMeta(ref.path);
357 return m_parser.m_length / 90000;
360 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
364 case iServiceInformation::sDescription:
365 return iServiceInformation::resIsString;
366 case iServiceInformation::sServiceref:
367 return iServiceInformation::resIsString;
368 case iServiceInformation::sFileSize:
369 return m_parser.m_filesize;
370 case iServiceInformation::sTimeCreate:
371 if (m_parser.m_time_create)
372 return m_parser.m_time_create;
374 return iServiceInformation::resNA;
376 return iServiceInformation::resNA;
380 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
384 case iServiceInformation::sDescription:
385 return m_parser.m_description;
386 case iServiceInformation::sServiceref:
387 return m_parser.m_ref.toString();
388 case iServiceInformation::sTags:
389 return m_parser.m_tags;
395 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
399 case iServiceInformation::sFileSize:
400 return PyLong_FromLongLong(m_parser.m_filesize);
406 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
408 if (!ref.path.empty())
410 if (ref.path.substr(0, 7) == "http://")
412 eServiceReference equivalentref(ref);
413 /* this might be a scrambled stream (id + 0x100), force equivalent dvb type */
414 equivalentref.type = eServiceFactoryDVB::id;
415 equivalentref.path.clear();
416 return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
420 ePtr<eServiceEvent> event = new eServiceEvent;
421 std::string filename = ref.path;
422 filename.erase(filename.length()-2, 2);
424 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
435 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
437 DECLARE_REF(eDVBPVRServiceOfflineOperations);
438 eServiceReferenceDVB m_ref;
440 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
442 RESULT deleteFromDisk(int simulate);
443 RESULT getListOfFilenames(std::list<std::string> &);
447 DEFINE_REF(eDVBPVRServiceOfflineOperations);
449 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
453 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
459 std::list<std::string> res;
460 if (getListOfFilenames(res))
463 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
465 eDebug("FATAL !! can't get background file eraser");
467 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
469 eDebug("Removing %s...", i->c_str());
471 eraser->erase(i->c_str());
473 ::unlink(i->c_str());
480 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
483 res.push_back(m_ref.path);
485 // handling for old splitted recordings (enigma 1)
490 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
492 if (stat(buf, &s) < 0)
497 res.push_back(m_ref.path + ".meta");
498 res.push_back(m_ref.path + ".ap");
499 res.push_back(m_ref.path + ".sc");
500 res.push_back(m_ref.path + ".cuts");
501 std::string tmp = m_ref.path;
502 tmp.erase(m_ref.path.length()-3);
503 res.push_back(tmp + ".eit");
507 RESULT eDVBPVRServiceOfflineOperations::reindex()
509 const char *filename = m_ref.path.c_str();
510 eDebug("reindexing %s...", filename);
512 eMPEGStreamInformation info;
513 eMPEGStreamParserTS parser(info);
515 info.startSave(filename);
519 int err = f.open(m_ref.path.c_str(), 0);
524 off_t length = f.length();
525 unsigned char buffer[188*256*4];
528 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
529 int r = f.read(offset, buffer, sizeof(buffer));
535 parser.parseData(offset, buffer, r);
544 DEFINE_REF(eServiceFactoryDVB)
546 eServiceFactoryDVB::eServiceFactoryDVB()
548 ePtr<eServiceCenter> sc;
550 eServiceCenter::getPrivInstance(sc);
553 std::list<std::string> extensions;
554 extensions.push_back("ts");
555 extensions.push_back("trp");
556 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
559 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
560 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
563 eServiceFactoryDVB::~eServiceFactoryDVB()
565 ePtr<eServiceCenter> sc;
567 eServiceCenter::getPrivInstance(sc);
569 sc->removeServiceFactory(eServiceFactoryDVB::id);
572 DEFINE_REF(eDVBServiceList);
574 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
578 eDVBServiceList::~eDVBServiceList()
582 RESULT eDVBServiceList::startQuery()
584 ePtr<iDVBChannelList> db;
585 ePtr<eDVBResourceManager> res;
588 if ((err = eDVBResourceManager::getInstance(res)) != 0)
590 eDebug("no resource manager");
593 if ((err = res->getChannelList(db)) != 0)
595 eDebug("no channel list");
599 ePtr<eDVBChannelQuery> q;
601 if (!m_parent.path.empty())
603 eDVBChannelQuery::compile(q, m_parent.path);
606 eDebug("compile query failed");
611 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
613 eDebug("startQuery failed");
620 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
622 eServiceReferenceDVB ref;
627 while (!m_query->getNextResult(ref))
631 list.sort(iListableServiceCompare(this));
636 // The first argument of this function is a format string to specify the order and
637 // the content of the returned list
638 // useable format options are
639 // R = Service Reference (as swig object .. this is very slow)
640 // S = Service Reference (as python string object .. same as ref.toString())
641 // C = Service Reference (as python string object .. same as ref.toCompareString())
642 // N = Service Name (as python string object)
643 // n = Short Service Name (short name brakets used) (as python string object)
644 // when exactly one return value per service is selected in the format string,
645 // then each value is directly a list entry
646 // when more than one value is returned per service, then the list is a list of
648 // unknown format string chars are returned as python None values !
649 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
652 std::list<eServiceReference> tmplist;
655 if (!format || !(retcount=strlen(format)))
656 format = "R"; // just return service reference swig object ...
658 if (!getContent(tmplist, sorted))
660 int services=tmplist.size();
661 ePtr<iStaticServiceInformation> sptr;
662 eServiceCenterPtr service_center;
664 if (strchr(format, 'N') || strchr(format, 'n'))
665 eServiceCenter::getPrivInstance(service_center);
667 ret = PyList_New(services);
668 std::list<eServiceReference>::iterator it(tmplist.begin());
670 for (int cnt=0; cnt < services; ++cnt)
672 eServiceReference &ref=*it++;
673 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
674 for (int i=0; i < retcount; ++i)
679 case 'R': // service reference (swig)object
680 tmp = NEW_eServiceReference(ref);
682 case 'C': // service reference compare string
683 tmp = PyString_FromString(ref.toCompareString().c_str());
685 case 'S': // service reference string
686 tmp = PyString_FromString(ref.toString().c_str());
688 case 'N': // service name
691 service_center->info(ref, sptr);
695 sptr->getName(ref, name);
697 // filter short name brakets
699 while((pos = name.find("\xc2\x86")) != std::string::npos)
701 while((pos = name.find("\xc2\x87")) != std::string::npos)
705 tmp = PyString_FromString(name.c_str());
709 tmp = PyString_FromString("<n/a>");
711 case 'n': // short service name
714 service_center->info(ref, sptr);
718 sptr->getName(ref, name);
719 name = buildShortName(name);
721 tmp = PyString_FromString(name.c_str());
725 tmp = PyString_FromString("<n/a>");
738 PyTuple_SET_ITEM(tuple, i, tmp);
740 PyList_SET_ITEM(ret, cnt, tmp);
744 PyList_SET_ITEM(ret, cnt, tuple);
747 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
750 RESULT eDVBServiceList::getNext(eServiceReference &ref)
755 return m_query->getNextResult((eServiceReferenceDVB&)ref);
758 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
760 if (m_parent.flags & eServiceReference::canDescent) // bouquet
762 ePtr<iDVBChannelList> db;
763 ePtr<eDVBResourceManager> resm;
765 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
768 if (db->getBouquet(m_parent, m_bouquet) != 0)
779 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
783 return m_bouquet->addService(ref, before);
786 RESULT eDVBServiceList::removeService(eServiceReference &ref)
790 return m_bouquet->removeService(ref);
793 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
797 return m_bouquet->moveService(ref, pos);
800 RESULT eDVBServiceList::flushChanges()
804 return m_bouquet->flushChanges();
807 RESULT eDVBServiceList::setListName(const std::string &name)
811 return m_bouquet->setListName(name);
814 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
816 ePtr<eDVBService> service;
817 int r = lookupService(service, ref);
820 // check resources...
821 ptr = new eDVBServicePlay(ref, service);
825 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
827 if (ref.path.empty())
829 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
833 bool isstream = ref.path.substr(0, 7) == "http://";
836 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref, isstream);
844 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
846 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
847 if (list->startQuery())
857 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
859 /* is a listable service? */
860 if (ref.flags & eServiceReference::canDescent) // bouquet
862 if ( !ref.name.empty() ) // satellites or providers list
863 ptr = m_StaticServiceDVBInfo;
864 else // a dvb bouquet
865 ptr = m_StaticServiceDVBBouquetInfo;
867 else if (!ref.path.empty()) /* do we have a PVR service? */
868 ptr = new eStaticServiceDVBPVRInformation(ref);
869 else // normal dvb service
871 ePtr<eDVBService> service;
872 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
873 ptr = m_StaticServiceDVBInfo;
875 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
881 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
883 if (ref.path.empty())
889 ptr = new eDVBPVRServiceOfflineOperations(ref);
894 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
896 if (!ref.path.empty()) // playback
898 eDVBMetaParser parser;
899 int ret=parser.parseFile(ref.path);
900 service = new eDVBService;
902 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
906 // TODO: handle the listing itself
907 // if (ref.... == -1) .. return "... bouquets ...";
908 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
910 ePtr<iDVBChannelList> db;
911 ePtr<eDVBResourceManager> res;
914 if ((err = eDVBResourceManager::getInstance(res)) != 0)
916 eDebug("no resource manager");
919 if ((err = res->getChannelList(db)) != 0)
921 eDebug("no channel list");
925 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
926 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
928 // eDebug("getService failed!");
936 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
937 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
940 m_is_stream = m_reference.path.substr(0, 7) == "http://";
941 m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
943 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
944 m_skipmode = m_fastforward = m_slowmotion = 0;
946 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
947 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
948 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
950 m_cuesheet_changed = 0;
951 m_cutlist_enabled = 1;
953 m_subtitle_widget = 0;
957 m_subtitle_sync_timer = eTimer::create(eApp);
959 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
962 eDVBServicePlay::~eDVBServicePlay()
967 int ret=meta.parseFile(m_reference.path);
971 meta.m_service_data="";
972 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
973 meta.m_service_data += tmp;
975 for (int x=0; x < eDVBService::cacheMax; ++x)
977 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
980 sprintf(tmp, ",c:%02d%04x", x, entry);
981 meta.m_service_data += tmp;
984 meta.updateMeta(m_reference.path);
987 delete m_subtitle_widget;
990 void eDVBServicePlay::gotNewEvent()
994 ePtr<eServiceEvent> m_event_now, m_event_next;
995 getEvent(m_event_now, 0);
996 getEvent(m_event_next, 1);
999 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1001 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1003 m_event((iPlayableService*)this, evUpdatedEventInfo);
1006 void eDVBServicePlay::serviceEvent(int event)
1008 m_tune_state = event;
1012 case eDVBServicePMTHandler::eventTuned:
1014 ePtr<iDVBDemux> m_demux;
1015 if (!m_service_handler.getDataDemux(m_demux))
1017 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1018 int sid = ref.getParentServiceID().get();
1020 sid = ref.getServiceID().get();
1021 if ( ref.getParentTransportStreamID().get() &&
1022 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1023 m_event_handler.startOther(m_demux, sid);
1025 m_event_handler.start(m_demux, sid);
1027 m_event((iPlayableService*)this, evTunedIn);
1030 case eDVBServicePMTHandler::eventNoResources:
1031 case eDVBServicePMTHandler::eventNoPAT:
1032 case eDVBServicePMTHandler::eventNoPATEntry:
1033 case eDVBServicePMTHandler::eventNoPMT:
1034 case eDVBServicePMTHandler::eventTuneFailed:
1035 case eDVBServicePMTHandler::eventMisconfiguration:
1037 eDebug("DVB service failed to tune - error %d", event);
1038 m_event((iPlayableService*)this, evTuneFailed);
1041 case eDVBServicePMTHandler::eventNewProgramInfo:
1043 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1044 if (m_timeshift_enabled)
1045 updateTimeshiftPids();
1046 if (!m_timeshift_active)
1048 if (m_first_program_info & 1 && m_is_pvr)
1050 m_first_program_info &= ~1;
1053 if (!m_timeshift_active)
1054 m_event((iPlayableService*)this, evUpdatedInfo);
1057 case eDVBServicePMTHandler::eventPreStart:
1060 case eDVBServicePMTHandler::eventEOF:
1061 m_event((iPlayableService*)this, evEOF);
1063 case eDVBServicePMTHandler::eventSOF:
1064 m_event((iPlayableService*)this, evSOF);
1066 case eDVBServicePMTHandler::eventHBBTVInfo:
1067 m_event((iPlayableService*)this, evHBBTVInfo);
1072 void eDVBServicePlay::serviceEventTimeshift(int event)
1076 case eDVBServicePMTHandler::eventNewProgramInfo:
1077 eDebug("eventNewProgramInfo TS");
1078 if (m_timeshift_active)
1081 if (m_first_program_info & 2)
1085 eDebug("re-apply slowmotion after timeshift file change");
1086 m_decoder->setSlowMotion(m_slowmotion);
1090 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1092 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1093 if (m_fastforward != 1)
1094 m_decoder->setFastForward(m_fastforward);
1096 m_decoder->setTrickmode();
1100 m_first_program_info &= ~2;
1102 m_event((iPlayableService*)this, evUpdatedInfo);
1105 case eDVBServicePMTHandler::eventSOF:
1107 if (!m_timeshift_file_next.empty())
1109 eDebug("timeshift SOF, switch to next file");
1112 m_first_program_info |= 2;
1114 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1115 r.path = m_timeshift_file_next;
1117 /* free the timeshift service handler, we need the resources */
1118 m_service_handler_timeshift.free();
1122 m_cue->seekTo(0, -1000);
1123 ePtr<iTsSource> source = createTsSource(r);
1124 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1126 m_event((iPlayableService*)this, evUser+1);
1130 m_event((iPlayableService*)this, evSOF);
1132 case eDVBServicePMTHandler::eventEOF:
1133 if ((!m_is_paused) && (m_skipmode >= 0))
1135 if (m_timeshift_file_next.empty())
1137 eDebug("timeshift EOF, so let's go live");
1142 eDebug("timeshift EOF, switch to next file");
1144 m_first_program_info |= 2;
1146 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1147 r.path = m_timeshift_file_next;
1149 /* free the timeshift service handler, we need the resources */
1150 m_service_handler_timeshift.free();
1153 ePtr<iTsSource> source = createTsSource(r);
1154 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 */
1156 m_event((iPlayableService*)this, evUser+1);
1163 RESULT eDVBServicePlay::start()
1165 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1167 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1168 two (one for decoding, one for data source), as we must be prepared
1169 to start recording from the data demux. */
1172 eDVBMetaParser meta;
1173 if (!meta.parseFile(m_reference.path))
1175 service = meta.m_ref;
1176 service.path = m_reference.path;
1178 m_cue = new eCueSheet();
1181 m_event(this, evStart);
1183 m_first_program_info = 1;
1184 ePtr<iTsSource> source = createTsSource(service);
1185 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1189 /* inject EIT if there is a stored one */
1190 std::string filename = service.path;
1191 filename.erase(filename.length()-2, 2);
1193 ePtr<eServiceEvent> event = new eServiceEvent;
1194 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1196 ePtr<eServiceEvent> empty;
1197 m_event_handler.inject(event, 0);
1198 m_event_handler.inject(empty, 1);
1200 m_event(this, evStart);
1205 RESULT eDVBServicePlay::stop()
1207 /* add bookmark for last play position */
1210 pts_t play_position, length;
1211 if (!getPlayPosition(play_position))
1213 /* remove last position */
1214 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1216 if (i->what == 3) /* current play position */
1218 m_cue_entries.erase(i);
1219 i = m_cue_entries.begin();
1225 if (getLength(length))
1230 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1232 m_cuesheet_changed = 1;
1236 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1238 m_service_handler_timeshift.free();
1239 m_service_handler.free();
1241 if (m_is_pvr && m_cuesheet_changed)
1244 /* save cuesheet only when main file is accessible. */
1245 if (!::stat(m_reference.path.c_str(), &s))
1248 m_event((iPlayableService*)this, evStopped);
1252 RESULT eDVBServicePlay::setTarget(int target)
1254 m_is_primary = !target;
1258 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1260 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1264 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1266 /* note: we check for timeshift to be enabled,
1267 not neccessary active. if you pause when timeshift
1268 is not active, you should activate it when unpausing */
1269 if ((!m_is_pvr) && (!m_timeshift_enabled))
1279 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1281 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1282 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1283 setFastForward_internal(0);
1286 m_slowmotion = ratio;
1287 return m_decoder->setSlowMotion(ratio);
1293 RESULT eDVBServicePlay::setFastForward(int ratio)
1295 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1297 return setFastForward_internal(ratio);
1300 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1302 int skipmode, ffratio, ret = 0;
1309 } else if (ratio > 0)
1317 } else // if (ratio < 0)
1323 if (m_skipmode != skipmode)
1325 eDebug("setting cue skipmode to %d", skipmode);
1327 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1330 m_skipmode = skipmode;
1333 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1335 m_fastforward = ffratio;
1341 ; /* return m_decoder->play(); is done in caller*/
1342 else if (ffratio != 1)
1343 ret = m_decoder->setFastForward(ffratio);
1345 ret = m_decoder->setTrickmode();
1348 eDebug("final seek after trickplay ret %d", seekTo(pos));
1353 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1355 if (m_is_pvr || m_timeshift_enabled)
1365 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1366 RESULT eDVBServicePlay::getLength(pts_t &len)
1368 ePtr<iDVBPVRChannel> pvr_channel;
1370 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1373 return pvr_channel->getLength(len);
1376 RESULT eDVBServicePlay::pause()
1378 eDebug("eDVBServicePlay::pause");
1379 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1384 return m_decoder->pause();
1389 RESULT eDVBServicePlay::unpause()
1391 eDebug("eDVBServicePlay::unpause");
1392 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1397 return m_decoder->play();
1402 RESULT eDVBServicePlay::seekTo(pts_t to)
1404 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1406 if (!m_decode_demux)
1409 ePtr<iDVBPVRChannel> pvr_channel;
1411 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1417 m_cue->seekTo(0, to);
1418 m_dvb_subtitle_pages.clear();
1419 m_subtitle_pages.clear();
1424 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1426 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1428 if (!m_decode_demux)
1431 ePtr<iDVBPVRChannel> pvr_channel;
1433 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1438 /* HACK until we have skip-AP api */
1439 if ((to > 0) && (to < 100))
1447 m_cue->seekTo(mode, to);
1448 m_dvb_subtitle_pages.clear();
1449 m_subtitle_pages.clear();
1453 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1455 ePtr<iDVBPVRChannel> pvr_channel;
1457 if (!m_decode_demux)
1460 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1465 /* if there is a decoder, use audio or video PTS */
1468 r = m_decoder->getPTS(0, pos);
1474 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1477 RESULT eDVBServicePlay::setTrickmode(int trick)
1479 /* currently unimplemented */
1483 RESULT eDVBServicePlay::isCurrentlySeekable()
1488 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1489 if (m_decoder->getVideoProgressive() == -1)
1495 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1501 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1507 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1513 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1519 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1525 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1528 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1529 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1531 if (!m_timeshift_enabled)
1533 /* query config path */
1535 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1536 eDebug("could not query ts path from config");
1540 /* we need enough diskspace */
1542 if (statfs(tspath.c_str(), &fs) < 0)
1544 eDebug("statfs failed!");
1548 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1550 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1560 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1571 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1577 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1583 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1589 RESULT eDVBServicePlay::getName(std::string &name)
1593 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1594 return i->getName(m_reference, name);
1596 else if (m_is_stream)
1598 name = m_reference.name;
1601 name = m_reference.path;
1608 else if (m_dvb_service)
1610 m_dvb_service->getName(m_reference, name);
1614 else if (!m_reference.name.empty())
1615 eStaticServiceDVBInformation().getName(m_reference, name);
1617 name = "DVB service";
1621 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1623 return m_event_handler.getEvent(evt, nownext);
1626 int eDVBServicePlay::getInfo(int w)
1628 eDVBServicePMTHandler::program program;
1630 if (w == sCAIDs || w == sCAIDPIDs)
1631 return resIsPyObject;
1633 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1635 int no_program_info = 0;
1637 if (h.getProgramInfo(program))
1638 no_program_info = 1;
1644 return m_decoder->getVideoHeight();
1648 return m_decoder->getVideoWidth();
1652 return m_decoder->getVideoFrameRate();
1656 return m_decoder->getVideoProgressive();
1662 aspect = m_decoder->getVideoAspect();
1663 if (aspect == -1 && no_program_info)
1665 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1667 ePtr<eServiceEvent> evt;
1668 if (!m_event_handler.getEvent(evt, 0))
1670 ePtr<eComponentData> data;
1671 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1673 if ( data->getStreamContent() == 1 )
1675 switch(data->getComponentType())
1678 case 1: // 4:3 SD PAL
1680 case 3: // 16:9 SD PAL
1681 case 4: // > 16:9 PAL
1682 case 5: // 4:3 SD NTSC
1684 case 7: // 16:9 SD NTSC
1685 case 8: // > 16:9 NTSC
1688 case 9: // 4:3 HD PAL
1690 case 0xB: // 16:9 HD PAL
1691 case 0xC: // > 16:9 HD PAL
1692 case 0xD: // 4:3 HD NTSC
1694 case 0xF: // 16:9 HD NTSC
1695 case 0x10: // > 16:9 HD PAL
1696 return data->getComponentType();
1706 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1710 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1714 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1715 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1719 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1722 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1726 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1730 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1734 if (no_program_info) return -1; return program.pcrPid;
1735 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1736 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1737 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1738 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1739 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1740 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1741 case sProvider: if (!m_dvb_service) return -1; return -2;
1742 case sServiceref: return resIsString;
1743 case sDVBState: return m_tune_state;
1750 std::string eDVBServicePlay::getInfoString(int w)
1755 if (!m_dvb_service) return "";
1756 return m_dvb_service->m_provider_name;
1758 return m_reference.toString();
1762 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1766 case sLiveStreamDemuxId:
1769 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1779 return iServiceInformation::getInfoString(w);
1782 PyObject *eDVBServicePlay::getInfoObject(int w)
1787 return m_service_handler.getCaIds();
1789 return m_service_handler.getCaIds(true);
1790 case sTransponderData:
1791 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1794 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1795 return h.getHbbTVApplications();
1800 return iServiceInformation::getInfoObject(w);
1803 int eDVBServicePlay::getNumberOfTracks()
1805 eDVBServicePMTHandler::program program;
1806 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1807 if (h.getProgramInfo(program))
1809 return program.audioStreams.size();
1812 int eDVBServicePlay::getCurrentTrack()
1814 eDVBServicePMTHandler::program program;
1815 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1816 if (h.getProgramInfo(program))
1819 int max = program.audioStreams.size();
1822 for (i = 0; i < max; ++i)
1823 if (program.audioStreams[i].pid == m_current_audio_pid)
1829 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1831 int ret = selectAudioStream(i);
1833 if (m_decoder->set())
1839 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1841 eDVBServicePMTHandler::program program;
1842 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1844 if (h.getProgramInfo(program))
1847 if (i >= program.audioStreams.size())
1850 info.m_pid = program.audioStreams[i].pid;
1852 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1853 info.m_description = "MPEG";
1854 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1855 info.m_description = "Dolby Digital";
1856 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1857 info.m_description = "Dolby Digital+";
1858 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1859 info.m_description = "AAC";
1860 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1861 info.m_description = "AAC-HE";
1862 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1863 info.m_description = "DTS";
1864 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1865 info.m_description = "DTS-HD";
1867 info.m_description = "???";
1869 if (program.audioStreams[i].component_tag != -1)
1871 ePtr<eServiceEvent> evt;
1872 if (!m_event_handler.getEvent(evt, 0))
1874 ePtr<eComponentData> data;
1875 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1876 info.m_language = data->getText();
1880 if (info.m_language.empty())
1881 info.m_language = program.audioStreams[i].language_code;
1886 int eDVBServicePlay::selectAudioStream(int i)
1888 eDVBServicePMTHandler::program program;
1889 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1890 pts_t position = -1;
1892 if (h.getProgramInfo(program))
1895 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1903 stream = program.defaultAudioStream;
1905 int apid = -1, apidtype = -1;
1907 if (((unsigned int)stream) < program.audioStreams.size())
1909 apid = program.audioStreams[stream].pid;
1910 apidtype = program.audioStreams[stream].type;
1913 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1914 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1916 m_current_audio_pid = apid;
1918 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1920 eDebug("set audio pid failed");
1925 eDebug("seekTo ret %d", seekTo(position));
1929 /* 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 */
1930 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1932 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1934 rdsPid = program.audioStreams[stream].rdsPid;
1935 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1938 ePtr<iDVBDemux> data_demux;
1939 if (!h.getDataDemux(data_demux))
1941 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1942 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1943 m_rds_decoder->start(rdsPid);
1948 /* store new pid as default only when:
1949 a.) we have an entry in the service db for the current service,
1950 b.) we are not playing back something,
1951 c.) we are not selecting the default entry. (we wouldn't change
1952 anything in the best case, or destroy the default setting in
1953 case the real default is not yet available.)
1955 if (m_dvb_service && ((i != -1)
1956 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1958 if (apidtype == eDVBAudio::aMPEG)
1960 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1961 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1963 else if (apidtype == eDVBAudio::aAC3)
1965 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1966 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1970 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1971 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1975 h.resetCachedProgram();
1980 int eDVBServicePlay::getCurrentChannel()
1982 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1985 RESULT eDVBServicePlay::selectChannel(int i)
1987 if (i < LEFT || i > RIGHT || i == STEREO)
1990 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1992 m_decoder->setAudioChannel(i);
1996 std::string eDVBServicePlay::getText(int x)
2002 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2004 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2009 void eDVBServicePlay::rdsDecoderEvent(int what)
2013 case eDVBRdsDecoder::RadioTextChanged:
2014 m_event((iPlayableService*)this, evUpdatedRadioText);
2016 case eDVBRdsDecoder::RtpTextChanged:
2017 m_event((iPlayableService*)this, evUpdatedRtpText);
2019 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2020 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2022 case eDVBRdsDecoder::RecvRassSlidePic:
2023 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2028 void eDVBServicePlay::showRassSlidePicture()
2034 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2035 if (rass_slide_pic.length())
2036 m_decoder->showSinglePic(rass_slide_pic.c_str());
2038 eDebug("empty filename for rass slide picture received!!");
2041 eDebug("no MPEG Decoder to show iframes avail");
2044 eDebug("showRassSlidePicture called.. but not decoder");
2047 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2053 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2054 if (rass_interactive_pic.length())
2055 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2057 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2060 eDebug("no MPEG Decoder to show iframes avail");
2063 eDebug("showRassInteractivePic called.. but not decoder");
2066 ePyObject eDVBServicePlay::getRassInteractiveMask()
2069 return m_rds_decoder->getRassPictureMask();
2073 int eDVBServiceBase::getFrontendInfo(int w)
2075 eUsePtr<iDVBChannel> channel;
2076 if(m_service_handler.getChannel(channel))
2078 ePtr<iDVBFrontend> fe;
2079 if(channel->getFrontend(fe))
2081 return fe->readFrontendData(w);
2084 PyObject *eDVBServiceBase::getFrontendData()
2086 ePyObject ret = PyDict_New();
2089 eUsePtr<iDVBChannel> channel;
2090 if(!m_service_handler.getChannel(channel))
2092 ePtr<iDVBFrontend> fe;
2093 if(!channel->getFrontend(fe))
2094 fe->getFrontendData(ret);
2102 PyObject *eDVBServiceBase::getFrontendStatus()
2104 ePyObject ret = PyDict_New();
2107 eUsePtr<iDVBChannel> channel;
2108 if(!m_service_handler.getChannel(channel))
2110 ePtr<iDVBFrontend> fe;
2111 if(!channel->getFrontend(fe))
2112 fe->getFrontendStatus(ret);
2120 PyObject *eDVBServiceBase::getTransponderData(bool original)
2122 ePyObject ret = PyDict_New();
2125 eUsePtr<iDVBChannel> channel;
2126 if(!m_service_handler.getChannel(channel))
2128 ePtr<iDVBFrontend> fe;
2129 if(!channel->getFrontend(fe))
2130 fe->getTransponderData(ret, original);
2138 PyObject *eDVBServiceBase::getAll(bool original)
2140 ePyObject ret = getTransponderData(original);
2143 eUsePtr<iDVBChannel> channel;
2144 if(!m_service_handler.getChannel(channel))
2146 ePtr<iDVBFrontend> fe;
2147 if(!channel->getFrontend(fe))
2149 fe->getFrontendData(ret);
2150 fe->getFrontendStatus(ret);
2157 int eDVBServicePlay::getNumberOfSubservices()
2159 ePtr<eServiceEvent> evt;
2160 if (!m_event_handler.getEvent(evt, 0))
2161 return evt->getNumOfLinkageServices();
2165 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2167 ePtr<eServiceEvent> evt;
2168 if (!m_event_handler.getEvent(evt, 0))
2170 if (!evt->getLinkageService(sub, m_reference, n))
2173 sub.type=eServiceReference::idInvalid;
2177 RESULT eDVBServicePlay::startTimeshift()
2179 ePtr<iDVBDemux> demux;
2181 eDebug("Start timeshift!");
2183 if (m_timeshift_enabled)
2186 /* start recording with the data demux. */
2187 if (m_service_handler.getDataDemux(demux))
2190 demux->createTSRecorder(m_record);
2195 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2196 eDebug("could not query ts path");
2199 tspath.append("/timeshift.XXXXXX");
2201 templ = new char[tspath.length() + 1];
2202 strcpy(templ, tspath.c_str());
2204 m_timeshift_fd = mkstemp(templ);
2205 m_timeshift_file = std::string(templ);
2207 eDebug("recording to %s", templ);
2211 if (m_timeshift_fd < 0)
2217 m_record->setTargetFD(m_timeshift_fd);
2219 m_timeshift_enabled = 1;
2221 updateTimeshiftPids();
2227 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2229 if (!m_timeshift_enabled)
2235 m_timeshift_enabled = 0;
2240 close(m_timeshift_fd);
2241 eDebug("remove timeshift file");
2242 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2247 int eDVBServicePlay::isTimeshiftActive()
2249 return m_timeshift_enabled && m_timeshift_active;
2252 RESULT eDVBServicePlay::activateTimeshift()
2254 if (!m_timeshift_enabled)
2257 if (!m_timeshift_active)
2259 switchToTimeshift();
2266 PyObject *eDVBServicePlay::getCutList()
2268 ePyObject list = PyList_New(0);
2270 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2272 ePyObject tuple = PyTuple_New(2);
2273 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2274 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2275 PyList_Append(list, tuple);
2282 void eDVBServicePlay::setCutList(ePyObject list)
2284 if (!PyList_Check(list))
2286 int size = PyList_Size(list);
2289 m_cue_entries.clear();
2291 for (i=0; i<size; ++i)
2293 ePyObject tuple = PyList_GET_ITEM(list, i);
2294 if (!PyTuple_Check(tuple))
2296 eDebug("non-tuple in cutlist");
2299 if (PyTuple_Size(tuple) != 2)
2301 eDebug("cutlist entries need to be a 2-tuple");
2304 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2305 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2307 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2310 pts_t pts = PyLong_AsLongLong(ppts);
2311 int type = PyInt_AsLong(ptype);
2312 m_cue_entries.insert(cueEntry(pts, type));
2313 eDebug("adding %08llx, %d", pts, type);
2315 m_cuesheet_changed = 1;
2317 cutlistToCuesheet();
2318 m_event((iPlayableService*)this, evCuesheetChanged);
2321 void eDVBServicePlay::setCutListEnable(int enable)
2323 m_cutlist_enabled = enable;
2324 cutlistToCuesheet();
2327 void eDVBServicePlay::updateTimeshiftPids()
2332 eDVBServicePMTHandler::program program;
2333 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2335 if (h.getProgramInfo(program))
2339 std::set<int> pids_to_record;
2340 pids_to_record.insert(0); // PAT
2341 if (program.pmtPid != -1)
2342 pids_to_record.insert(program.pmtPid); // PMT
2344 if (program.textPid != -1)
2345 pids_to_record.insert(program.textPid); // Videotext
2347 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2348 i(program.videoStreams.begin());
2349 i != program.videoStreams.end(); ++i)
2350 pids_to_record.insert(i->pid);
2352 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2353 i(program.audioStreams.begin());
2354 i != program.audioStreams.end(); ++i)
2355 pids_to_record.insert(i->pid);
2357 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2358 i(program.subtitleStreams.begin());
2359 i != program.subtitleStreams.end(); ++i)
2360 pids_to_record.insert(i->pid);
2362 std::set<int> new_pids, obsolete_pids;
2364 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2365 m_pids_active.begin(), m_pids_active.end(),
2366 std::inserter(new_pids, new_pids.begin()));
2368 std::set_difference(
2369 m_pids_active.begin(), m_pids_active.end(),
2370 pids_to_record.begin(), pids_to_record.end(),
2371 std::inserter(new_pids, new_pids.begin())
2374 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2375 m_record->addPID(*i);
2377 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2378 m_record->removePID(*i);
2382 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2384 m_timeshift_file_next = f;
2388 void eDVBServicePlay::switchToLive()
2390 if (!m_timeshift_active)
2393 eDebug("SwitchToLive");
2397 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2399 /* free the timeshift service handler, we need the resources */
2400 m_service_handler_timeshift.free();
2402 updateDecoder(true);
2405 void eDVBServicePlay::resetTimeshift(int start)
2410 m_teletext_parser = 0;
2412 m_subtitle_parser = 0;
2413 m_new_subtitle_page_connection = 0;
2414 m_new_dvb_subtitle_page_connection = 0;
2415 m_rds_decoder_event_connection = 0;
2416 m_video_event_connection = 0;
2417 m_timeshift_changed = 1;
2418 m_timeshift_file_next.clear();
2422 m_cue = new eCueSheet();
2423 m_timeshift_active = 1;
2426 m_timeshift_active = 0;
2429 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2433 eHttpStream *f = new eHttpStream();
2434 f->open(ref.path.c_str());
2435 return ePtr<iTsSource>(f);
2439 eRawFile *f = new eRawFile();
2440 f->open(ref.path.c_str());
2441 return ePtr<iTsSource>(f);
2445 void eDVBServicePlay::switchToTimeshift()
2447 if (m_timeshift_active)
2452 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2453 r.path = m_timeshift_file;
2455 m_cue->seekTo(0, -1000);
2457 ePtr<iTsSource> source = createTsSource(r);
2458 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 */
2460 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2462 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2465 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2467 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2468 bool mustPlay = false;
2470 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2472 eDVBServicePMTHandler::program program;
2473 if (h.getProgramInfo(program))
2474 eDebug("getting program info failed.");
2477 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2478 if (!program.videoStreams.empty())
2480 eDebugNoNewLine(" (");
2481 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2482 i(program.videoStreams.begin());
2483 i != program.videoStreams.end(); ++i)
2490 if (i != program.videoStreams.begin())
2491 eDebugNoNewLine(", ");
2492 eDebugNoNewLine("%04x", i->pid);
2494 eDebugNoNewLine(")");
2496 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2497 if (!program.audioStreams.empty())
2499 eDebugNoNewLine(" (");
2500 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2501 i(program.audioStreams.begin());
2502 i != program.audioStreams.end(); ++i)
2504 if (i != program.audioStreams.begin())
2505 eDebugNoNewLine(", ");
2506 eDebugNoNewLine("%04x", i->pid);
2508 eDebugNoNewLine(")");
2510 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2511 pcrpid = program.pcrPid;
2512 eDebug(", and the text pid is %04x", program.textPid);
2513 tpid = program.textPid;
2518 h.getDecodeDemux(m_decode_demux);
2521 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2523 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2526 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2527 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2528 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2529 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2530 if (m_timeshift_changed)
2532 ePyObject subs = getCachedSubtitle();
2533 if (subs != Py_None)
2535 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2536 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2537 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2538 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2539 if (type == 0) // dvb
2540 m_subtitle_parser->start(pid, comp_page, anc_page);
2541 else if (type == 1) // ttx
2542 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2549 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2553 m_timeshift_changed = 0;
2557 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2560 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2561 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2562 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2566 eServiceReferenceDVB ref;
2567 m_service_handler.getServiceReference(ref);
2568 eServiceReferenceDVB parent = ref.getParentServiceReference();
2573 ePtr<eDVBResourceManager> res_mgr;
2574 if (!eDVBResourceManager::getInstance(res_mgr))
2576 ePtr<iDVBChannelList> db;
2577 if (!res_mgr->getChannelList(db))
2579 ePtr<eDVBService> origService;
2580 if (!db->getService(parent, origService))
2582 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2583 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2590 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2591 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2593 m_decoder->setVideoPID(vpid, vpidtype);
2594 selectAudioStream();
2596 if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2597 m_decoder->setSyncPCR(pcrpid);
2599 m_decoder->setSyncPCR(-1);
2603 m_decoder->setTextPID(tpid);
2604 m_teletext_parser->start(program.textPid);
2607 if (vpid > 0 && vpid < 0x2000)
2611 std::string radio_pic;
2612 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2613 m_decoder->setRadioPic(radio_pic);
2621 m_decoder->setAudioChannel(achannel);
2623 /* don't worry about non-existing services, nor pvr services */
2626 /* (audio pid will be set in selectAudioTrack */
2627 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2628 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2629 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2630 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2632 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2633 sendSeekableStateChanged = true;
2635 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2637 if (sendSeekableStateChanged)
2638 m_event((iPlayableService*)this, evSeekableStatusChanged);
2641 void eDVBServicePlay::loadCuesheet()
2643 std::string filename = m_reference.path + ".cuts";
2645 m_cue_entries.clear();
2647 FILE *f = fopen(filename.c_str(), "rb");
2651 eDebug("loading cuts..");
2654 unsigned long long where;
2657 if (!fread(&where, sizeof(where), 1, f))
2659 if (!fread(&what, sizeof(what), 1, f))
2662 #if BYTE_ORDER == LITTLE_ENDIAN
2663 where = bswap_64(where);
2670 m_cue_entries.insert(cueEntry(where, what));
2673 eDebug("%zd entries", m_cue_entries.size());
2675 eDebug("cutfile not found!");
2677 m_cuesheet_changed = 0;
2678 cutlistToCuesheet();
2679 m_event((iPlayableService*)this, evCuesheetChanged);
2682 void eDVBServicePlay::saveCuesheet()
2684 std::string filename = m_reference.path + ".cuts";
2686 FILE *f = fopen(filename.c_str(), "wb");
2690 unsigned long long where;
2693 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2695 #if BYTE_ORDER == BIG_ENDIAN
2698 where = bswap_64(i->where);
2700 what = htonl(i->what);
2701 fwrite(&where, sizeof(where), 1, f);
2702 fwrite(&what, sizeof(what), 1, f);
2708 m_cuesheet_changed = 0;
2711 void eDVBServicePlay::cutlistToCuesheet()
2715 eDebug("no cue sheet");
2720 if (!m_cutlist_enabled)
2722 m_cue->commitSpans();
2723 eDebug("cutlists were disabled");
2727 pts_t in = 0, out = 0, length = 0;
2731 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2733 int have_any_span = 0;
2737 if (i == m_cue_entries.end())
2739 if (!have_any_span && !in)
2743 if (i->what == 0) /* in */
2747 } else if (i->what == 1) /* out */
2749 else /* mark (2) or last play position (3) */
2768 m_cue->addSourceSpan(in, out);
2774 if (i == m_cue_entries.end())
2777 m_cue->commitSpans();
2780 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2782 if (m_subtitle_widget)
2783 disableSubtitles(parent);
2786 int tuplesize = PyTuple_Size(tuple);
2789 if (!PyTuple_Check(tuple))
2795 entry = PyTuple_GET_ITEM(tuple, 0);
2797 if (!PyInt_Check(entry))
2800 type = PyInt_AsLong(entry);
2802 if (type == 1) // teletext subtitles
2804 int page, magazine, pid;
2808 if (!m_teletext_parser)
2810 eDebug("enable teletext subtitles.. no parser !!!");
2814 entry = PyTuple_GET_ITEM(tuple, 1);
2815 if (!PyInt_Check(entry))
2817 pid = PyInt_AsLong(entry);
2819 entry = PyTuple_GET_ITEM(tuple, 2);
2820 if (!PyInt_Check(entry))
2822 page = PyInt_AsLong(entry);
2824 entry = PyTuple_GET_ITEM(tuple, 3);
2825 if (!PyInt_Check(entry))
2827 magazine = PyInt_AsLong(entry);
2829 m_subtitle_widget = new eSubtitleWidget(parent);
2830 m_subtitle_widget->resize(parent->size()); /* full size */
2831 m_teletext_parser->setPageAndMagazine(page, magazine);
2833 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2837 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2838 if (!m_subtitle_parser)
2840 eDebug("enable dvb subtitles.. no parser !!!");
2846 entry = PyTuple_GET_ITEM(tuple, 1);
2847 if (!PyInt_Check(entry))
2849 pid = PyInt_AsLong(entry);
2851 entry = PyTuple_GET_ITEM(tuple, 2);
2852 if (!PyInt_Check(entry))
2854 composition_page_id = PyInt_AsLong(entry);
2856 entry = PyTuple_GET_ITEM(tuple, 3);
2857 if (!PyInt_Check(entry))
2859 ancillary_page_id = PyInt_AsLong(entry);
2861 m_subtitle_widget = new eSubtitleWidget(parent);
2862 m_subtitle_widget->resize(parent->size()); /* full size */
2863 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2865 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2871 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2872 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2873 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2877 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2879 delete m_subtitle_widget;
2880 m_subtitle_widget = 0;
2881 if (m_subtitle_parser)
2883 m_subtitle_parser->stop();
2884 m_dvb_subtitle_pages.clear();
2886 if (m_teletext_parser)
2888 m_teletext_parser->setPageAndMagazine(-1, -1);
2889 m_subtitle_pages.clear();
2892 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2896 PyObject *eDVBServicePlay::getCachedSubtitle()
2900 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2903 unsigned int data = (unsigned int)tmp;
2904 int pid = (data&0xFFFF0000)>>16;
2905 ePyObject tuple = PyTuple_New(4);
2906 eDVBServicePMTHandler::program program;
2907 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2908 if (!h.getProgramInfo(program))
2910 if (program.textPid==pid) // teletext
2911 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2913 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2914 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2915 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2916 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2924 PyObject *eDVBServicePlay::getSubtitleList()
2926 if (!m_teletext_parser)
2929 ePyObject l = PyList_New(0);
2930 std::set<int> added_ttx_pages;
2932 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2933 m_teletext_parser->m_found_subtitle_pages;
2935 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2936 eDVBServicePMTHandler::program program;
2937 if (h.getProgramInfo(program))
2938 eDebug("getting program info failed.");
2941 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2942 it != program.subtitleStreams.end(); ++it)
2944 switch(it->subtitling_type)
2946 case 0x01: // ebu teletext subtitles
2948 int page_number = it->teletext_page_number & 0xFF;
2949 int magazine_number = it->teletext_magazine_number & 7;
2950 int hash = magazine_number << 8 | page_number;
2951 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2953 ePyObject tuple = PyTuple_New(5);
2954 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2955 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2956 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2957 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2958 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2959 PyList_Append(l, tuple);
2961 added_ttx_pages.insert(hash);
2966 case 0x20 ... 0x23: // dvb subtitles
2968 ePyObject tuple = PyTuple_New(5);
2969 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2970 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2971 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2972 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2973 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2974 PyList_Insert(l, 0, tuple);
2982 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2983 it != subs.end(); ++it)
2985 int page_number = it->teletext_page_number & 0xFF;
2986 int magazine_number = it->teletext_magazine_number & 7;
2987 int hash = magazine_number << 8 | page_number;
2988 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2990 ePyObject tuple = PyTuple_New(5);
2991 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2992 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2993 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2994 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2995 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2996 PyList_Append(l, tuple);
3004 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3006 if (m_subtitle_widget)
3010 m_decoder->getPTS(0, pos);
3011 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3012 m_subtitle_pages.push_back(page);
3013 checkSubtitleTiming();
3017 void eDVBServicePlay::checkSubtitleTiming()
3019 eDebug("checkSubtitleTiming");
3020 if (!m_subtitle_widget)
3024 enum { TELETEXT, DVB } type;
3025 eDVBTeletextSubtitlePage page;
3026 eDVBSubtitlePage dvb_page;
3028 if (!m_subtitle_pages.empty())
3030 page = m_subtitle_pages.front();
3032 show_time = page.m_pts;
3034 else if (!m_dvb_subtitle_pages.empty())
3036 dvb_page = m_dvb_subtitle_pages.front();
3038 show_time = dvb_page.m_show_time;
3046 m_decoder->getPTS(0, pos);
3048 eDebug("%lld %lld", pos, show_time);
3049 int diff = show_time - pos;
3050 if (type == TELETEXT && !page.m_have_pts)
3052 eDebug("ttx subtitle page without pts... immediate show");
3057 eDebug("[late (%d ms)]", -diff / 90);
3060 if (abs(diff) > 1800000)
3062 eDebug("[invalid]... immediate show!");
3067 if (type == TELETEXT)
3069 eDebug("display teletext subtitle page %lld", show_time);
3070 m_subtitle_widget->setPage(page);
3071 m_subtitle_pages.pop_front();
3075 eDebug("display dvb subtitle Page %lld", show_time);
3076 m_subtitle_widget->setPage(dvb_page);
3077 m_dvb_subtitle_pages.pop_front();
3081 eDebug("start subtitle delay %d", diff / 90);
3082 m_subtitle_sync_timer->start(diff / 90, 1);
3088 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3090 if (m_subtitle_widget)
3094 m_decoder->getPTS(0, pos);
3095 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3096 m_dvb_subtitle_pages.push_back(p);
3097 checkSubtitleTiming();
3101 int eDVBServicePlay::getAC3Delay()
3104 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3106 return m_decoder->getAC3Delay();
3111 int eDVBServicePlay::getPCMDelay()
3114 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3116 return m_decoder->getPCMDelay();
3121 void eDVBServicePlay::setAC3Delay(int delay)
3124 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3126 std::string config_delay;
3127 int config_delay_int = 0;
3128 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3129 config_delay_int = atoi(config_delay.c_str());
3130 m_decoder->setAC3Delay(delay + config_delay_int);
3134 void eDVBServicePlay::setPCMDelay(int delay)
3137 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3139 std::string config_delay;
3140 int config_delay_int = 0;
3141 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3142 config_delay_int = atoi(config_delay.c_str());
3144 config_delay_int = 0;
3145 m_decoder->setPCMDelay(delay + config_delay_int);
3149 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3151 switch(event.type) {
3152 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3153 m_event((iPlayableService*)this, evVideoSizeChanged);
3155 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3156 m_event((iPlayableService*)this, evVideoFramerateChanged);
3158 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3159 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3166 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3172 PyObject *eDVBServicePlay::getStreamingData()
3174 eDVBServicePMTHandler::program program;
3175 if (m_service_handler.getProgramInfo(program))
3180 ePyObject r = program.createPythonObject();
3181 ePtr<iDVBDemux> demux;
3182 if (!m_service_handler.getDataDemux(demux))
3185 if (!demux->getCADemuxID(demux_id))
3186 PutToDict(r, "demux", demux_id);
3193 DEFINE_REF(eDVBServicePlay)
3195 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3199 case iServiceInformation::sTransponderData:
3200 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3204 return iStaticServiceInformation::getInfoObject(ref, w);
3207 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");