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_new_subtitle_page_connection = 0;
1644 m_radiotext_updated_connection = 0;
1646 /* free the timeshift service handler, we need the resources */
1647 m_service_handler_timeshift.free();
1648 m_timeshift_active = 0;
1650 m_event((iPlayableService*)this, evSeekableStatusChanged);
1655 void eDVBServicePlay::switchToTimeshift()
1657 if (m_timeshift_active)
1662 m_teletext_parser = 0;
1663 m_radiotext_parser = 0;
1664 m_new_subtitle_page_connection = 0;
1665 m_radiotext_updated_connection = 0;
1667 m_timeshift_active = 1;
1669 m_event((iPlayableService*)this, evSeekableStatusChanged);
1671 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1672 r.path = m_timeshift_file;
1674 m_cue = new eCueSheet();
1675 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1676 updateDecoder(); /* mainly to switch off PCR */
1679 void eDVBServicePlay::updateDecoder()
1681 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1683 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1685 bool defaultac3=false;
1686 std::string default_ac3;
1688 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1689 defaultac3 = default_ac3 == "enable";
1691 eDVBServicePMTHandler::program program;
1692 if (h.getProgramInfo(program))
1693 eDebug("getting program info failed.");
1696 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1697 if (!program.videoStreams.empty())
1699 eDebugNoNewLine(" (");
1700 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1701 i(program.videoStreams.begin());
1702 i != program.videoStreams.end(); ++i)
1709 if (i != program.videoStreams.begin())
1710 eDebugNoNewLine(", ");
1711 eDebugNoNewLine("%04x", i->pid);
1713 eDebugNoNewLine(")");
1715 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1716 if (!program.audioStreams.empty())
1718 eDebugNoNewLine(" (");
1719 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1720 i(program.audioStreams.begin());
1721 i != program.audioStreams.end(); ++i)
1723 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1725 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1731 if (i != program.audioStreams.begin())
1732 eDebugNoNewLine(", ");
1733 eDebugNoNewLine("%04x", i->pid);
1735 eDebugNoNewLine(")");
1737 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1738 pcrpid = program.pcrPid;
1739 eDebug(", and the text pid is %04x", program.textPid);
1740 tpid = program.textPid;
1745 h.getDecodeDemux(m_decode_demux);
1747 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1749 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1750 #ifdef INTERNAL_TELETEXT
1751 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1752 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1760 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1761 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1762 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1764 else // subservice or recording
1766 eServiceReferenceDVB ref;
1767 m_service_handler.getServiceReference(ref);
1768 eServiceReferenceDVB parent = ref.getParentServiceReference();
1773 ePtr<eDVBResourceManager> res_mgr;
1774 if (!eDVBResourceManager::getInstance(res_mgr))
1776 ePtr<iDVBChannelList> db;
1777 if (!res_mgr->getChannelList(db))
1779 ePtr<eDVBService> origService;
1780 if (!db->getService(parent, origService))
1782 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1783 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1789 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1790 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1792 m_decoder->setVideoPID(vpid, vpidtype);
1793 m_decoder->setAudioPID(apid, apidtype);
1794 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1796 m_decoder->setSyncPCR(pcrpid);
1799 ePtr<iDVBDemux> data_demux;
1800 if (!h.getDataDemux(data_demux))
1802 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1803 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1804 m_radiotext_parser->start(apid);
1809 m_decoder->setSyncPCR(-1);
1811 m_decoder->setTextPID(tpid);
1813 if (m_teletext_parser)
1814 m_teletext_parser->start(tpid);
1817 m_decoder->setTrickmode(1);
1821 if (vpid > 0 && vpid < 0x2000)
1825 std::string radio_pic;
1826 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1827 m_decoder->setRadioPic(radio_pic);
1830 m_decoder->setAudioChannel(achannel);
1832 // how we can do this better?
1833 // update cache pid when the user changed the audio track or video track
1834 // TODO handling of difference audio types.. default audio types..
1836 /* don't worry about non-existing services, nor pvr services */
1837 if (m_dvb_service && !m_is_pvr)
1839 if (apidtype == eDVBAudio::aMPEG)
1841 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1842 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1846 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1847 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1849 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1850 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1851 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1852 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1855 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1858 void eDVBServicePlay::loadCuesheet()
1860 std::string filename = m_reference.path + ".cuts";
1862 m_cue_entries.clear();
1864 FILE *f = fopen(filename.c_str(), "rb");
1868 eDebug("loading cuts..");
1871 unsigned long long where;
1874 if (!fread(&where, sizeof(where), 1, f))
1876 if (!fread(&what, sizeof(what), 1, f))
1879 #if BYTE_ORDER == LITTLE_ENDIAN
1880 where = bswap_64(where);
1887 m_cue_entries.insert(cueEntry(where, what));
1890 eDebug("%d entries", m_cue_entries.size());
1892 eDebug("cutfile not found!");
1894 m_cuesheet_changed = 0;
1895 cutlistToCuesheet();
1896 m_event((iPlayableService*)this, evCuesheetChanged);
1899 void eDVBServicePlay::saveCuesheet()
1901 std::string filename = m_reference.path + ".cuts";
1903 FILE *f = fopen(filename.c_str(), "wb");
1907 unsigned long long where;
1910 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1912 #if BYTE_ORDER == BIG_ENDIAN
1915 where = bswap_64(i->where);
1917 what = htonl(i->what);
1918 fwrite(&where, sizeof(where), 1, f);
1919 fwrite(&what, sizeof(what), 1, f);
1925 m_cuesheet_changed = 0;
1928 void eDVBServicePlay::cutlistToCuesheet()
1932 eDebug("no cue sheet");
1937 if (!m_cutlist_enabled)
1939 m_cue->commitSpans();
1940 eDebug("cutlists were disabled");
1944 pts_t in = 0, out = 0, length = 0;
1948 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1952 if (i == m_cue_entries.end())
1955 if (i->what == 0) /* in */
1959 } else if (i->what == 1) /* out */
1961 else /* mark (2) or last play position (3) */
1969 m_cue->addSourceSpan(in, out);
1973 if (i == m_cue_entries.end())
1976 m_cue->commitSpans();
1979 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1981 if (m_subtitle_widget)
1982 disableSubtitles(parent);
1984 if (!m_teletext_parser)
1987 if (!PyInt_Check(entry))
1990 m_subtitle_widget = new eSubtitleWidget(parent);
1991 m_subtitle_widget->resize(parent->size()); /* full size */
1993 int page = PyInt_AsLong(entry);
1995 m_teletext_parser->setPage(page);
2000 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2002 delete m_subtitle_widget;
2003 m_subtitle_widget = 0;
2007 PyObject *eDVBServicePlay::getSubtitleList()
2009 if (!m_teletext_parser)
2015 PyObject *l = PyList_New(0);
2017 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2019 PyObject *tuple = PyTuple_New(2);
2021 sprintf(desc, "Page %x", *i);
2022 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2023 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2024 PyList_Append(l, tuple);
2030 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2032 if (m_subtitle_widget)
2034 m_subtitle_pages.push_back(page);
2036 checkSubtitleTiming();
2040 void eDVBServicePlay::checkSubtitleTiming()
2044 if (m_subtitle_pages.empty())
2047 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
2052 m_decoder->getPTS(0, pos);
2054 int diff = p.m_pts - pos;
2057 eDebug("[late (%d ms)]", -diff / 90);
2062 eDebug("[invalid]");
2068 m_subtitle_widget->setPage(p);
2069 m_subtitle_pages.pop_front();
2072 m_subtitle_sync_timer.start(diff / 90, 1);
2078 int eDVBServicePlay::getAC3Delay()
2081 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2083 return m_decoder->getAC3Delay();
2088 int eDVBServicePlay::getPCMDelay()
2091 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2093 return m_decoder->getPCMDelay();
2098 void eDVBServicePlay::setAC3Delay(int delay)
2101 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2103 m_decoder->setAC3Delay(delay);
2106 void eDVBServicePlay::setPCMDelay(int delay)
2109 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2111 m_decoder->setPCMDelay(delay);
2114 DEFINE_REF(eDVBServicePlay)
2116 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");