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);
1340 h.resetCachedProgram();
1345 int eDVBServicePlay::getCurrentChannel()
1347 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1350 RESULT eDVBServicePlay::selectChannel(int i)
1352 if (i < LEFT || i > RIGHT || i == STEREO)
1355 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1357 m_decoder->setAudioChannel(i);
1361 std::string eDVBServicePlay::getRadioText(int x)
1363 if (m_radiotext_parser)
1367 return m_radiotext_parser->getCurrentText();
1372 void eDVBServicePlay::radioTextUpdated()
1374 m_event((iPlayableService*)this, evUpdatedRadioText);
1377 int eDVBServiceBase::getFrontendInfo(int w)
1379 eUsePtr<iDVBChannel> channel;
1380 if(m_service_handler.getChannel(channel))
1382 ePtr<iDVBFrontend> fe;
1383 if(channel->getFrontend(fe))
1385 return fe->readFrontendData(w);
1388 PyObject *eDVBServiceBase::getFrontendData(bool original)
1392 eUsePtr<iDVBChannel> channel;
1393 if(!m_service_handler.getChannel(channel))
1395 ePtr<iDVBFrontend> fe;
1396 if(!channel->getFrontend(fe))
1398 ret = fe->readTransponderData(original);
1401 ePtr<iDVBFrontendParameters> feparm;
1402 channel->getCurrentFrontendParameters(feparm);
1405 eDVBFrontendParametersSatellite osat;
1406 if (!feparm->getDVBS(osat))
1408 void PutToDict(PyObject *, const char*, long);
1409 void PutToDict(PyObject *, const char*, const char*);
1410 PutToDict(ret, "orbital_position", osat.orbital_position);
1411 const char *tmp = "UNKNOWN";
1412 switch(osat.polarisation)
1414 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1415 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1416 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1417 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1420 PutToDict(ret, "polarization", tmp);
1434 int eDVBServicePlay::getNumberOfSubservices()
1436 ePtr<eServiceEvent> evt;
1437 if (!m_event_handler.getEvent(evt, 0))
1438 return evt->getNumOfLinkageServices();
1442 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1444 ePtr<eServiceEvent> evt;
1445 if (!m_event_handler.getEvent(evt, 0))
1447 if (!evt->getLinkageService(sub, m_reference, n))
1450 sub.type=eServiceReference::idInvalid;
1454 RESULT eDVBServicePlay::startTimeshift()
1456 ePtr<iDVBDemux> demux;
1458 eDebug("Start timeshift!");
1460 if (m_timeshift_enabled)
1463 /* start recording with the data demux. */
1464 if (m_service_handler.getDataDemux(demux))
1467 demux->createTSRecorder(m_record);
1471 char templ[]=TSPATH "/timeshift.XXXXXX";
1472 m_timeshift_fd = mkstemp(templ);
1473 m_timeshift_file = templ;
1475 eDebug("recording to %s", templ);
1477 if (m_timeshift_fd < 0)
1483 m_record->setTargetFD(m_timeshift_fd);
1485 m_timeshift_enabled = 1;
1487 updateTimeshiftPids();
1493 RESULT eDVBServicePlay::stopTimeshift()
1495 if (!m_timeshift_enabled)
1500 m_timeshift_enabled = 0;
1505 close(m_timeshift_fd);
1506 eDebug("remove timeshift file");
1507 remove(m_timeshift_file.c_str());
1512 int eDVBServicePlay::isTimeshiftActive()
1514 return m_timeshift_enabled && m_timeshift_active;
1517 RESULT eDVBServicePlay::activateTimeshift()
1519 if (!m_timeshift_enabled)
1522 if (!m_timeshift_active)
1524 switchToTimeshift();
1531 PyObject *eDVBServicePlay::getCutList()
1533 PyObject *list = PyList_New(0);
1535 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1537 PyObject *tuple = PyTuple_New(2);
1538 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1539 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1540 PyList_Append(list, tuple);
1547 void eDVBServicePlay::setCutList(PyObject *list)
1549 if (!PyList_Check(list))
1551 int size = PyList_Size(list);
1554 m_cue_entries.clear();
1556 for (i=0; i<size; ++i)
1558 PyObject *tuple = PyList_GetItem(list, i);
1559 if (!PyTuple_Check(tuple))
1561 eDebug("non-tuple in cutlist");
1564 if (PyTuple_Size(tuple) != 2)
1566 eDebug("cutlist entries need to be a 2-tuple");
1569 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1570 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1572 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1575 pts_t pts = PyLong_AsLongLong(ppts);
1576 int type = PyInt_AsLong(ptype);
1577 m_cue_entries.insert(cueEntry(pts, type));
1578 eDebug("adding %08llx, %d", pts, type);
1580 m_cuesheet_changed = 1;
1582 cutlistToCuesheet();
1583 m_event((iPlayableService*)this, evCuesheetChanged);
1586 void eDVBServicePlay::setCutListEnable(int enable)
1588 m_cutlist_enabled = enable;
1589 cutlistToCuesheet();
1592 void eDVBServicePlay::updateTimeshiftPids()
1597 eDVBServicePMTHandler::program program;
1598 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1600 if (h.getProgramInfo(program))
1604 std::set<int> pids_to_record;
1605 pids_to_record.insert(0); // PAT
1606 if (program.pmtPid != -1)
1607 pids_to_record.insert(program.pmtPid); // PMT
1609 if (program.textPid != -1)
1610 pids_to_record.insert(program.textPid); // Videotext
1612 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1613 i(program.videoStreams.begin());
1614 i != program.videoStreams.end(); ++i)
1615 pids_to_record.insert(i->pid);
1617 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1618 i(program.audioStreams.begin());
1619 i != program.audioStreams.end(); ++i)
1620 pids_to_record.insert(i->pid);
1622 std::set<int> new_pids, obsolete_pids;
1624 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1625 m_pids_active.begin(), m_pids_active.end(),
1626 std::inserter(new_pids, new_pids.begin()));
1628 std::set_difference(
1629 m_pids_active.begin(), m_pids_active.end(),
1630 pids_to_record.begin(), pids_to_record.end(),
1631 std::inserter(new_pids, new_pids.begin())
1634 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1635 m_record->addPID(*i);
1637 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1638 m_record->removePID(*i);
1642 void eDVBServicePlay::switchToLive()
1644 if (!m_timeshift_active)
1650 m_teletext_parser = 0;
1651 m_radiotext_parser = 0;
1652 m_subtitle_parser = 0;
1653 m_new_dvb_subtitle_page_connection = 0;
1654 m_new_subtitle_page_connection = 0;
1655 m_radiotext_updated_connection = 0;
1657 /* free the timeshift service handler, we need the resources */
1658 m_service_handler_timeshift.free();
1659 m_timeshift_active = 0;
1661 m_event((iPlayableService*)this, evSeekableStatusChanged);
1666 void eDVBServicePlay::switchToTimeshift()
1668 if (m_timeshift_active)
1673 m_teletext_parser = 0;
1674 m_radiotext_parser = 0;
1675 m_subtitle_parser = 0;
1676 m_new_subtitle_page_connection = 0;
1677 m_new_dvb_subtitle_page_connection = 0;
1678 m_radiotext_updated_connection = 0;
1680 m_timeshift_active = 1;
1682 m_event((iPlayableService*)this, evSeekableStatusChanged);
1684 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1685 r.path = m_timeshift_file;
1687 m_cue = new eCueSheet();
1688 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1689 updateDecoder(); /* mainly to switch off PCR */
1692 void eDVBServicePlay::updateDecoder()
1694 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1696 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1698 bool defaultac3=false;
1699 std::string default_ac3;
1701 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1702 defaultac3 = default_ac3 == "True";
1704 eDVBServicePMTHandler::program program;
1705 if (h.getProgramInfo(program))
1706 eDebug("getting program info failed.");
1709 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1710 if (!program.videoStreams.empty())
1712 eDebugNoNewLine(" (");
1713 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1714 i(program.videoStreams.begin());
1715 i != program.videoStreams.end(); ++i)
1722 if (i != program.videoStreams.begin())
1723 eDebugNoNewLine(", ");
1724 eDebugNoNewLine("%04x", i->pid);
1726 eDebugNoNewLine(")");
1728 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1729 if (!program.audioStreams.empty())
1731 eDebugNoNewLine(" (");
1732 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1733 i(program.audioStreams.begin());
1734 i != program.audioStreams.end(); ++i)
1736 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1738 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1744 if (i != program.audioStreams.begin())
1745 eDebugNoNewLine(", ");
1746 eDebugNoNewLine("%04x", i->pid);
1748 eDebugNoNewLine(")");
1750 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1751 pcrpid = program.pcrPid;
1752 eDebug(", and the text pid is %04x", program.textPid);
1753 tpid = program.textPid;
1758 h.getDecodeDemux(m_decode_demux);
1760 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1762 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1763 #ifdef INTERNAL_TELETEXT
1764 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1765 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1767 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1768 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1775 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1776 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1777 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1779 else // subservice or recording
1781 eServiceReferenceDVB ref;
1782 m_service_handler.getServiceReference(ref);
1783 eServiceReferenceDVB parent = ref.getParentServiceReference();
1788 ePtr<eDVBResourceManager> res_mgr;
1789 if (!eDVBResourceManager::getInstance(res_mgr))
1791 ePtr<iDVBChannelList> db;
1792 if (!res_mgr->getChannelList(db))
1794 ePtr<eDVBService> origService;
1795 if (!db->getService(parent, origService))
1797 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1798 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1804 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1805 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1807 m_decoder->setVideoPID(vpid, vpidtype);
1808 m_decoder->setAudioPID(apid, apidtype);
1809 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1811 m_decoder->setSyncPCR(pcrpid);
1814 ePtr<iDVBDemux> data_demux;
1815 if (!h.getDataDemux(data_demux))
1817 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1818 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1819 m_radiotext_parser->start(apid);
1824 m_decoder->setSyncPCR(-1);
1826 m_decoder->setTextPID(tpid);
1828 m_teletext_parser->start(program.textPid);
1831 m_decoder->setTrickmode(1);
1835 if (vpid > 0 && vpid < 0x2000)
1839 std::string radio_pic;
1840 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1841 m_decoder->setRadioPic(radio_pic);
1844 m_decoder->setAudioChannel(achannel);
1846 // how we can do this better?
1847 // update cache pid when the user changed the audio track or video track
1848 // TODO handling of difference audio types.. default audio types..
1850 /* don't worry about non-existing services, nor pvr services */
1851 if (m_dvb_service && !m_is_pvr)
1853 if (apidtype == eDVBAudio::aMPEG)
1855 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1856 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1860 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1861 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1863 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1864 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1865 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1866 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1869 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1872 void eDVBServicePlay::loadCuesheet()
1874 std::string filename = m_reference.path + ".cuts";
1876 m_cue_entries.clear();
1878 FILE *f = fopen(filename.c_str(), "rb");
1882 eDebug("loading cuts..");
1885 unsigned long long where;
1888 if (!fread(&where, sizeof(where), 1, f))
1890 if (!fread(&what, sizeof(what), 1, f))
1893 #if BYTE_ORDER == LITTLE_ENDIAN
1894 where = bswap_64(where);
1901 m_cue_entries.insert(cueEntry(where, what));
1904 eDebug("%d entries", m_cue_entries.size());
1906 eDebug("cutfile not found!");
1908 m_cuesheet_changed = 0;
1909 cutlistToCuesheet();
1910 m_event((iPlayableService*)this, evCuesheetChanged);
1913 void eDVBServicePlay::saveCuesheet()
1915 std::string filename = m_reference.path + ".cuts";
1917 FILE *f = fopen(filename.c_str(), "wb");
1921 unsigned long long where;
1924 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1926 #if BYTE_ORDER == BIG_ENDIAN
1929 where = bswap_64(i->where);
1931 what = htonl(i->what);
1932 fwrite(&where, sizeof(where), 1, f);
1933 fwrite(&what, sizeof(what), 1, f);
1939 m_cuesheet_changed = 0;
1942 void eDVBServicePlay::cutlistToCuesheet()
1946 eDebug("no cue sheet");
1951 if (!m_cutlist_enabled)
1953 m_cue->commitSpans();
1954 eDebug("cutlists were disabled");
1958 pts_t in = 0, out = 0, length = 0;
1962 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1966 if (i == m_cue_entries.end())
1969 if (i->what == 0) /* in */
1973 } else if (i->what == 1) /* out */
1975 else /* mark (2) or last play position (3) */
1983 m_cue->addSourceSpan(in, out);
1987 if (i == m_cue_entries.end())
1990 m_cue->commitSpans();
1993 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1995 if (m_subtitle_widget)
1996 disableSubtitles(parent);
1998 if (!PyInt_Check(entry))
2001 int page = PyInt_AsLong(entry);
2003 if (page > 0 && !m_teletext_parser)
2005 if (page < 0 && !m_subtitle_parser)
2008 m_subtitle_widget = new eSubtitleWidget(parent);
2009 m_subtitle_widget->resize(parent->size()); /* full size */
2013 /* eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2014 eDVBServicePMTHandler::program program;
2015 if (h.getProgramInfo(program))
2016 eDebug("getting program info failed.");
2019 eDebug("start teletext on pid %04x, page %d", program.textPid, page);
2020 m_teletext_parser->start(program.textPid);*/
2021 m_teletext_parser->setPage(page);
2027 m_subtitle_parser->start(pid);
2033 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2035 delete m_subtitle_widget;
2036 m_subtitle_widget = 0;
2037 if (m_subtitle_parser)
2039 m_subtitle_parser->stop();
2040 m_dvb_subtitle_pages.clear();
2042 if (m_teletext_parser)
2044 m_teletext_parser->setPage(-1);
2045 m_subtitle_pages.clear();
2050 PyObject *eDVBServicePlay::getSubtitleList()
2052 if (!m_teletext_parser)
2058 PyObject *l = PyList_New(0);
2060 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2062 PyObject *tuple = PyTuple_New(2);
2064 sprintf(desc, "Page %x", *i);
2065 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2066 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2067 PyList_Append(l, tuple);
2071 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2072 eDVBServicePMTHandler::program program;
2073 if (h.getProgramInfo(program))
2074 eDebug("getting program info failed.");
2077 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2078 it != program.subtitleStreams.end(); ++it)
2080 PyObject *tuple = PyTuple_New(2);
2082 sprintf(desc, "DVB %s", it->language_code.c_str());
2083 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2084 PyTuple_SetItem(tuple, 1, PyInt_FromLong(-it->pid));
2085 PyList_Append(l, tuple);
2093 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2095 if (m_subtitle_widget)
2097 m_subtitle_pages.push_back(page);
2098 checkSubtitleTiming();
2102 void eDVBServicePlay::checkSubtitleTiming()
2104 // eDebug("checkSubtitleTiming");
2105 if (!m_subtitle_widget)
2109 enum { TELETEXT, DVB } type;
2110 eDVBTeletextSubtitlePage page;
2111 eDVBSubtitlePage dvb_page;
2113 if (!m_subtitle_pages.empty())
2115 page = m_subtitle_pages.front();
2117 show_time = page.m_pts;
2119 else if (!m_dvb_subtitle_pages.empty())
2121 dvb_page = m_dvb_subtitle_pages.front();
2123 show_time = dvb_page.m_show_time;
2131 m_decoder->getPTS(0, pos);
2133 // eDebug("%lld %lld", pos, show_time);
2134 int diff = show_time - pos;
2137 eDebug("[late (%d ms)]", -diff / 90);
2142 eDebug("[invalid]");
2148 if (type == TELETEXT)
2150 eDebug("display teletext subtitle page");
2151 m_subtitle_widget->setPage(page);
2152 m_subtitle_pages.pop_front();
2156 eDebug("display dvb subtitle Page");
2157 m_subtitle_widget->setPage(dvb_page);
2158 m_dvb_subtitle_pages.pop_front();
2162 eDebug("start subtitle delay %d", diff / 90);
2163 m_subtitle_sync_timer.start(diff / 90, 1);
2169 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2171 if (m_subtitle_widget)
2173 m_dvb_subtitle_pages.push_back(p);
2174 checkSubtitleTiming();
2178 int eDVBServicePlay::getAC3Delay()
2181 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2183 return m_decoder->getAC3Delay();
2188 int eDVBServicePlay::getPCMDelay()
2191 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2193 return m_decoder->getPCMDelay();
2198 void eDVBServicePlay::setAC3Delay(int delay)
2201 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2203 m_decoder->setAC3Delay(delay);
2206 void eDVBServicePlay::setPCMDelay(int delay)
2209 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2211 m_decoder->setPCMDelay(delay);
2214 DEFINE_REF(eDVBServicePlay)
2216 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");