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 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1162 if (h.getProgramInfo(program))
1168 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1170 ePtr<eServiceEvent> evt;
1171 if (!m_event_handler.getEvent(evt, 0))
1173 ePtr<eComponentData> data;
1174 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1176 if ( data->getStreamContent() == 1 )
1178 switch(data->getComponentType())
1181 case 1: // 4:3 SD PAL
1183 case 3: // 16:9 SD PAL
1184 case 4: // > 16:9 PAL
1185 case 5: // 4:3 SD NTSC
1187 case 7: // 16:9 SD NTSC
1188 case 8: // > 16:9 NTSC
1191 case 9: // 4:3 HD PAL
1193 case 0xB: // 16:9 HD PAL
1194 case 0xC: // > 16:9 HD PAL
1195 case 0xD: // 4:3 HD NTSC
1197 case 0xF: // 16:9 HD NTSC
1198 case 0x10: // > 16:9 HD PAL
1199 return data->getComponentType();
1206 case sIsCrypted: return program.isCrypted();
1207 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1208 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1209 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1210 case sPCRPID: return program.pcrPid;
1211 case sPMTPID: return program.pmtPid;
1212 case sTXTPID: return program.textPid;
1213 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1214 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1215 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1216 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1217 case sProvider: if (!m_dvb_service) return -1; return -2;
1223 std::string eDVBServicePlay::getInfoString(int w)
1228 if (!m_dvb_service) return "";
1229 return m_dvb_service->m_provider_name;
1233 return iServiceInformation::getInfoString(w);
1236 PyObject *eDVBServicePlay::getInfoObject(int w)
1241 return m_service_handler.getCaIds();
1245 return iServiceInformation::getInfoObject(w);
1248 int eDVBServicePlay::getNumberOfTracks()
1250 eDVBServicePMTHandler::program program;
1251 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1252 if (h.getProgramInfo(program))
1254 return program.audioStreams.size();
1257 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1259 int ret = selectAudioStream(i);
1261 if (m_decoder->start())
1267 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1269 eDVBServicePMTHandler::program program;
1270 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1272 if (h.getProgramInfo(program))
1275 if (i >= program.audioStreams.size())
1278 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1279 info.m_description = "MPEG";
1280 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1281 info.m_description = "AC3";
1282 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1283 info.m_description = "AAC";
1284 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1285 info.m_description = "DTS";
1287 info.m_description = "???";
1289 if (program.audioStreams[i].component_tag != -1)
1291 ePtr<eServiceEvent> evt;
1292 if (!m_event_handler.getEvent(evt, 0))
1294 ePtr<eComponentData> data;
1295 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1296 info.m_language = data->getText();
1300 if (info.m_language.empty())
1301 info.m_language = program.audioStreams[i].language_code;
1306 int eDVBServicePlay::selectAudioStream(int i)
1308 eDVBServicePMTHandler::program program;
1309 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1311 if (h.getProgramInfo(program))
1314 if ((unsigned int)i >= program.audioStreams.size())
1320 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1323 if (m_radiotext_parser)
1324 m_radiotext_parser->start(program.audioStreams[i].pid);
1326 if (m_dvb_service && !m_is_pvr)
1328 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1330 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1331 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1335 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1336 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1343 int eDVBServicePlay::getCurrentChannel()
1345 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1348 RESULT eDVBServicePlay::selectChannel(int i)
1350 if (i < LEFT || i > RIGHT || i == STEREO)
1353 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1355 m_decoder->setAudioChannel(i);
1359 std::string eDVBServicePlay::getRadioText(int x)
1361 if (m_radiotext_parser)
1365 return m_radiotext_parser->getCurrentText();
1370 void eDVBServicePlay::radioTextUpdated()
1372 m_event((iPlayableService*)this, evUpdatedRadioText);
1375 int eDVBServiceBase::getFrontendInfo(int w)
1377 eUsePtr<iDVBChannel> channel;
1378 if(m_service_handler.getChannel(channel))
1380 ePtr<iDVBFrontend> fe;
1381 if(channel->getFrontend(fe))
1383 return fe->readFrontendData(w);
1386 PyObject *eDVBServiceBase::getFrontendData(bool original)
1390 eUsePtr<iDVBChannel> channel;
1391 if(!m_service_handler.getChannel(channel))
1393 ePtr<iDVBFrontend> fe;
1394 if(!channel->getFrontend(fe))
1396 ret = fe->readTransponderData(original);
1399 ePtr<iDVBFrontendParameters> feparm;
1400 channel->getCurrentFrontendParameters(feparm);
1403 eDVBFrontendParametersSatellite osat;
1404 if (!feparm->getDVBS(osat))
1406 void PutToDict(PyObject *, const char*, long);
1407 void PutToDict(PyObject *, const char*, const char*);
1408 PutToDict(ret, "orbital_position", osat.orbital_position);
1409 const char *tmp = "UNKNOWN";
1410 switch(osat.polarisation)
1412 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1413 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1414 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1415 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1418 PutToDict(ret, "polarization", tmp);
1432 int eDVBServicePlay::getNumberOfSubservices()
1434 ePtr<eServiceEvent> evt;
1435 if (!m_event_handler.getEvent(evt, 0))
1436 return evt->getNumOfLinkageServices();
1440 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1442 ePtr<eServiceEvent> evt;
1443 if (!m_event_handler.getEvent(evt, 0))
1445 if (!evt->getLinkageService(sub, m_reference, n))
1448 sub.type=eServiceReference::idInvalid;
1452 RESULT eDVBServicePlay::startTimeshift()
1454 ePtr<iDVBDemux> demux;
1456 eDebug("Start timeshift!");
1458 if (m_timeshift_enabled)
1461 /* start recording with the data demux. */
1462 if (m_service_handler.getDataDemux(demux))
1465 demux->createTSRecorder(m_record);
1469 char templ[]=TSPATH "/timeshift.XXXXXX";
1470 m_timeshift_fd = mkstemp(templ);
1471 m_timeshift_file = templ;
1473 eDebug("recording to %s", templ);
1475 if (m_timeshift_fd < 0)
1481 m_record->setTargetFD(m_timeshift_fd);
1483 m_timeshift_enabled = 1;
1485 updateTimeshiftPids();
1491 RESULT eDVBServicePlay::stopTimeshift()
1493 if (!m_timeshift_enabled)
1498 m_timeshift_enabled = 0;
1503 close(m_timeshift_fd);
1504 eDebug("remove timeshift file");
1505 remove(m_timeshift_file.c_str());
1510 int eDVBServicePlay::isTimeshiftActive()
1512 return m_timeshift_enabled && m_timeshift_active;
1515 RESULT eDVBServicePlay::activateTimeshift()
1517 if (!m_timeshift_enabled)
1520 if (!m_timeshift_active)
1522 switchToTimeshift();
1529 PyObject *eDVBServicePlay::getCutList()
1531 PyObject *list = PyList_New(0);
1533 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1535 PyObject *tuple = PyTuple_New(2);
1536 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1537 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1538 PyList_Append(list, tuple);
1545 void eDVBServicePlay::setCutList(PyObject *list)
1547 if (!PyList_Check(list))
1549 int size = PyList_Size(list);
1552 m_cue_entries.clear();
1554 for (i=0; i<size; ++i)
1556 PyObject *tuple = PyList_GetItem(list, i);
1557 if (!PyTuple_Check(tuple))
1559 eDebug("non-tuple in cutlist");
1562 if (PyTuple_Size(tuple) != 2)
1564 eDebug("cutlist entries need to be a 2-tuple");
1567 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1568 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1570 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1573 pts_t pts = PyLong_AsLongLong(ppts);
1574 int type = PyInt_AsLong(ptype);
1575 m_cue_entries.insert(cueEntry(pts, type));
1576 eDebug("adding %08llx, %d", pts, type);
1578 m_cuesheet_changed = 1;
1580 cutlistToCuesheet();
1581 m_event((iPlayableService*)this, evCuesheetChanged);
1584 void eDVBServicePlay::setCutListEnable(int enable)
1586 m_cutlist_enabled = enable;
1587 cutlistToCuesheet();
1590 void eDVBServicePlay::updateTimeshiftPids()
1595 eDVBServicePMTHandler::program program;
1596 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1598 if (h.getProgramInfo(program))
1602 std::set<int> pids_to_record;
1603 pids_to_record.insert(0); // PAT
1604 if (program.pmtPid != -1)
1605 pids_to_record.insert(program.pmtPid); // PMT
1607 if (program.textPid != -1)
1608 pids_to_record.insert(program.textPid); // Videotext
1610 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1611 i(program.videoStreams.begin());
1612 i != program.videoStreams.end(); ++i)
1613 pids_to_record.insert(i->pid);
1615 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1616 i(program.audioStreams.begin());
1617 i != program.audioStreams.end(); ++i)
1618 pids_to_record.insert(i->pid);
1620 std::set<int> new_pids, obsolete_pids;
1622 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1623 m_pids_active.begin(), m_pids_active.end(),
1624 std::inserter(new_pids, new_pids.begin()));
1626 std::set_difference(
1627 m_pids_active.begin(), m_pids_active.end(),
1628 pids_to_record.begin(), pids_to_record.end(),
1629 std::inserter(new_pids, new_pids.begin())
1632 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1633 m_record->addPID(*i);
1635 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1636 m_record->removePID(*i);
1640 void eDVBServicePlay::switchToLive()
1642 if (!m_timeshift_active)
1648 m_teletext_parser = 0;
1649 m_radiotext_parser = 0;
1650 m_subtitle_parser = 0;
1651 m_new_dvb_subtitle_region_connection = 0;
1652 m_new_subtitle_page_connection = 0;
1653 m_radiotext_updated_connection = 0;
1655 /* free the timeshift service handler, we need the resources */
1656 m_service_handler_timeshift.free();
1657 m_timeshift_active = 0;
1659 m_event((iPlayableService*)this, evSeekableStatusChanged);
1664 void eDVBServicePlay::switchToTimeshift()
1666 if (m_timeshift_active)
1671 m_teletext_parser = 0;
1672 m_radiotext_parser = 0;
1673 m_subtitle_parser = 0;
1674 m_new_subtitle_page_connection = 0;
1675 m_new_dvb_subtitle_region_connection = 0;
1676 m_radiotext_updated_connection = 0;
1678 m_timeshift_active = 1;
1680 m_event((iPlayableService*)this, evSeekableStatusChanged);
1682 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1683 r.path = m_timeshift_file;
1685 m_cue = new eCueSheet();
1686 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1687 updateDecoder(); /* mainly to switch off PCR */
1690 void eDVBServicePlay::updateDecoder()
1692 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1694 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1696 bool defaultac3=false;
1697 std::string default_ac3;
1699 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1700 defaultac3 = default_ac3 == "True";
1702 eDVBServicePMTHandler::program program;
1703 if (h.getProgramInfo(program))
1704 eDebug("getting program info failed.");
1707 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1708 if (!program.videoStreams.empty())
1710 eDebugNoNewLine(" (");
1711 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1712 i(program.videoStreams.begin());
1713 i != program.videoStreams.end(); ++i)
1720 if (i != program.videoStreams.begin())
1721 eDebugNoNewLine(", ");
1722 eDebugNoNewLine("%04x", i->pid);
1724 eDebugNoNewLine(")");
1726 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1727 if (!program.audioStreams.empty())
1729 eDebugNoNewLine(" (");
1730 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1731 i(program.audioStreams.begin());
1732 i != program.audioStreams.end(); ++i)
1734 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1736 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1742 if (i != program.audioStreams.begin())
1743 eDebugNoNewLine(", ");
1744 eDebugNoNewLine("%04x", i->pid);
1746 eDebugNoNewLine(")");
1748 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1749 pcrpid = program.pcrPid;
1750 eDebug(", and the text pid is %04x", program.textPid);
1751 tpid = program.textPid;
1756 h.getDecodeDemux(m_decode_demux);
1758 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1760 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1761 #ifdef INTERNAL_TELETEXT
1762 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1763 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1765 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1766 m_subtitle_parser->connectNewRegion(slot(*this, &eDVBServicePlay::newDVBSubtitleRegion), m_new_dvb_subtitle_region_connection);
1773 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1774 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1775 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1777 else // subservice or recording
1779 eServiceReferenceDVB ref;
1780 m_service_handler.getServiceReference(ref);
1781 eServiceReferenceDVB parent = ref.getParentServiceReference();
1786 ePtr<eDVBResourceManager> res_mgr;
1787 if (!eDVBResourceManager::getInstance(res_mgr))
1789 ePtr<iDVBChannelList> db;
1790 if (!res_mgr->getChannelList(db))
1792 ePtr<eDVBService> origService;
1793 if (!db->getService(parent, origService))
1795 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1796 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1802 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1803 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1805 m_decoder->setVideoPID(vpid, vpidtype);
1806 m_decoder->setAudioPID(apid, apidtype);
1807 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1809 m_decoder->setSyncPCR(pcrpid);
1812 ePtr<iDVBDemux> data_demux;
1813 if (!h.getDataDemux(data_demux))
1815 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1816 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1817 m_radiotext_parser->start(apid);
1822 m_decoder->setSyncPCR(-1);
1824 m_decoder->setTextPID(tpid);
1826 if (m_teletext_parser)
1827 m_teletext_parser->start(tpid);
1829 // if (m_subtitle_parser && program.subtitleStreams.size() > 0)
1830 // m_subtitle_parser->start(program.subtitleStreams[0].pid);
1833 m_decoder->setTrickmode(1);
1837 if (vpid > 0 && vpid < 0x2000)
1841 std::string radio_pic;
1842 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1843 m_decoder->setRadioPic(radio_pic);
1846 m_decoder->setAudioChannel(achannel);
1848 // how we can do this better?
1849 // update cache pid when the user changed the audio track or video track
1850 // TODO handling of difference audio types.. default audio types..
1852 /* don't worry about non-existing services, nor pvr services */
1853 if (m_dvb_service && !m_is_pvr)
1855 if (apidtype == eDVBAudio::aMPEG)
1857 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1858 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1862 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1863 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1865 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1866 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1867 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1868 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1871 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1874 void eDVBServicePlay::loadCuesheet()
1876 std::string filename = m_reference.path + ".cuts";
1878 m_cue_entries.clear();
1880 FILE *f = fopen(filename.c_str(), "rb");
1884 eDebug("loading cuts..");
1887 unsigned long long where;
1890 if (!fread(&where, sizeof(where), 1, f))
1892 if (!fread(&what, sizeof(what), 1, f))
1895 #if BYTE_ORDER == LITTLE_ENDIAN
1896 where = bswap_64(where);
1903 m_cue_entries.insert(cueEntry(where, what));
1906 eDebug("%d entries", m_cue_entries.size());
1908 eDebug("cutfile not found!");
1910 m_cuesheet_changed = 0;
1911 cutlistToCuesheet();
1912 m_event((iPlayableService*)this, evCuesheetChanged);
1915 void eDVBServicePlay::saveCuesheet()
1917 std::string filename = m_reference.path + ".cuts";
1919 FILE *f = fopen(filename.c_str(), "wb");
1923 unsigned long long where;
1926 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1928 #if BYTE_ORDER == BIG_ENDIAN
1931 where = bswap_64(i->where);
1933 what = htonl(i->what);
1934 fwrite(&where, sizeof(where), 1, f);
1935 fwrite(&what, sizeof(what), 1, f);
1941 m_cuesheet_changed = 0;
1944 void eDVBServicePlay::cutlistToCuesheet()
1948 eDebug("no cue sheet");
1953 if (!m_cutlist_enabled)
1955 m_cue->commitSpans();
1956 eDebug("cutlists were disabled");
1960 pts_t in = 0, out = 0, length = 0;
1964 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1968 if (i == m_cue_entries.end())
1971 if (i->what == 0) /* in */
1975 } else if (i->what == 1) /* out */
1977 else /* mark (2) or last play position (3) */
1985 m_cue->addSourceSpan(in, out);
1989 if (i == m_cue_entries.end())
1992 m_cue->commitSpans();
1995 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1997 if (m_subtitle_widget)
1998 disableSubtitles(parent);
2000 if (!m_teletext_parser)
2003 if (!PyInt_Check(entry))
2006 m_subtitle_widget = new eSubtitleWidget(parent);
2007 m_subtitle_widget->resize(parent->size()); /* full size */
2009 int page = PyInt_AsLong(entry);
2011 m_teletext_parser->setPage(page);
2016 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2018 delete m_subtitle_widget;
2019 m_subtitle_widget = 0;
2023 PyObject *eDVBServicePlay::getSubtitleList()
2025 if (!m_teletext_parser)
2031 PyObject *l = PyList_New(0);
2033 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2035 PyObject *tuple = PyTuple_New(2);
2037 sprintf(desc, "Page %x", *i);
2038 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2039 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2040 PyList_Append(l, tuple);
2046 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2048 if (m_subtitle_widget)
2050 m_subtitle_pages.push_back(page);
2052 checkSubtitleTiming();
2056 void eDVBServicePlay::checkSubtitleTiming()
2060 if (m_subtitle_pages.empty())
2063 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
2068 m_decoder->getPTS(0, pos);
2070 int diff = p.m_pts - pos;
2073 eDebug("[late (%d ms)]", -diff / 90);
2078 eDebug("[invalid]");
2084 m_subtitle_widget->setPage(p);
2085 m_subtitle_pages.pop_front();
2088 m_subtitle_sync_timer.start(diff / 90, 1);
2094 void eDVBServicePlay::newDVBSubtitleRegion(const eDVBSubtitleRegion &p)
2096 eDebug("new dvb subtitle region");
2099 void eDVBServicePlay::checkDvbSubtitleTiming()
2101 eDebug("check dvb subtitle timing");
2104 int eDVBServicePlay::getAC3Delay()
2107 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2109 return m_decoder->getAC3Delay();
2114 int eDVBServicePlay::getPCMDelay()
2117 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2119 return m_decoder->getPCMDelay();
2124 void eDVBServicePlay::setAC3Delay(int delay)
2127 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2129 m_decoder->setAC3Delay(delay);
2132 void eDVBServicePlay::setPCMDelay(int delay)
2135 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2137 m_decoder->setPCMDelay(delay);
2140 DEFINE_REF(eDVBServicePlay)
2142 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");