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>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
13 #include <lib/service/servicedvbrecord.h>
14 #include <lib/service/event.h>
15 #include <lib/dvb/metaparser.h>
16 #include <lib/dvb/tstools.h>
17 #include <lib/python/python.h>
22 #include <netinet/in.h>
24 #include <dvbsi++/event_information_section.h>
27 #error no byte order defined!
30 #define TSPATH "/media/hdd"
32 class eStaticServiceDVBInformation: public iStaticServiceInformation
34 DECLARE_REF(eStaticServiceDVBInformation);
36 RESULT getName(const eServiceReference &ref, std::string &name);
37 int getLength(const eServiceReference &ref);
40 DEFINE_REF(eStaticServiceDVBInformation);
42 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
44 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
45 if ( !ref.name.empty() )
47 if (service.getParentTransportStreamID().get()) // linkage subservice
49 ePtr<iServiceHandler> service_center;
50 if (!eServiceCenter::getInstance(service_center))
52 eServiceReferenceDVB parent = service;
53 parent.setTransportStreamID( service.getParentTransportStreamID() );
54 parent.setServiceID( service.getParentServiceID() );
55 parent.setParentTransportStreamID(eTransportStreamID(0));
56 parent.setParentServiceID(eServiceID(0));
58 ePtr<iStaticServiceInformation> service_info;
59 if (!service_center->info(parent, service_info))
61 if (!service_info->getName(parent, name))
63 // just show short name
64 unsigned int pos = name.find("\xc2\x86");
65 if ( pos != std::string::npos )
67 pos = name.find("\xc2\x87");
68 if ( pos != std::string::npos )
84 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
89 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
91 DECLARE_REF(eStaticServiceDVBBouquetInformation);
93 RESULT getName(const eServiceReference &ref, std::string &name);
94 int getLength(const eServiceReference &ref);
97 DEFINE_REF(eStaticServiceDVBBouquetInformation);
99 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
101 ePtr<iDVBChannelList> db;
102 ePtr<eDVBResourceManager> res;
105 if ((err = eDVBResourceManager::getInstance(res)) != 0)
107 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
110 if ((err = res->getChannelList(db)) != 0)
112 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
117 if ((err = db->getBouquet(ref, bouquet)) != 0)
119 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
123 if ( bouquet && bouquet->m_bouquet_name.length() )
125 name = bouquet->m_bouquet_name;
132 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
137 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
139 DECLARE_REF(eStaticServiceDVBPVRInformation);
140 eServiceReference m_ref;
141 eDVBMetaParser m_parser;
143 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
144 RESULT getName(const eServiceReference &ref, std::string &name);
145 int getLength(const eServiceReference &ref);
147 int getInfo(const eServiceReference &ref, int w);
148 std::string getInfoString(const eServiceReference &ref,int w);
151 DEFINE_REF(eStaticServiceDVBPVRInformation);
153 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
156 m_parser.parseFile(ref.path);
159 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
161 ASSERT(ref == m_ref);
162 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
166 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
168 ASSERT(ref == m_ref);
172 if (tstools.openFile(ref.path.c_str()))
176 if (tstools.calcLen(len))
182 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
186 case iServiceInformation::sDescription:
187 return iServiceInformation::resIsString;
188 case iServiceInformation::sTimeCreate:
189 if (m_parser.m_time_create)
190 return m_parser.m_time_create;
192 return iServiceInformation::resNA;
194 return iServiceInformation::resNA;
198 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
202 case iServiceInformation::sDescription:
203 return m_parser.m_description;
209 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
211 DECLARE_REF(eDVBPVRServiceOfflineOperations);
212 eServiceReferenceDVB m_ref;
214 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
216 RESULT deleteFromDisk(int simulate);
217 RESULT getListOfFilenames(std::list<std::string> &);
220 DEFINE_REF(eDVBPVRServiceOfflineOperations);
222 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
226 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
232 std::list<std::string> res;
233 if (getListOfFilenames(res))
236 /* TODO: deferred removing.. */
237 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
239 eDebug("Removing %s...", i->c_str());
240 ::unlink(i->c_str());
247 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
250 res.push_back(m_ref.path);
251 res.push_back(m_ref.path + ".meta");
252 res.push_back(m_ref.path + ".ap");
253 res.push_back(m_ref.path + ".cuts");
254 res.push_back(m_ref.path + ".eit");
258 DEFINE_REF(eServiceFactoryDVB)
260 eServiceFactoryDVB::eServiceFactoryDVB()
262 ePtr<eServiceCenter> sc;
264 eServiceCenter::getPrivInstance(sc);
266 sc->addServiceFactory(eServiceFactoryDVB::id, this);
269 eServiceFactoryDVB::~eServiceFactoryDVB()
271 ePtr<eServiceCenter> sc;
273 eServiceCenter::getPrivInstance(sc);
275 sc->removeServiceFactory(eServiceFactoryDVB::id);
278 DEFINE_REF(eDVBServiceList);
280 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
284 eDVBServiceList::~eDVBServiceList()
288 RESULT eDVBServiceList::startQuery()
290 ePtr<iDVBChannelList> db;
291 ePtr<eDVBResourceManager> res;
294 if ((err = eDVBResourceManager::getInstance(res)) != 0)
296 eDebug("no resource manager");
299 if ((err = res->getChannelList(db)) != 0)
301 eDebug("no channel list");
305 ePtr<eDVBChannelQuery> q;
307 if (!m_parent.path.empty())
309 eDVBChannelQuery::compile(q, m_parent.path);
312 eDebug("compile query failed");
317 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
319 eDebug("startQuery failed");
326 RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
328 eServiceReferenceDVB ref;
330 if (!m_query || !list || !PyList_Check(list))
333 std::list<eServiceReferenceDVB> tmplist;
335 while (!m_query->getNextResult(ref))
336 tmplist.push_back(ref);
339 tmplist.sort(iListableServiceCompare(this));
341 for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
342 it != tmplist.end(); ++it)
344 PyObject *refobj = New_eServiceReference(*it);
345 PyList_Append(list, refobj);
351 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
353 eServiceReferenceDVB ref;
358 while (!m_query->getNextResult(ref))
362 list.sort(iListableServiceCompare(this));
367 RESULT eDVBServiceList::getNext(eServiceReference &ref)
372 return m_query->getNextResult((eServiceReferenceDVB&)ref);
375 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
377 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
380 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
382 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
384 ePtr<iDVBChannelList> db;
385 ePtr<eDVBResourceManager> resm;
387 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
390 if (db->getBouquet(m_parent, m_bouquet) != 0)
401 RESULT eDVBServiceList::addService(eServiceReference &ref)
405 return m_bouquet->addService(ref);
408 RESULT eDVBServiceList::removeService(eServiceReference &ref)
412 return m_bouquet->removeService(ref);
415 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
419 return m_bouquet->moveService(ref, pos);
422 RESULT eDVBServiceList::flushChanges()
426 return m_bouquet->flushChanges();
429 RESULT eDVBServiceList::setListName(const std::string &name)
433 return m_bouquet->setListName(name);
436 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
438 ePtr<eDVBService> service;
439 int r = lookupService(service, ref);
442 // check resources...
443 ptr = new eDVBServicePlay(ref, service);
447 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
449 if (ref.path.empty())
451 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
460 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
462 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
463 if (list->startQuery())
473 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
475 /* is a listable service? */
476 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
478 if ( !ref.name.empty() ) // satellites or providers list
479 ptr = new eStaticServiceDVBInformation;
480 else // a dvb bouquet
481 ptr = new eStaticServiceDVBBouquetInformation;
483 else if (!ref.path.empty()) /* do we have a PVR service? */
484 ptr = new eStaticServiceDVBPVRInformation(ref);
485 else // normal dvb service
487 ePtr<eDVBService> service;
488 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
489 ptr = new eStaticServiceDVBInformation;
491 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
497 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
499 if (ref.path.empty())
505 ptr = new eDVBPVRServiceOfflineOperations(ref);
510 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
512 // TODO: handle the listing itself
513 // if (ref.... == -1) .. return "... bouquets ...";
514 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
516 ePtr<iDVBChannelList> db;
517 ePtr<eDVBResourceManager> res;
520 if ((err = eDVBResourceManager::getInstance(res)) != 0)
522 eDebug("no resource manager");
525 if ((err = res->getChannelList(db)) != 0)
527 eDebug("no channel list");
531 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
532 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
534 eDebug("getService failed!");
541 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
542 m_reference(ref), m_dvb_service(service), m_is_paused(0)
544 m_is_pvr = !ref.path.empty();
546 m_timeshift_enabled = m_timeshift_active = 0;
549 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
550 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
551 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
553 m_cuesheet_changed = 0;
554 m_cutlist_enabled = 1;
557 eDVBServicePlay::~eDVBServicePlay()
561 void eDVBServicePlay::gotNewEvent()
565 ePtr<eServiceEvent> m_event_now, m_event_next;
566 getEvent(m_event_now, 0);
567 getEvent(m_event_next, 1);
570 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
572 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
574 m_event((iPlayableService*)this, evUpdatedEventInfo);
577 void eDVBServicePlay::serviceEvent(int event)
581 case eDVBServicePMTHandler::eventTuned:
583 ePtr<iDVBDemux> m_demux;
584 if (!m_service_handler.getDataDemux(m_demux))
586 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
587 int sid = ref.getParentServiceID().get();
589 sid = ref.getServiceID().get();
590 if ( ref.getParentTransportStreamID().get() &&
591 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
592 m_event_handler.startOther(m_demux, sid);
594 m_event_handler.start(m_demux, sid);
598 case eDVBServicePMTHandler::eventTuneFailed:
600 eDebug("DVB service failed to tune");
601 m_event((iPlayableService*)this, evTuneFailed);
604 case eDVBServicePMTHandler::eventNewProgramInfo:
606 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
607 if (m_timeshift_enabled)
608 updateTimeshiftPids();
609 if (!m_timeshift_active)
611 if (m_first_program_info && m_is_pvr)
613 m_first_program_info = 0;
616 m_event((iPlayableService*)this, evUpdatedInfo);
619 case eDVBServicePMTHandler::eventEOF:
620 m_event((iPlayableService*)this, evEOF);
622 case eDVBServicePMTHandler::eventSOF:
623 m_event((iPlayableService*)this, evSOF);
628 void eDVBServicePlay::serviceEventTimeshift(int event)
632 case eDVBServicePMTHandler::eventNewProgramInfo:
633 if (m_timeshift_active)
636 case eDVBServicePMTHandler::eventEOF:
642 RESULT eDVBServicePlay::start()
645 /* in pvr mode, we only want to use one demux. in tv mode, we're using
646 two (one for decoding, one for data source), as we must be prepared
647 to start recording from the data demux. */
648 m_cue = new eCueSheet();
650 m_first_program_info = 1;
651 eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
652 r = m_service_handler.tune(service, m_is_pvr, m_cue);
654 /* inject EIT if there is a stored one */
657 std::string filename = service.path;
658 filename.erase(filename.length()-2, 2);
660 int fd = ::open( filename.c_str(), O_RDONLY );
664 int rd = ::read(fd, buf, 4096);
666 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
669 ePtr<eServiceEvent> event = new eServiceEvent;
670 ePtr<eServiceEvent> empty;
671 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
672 m_event_handler.inject(event, 0);
673 m_event_handler.inject(empty, 1);
682 m_event(this, evStart);
683 m_event((iPlayableService*)this, evSeekableStatusChanged);
687 RESULT eDVBServicePlay::stop()
689 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
691 m_service_handler_timeshift.free();
692 m_service_handler.free();
694 if (m_is_pvr && m_cuesheet_changed)
700 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
702 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
706 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
708 /* note: we check for timeshift to be enabled,
709 not neccessary active. if you pause when timeshift
710 is not active, you should activate it when unpausing */
711 if ((!m_is_pvr) && (!m_timeshift_enabled))
721 RESULT eDVBServicePlay::setSlowMotion(int ratio)
724 return m_decoder->setSlowMotion(ratio);
729 RESULT eDVBServicePlay::setFastForward(int ratio)
731 int skipmode, ffratio;
737 } else if (ratio > 0)
745 } else // if (ratio < 0)
751 if (m_skipmode != skipmode)
753 eDebug("setting cue skipmode to %d", skipmode);
755 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
758 m_skipmode = skipmode;
763 return m_decoder->setFastForward(ffratio);
766 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
768 if (m_is_pvr || m_timeshift_enabled)
778 /* TODO: when timeshift is enabled but not active, this doesn't work. */
779 RESULT eDVBServicePlay::getLength(pts_t &len)
781 ePtr<iDVBPVRChannel> pvr_channel;
783 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
786 return pvr_channel->getLength(len);
789 RESULT eDVBServicePlay::pause()
791 if (!m_is_paused && m_decoder)
794 return m_decoder->freeze(0);
799 RESULT eDVBServicePlay::unpause()
801 if (m_is_paused && m_decoder)
804 return m_decoder->unfreeze();
809 RESULT eDVBServicePlay::seekTo(pts_t to)
811 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
816 ePtr<iDVBPVRChannel> pvr_channel;
818 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
824 m_cue->seekTo(0, to);
828 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
830 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
835 ePtr<iDVBPVRChannel> pvr_channel;
837 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
842 /* HACK until we have skip-AP api */
843 if ((to > 0) && (to < 100))
851 m_cue->seekTo(mode, to);
855 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
857 ePtr<iDVBPVRChannel> pvr_channel;
862 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
867 /* if there is a decoder, use audio or video PTS */
870 r = m_decoder->getPTS(0, pos);
876 return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
879 RESULT eDVBServicePlay::setTrickmode(int trick)
882 m_decoder->setTrickmode(trick);
886 RESULT eDVBServicePlay::isCurrentlySeekable()
888 return m_is_pvr || m_timeshift_active;
891 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
897 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
903 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
909 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
915 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
918 if (m_timeshift_enabled || !m_is_pvr)
920 if (!m_timeshift_enabled)
922 /* we need enough diskspace */
924 if (statfs(TSPATH "/.", &fs) < 0)
926 eDebug("statfs failed!");
930 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
932 eDebug("not enough diskspace for timeshift! (less than 1GB)");
942 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
953 RESULT eDVBServicePlay::getName(std::string &name)
957 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
958 return i->getName(m_reference, name);
962 m_dvb_service->getName(m_reference, name);
966 else if (!m_reference.name.empty())
967 eStaticServiceDVBInformation().getName(m_reference, name);
969 name = "DVB service";
973 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
975 return m_event_handler.getEvent(evt, nownext);
978 int eDVBServicePlay::getInfo(int w)
980 eDVBServicePMTHandler::program program;
982 if (m_service_handler.getProgramInfo(program))
988 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
990 ePtr<eServiceEvent> evt;
991 if (!m_event_handler.getEvent(evt, 0))
993 ePtr<eComponentData> data;
994 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
996 if ( data->getStreamContent() == 1 )
998 switch(data->getComponentType())
1001 case 1: // 4:3 SD PAL
1003 case 3: // 16:9 SD PAL
1004 case 4: // > 16:9 PAL
1005 case 5: // 4:3 SD NTSC
1007 case 7: // 16:9 SD NTSC
1008 case 8: // > 16:9 NTSC
1011 case 9: // 4:3 HD PAL
1013 case 0xB: // 16:9 HD PAL
1014 case 0xC: // > 16:9 HD PAL
1015 case 0xD: // 4:3 HD NTSC
1017 case 0xF: // 16:9 HD NTSC
1018 case 0x10: // > 16:9 HD PAL
1019 return data->getComponentType();
1026 case sIsCrypted: return program.isCrypted;
1027 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1028 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1029 case sPCRPID: return program.pcrPid;
1030 case sPMTPID: return program.pmtPid;
1031 case sTXTPID: return program.textPid;
1032 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1033 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1034 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1035 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1036 case sProvider: if (!m_dvb_service) return -1; return -2;
1042 std::string eDVBServicePlay::getInfoString(int w)
1047 if (!m_dvb_service) return "";
1048 return m_dvb_service->m_provider_name;
1054 int eDVBServicePlay::getNumberOfTracks()
1056 eDVBServicePMTHandler::program program;
1057 if (m_service_handler.getProgramInfo(program))
1059 return program.audioStreams.size();
1062 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1064 int ret = selectAudioStream(i);
1066 if (m_decoder->start())
1072 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1074 eDVBServicePMTHandler::program program;
1076 if (m_service_handler.getProgramInfo(program))
1079 if (i >= program.audioStreams.size())
1082 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1083 info.m_description = "MPEG";
1084 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1085 info.m_description = "AC3";
1086 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1087 info.m_description = "DTS";
1089 info.m_description = "???";
1091 if (program.audioStreams[i].component_tag != -1)
1093 ePtr<eServiceEvent> evt;
1094 if (!m_event_handler.getEvent(evt, 0))
1096 ePtr<eComponentData> data;
1097 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1098 info.m_language = data->getText();
1102 if (info.m_language.empty())
1103 info.m_language = program.audioStreams[i].language_code;
1108 int eDVBServicePlay::selectAudioStream(int i)
1110 eDVBServicePMTHandler::program program;
1112 if (m_service_handler.getProgramInfo(program))
1115 if ((unsigned int)i >= program.audioStreams.size())
1121 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1124 if (m_dvb_service && !m_is_pvr)
1126 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1128 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1129 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1132 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1133 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1137 m_current_audio_stream = i;
1142 int eDVBServicePlay::getFrontendInfo(int w)
1146 eUsePtr<iDVBChannel> channel;
1147 if(m_service_handler.getChannel(channel))
1149 ePtr<iDVBFrontend> fe;
1150 if(channel->getFrontend(fe))
1152 return fe->readFrontendData(w);
1155 PyObject *eDVBServicePlay::getFrontendData(bool original)
1159 eUsePtr<iDVBChannel> channel;
1160 if(!m_service_handler.getChannel(channel))
1162 ePtr<iDVBFrontend> fe;
1163 if(!channel->getFrontend(fe))
1165 ret = fe->readTransponderData(original);
1168 ePtr<iDVBFrontendParameters> feparm;
1169 channel->getCurrentFrontendParameters(feparm);
1172 eDVBFrontendParametersSatellite osat;
1173 if (!feparm->getDVBS(osat))
1175 void PutToDict(PyObject *, const char*, const char*);
1176 PutToDict(ret, "orbital_position", osat.orbital_position);
1177 const char *tmp = "UNKNOWN";
1178 switch(osat.polarisation)
1180 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1181 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1182 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1183 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1186 PutToDict(ret, "polarization", tmp);
1200 int eDVBServicePlay::getNumberOfSubservices()
1202 ePtr<eServiceEvent> evt;
1203 if (!m_event_handler.getEvent(evt, 0))
1204 return evt->getNumOfLinkageServices();
1208 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1210 ePtr<eServiceEvent> evt;
1211 if (!m_event_handler.getEvent(evt, 0))
1213 if (!evt->getLinkageService(sub, m_reference, n))
1216 sub.type=eServiceReference::idInvalid;
1220 RESULT eDVBServicePlay::startTimeshift()
1222 ePtr<iDVBDemux> demux;
1224 eDebug("Start timeshift!");
1226 if (m_timeshift_enabled)
1229 /* start recording with the data demux. */
1230 if (m_service_handler.getDataDemux(demux))
1233 demux->createTSRecorder(m_record);
1237 char templ[]=TSPATH "/timeshift.XXXXXX";
1238 m_timeshift_fd = mkstemp(templ);
1239 m_timeshift_file = templ;
1241 eDebug("recording to %s", templ);
1243 if (m_timeshift_fd < 0)
1249 m_record->setTargetFD(m_timeshift_fd);
1251 m_timeshift_enabled = 1;
1253 updateTimeshiftPids();
1259 RESULT eDVBServicePlay::stopTimeshift()
1261 if (!m_timeshift_enabled)
1266 m_timeshift_enabled = 0;
1271 close(m_timeshift_fd);
1272 eDebug("remove timeshift file");
1273 remove(m_timeshift_file.c_str());
1278 int eDVBServicePlay::isTimeshiftActive()
1280 return m_timeshift_enabled && m_timeshift_active;
1283 RESULT eDVBServicePlay::activateTimeshift()
1285 if (!m_timeshift_enabled)
1288 if (!m_timeshift_active)
1290 switchToTimeshift();
1297 PyObject *eDVBServicePlay::getCutList()
1299 PyObject *list = PyList_New(0);
1301 for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1303 PyObject *tuple = PyTuple_New(2);
1304 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1305 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1306 PyList_Append(list, tuple);
1313 void eDVBServicePlay::setCutList(PyObject *list)
1315 if (!PyList_Check(list))
1317 int size = PyList_Size(list);
1320 m_cue_entries.clear();
1322 for (i=0; i<size; ++i)
1324 PyObject *tuple = PyList_GetItem(list, i);
1325 if (!PyTuple_Check(tuple))
1327 eDebug("non-tuple in cutlist");
1330 if (PyTuple_Size(tuple) != 2)
1332 eDebug("cutlist entries need to be a 2-tuple");
1335 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1336 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1338 eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1341 pts_t pts = PyLong_AsLongLong(ppts);
1342 int type = PyInt_AsLong(ptype);
1343 m_cue_entries.insert(cueEntry(pts, type));
1344 eDebug("adding %08llx, %d", pts, type);
1346 m_cuesheet_changed = 1;
1348 cutlistToCuesheet();
1349 m_event((iPlayableService*)this, evCuesheetChanged);
1352 void eDVBServicePlay::setCutListEnable(int enable)
1354 m_cutlist_enabled = enable;
1355 cutlistToCuesheet();
1358 void eDVBServicePlay::updateTimeshiftPids()
1363 eDVBServicePMTHandler::program program;
1364 if (m_service_handler.getProgramInfo(program))
1368 std::set<int> pids_to_record;
1369 pids_to_record.insert(0); // PAT
1370 if (program.pmtPid != -1)
1371 pids_to_record.insert(program.pmtPid); // PMT
1373 if (program.textPid != -1)
1374 pids_to_record.insert(program.textPid); // Videotext
1376 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1377 i(program.videoStreams.begin());
1378 i != program.videoStreams.end(); ++i)
1379 pids_to_record.insert(i->pid);
1381 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1382 i(program.audioStreams.begin());
1383 i != program.audioStreams.end(); ++i)
1384 pids_to_record.insert(i->pid);
1386 std::set<int> new_pids, obsolete_pids;
1388 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1389 m_pids_active.begin(), m_pids_active.end(),
1390 std::inserter(new_pids, new_pids.begin()));
1392 std::set_difference(
1393 m_pids_active.begin(), m_pids_active.end(),
1394 pids_to_record.begin(), pids_to_record.end(),
1395 std::inserter(new_pids, new_pids.begin())
1398 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1399 m_record->addPID(*i);
1401 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1402 m_record->removePID(*i);
1406 void eDVBServicePlay::switchToLive()
1408 if (!m_timeshift_active)
1413 /* free the timeshift service handler, we need the resources */
1414 m_service_handler_timeshift.free();
1415 m_timeshift_active = 0;
1417 m_event((iPlayableService*)this, evSeekableStatusChanged);
1422 void eDVBServicePlay::switchToTimeshift()
1424 if (m_timeshift_active)
1430 m_timeshift_active = 1;
1432 m_event((iPlayableService*)this, evSeekableStatusChanged);
1434 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1435 r.path = m_timeshift_file;
1437 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1440 void eDVBServicePlay::updateDecoder()
1442 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1443 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1445 eDVBServicePMTHandler::program program;
1446 if (h.getProgramInfo(program))
1447 eDebug("getting program info failed.");
1450 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1451 if (!program.videoStreams.empty())
1453 eDebugNoNewLine(" (");
1454 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1455 i(program.videoStreams.begin());
1456 i != program.videoStreams.end(); ++i)
1460 if (i != program.videoStreams.begin())
1461 eDebugNoNewLine(", ");
1462 eDebugNoNewLine("%04x", i->pid);
1464 eDebugNoNewLine(")");
1466 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1467 if (!program.audioStreams.empty())
1469 eDebugNoNewLine(" (");
1470 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1471 i(program.audioStreams.begin());
1472 i != program.audioStreams.end(); ++i)
1479 if (i != program.audioStreams.begin())
1480 eDebugNoNewLine(", ");
1481 eDebugNoNewLine("%04x", i->pid);
1483 eDebugNoNewLine(")");
1485 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1486 pcrpid = program.pcrPid;
1487 eDebug(", and the text pid is %04x", program.textPid);
1488 tpid = program.textPid;
1493 h.getDecodeDemux(m_decode_demux);
1495 m_decode_demux->getMPEGDecoder(m_decoder);
1497 m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1502 m_decoder->setVideoPID(vpid);
1503 m_current_audio_stream = 0;
1504 m_decoder->setAudioPID(apid, apidtype);
1505 if (!(m_is_pvr || m_timeshift_active))
1506 m_decoder->setSyncPCR(pcrpid);
1508 m_decoder->setSyncPCR(-1);
1509 m_decoder->setTextPID(tpid);
1511 // how we can do this better?
1512 // update cache pid when the user changed the audio track or video track
1513 // TODO handling of difference audio types.. default audio types..
1515 /* don't worry about non-existing services, nor pvr services */
1516 if (m_dvb_service && !m_is_pvr)
1518 if (apidtype == eDVBAudio::aMPEG)
1520 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1521 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1525 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1526 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1528 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1529 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1530 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1535 void eDVBServicePlay::loadCuesheet()
1537 std::string filename = m_reference.path + ".cuts";
1539 m_cue_entries.clear();
1541 FILE *f = fopen(filename.c_str(), "rb");
1545 eDebug("loading cuts..");
1548 unsigned long long where;
1551 if (!fread(&where, sizeof(where), 1, f))
1553 if (!fread(&what, sizeof(what), 1, f))
1556 #if BYTE_ORDER == LITTLE_ENDIAN
1557 where = bswap_64(where);
1564 m_cue_entries.insert(cueEntry(where, what));
1567 eDebug("%d entries", m_cue_entries.size());
1569 eDebug("cutfile not found!");
1571 m_cuesheet_changed = 0;
1572 cutlistToCuesheet();
1573 m_event((iPlayableService*)this, evCuesheetChanged);
1576 void eDVBServicePlay::saveCuesheet()
1578 std::string filename = m_reference.path + ".cuts";
1580 FILE *f = fopen(filename.c_str(), "wb");
1584 unsigned long long where;
1587 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1589 #if BYTE_ORDER == BIG_ENDIAN
1592 where = bswap_64(i->where);
1594 what = htonl(i->what);
1595 fwrite(&where, sizeof(where), 1, f);
1596 fwrite(&what, sizeof(what), 1, f);
1602 m_cuesheet_changed = 0;
1605 void eDVBServicePlay::cutlistToCuesheet()
1609 eDebug("no cue sheet");
1614 if (!m_cutlist_enabled)
1616 m_cue->commitSpans();
1617 eDebug("cutlists where disabled");
1621 pts_t in = 0, out = 0, length = 0;
1625 std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1629 if (i == m_cue_entries.end())
1632 if (i->what == 0) /* in */
1636 } else if (i->what == 1) /* out */
1646 m_cue->addSourceSpan(in, out);
1650 if (i == m_cue_entries.end())
1653 m_cue->commitSpans();
1656 DEFINE_REF(eDVBServicePlay)
1658 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");