1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
31 #error no byte order defined!
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 DECLARE_REF(eStaticServiceDVBInformation);
38 RESULT getName(const eServiceReference &ref, std::string &name);
39 int getLength(const eServiceReference &ref);
40 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41 PyObject *getInfoObject(const eServiceReference &ref, int);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
66 name=buildShortName(name) + " - ";
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 ePtr<eDVBResourceManager> res_mgr;
87 if ( eDVBResourceManager::getInstance( res_mgr ) )
88 eDebug("isPlayable... no res manager!!");
91 eDVBChannelID chid, chid_ignore;
92 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94 return res_mgr->canAllocateChannel(chid, chid_ignore);
99 extern void PutToDict(ePyObject &dict, const char*key, long value); // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
106 if (r.type == eServiceReference::idDVB)
108 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
111 case iServiceInformation::sTransponderData:
113 ePtr<eDVBResourceManager> res;
114 if (!eDVBResourceManager::getInstance(res))
116 ePtr<iDVBChannelList> db;
117 if (!res->getChannelList(db))
120 ref.getChannelID(chid);
121 ePtr<iDVBFrontendParameters> feparm;
122 if (!db->getChannelFrontendData(chid, feparm))
125 if (!feparm->getSystem(system))
127 ePyObject dict = PyDict_New();
130 case iDVBFrontend::feSatellite:
132 eDVBFrontendParametersSatellite s;
134 PutSatelliteDataToDict(dict, s);
137 case iDVBFrontend::feTerrestrial:
139 eDVBFrontendParametersTerrestrial t;
141 PutTerrestrialDataToDict(dict, t);
144 case iDVBFrontend::feCable:
146 eDVBFrontendParametersCable c;
148 PutCableDataToDict(dict, c);
152 eDebug("unknown frontend type %d", system);
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
171 ePtr<iDVBChannelList> db;
172 ePtr<eDVBResourceManager> res;
175 if ((err = eDVBResourceManager::getInstance(res)) != 0)
177 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
180 if ((err = res->getChannelList(db)) != 0)
182 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
187 if ((err = db->getBouquet(ref, bouquet)) != 0)
189 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
193 if ( bouquet && bouquet->m_bouquet_name.length() )
195 name = bouquet->m_bouquet_name;
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
204 if (ref.flags & eServiceReference::isGroup)
206 ePtr<iDVBChannelList> db;
207 ePtr<eDVBResourceManager> res;
209 if (eDVBResourceManager::getInstance(res))
211 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
215 if (res->getChannelList(db))
217 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
222 if (db->getBouquet(ref, bouquet))
224 eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
228 int prio_order = eDVBFrontend::getTypePriorityOrder();
230 eDVBChannelID chid, chid_ignore;
231 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
234 static unsigned char prio_map[6][3] = {
235 { 3, 2, 1 }, // -S -C -T
236 { 3, 1, 2 }, // -S -T -C
237 { 2, 3, 1 }, // -C -S -T
238 { 1, 3, 2 }, // -C -T -S
239 { 1, 2, 3 }, // -T -C -S
240 { 2, 1, 3 } // -T -S -C
242 ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243 int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
248 case 30000: // cached DVB-T channel
249 case 1: // DVB-T frontend
250 tmp = prio_map[prio_order][2];
252 case 40000: // cached DVB-C channel
254 tmp = prio_map[prio_order][1];
257 tmp = prio_map[prio_order][0];
262 m_playable_service = *it;
269 m_playable_service = eServiceReference();
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
278 #include <lib/dvb/epgcache.h>
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
282 return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
287 DECLARE_REF(eStaticServiceDVBPVRInformation);
288 eServiceReference m_ref;
289 eDVBMetaParser m_parser;
291 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292 RESULT getName(const eServiceReference &ref, std::string &name);
293 int getLength(const eServiceReference &ref);
294 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295 int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296 int getInfo(const eServiceReference &ref, int w);
297 std::string getInfoString(const eServiceReference &ref,int w);
298 PyObject *getInfoObject(const eServiceReference &r, int what);
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
306 m_parser.parseFile(ref.path);
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
311 ASSERT(ref == m_ref);
312 if (m_parser.m_name.size())
313 name = m_parser.m_name;
317 size_t n = name.rfind('/');
318 if (n != std::string::npos)
319 name = name.substr(n + 1);
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
326 ASSERT(ref == m_ref);
331 stat(ref.path.c_str(), &s);
333 if (tstools.openFile(ref.path.c_str(), 1))
336 /* check if cached data is still valid */
337 if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338 return m_parser.m_length / 90000;
340 /* open again, this time with stream info */
341 if (tstools.openFile(ref.path.c_str()))
344 /* otherwise, re-calc length and update meta file */
346 if (tstools.calcLen(len))
349 m_parser.m_length = len;
350 m_parser.m_filesize = s.st_size;
351 m_parser.updateMeta(ref.path);
352 return m_parser.m_length / 90000;
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
359 case iServiceInformation::sDescription:
360 return iServiceInformation::resIsString;
361 case iServiceInformation::sServiceref:
362 return iServiceInformation::resIsString;
363 case iServiceInformation::sFileSize:
364 return m_parser.m_filesize;
365 case iServiceInformation::sTimeCreate:
366 if (m_parser.m_time_create)
367 return m_parser.m_time_create;
369 return iServiceInformation::resNA;
371 return iServiceInformation::resNA;
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
379 case iServiceInformation::sDescription:
380 return m_parser.m_description;
381 case iServiceInformation::sServiceref:
382 return m_parser.m_ref.toString();
383 case iServiceInformation::sTags:
384 return m_parser.m_tags;
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
394 case iServiceInformation::sFileSize:
395 return PyLong_FromLongLong(m_parser.m_filesize);
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
403 if (!ref.path.empty())
405 ePtr<eServiceEvent> event = new eServiceEvent;
406 std::string filename = ref.path;
407 filename.erase(filename.length()-2, 2);
409 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
421 DECLARE_REF(eDVBPVRServiceOfflineOperations);
422 eServiceReferenceDVB m_ref;
424 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
426 RESULT deleteFromDisk(int simulate);
427 RESULT getListOfFilenames(std::list<std::string> &);
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
443 std::list<std::string> res;
444 if (getListOfFilenames(res))
447 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
449 eDebug("FATAL !! can't get background file eraser");
451 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
453 eDebug("Removing %s...", i->c_str());
455 eraser->erase(i->c_str());
457 ::unlink(i->c_str());
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
467 res.push_back(m_ref.path);
469 // handling for old splitted recordings (enigma 1)
474 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
476 if (stat(buf, &s) < 0)
481 res.push_back(m_ref.path + ".meta");
482 res.push_back(m_ref.path + ".ap");
483 res.push_back(m_ref.path + ".sc");
484 res.push_back(m_ref.path + ".cuts");
485 std::string tmp = m_ref.path;
486 tmp.erase(m_ref.path.length()-3);
487 res.push_back(tmp + ".eit");
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
493 const char *filename = m_ref.path.c_str();
494 eDebug("reindexing %s...", filename);
496 eMPEGStreamInformation info;
497 eMPEGStreamParserTS parser(info);
499 info.startSave(filename);
503 int err = f.open(m_ref.path.c_str(), 0);
507 off_t length = f.length();
508 unsigned char buffer[188*256*4];
511 off_t offset = f.lseek(0, SEEK_CUR);
512 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513 int r = f.read(buffer, sizeof(buffer));
518 parser.parseData(offset, buffer, r);
527 DEFINE_REF(eServiceFactoryDVB)
529 eServiceFactoryDVB::eServiceFactoryDVB()
531 ePtr<eServiceCenter> sc;
533 eServiceCenter::getPrivInstance(sc);
536 std::list<std::string> extensions;
537 extensions.push_back("ts");
538 extensions.push_back("trp");
539 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
542 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
543 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
546 eServiceFactoryDVB::~eServiceFactoryDVB()
548 ePtr<eServiceCenter> sc;
550 eServiceCenter::getPrivInstance(sc);
552 sc->removeServiceFactory(eServiceFactoryDVB::id);
555 DEFINE_REF(eDVBServiceList);
557 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
561 eDVBServiceList::~eDVBServiceList()
565 RESULT eDVBServiceList::startQuery()
567 ePtr<iDVBChannelList> db;
568 ePtr<eDVBResourceManager> res;
571 if ((err = eDVBResourceManager::getInstance(res)) != 0)
573 eDebug("no resource manager");
576 if ((err = res->getChannelList(db)) != 0)
578 eDebug("no channel list");
582 ePtr<eDVBChannelQuery> q;
584 if (!m_parent.path.empty())
586 eDVBChannelQuery::compile(q, m_parent.path);
589 eDebug("compile query failed");
594 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
596 eDebug("startQuery failed");
603 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
605 eServiceReferenceDVB ref;
610 while (!m_query->getNextResult(ref))
614 list.sort(iListableServiceCompare(this));
619 // The first argument of this function is a format string to specify the order and
620 // the content of the returned list
621 // useable format options are
622 // R = Service Reference (as swig object .. this is very slow)
623 // S = Service Reference (as python string object .. same as ref.toString())
624 // C = Service Reference (as python string object .. same as ref.toCompareString())
625 // N = Service Name (as python string object)
626 // n = Short Service Name (short name brakets used) (as python string object)
627 // when exactly one return value per service is selected in the format string,
628 // then each value is directly a list entry
629 // when more than one value is returned per service, then the list is a list of
631 // unknown format string chars are returned as python None values !
632 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
635 std::list<eServiceReference> tmplist;
638 if (!format || !(retcount=strlen(format)))
639 format = "R"; // just return service reference swig object ...
641 if (!getContent(tmplist, sorted))
643 int services=tmplist.size();
644 ePtr<iStaticServiceInformation> sptr;
645 eServiceCenterPtr service_center;
647 if (strchr(format, 'N') || strchr(format, 'n'))
648 eServiceCenter::getPrivInstance(service_center);
650 ret = PyList_New(services);
651 std::list<eServiceReference>::iterator it(tmplist.begin());
653 for (int cnt=0; cnt < services; ++cnt)
655 eServiceReference &ref=*it++;
656 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
657 for (int i=0; i < retcount; ++i)
662 case 'R': // service reference (swig)object
663 tmp = NEW_eServiceReference(ref);
665 case 'C': // service reference compare string
666 tmp = PyString_FromString(ref.toCompareString().c_str());
668 case 'S': // service reference string
669 tmp = PyString_FromString(ref.toString().c_str());
671 case 'N': // service name
674 service_center->info(ref, sptr);
678 sptr->getName(ref, name);
680 // filter short name brakets
682 while((pos = name.find("\xc2\x86")) != std::string::npos)
684 while((pos = name.find("\xc2\x87")) != std::string::npos)
688 tmp = PyString_FromString(name.c_str());
692 tmp = PyString_FromString("<n/a>");
694 case 'n': // short service name
697 service_center->info(ref, sptr);
701 sptr->getName(ref, name);
702 name = buildShortName(name);
704 tmp = PyString_FromString(name.c_str());
708 tmp = PyString_FromString("<n/a>");
721 PyTuple_SET_ITEM(tuple, i, tmp);
723 PyList_SET_ITEM(ret, cnt, tmp);
727 PyList_SET_ITEM(ret, cnt, tuple);
730 return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
733 RESULT eDVBServiceList::getNext(eServiceReference &ref)
738 return m_query->getNextResult((eServiceReferenceDVB&)ref);
741 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
743 if (m_parent.flags & eServiceReference::canDescent) // bouquet
745 ePtr<iDVBChannelList> db;
746 ePtr<eDVBResourceManager> resm;
748 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
751 if (db->getBouquet(m_parent, m_bouquet) != 0)
762 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
766 return m_bouquet->addService(ref, before);
769 RESULT eDVBServiceList::removeService(eServiceReference &ref)
773 return m_bouquet->removeService(ref);
776 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
780 return m_bouquet->moveService(ref, pos);
783 RESULT eDVBServiceList::flushChanges()
787 return m_bouquet->flushChanges();
790 RESULT eDVBServiceList::setListName(const std::string &name)
794 return m_bouquet->setListName(name);
797 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
799 ePtr<eDVBService> service;
800 int r = lookupService(service, ref);
803 // check resources...
804 ptr = new eDVBServicePlay(ref, service);
808 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
810 if (ref.path.empty())
812 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
821 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
823 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
824 if (list->startQuery())
834 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
836 /* is a listable service? */
837 if (ref.flags & eServiceReference::canDescent) // bouquet
839 if ( !ref.name.empty() ) // satellites or providers list
840 ptr = m_StaticServiceDVBInfo;
841 else // a dvb bouquet
842 ptr = m_StaticServiceDVBBouquetInfo;
844 else if (!ref.path.empty()) /* do we have a PVR service? */
845 ptr = new eStaticServiceDVBPVRInformation(ref);
846 else // normal dvb service
848 ePtr<eDVBService> service;
849 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
850 ptr = m_StaticServiceDVBInfo;
852 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
858 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
860 if (ref.path.empty())
866 ptr = new eDVBPVRServiceOfflineOperations(ref);
871 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
873 if (!ref.path.empty()) // playback
875 eDVBMetaParser parser;
876 int ret=parser.parseFile(ref.path);
877 service = new eDVBService;
879 eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
883 // TODO: handle the listing itself
884 // if (ref.... == -1) .. return "... bouquets ...";
885 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
887 ePtr<iDVBChannelList> db;
888 ePtr<eDVBResourceManager> res;
891 if ((err = eDVBResourceManager::getInstance(res)) != 0)
893 eDebug("no resource manager");
896 if ((err = res->getChannelList(db)) != 0)
898 eDebug("no channel list");
902 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
903 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
905 eDebug("getService failed!");
913 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
914 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
917 m_is_pvr = !m_reference.path.empty();
919 m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
920 m_skipmode = m_fastforward = m_slowmotion = 0;
922 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
923 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
924 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
926 m_cuesheet_changed = 0;
927 m_cutlist_enabled = 1;
929 m_subtitle_widget = 0;
933 m_subtitle_sync_timer = eTimer::create(eApp);
935 CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
938 eDVBServicePlay::~eDVBServicePlay()
943 int ret=meta.parseFile(m_reference.path);
947 meta.m_service_data="";
948 sprintf(tmp, "f:%x", m_dvb_service->m_flags);
949 meta.m_service_data += tmp;
951 for (int x=0; x < eDVBService::cacheMax; ++x)
953 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
956 sprintf(tmp, ",c:%02d%04x", x, entry);
957 meta.m_service_data += tmp;
960 meta.updateMeta(m_reference.path);
963 delete m_subtitle_widget;
966 void eDVBServicePlay::gotNewEvent()
970 ePtr<eServiceEvent> m_event_now, m_event_next;
971 getEvent(m_event_now, 0);
972 getEvent(m_event_next, 1);
975 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
977 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
979 m_event((iPlayableService*)this, evUpdatedEventInfo);
982 void eDVBServicePlay::serviceEvent(int event)
984 m_tune_state = event;
988 case eDVBServicePMTHandler::eventTuned:
990 ePtr<iDVBDemux> m_demux;
991 if (!m_service_handler.getDataDemux(m_demux))
993 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
994 int sid = ref.getParentServiceID().get();
996 sid = ref.getServiceID().get();
997 if ( ref.getParentTransportStreamID().get() &&
998 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
999 m_event_handler.startOther(m_demux, sid);
1001 m_event_handler.start(m_demux, sid);
1003 m_event((iPlayableService*)this, evTunedIn);
1006 case eDVBServicePMTHandler::eventNoResources:
1007 case eDVBServicePMTHandler::eventNoPAT:
1008 case eDVBServicePMTHandler::eventNoPATEntry:
1009 case eDVBServicePMTHandler::eventNoPMT:
1010 case eDVBServicePMTHandler::eventTuneFailed:
1011 case eDVBServicePMTHandler::eventMisconfiguration:
1013 eDebug("DVB service failed to tune - error %d", event);
1014 m_event((iPlayableService*)this, evTuneFailed);
1017 case eDVBServicePMTHandler::eventNewProgramInfo:
1019 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1020 if (m_timeshift_enabled)
1021 updateTimeshiftPids();
1022 if (!m_timeshift_active)
1024 if (m_first_program_info && m_is_pvr)
1026 m_first_program_info = 0;
1029 m_event((iPlayableService*)this, evUpdatedInfo);
1032 case eDVBServicePMTHandler::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 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1133 m_cuesheet_changed = 1;
1137 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1139 m_service_handler_timeshift.free();
1140 m_service_handler.free();
1142 if (m_is_pvr && m_cuesheet_changed)
1145 /* save cuesheet only when main file is accessible. */
1146 if (!::stat(m_reference.path.c_str(), &s))
1149 m_event((iPlayableService*)this, evStopped);
1153 RESULT eDVBServicePlay::setTarget(int target)
1155 m_is_primary = !target;
1159 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1161 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1165 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1167 /* note: we check for timeshift to be enabled,
1168 not neccessary active. if you pause when timeshift
1169 is not active, you should activate it when unpausing */
1170 if ((!m_is_pvr) && (!m_timeshift_enabled))
1180 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1182 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1183 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1184 setFastForward_internal(0);
1187 m_slowmotion = ratio;
1188 return m_decoder->setSlowMotion(ratio);
1194 RESULT eDVBServicePlay::setFastForward(int ratio)
1196 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1198 return setFastForward_internal(ratio);
1201 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1203 int skipmode, ffratio, ret = 0;
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;
1234 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1236 m_fastforward = ffratio;
1242 ; /* return m_decoder->play(); is done in caller*/
1243 else if (ffratio != 1)
1244 ret = m_decoder->setFastForward(ffratio);
1246 ret = m_decoder->setTrickmode();
1249 eDebug("final seek after trickplay ret %d", seekTo(pos));
1254 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1256 if (m_is_pvr || m_timeshift_enabled)
1266 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1267 RESULT eDVBServicePlay::getLength(pts_t &len)
1269 ePtr<iDVBPVRChannel> pvr_channel;
1271 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1274 return pvr_channel->getLength(len);
1277 RESULT eDVBServicePlay::pause()
1279 eDebug("eDVBServicePlay::pause");
1280 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1285 return m_decoder->pause();
1290 RESULT eDVBServicePlay::unpause()
1292 eDebug("eDVBServicePlay::unpause");
1293 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1298 return m_decoder->play();
1303 RESULT eDVBServicePlay::seekTo(pts_t to)
1305 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1307 if (!m_decode_demux)
1310 ePtr<iDVBPVRChannel> pvr_channel;
1312 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1318 m_cue->seekTo(0, to);
1319 m_dvb_subtitle_pages.clear();
1320 m_subtitle_pages.clear();
1325 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1327 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1329 if (!m_decode_demux)
1332 ePtr<iDVBPVRChannel> pvr_channel;
1334 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1339 /* HACK until we have skip-AP api */
1340 if ((to > 0) && (to < 100))
1348 m_cue->seekTo(mode, to);
1349 m_dvb_subtitle_pages.clear();
1350 m_subtitle_pages.clear();
1354 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1356 ePtr<iDVBPVRChannel> pvr_channel;
1358 if (!m_decode_demux)
1361 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1366 /* if there is a decoder, use audio or video PTS */
1369 r = m_decoder->getPTS(0, pos);
1375 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1378 RESULT eDVBServicePlay::setTrickmode(int trick)
1380 /* currently unimplemented */
1384 RESULT eDVBServicePlay::isCurrentlySeekable()
1389 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1390 if (m_decoder->getVideoProgressive() == -1)
1396 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1402 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1408 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1414 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1420 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1426 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1429 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1430 (m_timeshift_enabled || !m_is_pvr))
1432 if (!m_timeshift_enabled)
1434 /* query config path */
1436 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1437 eDebug("could not query ts path from config");
1441 /* we need enough diskspace */
1443 if (statfs(tspath.c_str(), &fs) < 0)
1445 eDebug("statfs failed!");
1449 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1451 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1461 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1472 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1478 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1484 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1490 RESULT eDVBServicePlay::getName(std::string &name)
1494 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1495 return i->getName(m_reference, name);
1497 else if (m_dvb_service)
1499 m_dvb_service->getName(m_reference, name);
1503 else if (!m_reference.name.empty())
1504 eStaticServiceDVBInformation().getName(m_reference, name);
1506 name = "DVB service";
1510 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1512 return m_event_handler.getEvent(evt, nownext);
1515 int eDVBServicePlay::getInfo(int w)
1517 eDVBServicePMTHandler::program program;
1520 return resIsPyObject;
1522 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1524 int no_program_info = 0;
1526 if (h.getProgramInfo(program))
1527 no_program_info = 1;
1533 return m_decoder->getVideoHeight();
1537 return m_decoder->getVideoWidth();
1541 return m_decoder->getVideoFrameRate();
1545 return m_decoder->getVideoProgressive();
1551 aspect = m_decoder->getVideoAspect();
1552 if (aspect == -1 && no_program_info)
1554 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1556 ePtr<eServiceEvent> evt;
1557 if (!m_event_handler.getEvent(evt, 0))
1559 ePtr<eComponentData> data;
1560 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1562 if ( data->getStreamContent() == 1 )
1564 switch(data->getComponentType())
1567 case 1: // 4:3 SD PAL
1569 case 3: // 16:9 SD PAL
1570 case 4: // > 16:9 PAL
1571 case 5: // 4:3 SD NTSC
1573 case 7: // 16:9 SD NTSC
1574 case 8: // > 16:9 NTSC
1577 case 9: // 4:3 HD PAL
1579 case 0xB: // 16:9 HD PAL
1580 case 0xC: // > 16:9 HD PAL
1581 case 0xD: // 4:3 HD NTSC
1583 case 0xF: // 16:9 HD NTSC
1584 case 0x10: // > 16:9 HD PAL
1585 return data->getComponentType();
1595 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1599 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1603 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1604 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1608 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1611 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1615 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1619 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1623 if (no_program_info) return -1; return program.pcrPid;
1624 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1625 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1626 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1627 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1628 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1629 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1630 case sProvider: if (!m_dvb_service) return -1; return -2;
1631 case sServiceref: return resIsString;
1632 case sDVBState: return m_tune_state;
1639 std::string eDVBServicePlay::getInfoString(int w)
1644 if (!m_dvb_service) return "";
1645 return m_dvb_service->m_provider_name;
1647 return m_reference.toString();
1651 return iServiceInformation::getInfoString(w);
1654 PyObject *eDVBServicePlay::getInfoObject(int w)
1659 return m_service_handler.getCaIds();
1660 case sTransponderData:
1661 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1665 return iServiceInformation::getInfoObject(w);
1668 int eDVBServicePlay::getNumberOfTracks()
1670 eDVBServicePMTHandler::program program;
1671 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1672 if (h.getProgramInfo(program))
1674 return program.audioStreams.size();
1677 int eDVBServicePlay::getCurrentTrack()
1679 eDVBServicePMTHandler::program program;
1680 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1681 if (h.getProgramInfo(program))
1684 int max = program.audioStreams.size();
1687 for (i = 0; i < max; ++i)
1688 if (program.audioStreams[i].pid == m_current_audio_pid)
1694 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1696 int ret = selectAudioStream(i);
1698 if (m_decoder->set())
1704 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1706 eDVBServicePMTHandler::program program;
1707 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1709 if (h.getProgramInfo(program))
1712 if (i >= program.audioStreams.size())
1715 info.m_pid = program.audioStreams[i].pid;
1717 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1718 info.m_description = "MPEG";
1719 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1720 info.m_description = "AC3";
1721 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1722 info.m_description = "AAC";
1723 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1724 info.m_description = "AAC-HE";
1725 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1726 info.m_description = "DTS";
1728 info.m_description = "???";
1730 if (program.audioStreams[i].component_tag != -1)
1732 ePtr<eServiceEvent> evt;
1733 if (!m_event_handler.getEvent(evt, 0))
1735 ePtr<eComponentData> data;
1736 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1737 info.m_language = data->getText();
1741 if (info.m_language.empty())
1742 info.m_language = program.audioStreams[i].language_code;
1747 int eDVBServicePlay::selectAudioStream(int i)
1749 eDVBServicePMTHandler::program program;
1750 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1751 pts_t position = -1;
1753 if (h.getProgramInfo(program))
1756 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1764 stream = program.defaultAudioStream;
1766 int apid = -1, apidtype = -1;
1768 if (((unsigned int)stream) < program.audioStreams.size())
1770 apid = program.audioStreams[stream].pid;
1771 apidtype = program.audioStreams[stream].type;
1774 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1775 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1777 m_current_audio_pid = apid;
1779 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1781 eDebug("set audio pid failed");
1786 eDebug("seekTo ret %d", seekTo(position));
1790 /* 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 */
1791 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1793 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1795 rdsPid = program.audioStreams[stream].rdsPid;
1796 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1799 ePtr<iDVBDemux> data_demux;
1800 if (!h.getDataDemux(data_demux))
1802 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1803 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1804 m_rds_decoder->start(rdsPid);
1809 /* store new pid as default only when:
1810 a.) we have an entry in the service db for the current service,
1811 b.) we are not playing back something,
1812 c.) we are not selecting the default entry. (we wouldn't change
1813 anything in the best case, or destroy the default setting in
1814 case the real default is not yet available.)
1816 if (m_dvb_service && ((i != -1)
1817 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1819 if (apidtype == eDVBAudio::aMPEG)
1821 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1822 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1824 else if (apidtype == eDVBAudio::aAC3)
1826 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1827 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1831 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1832 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1836 h.resetCachedProgram();
1841 int eDVBServicePlay::getCurrentChannel()
1843 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1846 RESULT eDVBServicePlay::selectChannel(int i)
1848 if (i < LEFT || i > RIGHT || i == STEREO)
1851 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1853 m_decoder->setAudioChannel(i);
1857 std::string eDVBServicePlay::getText(int x)
1863 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1865 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1870 void eDVBServicePlay::rdsDecoderEvent(int what)
1874 case eDVBRdsDecoder::RadioTextChanged:
1875 m_event((iPlayableService*)this, evUpdatedRadioText);
1877 case eDVBRdsDecoder::RtpTextChanged:
1878 m_event((iPlayableService*)this, evUpdatedRtpText);
1880 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1881 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1883 case eDVBRdsDecoder::RecvRassSlidePic:
1884 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1889 void eDVBServicePlay::showRassSlidePicture()
1895 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1896 if (rass_slide_pic.length())
1897 m_decoder->showSinglePic(rass_slide_pic.c_str());
1899 eDebug("empty filename for rass slide picture received!!");
1902 eDebug("no MPEG Decoder to show iframes avail");
1905 eDebug("showRassSlidePicture called.. but not decoder");
1908 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1914 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1915 if (rass_interactive_pic.length())
1916 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1918 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1921 eDebug("no MPEG Decoder to show iframes avail");
1924 eDebug("showRassInteractivePic called.. but not decoder");
1927 ePyObject eDVBServicePlay::getRassInteractiveMask()
1930 return m_rds_decoder->getRassPictureMask();
1934 int eDVBServiceBase::getFrontendInfo(int w)
1936 eUsePtr<iDVBChannel> channel;
1937 if(m_service_handler.getChannel(channel))
1939 ePtr<iDVBFrontend> fe;
1940 if(channel->getFrontend(fe))
1942 return fe->readFrontendData(w);
1945 PyObject *eDVBServiceBase::getFrontendData()
1947 ePyObject ret = PyDict_New();
1950 eUsePtr<iDVBChannel> channel;
1951 if(!m_service_handler.getChannel(channel))
1953 ePtr<iDVBFrontend> fe;
1954 if(!channel->getFrontend(fe))
1955 fe->getFrontendData(ret);
1963 PyObject *eDVBServiceBase::getFrontendStatus()
1965 ePyObject ret = PyDict_New();
1968 eUsePtr<iDVBChannel> channel;
1969 if(!m_service_handler.getChannel(channel))
1971 ePtr<iDVBFrontend> fe;
1972 if(!channel->getFrontend(fe))
1973 fe->getFrontendStatus(ret);
1981 PyObject *eDVBServiceBase::getTransponderData(bool original)
1983 ePyObject ret = PyDict_New();
1986 eUsePtr<iDVBChannel> channel;
1987 if(!m_service_handler.getChannel(channel))
1989 ePtr<iDVBFrontend> fe;
1990 if(!channel->getFrontend(fe))
1991 fe->getTransponderData(ret, original);
1999 PyObject *eDVBServiceBase::getAll(bool original)
2001 ePyObject ret = getTransponderData(original);
2004 eUsePtr<iDVBChannel> channel;
2005 if(!m_service_handler.getChannel(channel))
2007 ePtr<iDVBFrontend> fe;
2008 if(!channel->getFrontend(fe))
2010 fe->getFrontendData(ret);
2011 fe->getFrontendStatus(ret);
2018 int eDVBServicePlay::getNumberOfSubservices()
2020 ePtr<eServiceEvent> evt;
2021 if (!m_event_handler.getEvent(evt, 0))
2022 return evt->getNumOfLinkageServices();
2026 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2028 ePtr<eServiceEvent> evt;
2029 if (!m_event_handler.getEvent(evt, 0))
2031 if (!evt->getLinkageService(sub, m_reference, n))
2034 sub.type=eServiceReference::idInvalid;
2038 RESULT eDVBServicePlay::startTimeshift()
2040 ePtr<iDVBDemux> demux;
2042 eDebug("Start timeshift!");
2044 if (m_timeshift_enabled)
2047 /* start recording with the data demux. */
2048 if (m_service_handler.getDataDemux(demux))
2051 demux->createTSRecorder(m_record);
2056 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2057 eDebug("could not query ts path");
2060 tspath.append("/timeshift.XXXXXX");
2062 templ = new char[tspath.length() + 1];
2063 strcpy(templ, tspath.c_str());
2065 m_timeshift_fd = mkstemp(templ);
2066 m_timeshift_file = std::string(templ);
2068 eDebug("recording to %s", templ);
2072 if (m_timeshift_fd < 0)
2078 m_record->setTargetFD(m_timeshift_fd);
2080 m_timeshift_enabled = 1;
2082 updateTimeshiftPids();
2088 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2090 if (!m_timeshift_enabled)
2096 m_timeshift_enabled = 0;
2101 close(m_timeshift_fd);
2102 eDebug("remove timeshift file");
2103 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2108 int eDVBServicePlay::isTimeshiftActive()
2110 return m_timeshift_enabled && m_timeshift_active;
2113 RESULT eDVBServicePlay::activateTimeshift()
2115 if (!m_timeshift_enabled)
2118 if (!m_timeshift_active)
2120 switchToTimeshift();
2127 PyObject *eDVBServicePlay::getCutList()
2129 ePyObject list = PyList_New(0);
2131 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2133 ePyObject tuple = PyTuple_New(2);
2134 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2135 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2136 PyList_Append(list, tuple);
2143 void eDVBServicePlay::setCutList(ePyObject list)
2145 if (!PyList_Check(list))
2147 int size = PyList_Size(list);
2150 m_cue_entries.clear();
2152 for (i=0; i<size; ++i)
2154 ePyObject tuple = PyList_GET_ITEM(list, i);
2155 if (!PyTuple_Check(tuple))
2157 eDebug("non-tuple in cutlist");
2160 if (PyTuple_Size(tuple) != 2)
2162 eDebug("cutlist entries need to be a 2-tuple");
2165 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2166 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2168 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2171 pts_t pts = PyLong_AsLongLong(ppts);
2172 int type = PyInt_AsLong(ptype);
2173 m_cue_entries.insert(cueEntry(pts, type));
2174 eDebug("adding %08llx, %d", pts, type);
2176 m_cuesheet_changed = 1;
2178 cutlistToCuesheet();
2179 m_event((iPlayableService*)this, evCuesheetChanged);
2182 void eDVBServicePlay::setCutListEnable(int enable)
2184 m_cutlist_enabled = enable;
2185 cutlistToCuesheet();
2188 void eDVBServicePlay::updateTimeshiftPids()
2193 eDVBServicePMTHandler::program program;
2194 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2196 if (h.getProgramInfo(program))
2200 std::set<int> pids_to_record;
2201 pids_to_record.insert(0); // PAT
2202 if (program.pmtPid != -1)
2203 pids_to_record.insert(program.pmtPid); // PMT
2205 if (program.textPid != -1)
2206 pids_to_record.insert(program.textPid); // Videotext
2208 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2209 i(program.videoStreams.begin());
2210 i != program.videoStreams.end(); ++i)
2211 pids_to_record.insert(i->pid);
2213 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2214 i(program.audioStreams.begin());
2215 i != program.audioStreams.end(); ++i)
2216 pids_to_record.insert(i->pid);
2218 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2219 i(program.subtitleStreams.begin());
2220 i != program.subtitleStreams.end(); ++i)
2221 pids_to_record.insert(i->pid);
2223 std::set<int> new_pids, obsolete_pids;
2225 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2226 m_pids_active.begin(), m_pids_active.end(),
2227 std::inserter(new_pids, new_pids.begin()));
2229 std::set_difference(
2230 m_pids_active.begin(), m_pids_active.end(),
2231 pids_to_record.begin(), pids_to_record.end(),
2232 std::inserter(new_pids, new_pids.begin())
2235 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2236 m_record->addPID(*i);
2238 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2239 m_record->removePID(*i);
2243 void eDVBServicePlay::switchToLive()
2245 if (!m_timeshift_active)
2248 eDebug("SwitchToLive");
2253 m_teletext_parser = 0;
2255 m_subtitle_parser = 0;
2256 m_new_dvb_subtitle_page_connection = 0;
2257 m_new_subtitle_page_connection = 0;
2258 m_rds_decoder_event_connection = 0;
2259 m_video_event_connection = 0;
2260 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2262 /* free the timeshift service handler, we need the resources */
2263 m_service_handler_timeshift.free();
2264 m_timeshift_active = 0;
2265 m_timeshift_changed = 1;
2267 updateDecoder(true);
2270 void eDVBServicePlay::switchToTimeshift()
2272 if (m_timeshift_active)
2277 m_teletext_parser = 0;
2279 m_subtitle_parser = 0;
2280 m_new_subtitle_page_connection = 0;
2281 m_new_dvb_subtitle_page_connection = 0;
2282 m_rds_decoder_event_connection = 0;
2283 m_video_event_connection = 0;
2285 m_timeshift_active = 1;
2286 m_timeshift_changed = 1;
2288 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2289 r.path = m_timeshift_file;
2291 m_cue = new eCueSheet();
2292 m_cue->seekTo(0, -1000);
2293 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2295 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2297 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2300 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2302 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2303 bool mustPlay = false;
2305 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2307 eDVBServicePMTHandler::program program;
2308 if (h.getProgramInfo(program))
2309 eDebug("getting program info failed.");
2312 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2313 if (!program.videoStreams.empty())
2315 eDebugNoNewLine(" (");
2316 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2317 i(program.videoStreams.begin());
2318 i != program.videoStreams.end(); ++i)
2325 if (i != program.videoStreams.begin())
2326 eDebugNoNewLine(", ");
2327 eDebugNoNewLine("%04x", i->pid);
2329 eDebugNoNewLine(")");
2331 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2332 if (!program.audioStreams.empty())
2334 eDebugNoNewLine(" (");
2335 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2336 i(program.audioStreams.begin());
2337 i != program.audioStreams.end(); ++i)
2339 if (i != program.audioStreams.begin())
2340 eDebugNoNewLine(", ");
2341 eDebugNoNewLine("%04x", i->pid);
2343 eDebugNoNewLine(")");
2345 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2346 pcrpid = program.pcrPid;
2347 eDebug(", and the text pid is %04x", program.textPid);
2348 tpid = program.textPid;
2353 h.getDecodeDemux(m_decode_demux);
2354 if (m_timeshift_changed)
2358 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2360 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2363 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2364 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2365 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2366 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2367 if (m_timeshift_changed)
2369 ePyObject subs = getCachedSubtitle();
2370 if (subs != Py_None)
2372 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2373 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2374 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2375 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2376 if (type == 0) // dvb
2377 m_subtitle_parser->start(pid, comp_page, anc_page);
2378 else if (type == 1) // ttx
2379 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2386 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2390 m_timeshift_changed = 0;
2394 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2397 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2398 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2399 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2403 eServiceReferenceDVB ref;
2404 m_service_handler.getServiceReference(ref);
2405 eServiceReferenceDVB parent = ref.getParentServiceReference();
2410 ePtr<eDVBResourceManager> res_mgr;
2411 if (!eDVBResourceManager::getInstance(res_mgr))
2413 ePtr<iDVBChannelList> db;
2414 if (!res_mgr->getChannelList(db))
2416 ePtr<eDVBService> origService;
2417 if (!db->getService(parent, origService))
2419 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2420 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2427 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2428 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2430 m_decoder->setVideoPID(vpid, vpidtype);
2431 selectAudioStream();
2433 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2434 m_decoder->setSyncPCR(pcrpid);
2436 m_decoder->setSyncPCR(-1);
2440 m_decoder->setTextPID(tpid);
2441 m_teletext_parser->start(program.textPid);
2444 if (vpid > 0 && vpid < 0x2000)
2448 std::string radio_pic;
2449 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2450 m_decoder->setRadioPic(radio_pic);
2458 m_decoder->setAudioChannel(achannel);
2460 /* don't worry about non-existing services, nor pvr services */
2463 /* (audio pid will be set in selectAudioTrack */
2464 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2465 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2466 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2467 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2469 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2470 sendSeekableStateChanged = true;
2472 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2474 if (sendSeekableStateChanged)
2475 m_event((iPlayableService*)this, evSeekableStatusChanged);
2478 void eDVBServicePlay::loadCuesheet()
2480 std::string filename = m_reference.path + ".cuts";
2482 m_cue_entries.clear();
2484 FILE *f = fopen(filename.c_str(), "rb");
2488 eDebug("loading cuts..");
2491 unsigned long long where;
2494 if (!fread(&where, sizeof(where), 1, f))
2496 if (!fread(&what, sizeof(what), 1, f))
2499 #if BYTE_ORDER == LITTLE_ENDIAN
2500 where = bswap_64(where);
2507 m_cue_entries.insert(cueEntry(where, what));
2510 eDebug("%d entries", m_cue_entries.size());
2512 eDebug("cutfile not found!");
2514 m_cuesheet_changed = 0;
2515 cutlistToCuesheet();
2516 m_event((iPlayableService*)this, evCuesheetChanged);
2519 void eDVBServicePlay::saveCuesheet()
2521 std::string filename = m_reference.path + ".cuts";
2523 FILE *f = fopen(filename.c_str(), "wb");
2527 unsigned long long where;
2530 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2532 #if BYTE_ORDER == BIG_ENDIAN
2535 where = bswap_64(i->where);
2537 what = htonl(i->what);
2538 fwrite(&where, sizeof(where), 1, f);
2539 fwrite(&what, sizeof(what), 1, f);
2545 m_cuesheet_changed = 0;
2548 void eDVBServicePlay::cutlistToCuesheet()
2552 eDebug("no cue sheet");
2557 if (!m_cutlist_enabled)
2559 m_cue->commitSpans();
2560 eDebug("cutlists were disabled");
2564 pts_t in = 0, out = 0, length = 0;
2568 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2570 int have_any_span = 0;
2574 if (i == m_cue_entries.end())
2576 if (!have_any_span && !in)
2580 if (i->what == 0) /* in */
2584 } else if (i->what == 1) /* out */
2586 else /* mark (2) or last play position (3) */
2605 m_cue->addSourceSpan(in, out);
2611 if (i == m_cue_entries.end())
2614 m_cue->commitSpans();
2617 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2619 if (m_subtitle_widget)
2620 disableSubtitles(parent);
2623 int tuplesize = PyTuple_Size(tuple);
2626 if (!PyTuple_Check(tuple))
2632 entry = PyTuple_GET_ITEM(tuple, 0);
2634 if (!PyInt_Check(entry))
2637 type = PyInt_AsLong(entry);
2639 if (type == 1) // teletext subtitles
2641 int page, magazine, pid;
2645 if (!m_teletext_parser)
2647 eDebug("enable teletext subtitles.. no parser !!!");
2651 entry = PyTuple_GET_ITEM(tuple, 1);
2652 if (!PyInt_Check(entry))
2654 pid = PyInt_AsLong(entry);
2656 entry = PyTuple_GET_ITEM(tuple, 2);
2657 if (!PyInt_Check(entry))
2659 page = PyInt_AsLong(entry);
2661 entry = PyTuple_GET_ITEM(tuple, 3);
2662 if (!PyInt_Check(entry))
2664 magazine = PyInt_AsLong(entry);
2666 m_subtitle_widget = new eSubtitleWidget(parent);
2667 m_subtitle_widget->resize(parent->size()); /* full size */
2668 m_teletext_parser->setPageAndMagazine(page, magazine);
2670 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2674 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2675 if (!m_subtitle_parser)
2677 eDebug("enable dvb subtitles.. no parser !!!");
2683 entry = PyTuple_GET_ITEM(tuple, 1);
2684 if (!PyInt_Check(entry))
2686 pid = PyInt_AsLong(entry);
2688 entry = PyTuple_GET_ITEM(tuple, 2);
2689 if (!PyInt_Check(entry))
2691 composition_page_id = PyInt_AsLong(entry);
2693 entry = PyTuple_GET_ITEM(tuple, 3);
2694 if (!PyInt_Check(entry))
2696 ancillary_page_id = PyInt_AsLong(entry);
2698 m_subtitle_widget = new eSubtitleWidget(parent);
2699 m_subtitle_widget->resize(parent->size()); /* full size */
2700 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2702 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2708 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2709 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2710 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2714 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2716 delete m_subtitle_widget;
2717 m_subtitle_widget = 0;
2718 if (m_subtitle_parser)
2720 m_subtitle_parser->stop();
2721 m_dvb_subtitle_pages.clear();
2723 if (m_teletext_parser)
2725 m_teletext_parser->setPageAndMagazine(-1, -1);
2726 m_subtitle_pages.clear();
2729 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2733 PyObject *eDVBServicePlay::getCachedSubtitle()
2737 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2740 unsigned int data = (unsigned int)tmp;
2741 int pid = (data&0xFFFF0000)>>16;
2742 ePyObject tuple = PyTuple_New(4);
2743 eDVBServicePMTHandler::program program;
2744 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2745 if (!h.getProgramInfo(program))
2747 if (program.textPid==pid) // teletext
2748 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2750 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2751 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2752 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2753 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2761 PyObject *eDVBServicePlay::getSubtitleList()
2763 if (!m_teletext_parser)
2766 ePyObject l = PyList_New(0);
2767 std::set<int> added_ttx_pages;
2769 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2770 m_teletext_parser->m_found_subtitle_pages;
2772 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2773 eDVBServicePMTHandler::program program;
2774 if (h.getProgramInfo(program))
2775 eDebug("getting program info failed.");
2778 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2779 it != program.subtitleStreams.end(); ++it)
2781 switch(it->subtitling_type)
2783 case 0x01: // ebu teletext subtitles
2785 int page_number = it->teletext_page_number & 0xFF;
2786 int magazine_number = it->teletext_magazine_number & 7;
2787 int hash = magazine_number << 8 | page_number;
2788 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2790 ePyObject tuple = PyTuple_New(5);
2791 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2792 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2793 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2794 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2795 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2796 PyList_Append(l, tuple);
2798 added_ttx_pages.insert(hash);
2803 case 0x20 ... 0x23: // dvb subtitles
2805 ePyObject tuple = PyTuple_New(5);
2806 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2807 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2808 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2809 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2810 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2811 PyList_Insert(l, 0, tuple);
2819 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2820 it != subs.end(); ++it)
2822 int page_number = it->teletext_page_number & 0xFF;
2823 int magazine_number = it->teletext_magazine_number & 7;
2824 int hash = magazine_number << 8 | page_number;
2825 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2827 ePyObject tuple = PyTuple_New(5);
2828 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2829 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2830 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2831 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2832 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2833 PyList_Append(l, tuple);
2841 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2843 if (m_subtitle_widget)
2847 m_decoder->getPTS(0, pos);
2848 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2849 m_subtitle_pages.push_back(page);
2850 checkSubtitleTiming();
2854 void eDVBServicePlay::checkSubtitleTiming()
2856 eDebug("checkSubtitleTiming");
2857 if (!m_subtitle_widget)
2861 enum { TELETEXT, DVB } type;
2862 eDVBTeletextSubtitlePage page;
2863 eDVBSubtitlePage dvb_page;
2865 if (!m_subtitle_pages.empty())
2867 page = m_subtitle_pages.front();
2869 show_time = page.m_pts;
2871 else if (!m_dvb_subtitle_pages.empty())
2873 dvb_page = m_dvb_subtitle_pages.front();
2875 show_time = dvb_page.m_show_time;
2883 m_decoder->getPTS(0, pos);
2885 eDebug("%lld %lld", pos, show_time);
2886 int diff = show_time - pos;
2887 if (type == TELETEXT && !page.m_have_pts)
2889 eDebug("ttx subtitle page without pts... immediate show");
2894 eDebug("[late (%d ms)]", -diff / 90);
2897 if (abs(diff) > 1800000)
2899 eDebug("[invalid]... immediate show!");
2904 if (type == TELETEXT)
2906 eDebug("display teletext subtitle page %lld", show_time);
2907 m_subtitle_widget->setPage(page);
2908 m_subtitle_pages.pop_front();
2912 eDebug("display dvb subtitle Page %lld", show_time);
2913 m_subtitle_widget->setPage(dvb_page);
2914 m_dvb_subtitle_pages.pop_front();
2918 eDebug("start subtitle delay %d", diff / 90);
2919 m_subtitle_sync_timer->start(diff / 90, 1);
2925 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2927 if (m_subtitle_widget)
2931 m_decoder->getPTS(0, pos);
2932 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2933 m_dvb_subtitle_pages.push_back(p);
2934 checkSubtitleTiming();
2938 int eDVBServicePlay::getAC3Delay()
2941 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2943 return m_decoder->getAC3Delay();
2948 int eDVBServicePlay::getPCMDelay()
2951 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2953 return m_decoder->getPCMDelay();
2958 void eDVBServicePlay::setAC3Delay(int delay)
2961 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2963 std::string config_delay;
2964 int config_delay_int = 0;
2965 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2966 config_delay_int = atoi(config_delay.c_str());
2967 m_decoder->setAC3Delay(delay + config_delay_int);
2971 void eDVBServicePlay::setPCMDelay(int delay)
2974 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2976 std::string config_delay;
2977 int config_delay_int = 0;
2978 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2979 config_delay_int = atoi(config_delay.c_str());
2981 config_delay_int = 0;
2982 m_decoder->setPCMDelay(delay + config_delay_int);
2986 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2988 switch(event.type) {
2989 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2990 m_event((iPlayableService*)this, evVideoSizeChanged);
2992 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2993 m_event((iPlayableService*)this, evVideoFramerateChanged);
2995 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2996 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3003 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3009 PyObject *eDVBServicePlay::getStreamingData()
3011 eDVBServicePMTHandler::program program;
3012 if (m_service_handler.getProgramInfo(program))
3017 ePyObject r = program.createPythonObject();
3018 ePtr<iDVBDemux> demux;
3019 if (!m_service_handler.getDataDemux(demux))
3022 if (!demux->getCADemuxID(demux_id))
3023 PutToDict(r, "demux", demux_id);
3030 DEFINE_REF(eDVBServicePlay)
3032 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3036 case iServiceInformation::sTransponderData:
3037 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3041 return iStaticServiceInformation::getInfoObject(ref, w);
3044 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");