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 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);
1191 m_slowmotion = ratio;
1192 return m_decoder->setSlowMotion(ratio);
1198 RESULT eDVBServicePlay::setFastForward(int ratio)
1200 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1202 return setFastForward_internal(ratio);
1205 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1207 int skipmode, ffratio, ret = 0;
1214 } else if (ratio > 0)
1222 } else // if (ratio < 0)
1228 if (m_skipmode != skipmode)
1230 eDebug("setting cue skipmode to %d", skipmode);
1232 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1235 m_skipmode = skipmode;
1238 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1240 m_fastforward = ffratio;
1246 ; /* return m_decoder->play(); is done in caller*/
1247 else if (ffratio != 1)
1248 ret = m_decoder->setFastForward(ffratio);
1250 ret = m_decoder->setTrickmode();
1253 eDebug("final seek after trickplay ret %d", seekTo(pos));
1258 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1260 if (m_is_pvr || m_timeshift_enabled)
1270 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1271 RESULT eDVBServicePlay::getLength(pts_t &len)
1273 ePtr<iDVBPVRChannel> pvr_channel;
1275 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1278 return pvr_channel->getLength(len);
1281 RESULT eDVBServicePlay::pause()
1283 eDebug("eDVBServicePlay::pause");
1284 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1289 return m_decoder->pause();
1294 RESULT eDVBServicePlay::unpause()
1296 eDebug("eDVBServicePlay::unpause");
1297 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1302 return m_decoder->play();
1307 RESULT eDVBServicePlay::seekTo(pts_t to)
1309 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1311 if (!m_decode_demux)
1314 ePtr<iDVBPVRChannel> pvr_channel;
1316 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1322 m_cue->seekTo(0, to);
1323 m_dvb_subtitle_pages.clear();
1324 m_subtitle_pages.clear();
1329 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1331 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1333 if (!m_decode_demux)
1336 ePtr<iDVBPVRChannel> pvr_channel;
1338 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1343 /* HACK until we have skip-AP api */
1344 if ((to > 0) && (to < 100))
1352 m_cue->seekTo(mode, to);
1353 m_dvb_subtitle_pages.clear();
1354 m_subtitle_pages.clear();
1358 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1360 ePtr<iDVBPVRChannel> pvr_channel;
1362 if (!m_decode_demux)
1365 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1370 /* if there is a decoder, use audio or video PTS */
1373 r = m_decoder->getPTS(0, pos);
1379 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1382 RESULT eDVBServicePlay::setTrickmode(int trick)
1384 /* currently unimplemented */
1388 RESULT eDVBServicePlay::isCurrentlySeekable()
1393 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1394 if (m_decoder->getVideoProgressive() == -1)
1400 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1406 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1412 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1418 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1424 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1430 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1433 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1434 (m_timeshift_enabled || !m_is_pvr))
1436 if (!m_timeshift_enabled)
1438 /* query config path */
1440 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1441 eDebug("could not query ts path from config");
1445 /* we need enough diskspace */
1447 if (statfs(tspath.c_str(), &fs) < 0)
1449 eDebug("statfs failed!");
1453 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1455 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1465 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1476 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1482 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1488 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1494 RESULT eDVBServicePlay::getName(std::string &name)
1498 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1499 return i->getName(m_reference, name);
1501 else if (m_dvb_service)
1503 m_dvb_service->getName(m_reference, name);
1507 else if (!m_reference.name.empty())
1508 eStaticServiceDVBInformation().getName(m_reference, name);
1510 name = "DVB service";
1514 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1516 return m_event_handler.getEvent(evt, nownext);
1519 int eDVBServicePlay::getInfo(int w)
1521 eDVBServicePMTHandler::program program;
1524 return resIsPyObject;
1526 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1528 int no_program_info = 0;
1530 if (h.getProgramInfo(program))
1531 no_program_info = 1;
1537 return m_decoder->getVideoHeight();
1541 return m_decoder->getVideoWidth();
1545 return m_decoder->getVideoFrameRate();
1549 return m_decoder->getVideoProgressive();
1555 aspect = m_decoder->getVideoAspect();
1556 if (aspect == -1 && no_program_info)
1558 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1560 ePtr<eServiceEvent> evt;
1561 if (!m_event_handler.getEvent(evt, 0))
1563 ePtr<eComponentData> data;
1564 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1566 if ( data->getStreamContent() == 1 )
1568 switch(data->getComponentType())
1571 case 1: // 4:3 SD PAL
1573 case 3: // 16:9 SD PAL
1574 case 4: // > 16:9 PAL
1575 case 5: // 4:3 SD NTSC
1577 case 7: // 16:9 SD NTSC
1578 case 8: // > 16:9 NTSC
1581 case 9: // 4:3 HD PAL
1583 case 0xB: // 16:9 HD PAL
1584 case 0xC: // > 16:9 HD PAL
1585 case 0xD: // 4:3 HD NTSC
1587 case 0xF: // 16:9 HD NTSC
1588 case 0x10: // > 16:9 HD PAL
1589 return data->getComponentType();
1599 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1603 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1607 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1608 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1612 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1615 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1619 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1623 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1627 if (no_program_info) return -1; return program.pcrPid;
1628 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1629 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1630 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1631 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1632 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1633 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1634 case sProvider: if (!m_dvb_service) return -1; return -2;
1635 case sServiceref: return resIsString;
1636 case sDVBState: return m_tune_state;
1643 std::string eDVBServicePlay::getInfoString(int w)
1648 if (!m_dvb_service) return "";
1649 return m_dvb_service->m_provider_name;
1651 return m_reference.toString();
1655 return iServiceInformation::getInfoString(w);
1658 PyObject *eDVBServicePlay::getInfoObject(int w)
1663 return m_service_handler.getCaIds();
1664 case sTransponderData:
1665 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1669 return iServiceInformation::getInfoObject(w);
1672 int eDVBServicePlay::getNumberOfTracks()
1674 eDVBServicePMTHandler::program program;
1675 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1676 if (h.getProgramInfo(program))
1678 return program.audioStreams.size();
1681 int eDVBServicePlay::getCurrentTrack()
1683 eDVBServicePMTHandler::program program;
1684 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1685 if (h.getProgramInfo(program))
1688 int max = program.audioStreams.size();
1691 for (i = 0; i < max; ++i)
1692 if (program.audioStreams[i].pid == m_current_audio_pid)
1698 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1700 int ret = selectAudioStream(i);
1702 if (m_decoder->set())
1708 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1710 eDVBServicePMTHandler::program program;
1711 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1713 if (h.getProgramInfo(program))
1716 if (i >= program.audioStreams.size())
1719 info.m_pid = program.audioStreams[i].pid;
1721 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1722 info.m_description = "MPEG";
1723 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1724 info.m_description = "AC3";
1725 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1726 info.m_description = "AAC";
1727 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1728 info.m_description = "AAC-HE";
1729 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1730 info.m_description = "DTS";
1732 info.m_description = "???";
1734 if (program.audioStreams[i].component_tag != -1)
1736 ePtr<eServiceEvent> evt;
1737 if (!m_event_handler.getEvent(evt, 0))
1739 ePtr<eComponentData> data;
1740 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1741 info.m_language = data->getText();
1745 if (info.m_language.empty())
1746 info.m_language = program.audioStreams[i].language_code;
1751 int eDVBServicePlay::selectAudioStream(int i)
1753 eDVBServicePMTHandler::program program;
1754 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1755 pts_t position = -1;
1757 if (h.getProgramInfo(program))
1760 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1768 stream = program.defaultAudioStream;
1770 int apid = -1, apidtype = -1;
1772 if (((unsigned int)stream) < program.audioStreams.size())
1774 apid = program.audioStreams[stream].pid;
1775 apidtype = program.audioStreams[stream].type;
1778 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1779 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1781 m_current_audio_pid = apid;
1783 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1785 eDebug("set audio pid failed");
1790 eDebug("seekTo ret %d", seekTo(position));
1794 /* 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 */
1795 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1797 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1799 rdsPid = program.audioStreams[stream].rdsPid;
1800 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1803 ePtr<iDVBDemux> data_demux;
1804 if (!h.getDataDemux(data_demux))
1806 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1807 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1808 m_rds_decoder->start(rdsPid);
1813 /* store new pid as default only when:
1814 a.) we have an entry in the service db for the current service,
1815 b.) we are not playing back something,
1816 c.) we are not selecting the default entry. (we wouldn't change
1817 anything in the best case, or destroy the default setting in
1818 case the real default is not yet available.)
1820 if (m_dvb_service && ((i != -1)
1821 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1823 if (apidtype == eDVBAudio::aMPEG)
1825 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1826 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1828 else if (apidtype == eDVBAudio::aAC3)
1830 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1831 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1835 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1836 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1840 h.resetCachedProgram();
1845 int eDVBServicePlay::getCurrentChannel()
1847 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1850 RESULT eDVBServicePlay::selectChannel(int i)
1852 if (i < LEFT || i > RIGHT || i == STEREO)
1855 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1857 m_decoder->setAudioChannel(i);
1861 std::string eDVBServicePlay::getText(int x)
1867 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1869 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1874 void eDVBServicePlay::rdsDecoderEvent(int what)
1878 case eDVBRdsDecoder::RadioTextChanged:
1879 m_event((iPlayableService*)this, evUpdatedRadioText);
1881 case eDVBRdsDecoder::RtpTextChanged:
1882 m_event((iPlayableService*)this, evUpdatedRtpText);
1884 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1885 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1887 case eDVBRdsDecoder::RecvRassSlidePic:
1888 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1893 void eDVBServicePlay::showRassSlidePicture()
1899 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1900 if (rass_slide_pic.length())
1901 m_decoder->showSinglePic(rass_slide_pic.c_str());
1903 eDebug("empty filename for rass slide picture received!!");
1906 eDebug("no MPEG Decoder to show iframes avail");
1909 eDebug("showRassSlidePicture called.. but not decoder");
1912 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1918 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1919 if (rass_interactive_pic.length())
1920 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1922 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1925 eDebug("no MPEG Decoder to show iframes avail");
1928 eDebug("showRassInteractivePic called.. but not decoder");
1931 ePyObject eDVBServicePlay::getRassInteractiveMask()
1934 return m_rds_decoder->getRassPictureMask();
1938 int eDVBServiceBase::getFrontendInfo(int w)
1940 eUsePtr<iDVBChannel> channel;
1941 if(m_service_handler.getChannel(channel))
1943 ePtr<iDVBFrontend> fe;
1944 if(channel->getFrontend(fe))
1946 return fe->readFrontendData(w);
1949 PyObject *eDVBServiceBase::getFrontendData()
1951 ePyObject ret = PyDict_New();
1954 eUsePtr<iDVBChannel> channel;
1955 if(!m_service_handler.getChannel(channel))
1957 ePtr<iDVBFrontend> fe;
1958 if(!channel->getFrontend(fe))
1959 fe->getFrontendData(ret);
1967 PyObject *eDVBServiceBase::getFrontendStatus()
1969 ePyObject ret = PyDict_New();
1972 eUsePtr<iDVBChannel> channel;
1973 if(!m_service_handler.getChannel(channel))
1975 ePtr<iDVBFrontend> fe;
1976 if(!channel->getFrontend(fe))
1977 fe->getFrontendStatus(ret);
1985 PyObject *eDVBServiceBase::getTransponderData(bool original)
1987 ePyObject ret = PyDict_New();
1990 eUsePtr<iDVBChannel> channel;
1991 if(!m_service_handler.getChannel(channel))
1993 ePtr<iDVBFrontend> fe;
1994 if(!channel->getFrontend(fe))
1995 fe->getTransponderData(ret, original);
2003 PyObject *eDVBServiceBase::getAll(bool original)
2005 ePyObject ret = getTransponderData(original);
2008 eUsePtr<iDVBChannel> channel;
2009 if(!m_service_handler.getChannel(channel))
2011 ePtr<iDVBFrontend> fe;
2012 if(!channel->getFrontend(fe))
2014 fe->getFrontendData(ret);
2015 fe->getFrontendStatus(ret);
2022 int eDVBServicePlay::getNumberOfSubservices()
2024 ePtr<eServiceEvent> evt;
2025 if (!m_event_handler.getEvent(evt, 0))
2026 return evt->getNumOfLinkageServices();
2030 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2032 ePtr<eServiceEvent> evt;
2033 if (!m_event_handler.getEvent(evt, 0))
2035 if (!evt->getLinkageService(sub, m_reference, n))
2038 sub.type=eServiceReference::idInvalid;
2042 RESULT eDVBServicePlay::startTimeshift()
2044 ePtr<iDVBDemux> demux;
2046 eDebug("Start timeshift!");
2048 if (m_timeshift_enabled)
2051 /* start recording with the data demux. */
2052 if (m_service_handler.getDataDemux(demux))
2055 demux->createTSRecorder(m_record);
2060 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2061 eDebug("could not query ts path");
2064 tspath.append("/timeshift.XXXXXX");
2066 templ = new char[tspath.length() + 1];
2067 strcpy(templ, tspath.c_str());
2069 m_timeshift_fd = mkstemp(templ);
2070 m_timeshift_file = std::string(templ);
2072 eDebug("recording to %s", templ);
2076 if (m_timeshift_fd < 0)
2082 m_record->setTargetFD(m_timeshift_fd);
2084 m_timeshift_enabled = 1;
2086 updateTimeshiftPids();
2092 RESULT eDVBServicePlay::stopTimeshift()
2094 if (!m_timeshift_enabled)
2099 m_timeshift_enabled = 0;
2104 close(m_timeshift_fd);
2105 eDebug("remove timeshift file");
2106 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2111 int eDVBServicePlay::isTimeshiftActive()
2113 return m_timeshift_enabled && m_timeshift_active;
2116 RESULT eDVBServicePlay::activateTimeshift()
2118 if (!m_timeshift_enabled)
2121 if (!m_timeshift_active)
2123 switchToTimeshift();
2130 PyObject *eDVBServicePlay::getCutList()
2132 ePyObject list = PyList_New(0);
2134 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2136 ePyObject tuple = PyTuple_New(2);
2137 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2138 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2139 PyList_Append(list, tuple);
2146 void eDVBServicePlay::setCutList(ePyObject list)
2148 if (!PyList_Check(list))
2150 int size = PyList_Size(list);
2153 m_cue_entries.clear();
2155 for (i=0; i<size; ++i)
2157 ePyObject tuple = PyList_GET_ITEM(list, i);
2158 if (!PyTuple_Check(tuple))
2160 eDebug("non-tuple in cutlist");
2163 if (PyTuple_Size(tuple) != 2)
2165 eDebug("cutlist entries need to be a 2-tuple");
2168 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2169 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2171 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2174 pts_t pts = PyLong_AsLongLong(ppts);
2175 int type = PyInt_AsLong(ptype);
2176 m_cue_entries.insert(cueEntry(pts, type));
2177 eDebug("adding %08llx, %d", pts, type);
2179 m_cuesheet_changed = 1;
2181 cutlistToCuesheet();
2182 m_event((iPlayableService*)this, evCuesheetChanged);
2185 void eDVBServicePlay::setCutListEnable(int enable)
2187 m_cutlist_enabled = enable;
2188 cutlistToCuesheet();
2191 void eDVBServicePlay::updateTimeshiftPids()
2196 eDVBServicePMTHandler::program program;
2197 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2199 if (h.getProgramInfo(program))
2203 std::set<int> pids_to_record;
2204 pids_to_record.insert(0); // PAT
2205 if (program.pmtPid != -1)
2206 pids_to_record.insert(program.pmtPid); // PMT
2208 if (program.textPid != -1)
2209 pids_to_record.insert(program.textPid); // Videotext
2211 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2212 i(program.videoStreams.begin());
2213 i != program.videoStreams.end(); ++i)
2214 pids_to_record.insert(i->pid);
2216 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2217 i(program.audioStreams.begin());
2218 i != program.audioStreams.end(); ++i)
2219 pids_to_record.insert(i->pid);
2221 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2222 i(program.subtitleStreams.begin());
2223 i != program.subtitleStreams.end(); ++i)
2224 pids_to_record.insert(i->pid);
2226 std::set<int> new_pids, obsolete_pids;
2228 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2229 m_pids_active.begin(), m_pids_active.end(),
2230 std::inserter(new_pids, new_pids.begin()));
2232 std::set_difference(
2233 m_pids_active.begin(), m_pids_active.end(),
2234 pids_to_record.begin(), pids_to_record.end(),
2235 std::inserter(new_pids, new_pids.begin())
2238 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2239 m_record->addPID(*i);
2241 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2242 m_record->removePID(*i);
2246 void eDVBServicePlay::switchToLive()
2248 if (!m_timeshift_active)
2251 eDebug("SwitchToLive");
2256 m_teletext_parser = 0;
2258 m_subtitle_parser = 0;
2259 m_new_dvb_subtitle_page_connection = 0;
2260 m_new_subtitle_page_connection = 0;
2261 m_rds_decoder_event_connection = 0;
2262 m_video_event_connection = 0;
2263 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2265 /* free the timeshift service handler, we need the resources */
2266 m_service_handler_timeshift.free();
2267 m_timeshift_active = 0;
2268 m_timeshift_changed = 1;
2270 updateDecoder(true);
2273 void eDVBServicePlay::switchToTimeshift()
2275 if (m_timeshift_active)
2280 m_teletext_parser = 0;
2282 m_subtitle_parser = 0;
2283 m_new_subtitle_page_connection = 0;
2284 m_new_dvb_subtitle_page_connection = 0;
2285 m_rds_decoder_event_connection = 0;
2286 m_video_event_connection = 0;
2288 m_timeshift_active = 1;
2289 m_timeshift_changed = 1;
2291 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2292 r.path = m_timeshift_file;
2294 m_cue = new eCueSheet();
2295 m_cue->seekTo(0, -1000);
2296 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2298 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2300 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2303 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2305 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2306 bool mustPlay = false;
2308 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2310 eDVBServicePMTHandler::program program;
2311 if (h.getProgramInfo(program))
2312 eDebug("getting program info failed.");
2315 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2316 if (!program.videoStreams.empty())
2318 eDebugNoNewLine(" (");
2319 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2320 i(program.videoStreams.begin());
2321 i != program.videoStreams.end(); ++i)
2328 if (i != program.videoStreams.begin())
2329 eDebugNoNewLine(", ");
2330 eDebugNoNewLine("%04x", i->pid);
2332 eDebugNoNewLine(")");
2334 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2335 if (!program.audioStreams.empty())
2337 eDebugNoNewLine(" (");
2338 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2339 i(program.audioStreams.begin());
2340 i != program.audioStreams.end(); ++i)
2342 if (i != program.audioStreams.begin())
2343 eDebugNoNewLine(", ");
2344 eDebugNoNewLine("%04x", i->pid);
2346 eDebugNoNewLine(")");
2348 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2349 pcrpid = program.pcrPid;
2350 eDebug(", and the text pid is %04x", program.textPid);
2351 tpid = program.textPid;
2356 h.getDecodeDemux(m_decode_demux);
2357 if (m_timeshift_changed)
2361 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2363 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2366 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2367 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2368 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2369 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2370 if (m_timeshift_changed)
2372 ePyObject subs = getCachedSubtitle();
2373 if (subs != Py_None)
2375 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2376 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2377 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2378 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2379 if (type == 0) // dvb
2380 m_subtitle_parser->start(pid, comp_page, anc_page);
2381 else if (type == 1) // ttx
2382 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2389 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2393 m_timeshift_changed = 0;
2397 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2400 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2401 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2402 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2406 eServiceReferenceDVB ref;
2407 m_service_handler.getServiceReference(ref);
2408 eServiceReferenceDVB parent = ref.getParentServiceReference();
2413 ePtr<eDVBResourceManager> res_mgr;
2414 if (!eDVBResourceManager::getInstance(res_mgr))
2416 ePtr<iDVBChannelList> db;
2417 if (!res_mgr->getChannelList(db))
2419 ePtr<eDVBService> origService;
2420 if (!db->getService(parent, origService))
2422 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2423 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2430 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2431 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2433 m_decoder->setVideoPID(vpid, vpidtype);
2434 selectAudioStream();
2436 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2437 m_decoder->setSyncPCR(pcrpid);
2439 m_decoder->setSyncPCR(-1);
2443 m_decoder->setTextPID(tpid);
2444 m_teletext_parser->start(program.textPid);
2447 if (vpid > 0 && vpid < 0x2000)
2451 std::string radio_pic;
2452 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2453 m_decoder->setRadioPic(radio_pic);
2461 m_decoder->setAudioChannel(achannel);
2463 /* don't worry about non-existing services, nor pvr services */
2466 /* (audio pid will be set in selectAudioTrack */
2467 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2468 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2469 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2470 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2472 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2473 sendSeekableStateChanged = true;
2475 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2477 if (sendSeekableStateChanged)
2478 m_event((iPlayableService*)this, evSeekableStatusChanged);
2481 void eDVBServicePlay::loadCuesheet()
2483 std::string filename = m_reference.path + ".cuts";
2485 m_cue_entries.clear();
2487 FILE *f = fopen(filename.c_str(), "rb");
2491 eDebug("loading cuts..");
2494 unsigned long long where;
2497 if (!fread(&where, sizeof(where), 1, f))
2499 if (!fread(&what, sizeof(what), 1, f))
2502 #if BYTE_ORDER == LITTLE_ENDIAN
2503 where = bswap_64(where);
2510 m_cue_entries.insert(cueEntry(where, what));
2513 eDebug("%d entries", m_cue_entries.size());
2515 eDebug("cutfile not found!");
2517 m_cuesheet_changed = 0;
2518 cutlistToCuesheet();
2519 m_event((iPlayableService*)this, evCuesheetChanged);
2522 void eDVBServicePlay::saveCuesheet()
2524 std::string filename = m_reference.path + ".cuts";
2526 FILE *f = fopen(filename.c_str(), "wb");
2530 unsigned long long where;
2533 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2535 #if BYTE_ORDER == BIG_ENDIAN
2538 where = bswap_64(i->where);
2540 what = htonl(i->what);
2541 fwrite(&where, sizeof(where), 1, f);
2542 fwrite(&what, sizeof(what), 1, f);
2548 m_cuesheet_changed = 0;
2551 void eDVBServicePlay::cutlistToCuesheet()
2555 eDebug("no cue sheet");
2560 if (!m_cutlist_enabled)
2562 m_cue->commitSpans();
2563 eDebug("cutlists were disabled");
2567 pts_t in = 0, out = 0, length = 0;
2571 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2573 int have_any_span = 0;
2577 if (i == m_cue_entries.end())
2583 if (i->what == 0) /* in */
2587 } else if (i->what == 1) /* out */
2589 else /* mark (2) or last play position (3) */
2608 m_cue->addSourceSpan(in, out);
2613 if (i == m_cue_entries.end())
2616 m_cue->commitSpans();
2619 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2621 if (m_subtitle_widget)
2622 disableSubtitles(parent);
2625 int tuplesize = PyTuple_Size(tuple);
2628 if (!PyTuple_Check(tuple))
2634 entry = PyTuple_GET_ITEM(tuple, 0);
2636 if (!PyInt_Check(entry))
2639 type = PyInt_AsLong(entry);
2641 if (type == 1) // teletext subtitles
2643 int page, magazine, pid;
2647 if (!m_teletext_parser)
2649 eDebug("enable teletext subtitles.. no parser !!!");
2653 entry = PyTuple_GET_ITEM(tuple, 1);
2654 if (!PyInt_Check(entry))
2656 pid = PyInt_AsLong(entry);
2658 entry = PyTuple_GET_ITEM(tuple, 2);
2659 if (!PyInt_Check(entry))
2661 page = PyInt_AsLong(entry);
2663 entry = PyTuple_GET_ITEM(tuple, 3);
2664 if (!PyInt_Check(entry))
2666 magazine = PyInt_AsLong(entry);
2668 m_subtitle_widget = new eSubtitleWidget(parent);
2669 m_subtitle_widget->resize(parent->size()); /* full size */
2670 m_teletext_parser->setPageAndMagazine(page, magazine);
2672 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2676 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2677 if (!m_subtitle_parser)
2679 eDebug("enable dvb subtitles.. no parser !!!");
2685 entry = PyTuple_GET_ITEM(tuple, 1);
2686 if (!PyInt_Check(entry))
2688 pid = PyInt_AsLong(entry);
2690 entry = PyTuple_GET_ITEM(tuple, 2);
2691 if (!PyInt_Check(entry))
2693 composition_page_id = PyInt_AsLong(entry);
2695 entry = PyTuple_GET_ITEM(tuple, 3);
2696 if (!PyInt_Check(entry))
2698 ancillary_page_id = PyInt_AsLong(entry);
2700 m_subtitle_widget = new eSubtitleWidget(parent);
2701 m_subtitle_widget->resize(parent->size()); /* full size */
2702 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2704 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2710 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2711 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2712 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2716 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2718 delete m_subtitle_widget;
2719 m_subtitle_widget = 0;
2720 if (m_subtitle_parser)
2722 m_subtitle_parser->stop();
2723 m_dvb_subtitle_pages.clear();
2725 if (m_teletext_parser)
2727 m_teletext_parser->setPageAndMagazine(-1, -1);
2728 m_subtitle_pages.clear();
2731 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2735 PyObject *eDVBServicePlay::getCachedSubtitle()
2739 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2742 unsigned int data = (unsigned int)tmp;
2743 int pid = (data&0xFFFF0000)>>16;
2744 ePyObject tuple = PyTuple_New(4);
2745 eDVBServicePMTHandler::program program;
2746 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2747 if (!h.getProgramInfo(program))
2749 if (program.textPid==pid) // teletext
2750 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2752 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2753 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2754 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2755 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2763 PyObject *eDVBServicePlay::getSubtitleList()
2765 if (!m_teletext_parser)
2768 ePyObject l = PyList_New(0);
2769 std::set<int> added_ttx_pages;
2771 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2772 m_teletext_parser->m_found_subtitle_pages;
2774 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2775 eDVBServicePMTHandler::program program;
2776 if (h.getProgramInfo(program))
2777 eDebug("getting program info failed.");
2780 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2781 it != program.subtitleStreams.end(); ++it)
2783 switch(it->subtitling_type)
2785 case 0x01: // ebu teletext subtitles
2787 int page_number = it->teletext_page_number & 0xFF;
2788 int magazine_number = it->teletext_magazine_number & 7;
2789 int hash = magazine_number << 8 | page_number;
2790 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2792 ePyObject tuple = PyTuple_New(5);
2793 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2794 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2795 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2796 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2797 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2798 PyList_Append(l, tuple);
2800 added_ttx_pages.insert(hash);
2805 case 0x20 ... 0x23: // dvb subtitles
2807 ePyObject tuple = PyTuple_New(5);
2808 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2809 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2810 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2811 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2812 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2813 PyList_Insert(l, 0, tuple);
2821 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2822 it != subs.end(); ++it)
2824 int page_number = it->teletext_page_number & 0xFF;
2825 int magazine_number = it->teletext_magazine_number & 7;
2826 int hash = magazine_number << 8 | page_number;
2827 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2829 ePyObject tuple = PyTuple_New(5);
2830 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2831 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2832 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2833 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2834 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2835 PyList_Append(l, tuple);
2843 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2845 if (m_subtitle_widget)
2849 m_decoder->getPTS(0, pos);
2850 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2851 m_subtitle_pages.push_back(page);
2852 checkSubtitleTiming();
2856 void eDVBServicePlay::checkSubtitleTiming()
2858 eDebug("checkSubtitleTiming");
2859 if (!m_subtitle_widget)
2863 enum { TELETEXT, DVB } type;
2864 eDVBTeletextSubtitlePage page;
2865 eDVBSubtitlePage dvb_page;
2867 if (!m_subtitle_pages.empty())
2869 page = m_subtitle_pages.front();
2871 show_time = page.m_pts;
2873 else if (!m_dvb_subtitle_pages.empty())
2875 dvb_page = m_dvb_subtitle_pages.front();
2877 show_time = dvb_page.m_show_time;
2885 m_decoder->getPTS(0, pos);
2887 eDebug("%lld %lld", pos, show_time);
2888 int diff = show_time - pos;
2889 if (type == TELETEXT && !page.m_have_pts)
2891 eDebug("ttx subtitle page without pts... immediate show");
2896 eDebug("[late (%d ms)]", -diff / 90);
2899 if (abs(diff) > 1800000)
2901 eDebug("[invalid]... immediate show!");
2906 if (type == TELETEXT)
2908 eDebug("display teletext subtitle page %lld", show_time);
2909 m_subtitle_widget->setPage(page);
2910 m_subtitle_pages.pop_front();
2914 eDebug("display dvb subtitle Page %lld", show_time);
2915 m_subtitle_widget->setPage(dvb_page);
2916 m_dvb_subtitle_pages.pop_front();
2920 eDebug("start subtitle delay %d", diff / 90);
2921 m_subtitle_sync_timer->start(diff / 90, 1);
2927 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2929 if (m_subtitle_widget)
2933 m_decoder->getPTS(0, pos);
2934 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2935 m_dvb_subtitle_pages.push_back(p);
2936 checkSubtitleTiming();
2940 int eDVBServicePlay::getAC3Delay()
2943 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2945 return m_decoder->getAC3Delay();
2950 int eDVBServicePlay::getPCMDelay()
2953 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2955 return m_decoder->getPCMDelay();
2960 void eDVBServicePlay::setAC3Delay(int delay)
2963 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2965 std::string config_delay;
2966 int config_delay_int = 0;
2967 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2968 config_delay_int = atoi(config_delay.c_str());
2969 m_decoder->setAC3Delay(delay + config_delay_int);
2973 void eDVBServicePlay::setPCMDelay(int delay)
2976 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2978 std::string config_delay;
2979 int config_delay_int = 0;
2980 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2981 config_delay_int = atoi(config_delay.c_str());
2983 config_delay_int = 0;
2984 m_decoder->setPCMDelay(delay + config_delay_int);
2988 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2990 switch(event.type) {
2991 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2992 m_event((iPlayableService*)this, evVideoSizeChanged);
2994 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2995 m_event((iPlayableService*)this, evVideoFramerateChanged);
2997 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2998 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3005 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3011 PyObject *eDVBServicePlay::getStreamingData()
3013 eDVBServicePMTHandler::program program;
3014 if (m_service_handler.getProgramInfo(program))
3019 ePyObject r = program.createPythonObject();
3020 ePtr<iDVBDemux> demux;
3021 if (!m_service_handler.getDataDemux(demux))
3024 if (!demux->getCADemuxID(demux_id))
3025 PutToDict(r, "demux", demux_id);
3032 DEFINE_REF(eDVBServicePlay)
3034 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3038 case iServiceInformation::sTransponderData:
3039 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3043 return iStaticServiceInformation::getInfoObject(ref, w);
3046 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");