1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
106 if (r.type == eServiceReference::idDVB)
108 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
111 case iServiceInformation::sTransponderData:
113 ePtr<eDVBResourceManager> res;
114 if (!eDVBResourceManager::getInstance(res))
116 ePtr<iDVBChannelList> db;
117 if (!res->getChannelList(db))
120 ref.getChannelID(chid);
121 ePtr<iDVBFrontendParameters> feparm;
122 if (!db->getChannelFrontendData(chid, feparm))
125 if (!feparm->getSystem(system))
127 ePyObject dict = PyDict_New();
130 case iDVBFrontend::feSatellite:
132 eDVBFrontendParametersSatellite s;
134 PutSatelliteDataToDict(dict, s);
137 case iDVBFrontend::feTerrestrial:
139 eDVBFrontendParametersTerrestrial t;
141 PutTerrestrialDataToDict(dict, t);
144 case iDVBFrontend::feCable:
146 eDVBFrontendParametersCable c;
148 PutCableDataToDict(dict, c);
152 eDebug("unknown frontend type %d", system);
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
171 ePtr<iDVBChannelList> db;
172 ePtr<eDVBResourceManager> res;
175 if ((err = eDVBResourceManager::getInstance(res)) != 0)
177 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
180 if ((err = res->getChannelList(db)) != 0)
182 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
187 if ((err = db->getBouquet(ref, bouquet)) != 0)
189 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
193 if ( bouquet && bouquet->m_bouquet_name.length() )
195 name = bouquet->m_bouquet_name;
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
204 if (ref.flags & eServiceReference::isGroup)
206 ePtr<iDVBChannelList> db;
207 ePtr<eDVBResourceManager> res;
209 if (eDVBResourceManager::getInstance(res))
211 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
215 if (res->getChannelList(db))
217 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
222 if (db->getBouquet(ref, bouquet))
224 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
228 int prio_order = eDVBFrontend::getTypePriorityOrder();
230 eDVBChannelID chid, chid_ignore;
231 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
234 static unsigned char prio_map[6][3] = {
235 { 3, 2, 1 }, // -S -C -T
236 { 3, 1, 2 }, // -S -T -C
237 { 2, 3, 1 }, // -C -S -T
238 { 1, 3, 2 }, // -C -T -S
239 { 1, 2, 3 }, // -T -C -S
240 { 2, 1, 3 } // -T -S -C
242 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
248 case 30000: // cached DVB-T channel
249 case 1: // DVB-T frontend
250 tmp = prio_map[prio_order][2];
252 case 40000: // cached DVB-C channel
254 tmp = prio_map[prio_order][1];
257 tmp = prio_map[prio_order][0];
262 m_playable_service = *it;
269 m_playable_service = eServiceReference();
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
278 #include <lib/dvb/epgcache.h>
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
282 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
287 DECLARE_REF(eStaticServiceDVBPVRInformation);
288 eServiceReference m_ref;
289 eDVBMetaParser m_parser;
291 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292 RESULT getName(const eServiceReference &ref, std::string &name);
293 int getLength(const eServiceReference &ref);
294 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296 int getInfo(const eServiceReference &ref, int w);
297 std::string getInfoString(const eServiceReference &ref,int w);
298 PyObject *getInfoObject(const eServiceReference &r, int what);
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
306 m_parser.parseFile(ref.path);
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
311 ASSERT(ref == m_ref);
312 if (m_parser.m_name.size())
313 name = m_parser.m_name;
317 size_t n = name.rfind('/');
318 if (n != std::string::npos)
319 name = name.substr(n + 1);
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
326 ASSERT(ref == m_ref);
331 stat(ref.path.c_str(), &s);
333 if (tstools.openFile(ref.path.c_str(), 1))
336 /* check if cached data is still valid */
337 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338 return m_parser.m_length / 90000;
340 /* open again, this time with stream info */
341 if (tstools.openFile(ref.path.c_str()))
344 /* otherwise, re-calc length and update meta file */
346 if (tstools.calcLen(len))
349 m_parser.m_length = len;
350 m_parser.m_filesize = s.st_size;
351 m_parser.updateMeta(ref.path);
352 return m_parser.m_length / 90000;
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
359 case iServiceInformation::sDescription:
360 return iServiceInformation::resIsString;
361 case iServiceInformation::sServiceref:
362 return iServiceInformation::resIsString;
363 case iServiceInformation::sFileSize:
364 return m_parser.m_filesize;
365 case iServiceInformation::sTimeCreate:
366 if (m_parser.m_time_create)
367 return m_parser.m_time_create;
369 return iServiceInformation::resNA;
371 return iServiceInformation::resNA;
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
379 case iServiceInformation::sDescription:
380 return m_parser.m_description;
381 case iServiceInformation::sServiceref:
382 return m_parser.m_ref.toString();
383 case iServiceInformation::sTags:
384 return m_parser.m_tags;
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
394 case iServiceInformation::sFileSize:
395 return PyLong_FromLongLong(m_parser.m_filesize);
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
403 if (!ref.path.empty())
405 ePtr<eServiceEvent> event = new eServiceEvent;
406 std::string filename = ref.path;
407 filename.erase(filename.length()-2, 2);
409 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
421 DECLARE_REF(eDVBPVRServiceOfflineOperations);
422 eServiceReferenceDVB m_ref;
424 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
426 RESULT deleteFromDisk(int simulate);
427 RESULT getListOfFilenames(std::list<std::string> &);
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
443 std::list<std::string> res;
444 if (getListOfFilenames(res))
447 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
449 eDebug("FATAL !! can't get background file eraser");
451 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
453 eDebug("Removing %s...", i->c_str());
455 eraser->erase(i->c_str());
457 ::unlink(i->c_str());
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
467 res.push_back(m_ref.path);
469 // handling for old splitted recordings (enigma 1)
474 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
476 if (stat(buf, &s) < 0)
481 res.push_back(m_ref.path + ".meta");
482 res.push_back(m_ref.path + ".ap");
483 res.push_back(m_ref.path + ".sc");
484 res.push_back(m_ref.path + ".cuts");
485 std::string tmp = m_ref.path;
486 tmp.erase(m_ref.path.length()-3);
487 res.push_back(tmp + ".eit");
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
493 const char *filename = m_ref.path.c_str();
494 eDebug("reindexing %s...", filename);
496 eMPEGStreamInformation info;
497 eMPEGStreamParserTS parser(info);
499 info.startSave(filename);
503 int err = f.open(m_ref.path.c_str(), 0);
507 off_t length = f.length();
508 unsigned char buffer[188*256*4];
511 off_t offset = f.lseek(0, SEEK_CUR);
512 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513 int r = f.read(buffer, sizeof(buffer));
518 parser.parseData(offset, buffer, r);
527 DEFINE_REF(eServiceFactoryDVB)
529 eServiceFactoryDVB::eServiceFactoryDVB()
531 ePtr<eServiceCenter> sc;
533 eServiceCenter::getPrivInstance(sc);
536 std::list<std::string> extensions;
537 extensions.push_back("ts");
538 extensions.push_back("trp");
539 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
542 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
543 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
546 eServiceFactoryDVB::~eServiceFactoryDVB()
548 ePtr<eServiceCenter> sc;
550 eServiceCenter::getPrivInstance(sc);
552 sc->removeServiceFactory(eServiceFactoryDVB::id);
555 DEFINE_REF(eDVBServiceList);
557 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
561 eDVBServiceList::~eDVBServiceList()
565 RESULT eDVBServiceList::startQuery()
567 ePtr<iDVBChannelList> db;
568 ePtr<eDVBResourceManager> res;
571 if ((err = eDVBResourceManager::getInstance(res)) != 0)
573 eDebug("no resource manager");
576 if ((err = res->getChannelList(db)) != 0)
578 eDebug("no channel list");
582 ePtr<eDVBChannelQuery> q;
584 if (!m_parent.path.empty())
586 eDVBChannelQuery::compile(q, m_parent.path);
589 eDebug("compile query failed");
594 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
596 eDebug("startQuery failed");
603 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
605 eServiceReferenceDVB ref;
610 while (!m_query->getNextResult(ref))
614 list.sort(iListableServiceCompare(this));
619 // The first argument of this function is a format string to specify the order and
620 // the content of the returned list
621 // useable format options are
622 // R = Service Reference (as swig object .. this is very slow)
623 // S = Service Reference (as python string object .. same as ref.toString())
624 // C = Service Reference (as python string object .. same as ref.toCompareString())
625 // N = Service Name (as python string object)
626 // n = Short Service Name (short name brakets used) (as python string object)
627 // when exactly one return value per service is selected in the format string,
628 // then each value is directly a list entry
629 // when more than one value is returned per service, then the list is a list of
631 // unknown format string chars are returned as python None values !
632 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
635 std::list<eServiceReference> tmplist;
638 if (!format || !(retcount=strlen(format)))
639 format = "R"; // just return service reference swig object ...
641 if (!getContent(tmplist, sorted))
643 int services=tmplist.size();
644 ePtr<iStaticServiceInformation> sptr;
645 eServiceCenterPtr service_center;
647 if (strchr(format, 'N') || strchr(format, 'n'))
648 eServiceCenter::getPrivInstance(service_center);
650 ret = PyList_New(services);
651 std::list<eServiceReference>::iterator it(tmplist.begin());
653 for (int cnt=0; cnt < services; ++cnt)
655 eServiceReference &ref=*it++;
656 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
657 for (int i=0; i < retcount; ++i)
662 case 'R': // service reference (swig)object
663 tmp = NEW_eServiceReference(ref);
665 case 'C': // service reference compare string
666 tmp = PyString_FromString(ref.toCompareString().c_str());
668 case 'S': // service reference string
669 tmp = PyString_FromString(ref.toString().c_str());
671 case 'N': // service name
674 service_center->info(ref, sptr);
678 sptr->getName(ref, name);
680 // filter short name brakets
682 while((pos = name.find("\xc2\x86")) != std::string::npos)
684 while((pos = name.find("\xc2\x87")) != std::string::npos)
688 tmp = PyString_FromString(name.c_str());
692 tmp = PyString_FromString("<n/a>");
694 case 'n': // short service name
697 service_center->info(ref, sptr);
701 sptr->getName(ref, name);
702 name = buildShortName(name);
704 tmp = PyString_FromString(name.c_str());
708 tmp = PyString_FromString("<n/a>");
721 PyTuple_SET_ITEM(tuple, i, tmp);
723 PyList_SET_ITEM(ret, cnt, tmp);
727 PyList_SET_ITEM(ret, cnt, tuple);
730 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
733 RESULT eDVBServiceList::getNext(eServiceReference &ref)
738 return m_query->getNextResult((eServiceReferenceDVB&)ref);
741 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
743 if (m_parent.flags & eServiceReference::canDescent) // bouquet
745 ePtr<iDVBChannelList> db;
746 ePtr<eDVBResourceManager> resm;
748 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
751 if (db->getBouquet(m_parent, m_bouquet) != 0)
762 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
766 return m_bouquet->addService(ref, before);
769 RESULT eDVBServiceList::removeService(eServiceReference &ref)
773 return m_bouquet->removeService(ref);
776 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
780 return m_bouquet->moveService(ref, pos);
783 RESULT eDVBServiceList::flushChanges()
787 return m_bouquet->flushChanges();
790 RESULT eDVBServiceList::setListName(const std::string &name)
794 return m_bouquet->setListName(name);
797 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
799 ePtr<eDVBService> service;
800 int r = lookupService(service, ref);
803 // check resources...
804 ptr = new eDVBServicePlay(ref, service);
808 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
810 if (ref.path.empty())
812 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
821 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
823 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
824 if (list->startQuery())
834 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
836 /* is a listable service? */
837 if (ref.flags & eServiceReference::canDescent) // bouquet
839 if ( !ref.name.empty() ) // satellites or providers list
840 ptr = m_StaticServiceDVBInfo;
841 else // a dvb bouquet
842 ptr = m_StaticServiceDVBBouquetInfo;
844 else if (!ref.path.empty()) /* do we have a PVR service? */
845 ptr = new eStaticServiceDVBPVRInformation(ref);
846 else // normal dvb service
848 ePtr<eDVBService> service;
849 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
850 ptr = m_StaticServiceDVBInfo;
852 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
858 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
860 if (ref.path.empty())
866 ptr = new eDVBPVRServiceOfflineOperations(ref);
871 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
873 if (!ref.path.empty()) // playback
875 eDVBMetaParser parser;
876 int ret=parser.parseFile(ref.path);
877 service = new eDVBService;
879 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
883 // TODO: handle the listing itself
884 // if (ref.... == -1) .. return "... bouquets ...";
885 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
887 ePtr<iDVBChannelList> db;
888 ePtr<eDVBResourceManager> res;
891 if ((err = eDVBResourceManager::getInstance(res)) != 0)
893 eDebug("no resource manager");
896 if ((err = res->getChannelList(db)) != 0)
898 eDebug("no channel list");
902 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
903 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
905 eDebug("getService failed!");
913 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
914 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
917 m_is_pvr = !m_reference.path.empty();
919 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
922 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
923 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
924 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
926 m_cuesheet_changed = 0;
927 m_cutlist_enabled = 1;
929 m_subtitle_widget = 0;
933 m_subtitle_sync_timer = eTimer::create(eApp);
935 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
938 eDVBServicePlay::~eDVBServicePlay()
943 int ret=meta.parseFile(m_reference.path);
947 meta.m_service_data="";
948 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
949 meta.m_service_data += tmp;
951 for (int x=0; x < eDVBService::cacheMax; ++x)
953 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
956 sprintf(tmp, ",c:%02d%04x", x, entry);
957 meta.m_service_data += tmp;
960 meta.updateMeta(m_reference.path);
963 delete m_subtitle_widget;
966 void eDVBServicePlay::gotNewEvent()
970 ePtr<eServiceEvent> m_event_now, m_event_next;
971 getEvent(m_event_now, 0);
972 getEvent(m_event_next, 1);
975 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
977 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
979 m_event((iPlayableService*)this, evUpdatedEventInfo);
982 void eDVBServicePlay::serviceEvent(int event)
984 m_tune_state = event;
988 case eDVBServicePMTHandler::eventTuned:
990 ePtr<iDVBDemux> m_demux;
991 if (!m_service_handler.getDataDemux(m_demux))
993 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
994 int sid = ref.getParentServiceID().get();
996 sid = ref.getServiceID().get();
997 if ( ref.getParentTransportStreamID().get() &&
998 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
999 m_event_handler.startOther(m_demux, sid);
1001 m_event_handler.start(m_demux, sid);
1003 m_event((iPlayableService*)this, evTunedIn);
1006 case eDVBServicePMTHandler::eventNoResources:
1007 case eDVBServicePMTHandler::eventNoPAT:
1008 case eDVBServicePMTHandler::eventNoPATEntry:
1009 case eDVBServicePMTHandler::eventNoPMT:
1010 case eDVBServicePMTHandler::eventTuneFailed:
1011 case eDVBServicePMTHandler::eventMisconfiguration:
1013 eDebug("DVB service failed to tune - error %d", event);
1014 m_event((iPlayableService*)this, evTuneFailed);
1017 case eDVBServicePMTHandler::eventNewProgramInfo:
1019 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1020 if (m_timeshift_enabled)
1021 updateTimeshiftPids();
1022 if (!m_timeshift_active)
1024 if (m_first_program_info && m_is_pvr)
1026 m_first_program_info = 0;
1029 m_event((iPlayableService*)this, evUpdatedInfo);
1032 case eDVBServicePMTHandler::eventPreStart:
1035 case eDVBServicePMTHandler::eventEOF:
1036 m_event((iPlayableService*)this, evEOF);
1038 case eDVBServicePMTHandler::eventSOF:
1039 m_event((iPlayableService*)this, evSOF);
1044 void eDVBServicePlay::serviceEventTimeshift(int event)
1048 case eDVBServicePMTHandler::eventNewProgramInfo:
1049 if (m_timeshift_active)
1052 case eDVBServicePMTHandler::eventSOF:
1053 m_event((iPlayableService*)this, evSOF);
1055 case eDVBServicePMTHandler::eventEOF:
1056 if ((!m_is_paused) && (m_skipmode >= 0))
1058 eDebug("timeshift EOF, so let's go live");
1065 RESULT eDVBServicePlay::start()
1067 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1069 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1070 two (one for decoding, one for data source), as we must be prepared
1071 to start recording from the data demux. */
1074 eDVBMetaParser meta;
1075 if (!meta.parseFile(m_reference.path))
1077 service = meta.m_ref;
1078 service.path = m_reference.path;
1080 m_cue = new eCueSheet();
1083 m_event(this, evStart);
1085 m_first_program_info = 1;
1086 m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1090 /* inject EIT if there is a stored one */
1091 std::string filename = service.path;
1092 filename.erase(filename.length()-2, 2);
1094 ePtr<eServiceEvent> event = new eServiceEvent;
1095 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1097 ePtr<eServiceEvent> empty;
1098 m_event_handler.inject(event, 0);
1099 m_event_handler.inject(empty, 1);
1101 m_event(this, evStart);
1106 RESULT eDVBServicePlay::stop()
1108 /* add bookmark for last play position */
1111 pts_t play_position, length;
1112 if (!getPlayPosition(play_position))
1114 /* remove last position */
1115 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1117 if (i->what == 3) /* current play position */
1119 m_cue_entries.erase(i);
1120 i = m_cue_entries.begin();
1126 if (getLength(length))
1131 int perc = play_position * 100LL / length;
1133 /* only store last play position when between 1% and 99% */
1134 if ((1 < perc) && (perc < 99))
1135 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1137 m_cuesheet_changed = 1;
1141 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1143 m_service_handler_timeshift.free();
1144 m_service_handler.free();
1146 if (m_is_pvr && m_cuesheet_changed)
1149 /* save cuesheet only when main file is accessible. */
1150 if (!::stat(m_reference.path.c_str(), &s))
1153 m_event((iPlayableService*)this, evStopped);
1157 RESULT eDVBServicePlay::setTarget(int target)
1159 m_is_primary = !target;
1163 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1165 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1169 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1171 /* note: we check for timeshift to be enabled,
1172 not neccessary active. if you pause when timeshift
1173 is not active, you should activate it when unpausing */
1174 if ((!m_is_pvr) && (!m_timeshift_enabled))
1184 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1186 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1187 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1188 setFastForward_internal(0);
1190 return m_decoder->setSlowMotion(ratio);
1195 RESULT eDVBServicePlay::setFastForward(int ratio)
1197 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1199 return setFastForward_internal(ratio);
1202 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1204 int skipmode, ffratio;
1210 } else if (ratio > 0)
1218 } else // if (ratio < 0)
1224 if (m_skipmode != skipmode)
1226 eDebug("setting cue skipmode to %d", skipmode);
1228 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1231 m_skipmode = skipmode;
1237 ; /* return m_decoder->play(); is done in caller*/
1238 else if (ffratio != 1)
1239 return m_decoder->setFastForward(ffratio);
1241 return m_decoder->setTrickmode();
1245 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1247 if (m_is_pvr || m_timeshift_enabled)
1257 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1258 RESULT eDVBServicePlay::getLength(pts_t &len)
1260 ePtr<iDVBPVRChannel> pvr_channel;
1262 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1265 return pvr_channel->getLength(len);
1268 RESULT eDVBServicePlay::pause()
1270 eDebug("eDVBServicePlay::pause");
1271 setFastForward_internal(0);
1275 return m_decoder->pause();
1280 RESULT eDVBServicePlay::unpause()
1282 eDebug("eDVBServicePlay::unpause");
1283 setFastForward_internal(0);
1287 return m_decoder->play();
1292 RESULT eDVBServicePlay::seekTo(pts_t to)
1294 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1296 if (!m_decode_demux)
1299 ePtr<iDVBPVRChannel> pvr_channel;
1301 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1307 m_cue->seekTo(0, to);
1308 m_dvb_subtitle_pages.clear();
1309 m_subtitle_pages.clear();
1314 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1316 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1318 if (!m_decode_demux)
1321 ePtr<iDVBPVRChannel> pvr_channel;
1323 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1328 /* HACK until we have skip-AP api */
1329 if ((to > 0) && (to < 100))
1337 m_cue->seekTo(mode, to);
1338 m_dvb_subtitle_pages.clear();
1339 m_subtitle_pages.clear();
1343 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1345 ePtr<iDVBPVRChannel> pvr_channel;
1347 if (!m_decode_demux)
1350 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1355 /* if there is a decoder, use audio or video PTS */
1358 r = m_decoder->getPTS(0, pos);
1364 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1367 RESULT eDVBServicePlay::setTrickmode(int trick)
1369 /* currently unimplemented */
1373 RESULT eDVBServicePlay::isCurrentlySeekable()
1375 return m_is_pvr || m_timeshift_active;
1378 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1384 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1390 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1396 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1402 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1408 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1411 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1412 (m_timeshift_enabled || !m_is_pvr))
1414 if (!m_timeshift_enabled)
1416 /* query config path */
1418 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1419 eDebug("could not query ts path from config");
1423 /* we need enough diskspace */
1425 if (statfs(tspath.c_str(), &fs) < 0)
1427 eDebug("statfs failed!");
1431 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1433 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1443 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1454 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1460 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1466 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1472 RESULT eDVBServicePlay::getName(std::string &name)
1476 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1477 return i->getName(m_reference, name);
1479 else if (m_dvb_service)
1481 m_dvb_service->getName(m_reference, name);
1485 else if (!m_reference.name.empty())
1486 eStaticServiceDVBInformation().getName(m_reference, name);
1488 name = "DVB service";
1492 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1494 return m_event_handler.getEvent(evt, nownext);
1497 int eDVBServicePlay::getInfo(int w)
1499 eDVBServicePMTHandler::program program;
1502 return resIsPyObject;
1504 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1506 int no_program_info = 0;
1508 if (h.getProgramInfo(program))
1509 no_program_info = 1;
1515 return m_decoder->getVideoHeight();
1519 return m_decoder->getVideoWidth();
1523 return m_decoder->getVideoFrameRate();
1527 return m_decoder->getVideoProgressive();
1533 aspect = m_decoder->getVideoAspect();
1534 if (aspect == -1 && no_program_info)
1536 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1538 ePtr<eServiceEvent> evt;
1539 if (!m_event_handler.getEvent(evt, 0))
1541 ePtr<eComponentData> data;
1542 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1544 if ( data->getStreamContent() == 1 )
1546 switch(data->getComponentType())
1549 case 1: // 4:3 SD PAL
1551 case 3: // 16:9 SD PAL
1552 case 4: // > 16:9 PAL
1553 case 5: // 4:3 SD NTSC
1555 case 7: // 16:9 SD NTSC
1556 case 8: // > 16:9 NTSC
1559 case 9: // 4:3 HD PAL
1561 case 0xB: // 16:9 HD PAL
1562 case 0xC: // > 16:9 HD PAL
1563 case 0xD: // 4:3 HD NTSC
1565 case 0xF: // 16:9 HD NTSC
1566 case 0x10: // > 16:9 HD PAL
1567 return data->getComponentType();
1577 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1581 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1585 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1586 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1590 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1593 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1597 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1601 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1605 if (no_program_info) return -1; return program.pcrPid;
1606 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1607 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1608 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1609 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1610 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1611 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1612 case sProvider: if (!m_dvb_service) return -1; return -2;
1613 case sServiceref: return resIsString;
1614 case sDVBState: return m_tune_state;
1621 std::string eDVBServicePlay::getInfoString(int w)
1626 if (!m_dvb_service) return "";
1627 return m_dvb_service->m_provider_name;
1629 return m_reference.toString();
1633 return iServiceInformation::getInfoString(w);
1636 PyObject *eDVBServicePlay::getInfoObject(int w)
1641 return m_service_handler.getCaIds();
1642 case sTransponderData:
1643 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1647 return iServiceInformation::getInfoObject(w);
1650 int eDVBServicePlay::getNumberOfTracks()
1652 eDVBServicePMTHandler::program program;
1653 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1654 if (h.getProgramInfo(program))
1656 return program.audioStreams.size();
1659 int eDVBServicePlay::getCurrentTrack()
1661 eDVBServicePMTHandler::program program;
1662 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1663 if (h.getProgramInfo(program))
1666 int max = program.audioStreams.size();
1669 for (i = 0; i < max; ++i)
1670 if (program.audioStreams[i].pid == m_current_audio_pid)
1676 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1678 int ret = selectAudioStream(i);
1680 if (m_decoder->set())
1686 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1688 eDVBServicePMTHandler::program program;
1689 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1691 if (h.getProgramInfo(program))
1694 if (i >= program.audioStreams.size())
1697 info.m_pid = program.audioStreams[i].pid;
1699 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1700 info.m_description = "MPEG";
1701 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1702 info.m_description = "AC3";
1703 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1704 info.m_description = "AAC";
1705 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1706 info.m_description = "AAC-HE";
1707 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1708 info.m_description = "DTS";
1710 info.m_description = "???";
1712 if (program.audioStreams[i].component_tag != -1)
1714 ePtr<eServiceEvent> evt;
1715 if (!m_event_handler.getEvent(evt, 0))
1717 ePtr<eComponentData> data;
1718 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1719 info.m_language = data->getText();
1723 if (info.m_language.empty())
1724 info.m_language = program.audioStreams[i].language_code;
1729 int eDVBServicePlay::selectAudioStream(int i)
1731 eDVBServicePMTHandler::program program;
1732 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1734 if (h.getProgramInfo(program))
1737 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1745 stream = program.defaultAudioStream;
1747 int apid = -1, apidtype = -1;
1749 if (((unsigned int)stream) < program.audioStreams.size())
1751 apid = program.audioStreams[stream].pid;
1752 apidtype = program.audioStreams[stream].type;
1755 m_current_audio_pid = apid;
1757 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1759 eDebug("set audio pid failed");
1765 /* 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 */
1766 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1768 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1770 rdsPid = program.audioStreams[stream].rdsPid;
1771 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1774 ePtr<iDVBDemux> data_demux;
1775 if (!h.getDataDemux(data_demux))
1777 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1778 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1779 m_rds_decoder->start(rdsPid);
1784 /* store new pid as default only when:
1785 a.) we have an entry in the service db for the current service,
1786 b.) we are not playing back something,
1787 c.) we are not selecting the default entry. (we wouldn't change
1788 anything in the best case, or destroy the default setting in
1789 case the real default is not yet available.)
1791 if (m_dvb_service && ((i != -1)
1792 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1794 if (apidtype == eDVBAudio::aMPEG)
1796 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1797 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1799 else if (apidtype == eDVBAudio::aAC3)
1801 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1802 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1806 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1807 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1811 h.resetCachedProgram();
1816 int eDVBServicePlay::getCurrentChannel()
1818 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1821 RESULT eDVBServicePlay::selectChannel(int i)
1823 if (i < LEFT || i > RIGHT || i == STEREO)
1826 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1828 m_decoder->setAudioChannel(i);
1832 std::string eDVBServicePlay::getText(int x)
1838 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1840 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1845 void eDVBServicePlay::rdsDecoderEvent(int what)
1849 case eDVBRdsDecoder::RadioTextChanged:
1850 m_event((iPlayableService*)this, evUpdatedRadioText);
1852 case eDVBRdsDecoder::RtpTextChanged:
1853 m_event((iPlayableService*)this, evUpdatedRtpText);
1855 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1856 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1858 case eDVBRdsDecoder::RecvRassSlidePic:
1859 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1864 void eDVBServicePlay::showRassSlidePicture()
1870 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1871 if (rass_slide_pic.length())
1872 m_decoder->showSinglePic(rass_slide_pic.c_str());
1874 eDebug("empty filename for rass slide picture received!!");
1877 eDebug("no MPEG Decoder to show iframes avail");
1880 eDebug("showRassSlidePicture called.. but not decoder");
1883 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1889 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1890 if (rass_interactive_pic.length())
1891 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1893 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1896 eDebug("no MPEG Decoder to show iframes avail");
1899 eDebug("showRassInteractivePic called.. but not decoder");
1902 ePyObject eDVBServicePlay::getRassInteractiveMask()
1905 return m_rds_decoder->getRassPictureMask();
1909 int eDVBServiceBase::getFrontendInfo(int w)
1911 eUsePtr<iDVBChannel> channel;
1912 if(m_service_handler.getChannel(channel))
1914 ePtr<iDVBFrontend> fe;
1915 if(channel->getFrontend(fe))
1917 return fe->readFrontendData(w);
1920 PyObject *eDVBServiceBase::getFrontendData()
1922 ePyObject ret = PyDict_New();
1925 eUsePtr<iDVBChannel> channel;
1926 if(!m_service_handler.getChannel(channel))
1928 ePtr<iDVBFrontend> fe;
1929 if(!channel->getFrontend(fe))
1930 fe->getFrontendData(ret);
1938 PyObject *eDVBServiceBase::getFrontendStatus()
1940 ePyObject ret = PyDict_New();
1943 eUsePtr<iDVBChannel> channel;
1944 if(!m_service_handler.getChannel(channel))
1946 ePtr<iDVBFrontend> fe;
1947 if(!channel->getFrontend(fe))
1948 fe->getFrontendStatus(ret);
1956 PyObject *eDVBServiceBase::getTransponderData(bool original)
1958 ePyObject ret = PyDict_New();
1961 eUsePtr<iDVBChannel> channel;
1962 if(!m_service_handler.getChannel(channel))
1964 ePtr<iDVBFrontend> fe;
1965 if(!channel->getFrontend(fe))
1966 fe->getTransponderData(ret, original);
1974 PyObject *eDVBServiceBase::getAll(bool original)
1976 ePyObject ret = getTransponderData(original);
1979 eUsePtr<iDVBChannel> channel;
1980 if(!m_service_handler.getChannel(channel))
1982 ePtr<iDVBFrontend> fe;
1983 if(!channel->getFrontend(fe))
1985 fe->getFrontendData(ret);
1986 fe->getFrontendStatus(ret);
1993 int eDVBServicePlay::getNumberOfSubservices()
1995 ePtr<eServiceEvent> evt;
1996 if (!m_event_handler.getEvent(evt, 0))
1997 return evt->getNumOfLinkageServices();
2001 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2003 ePtr<eServiceEvent> evt;
2004 if (!m_event_handler.getEvent(evt, 0))
2006 if (!evt->getLinkageService(sub, m_reference, n))
2009 sub.type=eServiceReference::idInvalid;
2013 RESULT eDVBServicePlay::startTimeshift()
2015 ePtr<iDVBDemux> demux;
2017 eDebug("Start timeshift!");
2019 if (m_timeshift_enabled)
2022 /* start recording with the data demux. */
2023 if (m_service_handler.getDataDemux(demux))
2026 demux->createTSRecorder(m_record);
2031 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2032 eDebug("could not query ts path");
2035 tspath.append("/timeshift.XXXXXX");
2037 templ = new char[tspath.length() + 1];
2038 strcpy(templ, tspath.c_str());
2040 m_timeshift_fd = mkstemp(templ);
2041 m_timeshift_file = std::string(templ);
2043 eDebug("recording to %s", templ);
2047 if (m_timeshift_fd < 0)
2053 m_record->setTargetFD(m_timeshift_fd);
2055 m_timeshift_enabled = 1;
2057 updateTimeshiftPids();
2063 RESULT eDVBServicePlay::stopTimeshift()
2065 if (!m_timeshift_enabled)
2070 m_timeshift_enabled = 0;
2075 close(m_timeshift_fd);
2076 eDebug("remove timeshift file");
2077 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2082 int eDVBServicePlay::isTimeshiftActive()
2084 return m_timeshift_enabled && m_timeshift_active;
2087 RESULT eDVBServicePlay::activateTimeshift()
2089 if (!m_timeshift_enabled)
2092 if (!m_timeshift_active)
2094 switchToTimeshift();
2101 PyObject *eDVBServicePlay::getCutList()
2103 ePyObject list = PyList_New(0);
2105 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2107 ePyObject tuple = PyTuple_New(2);
2108 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2109 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2110 PyList_Append(list, tuple);
2117 void eDVBServicePlay::setCutList(ePyObject list)
2119 if (!PyList_Check(list))
2121 int size = PyList_Size(list);
2124 m_cue_entries.clear();
2126 for (i=0; i<size; ++i)
2128 ePyObject tuple = PyList_GET_ITEM(list, i);
2129 if (!PyTuple_Check(tuple))
2131 eDebug("non-tuple in cutlist");
2134 if (PyTuple_Size(tuple) != 2)
2136 eDebug("cutlist entries need to be a 2-tuple");
2139 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2140 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2142 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2145 pts_t pts = PyLong_AsLongLong(ppts);
2146 int type = PyInt_AsLong(ptype);
2147 m_cue_entries.insert(cueEntry(pts, type));
2148 eDebug("adding %08llx, %d", pts, type);
2150 m_cuesheet_changed = 1;
2152 cutlistToCuesheet();
2153 m_event((iPlayableService*)this, evCuesheetChanged);
2156 void eDVBServicePlay::setCutListEnable(int enable)
2158 m_cutlist_enabled = enable;
2159 cutlistToCuesheet();
2162 void eDVBServicePlay::updateTimeshiftPids()
2167 eDVBServicePMTHandler::program program;
2168 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2170 if (h.getProgramInfo(program))
2174 std::set<int> pids_to_record;
2175 pids_to_record.insert(0); // PAT
2176 if (program.pmtPid != -1)
2177 pids_to_record.insert(program.pmtPid); // PMT
2179 if (program.textPid != -1)
2180 pids_to_record.insert(program.textPid); // Videotext
2182 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2183 i(program.videoStreams.begin());
2184 i != program.videoStreams.end(); ++i)
2185 pids_to_record.insert(i->pid);
2187 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2188 i(program.audioStreams.begin());
2189 i != program.audioStreams.end(); ++i)
2190 pids_to_record.insert(i->pid);
2192 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2193 i(program.subtitleStreams.begin());
2194 i != program.subtitleStreams.end(); ++i)
2195 pids_to_record.insert(i->pid);
2197 std::set<int> new_pids, obsolete_pids;
2199 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2200 m_pids_active.begin(), m_pids_active.end(),
2201 std::inserter(new_pids, new_pids.begin()));
2203 std::set_difference(
2204 m_pids_active.begin(), m_pids_active.end(),
2205 pids_to_record.begin(), pids_to_record.end(),
2206 std::inserter(new_pids, new_pids.begin())
2209 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2210 m_record->addPID(*i);
2212 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2213 m_record->removePID(*i);
2217 void eDVBServicePlay::switchToLive()
2219 if (!m_timeshift_active)
2222 eDebug("SwitchToLive");
2227 m_teletext_parser = 0;
2229 m_subtitle_parser = 0;
2230 m_new_dvb_subtitle_page_connection = 0;
2231 m_new_subtitle_page_connection = 0;
2232 m_rds_decoder_event_connection = 0;
2233 m_video_event_connection = 0;
2234 m_is_paused = m_skipmode = 0; /* not supported in live mode */
2236 /* free the timeshift service handler, we need the resources */
2237 m_service_handler_timeshift.free();
2238 m_timeshift_active = 0;
2239 m_timeshift_changed = 1;
2241 m_event((iPlayableService*)this, evSeekableStatusChanged);
2246 void eDVBServicePlay::switchToTimeshift()
2248 if (m_timeshift_active)
2253 m_teletext_parser = 0;
2255 m_subtitle_parser = 0;
2256 m_new_subtitle_page_connection = 0;
2257 m_new_dvb_subtitle_page_connection = 0;
2258 m_rds_decoder_event_connection = 0;
2259 m_video_event_connection = 0;
2261 m_timeshift_active = 1;
2262 m_timeshift_changed = 1;
2264 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2265 r.path = m_timeshift_file;
2267 m_cue = new eCueSheet();
2268 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2270 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2272 updateDecoder(); /* mainly to switch off PCR, and to set pause */
2274 m_event((iPlayableService*)this, evSeekableStatusChanged);
2277 void eDVBServicePlay::updateDecoder()
2279 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2281 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2283 eDVBServicePMTHandler::program program;
2284 if (h.getProgramInfo(program))
2285 eDebug("getting program info failed.");
2288 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2289 if (!program.videoStreams.empty())
2291 eDebugNoNewLine(" (");
2292 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2293 i(program.videoStreams.begin());
2294 i != program.videoStreams.end(); ++i)
2301 if (i != program.videoStreams.begin())
2302 eDebugNoNewLine(", ");
2303 eDebugNoNewLine("%04x", i->pid);
2305 eDebugNoNewLine(")");
2307 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2308 if (!program.audioStreams.empty())
2310 eDebugNoNewLine(" (");
2311 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2312 i(program.audioStreams.begin());
2313 i != program.audioStreams.end(); ++i)
2315 if (i != program.audioStreams.begin())
2316 eDebugNoNewLine(", ");
2317 eDebugNoNewLine("%04x", i->pid);
2319 eDebugNoNewLine(")");
2321 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2322 pcrpid = program.pcrPid;
2323 eDebug(", and the text pid is %04x", program.textPid);
2324 tpid = program.textPid;
2329 h.getDecodeDemux(m_decode_demux);
2330 if (m_timeshift_changed)
2334 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2336 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2339 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2340 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2341 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2342 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2343 if (m_timeshift_changed)
2345 ePyObject subs = getCachedSubtitle();
2346 if (subs != Py_None)
2348 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2349 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2350 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2351 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2352 if (type == 0) // dvb
2353 m_subtitle_parser->start(pid, comp_page, anc_page);
2354 else if (type == 1) // ttx
2355 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2360 m_decoder->play(); /* pids will be set later */
2363 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2364 m_decoder->play(); /* pids will be set later. */
2367 m_timeshift_changed = 0;
2373 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2374 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2375 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2379 eServiceReferenceDVB ref;
2380 m_service_handler.getServiceReference(ref);
2381 eServiceReferenceDVB parent = ref.getParentServiceReference();
2386 ePtr<eDVBResourceManager> res_mgr;
2387 if (!eDVBResourceManager::getInstance(res_mgr))
2389 ePtr<iDVBChannelList> db;
2390 if (!res_mgr->getChannelList(db))
2392 ePtr<eDVBService> origService;
2393 if (!db->getService(parent, origService))
2395 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2396 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2403 std::string config_delay;
2404 int config_delay_int = 0;
2405 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2406 config_delay_int = atoi(config_delay.c_str());
2407 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2409 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2410 config_delay_int = atoi(config_delay.c_str());
2412 config_delay_int = 0;
2413 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2415 m_decoder->setVideoPID(vpid, vpidtype);
2416 selectAudioStream();
2418 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2419 m_decoder->setSyncPCR(pcrpid);
2421 m_decoder->setSyncPCR(-1);
2425 m_decoder->setTextPID(tpid);
2426 m_teletext_parser->start(program.textPid);
2429 if (vpid > 0 && vpid < 0x2000)
2433 std::string radio_pic;
2434 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2435 m_decoder->setRadioPic(radio_pic);
2439 m_decoder->setAudioChannel(achannel);
2441 /* don't worry about non-existing services, nor pvr services */
2444 /* (audio pid will be set in selectAudioTrack */
2445 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2446 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2447 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2448 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2451 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2454 void eDVBServicePlay::loadCuesheet()
2456 std::string filename = m_reference.path + ".cuts";
2458 m_cue_entries.clear();
2460 FILE *f = fopen(filename.c_str(), "rb");
2464 eDebug("loading cuts..");
2467 unsigned long long where;
2470 if (!fread(&where, sizeof(where), 1, f))
2472 if (!fread(&what, sizeof(what), 1, f))
2475 #if BYTE_ORDER == LITTLE_ENDIAN
2476 where = bswap_64(where);
2483 m_cue_entries.insert(cueEntry(where, what));
2486 eDebug("%d entries", m_cue_entries.size());
2488 eDebug("cutfile not found!");
2490 m_cuesheet_changed = 0;
2491 cutlistToCuesheet();
2492 m_event((iPlayableService*)this, evCuesheetChanged);
2495 void eDVBServicePlay::saveCuesheet()
2497 std::string filename = m_reference.path + ".cuts";
2499 FILE *f = fopen(filename.c_str(), "wb");
2503 unsigned long long where;
2506 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2508 #if BYTE_ORDER == BIG_ENDIAN
2511 where = bswap_64(i->where);
2513 what = htonl(i->what);
2514 fwrite(&where, sizeof(where), 1, f);
2515 fwrite(&what, sizeof(what), 1, f);
2521 m_cuesheet_changed = 0;
2524 void eDVBServicePlay::cutlistToCuesheet()
2528 eDebug("no cue sheet");
2533 if (!m_cutlist_enabled)
2535 m_cue->commitSpans();
2536 eDebug("cutlists were disabled");
2540 pts_t in = 0, out = 0, length = 0;
2544 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2546 int have_any_span = 0;
2550 if (i == m_cue_entries.end())
2556 if (i->what == 0) /* in */
2560 } else if (i->what == 1) /* out */
2562 else /* mark (2) or last play position (3) */
2581 m_cue->addSourceSpan(in, out);
2586 if (i == m_cue_entries.end())
2589 m_cue->commitSpans();
2592 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2594 if (m_subtitle_widget)
2595 disableSubtitles(parent);
2598 int tuplesize = PyTuple_Size(tuple);
2601 if (!PyTuple_Check(tuple))
2607 entry = PyTuple_GET_ITEM(tuple, 0);
2609 if (!PyInt_Check(entry))
2612 type = PyInt_AsLong(entry);
2614 if (type == 1) // teletext subtitles
2616 int page, magazine, pid;
2620 if (!m_teletext_parser)
2622 eDebug("enable teletext subtitles.. no parser !!!");
2626 entry = PyTuple_GET_ITEM(tuple, 1);
2627 if (!PyInt_Check(entry))
2629 pid = PyInt_AsLong(entry);
2631 entry = PyTuple_GET_ITEM(tuple, 2);
2632 if (!PyInt_Check(entry))
2634 page = PyInt_AsLong(entry);
2636 entry = PyTuple_GET_ITEM(tuple, 3);
2637 if (!PyInt_Check(entry))
2639 magazine = PyInt_AsLong(entry);
2641 m_subtitle_widget = new eSubtitleWidget(parent);
2642 m_subtitle_widget->resize(parent->size()); /* full size */
2643 m_teletext_parser->setPageAndMagazine(page, magazine);
2645 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2649 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2650 if (!m_subtitle_parser)
2652 eDebug("enable dvb subtitles.. no parser !!!");
2658 entry = PyTuple_GET_ITEM(tuple, 1);
2659 if (!PyInt_Check(entry))
2661 pid = PyInt_AsLong(entry);
2663 entry = PyTuple_GET_ITEM(tuple, 2);
2664 if (!PyInt_Check(entry))
2666 composition_page_id = PyInt_AsLong(entry);
2668 entry = PyTuple_GET_ITEM(tuple, 3);
2669 if (!PyInt_Check(entry))
2671 ancillary_page_id = PyInt_AsLong(entry);
2673 m_subtitle_widget = new eSubtitleWidget(parent);
2674 m_subtitle_widget->resize(parent->size()); /* full size */
2675 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2677 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2683 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2684 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2685 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2689 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2691 delete m_subtitle_widget;
2692 m_subtitle_widget = 0;
2693 if (m_subtitle_parser)
2695 m_subtitle_parser->stop();
2696 m_dvb_subtitle_pages.clear();
2698 if (m_teletext_parser)
2700 m_teletext_parser->setPageAndMagazine(-1, -1);
2701 m_subtitle_pages.clear();
2704 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2708 PyObject *eDVBServicePlay::getCachedSubtitle()
2712 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2715 unsigned int data = (unsigned int)tmp;
2716 int pid = (data&0xFFFF0000)>>16;
2717 ePyObject tuple = PyTuple_New(4);
2718 eDVBServicePMTHandler::program program;
2719 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2720 if (!h.getProgramInfo(program))
2722 if (program.textPid==pid) // teletext
2723 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2725 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2726 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2727 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2728 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2736 PyObject *eDVBServicePlay::getSubtitleList()
2738 if (!m_teletext_parser)
2741 ePyObject l = PyList_New(0);
2742 std::set<int> added_ttx_pages;
2744 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2745 m_teletext_parser->m_found_subtitle_pages;
2747 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2748 eDVBServicePMTHandler::program program;
2749 if (h.getProgramInfo(program))
2750 eDebug("getting program info failed.");
2753 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2754 it != program.subtitleStreams.end(); ++it)
2756 switch(it->subtitling_type)
2758 case 0x01: // ebu teletext subtitles
2760 int page_number = it->teletext_page_number & 0xFF;
2761 int magazine_number = it->teletext_magazine_number & 7;
2762 int hash = magazine_number << 8 | page_number;
2763 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2765 ePyObject tuple = PyTuple_New(5);
2766 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2767 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2768 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2769 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2770 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2771 PyList_Append(l, tuple);
2773 added_ttx_pages.insert(hash);
2778 case 0x20 ... 0x23: // dvb subtitles
2780 ePyObject tuple = PyTuple_New(5);
2781 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2782 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2783 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2784 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2785 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2786 PyList_Insert(l, 0, tuple);
2794 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2795 it != subs.end(); ++it)
2797 int page_number = it->teletext_page_number & 0xFF;
2798 int magazine_number = it->teletext_magazine_number & 7;
2799 int hash = magazine_number << 8 | page_number;
2800 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2802 ePyObject tuple = PyTuple_New(5);
2803 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2804 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2805 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2806 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2807 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2808 PyList_Append(l, tuple);
2816 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2818 if (m_subtitle_widget)
2822 m_decoder->getPTS(0, pos);
2823 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2824 m_subtitle_pages.push_back(page);
2825 checkSubtitleTiming();
2829 void eDVBServicePlay::checkSubtitleTiming()
2831 eDebug("checkSubtitleTiming");
2832 if (!m_subtitle_widget)
2836 enum { TELETEXT, DVB } type;
2837 eDVBTeletextSubtitlePage page;
2838 eDVBSubtitlePage dvb_page;
2840 if (!m_subtitle_pages.empty())
2842 page = m_subtitle_pages.front();
2844 show_time = page.m_pts;
2846 else if (!m_dvb_subtitle_pages.empty())
2848 dvb_page = m_dvb_subtitle_pages.front();
2850 show_time = dvb_page.m_show_time;
2858 m_decoder->getPTS(0, pos);
2860 eDebug("%lld %lld", pos, show_time);
2861 int diff = show_time - pos;
2862 if (type == TELETEXT && !page.m_have_pts)
2864 eDebug("ttx subtitle page without pts... immediate show");
2869 eDebug("[late (%d ms)]", -diff / 90);
2872 if (abs(diff) > 1800000)
2874 eDebug("[invalid]... immediate show!");
2879 if (type == TELETEXT)
2881 eDebug("display teletext subtitle page %lld", show_time);
2882 m_subtitle_widget->setPage(page);
2883 m_subtitle_pages.pop_front();
2887 eDebug("display dvb subtitle Page %lld", show_time);
2888 m_subtitle_widget->setPage(dvb_page);
2889 m_dvb_subtitle_pages.pop_front();
2893 eDebug("start subtitle delay %d", diff / 90);
2894 m_subtitle_sync_timer->start(diff / 90, 1);
2900 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2902 if (m_subtitle_widget)
2906 m_decoder->getPTS(0, pos);
2907 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2908 m_dvb_subtitle_pages.push_back(p);
2909 checkSubtitleTiming();
2913 int eDVBServicePlay::getAC3Delay()
2916 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2918 return m_decoder->getAC3Delay();
2923 int eDVBServicePlay::getPCMDelay()
2926 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2928 return m_decoder->getPCMDelay();
2933 void eDVBServicePlay::setAC3Delay(int delay)
2936 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2938 m_decoder->setAC3Delay(delay);
2941 void eDVBServicePlay::setPCMDelay(int delay)
2944 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2946 m_decoder->setPCMDelay(delay);
2949 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2951 switch(event.type) {
2952 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2953 m_event((iPlayableService*)this, evVideoSizeChanged);
2955 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2956 m_event((iPlayableService*)this, evVideoFramerateChanged);
2958 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2959 m_event((iPlayableService*)this, evVideoProgressiveChanged);
2966 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2972 PyObject *eDVBServicePlay::getStreamingData()
2974 eDVBServicePMTHandler::program program;
2975 if (m_service_handler.getProgramInfo(program))
2980 ePyObject r = program.createPythonObject();
2981 ePtr<iDVBDemux> demux;
2982 if (!m_service_handler.getDataDemux(demux))
2985 if (!demux->getCADemuxID(demux_id))
2986 PutToDict(r, "demux", demux_id);
2993 DEFINE_REF(eDVBServicePlay)
2995 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2999 case iServiceInformation::sTransponderData:
3000 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3004 return iStaticServiceInformation::getInfoObject(ref, w);
3007 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");