1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
22 #include <lib/gui/esubtitle.h>
28 #include <netinet/in.h>
30 #define INTERNAL_TELETEXT
33 #error no byte order defined!
36 #define TSPATH "/media/hdd"
38 class eStaticServiceDVBInformation: public iStaticServiceInformation
40 DECLARE_REF(eStaticServiceDVBInformation);
42 RESULT getName(const eServiceReference &ref, std::string &name);
43 int getLength(const eServiceReference &ref);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
97 DECLARE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT getName(const eServiceReference &ref, std::string &name);
100 int getLength(const eServiceReference &ref);
103 DEFINE_REF(eStaticServiceDVBBouquetInformation);
105 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
107 ePtr<iDVBChannelList> db;
108 ePtr<eDVBResourceManager> res;
111 if ((err = eDVBResourceManager::getInstance(res)) != 0)
113 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
116 if ((err = res->getChannelList(db)) != 0)
118 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
123 if ((err = db->getBouquet(ref, bouquet)) != 0)
125 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
129 if ( bouquet && bouquet->m_bouquet_name.length() )
131 name = bouquet->m_bouquet_name;
138 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
143 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
145 DECLARE_REF(eStaticServiceDVBPVRInformation);
146 eServiceReference m_ref;
147 eDVBMetaParser m_parser;
149 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
150 RESULT getName(const eServiceReference &ref, std::string &name);
151 int getLength(const eServiceReference &ref);
152 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
154 int getInfo(const eServiceReference &ref, int w);
155 std::string getInfoString(const eServiceReference &ref,int w);
158 DEFINE_REF(eStaticServiceDVBPVRInformation);
160 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
163 m_parser.parseFile(ref.path);
166 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
168 ASSERT(ref == m_ref);
169 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
173 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
175 ASSERT(ref == m_ref);
179 if (tstools.openFile(ref.path.c_str()))
183 if (tstools.calcLen(len))
189 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
193 case iServiceInformation::sDescription:
194 return iServiceInformation::resIsString;
195 case iServiceInformation::sServiceref:
196 return iServiceInformation::resIsString;
197 case iServiceInformation::sTimeCreate:
198 if (m_parser.m_time_create)
199 return m_parser.m_time_create;
201 return iServiceInformation::resNA;
203 return iServiceInformation::resNA;
207 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
211 case iServiceInformation::sDescription:
212 return m_parser.m_description;
213 case iServiceInformation::sServiceref:
214 return m_parser.m_ref.toString();
215 case iServiceInformation::sTags:
216 return m_parser.m_tags;
222 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
224 if (!ref.path.empty())
226 ePtr<eServiceEvent> event = new eServiceEvent;
227 std::string filename = ref.path;
228 filename.erase(filename.length()-2, 2);
230 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
240 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
242 DECLARE_REF(eDVBPVRServiceOfflineOperations);
243 eServiceReferenceDVB m_ref;
245 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
247 RESULT deleteFromDisk(int simulate);
248 RESULT getListOfFilenames(std::list<std::string> &);
251 DEFINE_REF(eDVBPVRServiceOfflineOperations);
253 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
257 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
263 std::list<std::string> res;
264 if (getListOfFilenames(res))
267 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
269 eDebug("FATAL !! can't get background file eraser");
271 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
273 eDebug("Removing %s...", i->c_str());
275 eraser->erase(i->c_str());
277 ::unlink(i->c_str());
284 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
287 res.push_back(m_ref.path);
289 // handling for old splitted recordings (enigma 1)
294 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
296 if (stat(buf, &s) < 0)
301 res.push_back(m_ref.path + ".meta");
302 res.push_back(m_ref.path + ".ap");
303 res.push_back(m_ref.path + ".cuts");
304 std::string tmp = m_ref.path;
305 tmp.erase(m_ref.path.length()-3);
306 res.push_back(tmp + ".eit");
310 DEFINE_REF(eServiceFactoryDVB)
312 eServiceFactoryDVB::eServiceFactoryDVB()
314 ePtr<eServiceCenter> sc;
316 eServiceCenter::getPrivInstance(sc);
318 sc->addServiceFactory(eServiceFactoryDVB::id, this);
320 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
321 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
324 eServiceFactoryDVB::~eServiceFactoryDVB()
326 ePtr<eServiceCenter> sc;
328 eServiceCenter::getPrivInstance(sc);
330 sc->removeServiceFactory(eServiceFactoryDVB::id);
333 DEFINE_REF(eDVBServiceList);
335 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
339 eDVBServiceList::~eDVBServiceList()
343 RESULT eDVBServiceList::startQuery()
345 ePtr<iDVBChannelList> db;
346 ePtr<eDVBResourceManager> res;
349 if ((err = eDVBResourceManager::getInstance(res)) != 0)
351 eDebug("no resource manager");
354 if ((err = res->getChannelList(db)) != 0)
356 eDebug("no channel list");
360 ePtr<eDVBChannelQuery> q;
362 if (!m_parent.path.empty())
364 eDVBChannelQuery::compile(q, m_parent.path);
367 eDebug("compile query failed");
372 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
374 eDebug("startQuery failed");
381 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
383 eServiceReferenceDVB ref;
388 while (!m_query->getNextResult(ref))
392 list.sort(iListableServiceCompare(this));
397 // The first argument of this function is a format string to specify the order and
398 // the content of the returned list
399 // useable format options are
400 // R = Service Reference (as swig object .. this is very slow)
401 // S = Service Reference (as python string object .. same as ref.toString())
402 // C = Service Reference (as python string object .. same as ref.toCompareString())
403 // N = Service Name (as python string object)
404 // when exactly one return value per service is selected in the format string,
405 // then each value is directly a list entry
406 // when more than one value is returned per service, then the list is a list of
408 // unknown format string chars are returned as python None values !
409 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
412 std::list<eServiceReference> tmplist;
415 if (!format || !(retcount=strlen(format)))
416 format = "R"; // just return service reference swig object ...
418 if (!getContent(tmplist, sorted))
420 int services=tmplist.size();
421 ePtr<iStaticServiceInformation> sptr;
422 eServiceCenterPtr service_center;
424 if (strchr(format, 'N'))
425 eServiceCenter::getPrivInstance(service_center);
427 ret = PyList_New(services);
428 std::list<eServiceReference>::iterator it(tmplist.begin());
430 for (int cnt=0; cnt < services; ++cnt)
432 eServiceReference &ref=*it++;
433 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
434 for (int i=0; i < retcount; ++i)
439 case 'R': // service reference (swig)object
440 tmp = New_eServiceReference(ref);
442 case 'C': // service reference compare string
443 tmp = PyString_FromString(ref.toCompareString().c_str());
445 case 'S': // service reference string
446 tmp = PyString_FromString(ref.toString().c_str());
448 case 'N': // service name
451 service_center->info(ref, sptr);
455 sptr->getName(ref, name);
457 tmp = PyString_FromString(name.c_str());
461 tmp = PyString_FromString("<n/a>");
474 PyTuple_SET_ITEM(tuple, i, tmp);
476 PyList_SET_ITEM(ret, cnt, tmp);
480 PyList_SET_ITEM(ret, cnt, tuple);
483 return ret ? ret : PyList_New(0);
486 RESULT eDVBServiceList::getNext(eServiceReference &ref)
491 return m_query->getNextResult((eServiceReferenceDVB&)ref);
494 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
496 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
499 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
501 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
503 ePtr<iDVBChannelList> db;
504 ePtr<eDVBResourceManager> resm;
506 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
509 if (db->getBouquet(m_parent, m_bouquet) != 0)
520 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
524 return m_bouquet->addService(ref, before);
527 RESULT eDVBServiceList::removeService(eServiceReference &ref)
531 return m_bouquet->removeService(ref);
534 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
538 return m_bouquet->moveService(ref, pos);
541 RESULT eDVBServiceList::flushChanges()
545 return m_bouquet->flushChanges();
548 RESULT eDVBServiceList::setListName(const std::string &name)
552 return m_bouquet->setListName(name);
555 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
557 ePtr<eDVBService> service;
558 int r = lookupService(service, ref);
561 // check resources...
562 ptr = new eDVBServicePlay(ref, service);
566 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
568 if (ref.path.empty())
570 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
579 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
581 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
582 if (list->startQuery())
592 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
594 /* is a listable service? */
595 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
597 if ( !ref.name.empty() ) // satellites or providers list
598 ptr = m_StaticServiceDVBInfo;
599 else // a dvb bouquet
600 ptr = m_StaticServiceDVBBouquetInfo;
602 else if (!ref.path.empty()) /* do we have a PVR service? */
603 ptr = new eStaticServiceDVBPVRInformation(ref);
604 else // normal dvb service
606 ePtr<eDVBService> service;
607 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
608 ptr = m_StaticServiceDVBInfo;
610 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
616 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
618 if (ref.path.empty())
624 ptr = new eDVBPVRServiceOfflineOperations(ref);
629 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
631 // TODO: handle the listing itself
632 // if (ref.... == -1) .. return "... bouquets ...";
633 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
635 ePtr<iDVBChannelList> db;
636 ePtr<eDVBResourceManager> res;
639 if ((err = eDVBResourceManager::getInstance(res)) != 0)
641 eDebug("no resource manager");
644 if ((err = res->getChannelList(db)) != 0)
646 eDebug("no channel list");
650 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
651 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
653 eDebug("getService failed!");
660 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
661 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
664 m_is_pvr = !m_reference.path.empty();
666 m_timeshift_enabled = m_timeshift_active = 0;
669 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
670 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
671 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
673 m_cuesheet_changed = 0;
674 m_cutlist_enabled = 1;
676 m_subtitle_widget = 0;
678 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
681 eDVBServicePlay::~eDVBServicePlay()
683 delete m_subtitle_widget;
686 void eDVBServicePlay::gotNewEvent()
690 ePtr<eServiceEvent> m_event_now, m_event_next;
691 getEvent(m_event_now, 0);
692 getEvent(m_event_next, 1);
695 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
697 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
699 m_event((iPlayableService*)this, evUpdatedEventInfo);
702 void eDVBServicePlay::serviceEvent(int event)
706 case eDVBServicePMTHandler::eventTuned:
708 ePtr<iDVBDemux> m_demux;
709 if (!m_service_handler.getDataDemux(m_demux))
711 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
712 int sid = ref.getParentServiceID().get();
714 sid = ref.getServiceID().get();
715 if ( ref.getParentTransportStreamID().get() &&
716 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
717 m_event_handler.startOther(m_demux, sid);
719 m_event_handler.start(m_demux, sid);
723 case eDVBServicePMTHandler::eventTuneFailed:
725 eDebug("DVB service failed to tune");
726 m_event((iPlayableService*)this, evTuneFailed);
729 case eDVBServicePMTHandler::eventNewProgramInfo:
731 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
732 if (m_timeshift_enabled)
733 updateTimeshiftPids();
734 if (!m_timeshift_active)
736 if (m_first_program_info && m_is_pvr)
738 m_first_program_info = 0;
741 m_event((iPlayableService*)this, evUpdatedInfo);
744 case eDVBServicePMTHandler::eventEOF:
745 m_event((iPlayableService*)this, evEOF);
747 case eDVBServicePMTHandler::eventSOF:
748 m_event((iPlayableService*)this, evSOF);
753 void eDVBServicePlay::serviceEventTimeshift(int event)
757 case eDVBServicePMTHandler::eventNewProgramInfo:
758 if (m_timeshift_active)
761 case eDVBServicePMTHandler::eventSOF:
762 m_event((iPlayableService*)this, evSOF);
764 case eDVBServicePMTHandler::eventEOF:
770 RESULT eDVBServicePlay::start()
773 /* in pvr mode, we only want to use one demux. in tv mode, we're using
774 two (one for decoding, one for data source), as we must be prepared
775 to start recording from the data demux. */
777 m_cue = new eCueSheet();
779 m_first_program_info = 1;
780 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
781 r = m_service_handler.tune(service, m_is_pvr, m_cue);
783 /* inject EIT if there is a stored one */
786 std::string filename = service.path;
787 filename.erase(filename.length()-2, 2);
789 ePtr<eServiceEvent> event = new eServiceEvent;
790 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
792 ePtr<eServiceEvent> empty;
793 m_event_handler.inject(event, 0);
794 m_event_handler.inject(empty, 1);
801 m_event(this, evStart);
802 m_event((iPlayableService*)this, evSeekableStatusChanged);
806 RESULT eDVBServicePlay::stop()
808 /* add bookmark for last play position */
812 if (!getPlayPosition(play_position))
814 /* remove last position */
815 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
817 if (i->what == 3) /* current play position */
819 m_cue_entries.erase(i);
820 i = m_cue_entries.begin();
826 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
827 m_cuesheet_changed = 1;
831 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
833 m_service_handler_timeshift.free();
834 m_service_handler.free();
836 if (m_is_pvr && m_cuesheet_changed)
839 /* save cuesheet only when main file is accessible. */
840 if (!::stat(m_reference.path.c_str(), &s))
847 RESULT eDVBServicePlay::setTarget(int target)
849 m_is_primary = !target;
853 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
855 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
859 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
861 /* note: we check for timeshift to be enabled,
862 not neccessary active. if you pause when timeshift
863 is not active, you should activate it when unpausing */
864 if ((!m_is_pvr) && (!m_timeshift_enabled))
874 RESULT eDVBServicePlay::setSlowMotion(int ratio)
877 return m_decoder->setSlowMotion(ratio);
882 RESULT eDVBServicePlay::setFastForward(int ratio)
884 int skipmode, ffratio;
890 } else if (ratio > 0)
898 } else // if (ratio < 0)
904 if (m_skipmode != skipmode)
906 eDebug("setting cue skipmode to %d", skipmode);
908 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
911 m_skipmode = skipmode;
916 return m_decoder->setFastForward(ffratio);
919 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
921 if (m_is_pvr || m_timeshift_enabled)
931 /* TODO: when timeshift is enabled but not active, this doesn't work. */
932 RESULT eDVBServicePlay::getLength(pts_t &len)
934 ePtr<iDVBPVRChannel> pvr_channel;
936 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
939 return pvr_channel->getLength(len);
942 RESULT eDVBServicePlay::pause()
944 if (!m_is_paused && m_decoder)
947 return m_decoder->freeze(0);
952 RESULT eDVBServicePlay::unpause()
954 if (m_is_paused && m_decoder)
957 return m_decoder->unfreeze();
962 RESULT eDVBServicePlay::seekTo(pts_t to)
964 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
969 ePtr<iDVBPVRChannel> pvr_channel;
971 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
977 m_cue->seekTo(0, to);
981 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
983 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
988 ePtr<iDVBPVRChannel> pvr_channel;
990 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
995 /* HACK until we have skip-AP api */
996 if ((to > 0) && (to < 100))
1004 m_cue->seekTo(mode, to);
1008 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1010 ePtr<iDVBPVRChannel> pvr_channel;
1012 if (!m_decode_demux)
1015 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1020 /* if there is a decoder, use audio or video PTS */
1023 r = m_decoder->getPTS(0, pos);
1029 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1032 RESULT eDVBServicePlay::setTrickmode(int trick)
1035 m_decoder->setTrickmode(trick);
1039 RESULT eDVBServicePlay::isCurrentlySeekable()
1041 return m_is_pvr || m_timeshift_active;
1044 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1050 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1056 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1062 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1068 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1074 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1077 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1078 (m_timeshift_enabled || !m_is_pvr))
1080 if (!m_timeshift_enabled)
1082 /* we need enough diskspace */
1084 if (statfs(TSPATH "/.", &fs) < 0)
1086 eDebug("statfs failed!");
1090 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1092 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1102 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1113 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1119 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1125 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1131 RESULT eDVBServicePlay::getName(std::string &name)
1135 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1136 return i->getName(m_reference, name);
1140 m_dvb_service->getName(m_reference, name);
1144 else if (!m_reference.name.empty())
1145 eStaticServiceDVBInformation().getName(m_reference, name);
1147 name = "DVB service";
1151 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1153 return m_event_handler.getEvent(evt, nownext);
1156 int eDVBServicePlay::getInfo(int w)
1158 eDVBServicePMTHandler::program program;
1161 return resIsPyObject;
1163 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1165 if (h.getProgramInfo(program))
1171 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1173 ePtr<eServiceEvent> evt;
1174 if (!m_event_handler.getEvent(evt, 0))
1176 ePtr<eComponentData> data;
1177 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1179 if ( data->getStreamContent() == 1 )
1181 switch(data->getComponentType())
1184 case 1: // 4:3 SD PAL
1186 case 3: // 16:9 SD PAL
1187 case 4: // > 16:9 PAL
1188 case 5: // 4:3 SD NTSC
1190 case 7: // 16:9 SD NTSC
1191 case 8: // > 16:9 NTSC
1194 case 9: // 4:3 HD PAL
1196 case 0xB: // 16:9 HD PAL
1197 case 0xC: // > 16:9 HD PAL
1198 case 0xD: // 4:3 HD NTSC
1200 case 0xF: // 16:9 HD NTSC
1201 case 0x10: // > 16:9 HD PAL
1202 return data->getComponentType();
1209 case sIsCrypted: return program.isCrypted();
1210 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1211 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1212 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1213 case sPCRPID: return program.pcrPid;
1214 case sPMTPID: return program.pmtPid;
1215 case sTXTPID: return program.textPid;
1216 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1217 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1218 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1219 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1220 case sProvider: if (!m_dvb_service) return -1; return -2;
1226 std::string eDVBServicePlay::getInfoString(int w)
1231 if (!m_dvb_service) return "";
1232 return m_dvb_service->m_provider_name;
1236 return iServiceInformation::getInfoString(w);
1239 PyObject *eDVBServicePlay::getInfoObject(int w)
1244 return m_service_handler.getCaIds();
1248 return iServiceInformation::getInfoObject(w);
1251 int eDVBServicePlay::getNumberOfTracks()
1253 eDVBServicePMTHandler::program program;
1254 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1255 if (h.getProgramInfo(program))
1257 return program.audioStreams.size();
1260 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1262 int ret = selectAudioStream(i);
1264 if (m_decoder->start())
1270 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1272 eDVBServicePMTHandler::program program;
1273 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1275 if (h.getProgramInfo(program))
1278 if (i >= program.audioStreams.size())
1281 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1282 info.m_description = "MPEG";
1283 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1284 info.m_description = "AC3";
1285 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1286 info.m_description = "AAC";
1287 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1288 info.m_description = "DTS";
1290 info.m_description = "???";
1292 if (program.audioStreams[i].component_tag != -1)
1294 ePtr<eServiceEvent> evt;
1295 if (!m_event_handler.getEvent(evt, 0))
1297 ePtr<eComponentData> data;
1298 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1299 info.m_language = data->getText();
1303 if (info.m_language.empty())
1304 info.m_language = program.audioStreams[i].language_code;
1309 int eDVBServicePlay::selectAudioStream(int i)
1311 eDVBServicePMTHandler::program program;
1312 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1314 if (h.getProgramInfo(program))
1317 if ((unsigned int)i >= program.audioStreams.size())
1323 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1326 if (m_radiotext_parser)
1327 m_radiotext_parser->start(program.audioStreams[i].pid);
1329 if (m_dvb_service && !m_is_pvr)
1331 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1333 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1334 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1338 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1339 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1343 h.resetCachedProgram();
1348 int eDVBServicePlay::getCurrentChannel()
1350 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1353 RESULT eDVBServicePlay::selectChannel(int i)
1355 if (i < LEFT || i > RIGHT || i == STEREO)
1358 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1360 m_decoder->setAudioChannel(i);
1364 std::string eDVBServicePlay::getRadioText(int x)
1366 if (m_radiotext_parser)
1370 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1375 void eDVBServicePlay::radioTextUpdated()
1377 m_event((iPlayableService*)this, evUpdatedRadioText);
1380 int eDVBServiceBase::getFrontendInfo(int w)
1382 eUsePtr<iDVBChannel> channel;
1383 if(m_service_handler.getChannel(channel))
1385 ePtr<iDVBFrontend> fe;
1386 if(channel->getFrontend(fe))
1388 return fe->readFrontendData(w);
1391 PyObject *eDVBServiceBase::getFrontendData(bool original)
1395 eUsePtr<iDVBChannel> channel;
1396 if(!m_service_handler.getChannel(channel))
1398 ePtr<iDVBFrontend> fe;
1399 if(!channel->getFrontend(fe))
1401 ret = fe->readTransponderData(original);
1404 ePtr<iDVBFrontendParameters> feparm;
1405 channel->getCurrentFrontendParameters(feparm);
1408 eDVBFrontendParametersSatellite osat;
1409 if (!feparm->getDVBS(osat))
1411 void PutToDict(PyObject *, const char*, long);
1412 void PutToDict(PyObject *, const char*, const char*);
1413 PutToDict(ret, "orbital_position", osat.orbital_position);
1414 const char *tmp = "UNKNOWN";
1415 switch(osat.polarisation)
1417 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1418 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1419 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1420 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1423 PutToDict(ret, "polarization", tmp);
1437 int eDVBServicePlay::getNumberOfSubservices()
1439 ePtr<eServiceEvent> evt;
1440 if (!m_event_handler.getEvent(evt, 0))
1441 return evt->getNumOfLinkageServices();
1445 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1447 ePtr<eServiceEvent> evt;
1448 if (!m_event_handler.getEvent(evt, 0))
1450 if (!evt->getLinkageService(sub, m_reference, n))
1453 sub.type=eServiceReference::idInvalid;
1457 RESULT eDVBServicePlay::startTimeshift()
1459 ePtr<iDVBDemux> demux;
1461 eDebug("Start timeshift!");
1463 if (m_timeshift_enabled)
1466 /* start recording with the data demux. */
1467 if (m_service_handler.getDataDemux(demux))
1470 demux->createTSRecorder(m_record);
1474 char templ[]=TSPATH "/timeshift.XXXXXX";
1475 m_timeshift_fd = mkstemp(templ);
1476 m_timeshift_file = templ;
1478 eDebug("recording to %s", templ);
1480 if (m_timeshift_fd < 0)
1486 m_record->setTargetFD(m_timeshift_fd);
1488 m_timeshift_enabled = 1;
1490 updateTimeshiftPids();
1496 RESULT eDVBServicePlay::stopTimeshift()
1498 if (!m_timeshift_enabled)
1503 m_timeshift_enabled = 0;
1508 close(m_timeshift_fd);
1509 eDebug("remove timeshift file");
1510 remove(m_timeshift_file.c_str());
1515 int eDVBServicePlay::isTimeshiftActive()
1517 return m_timeshift_enabled && m_timeshift_active;
1520 RESULT eDVBServicePlay::activateTimeshift()
1522 if (!m_timeshift_enabled)
1525 if (!m_timeshift_active)
1527 switchToTimeshift();
1534 PyObject *eDVBServicePlay::getCutList()
1536 PyObject *list = PyList_New(0);
1538 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1540 PyObject *tuple = PyTuple_New(2);
1541 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1542 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1543 PyList_Append(list, tuple);
1550 void eDVBServicePlay::setCutList(PyObject *list)
1552 if (!PyList_Check(list))
1554 int size = PyList_Size(list);
1557 m_cue_entries.clear();
1559 for (i=0; i<size; ++i)
1561 PyObject *tuple = PyList_GetItem(list, i);
1562 if (!PyTuple_Check(tuple))
1564 eDebug("non-tuple in cutlist");
1567 if (PyTuple_Size(tuple) != 2)
1569 eDebug("cutlist entries need to be a 2-tuple");
1572 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1573 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1575 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1578 pts_t pts = PyLong_AsLongLong(ppts);
1579 int type = PyInt_AsLong(ptype);
1580 m_cue_entries.insert(cueEntry(pts, type));
1581 eDebug("adding %08llx, %d", pts, type);
1583 m_cuesheet_changed = 1;
1585 cutlistToCuesheet();
1586 m_event((iPlayableService*)this, evCuesheetChanged);
1589 void eDVBServicePlay::setCutListEnable(int enable)
1591 m_cutlist_enabled = enable;
1592 cutlistToCuesheet();
1595 void eDVBServicePlay::updateTimeshiftPids()
1600 eDVBServicePMTHandler::program program;
1601 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1603 if (h.getProgramInfo(program))
1607 std::set<int> pids_to_record;
1608 pids_to_record.insert(0); // PAT
1609 if (program.pmtPid != -1)
1610 pids_to_record.insert(program.pmtPid); // PMT
1612 if (program.textPid != -1)
1613 pids_to_record.insert(program.textPid); // Videotext
1615 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1616 i(program.videoStreams.begin());
1617 i != program.videoStreams.end(); ++i)
1618 pids_to_record.insert(i->pid);
1620 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1621 i(program.audioStreams.begin());
1622 i != program.audioStreams.end(); ++i)
1623 pids_to_record.insert(i->pid);
1625 std::set<int> new_pids, obsolete_pids;
1627 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1628 m_pids_active.begin(), m_pids_active.end(),
1629 std::inserter(new_pids, new_pids.begin()));
1631 std::set_difference(
1632 m_pids_active.begin(), m_pids_active.end(),
1633 pids_to_record.begin(), pids_to_record.end(),
1634 std::inserter(new_pids, new_pids.begin())
1637 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1638 m_record->addPID(*i);
1640 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1641 m_record->removePID(*i);
1645 void eDVBServicePlay::switchToLive()
1647 if (!m_timeshift_active)
1653 m_teletext_parser = 0;
1654 m_radiotext_parser = 0;
1655 m_subtitle_parser = 0;
1656 m_new_dvb_subtitle_page_connection = 0;
1657 m_new_subtitle_page_connection = 0;
1658 m_radiotext_updated_connection = 0;
1660 /* free the timeshift service handler, we need the resources */
1661 m_service_handler_timeshift.free();
1662 m_timeshift_active = 0;
1664 m_event((iPlayableService*)this, evSeekableStatusChanged);
1669 void eDVBServicePlay::switchToTimeshift()
1671 if (m_timeshift_active)
1676 m_teletext_parser = 0;
1677 m_radiotext_parser = 0;
1678 m_subtitle_parser = 0;
1679 m_new_subtitle_page_connection = 0;
1680 m_new_dvb_subtitle_page_connection = 0;
1681 m_radiotext_updated_connection = 0;
1683 m_timeshift_active = 1;
1685 m_event((iPlayableService*)this, evSeekableStatusChanged);
1687 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1688 r.path = m_timeshift_file;
1690 m_cue = new eCueSheet();
1691 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1692 updateDecoder(); /* mainly to switch off PCR */
1695 void eDVBServicePlay::updateDecoder()
1697 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1699 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1701 bool defaultac3=false;
1702 std::string default_ac3;
1704 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1705 defaultac3 = default_ac3 == "True";
1707 eDVBServicePMTHandler::program program;
1708 if (h.getProgramInfo(program))
1709 eDebug("getting program info failed.");
1712 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1713 if (!program.videoStreams.empty())
1715 eDebugNoNewLine(" (");
1716 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1717 i(program.videoStreams.begin());
1718 i != program.videoStreams.end(); ++i)
1725 if (i != program.videoStreams.begin())
1726 eDebugNoNewLine(", ");
1727 eDebugNoNewLine("%04x", i->pid);
1729 eDebugNoNewLine(")");
1731 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1732 if (!program.audioStreams.empty())
1734 eDebugNoNewLine(" (");
1735 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1736 i(program.audioStreams.begin());
1737 i != program.audioStreams.end(); ++i)
1739 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1741 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1747 if (i != program.audioStreams.begin())
1748 eDebugNoNewLine(", ");
1749 eDebugNoNewLine("%04x", i->pid);
1751 eDebugNoNewLine(")");
1753 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1754 pcrpid = program.pcrPid;
1755 eDebug(", and the text pid is %04x", program.textPid);
1756 tpid = program.textPid;
1761 h.getDecodeDemux(m_decode_demux);
1763 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1765 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1766 #ifdef INTERNAL_TELETEXT
1767 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1768 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1770 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1771 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1778 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1779 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1780 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1782 else // subservice or recording
1784 eServiceReferenceDVB ref;
1785 m_service_handler.getServiceReference(ref);
1786 eServiceReferenceDVB parent = ref.getParentServiceReference();
1791 ePtr<eDVBResourceManager> res_mgr;
1792 if (!eDVBResourceManager::getInstance(res_mgr))
1794 ePtr<iDVBChannelList> db;
1795 if (!res_mgr->getChannelList(db))
1797 ePtr<eDVBService> origService;
1798 if (!db->getService(parent, origService))
1800 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1801 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1807 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1808 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1810 m_decoder->setVideoPID(vpid, vpidtype);
1811 m_decoder->setAudioPID(apid, apidtype);
1812 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1814 m_decoder->setSyncPCR(pcrpid);
1817 ePtr<iDVBDemux> data_demux;
1818 if (!h.getDataDemux(data_demux))
1820 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1821 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1822 m_radiotext_parser->start(apid);
1827 m_decoder->setSyncPCR(-1);
1829 m_decoder->setTextPID(tpid);
1831 m_teletext_parser->start(program.textPid);
1834 m_decoder->setTrickmode(1);
1838 if (vpid > 0 && vpid < 0x2000)
1842 std::string radio_pic;
1843 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1844 m_decoder->setRadioPic(radio_pic);
1847 m_decoder->setAudioChannel(achannel);
1849 // how we can do this better?
1850 // update cache pid when the user changed the audio track or video track
1851 // TODO handling of difference audio types.. default audio types..
1853 /* don't worry about non-existing services, nor pvr services */
1854 if (m_dvb_service && !m_is_pvr)
1856 if (apidtype == eDVBAudio::aMPEG)
1858 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1859 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1863 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1864 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1866 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1867 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1868 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1869 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1872 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1875 void eDVBServicePlay::loadCuesheet()
1877 std::string filename = m_reference.path + ".cuts";
1879 m_cue_entries.clear();
1881 FILE *f = fopen(filename.c_str(), "rb");
1885 eDebug("loading cuts..");
1888 unsigned long long where;
1891 if (!fread(&where, sizeof(where), 1, f))
1893 if (!fread(&what, sizeof(what), 1, f))
1896 #if BYTE_ORDER == LITTLE_ENDIAN
1897 where = bswap_64(where);
1904 m_cue_entries.insert(cueEntry(where, what));
1907 eDebug("%d entries", m_cue_entries.size());
1909 eDebug("cutfile not found!");
1911 m_cuesheet_changed = 0;
1912 cutlistToCuesheet();
1913 m_event((iPlayableService*)this, evCuesheetChanged);
1916 void eDVBServicePlay::saveCuesheet()
1918 std::string filename = m_reference.path + ".cuts";
1920 FILE *f = fopen(filename.c_str(), "wb");
1924 unsigned long long where;
1927 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1929 #if BYTE_ORDER == BIG_ENDIAN
1932 where = bswap_64(i->where);
1934 what = htonl(i->what);
1935 fwrite(&where, sizeof(where), 1, f);
1936 fwrite(&what, sizeof(what), 1, f);
1942 m_cuesheet_changed = 0;
1945 void eDVBServicePlay::cutlistToCuesheet()
1949 eDebug("no cue sheet");
1954 if (!m_cutlist_enabled)
1956 m_cue->commitSpans();
1957 eDebug("cutlists were disabled");
1961 pts_t in = 0, out = 0, length = 0;
1965 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1969 if (i == m_cue_entries.end())
1972 if (i->what == 0) /* in */
1976 } else if (i->what == 1) /* out */
1978 else /* mark (2) or last play position (3) */
1986 m_cue->addSourceSpan(in, out);
1990 if (i == m_cue_entries.end())
1993 m_cue->commitSpans();
1996 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1998 if (m_subtitle_widget)
1999 disableSubtitles(parent);
2001 if (!PyInt_Check(entry))
2004 int page = PyInt_AsLong(entry);
2006 if (page > 0 && !m_teletext_parser)
2008 if (page < 0 && !m_subtitle_parser)
2011 m_subtitle_widget = new eSubtitleWidget(parent);
2012 m_subtitle_widget->resize(parent->size()); /* full size */
2016 /* eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2017 eDVBServicePMTHandler::program program;
2018 if (h.getProgramInfo(program))
2019 eDebug("getting program info failed.");
2022 eDebug("start teletext on pid %04x, page %d", program.textPid, page);
2023 m_teletext_parser->start(program.textPid);*/
2024 m_teletext_parser->setPage(page);
2030 m_subtitle_parser->start(pid);
2036 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2038 delete m_subtitle_widget;
2039 m_subtitle_widget = 0;
2040 if (m_subtitle_parser)
2042 m_subtitle_parser->stop();
2043 m_dvb_subtitle_pages.clear();
2045 if (m_teletext_parser)
2047 m_teletext_parser->setPage(-1);
2048 m_subtitle_pages.clear();
2053 PyObject *eDVBServicePlay::getSubtitleList()
2055 if (!m_teletext_parser)
2061 PyObject *l = PyList_New(0);
2063 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2065 PyObject *tuple = PyTuple_New(2);
2067 sprintf(desc, "Page %d", *i);
2068 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2069 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2070 PyList_Append(l, tuple);
2074 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2075 eDVBServicePMTHandler::program program;
2076 if (h.getProgramInfo(program))
2077 eDebug("getting program info failed.");
2080 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2081 it != program.subtitleStreams.end(); ++it)
2083 PyObject *tuple = PyTuple_New(2);
2085 sprintf(desc, "DVB %s", it->language_code.c_str());
2086 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2087 PyTuple_SetItem(tuple, 1, PyInt_FromLong(-it->pid));
2088 PyList_Append(l, tuple);
2096 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2098 if (m_subtitle_widget)
2100 m_subtitle_pages.push_back(page);
2101 checkSubtitleTiming();
2105 void eDVBServicePlay::checkSubtitleTiming()
2107 // eDebug("checkSubtitleTiming");
2108 if (!m_subtitle_widget)
2112 enum { TELETEXT, DVB } type;
2113 eDVBTeletextSubtitlePage page;
2114 eDVBSubtitlePage dvb_page;
2116 if (!m_subtitle_pages.empty())
2118 page = m_subtitle_pages.front();
2120 show_time = page.m_pts;
2122 else if (!m_dvb_subtitle_pages.empty())
2124 dvb_page = m_dvb_subtitle_pages.front();
2126 show_time = dvb_page.m_show_time;
2134 m_decoder->getPTS(0, pos);
2136 // eDebug("%lld %lld", pos, show_time);
2137 int diff = show_time - pos;
2140 eDebug("[late (%d ms)]", -diff / 90);
2145 eDebug("[invalid]");
2151 if (type == TELETEXT)
2153 eDebug("display teletext subtitle page");
2154 m_subtitle_widget->setPage(page);
2155 m_subtitle_pages.pop_front();
2159 eDebug("display dvb subtitle Page");
2160 m_subtitle_widget->setPage(dvb_page);
2161 m_dvb_subtitle_pages.pop_front();
2165 eDebug("start subtitle delay %d", diff / 90);
2166 m_subtitle_sync_timer.start(diff / 90, 1);
2172 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2174 if (m_subtitle_widget)
2176 m_dvb_subtitle_pages.push_back(p);
2177 checkSubtitleTiming();
2181 int eDVBServicePlay::getAC3Delay()
2184 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2186 return m_decoder->getAC3Delay();
2191 int eDVBServicePlay::getPCMDelay()
2194 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2196 return m_decoder->getPCMDelay();
2201 void eDVBServicePlay::setAC3Delay(int delay)
2204 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2206 m_decoder->setAC3Delay(delay);
2209 void eDVBServicePlay::setPCMDelay(int delay)
2212 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2214 m_decoder->setPCMDelay(delay);
2217 DEFINE_REF(eDVBServicePlay)
2219 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");