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/init_num.h>
7 #include <lib/base/init.h>
8 #include <lib/base/nconfig.h> // access to python config
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
21 #include <lib/gui/esubtitle.h>
26 #include <netinet/in.h>
28 #include <dvbsi++/event_information_section.h>
30 #define INTERNAL_TELETEXT
33 #error no byte order defined!
36 #define TSPATH "/media/hdd"
38 class eStaticServiceDVBInformation: public iStaticServiceInformation
40 DECLARE_REF(eStaticServiceDVBInformation);
42 RESULT getName(const eServiceReference &ref, std::string &name);
43 int getLength(const eServiceReference &ref);
46 DEFINE_REF(eStaticServiceDVBInformation);
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
50 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51 if ( !ref.name.empty() )
53 if (service.getParentTransportStreamID().get()) // linkage subservice
55 ePtr<iServiceHandler> service_center;
56 if (!eServiceCenter::getInstance(service_center))
58 eServiceReferenceDVB parent = service;
59 parent.setTransportStreamID( service.getParentTransportStreamID() );
60 parent.setServiceID( service.getParentServiceID() );
61 parent.setParentTransportStreamID(eTransportStreamID(0));
62 parent.setParentServiceID(eServiceID(0));
64 ePtr<iStaticServiceInformation> service_info;
65 if (!service_center->info(parent, service_info))
67 if (!service_info->getName(parent, name))
69 // just show short name
70 unsigned int pos = name.find("\xc2\x86");
71 if ( pos != std::string::npos )
73 pos = name.find("\xc2\x87");
74 if ( pos != std::string::npos )
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
95 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
97 DECLARE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT getName(const eServiceReference &ref, std::string &name);
100 int getLength(const eServiceReference &ref);
103 DEFINE_REF(eStaticServiceDVBBouquetInformation);
105 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
107 ePtr<iDVBChannelList> db;
108 ePtr<eDVBResourceManager> res;
111 if ((err = eDVBResourceManager::getInstance(res)) != 0)
113 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
116 if ((err = res->getChannelList(db)) != 0)
118 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
123 if ((err = db->getBouquet(ref, bouquet)) != 0)
125 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
129 if ( bouquet && bouquet->m_bouquet_name.length() )
131 name = bouquet->m_bouquet_name;
138 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
143 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
145 DECLARE_REF(eStaticServiceDVBPVRInformation);
146 eServiceReference m_ref;
147 eDVBMetaParser m_parser;
149 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
150 RESULT getName(const eServiceReference &ref, std::string &name);
151 int getLength(const eServiceReference &ref);
153 int getInfo(const eServiceReference &ref, int w);
154 std::string getInfoString(const eServiceReference &ref,int w);
157 DEFINE_REF(eStaticServiceDVBPVRInformation);
159 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
162 m_parser.parseFile(ref.path);
165 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
167 ASSERT(ref == m_ref);
168 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
172 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
174 ASSERT(ref == m_ref);
178 if (tstools.openFile(ref.path.c_str()))
182 if (tstools.calcLen(len))
188 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
192 case iServiceInformation::sDescription:
193 return iServiceInformation::resIsString;
194 case iServiceInformation::sServiceref:
195 return iServiceInformation::resIsString;
196 case iServiceInformation::sTimeCreate:
197 if (m_parser.m_time_create)
198 return m_parser.m_time_create;
200 return iServiceInformation::resNA;
202 return iServiceInformation::resNA;
206 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
210 case iServiceInformation::sDescription:
211 return m_parser.m_description;
212 case iServiceInformation::sServiceref:
213 return m_parser.m_ref.toString();
219 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
221 DECLARE_REF(eDVBPVRServiceOfflineOperations);
222 eServiceReferenceDVB m_ref;
224 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
226 RESULT deleteFromDisk(int simulate);
227 RESULT getListOfFilenames(std::list<std::string> &);
230 DEFINE_REF(eDVBPVRServiceOfflineOperations);
232 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
236 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
242 std::list<std::string> res;
243 if (getListOfFilenames(res))
246 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
248 eDebug("FATAL !! can't get background file eraser");
250 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
252 eDebug("Removing %s...", i->c_str());
254 eraser->erase(i->c_str());
256 ::unlink(i->c_str());
263 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
266 res.push_back(m_ref.path);
268 // handling for old splitted recordings (enigma 1)
273 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
275 if (stat(buf, &s) < 0)
280 res.push_back(m_ref.path + ".meta");
281 res.push_back(m_ref.path + ".ap");
282 res.push_back(m_ref.path + ".cuts");
283 std::string tmp = m_ref.path;
284 tmp.erase(m_ref.path.length()-3);
285 res.push_back(tmp + ".eit");
289 DEFINE_REF(eServiceFactoryDVB)
291 eServiceFactoryDVB::eServiceFactoryDVB()
293 ePtr<eServiceCenter> sc;
295 eServiceCenter::getPrivInstance(sc);
297 sc->addServiceFactory(eServiceFactoryDVB::id, this);
300 eServiceFactoryDVB::~eServiceFactoryDVB()
302 ePtr<eServiceCenter> sc;
304 eServiceCenter::getPrivInstance(sc);
306 sc->removeServiceFactory(eServiceFactoryDVB::id);
309 DEFINE_REF(eDVBServiceList);
311 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
315 eDVBServiceList::~eDVBServiceList()
319 RESULT eDVBServiceList::startQuery()
321 ePtr<iDVBChannelList> db;
322 ePtr<eDVBResourceManager> res;
325 if ((err = eDVBResourceManager::getInstance(res)) != 0)
327 eDebug("no resource manager");
330 if ((err = res->getChannelList(db)) != 0)
332 eDebug("no channel list");
336 ePtr<eDVBChannelQuery> q;
338 if (!m_parent.path.empty())
340 eDVBChannelQuery::compile(q, m_parent.path);
343 eDebug("compile query failed");
348 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
350 eDebug("startQuery failed");
357 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
359 eServiceReferenceDVB ref;
364 while (!m_query->getNextResult(ref))
368 list.sort(iListableServiceCompare(this));
373 // The first argument of this function is a format string to specify the order and
374 // the content of the returned list
375 // useable format options are
376 // R = Service Reference (as swig object .. this is very slow)
377 // S = Service Reference (as python string object .. same as ref.toString())
378 // N = Service Name (as python string object)
379 // when exactly one return value per service is selected in the format string,
380 // then each value is directly a list entry
381 // when more than one value is returned per service, then the list is a list of
383 // unknown format string chars are returned as python None values !
384 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
387 std::list<eServiceReference> tmplist;
390 if (!format || !(retcount=strlen(format)))
391 format = "R"; // just return service reference swig object ...
393 if (!getContent(tmplist, sorted))
395 int services=tmplist.size();
396 ePtr<iStaticServiceInformation> sptr;
397 eServiceCenterPtr service_center;
399 if (strchr(format, 'N'))
400 eServiceCenter::getPrivInstance(service_center);
402 ret = PyList_New(services);
403 std::list<eServiceReference>::iterator it(tmplist.begin());
405 for (int cnt=0; cnt < services; ++cnt)
407 eServiceReference &ref=*it++;
408 PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
409 for (int i=0; i < retcount; ++i)
414 case 'R': // service reference (swig)object
415 tmp = New_eServiceReference(ref);
417 case 'S': // service reference string
418 tmp = PyString_FromString(ref.toString().c_str());
420 case 'N': // service name
423 service_center->info(ref, sptr);
427 sptr->getName(ref, name);
429 tmp = PyString_FromString(name.c_str());
433 tmp = PyString_FromString("<n/a>");
446 PyTuple_SET_ITEM(tuple, i, tmp);
448 PyList_SET_ITEM(ret, cnt, tmp);
452 PyList_SET_ITEM(ret, cnt, tuple);
455 return ret ? ret : PyList_New(0);
458 RESULT eDVBServiceList::getNext(eServiceReference &ref)
463 return m_query->getNextResult((eServiceReferenceDVB&)ref);
466 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
468 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
471 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
473 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
475 ePtr<iDVBChannelList> db;
476 ePtr<eDVBResourceManager> resm;
478 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
481 if (db->getBouquet(m_parent, m_bouquet) != 0)
492 RESULT eDVBServiceList::addService(eServiceReference &ref)
496 return m_bouquet->addService(ref);
499 RESULT eDVBServiceList::removeService(eServiceReference &ref)
503 return m_bouquet->removeService(ref);
506 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
510 return m_bouquet->moveService(ref, pos);
513 RESULT eDVBServiceList::flushChanges()
517 return m_bouquet->flushChanges();
520 RESULT eDVBServiceList::setListName(const std::string &name)
524 return m_bouquet->setListName(name);
527 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
529 ePtr<eDVBService> service;
530 int r = lookupService(service, ref);
533 // check resources...
534 ptr = new eDVBServicePlay(ref, service);
538 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
540 if (ref.path.empty())
542 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
551 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
553 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
554 if (list->startQuery())
564 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
566 /* is a listable service? */
567 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
569 if ( !ref.name.empty() ) // satellites or providers list
570 ptr = new eStaticServiceDVBInformation;
571 else // a dvb bouquet
572 ptr = new eStaticServiceDVBBouquetInformation;
574 else if (!ref.path.empty()) /* do we have a PVR service? */
575 ptr = new eStaticServiceDVBPVRInformation(ref);
576 else // normal dvb service
578 ePtr<eDVBService> service;
579 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
580 ptr = new eStaticServiceDVBInformation;
582 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
588 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
590 if (ref.path.empty())
596 ptr = new eDVBPVRServiceOfflineOperations(ref);
601 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
603 // TODO: handle the listing itself
604 // if (ref.... == -1) .. return "... bouquets ...";
605 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
607 ePtr<iDVBChannelList> db;
608 ePtr<eDVBResourceManager> res;
611 if ((err = eDVBResourceManager::getInstance(res)) != 0)
613 eDebug("no resource manager");
616 if ((err = res->getChannelList(db)) != 0)
618 eDebug("no channel list");
622 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
623 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
625 eDebug("getService failed!");
632 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
633 m_reference(ref), m_dvb_service(service), m_is_paused(0)
636 m_is_pvr = !m_reference.path.empty();
638 m_timeshift_enabled = m_timeshift_active = 0;
641 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
642 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
643 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
645 m_cuesheet_changed = 0;
646 m_cutlist_enabled = 1;
648 m_subtitle_widget = 0;
650 CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
653 eDVBServicePlay::~eDVBServicePlay()
655 delete m_subtitle_widget;
658 void eDVBServicePlay::gotNewEvent()
662 ePtr<eServiceEvent> m_event_now, m_event_next;
663 getEvent(m_event_now, 0);
664 getEvent(m_event_next, 1);
667 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
669 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
671 m_event((iPlayableService*)this, evUpdatedEventInfo);
674 void eDVBServicePlay::serviceEvent(int event)
678 case eDVBServicePMTHandler::eventTuned:
680 ePtr<iDVBDemux> m_demux;
681 if (!m_service_handler.getDataDemux(m_demux))
683 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
684 int sid = ref.getParentServiceID().get();
686 sid = ref.getServiceID().get();
687 if ( ref.getParentTransportStreamID().get() &&
688 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
689 m_event_handler.startOther(m_demux, sid);
691 m_event_handler.start(m_demux, sid);
695 case eDVBServicePMTHandler::eventTuneFailed:
697 eDebug("DVB service failed to tune");
698 m_event((iPlayableService*)this, evTuneFailed);
701 case eDVBServicePMTHandler::eventNewProgramInfo:
703 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
704 if (m_timeshift_enabled)
705 updateTimeshiftPids();
706 if (!m_timeshift_active)
708 if (m_first_program_info && m_is_pvr)
710 m_first_program_info = 0;
713 m_event((iPlayableService*)this, evUpdatedInfo);
716 case eDVBServicePMTHandler::eventEOF:
717 m_event((iPlayableService*)this, evEOF);
719 case eDVBServicePMTHandler::eventSOF:
720 m_event((iPlayableService*)this, evSOF);
725 void eDVBServicePlay::serviceEventTimeshift(int event)
729 case eDVBServicePMTHandler::eventNewProgramInfo:
730 if (m_timeshift_active)
733 case eDVBServicePMTHandler::eventSOF:
734 m_event((iPlayableService*)this, evSOF);
736 case eDVBServicePMTHandler::eventEOF:
742 RESULT eDVBServicePlay::start()
745 /* in pvr mode, we only want to use one demux. in tv mode, we're using
746 two (one for decoding, one for data source), as we must be prepared
747 to start recording from the data demux. */
749 m_cue = new eCueSheet();
751 m_first_program_info = 1;
752 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
753 r = m_service_handler.tune(service, m_is_pvr, m_cue);
755 /* inject EIT if there is a stored one */
758 std::string filename = service.path;
759 filename.erase(filename.length()-2, 2);
761 int fd = ::open( filename.c_str(), O_RDONLY );
765 int rd = ::read(fd, buf, 4096);
767 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
770 ePtr<eServiceEvent> event = new eServiceEvent;
771 ePtr<eServiceEvent> empty;
772 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
773 m_event_handler.inject(event, 0);
774 m_event_handler.inject(empty, 1);
783 m_event(this, evStart);
784 m_event((iPlayableService*)this, evSeekableStatusChanged);
788 RESULT eDVBServicePlay::stop()
790 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
792 m_service_handler_timeshift.free();
793 m_service_handler.free();
795 if (m_is_pvr && m_cuesheet_changed)
801 RESULT eDVBServicePlay::setTarget(int target)
803 m_is_primary = !target;
807 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
809 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
813 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
815 /* note: we check for timeshift to be enabled,
816 not neccessary active. if you pause when timeshift
817 is not active, you should activate it when unpausing */
818 if ((!m_is_pvr) && (!m_timeshift_enabled))
828 RESULT eDVBServicePlay::setSlowMotion(int ratio)
831 return m_decoder->setSlowMotion(ratio);
836 RESULT eDVBServicePlay::setFastForward(int ratio)
838 int skipmode, ffratio;
844 } else if (ratio > 0)
852 } else // if (ratio < 0)
858 if (m_skipmode != skipmode)
860 eDebug("setting cue skipmode to %d", skipmode);
862 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
865 m_skipmode = skipmode;
870 return m_decoder->setFastForward(ffratio);
873 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
875 if (m_is_pvr || m_timeshift_enabled)
885 /* TODO: when timeshift is enabled but not active, this doesn't work. */
886 RESULT eDVBServicePlay::getLength(pts_t &len)
888 ePtr<iDVBPVRChannel> pvr_channel;
890 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
893 return pvr_channel->getLength(len);
896 RESULT eDVBServicePlay::pause()
898 if (!m_is_paused && m_decoder)
901 return m_decoder->freeze(0);
906 RESULT eDVBServicePlay::unpause()
908 if (m_is_paused && m_decoder)
911 return m_decoder->unfreeze();
916 RESULT eDVBServicePlay::seekTo(pts_t to)
918 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
923 ePtr<iDVBPVRChannel> pvr_channel;
925 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
931 m_cue->seekTo(0, to);
935 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
937 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
942 ePtr<iDVBPVRChannel> pvr_channel;
944 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
949 /* HACK until we have skip-AP api */
950 if ((to > 0) && (to < 100))
958 m_cue->seekTo(mode, to);
962 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
964 ePtr<iDVBPVRChannel> pvr_channel;
969 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
974 /* if there is a decoder, use audio or video PTS */
977 r = m_decoder->getPTS(0, pos);
983 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
986 RESULT eDVBServicePlay::setTrickmode(int trick)
989 m_decoder->setTrickmode(trick);
993 RESULT eDVBServicePlay::isCurrentlySeekable()
995 return m_is_pvr || m_timeshift_active;
998 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1004 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1010 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1016 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1022 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1028 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1031 if (m_timeshift_enabled || !m_is_pvr)
1033 if (!m_timeshift_enabled)
1035 /* we need enough diskspace */
1037 if (statfs(TSPATH "/.", &fs) < 0)
1039 eDebug("statfs failed!");
1043 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1045 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1055 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1066 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1072 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1078 RESULT eDVBServicePlay::getName(std::string &name)
1082 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1083 return i->getName(m_reference, name);
1087 m_dvb_service->getName(m_reference, name);
1091 else if (!m_reference.name.empty())
1092 eStaticServiceDVBInformation().getName(m_reference, name);
1094 name = "DVB service";
1098 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1100 return m_event_handler.getEvent(evt, nownext);
1103 int eDVBServicePlay::getInfo(int w)
1105 eDVBServicePMTHandler::program program;
1108 return resIsPyObject;
1110 if (m_service_handler.getProgramInfo(program))
1116 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1118 ePtr<eServiceEvent> evt;
1119 if (!m_event_handler.getEvent(evt, 0))
1121 ePtr<eComponentData> data;
1122 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1124 if ( data->getStreamContent() == 1 )
1126 switch(data->getComponentType())
1129 case 1: // 4:3 SD PAL
1131 case 3: // 16:9 SD PAL
1132 case 4: // > 16:9 PAL
1133 case 5: // 4:3 SD NTSC
1135 case 7: // 16:9 SD NTSC
1136 case 8: // > 16:9 NTSC
1139 case 9: // 4:3 HD PAL
1141 case 0xB: // 16:9 HD PAL
1142 case 0xC: // > 16:9 HD PAL
1143 case 0xD: // 4:3 HD NTSC
1145 case 0xF: // 16:9 HD NTSC
1146 case 0x10: // > 16:9 HD PAL
1147 return data->getComponentType();
1154 case sIsCrypted: return program.isCrypted();
1155 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1156 case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1157 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1158 case sPCRPID: return program.pcrPid;
1159 case sPMTPID: return program.pmtPid;
1160 case sTXTPID: return program.textPid;
1161 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1162 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1163 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1164 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1165 case sProvider: if (!m_dvb_service) return -1; return -2;
1171 std::string eDVBServicePlay::getInfoString(int w)
1176 if (!m_dvb_service) return "";
1177 return m_dvb_service->m_provider_name;
1181 return iServiceInformation::getInfoString(w);
1184 PyObject *eDVBServicePlay::getInfoObject(int w)
1189 return m_service_handler.getCaIds();
1193 return iServiceInformation::getInfoObject(w);
1196 int eDVBServicePlay::getNumberOfTracks()
1198 eDVBServicePMTHandler::program program;
1199 if (m_service_handler.getProgramInfo(program))
1201 return program.audioStreams.size();
1204 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1206 int ret = selectAudioStream(i);
1208 if (m_decoder->start())
1214 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1216 eDVBServicePMTHandler::program program;
1218 if (m_service_handler.getProgramInfo(program))
1221 if (i >= program.audioStreams.size())
1224 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1225 info.m_description = "MPEG";
1226 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1227 info.m_description = "AC3";
1228 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1229 info.m_description = "AAC";
1230 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1231 info.m_description = "DTS";
1233 info.m_description = "???";
1235 if (program.audioStreams[i].component_tag != -1)
1237 ePtr<eServiceEvent> evt;
1238 if (!m_event_handler.getEvent(evt, 0))
1240 ePtr<eComponentData> data;
1241 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1242 info.m_language = data->getText();
1246 if (info.m_language.empty())
1247 info.m_language = program.audioStreams[i].language_code;
1252 int eDVBServicePlay::selectAudioStream(int i)
1254 eDVBServicePMTHandler::program program;
1256 if (m_service_handler.getProgramInfo(program))
1259 if ((unsigned int)i >= program.audioStreams.size())
1265 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1268 if (m_dvb_service && !m_is_pvr)
1270 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1272 m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1273 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1276 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1277 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1281 m_current_audio_stream = i;
1286 int eDVBServicePlay::getCurrentChannel()
1288 return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1291 RESULT eDVBServicePlay::selectChannel(int i)
1293 if (i < LEFT || i > RIGHT || i == STEREO)
1296 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1298 m_decoder->setAudioChannel(i);
1302 int eDVBServiceBase::getFrontendInfo(int w)
1304 eUsePtr<iDVBChannel> channel;
1305 if(m_service_handler.getChannel(channel))
1307 ePtr<iDVBFrontend> fe;
1308 if(channel->getFrontend(fe))
1310 return fe->readFrontendData(w);
1313 PyObject *eDVBServiceBase::getFrontendData(bool original)
1317 eUsePtr<iDVBChannel> channel;
1318 if(!m_service_handler.getChannel(channel))
1320 ePtr<iDVBFrontend> fe;
1321 if(!channel->getFrontend(fe))
1323 ret = fe->readTransponderData(original);
1326 ePtr<iDVBFrontendParameters> feparm;
1327 channel->getCurrentFrontendParameters(feparm);
1330 eDVBFrontendParametersSatellite osat;
1331 if (!feparm->getDVBS(osat))
1333 void PutToDict(PyObject *, const char*, long);
1334 void PutToDict(PyObject *, const char*, const char*);
1335 PutToDict(ret, "orbital_position", osat.orbital_position);
1336 const char *tmp = "UNKNOWN";
1337 switch(osat.polarisation)
1339 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1340 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1341 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1342 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1345 PutToDict(ret, "polarization", tmp);
1359 int eDVBServicePlay::getNumberOfSubservices()
1361 ePtr<eServiceEvent> evt;
1362 if (!m_event_handler.getEvent(evt, 0))
1363 return evt->getNumOfLinkageServices();
1367 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1369 ePtr<eServiceEvent> evt;
1370 if (!m_event_handler.getEvent(evt, 0))
1372 if (!evt->getLinkageService(sub, m_reference, n))
1375 sub.type=eServiceReference::idInvalid;
1379 RESULT eDVBServicePlay::startTimeshift()
1381 ePtr<iDVBDemux> demux;
1383 eDebug("Start timeshift!");
1385 if (m_timeshift_enabled)
1388 /* start recording with the data demux. */
1389 if (m_service_handler.getDataDemux(demux))
1392 demux->createTSRecorder(m_record);
1396 char templ[]=TSPATH "/timeshift.XXXXXX";
1397 m_timeshift_fd = mkstemp(templ);
1398 m_timeshift_file = templ;
1400 eDebug("recording to %s", templ);
1402 if (m_timeshift_fd < 0)
1408 m_record->setTargetFD(m_timeshift_fd);
1410 m_timeshift_enabled = 1;
1412 updateTimeshiftPids();
1418 RESULT eDVBServicePlay::stopTimeshift()
1420 if (!m_timeshift_enabled)
1425 m_timeshift_enabled = 0;
1430 close(m_timeshift_fd);
1431 eDebug("remove timeshift file");
1432 remove(m_timeshift_file.c_str());
1437 int eDVBServicePlay::isTimeshiftActive()
1439 return m_timeshift_enabled && m_timeshift_active;
1442 RESULT eDVBServicePlay::activateTimeshift()
1444 if (!m_timeshift_enabled)
1447 if (!m_timeshift_active)
1449 switchToTimeshift();
1456 PyObject *eDVBServicePlay::getCutList()
1458 PyObject *list = PyList_New(0);
1460 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1462 PyObject *tuple = PyTuple_New(2);
1463 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1464 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1465 PyList_Append(list, tuple);
1472 void eDVBServicePlay::setCutList(PyObject *list)
1474 if (!PyList_Check(list))
1476 int size = PyList_Size(list);
1479 m_cue_entries.clear();
1481 for (i=0; i<size; ++i)
1483 PyObject *tuple = PyList_GetItem(list, i);
1484 if (!PyTuple_Check(tuple))
1486 eDebug("non-tuple in cutlist");
1489 if (PyTuple_Size(tuple) != 2)
1491 eDebug("cutlist entries need to be a 2-tuple");
1494 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1495 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1497 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1500 pts_t pts = PyLong_AsLongLong(ppts);
1501 int type = PyInt_AsLong(ptype);
1502 m_cue_entries.insert(cueEntry(pts, type));
1503 eDebug("adding %08llx, %d", pts, type);
1505 m_cuesheet_changed = 1;
1507 cutlistToCuesheet();
1508 m_event((iPlayableService*)this, evCuesheetChanged);
1511 void eDVBServicePlay::setCutListEnable(int enable)
1513 m_cutlist_enabled = enable;
1514 cutlistToCuesheet();
1517 void eDVBServicePlay::updateTimeshiftPids()
1522 eDVBServicePMTHandler::program program;
1523 if (m_service_handler.getProgramInfo(program))
1527 std::set<int> pids_to_record;
1528 pids_to_record.insert(0); // PAT
1529 if (program.pmtPid != -1)
1530 pids_to_record.insert(program.pmtPid); // PMT
1532 if (program.textPid != -1)
1533 pids_to_record.insert(program.textPid); // Videotext
1535 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1536 i(program.videoStreams.begin());
1537 i != program.videoStreams.end(); ++i)
1538 pids_to_record.insert(i->pid);
1540 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1541 i(program.audioStreams.begin());
1542 i != program.audioStreams.end(); ++i)
1543 pids_to_record.insert(i->pid);
1545 std::set<int> new_pids, obsolete_pids;
1547 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1548 m_pids_active.begin(), m_pids_active.end(),
1549 std::inserter(new_pids, new_pids.begin()));
1551 std::set_difference(
1552 m_pids_active.begin(), m_pids_active.end(),
1553 pids_to_record.begin(), pids_to_record.end(),
1554 std::inserter(new_pids, new_pids.begin())
1557 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1558 m_record->addPID(*i);
1560 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1561 m_record->removePID(*i);
1565 void eDVBServicePlay::switchToLive()
1567 if (!m_timeshift_active)
1573 m_teletext_parser = 0;
1574 m_new_subtitle_page_connection = 0;
1576 /* free the timeshift service handler, we need the resources */
1577 m_service_handler_timeshift.free();
1578 m_timeshift_active = 0;
1580 m_event((iPlayableService*)this, evSeekableStatusChanged);
1585 void eDVBServicePlay::switchToTimeshift()
1587 if (m_timeshift_active)
1592 m_teletext_parser = 0;
1593 m_new_subtitle_page_connection = 0;
1595 m_timeshift_active = 1;
1597 m_event((iPlayableService*)this, evSeekableStatusChanged);
1599 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1600 r.path = m_timeshift_file;
1602 m_cue = new eCueSheet();
1603 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1604 updateDecoder(); /* mainly to switch off PCR */
1607 void eDVBServicePlay::updateDecoder()
1609 int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1611 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1613 bool defaultac3=false;
1614 std::string default_ac3;
1616 if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1617 defaultac3 = default_ac3 == "enable";
1619 eDVBServicePMTHandler::program program;
1620 if (h.getProgramInfo(program))
1621 eDebug("getting program info failed.");
1624 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1625 if (!program.videoStreams.empty())
1627 eDebugNoNewLine(" (");
1628 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1629 i(program.videoStreams.begin());
1630 i != program.videoStreams.end(); ++i)
1637 if (i != program.videoStreams.begin())
1638 eDebugNoNewLine(", ");
1639 eDebugNoNewLine("%04x", i->pid);
1641 eDebugNoNewLine(")");
1643 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1644 if (!program.audioStreams.empty())
1646 eDebugNoNewLine(" (");
1647 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1648 i(program.audioStreams.begin());
1649 i != program.audioStreams.end(); ++i)
1651 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1653 if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1659 if (i != program.audioStreams.begin())
1660 eDebugNoNewLine(", ");
1661 eDebugNoNewLine("%04x", i->pid);
1663 eDebugNoNewLine(")");
1665 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1666 pcrpid = program.pcrPid;
1667 eDebug(", and the text pid is %04x", program.textPid);
1668 tpid = program.textPid;
1673 h.getDecodeDemux(m_decode_demux);
1675 m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1677 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1678 #ifdef INTERNAL_TELETEXT
1679 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1680 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1688 achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1689 ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1690 pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1693 else if (m_reference.path.length()) // workaround for recordings
1695 eDebug("playback %s", m_reference.toString().c_str());
1697 ePtr<eDVBResourceManager> res_mgr;
1698 if (!eDVBResourceManager::getInstance(res_mgr))
1700 ePtr<iDVBChannelList> db;
1701 if (!res_mgr->getChannelList(db))
1703 ePtr<eDVBService> origService;
1704 eServiceReference tmp = m_reference;
1706 if (!db->getService((eServiceReferenceDVB&)tmp, origService))
1708 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1709 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1716 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1717 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1719 m_decoder->setVideoPID(vpid, vpidtype);
1720 m_current_audio_stream = 0;
1721 m_decoder->setAudioPID(apid, apidtype);
1722 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1723 m_decoder->setSyncPCR(pcrpid);
1725 m_decoder->setSyncPCR(-1);
1727 m_decoder->setTextPID(tpid);
1729 if (m_teletext_parser)
1730 m_teletext_parser->start(tpid);
1733 m_decoder->setTrickmode(1);
1737 if (vpid > 0 && vpid < 0x2000)
1741 std::string radio_pic;
1742 if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1743 m_decoder->setRadioPic(radio_pic);
1746 m_decoder->setAudioChannel(achannel);
1748 // how we can do this better?
1749 // update cache pid when the user changed the audio track or video track
1750 // TODO handling of difference audio types.. default audio types..
1752 /* don't worry about non-existing services, nor pvr services */
1753 if (m_dvb_service && !m_is_pvr)
1755 if (apidtype == eDVBAudio::aMPEG)
1757 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1758 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1762 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1763 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1765 m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1766 m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1767 m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1768 m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1773 void eDVBServicePlay::loadCuesheet()
1775 std::string filename = m_reference.path + ".cuts";
1777 m_cue_entries.clear();
1779 FILE *f = fopen(filename.c_str(), "rb");
1783 eDebug("loading cuts..");
1786 unsigned long long where;
1789 if (!fread(&where, sizeof(where), 1, f))
1791 if (!fread(&what, sizeof(what), 1, f))
1794 #if BYTE_ORDER == LITTLE_ENDIAN
1795 where = bswap_64(where);
1802 m_cue_entries.insert(cueEntry(where, what));
1805 eDebug("%d entries", m_cue_entries.size());
1807 eDebug("cutfile not found!");
1809 m_cuesheet_changed = 0;
1810 cutlistToCuesheet();
1811 m_event((iPlayableService*)this, evCuesheetChanged);
1814 void eDVBServicePlay::saveCuesheet()
1816 std::string filename = m_reference.path + ".cuts";
1818 FILE *f = fopen(filename.c_str(), "wb");
1822 unsigned long long where;
1825 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1827 #if BYTE_ORDER == BIG_ENDIAN
1830 where = bswap_64(i->where);
1832 what = htonl(i->what);
1833 fwrite(&where, sizeof(where), 1, f);
1834 fwrite(&what, sizeof(what), 1, f);
1840 m_cuesheet_changed = 0;
1843 void eDVBServicePlay::cutlistToCuesheet()
1847 eDebug("no cue sheet");
1852 if (!m_cutlist_enabled)
1854 m_cue->commitSpans();
1855 eDebug("cutlists where disabled");
1859 pts_t in = 0, out = 0, length = 0;
1863 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1867 if (i == m_cue_entries.end())
1870 if (i->what == 0) /* in */
1874 } else if (i->what == 1) /* out */
1884 m_cue->addSourceSpan(in, out);
1888 if (i == m_cue_entries.end())
1891 m_cue->commitSpans();
1894 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1896 if (m_subtitle_widget)
1897 disableSubtitles(parent);
1899 if (!m_teletext_parser)
1902 if (!PyInt_Check(entry))
1905 m_subtitle_widget = new eSubtitleWidget(parent);
1906 m_subtitle_widget->resize(parent->size()); /* full size */
1908 int page = PyInt_AsLong(entry);
1910 m_teletext_parser->setPage(page);
1915 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1917 delete m_subtitle_widget;
1918 m_subtitle_widget = 0;
1922 PyObject *eDVBServicePlay::getSubtitleList()
1924 if (!m_teletext_parser)
1930 PyObject *l = PyList_New(0);
1932 for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1934 PyObject *tuple = PyTuple_New(2);
1936 sprintf(desc, "Page %x", *i);
1937 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1938 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1939 PyList_Append(l, tuple);
1945 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1947 if (m_subtitle_widget)
1949 m_subtitle_pages.push_back(page);
1951 checkSubtitleTiming();
1955 void eDVBServicePlay::checkSubtitleTiming()
1959 if (m_subtitle_pages.empty())
1962 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1967 m_decoder->getPTS(0, pos);
1969 int diff = p.m_pts - pos;
1972 eDebug("[late (%d ms)]", -diff / 90);
1977 eDebug("[invalid]");
1983 m_subtitle_widget->setPage(p);
1984 m_subtitle_pages.pop_front();
1987 m_subtitle_sync_timer.start(diff / 90, 1);
1993 int eDVBServicePlay::getAC3Delay()
1996 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1998 return m_decoder->getAC3Delay();
2003 int eDVBServicePlay::getPCMDelay()
2006 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2008 return m_decoder->getPCMDelay();
2013 void eDVBServicePlay::setAC3Delay(int delay)
2016 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2018 m_decoder->setAC3Delay(delay);
2021 void eDVBServicePlay::setPCMDelay(int delay)
2024 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2026 m_decoder->setPCMDelay(delay);
2029 DEFINE_REF(eDVBServicePlay)
2031 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");