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>
31 #error no byte order defined!
34 #define TSPATH "/media/hdd"
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
38 DECLARE_REF(eStaticServiceDVBInformation);
40 RESULT getName(const eServiceReference &ref, std::string &name);
41 int getLength(const eServiceReference &ref);
44 DEFINE_REF(eStaticServiceDVBInformation);
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
48 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49 if ( !ref.name.empty() )
51 if (service.getParentTransportStreamID().get()) // linkage subservice
53 ePtr<iServiceHandler> service_center;
54 if (!eServiceCenter::getInstance(service_center))
56 eServiceReferenceDVB parent = service;
57 parent.setTransportStreamID( service.getParentTransportStreamID() );
58 parent.setServiceID( service.getParentServiceID() );
59 parent.setParentTransportStreamID(eTransportStreamID(0));
60 parent.setParentServiceID(eServiceID(0));
62 ePtr<iStaticServiceInformation> service_info;
63 if (!service_center->info(parent, service_info))
65 if (!service_info->getName(parent, name))
67 // just show short name
68 unsigned int pos = name.find("\xc2\x86");
69 if ( pos != std::string::npos )
71 pos = name.find("\xc2\x87");
72 if ( pos != std::string::npos )
88 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
93 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
95 DECLARE_REF(eStaticServiceDVBBouquetInformation);
97 RESULT getName(const eServiceReference &ref, std::string &name);
98 int getLength(const eServiceReference &ref);
101 DEFINE_REF(eStaticServiceDVBBouquetInformation);
103 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
105 ePtr<iDVBChannelList> db;
106 ePtr<eDVBResourceManager> res;
109 if ((err = eDVBResourceManager::getInstance(res)) != 0)
111 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
114 if ((err = res->getChannelList(db)) != 0)
116 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
121 if ((err = db->getBouquet(ref, bouquet)) != 0)
123 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
127 if ( bouquet && bouquet->m_bouquet_name.length() )
129 name = bouquet->m_bouquet_name;
136 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
141 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
143 DECLARE_REF(eStaticServiceDVBPVRInformation);
144 eServiceReference m_ref;
145 eDVBMetaParser m_parser;
147 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
148 RESULT getName(const eServiceReference &ref, std::string &name);
149 int getLength(const eServiceReference &ref);
150 RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
152 int getInfo(const eServiceReference &ref, int w);
153 std::string getInfoString(const eServiceReference &ref,int w);
156 DEFINE_REF(eStaticServiceDVBPVRInformation);
158 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
161 m_parser.parseFile(ref.path);
164 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
166 ASSERT(ref == m_ref);
167 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
171 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
173 ASSERT(ref == m_ref);
177 if (tstools.openFile(ref.path.c_str()))
181 if (tstools.calcLen(len))
187 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
191 case iServiceInformation::sDescription:
192 return iServiceInformation::resIsString;
193 case iServiceInformation::sServiceref:
194 return iServiceInformation::resIsString;
195 case iServiceInformation::sTimeCreate:
196 if (m_parser.m_time_create)
197 return m_parser.m_time_create;
199 return iServiceInformation::resNA;
201 return iServiceInformation::resNA;
205 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
209 case iServiceInformation::sDescription:
210 return m_parser.m_description;
211 case iServiceInformation::sServiceref:
212 return m_parser.m_ref.toString();
213 case iServiceInformation::sTags:
214 return m_parser.m_tags;
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 ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
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 ? (PyObject*)ret : (PyObject*)PyList_New(0);
484 RESULT eDVBServiceList::getNext(eServiceReference &ref)
489 return m_query->getNextResult((eServiceReferenceDVB&)ref);
492 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
494 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
496 ePtr<iDVBChannelList> db;
497 ePtr<eDVBResourceManager> resm;
499 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
502 if (db->getBouquet(m_parent, m_bouquet) != 0)
513 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
517 return m_bouquet->addService(ref, before);
520 RESULT eDVBServiceList::removeService(eServiceReference &ref)
524 return m_bouquet->removeService(ref);
527 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
531 return m_bouquet->moveService(ref, pos);
534 RESULT eDVBServiceList::flushChanges()
538 return m_bouquet->flushChanges();
541 RESULT eDVBServiceList::setListName(const std::string &name)
545 return m_bouquet->setListName(name);
548 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
550 ePtr<eDVBService> service;
551 int r = lookupService(service, ref);
554 // check resources...
555 ptr = new eDVBServicePlay(ref, service);
559 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
561 if (ref.path.empty())
563 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
572 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
574 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
575 if (list->startQuery())
585 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
587 /* is a listable service? */
588 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
590 if ( !ref.name.empty() ) // satellites or providers list
591 ptr = m_StaticServiceDVBInfo;
592 else // a dvb bouquet
593 ptr = m_StaticServiceDVBBouquetInfo;
595 else if (!ref.path.empty()) /* do we have a PVR service? */
596 ptr = new eStaticServiceDVBPVRInformation(ref);
597 else // normal dvb service
599 ePtr<eDVBService> service;
600 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
601 ptr = m_StaticServiceDVBInfo;
603 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
609 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
611 if (ref.path.empty())
617 ptr = new eDVBPVRServiceOfflineOperations(ref);
622 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
624 // TODO: handle the listing itself
625 // if (ref.... == -1) .. return "... bouquets ...";
626 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
628 ePtr<iDVBChannelList> db;
629 ePtr<eDVBResourceManager> res;
632 if ((err = eDVBResourceManager::getInstance(res)) != 0)
634 eDebug("no resource manager");
637 if ((err = res->getChannelList(db)) != 0)
639 eDebug("no channel list");
643 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
644 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
646 eDebug("getService failed!");
653 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
654 m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
657 m_is_pvr = !m_reference.path.empty();
659 m_timeshift_enabled = m_timeshift_active = 0;
662 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
663 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
664 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
666 m_cuesheet_changed = 0;
667 m_cutlist_enabled = 1;
669 m_subtitle_widget = 0;
671 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
674 eDVBServicePlay::~eDVBServicePlay()
676 delete m_subtitle_widget;
679 void eDVBServicePlay::gotNewEvent()
683 ePtr<eServiceEvent> m_event_now, m_event_next;
684 getEvent(m_event_now, 0);
685 getEvent(m_event_next, 1);
688 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
690 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
692 m_event((iPlayableService*)this, evUpdatedEventInfo);
695 void eDVBServicePlay::serviceEvent(int event)
699 case eDVBServicePMTHandler::eventTuned:
701 ePtr<iDVBDemux> m_demux;
702 if (!m_service_handler.getDataDemux(m_demux))
704 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
705 int sid = ref.getParentServiceID().get();
707 sid = ref.getServiceID().get();
708 if ( ref.getParentTransportStreamID().get() &&
709 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
710 m_event_handler.startOther(m_demux, sid);
712 m_event_handler.start(m_demux, sid);
716 case eDVBServicePMTHandler::eventTuneFailed:
718 eDebug("DVB service failed to tune");
719 m_event((iPlayableService*)this, evTuneFailed);
722 case eDVBServicePMTHandler::eventNewProgramInfo:
724 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
725 if (m_timeshift_enabled)
726 updateTimeshiftPids();
727 if (!m_timeshift_active)
729 if (m_first_program_info && m_is_pvr)
731 m_first_program_info = 0;
734 m_event((iPlayableService*)this, evUpdatedInfo);
737 case eDVBServicePMTHandler::eventEOF:
738 m_event((iPlayableService*)this, evEOF);
740 case eDVBServicePMTHandler::eventSOF:
741 m_event((iPlayableService*)this, evSOF);
746 void eDVBServicePlay::serviceEventTimeshift(int event)
750 case eDVBServicePMTHandler::eventNewProgramInfo:
751 if (m_timeshift_active)
754 case eDVBServicePMTHandler::eventSOF:
755 m_event((iPlayableService*)this, evSOF);
757 case eDVBServicePMTHandler::eventEOF:
763 RESULT eDVBServicePlay::start()
766 /* in pvr mode, we only want to use one demux. in tv mode, we're using
767 two (one for decoding, one for data source), as we must be prepared
768 to start recording from the data demux. */
770 m_cue = new eCueSheet();
772 m_first_program_info = 1;
773 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
774 r = m_service_handler.tune(service, m_is_pvr, m_cue);
776 /* inject EIT if there is a stored one */
779 std::string filename = service.path;
780 filename.erase(filename.length()-2, 2);
782 ePtr<eServiceEvent> event = new eServiceEvent;
783 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
785 ePtr<eServiceEvent> empty;
786 m_event_handler.inject(event, 0);
787 m_event_handler.inject(empty, 1);
794 m_event(this, evStart);
795 m_event((iPlayableService*)this, evSeekableStatusChanged);
799 RESULT eDVBServicePlay::stop()
801 /* add bookmark for last play position */
805 if (!getPlayPosition(play_position))
807 /* remove last position */
808 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
810 if (i->what == 3) /* current play position */
812 m_cue_entries.erase(i);
813 i = m_cue_entries.begin();
819 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
820 m_cuesheet_changed = 1;
824 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
826 m_service_handler_timeshift.free();
827 m_service_handler.free();
829 if (m_is_pvr && m_cuesheet_changed)
832 /* save cuesheet only when main file is accessible. */
833 if (!::stat(m_reference.path.c_str(), &s))
840 RESULT eDVBServicePlay::setTarget(int target)
842 m_is_primary = !target;
846 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
848 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
852 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
854 /* note: we check for timeshift to be enabled,
855 not neccessary active. if you pause when timeshift
856 is not active, you should activate it when unpausing */
857 if ((!m_is_pvr) && (!m_timeshift_enabled))
867 RESULT eDVBServicePlay::setSlowMotion(int ratio)
870 return m_decoder->setSlowMotion(ratio);
875 RESULT eDVBServicePlay::setFastForward(int ratio)
877 int skipmode, ffratio;
883 } else if (ratio > 0)
891 } else // if (ratio < 0)
897 if (m_skipmode != skipmode)
899 eDebug("setting cue skipmode to %d", skipmode);
901 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
904 m_skipmode = skipmode;
909 return m_decoder->setFastForward(ffratio);
912 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
914 if (m_is_pvr || m_timeshift_enabled)
924 /* TODO: when timeshift is enabled but not active, this doesn't work. */
925 RESULT eDVBServicePlay::getLength(pts_t &len)
927 ePtr<iDVBPVRChannel> pvr_channel;
929 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
932 return pvr_channel->getLength(len);
935 RESULT eDVBServicePlay::pause()
937 if (!m_is_paused && m_decoder)
940 return m_decoder->freeze(0);
945 RESULT eDVBServicePlay::unpause()
947 if (m_is_paused && m_decoder)
950 return m_decoder->unfreeze();
955 RESULT eDVBServicePlay::seekTo(pts_t to)
957 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
962 ePtr<iDVBPVRChannel> pvr_channel;
964 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
970 m_cue->seekTo(0, to);
974 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
976 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
981 ePtr<iDVBPVRChannel> pvr_channel;
983 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
988 /* HACK until we have skip-AP api */
989 if ((to > 0) && (to < 100))
997 m_cue->seekTo(mode, to);
1001 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1003 ePtr<iDVBPVRChannel> pvr_channel;
1005 if (!m_decode_demux)
1008 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1013 /* if there is a decoder, use audio or video PTS */
1016 r = m_decoder->getPTS(0, pos);
1022 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1025 RESULT eDVBServicePlay::setTrickmode(int trick)
1028 m_decoder->setTrickmode(trick);
1032 RESULT eDVBServicePlay::isCurrentlySeekable()
1034 return m_is_pvr || m_timeshift_active;
1037 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1043 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1049 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1055 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1061 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1067 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1070 if (m_have_video_pid && // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1071 (m_timeshift_enabled || !m_is_pvr))
1073 if (!m_timeshift_enabled)
1075 /* we need enough diskspace */
1077 if (statfs(TSPATH "/.", &fs) < 0)
1079 eDebug("statfs failed!");
1083 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1085 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1095 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1106 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1112 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1118 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1124 RESULT eDVBServicePlay::getName(std::string &name)
1128 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1129 return i->getName(m_reference, name);
1133 m_dvb_service->getName(m_reference, name);
1137 else if (!m_reference.name.empty())
1138 eStaticServiceDVBInformation().getName(m_reference, name);
1140 name = "DVB service";
1144 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1146 return m_event_handler.getEvent(evt, nownext);
1149 int eDVBServicePlay::getInfo(int w)
1151 eDVBServicePMTHandler::program program;
1154 return resIsPyObject;
1156 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1158 if (h.getProgramInfo(program))
1164 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1166 ePtr<eServiceEvent> evt;
1167 if (!m_event_handler.getEvent(evt, 0))
1169 ePtr<eComponentData> data;
1170 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1172 if ( data->getStreamContent() == 1 )
1174 switch(data->getComponentType())
1177 case 1: // 4:3 SD PAL
1179 case 3: // 16:9 SD PAL
1180 case 4: // > 16:9 PAL
1181 case 5: // 4:3 SD NTSC
1183 case 7: // 16:9 SD NTSC
1184 case 8: // > 16:9 NTSC
1187 case 9: // 4:3 HD PAL
1189 case 0xB: // 16:9 HD PAL
1190 case 0xC: // > 16:9 HD PAL
1191 case 0xD: // 4:3 HD NTSC
1193 case 0xF: // 16:9 HD NTSC
1194 case 0x10: // > 16:9 HD PAL
1195 return data->getComponentType();
1202 case sIsCrypted: return program.isCrypted();
1203 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1204 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1205 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1206 case sPCRPID: return program.pcrPid;
1207 case sPMTPID: return program.pmtPid;
1208 case sTXTPID: return program.textPid;
1209 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1210 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1211 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1212 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1213 case sProvider: if (!m_dvb_service) return -1; return -2;
1219 std::string eDVBServicePlay::getInfoString(int w)
1224 if (!m_dvb_service) return "";
1225 return m_dvb_service->m_provider_name;
1229 return iServiceInformation::getInfoString(w);
1232 PyObject *eDVBServicePlay::getInfoObject(int w)
1237 return m_service_handler.getCaIds();
1241 return iServiceInformation::getInfoObject(w);
1244 int eDVBServicePlay::getNumberOfTracks()
1246 eDVBServicePMTHandler::program program;
1247 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1248 if (h.getProgramInfo(program))
1250 return program.audioStreams.size();
1253 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1255 int ret = selectAudioStream(i);
1257 if (m_decoder->start())
1263 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1265 eDVBServicePMTHandler::program program;
1266 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1268 if (h.getProgramInfo(program))
1271 if (i >= program.audioStreams.size())
1274 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1275 info.m_description = "MPEG";
1276 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1277 info.m_description = "AC3";
1278 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1279 info.m_description = "AAC";
1280 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1281 info.m_description = "DTS";
1283 info.m_description = "???";
1285 if (program.audioStreams[i].component_tag != -1)
1287 ePtr<eServiceEvent> evt;
1288 if (!m_event_handler.getEvent(evt, 0))
1290 ePtr<eComponentData> data;
1291 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1292 info.m_language = data->getText();
1296 if (info.m_language.empty())
1297 info.m_language = program.audioStreams[i].language_code;
1302 int eDVBServicePlay::selectAudioStream(int i)
1304 eDVBServicePMTHandler::program program;
1305 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1307 if (h.getProgramInfo(program))
1310 if ((unsigned int)i >= program.audioStreams.size())
1316 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1319 if (m_radiotext_parser)
1320 m_radiotext_parser->start(program.audioStreams[i].pid);
1322 if (m_dvb_service && !m_is_pvr)
1324 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1326 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1327 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1331 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1332 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1336 h.resetCachedProgram();
1341 int eDVBServicePlay::getCurrentChannel()
1343 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1346 RESULT eDVBServicePlay::selectChannel(int i)
1348 if (i < LEFT || i > RIGHT || i == STEREO)
1351 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1353 m_decoder->setAudioChannel(i);
1357 std::string eDVBServicePlay::getRadioText(int x)
1359 if (m_radiotext_parser)
1363 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1368 void eDVBServicePlay::radioTextUpdated()
1370 m_event((iPlayableService*)this, evUpdatedRadioText);
1373 int eDVBServiceBase::getFrontendInfo(int w)
1375 eUsePtr<iDVBChannel> channel;
1376 if(m_service_handler.getChannel(channel))
1378 ePtr<iDVBFrontend> fe;
1379 if(channel->getFrontend(fe))
1381 return fe->readFrontendData(w);
1384 PyObject *eDVBServiceBase::getFrontendData(bool original)
1388 eUsePtr<iDVBChannel> channel;
1389 if(!m_service_handler.getChannel(channel))
1391 ePtr<iDVBFrontend> fe;
1392 if(!channel->getFrontend(fe))
1394 ret = fe->readTransponderData(original);
1397 ePtr<iDVBFrontendParameters> feparm;
1398 channel->getCurrentFrontendParameters(feparm);
1401 eDVBFrontendParametersSatellite osat;
1402 if (!feparm->getDVBS(osat))
1404 void PutToDict(ePyObject &, const char*, long);
1405 void PutToDict(ePyObject &, const char*, const char*);
1406 PutToDict(ret, "orbital_position", osat.orbital_position);
1407 const char *tmp = "UNKNOWN";
1408 switch(osat.polarisation)
1410 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1411 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1412 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1413 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1416 PutToDict(ret, "polarization", tmp);
1430 int eDVBServicePlay::getNumberOfSubservices()
1432 ePtr<eServiceEvent> evt;
1433 if (!m_event_handler.getEvent(evt, 0))
1434 return evt->getNumOfLinkageServices();
1438 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1440 ePtr<eServiceEvent> evt;
1441 if (!m_event_handler.getEvent(evt, 0))
1443 if (!evt->getLinkageService(sub, m_reference, n))
1446 sub.type=eServiceReference::idInvalid;
1450 RESULT eDVBServicePlay::startTimeshift()
1452 ePtr<iDVBDemux> demux;
1454 eDebug("Start timeshift!");
1456 if (m_timeshift_enabled)
1459 /* start recording with the data demux. */
1460 if (m_service_handler.getDataDemux(demux))
1463 demux->createTSRecorder(m_record);
1467 char templ[]=TSPATH "/timeshift.XXXXXX";
1468 m_timeshift_fd = mkstemp(templ);
1469 m_timeshift_file = templ;
1471 eDebug("recording to %s", templ);
1473 if (m_timeshift_fd < 0)
1479 m_record->setTargetFD(m_timeshift_fd);
1481 m_timeshift_enabled = 1;
1483 updateTimeshiftPids();
1489 RESULT eDVBServicePlay::stopTimeshift()
1491 if (!m_timeshift_enabled)
1496 m_timeshift_enabled = 0;
1501 close(m_timeshift_fd);
1502 eDebug("remove timeshift file");
1503 remove(m_timeshift_file.c_str());
1508 int eDVBServicePlay::isTimeshiftActive()
1510 return m_timeshift_enabled && m_timeshift_active;
1513 RESULT eDVBServicePlay::activateTimeshift()
1515 if (!m_timeshift_enabled)
1518 if (!m_timeshift_active)
1520 switchToTimeshift();
1527 PyObject *eDVBServicePlay::getCutList()
1529 ePyObject list = PyList_New(0);
1531 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1533 ePyObject tuple = PyTuple_New(2);
1534 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1535 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1536 PyList_Append(list, tuple);
1543 void eDVBServicePlay::setCutList(ePyObject list)
1545 if (!PyList_Check(list))
1547 int size = PyList_Size(list);
1550 m_cue_entries.clear();
1552 for (i=0; i<size; ++i)
1554 ePyObject tuple = PyList_GET_ITEM(list, i);
1555 if (!PyTuple_Check(tuple))
1557 eDebug("non-tuple in cutlist");
1560 if (PyTuple_Size(tuple) != 2)
1562 eDebug("cutlist entries need to be a 2-tuple");
1565 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1566 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1568 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1571 pts_t pts = PyLong_AsLongLong(ppts);
1572 int type = PyInt_AsLong(ptype);
1573 m_cue_entries.insert(cueEntry(pts, type));
1574 eDebug("adding %08llx, %d", pts, type);
1576 m_cuesheet_changed = 1;
1578 cutlistToCuesheet();
1579 m_event((iPlayableService*)this, evCuesheetChanged);
1582 void eDVBServicePlay::setCutListEnable(int enable)
1584 m_cutlist_enabled = enable;
1585 cutlistToCuesheet();
1588 void eDVBServicePlay::updateTimeshiftPids()
1593 eDVBServicePMTHandler::program program;
1594 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1596 if (h.getProgramInfo(program))
1600 std::set<int> pids_to_record;
1601 pids_to_record.insert(0); // PAT
1602 if (program.pmtPid != -1)
1603 pids_to_record.insert(program.pmtPid); // PMT
1605 if (program.textPid != -1)
1606 pids_to_record.insert(program.textPid); // Videotext
1608 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1609 i(program.videoStreams.begin());
1610 i != program.videoStreams.end(); ++i)
1611 pids_to_record.insert(i->pid);
1613 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1614 i(program.audioStreams.begin());
1615 i != program.audioStreams.end(); ++i)
1616 pids_to_record.insert(i->pid);
1618 std::set<int> new_pids, obsolete_pids;
1620 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1621 m_pids_active.begin(), m_pids_active.end(),
1622 std::inserter(new_pids, new_pids.begin()));
1624 std::set_difference(
1625 m_pids_active.begin(), m_pids_active.end(),
1626 pids_to_record.begin(), pids_to_record.end(),
1627 std::inserter(new_pids, new_pids.begin())
1630 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1631 m_record->addPID(*i);
1633 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1634 m_record->removePID(*i);
1638 void eDVBServicePlay::switchToLive()
1640 if (!m_timeshift_active)
1646 m_teletext_parser = 0;
1647 m_radiotext_parser = 0;
1648 m_subtitle_parser = 0;
1649 m_new_dvb_subtitle_page_connection = 0;
1650 m_new_subtitle_page_connection = 0;
1651 m_radiotext_updated_connection = 0;
1653 /* free the timeshift service handler, we need the resources */
1654 m_service_handler_timeshift.free();
1655 m_timeshift_active = 0;
1657 m_event((iPlayableService*)this, evSeekableStatusChanged);
1662 void eDVBServicePlay::switchToTimeshift()
1664 if (m_timeshift_active)
1669 m_teletext_parser = 0;
1670 m_radiotext_parser = 0;
1671 m_subtitle_parser = 0;
1672 m_new_subtitle_page_connection = 0;
1673 m_new_dvb_subtitle_page_connection = 0;
1674 m_radiotext_updated_connection = 0;
1676 m_timeshift_active = 1;
1678 m_event((iPlayableService*)this, evSeekableStatusChanged);
1680 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1681 r.path = m_timeshift_file;
1683 m_cue = new eCueSheet();
1684 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1685 updateDecoder(); /* mainly to switch off PCR */
1688 void eDVBServicePlay::updateDecoder()
1690 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1692 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1694 bool defaultac3=false;
1695 std::string default_ac3;
1697 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1698 defaultac3 = default_ac3 == "True";
1700 eDVBServicePMTHandler::program program;
1701 if (h.getProgramInfo(program))
1702 eDebug("getting program info failed.");
1705 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1706 if (!program.videoStreams.empty())
1708 eDebugNoNewLine(" (");
1709 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1710 i(program.videoStreams.begin());
1711 i != program.videoStreams.end(); ++i)
1718 if (i != program.videoStreams.begin())
1719 eDebugNoNewLine(", ");
1720 eDebugNoNewLine("%04x", i->pid);
1722 eDebugNoNewLine(")");
1724 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1725 if (!program.audioStreams.empty())
1727 eDebugNoNewLine(" (");
1728 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1729 i(program.audioStreams.begin());
1730 i != program.audioStreams.end(); ++i)
1732 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1734 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1740 if (i != program.audioStreams.begin())
1741 eDebugNoNewLine(", ");
1742 eDebugNoNewLine("%04x", i->pid);
1744 eDebugNoNewLine(")");
1746 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1747 pcrpid = program.pcrPid;
1748 eDebug(", and the text pid is %04x", program.textPid);
1749 tpid = program.textPid;
1754 h.getDecodeDemux(m_decode_demux);
1756 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1758 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1759 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1760 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1761 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1762 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1769 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1770 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1771 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1773 else // subservice or recording
1775 eServiceReferenceDVB ref;
1776 m_service_handler.getServiceReference(ref);
1777 eServiceReferenceDVB parent = ref.getParentServiceReference();
1782 ePtr<eDVBResourceManager> res_mgr;
1783 if (!eDVBResourceManager::getInstance(res_mgr))
1785 ePtr<iDVBChannelList> db;
1786 if (!res_mgr->getChannelList(db))
1788 ePtr<eDVBService> origService;
1789 if (!db->getService(parent, origService))
1791 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1792 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1798 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1799 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1801 m_decoder->setVideoPID(vpid, vpidtype);
1802 m_decoder->setAudioPID(apid, apidtype);
1803 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1805 m_decoder->setSyncPCR(pcrpid);
1808 ePtr<iDVBDemux> data_demux;
1809 if (!h.getDataDemux(data_demux))
1811 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1812 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1813 m_radiotext_parser->start(apid);
1818 m_decoder->setSyncPCR(-1);
1820 m_decoder->setTextPID(tpid);
1822 m_teletext_parser->start(program.textPid);
1825 m_decoder->setTrickmode(1);
1829 if (vpid > 0 && vpid < 0x2000)
1833 std::string radio_pic;
1834 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1835 m_decoder->setRadioPic(radio_pic);
1838 m_decoder->setAudioChannel(achannel);
1840 // how we can do this better?
1841 // update cache pid when the user changed the audio track or video track
1842 // TODO handling of difference audio types.. default audio types..
1844 /* don't worry about non-existing services, nor pvr services */
1845 if (m_dvb_service && !m_is_pvr)
1847 if (apidtype == eDVBAudio::aMPEG)
1849 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1850 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1854 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1855 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1857 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1858 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1859 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1860 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1863 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1866 void eDVBServicePlay::loadCuesheet()
1868 std::string filename = m_reference.path + ".cuts";
1870 m_cue_entries.clear();
1872 FILE *f = fopen(filename.c_str(), "rb");
1876 eDebug("loading cuts..");
1879 unsigned long long where;
1882 if (!fread(&where, sizeof(where), 1, f))
1884 if (!fread(&what, sizeof(what), 1, f))
1887 #if BYTE_ORDER == LITTLE_ENDIAN
1888 where = bswap_64(where);
1895 m_cue_entries.insert(cueEntry(where, what));
1898 eDebug("%d entries", m_cue_entries.size());
1900 eDebug("cutfile not found!");
1902 m_cuesheet_changed = 0;
1903 cutlistToCuesheet();
1904 m_event((iPlayableService*)this, evCuesheetChanged);
1907 void eDVBServicePlay::saveCuesheet()
1909 std::string filename = m_reference.path + ".cuts";
1911 FILE *f = fopen(filename.c_str(), "wb");
1915 unsigned long long where;
1918 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1920 #if BYTE_ORDER == BIG_ENDIAN
1923 where = bswap_64(i->where);
1925 what = htonl(i->what);
1926 fwrite(&where, sizeof(where), 1, f);
1927 fwrite(&what, sizeof(what), 1, f);
1933 m_cuesheet_changed = 0;
1936 void eDVBServicePlay::cutlistToCuesheet()
1940 eDebug("no cue sheet");
1945 if (!m_cutlist_enabled)
1947 m_cue->commitSpans();
1948 eDebug("cutlists were disabled");
1952 pts_t in = 0, out = 0, length = 0;
1956 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1960 if (i == m_cue_entries.end())
1963 if (i->what == 0) /* in */
1967 } else if (i->what == 1) /* out */
1969 else /* mark (2) or last play position (3) */
1977 m_cue->addSourceSpan(in, out);
1981 if (i == m_cue_entries.end())
1984 m_cue->commitSpans();
1987 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
1989 if (m_subtitle_widget)
1990 disableSubtitles(parent);
1993 int tuplesize = PyTuple_Size(tuple);
1996 if (!PyTuple_Check(tuple))
2002 entry = PyTuple_GET_ITEM(tuple, 0);
2004 if (!PyInt_Check(entry))
2007 type = PyInt_AsLong(entry);
2009 if (type == 1) // teletext subtitles
2011 int page, magazine, pid;
2015 if (!m_teletext_parser)
2017 eDebug("enable teletext subtitles.. no parser !!!");
2021 entry = PyTuple_GET_ITEM(tuple, 1);
2022 if (!PyInt_Check(entry))
2024 pid = PyInt_AsLong(entry);
2026 entry = PyTuple_GET_ITEM(tuple, 2);
2027 if (!PyInt_Check(entry))
2029 page = PyInt_AsLong(entry);
2031 entry = PyTuple_GET_ITEM(tuple, 3);
2032 if (!PyInt_Check(entry))
2034 magazine = PyInt_AsLong(entry);
2036 m_subtitle_widget = new eSubtitleWidget(parent);
2037 m_subtitle_widget->resize(parent->size()); /* full size */
2038 m_teletext_parser->setPageAndMagazine(page, magazine);
2040 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2044 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2045 if (!m_subtitle_parser)
2047 eDebug("enable dvb subtitles.. no parser !!!");
2053 entry = PyTuple_GET_ITEM(tuple, 1);
2054 if (!PyInt_Check(entry))
2056 pid = PyInt_AsLong(entry);
2058 entry = PyTuple_GET_ITEM(tuple, 2);
2059 if (!PyInt_Check(entry))
2061 composition_page_id = PyInt_AsLong(entry);
2063 entry = PyTuple_GET_ITEM(tuple, 3);
2064 if (!PyInt_Check(entry))
2066 ancillary_page_id = PyInt_AsLong(entry);
2068 m_subtitle_widget = new eSubtitleWidget(parent);
2069 m_subtitle_widget->resize(parent->size()); /* full size */
2070 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2072 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2078 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2079 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2080 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2084 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2086 delete m_subtitle_widget;
2087 m_subtitle_widget = 0;
2088 if (m_subtitle_parser)
2090 m_subtitle_parser->stop();
2091 m_dvb_subtitle_pages.clear();
2093 if (m_teletext_parser)
2095 m_teletext_parser->setPageAndMagazine(-1, -1);
2096 m_subtitle_pages.clear();
2099 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2103 PyObject *eDVBServicePlay::getCachedSubtitle()
2107 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2110 unsigned int data = (unsigned int)tmp;
2111 int pid = (data&0xFFFF0000)>>16;
2112 ePyObject tuple = PyTuple_New(4);
2113 eDVBServicePMTHandler::program program;
2114 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2115 if (!h.getProgramInfo(program))
2117 if (program.textPid==pid) // teletext
2118 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2120 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2121 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2122 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2123 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2132 PyObject *eDVBServicePlay::getSubtitleList()
2134 if (!m_teletext_parser)
2140 ePyObject l = PyList_New(0);
2141 std::set<int> added_ttx_pages;
2143 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2144 m_teletext_parser->m_found_subtitle_pages;
2146 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2147 eDVBServicePMTHandler::program program;
2148 if (h.getProgramInfo(program))
2149 eDebug("getting program info failed.");
2152 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2153 it != program.subtitleStreams.end(); ++it)
2155 switch(it->subtitling_type)
2157 case 0x01: // ebu teletext subtitles
2159 int page_number = it->teletext_page_number & 0xFF;
2160 int magazine_number = it->teletext_magazine_number & 7;
2161 int hash = magazine_number << 8 | page_number;
2162 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2164 ePyObject tuple = PyTuple_New(5);
2165 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2166 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2167 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2168 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2169 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2170 PyList_Append(l, tuple);
2172 added_ttx_pages.insert(hash);
2177 case 0x20 ... 0x23: // dvb subtitles
2179 ePyObject tuple = PyTuple_New(5);
2180 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2181 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2182 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2183 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2184 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2185 PyList_Insert(l, 0, tuple);
2193 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2194 it != subs.end(); ++it)
2196 int page_number = it->teletext_page_number & 0xFF;
2197 int magazine_number = it->teletext_magazine_number & 7;
2198 int hash = magazine_number << 8 | page_number;
2199 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2201 ePyObject tuple = PyTuple_New(5);
2202 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2203 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2204 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2205 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2206 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2207 PyList_Append(l, tuple);
2215 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2217 if (m_subtitle_widget)
2219 m_subtitle_pages.push_back(page);
2220 checkSubtitleTiming();
2224 void eDVBServicePlay::checkSubtitleTiming()
2226 // eDebug("checkSubtitleTiming");
2227 if (!m_subtitle_widget)
2231 enum { TELETEXT, DVB } type;
2232 eDVBTeletextSubtitlePage page;
2233 eDVBSubtitlePage dvb_page;
2235 if (!m_subtitle_pages.empty())
2237 page = m_subtitle_pages.front();
2239 show_time = page.m_pts;
2241 else if (!m_dvb_subtitle_pages.empty())
2243 dvb_page = m_dvb_subtitle_pages.front();
2245 show_time = dvb_page.m_show_time;
2253 m_decoder->getPTS(0, pos);
2255 // eDebug("%lld %lld", pos, show_time);
2256 int diff = show_time - pos;
2259 eDebug("[late (%d ms)]", -diff / 90);
2264 eDebug("[invalid]");
2270 if (type == TELETEXT)
2272 eDebug("display teletext subtitle page");
2273 m_subtitle_widget->setPage(page);
2274 m_subtitle_pages.pop_front();
2278 eDebug("display dvb subtitle Page");
2279 m_subtitle_widget->setPage(dvb_page);
2280 m_dvb_subtitle_pages.pop_front();
2284 // eDebug("start subtitle delay %d", diff / 90);
2285 m_subtitle_sync_timer.start(diff / 90, 1);
2291 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2293 if (m_subtitle_widget)
2295 m_dvb_subtitle_pages.push_back(p);
2296 checkSubtitleTiming();
2300 int eDVBServicePlay::getAC3Delay()
2303 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2305 return m_decoder->getAC3Delay();
2310 int eDVBServicePlay::getPCMDelay()
2313 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2315 return m_decoder->getPCMDelay();
2320 void eDVBServicePlay::setAC3Delay(int delay)
2323 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2325 m_decoder->setAC3Delay(delay);
2328 void eDVBServicePlay::setPCMDelay(int delay)
2331 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2333 m_decoder->setPCMDelay(delay);
2336 DEFINE_REF(eDVBServicePlay)
2338 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");