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(bool switchToLive)
2094 if (!m_timeshift_enabled)
2100 m_timeshift_enabled = 0;
2105 close(m_timeshift_fd);
2106 eDebug("remove timeshift file");
2107 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2112 int eDVBServicePlay::isTimeshiftActive()
2114 return m_timeshift_enabled && m_timeshift_active;
2117 RESULT eDVBServicePlay::activateTimeshift()
2119 if (!m_timeshift_enabled)
2122 if (!m_timeshift_active)
2124 switchToTimeshift();
2131 PyObject *eDVBServicePlay::getCutList()
2133 ePyObject list = PyList_New(0);
2135 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2137 ePyObject tuple = PyTuple_New(2);
2138 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2139 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2140 PyList_Append(list, tuple);
2147 void eDVBServicePlay::setCutList(ePyObject list)
2149 if (!PyList_Check(list))
2151 int size = PyList_Size(list);
2154 m_cue_entries.clear();
2156 for (i=0; i<size; ++i)
2158 ePyObject tuple = PyList_GET_ITEM(list, i);
2159 if (!PyTuple_Check(tuple))
2161 eDebug("non-tuple in cutlist");
2164 if (PyTuple_Size(tuple) != 2)
2166 eDebug("cutlist entries need to be a 2-tuple");
2169 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2170 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2172 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2175 pts_t pts = PyLong_AsLongLong(ppts);
2176 int type = PyInt_AsLong(ptype);
2177 m_cue_entries.insert(cueEntry(pts, type));
2178 eDebug("adding %08llx, %d", pts, type);
2180 m_cuesheet_changed = 1;
2182 cutlistToCuesheet();
2183 m_event((iPlayableService*)this, evCuesheetChanged);
2186 void eDVBServicePlay::setCutListEnable(int enable)
2188 m_cutlist_enabled = enable;
2189 cutlistToCuesheet();
2192 void eDVBServicePlay::updateTimeshiftPids()
2197 eDVBServicePMTHandler::program program;
2198 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2200 if (h.getProgramInfo(program))
2204 std::set<int> pids_to_record;
2205 pids_to_record.insert(0); // PAT
2206 if (program.pmtPid != -1)
2207 pids_to_record.insert(program.pmtPid); // PMT
2209 if (program.textPid != -1)
2210 pids_to_record.insert(program.textPid); // Videotext
2212 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2213 i(program.videoStreams.begin());
2214 i != program.videoStreams.end(); ++i)
2215 pids_to_record.insert(i->pid);
2217 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2218 i(program.audioStreams.begin());
2219 i != program.audioStreams.end(); ++i)
2220 pids_to_record.insert(i->pid);
2222 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2223 i(program.subtitleStreams.begin());
2224 i != program.subtitleStreams.end(); ++i)
2225 pids_to_record.insert(i->pid);
2227 std::set<int> new_pids, obsolete_pids;
2229 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2230 m_pids_active.begin(), m_pids_active.end(),
2231 std::inserter(new_pids, new_pids.begin()));
2233 std::set_difference(
2234 m_pids_active.begin(), m_pids_active.end(),
2235 pids_to_record.begin(), pids_to_record.end(),
2236 std::inserter(new_pids, new_pids.begin())
2239 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2240 m_record->addPID(*i);
2242 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2243 m_record->removePID(*i);
2247 void eDVBServicePlay::switchToLive()
2249 if (!m_timeshift_active)
2252 eDebug("SwitchToLive");
2257 m_teletext_parser = 0;
2259 m_subtitle_parser = 0;
2260 m_new_dvb_subtitle_page_connection = 0;
2261 m_new_subtitle_page_connection = 0;
2262 m_rds_decoder_event_connection = 0;
2263 m_video_event_connection = 0;
2264 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2266 /* free the timeshift service handler, we need the resources */
2267 m_service_handler_timeshift.free();
2268 m_timeshift_active = 0;
2269 m_timeshift_changed = 1;
2271 updateDecoder(true);
2274 void eDVBServicePlay::switchToTimeshift()
2276 if (m_timeshift_active)
2281 m_teletext_parser = 0;
2283 m_subtitle_parser = 0;
2284 m_new_subtitle_page_connection = 0;
2285 m_new_dvb_subtitle_page_connection = 0;
2286 m_rds_decoder_event_connection = 0;
2287 m_video_event_connection = 0;
2289 m_timeshift_active = 1;
2290 m_timeshift_changed = 1;
2292 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2293 r.path = m_timeshift_file;
2295 m_cue = new eCueSheet();
2296 m_cue->seekTo(0, -1000);
2297 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2299 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2301 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2304 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2306 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2307 bool mustPlay = false;
2309 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2311 eDVBServicePMTHandler::program program;
2312 if (h.getProgramInfo(program))
2313 eDebug("getting program info failed.");
2316 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2317 if (!program.videoStreams.empty())
2319 eDebugNoNewLine(" (");
2320 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2321 i(program.videoStreams.begin());
2322 i != program.videoStreams.end(); ++i)
2329 if (i != program.videoStreams.begin())
2330 eDebugNoNewLine(", ");
2331 eDebugNoNewLine("%04x", i->pid);
2333 eDebugNoNewLine(")");
2335 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2336 if (!program.audioStreams.empty())
2338 eDebugNoNewLine(" (");
2339 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2340 i(program.audioStreams.begin());
2341 i != program.audioStreams.end(); ++i)
2343 if (i != program.audioStreams.begin())
2344 eDebugNoNewLine(", ");
2345 eDebugNoNewLine("%04x", i->pid);
2347 eDebugNoNewLine(")");
2349 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2350 pcrpid = program.pcrPid;
2351 eDebug(", and the text pid is %04x", program.textPid);
2352 tpid = program.textPid;
2357 h.getDecodeDemux(m_decode_demux);
2358 if (m_timeshift_changed)
2362 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2364 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2367 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2368 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2369 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2370 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2371 if (m_timeshift_changed)
2373 ePyObject subs = getCachedSubtitle();
2374 if (subs != Py_None)
2376 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2377 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2378 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2379 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2380 if (type == 0) // dvb
2381 m_subtitle_parser->start(pid, comp_page, anc_page);
2382 else if (type == 1) // ttx
2383 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2390 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2394 m_timeshift_changed = 0;
2398 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2401 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2402 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2403 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2407 eServiceReferenceDVB ref;
2408 m_service_handler.getServiceReference(ref);
2409 eServiceReferenceDVB parent = ref.getParentServiceReference();
2414 ePtr<eDVBResourceManager> res_mgr;
2415 if (!eDVBResourceManager::getInstance(res_mgr))
2417 ePtr<iDVBChannelList> db;
2418 if (!res_mgr->getChannelList(db))
2420 ePtr<eDVBService> origService;
2421 if (!db->getService(parent, origService))
2423 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2424 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2431 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2432 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2434 m_decoder->setVideoPID(vpid, vpidtype);
2435 selectAudioStream();
2437 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2438 m_decoder->setSyncPCR(pcrpid);
2440 m_decoder->setSyncPCR(-1);
2444 m_decoder->setTextPID(tpid);
2445 m_teletext_parser->start(program.textPid);
2448 if (vpid > 0 && vpid < 0x2000)
2452 std::string radio_pic;
2453 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2454 m_decoder->setRadioPic(radio_pic);
2462 m_decoder->setAudioChannel(achannel);
2464 /* don't worry about non-existing services, nor pvr services */
2467 /* (audio pid will be set in selectAudioTrack */
2468 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2469 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2470 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2471 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2473 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2474 sendSeekableStateChanged = true;
2476 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2478 if (sendSeekableStateChanged)
2479 m_event((iPlayableService*)this, evSeekableStatusChanged);
2482 void eDVBServicePlay::loadCuesheet()
2484 std::string filename = m_reference.path + ".cuts";
2486 m_cue_entries.clear();
2488 FILE *f = fopen(filename.c_str(), "rb");
2492 eDebug("loading cuts..");
2495 unsigned long long where;
2498 if (!fread(&where, sizeof(where), 1, f))
2500 if (!fread(&what, sizeof(what), 1, f))
2503 #if BYTE_ORDER == LITTLE_ENDIAN
2504 where = bswap_64(where);
2511 m_cue_entries.insert(cueEntry(where, what));
2514 eDebug("%d entries", m_cue_entries.size());
2516 eDebug("cutfile not found!");
2518 m_cuesheet_changed = 0;
2519 cutlistToCuesheet();
2520 m_event((iPlayableService*)this, evCuesheetChanged);
2523 void eDVBServicePlay::saveCuesheet()
2525 std::string filename = m_reference.path + ".cuts";
2527 FILE *f = fopen(filename.c_str(), "wb");
2531 unsigned long long where;
2534 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2536 #if BYTE_ORDER == BIG_ENDIAN
2539 where = bswap_64(i->where);
2541 what = htonl(i->what);
2542 fwrite(&where, sizeof(where), 1, f);
2543 fwrite(&what, sizeof(what), 1, f);
2549 m_cuesheet_changed = 0;
2552 void eDVBServicePlay::cutlistToCuesheet()
2556 eDebug("no cue sheet");
2561 if (!m_cutlist_enabled)
2563 m_cue->commitSpans();
2564 eDebug("cutlists were disabled");
2568 pts_t in = 0, out = 0, length = 0;
2572 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2574 int have_any_span = 0;
2578 if (i == m_cue_entries.end())
2580 if (!have_any_span && !in)
2584 if (i->what == 0) /* in */
2588 } else if (i->what == 1) /* out */
2590 else /* mark (2) or last play position (3) */
2609 m_cue->addSourceSpan(in, out);
2615 if (i == m_cue_entries.end())
2618 m_cue->commitSpans();
2621 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2623 if (m_subtitle_widget)
2624 disableSubtitles(parent);
2627 int tuplesize = PyTuple_Size(tuple);
2630 if (!PyTuple_Check(tuple))
2636 entry = PyTuple_GET_ITEM(tuple, 0);
2638 if (!PyInt_Check(entry))
2641 type = PyInt_AsLong(entry);
2643 if (type == 1) // teletext subtitles
2645 int page, magazine, pid;
2649 if (!m_teletext_parser)
2651 eDebug("enable teletext subtitles.. no parser !!!");
2655 entry = PyTuple_GET_ITEM(tuple, 1);
2656 if (!PyInt_Check(entry))
2658 pid = PyInt_AsLong(entry);
2660 entry = PyTuple_GET_ITEM(tuple, 2);
2661 if (!PyInt_Check(entry))
2663 page = PyInt_AsLong(entry);
2665 entry = PyTuple_GET_ITEM(tuple, 3);
2666 if (!PyInt_Check(entry))
2668 magazine = PyInt_AsLong(entry);
2670 m_subtitle_widget = new eSubtitleWidget(parent);
2671 m_subtitle_widget->resize(parent->size()); /* full size */
2672 m_teletext_parser->setPageAndMagazine(page, magazine);
2674 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2678 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2679 if (!m_subtitle_parser)
2681 eDebug("enable dvb subtitles.. no parser !!!");
2687 entry = PyTuple_GET_ITEM(tuple, 1);
2688 if (!PyInt_Check(entry))
2690 pid = PyInt_AsLong(entry);
2692 entry = PyTuple_GET_ITEM(tuple, 2);
2693 if (!PyInt_Check(entry))
2695 composition_page_id = PyInt_AsLong(entry);
2697 entry = PyTuple_GET_ITEM(tuple, 3);
2698 if (!PyInt_Check(entry))
2700 ancillary_page_id = PyInt_AsLong(entry);
2702 m_subtitle_widget = new eSubtitleWidget(parent);
2703 m_subtitle_widget->resize(parent->size()); /* full size */
2704 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2706 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2712 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2713 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2714 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2718 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2720 delete m_subtitle_widget;
2721 m_subtitle_widget = 0;
2722 if (m_subtitle_parser)
2724 m_subtitle_parser->stop();
2725 m_dvb_subtitle_pages.clear();
2727 if (m_teletext_parser)
2729 m_teletext_parser->setPageAndMagazine(-1, -1);
2730 m_subtitle_pages.clear();
2733 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2737 PyObject *eDVBServicePlay::getCachedSubtitle()
2741 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2744 unsigned int data = (unsigned int)tmp;
2745 int pid = (data&0xFFFF0000)>>16;
2746 ePyObject tuple = PyTuple_New(4);
2747 eDVBServicePMTHandler::program program;
2748 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2749 if (!h.getProgramInfo(program))
2751 if (program.textPid==pid) // teletext
2752 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2754 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2755 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2756 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2757 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2765 PyObject *eDVBServicePlay::getSubtitleList()
2767 if (!m_teletext_parser)
2770 ePyObject l = PyList_New(0);
2771 std::set<int> added_ttx_pages;
2773 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2774 m_teletext_parser->m_found_subtitle_pages;
2776 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2777 eDVBServicePMTHandler::program program;
2778 if (h.getProgramInfo(program))
2779 eDebug("getting program info failed.");
2782 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2783 it != program.subtitleStreams.end(); ++it)
2785 switch(it->subtitling_type)
2787 case 0x01: // ebu teletext subtitles
2789 int page_number = it->teletext_page_number & 0xFF;
2790 int magazine_number = it->teletext_magazine_number & 7;
2791 int hash = magazine_number << 8 | page_number;
2792 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2794 ePyObject tuple = PyTuple_New(5);
2795 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2796 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2797 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2798 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2799 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2800 PyList_Append(l, tuple);
2802 added_ttx_pages.insert(hash);
2807 case 0x20 ... 0x23: // dvb subtitles
2809 ePyObject tuple = PyTuple_New(5);
2810 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2811 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2812 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2813 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2814 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2815 PyList_Insert(l, 0, tuple);
2823 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2824 it != subs.end(); ++it)
2826 int page_number = it->teletext_page_number & 0xFF;
2827 int magazine_number = it->teletext_magazine_number & 7;
2828 int hash = magazine_number << 8 | page_number;
2829 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2831 ePyObject tuple = PyTuple_New(5);
2832 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2833 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2834 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2835 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2836 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2837 PyList_Append(l, tuple);
2845 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2847 if (m_subtitle_widget)
2851 m_decoder->getPTS(0, pos);
2852 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2853 m_subtitle_pages.push_back(page);
2854 checkSubtitleTiming();
2858 void eDVBServicePlay::checkSubtitleTiming()
2860 eDebug("checkSubtitleTiming");
2861 if (!m_subtitle_widget)
2865 enum { TELETEXT, DVB } type;
2866 eDVBTeletextSubtitlePage page;
2867 eDVBSubtitlePage dvb_page;
2869 if (!m_subtitle_pages.empty())
2871 page = m_subtitle_pages.front();
2873 show_time = page.m_pts;
2875 else if (!m_dvb_subtitle_pages.empty())
2877 dvb_page = m_dvb_subtitle_pages.front();
2879 show_time = dvb_page.m_show_time;
2887 m_decoder->getPTS(0, pos);
2889 eDebug("%lld %lld", pos, show_time);
2890 int diff = show_time - pos;
2891 if (type == TELETEXT && !page.m_have_pts)
2893 eDebug("ttx subtitle page without pts... immediate show");
2898 eDebug("[late (%d ms)]", -diff / 90);
2901 if (abs(diff) > 1800000)
2903 eDebug("[invalid]... immediate show!");
2908 if (type == TELETEXT)
2910 eDebug("display teletext subtitle page %lld", show_time);
2911 m_subtitle_widget->setPage(page);
2912 m_subtitle_pages.pop_front();
2916 eDebug("display dvb subtitle Page %lld", show_time);
2917 m_subtitle_widget->setPage(dvb_page);
2918 m_dvb_subtitle_pages.pop_front();
2922 eDebug("start subtitle delay %d", diff / 90);
2923 m_subtitle_sync_timer->start(diff / 90, 1);
2929 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2931 if (m_subtitle_widget)
2935 m_decoder->getPTS(0, pos);
2936 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2937 m_dvb_subtitle_pages.push_back(p);
2938 checkSubtitleTiming();
2942 int eDVBServicePlay::getAC3Delay()
2945 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2947 return m_decoder->getAC3Delay();
2952 int eDVBServicePlay::getPCMDelay()
2955 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2957 return m_decoder->getPCMDelay();
2962 void eDVBServicePlay::setAC3Delay(int delay)
2965 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2967 std::string config_delay;
2968 int config_delay_int = 0;
2969 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2970 config_delay_int = atoi(config_delay.c_str());
2971 m_decoder->setAC3Delay(delay + config_delay_int);
2975 void eDVBServicePlay::setPCMDelay(int delay)
2978 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2980 std::string config_delay;
2981 int config_delay_int = 0;
2982 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2983 config_delay_int = atoi(config_delay.c_str());
2985 config_delay_int = 0;
2986 m_decoder->setPCMDelay(delay + config_delay_int);
2990 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2992 switch(event.type) {
2993 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2994 m_event((iPlayableService*)this, evVideoSizeChanged);
2996 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2997 m_event((iPlayableService*)this, evVideoFramerateChanged);
2999 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3000 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3007 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3013 PyObject *eDVBServicePlay::getStreamingData()
3015 eDVBServicePMTHandler::program program;
3016 if (m_service_handler.getProgramInfo(program))
3021 ePyObject r = program.createPythonObject();
3022 ePtr<iDVBDemux> demux;
3023 if (!m_service_handler.getDataDemux(demux))
3026 if (!demux->getCADemuxID(demux_id))
3027 PutToDict(r, "demux", demux_id);
3034 DEFINE_REF(eDVBServicePlay)
3036 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3040 case iServiceInformation::sTransponderData:
3041 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3045 return iStaticServiceInformation::getInfoObject(ref, w);
3048 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");