1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
106 if (r.type == eServiceReference::idDVB)
108 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
111 case iServiceInformation::sTransponderData:
113 ePtr<eDVBResourceManager> res;
114 if (!eDVBResourceManager::getInstance(res))
116 ePtr<iDVBChannelList> db;
117 if (!res->getChannelList(db))
120 ref.getChannelID(chid);
121 ePtr<iDVBFrontendParameters> feparm;
122 if (!db->getChannelFrontendData(chid, feparm))
125 if (!feparm->getSystem(system))
127 ePyObject dict = PyDict_New();
130 case iDVBFrontend::feSatellite:
132 eDVBFrontendParametersSatellite s;
134 PutSatelliteDataToDict(dict, s);
137 case iDVBFrontend::feTerrestrial:
139 eDVBFrontendParametersTerrestrial t;
141 PutTerrestrialDataToDict(dict, t);
144 case iDVBFrontend::feCable:
146 eDVBFrontendParametersCable c;
148 PutCableDataToDict(dict, c);
152 eDebug("unknown frontend type %d", system);
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
171 ePtr<iDVBChannelList> db;
172 ePtr<eDVBResourceManager> res;
175 if ((err = eDVBResourceManager::getInstance(res)) != 0)
177 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
180 if ((err = res->getChannelList(db)) != 0)
182 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
187 if ((err = db->getBouquet(ref, bouquet)) != 0)
189 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
193 if ( bouquet && bouquet->m_bouquet_name.length() )
195 name = bouquet->m_bouquet_name;
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
204 if (ref.flags & eServiceReference::isGroup)
206 ePtr<iDVBChannelList> db;
207 ePtr<eDVBResourceManager> res;
209 if (eDVBResourceManager::getInstance(res))
211 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
215 if (res->getChannelList(db))
217 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
222 if (db->getBouquet(ref, bouquet))
224 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
228 int prio_order = eDVBFrontend::getTypePriorityOrder();
230 eDVBChannelID chid, chid_ignore;
231 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
234 static unsigned char prio_map[6][3] = {
235 { 3, 2, 1 }, // -S -C -T
236 { 3, 1, 2 }, // -S -T -C
237 { 2, 3, 1 }, // -C -S -T
238 { 1, 3, 2 }, // -C -T -S
239 { 1, 2, 3 }, // -T -C -S
240 { 2, 1, 3 } // -T -S -C
242 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
248 case 30000: // cached DVB-T channel
249 case 1: // DVB-T frontend
250 tmp = prio_map[prio_order][2];
252 case 40000: // cached DVB-C channel
254 tmp = prio_map[prio_order][1];
257 tmp = prio_map[prio_order][0];
262 m_playable_service = *it;
269 m_playable_service = eServiceReference();
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
278 #include <lib/dvb/epgcache.h>
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
282 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
287 DECLARE_REF(eStaticServiceDVBPVRInformation);
288 eServiceReference m_ref;
289 eDVBMetaParser m_parser;
291 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292 RESULT getName(const eServiceReference &ref, std::string &name);
293 int getLength(const eServiceReference &ref);
294 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296 int getInfo(const eServiceReference &ref, int w);
297 std::string getInfoString(const eServiceReference &ref,int w);
298 PyObject *getInfoObject(const eServiceReference &r, int what);
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
306 m_parser.parseFile(ref.path);
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
311 ASSERT(ref == m_ref);
312 if (m_parser.m_name.size())
313 name = m_parser.m_name;
317 size_t n = name.rfind('/');
318 if (n != std::string::npos)
319 name = name.substr(n + 1);
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
326 ASSERT(ref == m_ref);
331 stat(ref.path.c_str(), &s);
333 if (tstools.openFile(ref.path.c_str(), 1))
336 /* check if cached data is still valid */
337 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338 return m_parser.m_length / 90000;
340 /* open again, this time with stream info */
341 if (tstools.openFile(ref.path.c_str()))
344 /* otherwise, re-calc length and update meta file */
346 if (tstools.calcLen(len))
349 m_parser.m_length = len;
350 m_parser.m_filesize = s.st_size;
351 m_parser.updateMeta(ref.path);
352 return m_parser.m_length / 90000;
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
359 case iServiceInformation::sDescription:
360 return iServiceInformation::resIsString;
361 case iServiceInformation::sServiceref:
362 return iServiceInformation::resIsString;
363 case iServiceInformation::sFileSize:
364 return m_parser.m_filesize;
365 case iServiceInformation::sTimeCreate:
366 if (m_parser.m_time_create)
367 return m_parser.m_time_create;
369 return iServiceInformation::resNA;
371 return iServiceInformation::resNA;
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
379 case iServiceInformation::sDescription:
380 return m_parser.m_description;
381 case iServiceInformation::sServiceref:
382 return m_parser.m_ref.toString();
383 case iServiceInformation::sTags:
384 return m_parser.m_tags;
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
394 case iServiceInformation::sFileSize:
395 return PyLong_FromLongLong(m_parser.m_filesize);
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
403 if (!ref.path.empty())
405 ePtr<eServiceEvent> event = new eServiceEvent;
406 std::string filename = ref.path;
407 filename.erase(filename.length()-2, 2);
409 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
421 DECLARE_REF(eDVBPVRServiceOfflineOperations);
422 eServiceReferenceDVB m_ref;
424 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
426 RESULT deleteFromDisk(int simulate);
427 RESULT getListOfFilenames(std::list<std::string> &);
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
443 std::list<std::string> res;
444 if (getListOfFilenames(res))
447 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
449 eDebug("FATAL !! can't get background file eraser");
451 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
453 eDebug("Removing %s...", i->c_str());
455 eraser->erase(i->c_str());
457 ::unlink(i->c_str());
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
467 res.push_back(m_ref.path);
469 // handling for old splitted recordings (enigma 1)
474 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
476 if (stat(buf, &s) < 0)
481 res.push_back(m_ref.path + ".meta");
482 res.push_back(m_ref.path + ".ap");
483 res.push_back(m_ref.path + ".sc");
484 res.push_back(m_ref.path + ".cuts");
485 std::string tmp = m_ref.path;
486 tmp.erase(m_ref.path.length()-3);
487 res.push_back(tmp + ".eit");
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
493 const char *filename = m_ref.path.c_str();
494 eDebug("reindexing %s...", filename);
496 eMPEGStreamInformation info;
497 eMPEGStreamParserTS parser(info);
499 info.startSave(filename);
503 int err = f.open(m_ref.path.c_str(), 0);
508 off_t length = f.length();
509 unsigned char buffer[188*256*4];
512 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513 int r = f.read(offset, buffer, sizeof(buffer));
519 parser.parseData(offset, buffer, r);
528 DEFINE_REF(eServiceFactoryDVB)
530 eServiceFactoryDVB::eServiceFactoryDVB()
532 ePtr<eServiceCenter> sc;
534 eServiceCenter::getPrivInstance(sc);
537 std::list<std::string> extensions;
538 extensions.push_back("ts");
539 extensions.push_back("trp");
540 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
543 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
544 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
547 eServiceFactoryDVB::~eServiceFactoryDVB()
549 ePtr<eServiceCenter> sc;
551 eServiceCenter::getPrivInstance(sc);
553 sc->removeServiceFactory(eServiceFactoryDVB::id);
556 DEFINE_REF(eDVBServiceList);
558 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
562 eDVBServiceList::~eDVBServiceList()
566 RESULT eDVBServiceList::startQuery()
568 ePtr<iDVBChannelList> db;
569 ePtr<eDVBResourceManager> res;
572 if ((err = eDVBResourceManager::getInstance(res)) != 0)
574 eDebug("no resource manager");
577 if ((err = res->getChannelList(db)) != 0)
579 eDebug("no channel list");
583 ePtr<eDVBChannelQuery> q;
585 if (!m_parent.path.empty())
587 eDVBChannelQuery::compile(q, m_parent.path);
590 eDebug("compile query failed");
595 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
597 eDebug("startQuery failed");
604 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
606 eServiceReferenceDVB ref;
611 while (!m_query->getNextResult(ref))
615 list.sort(iListableServiceCompare(this));
620 // The first argument of this function is a format string to specify the order and
621 // the content of the returned list
622 // useable format options are
623 // R = Service Reference (as swig object .. this is very slow)
624 // S = Service Reference (as python string object .. same as ref.toString())
625 // C = Service Reference (as python string object .. same as ref.toCompareString())
626 // N = Service Name (as python string object)
627 // n = Short Service Name (short name brakets used) (as python string object)
628 // when exactly one return value per service is selected in the format string,
629 // then each value is directly a list entry
630 // when more than one value is returned per service, then the list is a list of
632 // unknown format string chars are returned as python None values !
633 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
636 std::list<eServiceReference> tmplist;
639 if (!format || !(retcount=strlen(format)))
640 format = "R"; // just return service reference swig object ...
642 if (!getContent(tmplist, sorted))
644 int services=tmplist.size();
645 ePtr<iStaticServiceInformation> sptr;
646 eServiceCenterPtr service_center;
648 if (strchr(format, 'N') || strchr(format, 'n'))
649 eServiceCenter::getPrivInstance(service_center);
651 ret = PyList_New(services);
652 std::list<eServiceReference>::iterator it(tmplist.begin());
654 for (int cnt=0; cnt < services; ++cnt)
656 eServiceReference &ref=*it++;
657 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
658 for (int i=0; i < retcount; ++i)
663 case 'R': // service reference (swig)object
664 tmp = NEW_eServiceReference(ref);
666 case 'C': // service reference compare string
667 tmp = PyString_FromString(ref.toCompareString().c_str());
669 case 'S': // service reference string
670 tmp = PyString_FromString(ref.toString().c_str());
672 case 'N': // service name
675 service_center->info(ref, sptr);
679 sptr->getName(ref, name);
681 // filter short name brakets
683 while((pos = name.find("\xc2\x86")) != std::string::npos)
685 while((pos = name.find("\xc2\x87")) != std::string::npos)
689 tmp = PyString_FromString(name.c_str());
693 tmp = PyString_FromString("<n/a>");
695 case 'n': // short service name
698 service_center->info(ref, sptr);
702 sptr->getName(ref, name);
703 name = buildShortName(name);
705 tmp = PyString_FromString(name.c_str());
709 tmp = PyString_FromString("<n/a>");
722 PyTuple_SET_ITEM(tuple, i, tmp);
724 PyList_SET_ITEM(ret, cnt, tmp);
728 PyList_SET_ITEM(ret, cnt, tuple);
731 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
734 RESULT eDVBServiceList::getNext(eServiceReference &ref)
739 return m_query->getNextResult((eServiceReferenceDVB&)ref);
742 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
744 if (m_parent.flags & eServiceReference::canDescent) // bouquet
746 ePtr<iDVBChannelList> db;
747 ePtr<eDVBResourceManager> resm;
749 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
752 if (db->getBouquet(m_parent, m_bouquet) != 0)
763 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
767 return m_bouquet->addService(ref, before);
770 RESULT eDVBServiceList::removeService(eServiceReference &ref)
774 return m_bouquet->removeService(ref);
777 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
781 return m_bouquet->moveService(ref, pos);
784 RESULT eDVBServiceList::flushChanges()
788 return m_bouquet->flushChanges();
791 RESULT eDVBServiceList::setListName(const std::string &name)
795 return m_bouquet->setListName(name);
798 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
800 ePtr<eDVBService> service;
801 int r = lookupService(service, ref);
804 // check resources...
805 ptr = new eDVBServicePlay(ref, service);
809 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
811 if (ref.path.empty())
813 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
822 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
824 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
825 if (list->startQuery())
835 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
837 /* is a listable service? */
838 if (ref.flags & eServiceReference::canDescent) // bouquet
840 if ( !ref.name.empty() ) // satellites or providers list
841 ptr = m_StaticServiceDVBInfo;
842 else // a dvb bouquet
843 ptr = m_StaticServiceDVBBouquetInfo;
845 else if (!ref.path.empty()) /* do we have a PVR service? */
846 ptr = new eStaticServiceDVBPVRInformation(ref);
847 else // normal dvb service
849 ePtr<eDVBService> service;
850 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
851 ptr = m_StaticServiceDVBInfo;
853 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
859 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
861 if (ref.path.empty())
867 ptr = new eDVBPVRServiceOfflineOperations(ref);
872 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
874 if (!ref.path.empty()) // playback
876 eDVBMetaParser parser;
877 int ret=parser.parseFile(ref.path);
878 service = new eDVBService;
880 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
884 // TODO: handle the listing itself
885 // if (ref.... == -1) .. return "... bouquets ...";
886 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
888 ePtr<iDVBChannelList> db;
889 ePtr<eDVBResourceManager> res;
892 if ((err = eDVBResourceManager::getInstance(res)) != 0)
894 eDebug("no resource manager");
897 if ((err = res->getChannelList(db)) != 0)
899 eDebug("no channel list");
903 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
904 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
906 eDebug("getService failed!");
914 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
915 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
918 m_is_pvr = !m_reference.path.empty();
920 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
921 m_skipmode = m_fastforward = m_slowmotion = 0;
923 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
924 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
925 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
927 m_cuesheet_changed = 0;
928 m_cutlist_enabled = 1;
930 m_subtitle_widget = 0;
934 m_subtitle_sync_timer = eTimer::create(eApp);
936 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
939 eDVBServicePlay::~eDVBServicePlay()
944 int ret=meta.parseFile(m_reference.path);
948 meta.m_service_data="";
949 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
950 meta.m_service_data += tmp;
952 for (int x=0; x < eDVBService::cacheMax; ++x)
954 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
957 sprintf(tmp, ",c:%02d%04x", x, entry);
958 meta.m_service_data += tmp;
961 meta.updateMeta(m_reference.path);
964 delete m_subtitle_widget;
967 void eDVBServicePlay::gotNewEvent()
971 ePtr<eServiceEvent> m_event_now, m_event_next;
972 getEvent(m_event_now, 0);
973 getEvent(m_event_next, 1);
976 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
978 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
980 m_event((iPlayableService*)this, evUpdatedEventInfo);
983 void eDVBServicePlay::serviceEvent(int event)
985 m_tune_state = event;
989 case eDVBServicePMTHandler::eventTuned:
991 ePtr<iDVBDemux> m_demux;
992 if (!m_service_handler.getDataDemux(m_demux))
994 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
995 int sid = ref.getParentServiceID().get();
997 sid = ref.getServiceID().get();
998 if ( ref.getParentTransportStreamID().get() &&
999 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1000 m_event_handler.startOther(m_demux, sid);
1002 m_event_handler.start(m_demux, sid);
1004 m_event((iPlayableService*)this, evTunedIn);
1007 case eDVBServicePMTHandler::eventNoResources:
1008 case eDVBServicePMTHandler::eventNoPAT:
1009 case eDVBServicePMTHandler::eventNoPATEntry:
1010 case eDVBServicePMTHandler::eventNoPMT:
1011 case eDVBServicePMTHandler::eventTuneFailed:
1012 case eDVBServicePMTHandler::eventMisconfiguration:
1014 eDebug("DVB service failed to tune - error %d", event);
1015 m_event((iPlayableService*)this, evTuneFailed);
1018 case eDVBServicePMTHandler::eventNewProgramInfo:
1020 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1021 if (m_timeshift_enabled)
1022 updateTimeshiftPids();
1023 if (!m_timeshift_active)
1025 if (m_first_program_info & 1 && m_is_pvr)
1027 m_first_program_info &= ~1;
1030 if (!m_timeshift_active)
1031 m_event((iPlayableService*)this, evUpdatedInfo);
1034 case eDVBServicePMTHandler::eventPreStart:
1037 case eDVBServicePMTHandler::eventEOF:
1038 m_event((iPlayableService*)this, evEOF);
1040 case eDVBServicePMTHandler::eventSOF:
1041 m_event((iPlayableService*)this, evSOF);
1046 void eDVBServicePlay::serviceEventTimeshift(int event)
1050 case eDVBServicePMTHandler::eventNewProgramInfo:
1051 eDebug("eventNewProgramInfo TS");
1052 if (m_timeshift_active)
1055 if (m_first_program_info & 2)
1059 eDebug("re-apply slowmotion after timeshift file change");
1060 m_decoder->setSlowMotion(m_slowmotion);
1064 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1066 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1067 if (m_fastforward != 1)
1068 m_decoder->setFastForward(m_fastforward);
1070 m_decoder->setTrickmode();
1074 m_first_program_info &= ~2;
1076 m_event((iPlayableService*)this, evUpdatedInfo);
1079 case eDVBServicePMTHandler::eventSOF:
1081 if (!m_timeshift_file_next.empty())
1083 eDebug("timeshift SOF, switch to next file");
1086 m_first_program_info |= 2;
1088 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1089 r.path = m_timeshift_file_next;
1091 /* free the timeshift service handler, we need the resources */
1092 m_service_handler_timeshift.free();
1096 m_cue->seekTo(0, -1000);
1097 ePtr<iTsSource> source = createTsSource(r);
1098 m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1100 m_event((iPlayableService*)this, evUser+1);
1104 m_event((iPlayableService*)this, evSOF);
1106 case eDVBServicePMTHandler::eventEOF:
1107 if ((!m_is_paused) && (m_skipmode >= 0))
1109 if (m_timeshift_file_next.empty())
1111 eDebug("timeshift EOF, so let's go live");
1116 eDebug("timeshift EOF, switch to next file");
1118 m_first_program_info |= 2;
1120 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1121 r.path = m_timeshift_file_next;
1123 /* free the timeshift service handler, we need the resources */
1124 m_service_handler_timeshift.free();
1127 ePtr<iTsSource> source = createTsSource(r);
1128 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 */
1130 m_event((iPlayableService*)this, evUser+1);
1137 RESULT eDVBServicePlay::start()
1139 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1141 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1142 two (one for decoding, one for data source), as we must be prepared
1143 to start recording from the data demux. */
1146 eDVBMetaParser meta;
1147 if (!meta.parseFile(m_reference.path))
1149 service = meta.m_ref;
1150 service.path = m_reference.path;
1152 m_cue = new eCueSheet();
1155 m_event(this, evStart);
1157 m_first_program_info = 1;
1158 ePtr<iTsSource> source = createTsSource(service);
1159 m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service);
1163 /* inject EIT if there is a stored one */
1164 std::string filename = service.path;
1165 filename.erase(filename.length()-2, 2);
1167 ePtr<eServiceEvent> event = new eServiceEvent;
1168 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1170 ePtr<eServiceEvent> empty;
1171 m_event_handler.inject(event, 0);
1172 m_event_handler.inject(empty, 1);
1174 m_event(this, evStart);
1179 RESULT eDVBServicePlay::stop()
1181 /* add bookmark for last play position */
1184 pts_t play_position, length;
1185 if (!getPlayPosition(play_position))
1187 /* remove last position */
1188 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1190 if (i->what == 3) /* current play position */
1192 m_cue_entries.erase(i);
1193 i = m_cue_entries.begin();
1199 if (getLength(length))
1204 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1206 m_cuesheet_changed = 1;
1210 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1212 m_service_handler_timeshift.free();
1213 m_service_handler.free();
1215 if (m_is_pvr && m_cuesheet_changed)
1218 /* save cuesheet only when main file is accessible. */
1219 if (!::stat(m_reference.path.c_str(), &s))
1222 m_event((iPlayableService*)this, evStopped);
1226 RESULT eDVBServicePlay::setTarget(int target)
1228 m_is_primary = !target;
1232 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1234 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1238 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1240 /* note: we check for timeshift to be enabled,
1241 not neccessary active. if you pause when timeshift
1242 is not active, you should activate it when unpausing */
1243 if ((!m_is_pvr) && (!m_timeshift_enabled))
1253 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1255 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1256 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1257 setFastForward_internal(0);
1260 m_slowmotion = ratio;
1261 return m_decoder->setSlowMotion(ratio);
1267 RESULT eDVBServicePlay::setFastForward(int ratio)
1269 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1271 return setFastForward_internal(ratio);
1274 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1276 int skipmode, ffratio, ret = 0;
1283 } else if (ratio > 0)
1291 } else // if (ratio < 0)
1297 if (m_skipmode != skipmode)
1299 eDebug("setting cue skipmode to %d", skipmode);
1301 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1304 m_skipmode = skipmode;
1307 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1309 m_fastforward = ffratio;
1315 ; /* return m_decoder->play(); is done in caller*/
1316 else if (ffratio != 1)
1317 ret = m_decoder->setFastForward(ffratio);
1319 ret = m_decoder->setTrickmode();
1322 eDebug("final seek after trickplay ret %d", seekTo(pos));
1327 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1329 if (m_is_pvr || m_timeshift_enabled)
1339 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1340 RESULT eDVBServicePlay::getLength(pts_t &len)
1342 ePtr<iDVBPVRChannel> pvr_channel;
1344 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1347 return pvr_channel->getLength(len);
1350 RESULT eDVBServicePlay::pause()
1352 eDebug("eDVBServicePlay::pause");
1353 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1358 return m_decoder->pause();
1363 RESULT eDVBServicePlay::unpause()
1365 eDebug("eDVBServicePlay::unpause");
1366 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1371 return m_decoder->play();
1376 RESULT eDVBServicePlay::seekTo(pts_t to)
1378 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1380 if (!m_decode_demux)
1383 ePtr<iDVBPVRChannel> pvr_channel;
1385 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1391 m_cue->seekTo(0, to);
1392 m_dvb_subtitle_pages.clear();
1393 m_subtitle_pages.clear();
1398 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1400 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1402 if (!m_decode_demux)
1405 ePtr<iDVBPVRChannel> pvr_channel;
1407 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1412 /* HACK until we have skip-AP api */
1413 if ((to > 0) && (to < 100))
1421 m_cue->seekTo(mode, to);
1422 m_dvb_subtitle_pages.clear();
1423 m_subtitle_pages.clear();
1427 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1429 ePtr<iDVBPVRChannel> pvr_channel;
1431 if (!m_decode_demux)
1434 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1439 /* if there is a decoder, use audio or video PTS */
1442 r = m_decoder->getPTS(0, pos);
1448 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1451 RESULT eDVBServicePlay::setTrickmode(int trick)
1453 /* currently unimplemented */
1457 RESULT eDVBServicePlay::isCurrentlySeekable()
1462 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1463 if (m_decoder->getVideoProgressive() == -1)
1469 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1475 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1481 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1487 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1493 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1499 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1502 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1503 (m_timeshift_enabled || !m_is_pvr))
1505 if (!m_timeshift_enabled)
1507 /* query config path */
1509 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1510 eDebug("could not query ts path from config");
1514 /* we need enough diskspace */
1516 if (statfs(tspath.c_str(), &fs) < 0)
1518 eDebug("statfs failed!");
1522 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1524 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1534 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1545 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1551 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1557 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1563 RESULT eDVBServicePlay::getName(std::string &name)
1567 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1568 return i->getName(m_reference, name);
1570 else if (m_dvb_service)
1572 m_dvb_service->getName(m_reference, name);
1576 else if (!m_reference.name.empty())
1577 eStaticServiceDVBInformation().getName(m_reference, name);
1579 name = "DVB service";
1583 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1585 return m_event_handler.getEvent(evt, nownext);
1588 int eDVBServicePlay::getInfo(int w)
1590 eDVBServicePMTHandler::program program;
1593 return resIsPyObject;
1595 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1597 int no_program_info = 0;
1599 if (h.getProgramInfo(program))
1600 no_program_info = 1;
1606 return m_decoder->getVideoHeight();
1610 return m_decoder->getVideoWidth();
1614 return m_decoder->getVideoFrameRate();
1618 return m_decoder->getVideoProgressive();
1624 aspect = m_decoder->getVideoAspect();
1625 if (aspect == -1 && no_program_info)
1627 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1629 ePtr<eServiceEvent> evt;
1630 if (!m_event_handler.getEvent(evt, 0))
1632 ePtr<eComponentData> data;
1633 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1635 if ( data->getStreamContent() == 1 )
1637 switch(data->getComponentType())
1640 case 1: // 4:3 SD PAL
1642 case 3: // 16:9 SD PAL
1643 case 4: // > 16:9 PAL
1644 case 5: // 4:3 SD NTSC
1646 case 7: // 16:9 SD NTSC
1647 case 8: // > 16:9 NTSC
1650 case 9: // 4:3 HD PAL
1652 case 0xB: // 16:9 HD PAL
1653 case 0xC: // > 16:9 HD PAL
1654 case 0xD: // 4:3 HD NTSC
1656 case 0xF: // 16:9 HD NTSC
1657 case 0x10: // > 16:9 HD PAL
1658 return data->getComponentType();
1668 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1672 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1676 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1677 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1681 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1684 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1688 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1692 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1696 if (no_program_info) return -1; return program.pcrPid;
1697 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1698 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1699 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1700 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1701 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1702 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1703 case sProvider: if (!m_dvb_service) return -1; return -2;
1704 case sServiceref: return resIsString;
1705 case sDVBState: return m_tune_state;
1712 std::string eDVBServicePlay::getInfoString(int w)
1717 if (!m_dvb_service) return "";
1718 return m_dvb_service->m_provider_name;
1720 return m_reference.toString();
1724 return iServiceInformation::getInfoString(w);
1727 PyObject *eDVBServicePlay::getInfoObject(int w)
1732 return m_service_handler.getCaIds();
1733 case sTransponderData:
1734 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1738 return iServiceInformation::getInfoObject(w);
1741 int eDVBServicePlay::getNumberOfTracks()
1743 eDVBServicePMTHandler::program program;
1744 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1745 if (h.getProgramInfo(program))
1747 return program.audioStreams.size();
1750 int eDVBServicePlay::getCurrentTrack()
1752 eDVBServicePMTHandler::program program;
1753 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1754 if (h.getProgramInfo(program))
1757 int max = program.audioStreams.size();
1760 for (i = 0; i < max; ++i)
1761 if (program.audioStreams[i].pid == m_current_audio_pid)
1767 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1769 int ret = selectAudioStream(i);
1771 if (m_decoder->set())
1777 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1779 eDVBServicePMTHandler::program program;
1780 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1782 if (h.getProgramInfo(program))
1785 if (i >= program.audioStreams.size())
1788 info.m_pid = program.audioStreams[i].pid;
1790 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1791 info.m_description = "MPEG";
1792 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1793 info.m_description = "AC3";
1794 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1795 info.m_description = "AAC";
1796 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1797 info.m_description = "AAC-HE";
1798 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1799 info.m_description = "DTS";
1801 info.m_description = "???";
1803 if (program.audioStreams[i].component_tag != -1)
1805 ePtr<eServiceEvent> evt;
1806 if (!m_event_handler.getEvent(evt, 0))
1808 ePtr<eComponentData> data;
1809 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1810 info.m_language = data->getText();
1814 if (info.m_language.empty())
1815 info.m_language = program.audioStreams[i].language_code;
1820 int eDVBServicePlay::selectAudioStream(int i)
1822 eDVBServicePMTHandler::program program;
1823 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1824 pts_t position = -1;
1826 if (h.getProgramInfo(program))
1829 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1837 stream = program.defaultAudioStream;
1839 int apid = -1, apidtype = -1;
1841 if (((unsigned int)stream) < program.audioStreams.size())
1843 apid = program.audioStreams[stream].pid;
1844 apidtype = program.audioStreams[stream].type;
1847 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1848 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1850 m_current_audio_pid = apid;
1852 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1854 eDebug("set audio pid failed");
1859 eDebug("seekTo ret %d", seekTo(position));
1863 /* 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 */
1864 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1866 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1868 rdsPid = program.audioStreams[stream].rdsPid;
1869 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1872 ePtr<iDVBDemux> data_demux;
1873 if (!h.getDataDemux(data_demux))
1875 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1876 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1877 m_rds_decoder->start(rdsPid);
1882 /* store new pid as default only when:
1883 a.) we have an entry in the service db for the current service,
1884 b.) we are not playing back something,
1885 c.) we are not selecting the default entry. (we wouldn't change
1886 anything in the best case, or destroy the default setting in
1887 case the real default is not yet available.)
1889 if (m_dvb_service && ((i != -1)
1890 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1892 if (apidtype == eDVBAudio::aMPEG)
1894 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1895 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1897 else if (apidtype == eDVBAudio::aAC3)
1899 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1900 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1904 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1905 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1909 h.resetCachedProgram();
1914 int eDVBServicePlay::getCurrentChannel()
1916 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1919 RESULT eDVBServicePlay::selectChannel(int i)
1921 if (i < LEFT || i > RIGHT || i == STEREO)
1924 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1926 m_decoder->setAudioChannel(i);
1930 std::string eDVBServicePlay::getText(int x)
1936 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1938 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1943 void eDVBServicePlay::rdsDecoderEvent(int what)
1947 case eDVBRdsDecoder::RadioTextChanged:
1948 m_event((iPlayableService*)this, evUpdatedRadioText);
1950 case eDVBRdsDecoder::RtpTextChanged:
1951 m_event((iPlayableService*)this, evUpdatedRtpText);
1953 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1954 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1956 case eDVBRdsDecoder::RecvRassSlidePic:
1957 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1962 void eDVBServicePlay::showRassSlidePicture()
1968 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1969 if (rass_slide_pic.length())
1970 m_decoder->showSinglePic(rass_slide_pic.c_str());
1972 eDebug("empty filename for rass slide picture received!!");
1975 eDebug("no MPEG Decoder to show iframes avail");
1978 eDebug("showRassSlidePicture called.. but not decoder");
1981 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1987 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1988 if (rass_interactive_pic.length())
1989 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1991 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1994 eDebug("no MPEG Decoder to show iframes avail");
1997 eDebug("showRassInteractivePic called.. but not decoder");
2000 ePyObject eDVBServicePlay::getRassInteractiveMask()
2003 return m_rds_decoder->getRassPictureMask();
2007 int eDVBServiceBase::getFrontendInfo(int w)
2009 eUsePtr<iDVBChannel> channel;
2010 if(m_service_handler.getChannel(channel))
2012 ePtr<iDVBFrontend> fe;
2013 if(channel->getFrontend(fe))
2015 return fe->readFrontendData(w);
2018 PyObject *eDVBServiceBase::getFrontendData()
2020 ePyObject ret = PyDict_New();
2023 eUsePtr<iDVBChannel> channel;
2024 if(!m_service_handler.getChannel(channel))
2026 ePtr<iDVBFrontend> fe;
2027 if(!channel->getFrontend(fe))
2028 fe->getFrontendData(ret);
2036 PyObject *eDVBServiceBase::getFrontendStatus()
2038 ePyObject ret = PyDict_New();
2041 eUsePtr<iDVBChannel> channel;
2042 if(!m_service_handler.getChannel(channel))
2044 ePtr<iDVBFrontend> fe;
2045 if(!channel->getFrontend(fe))
2046 fe->getFrontendStatus(ret);
2054 PyObject *eDVBServiceBase::getTransponderData(bool original)
2056 ePyObject ret = PyDict_New();
2059 eUsePtr<iDVBChannel> channel;
2060 if(!m_service_handler.getChannel(channel))
2062 ePtr<iDVBFrontend> fe;
2063 if(!channel->getFrontend(fe))
2064 fe->getTransponderData(ret, original);
2072 PyObject *eDVBServiceBase::getAll(bool original)
2074 ePyObject ret = getTransponderData(original);
2077 eUsePtr<iDVBChannel> channel;
2078 if(!m_service_handler.getChannel(channel))
2080 ePtr<iDVBFrontend> fe;
2081 if(!channel->getFrontend(fe))
2083 fe->getFrontendData(ret);
2084 fe->getFrontendStatus(ret);
2091 int eDVBServicePlay::getNumberOfSubservices()
2093 ePtr<eServiceEvent> evt;
2094 if (!m_event_handler.getEvent(evt, 0))
2095 return evt->getNumOfLinkageServices();
2099 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2101 ePtr<eServiceEvent> evt;
2102 if (!m_event_handler.getEvent(evt, 0))
2104 if (!evt->getLinkageService(sub, m_reference, n))
2107 sub.type=eServiceReference::idInvalid;
2111 RESULT eDVBServicePlay::startTimeshift()
2113 ePtr<iDVBDemux> demux;
2115 eDebug("Start timeshift!");
2117 if (m_timeshift_enabled)
2120 /* start recording with the data demux. */
2121 if (m_service_handler.getDataDemux(demux))
2124 demux->createTSRecorder(m_record);
2129 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2130 eDebug("could not query ts path");
2133 tspath.append("/timeshift.XXXXXX");
2135 templ = new char[tspath.length() + 1];
2136 strcpy(templ, tspath.c_str());
2138 m_timeshift_fd = mkstemp(templ);
2139 m_timeshift_file = std::string(templ);
2141 eDebug("recording to %s", templ);
2145 if (m_timeshift_fd < 0)
2151 m_record->setTargetFD(m_timeshift_fd);
2153 m_timeshift_enabled = 1;
2155 updateTimeshiftPids();
2161 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2163 if (!m_timeshift_enabled)
2169 m_timeshift_enabled = 0;
2174 close(m_timeshift_fd);
2175 eDebug("remove timeshift file");
2176 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2181 int eDVBServicePlay::isTimeshiftActive()
2183 return m_timeshift_enabled && m_timeshift_active;
2186 RESULT eDVBServicePlay::activateTimeshift()
2188 if (!m_timeshift_enabled)
2191 if (!m_timeshift_active)
2193 switchToTimeshift();
2200 PyObject *eDVBServicePlay::getCutList()
2202 ePyObject list = PyList_New(0);
2204 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2206 ePyObject tuple = PyTuple_New(2);
2207 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2208 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2209 PyList_Append(list, tuple);
2216 void eDVBServicePlay::setCutList(ePyObject list)
2218 if (!PyList_Check(list))
2220 int size = PyList_Size(list);
2223 m_cue_entries.clear();
2225 for (i=0; i<size; ++i)
2227 ePyObject tuple = PyList_GET_ITEM(list, i);
2228 if (!PyTuple_Check(tuple))
2230 eDebug("non-tuple in cutlist");
2233 if (PyTuple_Size(tuple) != 2)
2235 eDebug("cutlist entries need to be a 2-tuple");
2238 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2239 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2241 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2244 pts_t pts = PyLong_AsLongLong(ppts);
2245 int type = PyInt_AsLong(ptype);
2246 m_cue_entries.insert(cueEntry(pts, type));
2247 eDebug("adding %08llx, %d", pts, type);
2249 m_cuesheet_changed = 1;
2251 cutlistToCuesheet();
2252 m_event((iPlayableService*)this, evCuesheetChanged);
2255 void eDVBServicePlay::setCutListEnable(int enable)
2257 m_cutlist_enabled = enable;
2258 cutlistToCuesheet();
2261 void eDVBServicePlay::updateTimeshiftPids()
2266 eDVBServicePMTHandler::program program;
2267 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2269 if (h.getProgramInfo(program))
2273 std::set<int> pids_to_record;
2274 pids_to_record.insert(0); // PAT
2275 if (program.pmtPid != -1)
2276 pids_to_record.insert(program.pmtPid); // PMT
2278 if (program.textPid != -1)
2279 pids_to_record.insert(program.textPid); // Videotext
2281 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2282 i(program.videoStreams.begin());
2283 i != program.videoStreams.end(); ++i)
2284 pids_to_record.insert(i->pid);
2286 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2287 i(program.audioStreams.begin());
2288 i != program.audioStreams.end(); ++i)
2289 pids_to_record.insert(i->pid);
2291 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2292 i(program.subtitleStreams.begin());
2293 i != program.subtitleStreams.end(); ++i)
2294 pids_to_record.insert(i->pid);
2296 std::set<int> new_pids, obsolete_pids;
2298 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2299 m_pids_active.begin(), m_pids_active.end(),
2300 std::inserter(new_pids, new_pids.begin()));
2302 std::set_difference(
2303 m_pids_active.begin(), m_pids_active.end(),
2304 pids_to_record.begin(), pids_to_record.end(),
2305 std::inserter(new_pids, new_pids.begin())
2308 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2309 m_record->addPID(*i);
2311 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2312 m_record->removePID(*i);
2316 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2318 m_timeshift_file_next = f;
2322 void eDVBServicePlay::switchToLive()
2324 if (!m_timeshift_active)
2327 eDebug("SwitchToLive");
2331 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2333 /* free the timeshift service handler, we need the resources */
2334 m_service_handler_timeshift.free();
2336 updateDecoder(true);
2339 void eDVBServicePlay::resetTimeshift(int start)
2344 m_teletext_parser = 0;
2346 m_subtitle_parser = 0;
2347 m_new_subtitle_page_connection = 0;
2348 m_new_dvb_subtitle_page_connection = 0;
2349 m_rds_decoder_event_connection = 0;
2350 m_video_event_connection = 0;
2351 m_timeshift_changed = 1;
2352 m_timeshift_file_next.clear();
2356 m_cue = new eCueSheet();
2357 m_timeshift_active = 1;
2360 m_timeshift_active = 0;
2363 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2365 eRawFile *f = new eRawFile();
2366 f->open(ref.path.c_str());
2367 return ePtr<iTsSource>(f);
2370 void eDVBServicePlay::switchToTimeshift()
2372 if (m_timeshift_active)
2377 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2378 r.path = m_timeshift_file;
2380 m_cue->seekTo(0, -1000);
2382 ePtr<iTsSource> source = createTsSource(r);
2383 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 */
2385 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2387 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2390 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2392 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2393 bool mustPlay = false;
2395 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2397 eDVBServicePMTHandler::program program;
2398 if (h.getProgramInfo(program))
2399 eDebug("getting program info failed.");
2402 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2403 if (!program.videoStreams.empty())
2405 eDebugNoNewLine(" (");
2406 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2407 i(program.videoStreams.begin());
2408 i != program.videoStreams.end(); ++i)
2415 if (i != program.videoStreams.begin())
2416 eDebugNoNewLine(", ");
2417 eDebugNoNewLine("%04x", i->pid);
2419 eDebugNoNewLine(")");
2421 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2422 if (!program.audioStreams.empty())
2424 eDebugNoNewLine(" (");
2425 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2426 i(program.audioStreams.begin());
2427 i != program.audioStreams.end(); ++i)
2429 if (i != program.audioStreams.begin())
2430 eDebugNoNewLine(", ");
2431 eDebugNoNewLine("%04x", i->pid);
2433 eDebugNoNewLine(")");
2435 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2436 pcrpid = program.pcrPid;
2437 eDebug(", and the text pid is %04x", program.textPid);
2438 tpid = program.textPid;
2443 h.getDecodeDemux(m_decode_demux);
2446 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2448 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2451 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2452 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2453 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2454 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2455 if (m_timeshift_changed)
2457 ePyObject subs = getCachedSubtitle();
2458 if (subs != Py_None)
2460 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2461 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2462 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2463 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2464 if (type == 0) // dvb
2465 m_subtitle_parser->start(pid, comp_page, anc_page);
2466 else if (type == 1) // ttx
2467 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2474 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2478 m_timeshift_changed = 0;
2482 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2485 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2486 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2487 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2491 eServiceReferenceDVB ref;
2492 m_service_handler.getServiceReference(ref);
2493 eServiceReferenceDVB parent = ref.getParentServiceReference();
2498 ePtr<eDVBResourceManager> res_mgr;
2499 if (!eDVBResourceManager::getInstance(res_mgr))
2501 ePtr<iDVBChannelList> db;
2502 if (!res_mgr->getChannelList(db))
2504 ePtr<eDVBService> origService;
2505 if (!db->getService(parent, origService))
2507 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2508 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2515 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2516 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2518 m_decoder->setVideoPID(vpid, vpidtype);
2519 selectAudioStream();
2521 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2522 m_decoder->setSyncPCR(pcrpid);
2524 m_decoder->setSyncPCR(-1);
2528 m_decoder->setTextPID(tpid);
2529 m_teletext_parser->start(program.textPid);
2532 if (vpid > 0 && vpid < 0x2000)
2536 std::string radio_pic;
2537 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2538 m_decoder->setRadioPic(radio_pic);
2546 m_decoder->setAudioChannel(achannel);
2548 /* don't worry about non-existing services, nor pvr services */
2551 /* (audio pid will be set in selectAudioTrack */
2552 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2553 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2554 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2555 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2557 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2558 sendSeekableStateChanged = true;
2560 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2562 if (sendSeekableStateChanged)
2563 m_event((iPlayableService*)this, evSeekableStatusChanged);
2566 void eDVBServicePlay::loadCuesheet()
2568 std::string filename = m_reference.path + ".cuts";
2570 m_cue_entries.clear();
2572 FILE *f = fopen(filename.c_str(), "rb");
2576 eDebug("loading cuts..");
2579 unsigned long long where;
2582 if (!fread(&where, sizeof(where), 1, f))
2584 if (!fread(&what, sizeof(what), 1, f))
2587 #if BYTE_ORDER == LITTLE_ENDIAN
2588 where = bswap_64(where);
2595 m_cue_entries.insert(cueEntry(where, what));
2598 eDebug("%d entries", m_cue_entries.size());
2600 eDebug("cutfile not found!");
2602 m_cuesheet_changed = 0;
2603 cutlistToCuesheet();
2604 m_event((iPlayableService*)this, evCuesheetChanged);
2607 void eDVBServicePlay::saveCuesheet()
2609 std::string filename = m_reference.path + ".cuts";
2611 FILE *f = fopen(filename.c_str(), "wb");
2615 unsigned long long where;
2618 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2620 #if BYTE_ORDER == BIG_ENDIAN
2623 where = bswap_64(i->where);
2625 what = htonl(i->what);
2626 fwrite(&where, sizeof(where), 1, f);
2627 fwrite(&what, sizeof(what), 1, f);
2633 m_cuesheet_changed = 0;
2636 void eDVBServicePlay::cutlistToCuesheet()
2640 eDebug("no cue sheet");
2645 if (!m_cutlist_enabled)
2647 m_cue->commitSpans();
2648 eDebug("cutlists were disabled");
2652 pts_t in = 0, out = 0, length = 0;
2656 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2658 int have_any_span = 0;
2662 if (i == m_cue_entries.end())
2664 if (!have_any_span && !in)
2668 if (i->what == 0) /* in */
2672 } else if (i->what == 1) /* out */
2674 else /* mark (2) or last play position (3) */
2693 m_cue->addSourceSpan(in, out);
2699 if (i == m_cue_entries.end())
2702 m_cue->commitSpans();
2705 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2707 if (m_subtitle_widget)
2708 disableSubtitles(parent);
2711 int tuplesize = PyTuple_Size(tuple);
2714 if (!PyTuple_Check(tuple))
2720 entry = PyTuple_GET_ITEM(tuple, 0);
2722 if (!PyInt_Check(entry))
2725 type = PyInt_AsLong(entry);
2727 if (type == 1) // teletext subtitles
2729 int page, magazine, pid;
2733 if (!m_teletext_parser)
2735 eDebug("enable teletext subtitles.. no parser !!!");
2739 entry = PyTuple_GET_ITEM(tuple, 1);
2740 if (!PyInt_Check(entry))
2742 pid = PyInt_AsLong(entry);
2744 entry = PyTuple_GET_ITEM(tuple, 2);
2745 if (!PyInt_Check(entry))
2747 page = PyInt_AsLong(entry);
2749 entry = PyTuple_GET_ITEM(tuple, 3);
2750 if (!PyInt_Check(entry))
2752 magazine = PyInt_AsLong(entry);
2754 m_subtitle_widget = new eSubtitleWidget(parent);
2755 m_subtitle_widget->resize(parent->size()); /* full size */
2756 m_teletext_parser->setPageAndMagazine(page, magazine);
2758 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2762 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2763 if (!m_subtitle_parser)
2765 eDebug("enable dvb subtitles.. no parser !!!");
2771 entry = PyTuple_GET_ITEM(tuple, 1);
2772 if (!PyInt_Check(entry))
2774 pid = PyInt_AsLong(entry);
2776 entry = PyTuple_GET_ITEM(tuple, 2);
2777 if (!PyInt_Check(entry))
2779 composition_page_id = PyInt_AsLong(entry);
2781 entry = PyTuple_GET_ITEM(tuple, 3);
2782 if (!PyInt_Check(entry))
2784 ancillary_page_id = PyInt_AsLong(entry);
2786 m_subtitle_widget = new eSubtitleWidget(parent);
2787 m_subtitle_widget->resize(parent->size()); /* full size */
2788 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2790 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2796 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2797 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2798 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2802 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2804 delete m_subtitle_widget;
2805 m_subtitle_widget = 0;
2806 if (m_subtitle_parser)
2808 m_subtitle_parser->stop();
2809 m_dvb_subtitle_pages.clear();
2811 if (m_teletext_parser)
2813 m_teletext_parser->setPageAndMagazine(-1, -1);
2814 m_subtitle_pages.clear();
2817 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2821 PyObject *eDVBServicePlay::getCachedSubtitle()
2825 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2828 unsigned int data = (unsigned int)tmp;
2829 int pid = (data&0xFFFF0000)>>16;
2830 ePyObject tuple = PyTuple_New(4);
2831 eDVBServicePMTHandler::program program;
2832 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2833 if (!h.getProgramInfo(program))
2835 if (program.textPid==pid) // teletext
2836 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2838 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2839 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2840 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2841 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2849 PyObject *eDVBServicePlay::getSubtitleList()
2851 if (!m_teletext_parser)
2854 ePyObject l = PyList_New(0);
2855 std::set<int> added_ttx_pages;
2857 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2858 m_teletext_parser->m_found_subtitle_pages;
2860 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2861 eDVBServicePMTHandler::program program;
2862 if (h.getProgramInfo(program))
2863 eDebug("getting program info failed.");
2866 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2867 it != program.subtitleStreams.end(); ++it)
2869 switch(it->subtitling_type)
2871 case 0x01: // ebu teletext subtitles
2873 int page_number = it->teletext_page_number & 0xFF;
2874 int magazine_number = it->teletext_magazine_number & 7;
2875 int hash = magazine_number << 8 | page_number;
2876 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2878 ePyObject tuple = PyTuple_New(5);
2879 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2880 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2881 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2882 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2883 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2884 PyList_Append(l, tuple);
2886 added_ttx_pages.insert(hash);
2891 case 0x20 ... 0x23: // dvb subtitles
2893 ePyObject tuple = PyTuple_New(5);
2894 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2895 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2896 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2897 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2898 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2899 PyList_Insert(l, 0, tuple);
2907 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2908 it != subs.end(); ++it)
2910 int page_number = it->teletext_page_number & 0xFF;
2911 int magazine_number = it->teletext_magazine_number & 7;
2912 int hash = magazine_number << 8 | page_number;
2913 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2915 ePyObject tuple = PyTuple_New(5);
2916 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2917 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2918 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2919 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2920 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2921 PyList_Append(l, tuple);
2929 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2931 if (m_subtitle_widget)
2935 m_decoder->getPTS(0, pos);
2936 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2937 m_subtitle_pages.push_back(page);
2938 checkSubtitleTiming();
2942 void eDVBServicePlay::checkSubtitleTiming()
2944 eDebug("checkSubtitleTiming");
2945 if (!m_subtitle_widget)
2949 enum { TELETEXT, DVB } type;
2950 eDVBTeletextSubtitlePage page;
2951 eDVBSubtitlePage dvb_page;
2953 if (!m_subtitle_pages.empty())
2955 page = m_subtitle_pages.front();
2957 show_time = page.m_pts;
2959 else if (!m_dvb_subtitle_pages.empty())
2961 dvb_page = m_dvb_subtitle_pages.front();
2963 show_time = dvb_page.m_show_time;
2971 m_decoder->getPTS(0, pos);
2973 eDebug("%lld %lld", pos, show_time);
2974 int diff = show_time - pos;
2975 if (type == TELETEXT && !page.m_have_pts)
2977 eDebug("ttx subtitle page without pts... immediate show");
2982 eDebug("[late (%d ms)]", -diff / 90);
2985 if (abs(diff) > 1800000)
2987 eDebug("[invalid]... immediate show!");
2992 if (type == TELETEXT)
2994 eDebug("display teletext subtitle page %lld", show_time);
2995 m_subtitle_widget->setPage(page);
2996 m_subtitle_pages.pop_front();
3000 eDebug("display dvb subtitle Page %lld", show_time);
3001 m_subtitle_widget->setPage(dvb_page);
3002 m_dvb_subtitle_pages.pop_front();
3006 eDebug("start subtitle delay %d", diff / 90);
3007 m_subtitle_sync_timer->start(diff / 90, 1);
3013 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3015 if (m_subtitle_widget)
3019 m_decoder->getPTS(0, pos);
3020 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3021 m_dvb_subtitle_pages.push_back(p);
3022 checkSubtitleTiming();
3026 int eDVBServicePlay::getAC3Delay()
3029 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3031 return m_decoder->getAC3Delay();
3036 int eDVBServicePlay::getPCMDelay()
3039 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3041 return m_decoder->getPCMDelay();
3046 void eDVBServicePlay::setAC3Delay(int delay)
3049 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3051 std::string config_delay;
3052 int config_delay_int = 0;
3053 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3054 config_delay_int = atoi(config_delay.c_str());
3055 m_decoder->setAC3Delay(delay + config_delay_int);
3059 void eDVBServicePlay::setPCMDelay(int delay)
3062 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3064 std::string config_delay;
3065 int config_delay_int = 0;
3066 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3067 config_delay_int = atoi(config_delay.c_str());
3069 config_delay_int = 0;
3070 m_decoder->setPCMDelay(delay + config_delay_int);
3074 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3076 switch(event.type) {
3077 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3078 m_event((iPlayableService*)this, evVideoSizeChanged);
3080 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3081 m_event((iPlayableService*)this, evVideoFramerateChanged);
3083 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3084 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3091 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3097 PyObject *eDVBServicePlay::getStreamingData()
3099 eDVBServicePMTHandler::program program;
3100 if (m_service_handler.getProgramInfo(program))
3105 ePyObject r = program.createPythonObject();
3106 ePtr<iDVBDemux> demux;
3107 if (!m_service_handler.getDataDemux(demux))
3110 if (!demux->getCADemuxID(demux_id))
3111 PutToDict(r, "demux", demux_id);
3118 DEFINE_REF(eDVBServicePlay)
3120 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3124 case iServiceInformation::sTransponderData:
3125 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3129 return iStaticServiceInformation::getInfoObject(ref, w);
3132 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");