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();
220 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
222 if (!ref.path.empty())
224 ePtr<eServiceEvent> event = new eServiceEvent;
225 std::string filename = ref.path;
226 filename.erase(filename.length()-2, 2);
228 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
238 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
240 DECLARE_REF(eDVBPVRServiceOfflineOperations);
241 eServiceReferenceDVB m_ref;
243 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
245 RESULT deleteFromDisk(int simulate);
246 RESULT getListOfFilenames(std::list<std::string> &);
249 DEFINE_REF(eDVBPVRServiceOfflineOperations);
251 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
255 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
261 std::list<std::string> res;
262 if (getListOfFilenames(res))
265 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
267 eDebug("FATAL !! can't get background file eraser");
269 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
271 eDebug("Removing %s...", i->c_str());
273 eraser->erase(i->c_str());
275 ::unlink(i->c_str());
282 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
285 res.push_back(m_ref.path);
287 // handling for old splitted recordings (enigma 1)
292 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
294 if (stat(buf, &s) < 0)
299 res.push_back(m_ref.path + ".meta");
300 res.push_back(m_ref.path + ".ap");
301 res.push_back(m_ref.path + ".cuts");
302 std::string tmp = m_ref.path;
303 tmp.erase(m_ref.path.length()-3);
304 res.push_back(tmp + ".eit");
308 DEFINE_REF(eServiceFactoryDVB)
310 eServiceFactoryDVB::eServiceFactoryDVB()
312 ePtr<eServiceCenter> sc;
314 eServiceCenter::getPrivInstance(sc);
316 sc->addServiceFactory(eServiceFactoryDVB::id, this);
318 m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
319 m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
322 eServiceFactoryDVB::~eServiceFactoryDVB()
324 ePtr<eServiceCenter> sc;
326 eServiceCenter::getPrivInstance(sc);
328 sc->removeServiceFactory(eServiceFactoryDVB::id);
331 DEFINE_REF(eDVBServiceList);
333 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
337 eDVBServiceList::~eDVBServiceList()
341 RESULT eDVBServiceList::startQuery()
343 ePtr<iDVBChannelList> db;
344 ePtr<eDVBResourceManager> res;
347 if ((err = eDVBResourceManager::getInstance(res)) != 0)
349 eDebug("no resource manager");
352 if ((err = res->getChannelList(db)) != 0)
354 eDebug("no channel list");
358 ePtr<eDVBChannelQuery> q;
360 if (!m_parent.path.empty())
362 eDVBChannelQuery::compile(q, m_parent.path);
365 eDebug("compile query failed");
370 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
372 eDebug("startQuery failed");
379 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
381 eServiceReferenceDVB ref;
386 while (!m_query->getNextResult(ref))
390 list.sort(iListableServiceCompare(this));
395 // The first argument of this function is a format string to specify the order and
396 // the content of the returned list
397 // useable format options are
398 // R = Service Reference (as swig object .. this is very slow)
399 // S = Service Reference (as python string object .. same as ref.toString())
400 // C = Service Reference (as python string object .. same as ref.toCompareString())
401 // N = Service Name (as python string object)
402 // when exactly one return value per service is selected in the format string,
403 // then each value is directly a list entry
404 // when more than one value is returned per service, then the list is a list of
406 // unknown format string chars are returned as python None values !
407 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
410 std::list<eServiceReference> tmplist;
413 if (!format || !(retcount=strlen(format)))
414 format = "R"; // just return service reference swig object ...
416 if (!getContent(tmplist, sorted))
418 int services=tmplist.size();
419 ePtr<iStaticServiceInformation> sptr;
420 eServiceCenterPtr service_center;
422 if (strchr(format, 'N'))
423 eServiceCenter::getPrivInstance(service_center);
425 ret = PyList_New(services);
426 std::list<eServiceReference>::iterator it(tmplist.begin());
428 for (int cnt=0; cnt < services; ++cnt)
430 eServiceReference &ref=*it++;
431 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
432 for (int i=0; i < retcount; ++i)
437 case 'R': // service reference (swig)object
438 tmp = New_eServiceReference(ref);
440 case 'C': // service reference compare string
441 tmp = PyString_FromString(ref.toCompareString().c_str());
443 case 'S': // service reference string
444 tmp = PyString_FromString(ref.toString().c_str());
446 case 'N': // service name
449 service_center->info(ref, sptr);
453 sptr->getName(ref, name);
455 tmp = PyString_FromString(name.c_str());
459 tmp = PyString_FromString("<n/a>");
472 PyTuple_SET_ITEM(tuple, i, tmp);
474 PyList_SET_ITEM(ret, cnt, tmp);
478 PyList_SET_ITEM(ret, cnt, tuple);
481 return ret ? ret : PyList_New(0);
484 RESULT eDVBServiceList::getNext(eServiceReference &ref)
489 return m_query->getNextResult((eServiceReferenceDVB&)ref);
492 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
494 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
497 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
499 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
501 ePtr<iDVBChannelList> db;
502 ePtr<eDVBResourceManager> resm;
504 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
507 if (db->getBouquet(m_parent, m_bouquet) != 0)
518 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
522 return m_bouquet->addService(ref, before);
525 RESULT eDVBServiceList::removeService(eServiceReference &ref)
529 return m_bouquet->removeService(ref);
532 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
536 return m_bouquet->moveService(ref, pos);
539 RESULT eDVBServiceList::flushChanges()
543 return m_bouquet->flushChanges();
546 RESULT eDVBServiceList::setListName(const std::string &name)
550 return m_bouquet->setListName(name);
553 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
555 ePtr<eDVBService> service;
556 int r = lookupService(service, ref);
559 // check resources...
560 ptr = new eDVBServicePlay(ref, service);
564 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
566 if (ref.path.empty())
568 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
577 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
579 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
580 if (list->startQuery())
590 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
592 /* is a listable service? */
593 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
595 if ( !ref.name.empty() ) // satellites or providers list
596 ptr = m_StaticServiceDVBInfo;
597 else // a dvb bouquet
598 ptr = m_StaticServiceDVBBouquetInfo;
600 else if (!ref.path.empty()) /* do we have a PVR service? */
601 ptr = new eStaticServiceDVBPVRInformation(ref);
602 else // normal dvb service
604 ePtr<eDVBService> service;
605 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
606 ptr = m_StaticServiceDVBInfo;
608 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
614 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
616 if (ref.path.empty())
622 ptr = new eDVBPVRServiceOfflineOperations(ref);
627 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
629 // TODO: handle the listing itself
630 // if (ref.... == -1) .. return "... bouquets ...";
631 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
633 ePtr<iDVBChannelList> db;
634 ePtr<eDVBResourceManager> res;
637 if ((err = eDVBResourceManager::getInstance(res)) != 0)
639 eDebug("no resource manager");
642 if ((err = res->getChannelList(db)) != 0)
644 eDebug("no channel list");
648 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
649 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
651 eDebug("getService failed!");
658 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
659 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
662 m_is_pvr = !m_reference.path.empty();
664 m_timeshift_enabled = m_timeshift_active = 0;
667 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
668 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
669 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
671 m_cuesheet_changed = 0;
672 m_cutlist_enabled = 1;
674 m_subtitle_widget = 0;
676 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
679 eDVBServicePlay::~eDVBServicePlay()
681 delete m_subtitle_widget;
684 void eDVBServicePlay::gotNewEvent()
688 ePtr<eServiceEvent> m_event_now, m_event_next;
689 getEvent(m_event_now, 0);
690 getEvent(m_event_next, 1);
693 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
695 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
697 m_event((iPlayableService*)this, evUpdatedEventInfo);
700 void eDVBServicePlay::serviceEvent(int event)
704 case eDVBServicePMTHandler::eventTuned:
706 ePtr<iDVBDemux> m_demux;
707 if (!m_service_handler.getDataDemux(m_demux))
709 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
710 int sid = ref.getParentServiceID().get();
712 sid = ref.getServiceID().get();
713 if ( ref.getParentTransportStreamID().get() &&
714 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
715 m_event_handler.startOther(m_demux, sid);
717 m_event_handler.start(m_demux, sid);
721 case eDVBServicePMTHandler::eventTuneFailed:
723 eDebug("DVB service failed to tune");
724 m_event((iPlayableService*)this, evTuneFailed);
727 case eDVBServicePMTHandler::eventNewProgramInfo:
729 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
730 if (m_timeshift_enabled)
731 updateTimeshiftPids();
732 if (!m_timeshift_active)
734 if (m_first_program_info && m_is_pvr)
736 m_first_program_info = 0;
739 m_event((iPlayableService*)this, evUpdatedInfo);
742 case eDVBServicePMTHandler::eventEOF:
743 m_event((iPlayableService*)this, evEOF);
745 case eDVBServicePMTHandler::eventSOF:
746 m_event((iPlayableService*)this, evSOF);
751 void eDVBServicePlay::serviceEventTimeshift(int event)
755 case eDVBServicePMTHandler::eventNewProgramInfo:
756 if (m_timeshift_active)
759 case eDVBServicePMTHandler::eventSOF:
760 m_event((iPlayableService*)this, evSOF);
762 case eDVBServicePMTHandler::eventEOF:
768 RESULT eDVBServicePlay::start()
771 /* in pvr mode, we only want to use one demux. in tv mode, we're using
772 two (one for decoding, one for data source), as we must be prepared
773 to start recording from the data demux. */
775 m_cue = new eCueSheet();
777 m_first_program_info = 1;
778 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
779 r = m_service_handler.tune(service, m_is_pvr, m_cue);
781 /* inject EIT if there is a stored one */
784 std::string filename = service.path;
785 filename.erase(filename.length()-2, 2);
787 ePtr<eServiceEvent> event = new eServiceEvent;
788 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
790 ePtr<eServiceEvent> empty;
791 m_event_handler.inject(event, 0);
792 m_event_handler.inject(empty, 1);
799 m_event(this, evStart);
800 m_event((iPlayableService*)this, evSeekableStatusChanged);
804 RESULT eDVBServicePlay::stop()
806 /* add bookmark for last play position */
810 if (!getPlayPosition(play_position))
812 /* remove last position */
813 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
815 if (i->what == 3) /* current play position */
817 m_cue_entries.erase(i);
818 i = m_cue_entries.begin();
824 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
825 m_cuesheet_changed = 1;
829 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
831 m_service_handler_timeshift.free();
832 m_service_handler.free();
834 if (m_is_pvr && m_cuesheet_changed)
837 /* save cuesheet only when main file is accessible. */
838 if (!::stat(m_reference.path.c_str(), &s))
845 RESULT eDVBServicePlay::setTarget(int target)
847 m_is_primary = !target;
851 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
853 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
857 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
859 /* note: we check for timeshift to be enabled,
860 not neccessary active. if you pause when timeshift
861 is not active, you should activate it when unpausing */
862 if ((!m_is_pvr) && (!m_timeshift_enabled))
872 RESULT eDVBServicePlay::setSlowMotion(int ratio)
875 return m_decoder->setSlowMotion(ratio);
880 RESULT eDVBServicePlay::setFastForward(int ratio)
882 int skipmode, ffratio;
888 } else if (ratio > 0)
896 } else // if (ratio < 0)
902 if (m_skipmode != skipmode)
904 eDebug("setting cue skipmode to %d", skipmode);
906 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
909 m_skipmode = skipmode;
914 return m_decoder->setFastForward(ffratio);
917 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
919 if (m_is_pvr || m_timeshift_enabled)
929 /* TODO: when timeshift is enabled but not active, this doesn't work. */
930 RESULT eDVBServicePlay::getLength(pts_t &len)
932 ePtr<iDVBPVRChannel> pvr_channel;
934 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
937 return pvr_channel->getLength(len);
940 RESULT eDVBServicePlay::pause()
942 if (!m_is_paused && m_decoder)
945 return m_decoder->freeze(0);
950 RESULT eDVBServicePlay::unpause()
952 if (m_is_paused && m_decoder)
955 return m_decoder->unfreeze();
960 RESULT eDVBServicePlay::seekTo(pts_t to)
962 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
967 ePtr<iDVBPVRChannel> pvr_channel;
969 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
975 m_cue->seekTo(0, to);
979 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
981 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
986 ePtr<iDVBPVRChannel> pvr_channel;
988 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
993 /* HACK until we have skip-AP api */
994 if ((to > 0) && (to < 100))
1002 m_cue->seekTo(mode, to);
1006 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1008 ePtr<iDVBPVRChannel> pvr_channel;
1010 if (!m_decode_demux)
1013 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1018 /* if there is a decoder, use audio or video PTS */
1021 r = m_decoder->getPTS(0, pos);
1027 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1030 RESULT eDVBServicePlay::setTrickmode(int trick)
1033 m_decoder->setTrickmode(trick);
1037 RESULT eDVBServicePlay::isCurrentlySeekable()
1039 return m_is_pvr || m_timeshift_active;
1042 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1048 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1054 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1060 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1066 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1072 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1075 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1076 (m_timeshift_enabled || !m_is_pvr))
1078 if (!m_timeshift_enabled)
1080 /* we need enough diskspace */
1082 if (statfs(TSPATH "/.", &fs) < 0)
1084 eDebug("statfs failed!");
1088 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1090 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1100 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1111 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1117 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1123 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1129 RESULT eDVBServicePlay::getName(std::string &name)
1133 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1134 return i->getName(m_reference, name);
1138 m_dvb_service->getName(m_reference, name);
1142 else if (!m_reference.name.empty())
1143 eStaticServiceDVBInformation().getName(m_reference, name);
1145 name = "DVB service";
1149 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1151 return m_event_handler.getEvent(evt, nownext);
1154 int eDVBServicePlay::getInfo(int w)
1156 eDVBServicePMTHandler::program program;
1159 return resIsPyObject;
1161 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1163 if (h.getProgramInfo(program))
1169 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1171 ePtr<eServiceEvent> evt;
1172 if (!m_event_handler.getEvent(evt, 0))
1174 ePtr<eComponentData> data;
1175 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1177 if ( data->getStreamContent() == 1 )
1179 switch(data->getComponentType())
1182 case 1: // 4:3 SD PAL
1184 case 3: // 16:9 SD PAL
1185 case 4: // > 16:9 PAL
1186 case 5: // 4:3 SD NTSC
1188 case 7: // 16:9 SD NTSC
1189 case 8: // > 16:9 NTSC
1192 case 9: // 4:3 HD PAL
1194 case 0xB: // 16:9 HD PAL
1195 case 0xC: // > 16:9 HD PAL
1196 case 0xD: // 4:3 HD NTSC
1198 case 0xF: // 16:9 HD NTSC
1199 case 0x10: // > 16:9 HD PAL
1200 return data->getComponentType();
1207 case sIsCrypted: return program.isCrypted();
1208 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1209 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1210 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1211 case sPCRPID: return program.pcrPid;
1212 case sPMTPID: return program.pmtPid;
1213 case sTXTPID: return program.textPid;
1214 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1215 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1216 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1217 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1218 case sProvider: if (!m_dvb_service) return -1; return -2;
1224 std::string eDVBServicePlay::getInfoString(int w)
1229 if (!m_dvb_service) return "";
1230 return m_dvb_service->m_provider_name;
1234 return iServiceInformation::getInfoString(w);
1237 PyObject *eDVBServicePlay::getInfoObject(int w)
1242 return m_service_handler.getCaIds();
1246 return iServiceInformation::getInfoObject(w);
1249 int eDVBServicePlay::getNumberOfTracks()
1251 eDVBServicePMTHandler::program program;
1252 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1253 if (h.getProgramInfo(program))
1255 return program.audioStreams.size();
1258 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1260 int ret = selectAudioStream(i);
1262 if (m_decoder->start())
1268 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1270 eDVBServicePMTHandler::program program;
1271 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1273 if (h.getProgramInfo(program))
1276 if (i >= program.audioStreams.size())
1279 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1280 info.m_description = "MPEG";
1281 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1282 info.m_description = "AC3";
1283 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1284 info.m_description = "AAC";
1285 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1286 info.m_description = "DTS";
1288 info.m_description = "???";
1290 if (program.audioStreams[i].component_tag != -1)
1292 ePtr<eServiceEvent> evt;
1293 if (!m_event_handler.getEvent(evt, 0))
1295 ePtr<eComponentData> data;
1296 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1297 info.m_language = data->getText();
1301 if (info.m_language.empty())
1302 info.m_language = program.audioStreams[i].language_code;
1307 int eDVBServicePlay::selectAudioStream(int i)
1309 eDVBServicePMTHandler::program program;
1310 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1312 if (h.getProgramInfo(program))
1315 if ((unsigned int)i >= program.audioStreams.size())
1321 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1324 if (m_radiotext_parser)
1325 m_radiotext_parser->start(program.audioStreams[i].pid);
1327 if (m_dvb_service && !m_is_pvr)
1329 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1331 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1332 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1336 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1337 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1341 h.resetCachedProgram();
1346 int eDVBServicePlay::getCurrentChannel()
1348 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1351 RESULT eDVBServicePlay::selectChannel(int i)
1353 if (i < LEFT || i > RIGHT || i == STEREO)
1356 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1358 m_decoder->setAudioChannel(i);
1362 std::string eDVBServicePlay::getRadioText(int x)
1364 if (m_radiotext_parser)
1368 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1373 void eDVBServicePlay::radioTextUpdated()
1375 m_event((iPlayableService*)this, evUpdatedRadioText);
1378 int eDVBServiceBase::getFrontendInfo(int w)
1380 eUsePtr<iDVBChannel> channel;
1381 if(m_service_handler.getChannel(channel))
1383 ePtr<iDVBFrontend> fe;
1384 if(channel->getFrontend(fe))
1386 return fe->readFrontendData(w);
1389 PyObject *eDVBServiceBase::getFrontendData(bool original)
1393 eUsePtr<iDVBChannel> channel;
1394 if(!m_service_handler.getChannel(channel))
1396 ePtr<iDVBFrontend> fe;
1397 if(!channel->getFrontend(fe))
1399 ret = fe->readTransponderData(original);
1402 ePtr<iDVBFrontendParameters> feparm;
1403 channel->getCurrentFrontendParameters(feparm);
1406 eDVBFrontendParametersSatellite osat;
1407 if (!feparm->getDVBS(osat))
1409 void PutToDict(PyObject *, const char*, long);
1410 void PutToDict(PyObject *, const char*, const char*);
1411 PutToDict(ret, "orbital_position", osat.orbital_position);
1412 const char *tmp = "UNKNOWN";
1413 switch(osat.polarisation)
1415 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1416 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1417 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1418 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1421 PutToDict(ret, "polarization", tmp);
1435 int eDVBServicePlay::getNumberOfSubservices()
1437 ePtr<eServiceEvent> evt;
1438 if (!m_event_handler.getEvent(evt, 0))
1439 return evt->getNumOfLinkageServices();
1443 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1445 ePtr<eServiceEvent> evt;
1446 if (!m_event_handler.getEvent(evt, 0))
1448 if (!evt->getLinkageService(sub, m_reference, n))
1451 sub.type=eServiceReference::idInvalid;
1455 RESULT eDVBServicePlay::startTimeshift()
1457 ePtr<iDVBDemux> demux;
1459 eDebug("Start timeshift!");
1461 if (m_timeshift_enabled)
1464 /* start recording with the data demux. */
1465 if (m_service_handler.getDataDemux(demux))
1468 demux->createTSRecorder(m_record);
1472 char templ[]=TSPATH "/timeshift.XXXXXX";
1473 m_timeshift_fd = mkstemp(templ);
1474 m_timeshift_file = templ;
1476 eDebug("recording to %s", templ);
1478 if (m_timeshift_fd < 0)
1484 m_record->setTargetFD(m_timeshift_fd);
1486 m_timeshift_enabled = 1;
1488 updateTimeshiftPids();
1494 RESULT eDVBServicePlay::stopTimeshift()
1496 if (!m_timeshift_enabled)
1501 m_timeshift_enabled = 0;
1506 close(m_timeshift_fd);
1507 eDebug("remove timeshift file");
1508 remove(m_timeshift_file.c_str());
1513 int eDVBServicePlay::isTimeshiftActive()
1515 return m_timeshift_enabled && m_timeshift_active;
1518 RESULT eDVBServicePlay::activateTimeshift()
1520 if (!m_timeshift_enabled)
1523 if (!m_timeshift_active)
1525 switchToTimeshift();
1532 PyObject *eDVBServicePlay::getCutList()
1534 PyObject *list = PyList_New(0);
1536 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1538 PyObject *tuple = PyTuple_New(2);
1539 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1540 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1541 PyList_Append(list, tuple);
1548 void eDVBServicePlay::setCutList(PyObject *list)
1550 if (!PyList_Check(list))
1552 int size = PyList_Size(list);
1555 m_cue_entries.clear();
1557 for (i=0; i<size; ++i)
1559 PyObject *tuple = PyList_GetItem(list, i);
1560 if (!PyTuple_Check(tuple))
1562 eDebug("non-tuple in cutlist");
1565 if (PyTuple_Size(tuple) != 2)
1567 eDebug("cutlist entries need to be a 2-tuple");
1570 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1571 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1573 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1576 pts_t pts = PyLong_AsLongLong(ppts);
1577 int type = PyInt_AsLong(ptype);
1578 m_cue_entries.insert(cueEntry(pts, type));
1579 eDebug("adding %08llx, %d", pts, type);
1581 m_cuesheet_changed = 1;
1583 cutlistToCuesheet();
1584 m_event((iPlayableService*)this, evCuesheetChanged);
1587 void eDVBServicePlay::setCutListEnable(int enable)
1589 m_cutlist_enabled = enable;
1590 cutlistToCuesheet();
1593 void eDVBServicePlay::updateTimeshiftPids()
1598 eDVBServicePMTHandler::program program;
1599 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1601 if (h.getProgramInfo(program))
1605 std::set<int> pids_to_record;
1606 pids_to_record.insert(0); // PAT
1607 if (program.pmtPid != -1)
1608 pids_to_record.insert(program.pmtPid); // PMT
1610 if (program.textPid != -1)
1611 pids_to_record.insert(program.textPid); // Videotext
1613 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1614 i(program.videoStreams.begin());
1615 i != program.videoStreams.end(); ++i)
1616 pids_to_record.insert(i->pid);
1618 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1619 i(program.audioStreams.begin());
1620 i != program.audioStreams.end(); ++i)
1621 pids_to_record.insert(i->pid);
1623 std::set<int> new_pids, obsolete_pids;
1625 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1626 m_pids_active.begin(), m_pids_active.end(),
1627 std::inserter(new_pids, new_pids.begin()));
1629 std::set_difference(
1630 m_pids_active.begin(), m_pids_active.end(),
1631 pids_to_record.begin(), pids_to_record.end(),
1632 std::inserter(new_pids, new_pids.begin())
1635 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1636 m_record->addPID(*i);
1638 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1639 m_record->removePID(*i);
1643 void eDVBServicePlay::switchToLive()
1645 if (!m_timeshift_active)
1651 m_teletext_parser = 0;
1652 m_radiotext_parser = 0;
1653 m_subtitle_parser = 0;
1654 m_new_dvb_subtitle_page_connection = 0;
1655 m_new_subtitle_page_connection = 0;
1656 m_radiotext_updated_connection = 0;
1658 /* free the timeshift service handler, we need the resources */
1659 m_service_handler_timeshift.free();
1660 m_timeshift_active = 0;
1662 m_event((iPlayableService*)this, evSeekableStatusChanged);
1667 void eDVBServicePlay::switchToTimeshift()
1669 if (m_timeshift_active)
1674 m_teletext_parser = 0;
1675 m_radiotext_parser = 0;
1676 m_subtitle_parser = 0;
1677 m_new_subtitle_page_connection = 0;
1678 m_new_dvb_subtitle_page_connection = 0;
1679 m_radiotext_updated_connection = 0;
1681 m_timeshift_active = 1;
1683 m_event((iPlayableService*)this, evSeekableStatusChanged);
1685 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1686 r.path = m_timeshift_file;
1688 m_cue = new eCueSheet();
1689 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1690 updateDecoder(); /* mainly to switch off PCR */
1693 void eDVBServicePlay::updateDecoder()
1695 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1697 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1699 bool defaultac3=false;
1700 std::string default_ac3;
1702 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1703 defaultac3 = default_ac3 == "True";
1705 eDVBServicePMTHandler::program program;
1706 if (h.getProgramInfo(program))
1707 eDebug("getting program info failed.");
1710 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1711 if (!program.videoStreams.empty())
1713 eDebugNoNewLine(" (");
1714 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1715 i(program.videoStreams.begin());
1716 i != program.videoStreams.end(); ++i)
1723 if (i != program.videoStreams.begin())
1724 eDebugNoNewLine(", ");
1725 eDebugNoNewLine("%04x", i->pid);
1727 eDebugNoNewLine(")");
1729 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1730 if (!program.audioStreams.empty())
1732 eDebugNoNewLine(" (");
1733 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1734 i(program.audioStreams.begin());
1735 i != program.audioStreams.end(); ++i)
1737 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1739 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1745 if (i != program.audioStreams.begin())
1746 eDebugNoNewLine(", ");
1747 eDebugNoNewLine("%04x", i->pid);
1749 eDebugNoNewLine(")");
1751 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1752 pcrpid = program.pcrPid;
1753 eDebug(", and the text pid is %04x", program.textPid);
1754 tpid = program.textPid;
1759 h.getDecodeDemux(m_decode_demux);
1761 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1763 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1764 #ifdef INTERNAL_TELETEXT
1765 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1766 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1768 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1769 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1776 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1777 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1778 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1780 else // subservice or recording
1782 eServiceReferenceDVB ref;
1783 m_service_handler.getServiceReference(ref);
1784 eServiceReferenceDVB parent = ref.getParentServiceReference();
1789 ePtr<eDVBResourceManager> res_mgr;
1790 if (!eDVBResourceManager::getInstance(res_mgr))
1792 ePtr<iDVBChannelList> db;
1793 if (!res_mgr->getChannelList(db))
1795 ePtr<eDVBService> origService;
1796 if (!db->getService(parent, origService))
1798 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1799 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1805 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1806 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1808 m_decoder->setVideoPID(vpid, vpidtype);
1809 m_decoder->setAudioPID(apid, apidtype);
1810 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1812 m_decoder->setSyncPCR(pcrpid);
1815 ePtr<iDVBDemux> data_demux;
1816 if (!h.getDataDemux(data_demux))
1818 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1819 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1820 m_radiotext_parser->start(apid);
1825 m_decoder->setSyncPCR(-1);
1827 m_decoder->setTextPID(tpid);
1829 m_teletext_parser->start(program.textPid);
1832 m_decoder->setTrickmode(1);
1836 if (vpid > 0 && vpid < 0x2000)
1840 std::string radio_pic;
1841 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1842 m_decoder->setRadioPic(radio_pic);
1845 m_decoder->setAudioChannel(achannel);
1847 // how we can do this better?
1848 // update cache pid when the user changed the audio track or video track
1849 // TODO handling of difference audio types.. default audio types..
1851 /* don't worry about non-existing services, nor pvr services */
1852 if (m_dvb_service && !m_is_pvr)
1854 if (apidtype == eDVBAudio::aMPEG)
1856 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1857 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1861 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1862 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1864 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1865 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1866 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1867 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1870 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1873 void eDVBServicePlay::loadCuesheet()
1875 std::string filename = m_reference.path + ".cuts";
1877 m_cue_entries.clear();
1879 FILE *f = fopen(filename.c_str(), "rb");
1883 eDebug("loading cuts..");
1886 unsigned long long where;
1889 if (!fread(&where, sizeof(where), 1, f))
1891 if (!fread(&what, sizeof(what), 1, f))
1894 #if BYTE_ORDER == LITTLE_ENDIAN
1895 where = bswap_64(where);
1902 m_cue_entries.insert(cueEntry(where, what));
1905 eDebug("%d entries", m_cue_entries.size());
1907 eDebug("cutfile not found!");
1909 m_cuesheet_changed = 0;
1910 cutlistToCuesheet();
1911 m_event((iPlayableService*)this, evCuesheetChanged);
1914 void eDVBServicePlay::saveCuesheet()
1916 std::string filename = m_reference.path + ".cuts";
1918 FILE *f = fopen(filename.c_str(), "wb");
1922 unsigned long long where;
1925 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1927 #if BYTE_ORDER == BIG_ENDIAN
1930 where = bswap_64(i->where);
1932 what = htonl(i->what);
1933 fwrite(&where, sizeof(where), 1, f);
1934 fwrite(&what, sizeof(what), 1, f);
1940 m_cuesheet_changed = 0;
1943 void eDVBServicePlay::cutlistToCuesheet()
1947 eDebug("no cue sheet");
1952 if (!m_cutlist_enabled)
1954 m_cue->commitSpans();
1955 eDebug("cutlists were disabled");
1959 pts_t in = 0, out = 0, length = 0;
1963 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1967 if (i == m_cue_entries.end())
1970 if (i->what == 0) /* in */
1974 } else if (i->what == 1) /* out */
1976 else /* mark (2) or last play position (3) */
1984 m_cue->addSourceSpan(in, out);
1988 if (i == m_cue_entries.end())
1991 m_cue->commitSpans();
1994 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1996 if (m_subtitle_widget)
1997 disableSubtitles(parent);
1999 if (!PyInt_Check(entry))
2002 int page = PyInt_AsLong(entry);
2004 if (page > 0 && !m_teletext_parser)
2006 if (page < 0 && !m_subtitle_parser)
2009 m_subtitle_widget = new eSubtitleWidget(parent);
2010 m_subtitle_widget->resize(parent->size()); /* full size */
2014 /* eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2015 eDVBServicePMTHandler::program program;
2016 if (h.getProgramInfo(program))
2017 eDebug("getting program info failed.");
2020 eDebug("start teletext on pid %04x, page %d", program.textPid, page);
2021 m_teletext_parser->start(program.textPid);*/
2022 m_teletext_parser->setPage(page);
2028 m_subtitle_parser->start(pid);
2034 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2036 delete m_subtitle_widget;
2037 m_subtitle_widget = 0;
2038 if (m_subtitle_parser)
2040 m_subtitle_parser->stop();
2041 m_dvb_subtitle_pages.clear();
2043 if (m_teletext_parser)
2045 m_teletext_parser->setPage(-1);
2046 m_subtitle_pages.clear();
2051 PyObject *eDVBServicePlay::getSubtitleList()
2053 if (!m_teletext_parser)
2059 PyObject *l = PyList_New(0);
2061 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2063 PyObject *tuple = PyTuple_New(2);
2065 sprintf(desc, "Page %d", *i);
2066 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2067 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2068 PyList_Append(l, tuple);
2072 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2073 eDVBServicePMTHandler::program program;
2074 if (h.getProgramInfo(program))
2075 eDebug("getting program info failed.");
2078 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2079 it != program.subtitleStreams.end(); ++it)
2081 PyObject *tuple = PyTuple_New(2);
2083 sprintf(desc, "DVB %s", it->language_code.c_str());
2084 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2085 PyTuple_SetItem(tuple, 1, PyInt_FromLong(-it->pid));
2086 PyList_Append(l, tuple);
2094 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2096 if (m_subtitle_widget)
2098 m_subtitle_pages.push_back(page);
2099 checkSubtitleTiming();
2103 void eDVBServicePlay::checkSubtitleTiming()
2105 // eDebug("checkSubtitleTiming");
2106 if (!m_subtitle_widget)
2110 enum { TELETEXT, DVB } type;
2111 eDVBTeletextSubtitlePage page;
2112 eDVBSubtitlePage dvb_page;
2114 if (!m_subtitle_pages.empty())
2116 page = m_subtitle_pages.front();
2118 show_time = page.m_pts;
2120 else if (!m_dvb_subtitle_pages.empty())
2122 dvb_page = m_dvb_subtitle_pages.front();
2124 show_time = dvb_page.m_show_time;
2132 m_decoder->getPTS(0, pos);
2134 // eDebug("%lld %lld", pos, show_time);
2135 int diff = show_time - pos;
2138 eDebug("[late (%d ms)]", -diff / 90);
2143 eDebug("[invalid]");
2149 if (type == TELETEXT)
2151 eDebug("display teletext subtitle page");
2152 m_subtitle_widget->setPage(page);
2153 m_subtitle_pages.pop_front();
2157 eDebug("display dvb subtitle Page");
2158 m_subtitle_widget->setPage(dvb_page);
2159 m_dvb_subtitle_pages.pop_front();
2163 eDebug("start subtitle delay %d", diff / 90);
2164 m_subtitle_sync_timer.start(diff / 90, 1);
2170 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2172 if (m_subtitle_widget)
2174 m_dvb_subtitle_pages.push_back(p);
2175 checkSubtitleTiming();
2179 int eDVBServicePlay::getAC3Delay()
2182 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2184 return m_decoder->getAC3Delay();
2189 int eDVBServicePlay::getPCMDelay()
2192 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2194 return m_decoder->getPCMDelay();
2199 void eDVBServicePlay::setAC3Delay(int delay)
2202 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2204 m_decoder->setAC3Delay(delay);
2207 void eDVBServicePlay::setPCMDelay(int delay)
2210 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2212 m_decoder->setPCMDelay(delay);
2215 DEFINE_REF(eDVBServicePlay)
2217 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");