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
2020 if (!m_teletext_parser)
2022 eDebug("enable teletext subtitles.. no parser !!!");
2026 // PyTuple_GET_ITEM(tuple, 1); //we dont need pid yet
2027 entry = PyTuple_GET_ITEM(tuple, 2);
2028 if (!PyInt_Check(entry))
2030 page = PyInt_AsLong(entry);
2032 entry = PyTuple_GET_ITEM(tuple, 3);
2033 if (!PyInt_Check(entry))
2035 magazine = PyInt_AsLong(entry);
2037 m_subtitle_widget = new eSubtitleWidget(parent);
2038 m_subtitle_widget->resize(parent->size()); /* full size */
2039 m_teletext_parser->setPageAndMagazine(page, magazine);
2043 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2044 if (!m_subtitle_parser)
2046 eDebug("enable dvb subtitles.. no parser !!!");
2052 entry = PyTuple_GET_ITEM(tuple, 1);
2053 if (!PyInt_Check(entry))
2055 pid = PyInt_AsLong(entry);
2057 entry = PyTuple_GET_ITEM(tuple, 2);
2058 if (!PyInt_Check(entry))
2060 composition_page_id = PyInt_AsLong(entry);
2062 entry = PyTuple_GET_ITEM(tuple, 3);
2063 if (!PyInt_Check(entry))
2065 ancillary_page_id = PyInt_AsLong(entry);
2067 m_subtitle_widget = new eSubtitleWidget(parent);
2068 m_subtitle_widget->resize(parent->size()); /* full size */
2069 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2075 eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2076 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2077 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2081 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2083 delete m_subtitle_widget;
2084 m_subtitle_widget = 0;
2085 if (m_subtitle_parser)
2087 m_subtitle_parser->stop();
2088 m_dvb_subtitle_pages.clear();
2090 if (m_teletext_parser)
2092 m_teletext_parser->setPageAndMagazine(0,0);
2093 m_subtitle_pages.clear();
2098 PyObject *eDVBServicePlay::getSubtitleList()
2100 if (!m_teletext_parser)
2106 PyObject *l = PyList_New(0);
2107 std::set<int> added_ttx_pages;
2109 std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2110 m_teletext_parser->m_found_subtitle_pages;
2112 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2113 eDVBServicePMTHandler::program program;
2114 if (h.getProgramInfo(program))
2115 eDebug("getting program info failed.");
2118 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2119 it != program.subtitleStreams.end(); ++it)
2121 switch(it->subtitling_type)
2123 case 0x01: // ebu teletext subtitles
2125 int page_number = it->teletext_page_number & 0xFF;
2126 int magazine_number = it->teletext_magazine_number & 7;
2127 int hash = magazine_number << 8 | page_number;
2128 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2130 PyObject *tuple = PyTuple_New(5);
2131 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2132 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2133 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2134 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2135 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2136 PyList_Append(l, tuple);
2138 added_ttx_pages.insert(hash);
2143 case 0x20 ... 0x23: // dvb subtitles
2145 PyObject *tuple = PyTuple_New(5);
2146 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2147 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2148 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2149 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2150 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2151 PyList_Insert(l, 0, tuple);
2159 for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2160 it != subs.end(); ++it)
2162 int page_number = it->teletext_page_number & 0xFF;
2163 int magazine_number = it->teletext_magazine_number & 7;
2164 int hash = magazine_number << 8 | page_number;
2165 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2167 PyObject *tuple = PyTuple_New(5);
2168 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2169 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2170 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2171 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2172 PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und")); // undetermined
2173 PyList_Append(l, tuple);
2181 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2183 if (m_subtitle_widget)
2185 m_subtitle_pages.push_back(page);
2186 checkSubtitleTiming();
2190 void eDVBServicePlay::checkSubtitleTiming()
2192 // eDebug("checkSubtitleTiming");
2193 if (!m_subtitle_widget)
2197 enum { TELETEXT, DVB } type;
2198 eDVBTeletextSubtitlePage page;
2199 eDVBSubtitlePage dvb_page;
2201 if (!m_subtitle_pages.empty())
2203 page = m_subtitle_pages.front();
2205 show_time = page.m_pts;
2207 else if (!m_dvb_subtitle_pages.empty())
2209 dvb_page = m_dvb_subtitle_pages.front();
2211 show_time = dvb_page.m_show_time;
2219 m_decoder->getPTS(0, pos);
2221 // eDebug("%lld %lld", pos, show_time);
2222 int diff = show_time - pos;
2225 eDebug("[late (%d ms)]", -diff / 90);
2230 eDebug("[invalid]");
2236 if (type == TELETEXT)
2238 eDebug("display teletext subtitle page");
2239 m_subtitle_widget->setPage(page);
2240 m_subtitle_pages.pop_front();
2244 eDebug("display dvb subtitle Page");
2245 m_subtitle_widget->setPage(dvb_page);
2246 m_dvb_subtitle_pages.pop_front();
2250 // eDebug("start subtitle delay %d", diff / 90);
2251 m_subtitle_sync_timer.start(diff / 90, 1);
2257 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2259 if (m_subtitle_widget)
2261 m_dvb_subtitle_pages.push_back(p);
2262 checkSubtitleTiming();
2266 int eDVBServicePlay::getAC3Delay()
2269 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2271 return m_decoder->getAC3Delay();
2276 int eDVBServicePlay::getPCMDelay()
2279 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2281 return m_decoder->getPCMDelay();
2286 void eDVBServicePlay::setAC3Delay(int delay)
2289 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2291 m_decoder->setAC3Delay(delay);
2294 void eDVBServicePlay::setPCMDelay(int delay)
2297 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2299 m_decoder->setPCMDelay(delay);
2302 DEFINE_REF(eDVBServicePlay)
2304 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");