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/init_num.h>
7 #include <lib/base/init.h>
8 #include <lib/base/nconfig.h> // access to python config
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>
21 #include <lib/gui/esubtitle.h>
27 #include <netinet/in.h>
29 #define INTERNAL_TELETEXT
32 #error no byte order defined!
35 #define TSPATH "/media/hdd"
37 class eStaticServiceDVBInformation: public iStaticServiceInformation
39 DECLARE_REF(eStaticServiceDVBInformation);
41 RESULT getName(const eServiceReference &ref, std::string &name);
42 int getLength(const eServiceReference &ref);
45 DEFINE_REF(eStaticServiceDVBInformation);
47 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
49 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
50 if ( !ref.name.empty() )
52 if (service.getParentTransportStreamID().get()) // linkage subservice
54 ePtr<iServiceHandler> service_center;
55 if (!eServiceCenter::getInstance(service_center))
57 eServiceReferenceDVB parent = service;
58 parent.setTransportStreamID( service.getParentTransportStreamID() );
59 parent.setServiceID( service.getParentServiceID() );
60 parent.setParentTransportStreamID(eTransportStreamID(0));
61 parent.setParentServiceID(eServiceID(0));
63 ePtr<iStaticServiceInformation> service_info;
64 if (!service_center->info(parent, service_info))
66 if (!service_info->getName(parent, name))
68 // just show short name
69 unsigned int pos = name.find("\xc2\x86");
70 if ( pos != std::string::npos )
72 pos = name.find("\xc2\x87");
73 if ( pos != std::string::npos )
89 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
94 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
96 DECLARE_REF(eStaticServiceDVBBouquetInformation);
98 RESULT getName(const eServiceReference &ref, std::string &name);
99 int getLength(const eServiceReference &ref);
102 DEFINE_REF(eStaticServiceDVBBouquetInformation);
104 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
106 ePtr<iDVBChannelList> db;
107 ePtr<eDVBResourceManager> res;
110 if ((err = eDVBResourceManager::getInstance(res)) != 0)
112 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
115 if ((err = res->getChannelList(db)) != 0)
117 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
122 if ((err = db->getBouquet(ref, bouquet)) != 0)
124 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
128 if ( bouquet && bouquet->m_bouquet_name.length() )
130 name = bouquet->m_bouquet_name;
137 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
142 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
144 DECLARE_REF(eStaticServiceDVBPVRInformation);
145 eServiceReference m_ref;
146 eDVBMetaParser m_parser;
148 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
149 RESULT getName(const eServiceReference &ref, std::string &name);
150 int getLength(const eServiceReference &ref);
151 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
153 int getInfo(const eServiceReference &ref, int w);
154 std::string getInfoString(const eServiceReference &ref,int w);
157 DEFINE_REF(eStaticServiceDVBPVRInformation);
159 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
162 m_parser.parseFile(ref.path);
165 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
167 ASSERT(ref == m_ref);
168 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
172 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
174 ASSERT(ref == m_ref);
178 if (tstools.openFile(ref.path.c_str()))
182 if (tstools.calcLen(len))
188 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
192 case iServiceInformation::sDescription:
193 return iServiceInformation::resIsString;
194 case iServiceInformation::sServiceref:
195 return iServiceInformation::resIsString;
196 case iServiceInformation::sTimeCreate:
197 if (m_parser.m_time_create)
198 return m_parser.m_time_create;
200 return iServiceInformation::resNA;
202 return iServiceInformation::resNA;
206 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
210 case iServiceInformation::sDescription:
211 return m_parser.m_description;
212 case iServiceInformation::sServiceref:
213 return m_parser.m_ref.toString();
219 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
221 if (!ref.path.empty())
223 ePtr<eServiceEvent> event = new eServiceEvent;
224 std::string filename = ref.path;
225 filename.erase(filename.length()-2, 2);
227 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
237 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
239 DECLARE_REF(eDVBPVRServiceOfflineOperations);
240 eServiceReferenceDVB m_ref;
242 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
244 RESULT deleteFromDisk(int simulate);
245 RESULT getListOfFilenames(std::list<std::string> &);
248 DEFINE_REF(eDVBPVRServiceOfflineOperations);
250 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
254 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
260 std::list<std::string> res;
261 if (getListOfFilenames(res))
264 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
266 eDebug("FATAL !! can't get background file eraser");
268 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
270 eDebug("Removing %s...", i->c_str());
272 eraser->erase(i->c_str());
274 ::unlink(i->c_str());
281 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
284 res.push_back(m_ref.path);
286 // handling for old splitted recordings (enigma 1)
291 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
293 if (stat(buf, &s) < 0)
298 res.push_back(m_ref.path + ".meta");
299 res.push_back(m_ref.path + ".ap");
300 res.push_back(m_ref.path + ".cuts");
301 std::string tmp = m_ref.path;
302 tmp.erase(m_ref.path.length()-3);
303 res.push_back(tmp + ".eit");
307 DEFINE_REF(eServiceFactoryDVB)
309 eServiceFactoryDVB::eServiceFactoryDVB()
311 ePtr<eServiceCenter> sc;
313 eServiceCenter::getPrivInstance(sc);
315 sc->addServiceFactory(eServiceFactoryDVB::id, this);
317 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
318 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
321 eServiceFactoryDVB::~eServiceFactoryDVB()
323 ePtr<eServiceCenter> sc;
325 eServiceCenter::getPrivInstance(sc);
327 sc->removeServiceFactory(eServiceFactoryDVB::id);
330 DEFINE_REF(eDVBServiceList);
332 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
336 eDVBServiceList::~eDVBServiceList()
340 RESULT eDVBServiceList::startQuery()
342 ePtr<iDVBChannelList> db;
343 ePtr<eDVBResourceManager> res;
346 if ((err = eDVBResourceManager::getInstance(res)) != 0)
348 eDebug("no resource manager");
351 if ((err = res->getChannelList(db)) != 0)
353 eDebug("no channel list");
357 ePtr<eDVBChannelQuery> q;
359 if (!m_parent.path.empty())
361 eDVBChannelQuery::compile(q, m_parent.path);
364 eDebug("compile query failed");
369 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
371 eDebug("startQuery failed");
378 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
380 eServiceReferenceDVB ref;
385 while (!m_query->getNextResult(ref))
389 list.sort(iListableServiceCompare(this));
394 // The first argument of this function is a format string to specify the order and
395 // the content of the returned list
396 // useable format options are
397 // R = Service Reference (as swig object .. this is very slow)
398 // S = Service Reference (as python string object .. same as ref.toString())
399 // C = Service Reference (as python string object .. same as ref.toCompareString())
400 // N = Service Name (as python string object)
401 // when exactly one return value per service is selected in the format string,
402 // then each value is directly a list entry
403 // when more than one value is returned per service, then the list is a list of
405 // unknown format string chars are returned as python None values !
406 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
409 std::list<eServiceReference> tmplist;
412 if (!format || !(retcount=strlen(format)))
413 format = "R"; // just return service reference swig object ...
415 if (!getContent(tmplist, sorted))
417 int services=tmplist.size();
418 ePtr<iStaticServiceInformation> sptr;
419 eServiceCenterPtr service_center;
421 if (strchr(format, 'N'))
422 eServiceCenter::getPrivInstance(service_center);
424 ret = PyList_New(services);
425 std::list<eServiceReference>::iterator it(tmplist.begin());
427 for (int cnt=0; cnt < services; ++cnt)
429 eServiceReference &ref=*it++;
430 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
431 for (int i=0; i < retcount; ++i)
436 case 'R': // service reference (swig)object
437 tmp = New_eServiceReference(ref);
439 case 'C': // service reference compare string
440 tmp = PyString_FromString(ref.toCompareString().c_str());
442 case 'S': // service reference string
443 tmp = PyString_FromString(ref.toString().c_str());
445 case 'N': // service name
448 service_center->info(ref, sptr);
452 sptr->getName(ref, name);
454 tmp = PyString_FromString(name.c_str());
458 tmp = PyString_FromString("<n/a>");
471 PyTuple_SET_ITEM(tuple, i, tmp);
473 PyList_SET_ITEM(ret, cnt, tmp);
477 PyList_SET_ITEM(ret, cnt, tuple);
480 return ret ? ret : PyList_New(0);
483 RESULT eDVBServiceList::getNext(eServiceReference &ref)
488 return m_query->getNextResult((eServiceReferenceDVB&)ref);
491 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
493 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
496 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
498 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
500 ePtr<iDVBChannelList> db;
501 ePtr<eDVBResourceManager> resm;
503 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
506 if (db->getBouquet(m_parent, m_bouquet) != 0)
517 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
521 return m_bouquet->addService(ref, before);
524 RESULT eDVBServiceList::removeService(eServiceReference &ref)
528 return m_bouquet->removeService(ref);
531 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
535 return m_bouquet->moveService(ref, pos);
538 RESULT eDVBServiceList::flushChanges()
542 return m_bouquet->flushChanges();
545 RESULT eDVBServiceList::setListName(const std::string &name)
549 return m_bouquet->setListName(name);
552 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
554 ePtr<eDVBService> service;
555 int r = lookupService(service, ref);
558 // check resources...
559 ptr = new eDVBServicePlay(ref, service);
563 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
565 if (ref.path.empty())
567 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
576 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
578 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
579 if (list->startQuery())
589 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
591 /* is a listable service? */
592 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
594 if ( !ref.name.empty() ) // satellites or providers list
595 ptr = m_StaticServiceDVBInfo;
596 else // a dvb bouquet
597 ptr = m_StaticServiceDVBBouquetInfo;
599 else if (!ref.path.empty()) /* do we have a PVR service? */
600 ptr = new eStaticServiceDVBPVRInformation(ref);
601 else // normal dvb service
603 ePtr<eDVBService> service;
604 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
605 ptr = m_StaticServiceDVBInfo;
607 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
613 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
615 if (ref.path.empty())
621 ptr = new eDVBPVRServiceOfflineOperations(ref);
626 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
628 // TODO: handle the listing itself
629 // if (ref.... == -1) .. return "... bouquets ...";
630 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
632 ePtr<iDVBChannelList> db;
633 ePtr<eDVBResourceManager> res;
636 if ((err = eDVBResourceManager::getInstance(res)) != 0)
638 eDebug("no resource manager");
641 if ((err = res->getChannelList(db)) != 0)
643 eDebug("no channel list");
647 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
648 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
650 eDebug("getService failed!");
657 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
658 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
661 m_is_pvr = !m_reference.path.empty();
663 m_timeshift_enabled = m_timeshift_active = 0;
666 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
667 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
668 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
670 m_cuesheet_changed = 0;
671 m_cutlist_enabled = 1;
673 m_subtitle_widget = 0;
675 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
678 eDVBServicePlay::~eDVBServicePlay()
680 delete m_subtitle_widget;
683 void eDVBServicePlay::gotNewEvent()
687 ePtr<eServiceEvent> m_event_now, m_event_next;
688 getEvent(m_event_now, 0);
689 getEvent(m_event_next, 1);
692 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
694 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
696 m_event((iPlayableService*)this, evUpdatedEventInfo);
699 void eDVBServicePlay::serviceEvent(int event)
703 case eDVBServicePMTHandler::eventTuned:
705 ePtr<iDVBDemux> m_demux;
706 if (!m_service_handler.getDataDemux(m_demux))
708 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
709 int sid = ref.getParentServiceID().get();
711 sid = ref.getServiceID().get();
712 if ( ref.getParentTransportStreamID().get() &&
713 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
714 m_event_handler.startOther(m_demux, sid);
716 m_event_handler.start(m_demux, sid);
720 case eDVBServicePMTHandler::eventTuneFailed:
722 eDebug("DVB service failed to tune");
723 m_event((iPlayableService*)this, evTuneFailed);
726 case eDVBServicePMTHandler::eventNewProgramInfo:
728 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
729 if (m_timeshift_enabled)
730 updateTimeshiftPids();
731 if (!m_timeshift_active)
733 if (m_first_program_info && m_is_pvr)
735 m_first_program_info = 0;
738 m_event((iPlayableService*)this, evUpdatedInfo);
741 case eDVBServicePMTHandler::eventEOF:
742 m_event((iPlayableService*)this, evEOF);
744 case eDVBServicePMTHandler::eventSOF:
745 m_event((iPlayableService*)this, evSOF);
750 void eDVBServicePlay::serviceEventTimeshift(int event)
754 case eDVBServicePMTHandler::eventNewProgramInfo:
755 if (m_timeshift_active)
758 case eDVBServicePMTHandler::eventSOF:
759 m_event((iPlayableService*)this, evSOF);
761 case eDVBServicePMTHandler::eventEOF:
767 RESULT eDVBServicePlay::start()
770 /* in pvr mode, we only want to use one demux. in tv mode, we're using
771 two (one for decoding, one for data source), as we must be prepared
772 to start recording from the data demux. */
774 m_cue = new eCueSheet();
776 m_first_program_info = 1;
777 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
778 r = m_service_handler.tune(service, m_is_pvr, m_cue);
780 /* inject EIT if there is a stored one */
783 std::string filename = service.path;
784 filename.erase(filename.length()-2, 2);
786 ePtr<eServiceEvent> event = new eServiceEvent;
787 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
789 ePtr<eServiceEvent> empty;
790 m_event_handler.inject(event, 0);
791 m_event_handler.inject(empty, 1);
798 m_event(this, evStart);
799 m_event((iPlayableService*)this, evSeekableStatusChanged);
803 RESULT eDVBServicePlay::stop()
805 /* add bookmark for last play position */
809 if (!getPlayPosition(play_position))
811 /* remove last position */
812 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
814 if (i->what == 3) /* current play position */
816 m_cue_entries.erase(i);
817 i = m_cue_entries.begin();
823 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
824 m_cuesheet_changed = 1;
828 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
830 m_service_handler_timeshift.free();
831 m_service_handler.free();
833 if (m_is_pvr && m_cuesheet_changed)
836 /* save cuesheet only when main file is accessible. */
837 if (!::stat(m_reference.path.c_str(), &s))
844 RESULT eDVBServicePlay::setTarget(int target)
846 m_is_primary = !target;
850 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
852 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
856 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
858 /* note: we check for timeshift to be enabled,
859 not neccessary active. if you pause when timeshift
860 is not active, you should activate it when unpausing */
861 if ((!m_is_pvr) && (!m_timeshift_enabled))
871 RESULT eDVBServicePlay::setSlowMotion(int ratio)
874 return m_decoder->setSlowMotion(ratio);
879 RESULT eDVBServicePlay::setFastForward(int ratio)
881 int skipmode, ffratio;
887 } else if (ratio > 0)
895 } else // if (ratio < 0)
901 if (m_skipmode != skipmode)
903 eDebug("setting cue skipmode to %d", skipmode);
905 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
908 m_skipmode = skipmode;
913 return m_decoder->setFastForward(ffratio);
916 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
918 if (m_is_pvr || m_timeshift_enabled)
928 /* TODO: when timeshift is enabled but not active, this doesn't work. */
929 RESULT eDVBServicePlay::getLength(pts_t &len)
931 ePtr<iDVBPVRChannel> pvr_channel;
933 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
936 return pvr_channel->getLength(len);
939 RESULT eDVBServicePlay::pause()
941 if (!m_is_paused && m_decoder)
944 return m_decoder->freeze(0);
949 RESULT eDVBServicePlay::unpause()
951 if (m_is_paused && m_decoder)
954 return m_decoder->unfreeze();
959 RESULT eDVBServicePlay::seekTo(pts_t to)
961 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
966 ePtr<iDVBPVRChannel> pvr_channel;
968 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
974 m_cue->seekTo(0, to);
978 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
980 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
985 ePtr<iDVBPVRChannel> pvr_channel;
987 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
992 /* HACK until we have skip-AP api */
993 if ((to > 0) && (to < 100))
1001 m_cue->seekTo(mode, to);
1005 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1007 ePtr<iDVBPVRChannel> pvr_channel;
1009 if (!m_decode_demux)
1012 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1017 /* if there is a decoder, use audio or video PTS */
1020 r = m_decoder->getPTS(0, pos);
1026 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1029 RESULT eDVBServicePlay::setTrickmode(int trick)
1032 m_decoder->setTrickmode(trick);
1036 RESULT eDVBServicePlay::isCurrentlySeekable()
1038 return m_is_pvr || m_timeshift_active;
1041 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1047 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1053 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1059 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1065 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1071 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1074 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1075 (m_timeshift_enabled || !m_is_pvr))
1077 if (!m_timeshift_enabled)
1079 /* we need enough diskspace */
1081 if (statfs(TSPATH "/.", &fs) < 0)
1083 eDebug("statfs failed!");
1087 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1089 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1099 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1110 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1116 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1122 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1128 RESULT eDVBServicePlay::getName(std::string &name)
1132 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1133 return i->getName(m_reference, name);
1137 m_dvb_service->getName(m_reference, name);
1141 else if (!m_reference.name.empty())
1142 eStaticServiceDVBInformation().getName(m_reference, name);
1144 name = "DVB service";
1148 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1150 return m_event_handler.getEvent(evt, nownext);
1153 int eDVBServicePlay::getInfo(int w)
1155 eDVBServicePMTHandler::program program;
1158 return resIsPyObject;
1160 if (m_service_handler.getProgramInfo(program))
1166 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1168 ePtr<eServiceEvent> evt;
1169 if (!m_event_handler.getEvent(evt, 0))
1171 ePtr<eComponentData> data;
1172 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1174 if ( data->getStreamContent() == 1 )
1176 switch(data->getComponentType())
1179 case 1: // 4:3 SD PAL
1181 case 3: // 16:9 SD PAL
1182 case 4: // > 16:9 PAL
1183 case 5: // 4:3 SD NTSC
1185 case 7: // 16:9 SD NTSC
1186 case 8: // > 16:9 NTSC
1189 case 9: // 4:3 HD PAL
1191 case 0xB: // 16:9 HD PAL
1192 case 0xC: // > 16:9 HD PAL
1193 case 0xD: // 4:3 HD NTSC
1195 case 0xF: // 16:9 HD NTSC
1196 case 0x10: // > 16:9 HD PAL
1197 return data->getComponentType();
1204 case sIsCrypted: return program.isCrypted();
1205 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1206 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1207 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1208 case sPCRPID: return program.pcrPid;
1209 case sPMTPID: return program.pmtPid;
1210 case sTXTPID: return program.textPid;
1211 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1212 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1213 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1214 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1215 case sProvider: if (!m_dvb_service) return -1; return -2;
1221 std::string eDVBServicePlay::getInfoString(int w)
1226 if (!m_dvb_service) return "";
1227 return m_dvb_service->m_provider_name;
1231 return iServiceInformation::getInfoString(w);
1234 PyObject *eDVBServicePlay::getInfoObject(int w)
1239 return m_service_handler.getCaIds();
1243 return iServiceInformation::getInfoObject(w);
1246 int eDVBServicePlay::getNumberOfTracks()
1248 eDVBServicePMTHandler::program program;
1249 if (m_service_handler.getProgramInfo(program))
1251 return program.audioStreams.size();
1254 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1256 int ret = selectAudioStream(i);
1258 if (m_decoder->start())
1264 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1266 eDVBServicePMTHandler::program program;
1268 if (m_service_handler.getProgramInfo(program))
1271 if (i >= program.audioStreams.size())
1274 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1275 info.m_description = "MPEG";
1276 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1277 info.m_description = "AC3";
1278 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1279 info.m_description = "AAC";
1280 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1281 info.m_description = "DTS";
1283 info.m_description = "???";
1285 if (program.audioStreams[i].component_tag != -1)
1287 ePtr<eServiceEvent> evt;
1288 if (!m_event_handler.getEvent(evt, 0))
1290 ePtr<eComponentData> data;
1291 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1292 info.m_language = data->getText();
1296 if (info.m_language.empty())
1297 info.m_language = program.audioStreams[i].language_code;
1302 int eDVBServicePlay::selectAudioStream(int i)
1304 eDVBServicePMTHandler::program program;
1306 if (m_service_handler.getProgramInfo(program))
1309 if ((unsigned int)i >= program.audioStreams.size())
1315 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1318 if (m_radiotext_parser)
1319 m_radiotext_parser->start(program.audioStreams[i].pid);
1321 if (m_dvb_service && !m_is_pvr)
1323 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1325 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1326 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1330 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1331 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1338 int eDVBServicePlay::getCurrentChannel()
1340 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1343 RESULT eDVBServicePlay::selectChannel(int i)
1345 if (i < LEFT || i > RIGHT || i == STEREO)
1348 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1350 m_decoder->setAudioChannel(i);
1354 std::string eDVBServicePlay::getRadioText(int x)
1356 if (m_radiotext_parser)
1360 return m_radiotext_parser->getCurrentText();
1365 void eDVBServicePlay::radioTextUpdated()
1367 m_event((iPlayableService*)this, evUpdatedRadioText);
1370 int eDVBServiceBase::getFrontendInfo(int w)
1372 eUsePtr<iDVBChannel> channel;
1373 if(m_service_handler.getChannel(channel))
1375 ePtr<iDVBFrontend> fe;
1376 if(channel->getFrontend(fe))
1378 return fe->readFrontendData(w);
1381 PyObject *eDVBServiceBase::getFrontendData(bool original)
1385 eUsePtr<iDVBChannel> channel;
1386 if(!m_service_handler.getChannel(channel))
1388 ePtr<iDVBFrontend> fe;
1389 if(!channel->getFrontend(fe))
1391 ret = fe->readTransponderData(original);
1394 ePtr<iDVBFrontendParameters> feparm;
1395 channel->getCurrentFrontendParameters(feparm);
1398 eDVBFrontendParametersSatellite osat;
1399 if (!feparm->getDVBS(osat))
1401 void PutToDict(PyObject *, const char*, long);
1402 void PutToDict(PyObject *, const char*, const char*);
1403 PutToDict(ret, "orbital_position", osat.orbital_position);
1404 const char *tmp = "UNKNOWN";
1405 switch(osat.polarisation)
1407 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1408 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1409 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1410 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1413 PutToDict(ret, "polarization", tmp);
1427 int eDVBServicePlay::getNumberOfSubservices()
1429 ePtr<eServiceEvent> evt;
1430 if (!m_event_handler.getEvent(evt, 0))
1431 return evt->getNumOfLinkageServices();
1435 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1437 ePtr<eServiceEvent> evt;
1438 if (!m_event_handler.getEvent(evt, 0))
1440 if (!evt->getLinkageService(sub, m_reference, n))
1443 sub.type=eServiceReference::idInvalid;
1447 RESULT eDVBServicePlay::startTimeshift()
1449 ePtr<iDVBDemux> demux;
1451 eDebug("Start timeshift!");
1453 if (m_timeshift_enabled)
1456 /* start recording with the data demux. */
1457 if (m_service_handler.getDataDemux(demux))
1460 demux->createTSRecorder(m_record);
1464 char templ[]=TSPATH "/timeshift.XXXXXX";
1465 m_timeshift_fd = mkstemp(templ);
1466 m_timeshift_file = templ;
1468 eDebug("recording to %s", templ);
1470 if (m_timeshift_fd < 0)
1476 m_record->setTargetFD(m_timeshift_fd);
1478 m_timeshift_enabled = 1;
1480 updateTimeshiftPids();
1486 RESULT eDVBServicePlay::stopTimeshift()
1488 if (!m_timeshift_enabled)
1493 m_timeshift_enabled = 0;
1498 close(m_timeshift_fd);
1499 eDebug("remove timeshift file");
1500 remove(m_timeshift_file.c_str());
1505 int eDVBServicePlay::isTimeshiftActive()
1507 return m_timeshift_enabled && m_timeshift_active;
1510 RESULT eDVBServicePlay::activateTimeshift()
1512 if (!m_timeshift_enabled)
1515 if (!m_timeshift_active)
1517 switchToTimeshift();
1524 PyObject *eDVBServicePlay::getCutList()
1526 PyObject *list = PyList_New(0);
1528 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1530 PyObject *tuple = PyTuple_New(2);
1531 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1532 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1533 PyList_Append(list, tuple);
1540 void eDVBServicePlay::setCutList(PyObject *list)
1542 if (!PyList_Check(list))
1544 int size = PyList_Size(list);
1547 m_cue_entries.clear();
1549 for (i=0; i<size; ++i)
1551 PyObject *tuple = PyList_GetItem(list, i);
1552 if (!PyTuple_Check(tuple))
1554 eDebug("non-tuple in cutlist");
1557 if (PyTuple_Size(tuple) != 2)
1559 eDebug("cutlist entries need to be a 2-tuple");
1562 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1563 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1565 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1568 pts_t pts = PyLong_AsLongLong(ppts);
1569 int type = PyInt_AsLong(ptype);
1570 m_cue_entries.insert(cueEntry(pts, type));
1571 eDebug("adding %08llx, %d", pts, type);
1573 m_cuesheet_changed = 1;
1575 cutlistToCuesheet();
1576 m_event((iPlayableService*)this, evCuesheetChanged);
1579 void eDVBServicePlay::setCutListEnable(int enable)
1581 m_cutlist_enabled = enable;
1582 cutlistToCuesheet();
1585 void eDVBServicePlay::updateTimeshiftPids()
1590 eDVBServicePMTHandler::program program;
1591 if (m_service_handler.getProgramInfo(program))
1595 std::set<int> pids_to_record;
1596 pids_to_record.insert(0); // PAT
1597 if (program.pmtPid != -1)
1598 pids_to_record.insert(program.pmtPid); // PMT
1600 if (program.textPid != -1)
1601 pids_to_record.insert(program.textPid); // Videotext
1603 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1604 i(program.videoStreams.begin());
1605 i != program.videoStreams.end(); ++i)
1606 pids_to_record.insert(i->pid);
1608 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1609 i(program.audioStreams.begin());
1610 i != program.audioStreams.end(); ++i)
1611 pids_to_record.insert(i->pid);
1613 std::set<int> new_pids, obsolete_pids;
1615 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1616 m_pids_active.begin(), m_pids_active.end(),
1617 std::inserter(new_pids, new_pids.begin()));
1619 std::set_difference(
1620 m_pids_active.begin(), m_pids_active.end(),
1621 pids_to_record.begin(), pids_to_record.end(),
1622 std::inserter(new_pids, new_pids.begin())
1625 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1626 m_record->addPID(*i);
1628 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1629 m_record->removePID(*i);
1633 void eDVBServicePlay::switchToLive()
1635 if (!m_timeshift_active)
1641 m_teletext_parser = 0;
1642 m_radiotext_parser = 0;
1643 m_subtitle_parser = 0;
1644 m_new_dvb_subtitle_region_connection = 0;
1645 m_new_subtitle_page_connection = 0;
1646 m_radiotext_updated_connection = 0;
1648 /* free the timeshift service handler, we need the resources */
1649 m_service_handler_timeshift.free();
1650 m_timeshift_active = 0;
1652 m_event((iPlayableService*)this, evSeekableStatusChanged);
1657 void eDVBServicePlay::switchToTimeshift()
1659 if (m_timeshift_active)
1664 m_teletext_parser = 0;
1665 m_radiotext_parser = 0;
1666 m_subtitle_parser = 0;
1667 m_new_subtitle_page_connection = 0;
1668 m_new_dvb_subtitle_region_connection = 0;
1669 m_radiotext_updated_connection = 0;
1671 m_timeshift_active = 1;
1673 m_event((iPlayableService*)this, evSeekableStatusChanged);
1675 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1676 r.path = m_timeshift_file;
1678 m_cue = new eCueSheet();
1679 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1680 updateDecoder(); /* mainly to switch off PCR */
1683 void eDVBServicePlay::updateDecoder()
1685 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1687 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1689 bool defaultac3=false;
1690 std::string default_ac3;
1692 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1693 defaultac3 = default_ac3 == "True";
1695 eDVBServicePMTHandler::program program;
1696 if (h.getProgramInfo(program))
1697 eDebug("getting program info failed.");
1700 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1701 if (!program.videoStreams.empty())
1703 eDebugNoNewLine(" (");
1704 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1705 i(program.videoStreams.begin());
1706 i != program.videoStreams.end(); ++i)
1713 if (i != program.videoStreams.begin())
1714 eDebugNoNewLine(", ");
1715 eDebugNoNewLine("%04x", i->pid);
1717 eDebugNoNewLine(")");
1719 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1720 if (!program.audioStreams.empty())
1722 eDebugNoNewLine(" (");
1723 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1724 i(program.audioStreams.begin());
1725 i != program.audioStreams.end(); ++i)
1727 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1729 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1735 if (i != program.audioStreams.begin())
1736 eDebugNoNewLine(", ");
1737 eDebugNoNewLine("%04x", i->pid);
1739 eDebugNoNewLine(")");
1741 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1742 pcrpid = program.pcrPid;
1743 eDebug(", and the text pid is %04x", program.textPid);
1744 tpid = program.textPid;
1749 h.getDecodeDemux(m_decode_demux);
1751 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1753 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1754 #ifdef INTERNAL_TELETEXT
1755 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1756 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1758 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1759 m_subtitle_parser->connectNewRegion(slot(*this, &eDVBServicePlay::newDVBSubtitleRegion), m_new_dvb_subtitle_region_connection);
1766 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1767 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1768 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1770 else // subservice or recording
1772 eServiceReferenceDVB ref;
1773 m_service_handler.getServiceReference(ref);
1774 eServiceReferenceDVB parent = ref.getParentServiceReference();
1779 ePtr<eDVBResourceManager> res_mgr;
1780 if (!eDVBResourceManager::getInstance(res_mgr))
1782 ePtr<iDVBChannelList> db;
1783 if (!res_mgr->getChannelList(db))
1785 ePtr<eDVBService> origService;
1786 if (!db->getService(parent, origService))
1788 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1789 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1795 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1796 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1798 m_decoder->setVideoPID(vpid, vpidtype);
1799 m_decoder->setAudioPID(apid, apidtype);
1800 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1802 m_decoder->setSyncPCR(pcrpid);
1805 ePtr<iDVBDemux> data_demux;
1806 if (!h.getDataDemux(data_demux))
1808 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1809 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1810 m_radiotext_parser->start(apid);
1815 m_decoder->setSyncPCR(-1);
1817 m_decoder->setTextPID(tpid);
1819 if (m_teletext_parser)
1820 m_teletext_parser->start(tpid);
1822 if (m_subtitle_parser && program.subtitleStreams.size() > 0)
1823 m_subtitle_parser->start(program.subtitleStreams[0].pid);
1826 m_decoder->setTrickmode(1);
1830 if (vpid > 0 && vpid < 0x2000)
1834 std::string radio_pic;
1835 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1836 m_decoder->setRadioPic(radio_pic);
1839 m_decoder->setAudioChannel(achannel);
1841 // how we can do this better?
1842 // update cache pid when the user changed the audio track or video track
1843 // TODO handling of difference audio types.. default audio types..
1845 /* don't worry about non-existing services, nor pvr services */
1846 if (m_dvb_service && !m_is_pvr)
1848 if (apidtype == eDVBAudio::aMPEG)
1850 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1851 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1855 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1856 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1858 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1859 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1860 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1861 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1864 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1867 void eDVBServicePlay::loadCuesheet()
1869 std::string filename = m_reference.path + ".cuts";
1871 m_cue_entries.clear();
1873 FILE *f = fopen(filename.c_str(), "rb");
1877 eDebug("loading cuts..");
1880 unsigned long long where;
1883 if (!fread(&where, sizeof(where), 1, f))
1885 if (!fread(&what, sizeof(what), 1, f))
1888 #if BYTE_ORDER == LITTLE_ENDIAN
1889 where = bswap_64(where);
1896 m_cue_entries.insert(cueEntry(where, what));
1899 eDebug("%d entries", m_cue_entries.size());
1901 eDebug("cutfile not found!");
1903 m_cuesheet_changed = 0;
1904 cutlistToCuesheet();
1905 m_event((iPlayableService*)this, evCuesheetChanged);
1908 void eDVBServicePlay::saveCuesheet()
1910 std::string filename = m_reference.path + ".cuts";
1912 FILE *f = fopen(filename.c_str(), "wb");
1916 unsigned long long where;
1919 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1921 #if BYTE_ORDER == BIG_ENDIAN
1924 where = bswap_64(i->where);
1926 what = htonl(i->what);
1927 fwrite(&where, sizeof(where), 1, f);
1928 fwrite(&what, sizeof(what), 1, f);
1934 m_cuesheet_changed = 0;
1937 void eDVBServicePlay::cutlistToCuesheet()
1941 eDebug("no cue sheet");
1946 if (!m_cutlist_enabled)
1948 m_cue->commitSpans();
1949 eDebug("cutlists were disabled");
1953 pts_t in = 0, out = 0, length = 0;
1957 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1961 if (i == m_cue_entries.end())
1964 if (i->what == 0) /* in */
1968 } else if (i->what == 1) /* out */
1970 else /* mark (2) or last play position (3) */
1978 m_cue->addSourceSpan(in, out);
1982 if (i == m_cue_entries.end())
1985 m_cue->commitSpans();
1988 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1990 if (m_subtitle_widget)
1991 disableSubtitles(parent);
1993 if (!m_teletext_parser)
1996 if (!PyInt_Check(entry))
1999 m_subtitle_widget = new eSubtitleWidget(parent);
2000 m_subtitle_widget->resize(parent->size()); /* full size */
2002 int page = PyInt_AsLong(entry);
2004 m_teletext_parser->setPage(page);
2009 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2011 delete m_subtitle_widget;
2012 m_subtitle_widget = 0;
2016 PyObject *eDVBServicePlay::getSubtitleList()
2018 if (!m_teletext_parser)
2024 PyObject *l = PyList_New(0);
2026 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2028 PyObject *tuple = PyTuple_New(2);
2030 sprintf(desc, "Page %x", *i);
2031 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2032 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2033 PyList_Append(l, tuple);
2039 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2041 if (m_subtitle_widget)
2043 m_subtitle_pages.push_back(page);
2045 checkSubtitleTiming();
2049 void eDVBServicePlay::checkSubtitleTiming()
2053 if (m_subtitle_pages.empty())
2056 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
2061 m_decoder->getPTS(0, pos);
2063 int diff = p.m_pts - pos;
2066 eDebug("[late (%d ms)]", -diff / 90);
2071 eDebug("[invalid]");
2077 m_subtitle_widget->setPage(p);
2078 m_subtitle_pages.pop_front();
2081 m_subtitle_sync_timer.start(diff / 90, 1);
2087 void eDVBServicePlay::newDVBSubtitleRegion(const eDVBSubtitleRegion &p)
2089 eDebug("new dvb subtitle region");
2092 void eDVBServicePlay::checkDvbSubtitleTiming()
2094 eDebug("check dvb subtitle timing");
2097 int eDVBServicePlay::getAC3Delay()
2100 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2102 return m_decoder->getAC3Delay();
2107 int eDVBServicePlay::getPCMDelay()
2110 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2112 return m_decoder->getPCMDelay();
2117 void eDVBServicePlay::setAC3Delay(int delay)
2120 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2122 m_decoder->setAC3Delay(delay);
2125 void eDVBServicePlay::setPCMDelay(int delay)
2128 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2130 m_decoder->setPCMDelay(delay);
2133 DEFINE_REF(eDVBServicePlay)
2135 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");