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 & 1 && m_is_pvr)
1026 m_first_program_info &= ~1;
1029 if (!m_timeshift_active)
1030 m_event((iPlayableService*)this, evUpdatedInfo);
1033 case eDVBServicePMTHandler::eventPreStart:
1036 case eDVBServicePMTHandler::eventEOF:
1037 m_event((iPlayableService*)this, evEOF);
1039 case eDVBServicePMTHandler::eventSOF:
1040 m_event((iPlayableService*)this, evSOF);
1045 void eDVBServicePlay::serviceEventTimeshift(int event)
1049 case eDVBServicePMTHandler::eventNewProgramInfo:
1050 eDebug("eventNewProgramInfo TS");
1051 if (m_timeshift_active)
1054 if (m_first_program_info & 2)
1058 eDebug("re-apply slowmotion after timeshift file change");
1059 m_decoder->setSlowMotion(m_slowmotion);
1063 eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1065 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1066 if (m_fastforward != 1)
1067 m_decoder->setFastForward(m_fastforward);
1069 m_decoder->setTrickmode();
1073 m_first_program_info &= ~2;
1075 m_event((iPlayableService*)this, evUpdatedInfo);
1078 case eDVBServicePMTHandler::eventSOF:
1080 if (!m_timeshift_file_next.empty())
1082 eDebug("timeshift SOF, switch to next file");
1085 m_first_program_info |= 2;
1087 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1088 r.path = m_timeshift_file_next;
1090 /* free the timeshift service handler, we need the resources */
1091 m_service_handler_timeshift.free();
1095 m_cue->seekTo(0, -1000);
1096 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1098 m_event((iPlayableService*)this, evUser+1);
1102 m_event((iPlayableService*)this, evSOF);
1104 case eDVBServicePMTHandler::eventEOF:
1105 if ((!m_is_paused) && (m_skipmode >= 0))
1107 if (m_timeshift_file_next.empty())
1109 eDebug("timeshift EOF, so let's go live");
1114 eDebug("timeshift EOF, switch to next file");
1116 m_first_program_info |= 2;
1118 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1119 r.path = m_timeshift_file_next;
1121 /* free the timeshift service handler, we need the resources */
1122 m_service_handler_timeshift.free();
1125 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1127 m_event((iPlayableService*)this, evUser+1);
1134 RESULT eDVBServicePlay::start()
1136 eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1138 /* in pvr mode, we only want to use one demux. in tv mode, we're using
1139 two (one for decoding, one for data source), as we must be prepared
1140 to start recording from the data demux. */
1143 eDVBMetaParser meta;
1144 if (!meta.parseFile(m_reference.path))
1146 service = meta.m_ref;
1147 service.path = m_reference.path;
1149 m_cue = new eCueSheet();
1152 m_event(this, evStart);
1154 m_first_program_info = 1;
1155 m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1159 /* inject EIT if there is a stored one */
1160 std::string filename = service.path;
1161 filename.erase(filename.length()-2, 2);
1163 ePtr<eServiceEvent> event = new eServiceEvent;
1164 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1166 ePtr<eServiceEvent> empty;
1167 m_event_handler.inject(event, 0);
1168 m_event_handler.inject(empty, 1);
1170 m_event(this, evStart);
1175 RESULT eDVBServicePlay::stop()
1177 /* add bookmark for last play position */
1180 pts_t play_position, length;
1181 if (!getPlayPosition(play_position))
1183 /* remove last position */
1184 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1186 if (i->what == 3) /* current play position */
1188 m_cue_entries.erase(i);
1189 i = m_cue_entries.begin();
1195 if (getLength(length))
1200 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1202 m_cuesheet_changed = 1;
1206 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1208 m_service_handler_timeshift.free();
1209 m_service_handler.free();
1211 if (m_is_pvr && m_cuesheet_changed)
1214 /* save cuesheet only when main file is accessible. */
1215 if (!::stat(m_reference.path.c_str(), &s))
1218 m_event((iPlayableService*)this, evStopped);
1222 RESULT eDVBServicePlay::setTarget(int target)
1224 m_is_primary = !target;
1228 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1230 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1234 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1236 /* note: we check for timeshift to be enabled,
1237 not neccessary active. if you pause when timeshift
1238 is not active, you should activate it when unpausing */
1239 if ((!m_is_pvr) && (!m_timeshift_enabled))
1249 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1251 ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1252 eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1253 setFastForward_internal(0);
1256 m_slowmotion = ratio;
1257 return m_decoder->setSlowMotion(ratio);
1263 RESULT eDVBServicePlay::setFastForward(int ratio)
1265 eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1267 return setFastForward_internal(ratio);
1270 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1272 int skipmode, ffratio, ret = 0;
1279 } else if (ratio > 0)
1287 } else // if (ratio < 0)
1293 if (m_skipmode != skipmode)
1295 eDebug("setting cue skipmode to %d", skipmode);
1297 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1300 m_skipmode = skipmode;
1303 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1305 m_fastforward = ffratio;
1311 ; /* return m_decoder->play(); is done in caller*/
1312 else if (ffratio != 1)
1313 ret = m_decoder->setFastForward(ffratio);
1315 ret = m_decoder->setTrickmode();
1318 eDebug("final seek after trickplay ret %d", seekTo(pos));
1323 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1325 if (m_is_pvr || m_timeshift_enabled)
1335 /* TODO: when timeshift is enabled but not active, this doesn't work. */
1336 RESULT eDVBServicePlay::getLength(pts_t &len)
1338 ePtr<iDVBPVRChannel> pvr_channel;
1340 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1343 return pvr_channel->getLength(len);
1346 RESULT eDVBServicePlay::pause()
1348 eDebug("eDVBServicePlay::pause");
1349 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1354 return m_decoder->pause();
1359 RESULT eDVBServicePlay::unpause()
1361 eDebug("eDVBServicePlay::unpause");
1362 setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1367 return m_decoder->play();
1372 RESULT eDVBServicePlay::seekTo(pts_t to)
1374 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1376 if (!m_decode_demux)
1379 ePtr<iDVBPVRChannel> pvr_channel;
1381 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1387 m_cue->seekTo(0, to);
1388 m_dvb_subtitle_pages.clear();
1389 m_subtitle_pages.clear();
1394 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1396 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1398 if (!m_decode_demux)
1401 ePtr<iDVBPVRChannel> pvr_channel;
1403 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1408 /* HACK until we have skip-AP api */
1409 if ((to > 0) && (to < 100))
1417 m_cue->seekTo(mode, to);
1418 m_dvb_subtitle_pages.clear();
1419 m_subtitle_pages.clear();
1423 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1425 ePtr<iDVBPVRChannel> pvr_channel;
1427 if (!m_decode_demux)
1430 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1435 /* if there is a decoder, use audio or video PTS */
1438 r = m_decoder->getPTS(0, pos);
1444 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1447 RESULT eDVBServicePlay::setTrickmode(int trick)
1449 /* currently unimplemented */
1453 RESULT eDVBServicePlay::isCurrentlySeekable()
1458 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1459 if (m_decoder->getVideoProgressive() == -1)
1465 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1471 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1477 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1483 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1489 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1495 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1498 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1499 (m_timeshift_enabled || !m_is_pvr))
1501 if (!m_timeshift_enabled)
1503 /* query config path */
1505 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1506 eDebug("could not query ts path from config");
1510 /* we need enough diskspace */
1512 if (statfs(tspath.c_str(), &fs) < 0)
1514 eDebug("statfs failed!");
1518 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1520 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1530 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1541 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1547 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1553 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1559 RESULT eDVBServicePlay::getName(std::string &name)
1563 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1564 return i->getName(m_reference, name);
1566 else if (m_dvb_service)
1568 m_dvb_service->getName(m_reference, name);
1572 else if (!m_reference.name.empty())
1573 eStaticServiceDVBInformation().getName(m_reference, name);
1575 name = "DVB service";
1579 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1581 return m_event_handler.getEvent(evt, nownext);
1584 int eDVBServicePlay::getInfo(int w)
1586 eDVBServicePMTHandler::program program;
1588 if (w == sCAIDs || w == sCAIDPIDs)
1589 return resIsPyObject;
1591 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1593 int no_program_info = 0;
1595 if (h.getProgramInfo(program))
1596 no_program_info = 1;
1602 return m_decoder->getVideoHeight();
1606 return m_decoder->getVideoWidth();
1610 return m_decoder->getVideoFrameRate();
1614 return m_decoder->getVideoProgressive();
1620 aspect = m_decoder->getVideoAspect();
1621 if (aspect == -1 && no_program_info)
1623 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1625 ePtr<eServiceEvent> evt;
1626 if (!m_event_handler.getEvent(evt, 0))
1628 ePtr<eComponentData> data;
1629 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1631 if ( data->getStreamContent() == 1 )
1633 switch(data->getComponentType())
1636 case 1: // 4:3 SD PAL
1638 case 3: // 16:9 SD PAL
1639 case 4: // > 16:9 PAL
1640 case 5: // 4:3 SD NTSC
1642 case 7: // 16:9 SD NTSC
1643 case 8: // > 16:9 NTSC
1646 case 9: // 4:3 HD PAL
1648 case 0xB: // 16:9 HD PAL
1649 case 0xC: // > 16:9 HD PAL
1650 case 0xD: // 4:3 HD NTSC
1652 case 0xF: // 16:9 HD NTSC
1653 case 0x10: // > 16:9 HD PAL
1654 return data->getComponentType();
1664 case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1668 int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1672 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1673 case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1677 int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1680 apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1684 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1688 int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1692 if (no_program_info) return -1; return program.pcrPid;
1693 case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1694 case sTXTPID: if (no_program_info) return -1; return program.textPid;
1695 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1696 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1697 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1698 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1699 case sProvider: if (!m_dvb_service) return -1; return -2;
1700 case sServiceref: return resIsString;
1701 case sDVBState: return m_tune_state;
1708 std::string eDVBServicePlay::getInfoString(int w)
1713 if (!m_dvb_service) return "";
1714 return m_dvb_service->m_provider_name;
1716 return m_reference.toString();
1720 return iServiceInformation::getInfoString(w);
1723 PyObject *eDVBServicePlay::getInfoObject(int w)
1728 return m_service_handler.getCaIds();
1730 return m_service_handler.getCaIds(true);
1731 case sTransponderData:
1732 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1736 return iServiceInformation::getInfoObject(w);
1739 int eDVBServicePlay::getNumberOfTracks()
1741 eDVBServicePMTHandler::program program;
1742 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1743 if (h.getProgramInfo(program))
1745 return program.audioStreams.size();
1748 int eDVBServicePlay::getCurrentTrack()
1750 eDVBServicePMTHandler::program program;
1751 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1752 if (h.getProgramInfo(program))
1755 int max = program.audioStreams.size();
1758 for (i = 0; i < max; ++i)
1759 if (program.audioStreams[i].pid == m_current_audio_pid)
1765 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1767 int ret = selectAudioStream(i);
1769 if (m_decoder->set())
1775 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1777 eDVBServicePMTHandler::program program;
1778 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1780 if (h.getProgramInfo(program))
1783 if (i >= program.audioStreams.size())
1786 info.m_pid = program.audioStreams[i].pid;
1788 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1789 info.m_description = "MPEG";
1790 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1791 info.m_description = "AC3";
1792 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1793 info.m_description = "AAC";
1794 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1795 info.m_description = "AAC-HE";
1796 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1797 info.m_description = "DTS";
1799 info.m_description = "???";
1801 if (program.audioStreams[i].component_tag != -1)
1803 ePtr<eServiceEvent> evt;
1804 if (!m_event_handler.getEvent(evt, 0))
1806 ePtr<eComponentData> data;
1807 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1808 info.m_language = data->getText();
1812 if (info.m_language.empty())
1813 info.m_language = program.audioStreams[i].language_code;
1818 int eDVBServicePlay::selectAudioStream(int i)
1820 eDVBServicePMTHandler::program program;
1821 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1822 pts_t position = -1;
1824 if (h.getProgramInfo(program))
1827 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1835 stream = program.defaultAudioStream;
1837 int apid = -1, apidtype = -1;
1839 if (((unsigned int)stream) < program.audioStreams.size())
1841 apid = program.audioStreams[stream].pid;
1842 apidtype = program.audioStreams[stream].type;
1845 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1846 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1848 m_current_audio_pid = apid;
1850 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1852 eDebug("set audio pid failed");
1857 eDebug("seekTo ret %d", seekTo(position));
1861 /* 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 */
1862 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1864 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1866 rdsPid = program.audioStreams[stream].rdsPid;
1867 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1870 ePtr<iDVBDemux> data_demux;
1871 if (!h.getDataDemux(data_demux))
1873 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1874 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1875 m_rds_decoder->start(rdsPid);
1880 /* store new pid as default only when:
1881 a.) we have an entry in the service db for the current service,
1882 b.) we are not playing back something,
1883 c.) we are not selecting the default entry. (we wouldn't change
1884 anything in the best case, or destroy the default setting in
1885 case the real default is not yet available.)
1887 if (m_dvb_service && ((i != -1)
1888 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1890 if (apidtype == eDVBAudio::aMPEG)
1892 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1893 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1895 else if (apidtype == eDVBAudio::aAC3)
1897 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1898 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1902 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1903 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1907 h.resetCachedProgram();
1912 int eDVBServicePlay::getCurrentChannel()
1914 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1917 RESULT eDVBServicePlay::selectChannel(int i)
1919 if (i < LEFT || i > RIGHT || i == STEREO)
1922 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1924 m_decoder->setAudioChannel(i);
1928 std::string eDVBServicePlay::getText(int x)
1934 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1936 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1941 void eDVBServicePlay::rdsDecoderEvent(int what)
1945 case eDVBRdsDecoder::RadioTextChanged:
1946 m_event((iPlayableService*)this, evUpdatedRadioText);
1948 case eDVBRdsDecoder::RtpTextChanged:
1949 m_event((iPlayableService*)this, evUpdatedRtpText);
1951 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1952 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1954 case eDVBRdsDecoder::RecvRassSlidePic:
1955 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1960 void eDVBServicePlay::showRassSlidePicture()
1966 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1967 if (rass_slide_pic.length())
1968 m_decoder->showSinglePic(rass_slide_pic.c_str());
1970 eDebug("empty filename for rass slide picture received!!");
1973 eDebug("no MPEG Decoder to show iframes avail");
1976 eDebug("showRassSlidePicture called.. but not decoder");
1979 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1985 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1986 if (rass_interactive_pic.length())
1987 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1989 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1992 eDebug("no MPEG Decoder to show iframes avail");
1995 eDebug("showRassInteractivePic called.. but not decoder");
1998 ePyObject eDVBServicePlay::getRassInteractiveMask()
2001 return m_rds_decoder->getRassPictureMask();
2005 int eDVBServiceBase::getFrontendInfo(int w)
2007 eUsePtr<iDVBChannel> channel;
2008 if(m_service_handler.getChannel(channel))
2010 ePtr<iDVBFrontend> fe;
2011 if(channel->getFrontend(fe))
2013 return fe->readFrontendData(w);
2016 PyObject *eDVBServiceBase::getFrontendData()
2018 ePyObject ret = PyDict_New();
2021 eUsePtr<iDVBChannel> channel;
2022 if(!m_service_handler.getChannel(channel))
2024 ePtr<iDVBFrontend> fe;
2025 if(!channel->getFrontend(fe))
2026 fe->getFrontendData(ret);
2034 PyObject *eDVBServiceBase::getFrontendStatus()
2036 ePyObject ret = PyDict_New();
2039 eUsePtr<iDVBChannel> channel;
2040 if(!m_service_handler.getChannel(channel))
2042 ePtr<iDVBFrontend> fe;
2043 if(!channel->getFrontend(fe))
2044 fe->getFrontendStatus(ret);
2052 PyObject *eDVBServiceBase::getTransponderData(bool original)
2054 ePyObject ret = PyDict_New();
2057 eUsePtr<iDVBChannel> channel;
2058 if(!m_service_handler.getChannel(channel))
2060 ePtr<iDVBFrontend> fe;
2061 if(!channel->getFrontend(fe))
2062 fe->getTransponderData(ret, original);
2070 PyObject *eDVBServiceBase::getAll(bool original)
2072 ePyObject ret = getTransponderData(original);
2075 eUsePtr<iDVBChannel> channel;
2076 if(!m_service_handler.getChannel(channel))
2078 ePtr<iDVBFrontend> fe;
2079 if(!channel->getFrontend(fe))
2081 fe->getFrontendData(ret);
2082 fe->getFrontendStatus(ret);
2089 int eDVBServicePlay::getNumberOfSubservices()
2091 ePtr<eServiceEvent> evt;
2092 if (!m_event_handler.getEvent(evt, 0))
2093 return evt->getNumOfLinkageServices();
2097 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2099 ePtr<eServiceEvent> evt;
2100 if (!m_event_handler.getEvent(evt, 0))
2102 if (!evt->getLinkageService(sub, m_reference, n))
2105 sub.type=eServiceReference::idInvalid;
2109 RESULT eDVBServicePlay::startTimeshift()
2111 ePtr<iDVBDemux> demux;
2113 eDebug("Start timeshift!");
2115 if (m_timeshift_enabled)
2118 /* start recording with the data demux. */
2119 if (m_service_handler.getDataDemux(demux))
2122 demux->createTSRecorder(m_record);
2127 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2128 eDebug("could not query ts path");
2131 tspath.append("/timeshift.XXXXXX");
2133 templ = new char[tspath.length() + 1];
2134 strcpy(templ, tspath.c_str());
2136 m_timeshift_fd = mkstemp(templ);
2137 m_timeshift_file = std::string(templ);
2139 eDebug("recording to %s", templ);
2143 if (m_timeshift_fd < 0)
2149 m_record->setTargetFD(m_timeshift_fd);
2151 m_timeshift_enabled = 1;
2153 updateTimeshiftPids();
2159 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2161 if (!m_timeshift_enabled)
2167 m_timeshift_enabled = 0;
2172 close(m_timeshift_fd);
2173 eDebug("remove timeshift file");
2174 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2179 int eDVBServicePlay::isTimeshiftActive()
2181 return m_timeshift_enabled && m_timeshift_active;
2184 RESULT eDVBServicePlay::activateTimeshift()
2186 if (!m_timeshift_enabled)
2189 if (!m_timeshift_active)
2191 switchToTimeshift();
2198 PyObject *eDVBServicePlay::getCutList()
2200 ePyObject list = PyList_New(0);
2202 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2204 ePyObject tuple = PyTuple_New(2);
2205 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2206 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2207 PyList_Append(list, tuple);
2214 void eDVBServicePlay::setCutList(ePyObject list)
2216 if (!PyList_Check(list))
2218 int size = PyList_Size(list);
2221 m_cue_entries.clear();
2223 for (i=0; i<size; ++i)
2225 ePyObject tuple = PyList_GET_ITEM(list, i);
2226 if (!PyTuple_Check(tuple))
2228 eDebug("non-tuple in cutlist");
2231 if (PyTuple_Size(tuple) != 2)
2233 eDebug("cutlist entries need to be a 2-tuple");
2236 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2237 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2239 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2242 pts_t pts = PyLong_AsLongLong(ppts);
2243 int type = PyInt_AsLong(ptype);
2244 m_cue_entries.insert(cueEntry(pts, type));
2245 eDebug("adding %08llx, %d", pts, type);
2247 m_cuesheet_changed = 1;
2249 cutlistToCuesheet();
2250 m_event((iPlayableService*)this, evCuesheetChanged);
2253 void eDVBServicePlay::setCutListEnable(int enable)
2255 m_cutlist_enabled = enable;
2256 cutlistToCuesheet();
2259 void eDVBServicePlay::updateTimeshiftPids()
2264 eDVBServicePMTHandler::program program;
2265 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2267 if (h.getProgramInfo(program))
2271 std::set<int> pids_to_record;
2272 pids_to_record.insert(0); // PAT
2273 if (program.pmtPid != -1)
2274 pids_to_record.insert(program.pmtPid); // PMT
2276 if (program.textPid != -1)
2277 pids_to_record.insert(program.textPid); // Videotext
2279 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2280 i(program.videoStreams.begin());
2281 i != program.videoStreams.end(); ++i)
2282 pids_to_record.insert(i->pid);
2284 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2285 i(program.audioStreams.begin());
2286 i != program.audioStreams.end(); ++i)
2287 pids_to_record.insert(i->pid);
2289 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2290 i(program.subtitleStreams.begin());
2291 i != program.subtitleStreams.end(); ++i)
2292 pids_to_record.insert(i->pid);
2294 std::set<int> new_pids, obsolete_pids;
2296 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2297 m_pids_active.begin(), m_pids_active.end(),
2298 std::inserter(new_pids, new_pids.begin()));
2300 std::set_difference(
2301 m_pids_active.begin(), m_pids_active.end(),
2302 pids_to_record.begin(), pids_to_record.end(),
2303 std::inserter(new_pids, new_pids.begin())
2306 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2307 m_record->addPID(*i);
2309 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2310 m_record->removePID(*i);
2314 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2316 m_timeshift_file_next = f;
2320 void eDVBServicePlay::switchToLive()
2322 if (!m_timeshift_active)
2325 eDebug("SwitchToLive");
2329 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2331 /* free the timeshift service handler, we need the resources */
2332 m_service_handler_timeshift.free();
2334 updateDecoder(true);
2337 void eDVBServicePlay::resetTimeshift(int start)
2342 m_teletext_parser = 0;
2344 m_subtitle_parser = 0;
2345 m_new_subtitle_page_connection = 0;
2346 m_new_dvb_subtitle_page_connection = 0;
2347 m_rds_decoder_event_connection = 0;
2348 m_video_event_connection = 0;
2349 m_timeshift_changed = 1;
2350 m_timeshift_file_next.clear();
2354 m_cue = new eCueSheet();
2355 m_timeshift_active = 1;
2358 m_timeshift_active = 0;
2361 void eDVBServicePlay::switchToTimeshift()
2363 if (m_timeshift_active)
2368 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2369 r.path = m_timeshift_file;
2371 m_cue->seekTo(0, -1000);
2372 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2374 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2376 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2379 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2381 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2382 bool mustPlay = false;
2384 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2386 eDVBServicePMTHandler::program program;
2387 if (h.getProgramInfo(program))
2388 eDebug("getting program info failed.");
2391 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2392 if (!program.videoStreams.empty())
2394 eDebugNoNewLine(" (");
2395 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2396 i(program.videoStreams.begin());
2397 i != program.videoStreams.end(); ++i)
2404 if (i != program.videoStreams.begin())
2405 eDebugNoNewLine(", ");
2406 eDebugNoNewLine("%04x", i->pid);
2408 eDebugNoNewLine(")");
2410 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2411 if (!program.audioStreams.empty())
2413 eDebugNoNewLine(" (");
2414 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2415 i(program.audioStreams.begin());
2416 i != program.audioStreams.end(); ++i)
2418 if (i != program.audioStreams.begin())
2419 eDebugNoNewLine(", ");
2420 eDebugNoNewLine("%04x", i->pid);
2422 eDebugNoNewLine(")");
2424 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2425 pcrpid = program.pcrPid;
2426 eDebug(", and the text pid is %04x", program.textPid);
2427 tpid = program.textPid;
2432 h.getDecodeDemux(m_decode_demux);
2435 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2437 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2440 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2441 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2442 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2443 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2444 if (m_timeshift_changed)
2446 ePyObject subs = getCachedSubtitle();
2447 if (subs != Py_None)
2449 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2450 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2451 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2452 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2453 if (type == 0) // dvb
2454 m_subtitle_parser->start(pid, comp_page, anc_page);
2455 else if (type == 1) // ttx
2456 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2463 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2467 m_timeshift_changed = 0;
2471 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2474 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2475 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2476 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2480 eServiceReferenceDVB ref;
2481 m_service_handler.getServiceReference(ref);
2482 eServiceReferenceDVB parent = ref.getParentServiceReference();
2487 ePtr<eDVBResourceManager> res_mgr;
2488 if (!eDVBResourceManager::getInstance(res_mgr))
2490 ePtr<iDVBChannelList> db;
2491 if (!res_mgr->getChannelList(db))
2493 ePtr<eDVBService> origService;
2494 if (!db->getService(parent, origService))
2496 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2497 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2504 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2505 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2507 m_decoder->setVideoPID(vpid, vpidtype);
2508 selectAudioStream();
2510 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2511 m_decoder->setSyncPCR(pcrpid);
2513 m_decoder->setSyncPCR(-1);
2517 m_decoder->setTextPID(tpid);
2518 m_teletext_parser->start(program.textPid);
2521 if (vpid > 0 && vpid < 0x2000)
2525 std::string radio_pic;
2526 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2527 m_decoder->setRadioPic(radio_pic);
2535 m_decoder->setAudioChannel(achannel);
2537 /* don't worry about non-existing services, nor pvr services */
2540 /* (audio pid will be set in selectAudioTrack */
2541 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2542 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2543 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2544 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2546 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2547 sendSeekableStateChanged = true;
2549 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2551 if (sendSeekableStateChanged)
2552 m_event((iPlayableService*)this, evSeekableStatusChanged);
2555 void eDVBServicePlay::loadCuesheet()
2557 std::string filename = m_reference.path + ".cuts";
2559 m_cue_entries.clear();
2561 FILE *f = fopen(filename.c_str(), "rb");
2565 eDebug("loading cuts..");
2568 unsigned long long where;
2571 if (!fread(&where, sizeof(where), 1, f))
2573 if (!fread(&what, sizeof(what), 1, f))
2576 #if BYTE_ORDER == LITTLE_ENDIAN
2577 where = bswap_64(where);
2584 m_cue_entries.insert(cueEntry(where, what));
2587 eDebug("%d entries", m_cue_entries.size());
2589 eDebug("cutfile not found!");
2591 m_cuesheet_changed = 0;
2592 cutlistToCuesheet();
2593 m_event((iPlayableService*)this, evCuesheetChanged);
2596 void eDVBServicePlay::saveCuesheet()
2598 std::string filename = m_reference.path + ".cuts";
2600 FILE *f = fopen(filename.c_str(), "wb");
2604 unsigned long long where;
2607 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2609 #if BYTE_ORDER == BIG_ENDIAN
2612 where = bswap_64(i->where);
2614 what = htonl(i->what);
2615 fwrite(&where, sizeof(where), 1, f);
2616 fwrite(&what, sizeof(what), 1, f);
2622 m_cuesheet_changed = 0;
2625 void eDVBServicePlay::cutlistToCuesheet()
2629 eDebug("no cue sheet");
2634 if (!m_cutlist_enabled)
2636 m_cue->commitSpans();
2637 eDebug("cutlists were disabled");
2641 pts_t in = 0, out = 0, length = 0;
2645 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2647 int have_any_span = 0;
2651 if (i == m_cue_entries.end())
2653 if (!have_any_span && !in)
2657 if (i->what == 0) /* in */
2661 } else if (i->what == 1) /* out */
2663 else /* mark (2) or last play position (3) */
2682 m_cue->addSourceSpan(in, out);
2688 if (i == m_cue_entries.end())
2691 m_cue->commitSpans();
2694 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2696 if (m_subtitle_widget)
2697 disableSubtitles(parent);
2700 int tuplesize = PyTuple_Size(tuple);
2703 if (!PyTuple_Check(tuple))
2709 entry = PyTuple_GET_ITEM(tuple, 0);
2711 if (!PyInt_Check(entry))
2714 type = PyInt_AsLong(entry);
2716 if (type == 1) // teletext subtitles
2718 int page, magazine, pid;
2722 if (!m_teletext_parser)
2724 eDebug("enable teletext subtitles.. no parser !!!");
2728 entry = PyTuple_GET_ITEM(tuple, 1);
2729 if (!PyInt_Check(entry))
2731 pid = PyInt_AsLong(entry);
2733 entry = PyTuple_GET_ITEM(tuple, 2);
2734 if (!PyInt_Check(entry))
2736 page = PyInt_AsLong(entry);
2738 entry = PyTuple_GET_ITEM(tuple, 3);
2739 if (!PyInt_Check(entry))
2741 magazine = PyInt_AsLong(entry);
2743 m_subtitle_widget = new eSubtitleWidget(parent);
2744 m_subtitle_widget->resize(parent->size()); /* full size */
2745 m_teletext_parser->setPageAndMagazine(page, magazine);
2747 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2751 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2752 if (!m_subtitle_parser)
2754 eDebug("enable dvb subtitles.. no parser !!!");
2760 entry = PyTuple_GET_ITEM(tuple, 1);
2761 if (!PyInt_Check(entry))
2763 pid = PyInt_AsLong(entry);
2765 entry = PyTuple_GET_ITEM(tuple, 2);
2766 if (!PyInt_Check(entry))
2768 composition_page_id = PyInt_AsLong(entry);
2770 entry = PyTuple_GET_ITEM(tuple, 3);
2771 if (!PyInt_Check(entry))
2773 ancillary_page_id = PyInt_AsLong(entry);
2775 m_subtitle_widget = new eSubtitleWidget(parent);
2776 m_subtitle_widget->resize(parent->size()); /* full size */
2777 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2779 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2785 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2786 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2787 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2791 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2793 delete m_subtitle_widget;
2794 m_subtitle_widget = 0;
2795 if (m_subtitle_parser)
2797 m_subtitle_parser->stop();
2798 m_dvb_subtitle_pages.clear();
2800 if (m_teletext_parser)
2802 m_teletext_parser->setPageAndMagazine(-1, -1);
2803 m_subtitle_pages.clear();
2806 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2810 PyObject *eDVBServicePlay::getCachedSubtitle()
2814 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2817 unsigned int data = (unsigned int)tmp;
2818 int pid = (data&0xFFFF0000)>>16;
2819 ePyObject tuple = PyTuple_New(4);
2820 eDVBServicePMTHandler::program program;
2821 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2822 if (!h.getProgramInfo(program))
2824 if (program.textPid==pid) // teletext
2825 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2827 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2828 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2829 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2830 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2838 PyObject *eDVBServicePlay::getSubtitleList()
2840 if (!m_teletext_parser)
2843 ePyObject l = PyList_New(0);
2844 std::set<int> added_ttx_pages;
2846 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2847 m_teletext_parser->m_found_subtitle_pages;
2849 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2850 eDVBServicePMTHandler::program program;
2851 if (h.getProgramInfo(program))
2852 eDebug("getting program info failed.");
2855 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2856 it != program.subtitleStreams.end(); ++it)
2858 switch(it->subtitling_type)
2860 case 0x01: // ebu teletext subtitles
2862 int page_number = it->teletext_page_number & 0xFF;
2863 int magazine_number = it->teletext_magazine_number & 7;
2864 int hash = magazine_number << 8 | page_number;
2865 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2867 ePyObject tuple = PyTuple_New(5);
2868 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2869 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2870 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2871 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2872 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2873 PyList_Append(l, tuple);
2875 added_ttx_pages.insert(hash);
2880 case 0x20 ... 0x23: // dvb subtitles
2882 ePyObject tuple = PyTuple_New(5);
2883 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2884 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2885 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2886 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2887 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2888 PyList_Insert(l, 0, tuple);
2896 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2897 it != subs.end(); ++it)
2899 int page_number = it->teletext_page_number & 0xFF;
2900 int magazine_number = it->teletext_magazine_number & 7;
2901 int hash = magazine_number << 8 | page_number;
2902 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2904 ePyObject tuple = PyTuple_New(5);
2905 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2906 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2907 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2908 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2909 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2910 PyList_Append(l, tuple);
2918 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2920 if (m_subtitle_widget)
2924 m_decoder->getPTS(0, pos);
2925 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2926 m_subtitle_pages.push_back(page);
2927 checkSubtitleTiming();
2931 void eDVBServicePlay::checkSubtitleTiming()
2933 eDebug("checkSubtitleTiming");
2934 if (!m_subtitle_widget)
2938 enum { TELETEXT, DVB } type;
2939 eDVBTeletextSubtitlePage page;
2940 eDVBSubtitlePage dvb_page;
2942 if (!m_subtitle_pages.empty())
2944 page = m_subtitle_pages.front();
2946 show_time = page.m_pts;
2948 else if (!m_dvb_subtitle_pages.empty())
2950 dvb_page = m_dvb_subtitle_pages.front();
2952 show_time = dvb_page.m_show_time;
2960 m_decoder->getPTS(0, pos);
2962 eDebug("%lld %lld", pos, show_time);
2963 int diff = show_time - pos;
2964 if (type == TELETEXT && !page.m_have_pts)
2966 eDebug("ttx subtitle page without pts... immediate show");
2971 eDebug("[late (%d ms)]", -diff / 90);
2974 if (abs(diff) > 1800000)
2976 eDebug("[invalid]... immediate show!");
2981 if (type == TELETEXT)
2983 eDebug("display teletext subtitle page %lld", show_time);
2984 m_subtitle_widget->setPage(page);
2985 m_subtitle_pages.pop_front();
2989 eDebug("display dvb subtitle Page %lld", show_time);
2990 m_subtitle_widget->setPage(dvb_page);
2991 m_dvb_subtitle_pages.pop_front();
2995 eDebug("start subtitle delay %d", diff / 90);
2996 m_subtitle_sync_timer->start(diff / 90, 1);
3002 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3004 if (m_subtitle_widget)
3008 m_decoder->getPTS(0, pos);
3009 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3010 m_dvb_subtitle_pages.push_back(p);
3011 checkSubtitleTiming();
3015 int eDVBServicePlay::getAC3Delay()
3018 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3020 return m_decoder->getAC3Delay();
3025 int eDVBServicePlay::getPCMDelay()
3028 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3030 return m_decoder->getPCMDelay();
3035 void eDVBServicePlay::setAC3Delay(int delay)
3038 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3040 std::string config_delay;
3041 int config_delay_int = 0;
3042 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3043 config_delay_int = atoi(config_delay.c_str());
3044 m_decoder->setAC3Delay(delay + config_delay_int);
3048 void eDVBServicePlay::setPCMDelay(int delay)
3051 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3053 std::string config_delay;
3054 int config_delay_int = 0;
3055 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3056 config_delay_int = atoi(config_delay.c_str());
3058 config_delay_int = 0;
3059 m_decoder->setPCMDelay(delay + config_delay_int);
3063 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3065 switch(event.type) {
3066 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3067 m_event((iPlayableService*)this, evVideoSizeChanged);
3069 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3070 m_event((iPlayableService*)this, evVideoFramerateChanged);
3072 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3073 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3080 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3086 PyObject *eDVBServicePlay::getStreamingData()
3088 eDVBServicePMTHandler::program program;
3089 if (m_service_handler.getProgramInfo(program))
3094 ePyObject r = program.createPythonObject();
3095 ePtr<iDVBDemux> demux;
3096 if (!m_service_handler.getDataDemux(demux))
3099 if (!demux->getCADemuxID(demux_id))
3100 PutToDict(r, "demux", demux_id);
3107 DEFINE_REF(eDVBServicePlay)
3109 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3113 case iServiceInformation::sTransponderData:
3114 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3118 return iStaticServiceInformation::getInfoObject(ref, w);
3121 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");