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 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 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1765 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1766 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1767 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1774 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1775 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1776 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1778 else // subservice or recording
1780 eServiceReferenceDVB ref;
1781 m_service_handler.getServiceReference(ref);
1782 eServiceReferenceDVB parent = ref.getParentServiceReference();
1787 ePtr<eDVBResourceManager> res_mgr;
1788 if (!eDVBResourceManager::getInstance(res_mgr))
1790 ePtr<iDVBChannelList> db;
1791 if (!res_mgr->getChannelList(db))
1793 ePtr<eDVBService> origService;
1794 if (!db->getService(parent, origService))
1796 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1797 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1803 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1804 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1806 m_decoder->setVideoPID(vpid, vpidtype);
1807 m_decoder->setAudioPID(apid, apidtype);
1808 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1810 m_decoder->setSyncPCR(pcrpid);
1813 ePtr<iDVBDemux> data_demux;
1814 if (!h.getDataDemux(data_demux))
1816 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1817 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1818 m_radiotext_parser->start(apid);
1823 m_decoder->setSyncPCR(-1);
1825 m_decoder->setTextPID(tpid);
1827 m_teletext_parser->start(program.textPid);
1830 m_decoder->setTrickmode(1);
1834 if (vpid > 0 && vpid < 0x2000)
1838 std::string radio_pic;
1839 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1840 m_decoder->setRadioPic(radio_pic);
1843 m_decoder->setAudioChannel(achannel);
1845 // how we can do this better?
1846 // update cache pid when the user changed the audio track or video track
1847 // TODO handling of difference audio types.. default audio types..
1849 /* don't worry about non-existing services, nor pvr services */
1850 if (m_dvb_service && !m_is_pvr)
1852 if (apidtype == eDVBAudio::aMPEG)
1854 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1855 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1859 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1860 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1862 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1863 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1864 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1865 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1868 m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1871 void eDVBServicePlay::loadCuesheet()
1873 std::string filename = m_reference.path + ".cuts";
1875 m_cue_entries.clear();
1877 FILE *f = fopen(filename.c_str(), "rb");
1881 eDebug("loading cuts..");
1884 unsigned long long where;
1887 if (!fread(&where, sizeof(where), 1, f))
1889 if (!fread(&what, sizeof(what), 1, f))
1892 #if BYTE_ORDER == LITTLE_ENDIAN
1893 where = bswap_64(where);
1900 m_cue_entries.insert(cueEntry(where, what));
1903 eDebug("%d entries", m_cue_entries.size());
1905 eDebug("cutfile not found!");
1907 m_cuesheet_changed = 0;
1908 cutlistToCuesheet();
1909 m_event((iPlayableService*)this, evCuesheetChanged);
1912 void eDVBServicePlay::saveCuesheet()
1914 std::string filename = m_reference.path + ".cuts";
1916 FILE *f = fopen(filename.c_str(), "wb");
1920 unsigned long long where;
1923 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1925 #if BYTE_ORDER == BIG_ENDIAN
1928 where = bswap_64(i->where);
1930 what = htonl(i->what);
1931 fwrite(&where, sizeof(where), 1, f);
1932 fwrite(&what, sizeof(what), 1, f);
1938 m_cuesheet_changed = 0;
1941 void eDVBServicePlay::cutlistToCuesheet()
1945 eDebug("no cue sheet");
1950 if (!m_cutlist_enabled)
1952 m_cue->commitSpans();
1953 eDebug("cutlists were disabled");
1957 pts_t in = 0, out = 0, length = 0;
1961 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1965 if (i == m_cue_entries.end())
1968 if (i->what == 0) /* in */
1972 } else if (i->what == 1) /* out */
1974 else /* mark (2) or last play position (3) */
1982 m_cue->addSourceSpan(in, out);
1986 if (i == m_cue_entries.end())
1989 m_cue->commitSpans();
1992 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
1994 if (m_subtitle_widget)
1995 disableSubtitles(parent);
1997 PyObject *entry = 0;
1998 int tuplesize = PyTuple_Size(tuple);
2001 if (!PyTuple_Check(tuple))
2007 entry = PyTuple_GET_ITEM(tuple, 0);
2009 if (!PyInt_Check(entry))
2012 type = PyInt_AsLong(entry);
2014 if (type == 1) // teletext subtitles
2016 int page, magazine, pid;
2020 if (!m_teletext_parser)
2022 eDebug("enable teletext subtitles.. no parser !!!");
2026 entry = PyTuple_GET_ITEM(tuple, 1);
2027 if (!PyInt_Check(entry))
2029 pid = PyInt_AsLong(entry);
2031 entry = PyTuple_GET_ITEM(tuple, 2);
2032 if (!PyInt_Check(entry))
2034 page = PyInt_AsLong(entry);
2036 entry = PyTuple_GET_ITEM(tuple, 3);
2037 if (!PyInt_Check(entry))
2039 magazine = PyInt_AsLong(entry);
2041 m_subtitle_widget = new eSubtitleWidget(parent);
2042 m_subtitle_widget->resize(parent->size()); /* full size */
2043 m_teletext_parser->setPageAndMagazine(page, magazine);
2045 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2049 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2050 if (!m_subtitle_parser)
2052 eDebug("enable dvb subtitles.. no parser !!!");
2058 entry = PyTuple_GET_ITEM(tuple, 1);
2059 if (!PyInt_Check(entry))
2061 pid = PyInt_AsLong(entry);
2063 entry = PyTuple_GET_ITEM(tuple, 2);
2064 if (!PyInt_Check(entry))
2066 composition_page_id = PyInt_AsLong(entry);
2068 entry = PyTuple_GET_ITEM(tuple, 3);
2069 if (!PyInt_Check(entry))
2071 ancillary_page_id = PyInt_AsLong(entry);
2073 m_subtitle_widget = new eSubtitleWidget(parent);
2074 m_subtitle_widget->resize(parent->size()); /* full size */
2075 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2077 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2083 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2084 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2085 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2089 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2091 delete m_subtitle_widget;
2092 m_subtitle_widget = 0;
2093 if (m_subtitle_parser)
2095 m_subtitle_parser->stop();
2096 m_dvb_subtitle_pages.clear();
2098 if (m_teletext_parser)
2100 m_teletext_parser->setPageAndMagazine(0,0);
2101 m_subtitle_pages.clear();
2104 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2108 PyObject *eDVBServicePlay::getCachedSubtitle()
2112 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2115 unsigned int data = (unsigned int)tmp;
2116 int pid = (data&0xFFFF0000)>>16;
2117 PyObject *tuple = PyTuple_New(4);
2118 eDVBServicePMTHandler::program program;
2119 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2120 if (!h.getProgramInfo(program))
2122 if (program.textPid==pid) // teletext
2123 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2125 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2126 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2127 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2128 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2137 PyObject *eDVBServicePlay::getSubtitleList()
2139 if (!m_teletext_parser)
2145 PyObject *l = PyList_New(0);
2146 std::set<int> added_ttx_pages;
2148 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2149 m_teletext_parser->m_found_subtitle_pages;
2151 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2152 eDVBServicePMTHandler::program program;
2153 if (h.getProgramInfo(program))
2154 eDebug("getting program info failed.");
2157 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2158 it != program.subtitleStreams.end(); ++it)
2160 switch(it->subtitling_type)
2162 case 0x01: // ebu teletext subtitles
2164 int page_number = it->teletext_page_number & 0xFF;
2165 int magazine_number = it->teletext_magazine_number & 7;
2166 int hash = magazine_number << 8 | page_number;
2167 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2169 PyObject *tuple = PyTuple_New(5);
2170 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2171 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2172 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2173 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2174 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2175 PyList_Append(l, tuple);
2177 added_ttx_pages.insert(hash);
2182 case 0x20 ... 0x23: // dvb subtitles
2184 PyObject *tuple = PyTuple_New(5);
2185 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2186 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2187 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2188 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2189 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2190 PyList_Insert(l, 0, tuple);
2198 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2199 it != subs.end(); ++it)
2201 int page_number = it->teletext_page_number & 0xFF;
2202 int magazine_number = it->teletext_magazine_number & 7;
2203 int hash = magazine_number << 8 | page_number;
2204 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2206 PyObject *tuple = PyTuple_New(5);
2207 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2208 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2209 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2210 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2211 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2212 PyList_Append(l, tuple);
2220 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2222 if (m_subtitle_widget)
2224 m_subtitle_pages.push_back(page);
2225 checkSubtitleTiming();
2229 void eDVBServicePlay::checkSubtitleTiming()
2231 // eDebug("checkSubtitleTiming");
2232 if (!m_subtitle_widget)
2236 enum { TELETEXT, DVB } type;
2237 eDVBTeletextSubtitlePage page;
2238 eDVBSubtitlePage dvb_page;
2240 if (!m_subtitle_pages.empty())
2242 page = m_subtitle_pages.front();
2244 show_time = page.m_pts;
2246 else if (!m_dvb_subtitle_pages.empty())
2248 dvb_page = m_dvb_subtitle_pages.front();
2250 show_time = dvb_page.m_show_time;
2258 m_decoder->getPTS(0, pos);
2260 // eDebug("%lld %lld", pos, show_time);
2261 int diff = show_time - pos;
2264 eDebug("[late (%d ms)]", -diff / 90);
2269 eDebug("[invalid]");
2275 if (type == TELETEXT)
2277 eDebug("display teletext subtitle page");
2278 m_subtitle_widget->setPage(page);
2279 m_subtitle_pages.pop_front();
2283 eDebug("display dvb subtitle Page");
2284 m_subtitle_widget->setPage(dvb_page);
2285 m_dvb_subtitle_pages.pop_front();
2289 // eDebug("start subtitle delay %d", diff / 90);
2290 m_subtitle_sync_timer.start(diff / 90, 1);
2296 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2298 if (m_subtitle_widget)
2300 m_dvb_subtitle_pages.push_back(p);
2301 checkSubtitleTiming();
2305 int eDVBServicePlay::getAC3Delay()
2308 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2310 return m_decoder->getAC3Delay();
2315 int eDVBServicePlay::getPCMDelay()
2318 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2320 return m_decoder->getPCMDelay();
2325 void eDVBServicePlay::setAC3Delay(int delay)
2328 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2330 m_decoder->setAC3Delay(delay);
2333 void eDVBServicePlay::setPCMDelay(int delay)
2336 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2338 m_decoder->setPCMDelay(delay);
2341 DEFINE_REF(eDVBServicePlay)
2343 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");