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;
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();
1729 case sTransponderData:
1730 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1734 return iServiceInformation::getInfoObject(w);
1737 int eDVBServicePlay::getNumberOfTracks()
1739 eDVBServicePMTHandler::program program;
1740 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1741 if (h.getProgramInfo(program))
1743 return program.audioStreams.size();
1746 int eDVBServicePlay::getCurrentTrack()
1748 eDVBServicePMTHandler::program program;
1749 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1750 if (h.getProgramInfo(program))
1753 int max = program.audioStreams.size();
1756 for (i = 0; i < max; ++i)
1757 if (program.audioStreams[i].pid == m_current_audio_pid)
1763 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1765 int ret = selectAudioStream(i);
1767 if (m_decoder->set())
1773 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1775 eDVBServicePMTHandler::program program;
1776 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1778 if (h.getProgramInfo(program))
1781 if (i >= program.audioStreams.size())
1784 info.m_pid = program.audioStreams[i].pid;
1786 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1787 info.m_description = "MPEG";
1788 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1789 info.m_description = "AC3";
1790 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1791 info.m_description = "AAC";
1792 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1793 info.m_description = "AAC-HE";
1794 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1795 info.m_description = "DTS";
1797 info.m_description = "???";
1799 if (program.audioStreams[i].component_tag != -1)
1801 ePtr<eServiceEvent> evt;
1802 if (!m_event_handler.getEvent(evt, 0))
1804 ePtr<eComponentData> data;
1805 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1806 info.m_language = data->getText();
1810 if (info.m_language.empty())
1811 info.m_language = program.audioStreams[i].language_code;
1816 int eDVBServicePlay::selectAudioStream(int i)
1818 eDVBServicePMTHandler::program program;
1819 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1820 pts_t position = -1;
1822 if (h.getProgramInfo(program))
1825 if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1833 stream = program.defaultAudioStream;
1835 int apid = -1, apidtype = -1;
1837 if (((unsigned int)stream) < program.audioStreams.size())
1839 apid = program.audioStreams[stream].pid;
1840 apidtype = program.audioStreams[stream].type;
1843 if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1844 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1846 m_current_audio_pid = apid;
1848 if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1850 eDebug("set audio pid failed");
1855 eDebug("seekTo ret %d", seekTo(position));
1859 /* 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 */
1860 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1862 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1864 rdsPid = program.audioStreams[stream].rdsPid;
1865 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1868 ePtr<iDVBDemux> data_demux;
1869 if (!h.getDataDemux(data_demux))
1871 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1872 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1873 m_rds_decoder->start(rdsPid);
1878 /* store new pid as default only when:
1879 a.) we have an entry in the service db for the current service,
1880 b.) we are not playing back something,
1881 c.) we are not selecting the default entry. (we wouldn't change
1882 anything in the best case, or destroy the default setting in
1883 case the real default is not yet available.)
1885 if (m_dvb_service && ((i != -1)
1886 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1888 if (apidtype == eDVBAudio::aMPEG)
1890 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1891 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1893 else if (apidtype == eDVBAudio::aAC3)
1895 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1896 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1900 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1901 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1905 h.resetCachedProgram();
1910 int eDVBServicePlay::getCurrentChannel()
1912 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1915 RESULT eDVBServicePlay::selectChannel(int i)
1917 if (i < LEFT || i > RIGHT || i == STEREO)
1920 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1922 m_decoder->setAudioChannel(i);
1926 std::string eDVBServicePlay::getText(int x)
1932 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1934 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1939 void eDVBServicePlay::rdsDecoderEvent(int what)
1943 case eDVBRdsDecoder::RadioTextChanged:
1944 m_event((iPlayableService*)this, evUpdatedRadioText);
1946 case eDVBRdsDecoder::RtpTextChanged:
1947 m_event((iPlayableService*)this, evUpdatedRtpText);
1949 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1950 m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1952 case eDVBRdsDecoder::RecvRassSlidePic:
1953 m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1958 void eDVBServicePlay::showRassSlidePicture()
1964 std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1965 if (rass_slide_pic.length())
1966 m_decoder->showSinglePic(rass_slide_pic.c_str());
1968 eDebug("empty filename for rass slide picture received!!");
1971 eDebug("no MPEG Decoder to show iframes avail");
1974 eDebug("showRassSlidePicture called.. but not decoder");
1977 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1983 std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1984 if (rass_interactive_pic.length())
1985 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1987 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1990 eDebug("no MPEG Decoder to show iframes avail");
1993 eDebug("showRassInteractivePic called.. but not decoder");
1996 ePyObject eDVBServicePlay::getRassInteractiveMask()
1999 return m_rds_decoder->getRassPictureMask();
2003 int eDVBServiceBase::getFrontendInfo(int w)
2005 eUsePtr<iDVBChannel> channel;
2006 if(m_service_handler.getChannel(channel))
2008 ePtr<iDVBFrontend> fe;
2009 if(channel->getFrontend(fe))
2011 return fe->readFrontendData(w);
2014 PyObject *eDVBServiceBase::getFrontendData()
2016 ePyObject ret = PyDict_New();
2019 eUsePtr<iDVBChannel> channel;
2020 if(!m_service_handler.getChannel(channel))
2022 ePtr<iDVBFrontend> fe;
2023 if(!channel->getFrontend(fe))
2024 fe->getFrontendData(ret);
2032 PyObject *eDVBServiceBase::getFrontendStatus()
2034 ePyObject ret = PyDict_New();
2037 eUsePtr<iDVBChannel> channel;
2038 if(!m_service_handler.getChannel(channel))
2040 ePtr<iDVBFrontend> fe;
2041 if(!channel->getFrontend(fe))
2042 fe->getFrontendStatus(ret);
2050 PyObject *eDVBServiceBase::getTransponderData(bool original)
2052 ePyObject ret = PyDict_New();
2055 eUsePtr<iDVBChannel> channel;
2056 if(!m_service_handler.getChannel(channel))
2058 ePtr<iDVBFrontend> fe;
2059 if(!channel->getFrontend(fe))
2060 fe->getTransponderData(ret, original);
2068 PyObject *eDVBServiceBase::getAll(bool original)
2070 ePyObject ret = getTransponderData(original);
2073 eUsePtr<iDVBChannel> channel;
2074 if(!m_service_handler.getChannel(channel))
2076 ePtr<iDVBFrontend> fe;
2077 if(!channel->getFrontend(fe))
2079 fe->getFrontendData(ret);
2080 fe->getFrontendStatus(ret);
2087 int eDVBServicePlay::getNumberOfSubservices()
2089 ePtr<eServiceEvent> evt;
2090 if (!m_event_handler.getEvent(evt, 0))
2091 return evt->getNumOfLinkageServices();
2095 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2097 ePtr<eServiceEvent> evt;
2098 if (!m_event_handler.getEvent(evt, 0))
2100 if (!evt->getLinkageService(sub, m_reference, n))
2103 sub.type=eServiceReference::idInvalid;
2107 RESULT eDVBServicePlay::startTimeshift()
2109 ePtr<iDVBDemux> demux;
2111 eDebug("Start timeshift!");
2113 if (m_timeshift_enabled)
2116 /* start recording with the data demux. */
2117 if (m_service_handler.getDataDemux(demux))
2120 demux->createTSRecorder(m_record);
2125 if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
2126 eDebug("could not query ts path");
2129 tspath.append("/timeshift.XXXXXX");
2131 templ = new char[tspath.length() + 1];
2132 strcpy(templ, tspath.c_str());
2134 m_timeshift_fd = mkstemp(templ);
2135 m_timeshift_file = std::string(templ);
2137 eDebug("recording to %s", templ);
2141 if (m_timeshift_fd < 0)
2147 m_record->setTargetFD(m_timeshift_fd);
2149 m_timeshift_enabled = 1;
2151 updateTimeshiftPids();
2157 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2159 if (!m_timeshift_enabled)
2165 m_timeshift_enabled = 0;
2170 close(m_timeshift_fd);
2171 eDebug("remove timeshift file");
2172 eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2177 int eDVBServicePlay::isTimeshiftActive()
2179 return m_timeshift_enabled && m_timeshift_active;
2182 RESULT eDVBServicePlay::activateTimeshift()
2184 if (!m_timeshift_enabled)
2187 if (!m_timeshift_active)
2189 switchToTimeshift();
2196 PyObject *eDVBServicePlay::getCutList()
2198 ePyObject list = PyList_New(0);
2200 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2202 ePyObject tuple = PyTuple_New(2);
2203 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2204 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2205 PyList_Append(list, tuple);
2212 void eDVBServicePlay::setCutList(ePyObject list)
2214 if (!PyList_Check(list))
2216 int size = PyList_Size(list);
2219 m_cue_entries.clear();
2221 for (i=0; i<size; ++i)
2223 ePyObject tuple = PyList_GET_ITEM(list, i);
2224 if (!PyTuple_Check(tuple))
2226 eDebug("non-tuple in cutlist");
2229 if (PyTuple_Size(tuple) != 2)
2231 eDebug("cutlist entries need to be a 2-tuple");
2234 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2235 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2237 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2240 pts_t pts = PyLong_AsLongLong(ppts);
2241 int type = PyInt_AsLong(ptype);
2242 m_cue_entries.insert(cueEntry(pts, type));
2243 eDebug("adding %08llx, %d", pts, type);
2245 m_cuesheet_changed = 1;
2247 cutlistToCuesheet();
2248 m_event((iPlayableService*)this, evCuesheetChanged);
2251 void eDVBServicePlay::setCutListEnable(int enable)
2253 m_cutlist_enabled = enable;
2254 cutlistToCuesheet();
2257 void eDVBServicePlay::updateTimeshiftPids()
2262 eDVBServicePMTHandler::program program;
2263 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2265 if (h.getProgramInfo(program))
2269 std::set<int> pids_to_record;
2270 pids_to_record.insert(0); // PAT
2271 if (program.pmtPid != -1)
2272 pids_to_record.insert(program.pmtPid); // PMT
2274 if (program.textPid != -1)
2275 pids_to_record.insert(program.textPid); // Videotext
2277 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2278 i(program.videoStreams.begin());
2279 i != program.videoStreams.end(); ++i)
2280 pids_to_record.insert(i->pid);
2282 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2283 i(program.audioStreams.begin());
2284 i != program.audioStreams.end(); ++i)
2285 pids_to_record.insert(i->pid);
2287 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2288 i(program.subtitleStreams.begin());
2289 i != program.subtitleStreams.end(); ++i)
2290 pids_to_record.insert(i->pid);
2292 std::set<int> new_pids, obsolete_pids;
2294 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
2295 m_pids_active.begin(), m_pids_active.end(),
2296 std::inserter(new_pids, new_pids.begin()));
2298 std::set_difference(
2299 m_pids_active.begin(), m_pids_active.end(),
2300 pids_to_record.begin(), pids_to_record.end(),
2301 std::inserter(new_pids, new_pids.begin())
2304 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2305 m_record->addPID(*i);
2307 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2308 m_record->removePID(*i);
2312 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2314 m_timeshift_file_next = f;
2318 void eDVBServicePlay::switchToLive()
2320 if (!m_timeshift_active)
2323 eDebug("SwitchToLive");
2327 m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2329 /* free the timeshift service handler, we need the resources */
2330 m_service_handler_timeshift.free();
2332 updateDecoder(true);
2335 void eDVBServicePlay::resetTimeshift(int start)
2340 m_teletext_parser = 0;
2342 m_subtitle_parser = 0;
2343 m_new_subtitle_page_connection = 0;
2344 m_new_dvb_subtitle_page_connection = 0;
2345 m_rds_decoder_event_connection = 0;
2346 m_video_event_connection = 0;
2347 m_timeshift_changed = 1;
2348 m_timeshift_file_next.clear();
2352 m_cue = new eCueSheet();
2353 m_timeshift_active = 1;
2356 m_timeshift_active = 0;
2359 void eDVBServicePlay::switchToTimeshift()
2361 if (m_timeshift_active)
2366 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2367 r.path = m_timeshift_file;
2369 m_cue->seekTo(0, -1000);
2370 m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2372 eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2374 updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2377 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2379 int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2380 bool mustPlay = false;
2382 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2384 eDVBServicePMTHandler::program program;
2385 if (h.getProgramInfo(program))
2386 eDebug("getting program info failed.");
2389 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2390 if (!program.videoStreams.empty())
2392 eDebugNoNewLine(" (");
2393 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2394 i(program.videoStreams.begin());
2395 i != program.videoStreams.end(); ++i)
2402 if (i != program.videoStreams.begin())
2403 eDebugNoNewLine(", ");
2404 eDebugNoNewLine("%04x", i->pid);
2406 eDebugNoNewLine(")");
2408 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2409 if (!program.audioStreams.empty())
2411 eDebugNoNewLine(" (");
2412 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2413 i(program.audioStreams.begin());
2414 i != program.audioStreams.end(); ++i)
2416 if (i != program.audioStreams.begin())
2417 eDebugNoNewLine(", ");
2418 eDebugNoNewLine("%04x", i->pid);
2420 eDebugNoNewLine(")");
2422 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2423 pcrpid = program.pcrPid;
2424 eDebug(", and the text pid is %04x", program.textPid);
2425 tpid = program.textPid;
2430 h.getDecodeDemux(m_decode_demux);
2433 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2435 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2438 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2439 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2440 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2441 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2442 if (m_timeshift_changed)
2444 ePyObject subs = getCachedSubtitle();
2445 if (subs != Py_None)
2447 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2448 pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2449 comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2450 anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2451 if (type == 0) // dvb
2452 m_subtitle_parser->start(pid, comp_page, anc_page);
2453 else if (type == 1) // ttx
2454 m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2461 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2465 m_timeshift_changed = 0;
2469 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2472 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2473 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2474 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2478 eServiceReferenceDVB ref;
2479 m_service_handler.getServiceReference(ref);
2480 eServiceReferenceDVB parent = ref.getParentServiceReference();
2485 ePtr<eDVBResourceManager> res_mgr;
2486 if (!eDVBResourceManager::getInstance(res_mgr))
2488 ePtr<iDVBChannelList> db;
2489 if (!res_mgr->getChannelList(db))
2491 ePtr<eDVBService> origService;
2492 if (!db->getService(parent, origService))
2494 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2495 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2502 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2503 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2505 m_decoder->setVideoPID(vpid, vpidtype);
2506 selectAudioStream();
2508 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2509 m_decoder->setSyncPCR(pcrpid);
2511 m_decoder->setSyncPCR(-1);
2515 m_decoder->setTextPID(tpid);
2516 m_teletext_parser->start(program.textPid);
2519 if (vpid > 0 && vpid < 0x2000)
2523 std::string radio_pic;
2524 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2525 m_decoder->setRadioPic(radio_pic);
2533 m_decoder->setAudioChannel(achannel);
2535 /* don't worry about non-existing services, nor pvr services */
2538 /* (audio pid will be set in selectAudioTrack */
2539 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2540 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2541 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2542 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2544 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2545 sendSeekableStateChanged = true;
2547 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2549 if (sendSeekableStateChanged)
2550 m_event((iPlayableService*)this, evSeekableStatusChanged);
2553 void eDVBServicePlay::loadCuesheet()
2555 std::string filename = m_reference.path + ".cuts";
2557 m_cue_entries.clear();
2559 FILE *f = fopen(filename.c_str(), "rb");
2563 eDebug("loading cuts..");
2566 unsigned long long where;
2569 if (!fread(&where, sizeof(where), 1, f))
2571 if (!fread(&what, sizeof(what), 1, f))
2574 #if BYTE_ORDER == LITTLE_ENDIAN
2575 where = bswap_64(where);
2582 m_cue_entries.insert(cueEntry(where, what));
2585 eDebug("%d entries", m_cue_entries.size());
2587 eDebug("cutfile not found!");
2589 m_cuesheet_changed = 0;
2590 cutlistToCuesheet();
2591 m_event((iPlayableService*)this, evCuesheetChanged);
2594 void eDVBServicePlay::saveCuesheet()
2596 std::string filename = m_reference.path + ".cuts";
2598 FILE *f = fopen(filename.c_str(), "wb");
2602 unsigned long long where;
2605 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2607 #if BYTE_ORDER == BIG_ENDIAN
2610 where = bswap_64(i->where);
2612 what = htonl(i->what);
2613 fwrite(&where, sizeof(where), 1, f);
2614 fwrite(&what, sizeof(what), 1, f);
2620 m_cuesheet_changed = 0;
2623 void eDVBServicePlay::cutlistToCuesheet()
2627 eDebug("no cue sheet");
2632 if (!m_cutlist_enabled)
2634 m_cue->commitSpans();
2635 eDebug("cutlists were disabled");
2639 pts_t in = 0, out = 0, length = 0;
2643 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2645 int have_any_span = 0;
2649 if (i == m_cue_entries.end())
2651 if (!have_any_span && !in)
2655 if (i->what == 0) /* in */
2659 } else if (i->what == 1) /* out */
2661 else /* mark (2) or last play position (3) */
2680 m_cue->addSourceSpan(in, out);
2686 if (i == m_cue_entries.end())
2689 m_cue->commitSpans();
2692 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2694 if (m_subtitle_widget)
2695 disableSubtitles(parent);
2698 int tuplesize = PyTuple_Size(tuple);
2701 if (!PyTuple_Check(tuple))
2707 entry = PyTuple_GET_ITEM(tuple, 0);
2709 if (!PyInt_Check(entry))
2712 type = PyInt_AsLong(entry);
2714 if (type == 1) // teletext subtitles
2716 int page, magazine, pid;
2720 if (!m_teletext_parser)
2722 eDebug("enable teletext subtitles.. no parser !!!");
2726 entry = PyTuple_GET_ITEM(tuple, 1);
2727 if (!PyInt_Check(entry))
2729 pid = PyInt_AsLong(entry);
2731 entry = PyTuple_GET_ITEM(tuple, 2);
2732 if (!PyInt_Check(entry))
2734 page = PyInt_AsLong(entry);
2736 entry = PyTuple_GET_ITEM(tuple, 3);
2737 if (!PyInt_Check(entry))
2739 magazine = PyInt_AsLong(entry);
2741 m_subtitle_widget = new eSubtitleWidget(parent);
2742 m_subtitle_widget->resize(parent->size()); /* full size */
2743 m_teletext_parser->setPageAndMagazine(page, magazine);
2745 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2749 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2750 if (!m_subtitle_parser)
2752 eDebug("enable dvb subtitles.. no parser !!!");
2758 entry = PyTuple_GET_ITEM(tuple, 1);
2759 if (!PyInt_Check(entry))
2761 pid = PyInt_AsLong(entry);
2763 entry = PyTuple_GET_ITEM(tuple, 2);
2764 if (!PyInt_Check(entry))
2766 composition_page_id = PyInt_AsLong(entry);
2768 entry = PyTuple_GET_ITEM(tuple, 3);
2769 if (!PyInt_Check(entry))
2771 ancillary_page_id = PyInt_AsLong(entry);
2773 m_subtitle_widget = new eSubtitleWidget(parent);
2774 m_subtitle_widget->resize(parent->size()); /* full size */
2775 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2777 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2783 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2784 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2785 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2789 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2791 delete m_subtitle_widget;
2792 m_subtitle_widget = 0;
2793 if (m_subtitle_parser)
2795 m_subtitle_parser->stop();
2796 m_dvb_subtitle_pages.clear();
2798 if (m_teletext_parser)
2800 m_teletext_parser->setPageAndMagazine(-1, -1);
2801 m_subtitle_pages.clear();
2804 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2808 PyObject *eDVBServicePlay::getCachedSubtitle()
2812 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2815 unsigned int data = (unsigned int)tmp;
2816 int pid = (data&0xFFFF0000)>>16;
2817 ePyObject tuple = PyTuple_New(4);
2818 eDVBServicePMTHandler::program program;
2819 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2820 if (!h.getProgramInfo(program))
2822 if (program.textPid==pid) // teletext
2823 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2825 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2826 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2827 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2828 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2836 PyObject *eDVBServicePlay::getSubtitleList()
2838 if (!m_teletext_parser)
2841 ePyObject l = PyList_New(0);
2842 std::set<int> added_ttx_pages;
2844 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2845 m_teletext_parser->m_found_subtitle_pages;
2847 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2848 eDVBServicePMTHandler::program program;
2849 if (h.getProgramInfo(program))
2850 eDebug("getting program info failed.");
2853 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2854 it != program.subtitleStreams.end(); ++it)
2856 switch(it->subtitling_type)
2858 case 0x01: // ebu teletext subtitles
2860 int page_number = it->teletext_page_number & 0xFF;
2861 int magazine_number = it->teletext_magazine_number & 7;
2862 int hash = magazine_number << 8 | page_number;
2863 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2865 ePyObject tuple = PyTuple_New(5);
2866 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2867 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2868 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2869 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2870 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2871 PyList_Append(l, tuple);
2873 added_ttx_pages.insert(hash);
2878 case 0x20 ... 0x23: // dvb subtitles
2880 ePyObject tuple = PyTuple_New(5);
2881 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2882 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2883 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2884 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2885 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2886 PyList_Insert(l, 0, tuple);
2894 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2895 it != subs.end(); ++it)
2897 int page_number = it->teletext_page_number & 0xFF;
2898 int magazine_number = it->teletext_magazine_number & 7;
2899 int hash = magazine_number << 8 | page_number;
2900 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2902 ePyObject tuple = PyTuple_New(5);
2903 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2904 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2905 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2906 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2907 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2908 PyList_Append(l, tuple);
2916 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2918 if (m_subtitle_widget)
2922 m_decoder->getPTS(0, pos);
2923 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2924 m_subtitle_pages.push_back(page);
2925 checkSubtitleTiming();
2929 void eDVBServicePlay::checkSubtitleTiming()
2931 eDebug("checkSubtitleTiming");
2932 if (!m_subtitle_widget)
2936 enum { TELETEXT, DVB } type;
2937 eDVBTeletextSubtitlePage page;
2938 eDVBSubtitlePage dvb_page;
2940 if (!m_subtitle_pages.empty())
2942 page = m_subtitle_pages.front();
2944 show_time = page.m_pts;
2946 else if (!m_dvb_subtitle_pages.empty())
2948 dvb_page = m_dvb_subtitle_pages.front();
2950 show_time = dvb_page.m_show_time;
2958 m_decoder->getPTS(0, pos);
2960 eDebug("%lld %lld", pos, show_time);
2961 int diff = show_time - pos;
2962 if (type == TELETEXT && !page.m_have_pts)
2964 eDebug("ttx subtitle page without pts... immediate show");
2969 eDebug("[late (%d ms)]", -diff / 90);
2972 if (abs(diff) > 1800000)
2974 eDebug("[invalid]... immediate show!");
2979 if (type == TELETEXT)
2981 eDebug("display teletext subtitle page %lld", show_time);
2982 m_subtitle_widget->setPage(page);
2983 m_subtitle_pages.pop_front();
2987 eDebug("display dvb subtitle Page %lld", show_time);
2988 m_subtitle_widget->setPage(dvb_page);
2989 m_dvb_subtitle_pages.pop_front();
2993 eDebug("start subtitle delay %d", diff / 90);
2994 m_subtitle_sync_timer->start(diff / 90, 1);
3000 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3002 if (m_subtitle_widget)
3006 m_decoder->getPTS(0, pos);
3007 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3008 m_dvb_subtitle_pages.push_back(p);
3009 checkSubtitleTiming();
3013 int eDVBServicePlay::getAC3Delay()
3016 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3018 return m_decoder->getAC3Delay();
3023 int eDVBServicePlay::getPCMDelay()
3026 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3028 return m_decoder->getPCMDelay();
3033 void eDVBServicePlay::setAC3Delay(int delay)
3036 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3038 std::string config_delay;
3039 int config_delay_int = 0;
3040 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3041 config_delay_int = atoi(config_delay.c_str());
3042 m_decoder->setAC3Delay(delay + config_delay_int);
3046 void eDVBServicePlay::setPCMDelay(int delay)
3049 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3051 std::string config_delay;
3052 int config_delay_int = 0;
3053 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3054 config_delay_int = atoi(config_delay.c_str());
3056 config_delay_int = 0;
3057 m_decoder->setPCMDelay(delay + config_delay_int);
3061 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3063 switch(event.type) {
3064 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3065 m_event((iPlayableService*)this, evVideoSizeChanged);
3067 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3068 m_event((iPlayableService*)this, evVideoFramerateChanged);
3070 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3071 m_event((iPlayableService*)this, evVideoProgressiveChanged);
3078 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3084 PyObject *eDVBServicePlay::getStreamingData()
3086 eDVBServicePMTHandler::program program;
3087 if (m_service_handler.getProgramInfo(program))
3092 ePyObject r = program.createPythonObject();
3093 ePtr<iDVBDemux> demux;
3094 if (!m_service_handler.getDataDemux(demux))
3097 if (!demux->getCADemuxID(demux_id))
3098 PutToDict(r, "demux", demux_id);
3105 DEFINE_REF(eDVBServicePlay)
3107 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3111 case iServiceInformation::sTransponderData:
3112 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3116 return iStaticServiceInformation::getInfoObject(ref, w);
3119 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");