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/dvb/metaparser.h>
15 #include <lib/dvb/tstools.h>
16 #include <lib/python/python.h>
20 #define TSPATH "/media/hdd"
22 class eStaticServiceDVBInformation: public iStaticServiceInformation
24 DECLARE_REF(eStaticServiceDVBInformation);
26 RESULT getName(const eServiceReference &ref, std::string &name);
27 int getLength(const eServiceReference &ref);
30 DEFINE_REF(eStaticServiceDVBInformation);
32 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
34 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
35 if ( !ref.name.empty() )
37 if (service.getParentTransportStreamID().get()) // linkage subservice
39 ePtr<iServiceHandler> service_center;
40 if (!eServiceCenter::getInstance(service_center))
42 eServiceReferenceDVB parent = service;
43 parent.setTransportStreamID( service.getParentTransportStreamID() );
44 parent.setServiceID( service.getParentServiceID() );
45 parent.setParentTransportStreamID(eTransportStreamID(0));
46 parent.setParentServiceID(eServiceID(0));
48 ePtr<iStaticServiceInformation> service_info;
49 if (!service_center->info(parent, service_info))
51 if (!service_info->getName(parent, name))
53 // just show short name
54 unsigned int pos = name.find("\xc2\x86");
55 if ( pos != std::string::npos )
57 pos = name.find("\xc2\x87");
58 if ( pos != std::string::npos )
74 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
79 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
81 DECLARE_REF(eStaticServiceDVBBouquetInformation);
83 RESULT getName(const eServiceReference &ref, std::string &name);
84 int getLength(const eServiceReference &ref);
87 DEFINE_REF(eStaticServiceDVBBouquetInformation);
89 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
91 ePtr<iDVBChannelList> db;
92 ePtr<eDVBResourceManager> res;
95 if ((err = eDVBResourceManager::getInstance(res)) != 0)
97 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
100 if ((err = res->getChannelList(db)) != 0)
102 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
107 if ((err = db->getBouquet(ref, bouquet)) != 0)
109 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
113 if ( bouquet && bouquet->m_bouquet_name.length() )
115 name = bouquet->m_bouquet_name;
122 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
127 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
129 DECLARE_REF(eStaticServiceDVBPVRInformation);
130 eServiceReference m_ref;
131 eDVBMetaParser m_parser;
133 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
134 RESULT getName(const eServiceReference &ref, std::string &name);
135 int getLength(const eServiceReference &ref);
137 int getInfo(const eServiceReference &ref, int w);
138 std::string getInfoString(const eServiceReference &ref,int w);
141 DEFINE_REF(eStaticServiceDVBPVRInformation);
143 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
146 m_parser.parseFile(ref.path);
149 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
151 ASSERT(ref == m_ref);
152 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
156 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
158 ASSERT(ref == m_ref);
162 if (tstools.openFile(ref.path.c_str()))
166 if (tstools.calcLen(len))
172 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
176 case iServiceInformation::sDescription:
177 return iServiceInformation::resIsString;
178 case iServiceInformation::sTimeCreate:
179 if (m_parser.m_time_create)
180 return m_parser.m_time_create;
182 return iServiceInformation::resNA;
184 return iServiceInformation::resNA;
188 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
192 case iServiceInformation::sDescription:
193 return m_parser.m_description;
199 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
201 DECLARE_REF(eDVBPVRServiceOfflineOperations);
202 eServiceReferenceDVB m_ref;
204 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
206 RESULT deleteFromDisk(int simulate);
207 RESULT getListOfFilenames(std::list<std::string> &);
210 DEFINE_REF(eDVBPVRServiceOfflineOperations);
212 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
216 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
222 std::list<std::string> res;
223 if (getListOfFilenames(res))
226 /* TODO: deferred removing.. */
227 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
229 eDebug("Removing %s...", i->c_str());
230 ::unlink(i->c_str());
237 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
240 res.push_back(m_ref.path);
241 res.push_back(m_ref.path + ".meta");
245 DEFINE_REF(eServiceFactoryDVB)
247 eServiceFactoryDVB::eServiceFactoryDVB()
249 ePtr<eServiceCenter> sc;
251 eServiceCenter::getPrivInstance(sc);
253 sc->addServiceFactory(eServiceFactoryDVB::id, this);
256 eServiceFactoryDVB::~eServiceFactoryDVB()
258 ePtr<eServiceCenter> sc;
260 eServiceCenter::getPrivInstance(sc);
262 sc->removeServiceFactory(eServiceFactoryDVB::id);
265 DEFINE_REF(eDVBServiceList);
267 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
271 eDVBServiceList::~eDVBServiceList()
275 RESULT eDVBServiceList::startQuery()
277 ePtr<iDVBChannelList> db;
278 ePtr<eDVBResourceManager> res;
281 if ((err = eDVBResourceManager::getInstance(res)) != 0)
283 eDebug("no resource manager");
286 if ((err = res->getChannelList(db)) != 0)
288 eDebug("no channel list");
292 ePtr<eDVBChannelQuery> q;
294 if (!m_parent.path.empty())
296 eDVBChannelQuery::compile(q, m_parent.path);
299 eDebug("compile query failed");
304 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
306 eDebug("startQuery failed");
313 RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
315 eServiceReferenceDVB ref;
317 if (!m_query || !list || !PyList_Check(list))
320 std::list<eServiceReferenceDVB> tmplist;
322 while (!m_query->getNextResult(ref))
323 tmplist.push_back(ref);
326 tmplist.sort(iListableServiceCompare(this));
328 for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
329 it != tmplist.end(); ++it)
331 PyObject *refobj = New_eServiceReference(*it);
332 PyList_Append(list, refobj);
338 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
340 eServiceReferenceDVB ref;
345 while (!m_query->getNextResult(ref))
349 list.sort(iListableServiceCompare(this));
354 RESULT eDVBServiceList::getNext(eServiceReference &ref)
359 return m_query->getNextResult((eServiceReferenceDVB&)ref);
362 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
364 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
367 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
369 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
371 ePtr<iDVBChannelList> db;
372 ePtr<eDVBResourceManager> resm;
374 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
377 if (db->getBouquet(m_parent, m_bouquet) != 0)
388 RESULT eDVBServiceList::addService(eServiceReference &ref)
392 return m_bouquet->addService(ref);
395 RESULT eDVBServiceList::removeService(eServiceReference &ref)
399 return m_bouquet->removeService(ref);
402 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
406 return m_bouquet->moveService(ref, pos);
409 RESULT eDVBServiceList::flushChanges()
413 return m_bouquet->flushChanges();
416 RESULT eDVBServiceList::setListName(const std::string &name)
420 return m_bouquet->setListName(name);
423 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
425 ePtr<eDVBService> service;
426 int r = lookupService(service, ref);
429 // check resources...
430 ptr = new eDVBServicePlay(ref, service);
434 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
436 if (ref.path.empty())
438 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
447 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
449 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
450 if (list->startQuery())
460 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
462 /* is a listable service? */
463 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
465 if ( !ref.name.empty() ) // satellites or providers list
466 ptr = new eStaticServiceDVBInformation;
467 else // a dvb bouquet
468 ptr = new eStaticServiceDVBBouquetInformation;
470 else if (!ref.path.empty()) /* do we have a PVR service? */
471 ptr = new eStaticServiceDVBPVRInformation(ref);
472 else // normal dvb service
474 ePtr<eDVBService> service;
475 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
476 ptr = new eStaticServiceDVBInformation;
478 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
484 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
486 if (ref.path.empty())
492 ptr = new eDVBPVRServiceOfflineOperations(ref);
497 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
499 // TODO: handle the listing itself
500 // if (ref.... == -1) .. return "... bouquets ...";
501 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
503 ePtr<iDVBChannelList> db;
504 ePtr<eDVBResourceManager> res;
507 if ((err = eDVBResourceManager::getInstance(res)) != 0)
509 eDebug("no resource manager");
512 if ((err = res->getChannelList(db)) != 0)
514 eDebug("no channel list");
518 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
519 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
521 eDebug("getService failed!");
528 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
529 m_reference(ref), m_dvb_service(service), m_is_paused(0)
531 m_is_pvr = !ref.path.empty();
532 m_timeshift_enabled = m_timeshift_active = 0;
535 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
536 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
537 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
540 eDVBServicePlay::~eDVBServicePlay()
544 void eDVBServicePlay::gotNewEvent()
548 ePtr<eServiceEvent> m_event_now, m_event_next;
549 getEvent(m_event_now, 0);
550 getEvent(m_event_next, 1);
553 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
555 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
557 m_event((iPlayableService*)this, evUpdatedEventInfo);
560 void eDVBServicePlay::serviceEvent(int event)
564 case eDVBServicePMTHandler::eventTuned:
566 ePtr<iDVBDemux> m_demux;
567 if (!m_service_handler.getDataDemux(m_demux))
569 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
570 int sid = ref.getParentServiceID().get();
572 sid = ref.getServiceID().get();
573 if ( ref.getParentTransportStreamID().get() &&
574 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
575 m_event_handler.startOther(m_demux, sid);
577 m_event_handler.start(m_demux, sid);
581 case eDVBServicePMTHandler::eventTuneFailed:
583 eDebug("DVB service failed to tune");
584 m_event((iPlayableService*)this, evTuneFailed);
587 case eDVBServicePMTHandler::eventNewProgramInfo:
589 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
590 if (m_timeshift_enabled)
591 updateTimeshiftPids();
592 if (!m_timeshift_active)
594 m_event((iPlayableService*)this, evUpdatedInfo);
597 case eDVBServicePMTHandler::eventEOF:
598 m_event((iPlayableService*)this, evEOF);
600 case eDVBServicePMTHandler::eventSOF:
601 m_event((iPlayableService*)this, evSOF);
606 void eDVBServicePlay::serviceEventTimeshift(int event)
610 case eDVBServicePMTHandler::eventNewProgramInfo:
611 if (m_timeshift_active)
614 case eDVBServicePMTHandler::eventEOF:
620 RESULT eDVBServicePlay::start()
623 /* in pvr mode, we only want to use one demux. in tv mode, we're using
624 two (one for decoding, one for data source), as we must be prepared
625 to start recording from the data demux. */
626 m_cue = new eCueSheet();
627 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
628 m_event(this, evStart);
629 m_event((iPlayableService*)this, evSeekableStatusChanged);
633 RESULT eDVBServicePlay::stop()
635 eDebug("stop timeshift");
636 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
638 eDebug("free ts handler");
639 m_service_handler_timeshift.free();
640 eDebug("stop service handler");
641 m_service_handler.free();
647 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
649 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
653 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
655 /* note: we check for timeshift to be enabled,
656 not neccessary active. if you pause when timeshift
657 is not active, you should activate it when unpausing */
658 if ((!m_is_pvr) && (!m_timeshift_enabled))
668 RESULT eDVBServicePlay::setSlowMotion(int ratio)
671 return m_decoder->setSlowMotion(ratio);
676 RESULT eDVBServicePlay::setFastForward(int ratio)
678 int skipmode, ffratio;
684 } else if (ratio > 0)
692 } else // if (ratio < 0)
698 if (m_skipmode != skipmode)
700 eDebug("setting cue skipmode to %d", skipmode);
702 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
705 m_skipmode = skipmode;
710 return m_decoder->setFastForward(ffratio);
713 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
715 if (m_is_pvr || m_timeshift_enabled)
725 /* TODO: when timeshift is enabled but not active, this doesn't work. */
726 RESULT eDVBServicePlay::getLength(pts_t &len)
728 ePtr<iDVBPVRChannel> pvr_channel;
730 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
733 return pvr_channel->getLength(len);
736 RESULT eDVBServicePlay::pause()
738 if (!m_is_paused && m_decoder)
741 return m_decoder->freeze(0);
746 RESULT eDVBServicePlay::unpause()
748 if (m_is_paused && m_decoder)
751 return m_decoder->unfreeze();
756 RESULT eDVBServicePlay::seekTo(pts_t to)
758 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
763 ePtr<iDVBPVRChannel> pvr_channel;
765 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
771 m_cue->seekTo(0, to);
775 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
777 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
782 ePtr<iDVBPVRChannel> pvr_channel;
784 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
792 m_cue->seekTo(1, to);
796 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
798 ePtr<iDVBPVRChannel> pvr_channel;
803 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
806 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
809 RESULT eDVBServicePlay::setTrickmode(int trick)
812 m_decoder->setTrickmode(trick);
816 RESULT eDVBServicePlay::isCurrentlySeekable()
818 return m_is_pvr || m_timeshift_active;
821 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
827 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
833 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
839 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
845 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
848 if (m_timeshift_enabled || !m_is_pvr)
850 if (!m_timeshift_enabled)
852 /* we need enough diskspace */
854 if (statfs(TSPATH "/.", &fs) < 0)
856 eDebug("statfs failed!");
860 if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
862 eDebug("not enough diskspace for timeshift! (less than 1GB)");
872 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
883 RESULT eDVBServicePlay::getName(std::string &name)
887 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
888 return i->getName(m_reference, name);
892 m_dvb_service->getName(m_reference, name);
896 else if (!m_reference.name.empty())
897 eStaticServiceDVBInformation().getName(m_reference, name);
899 name = "DVB service";
903 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
905 return m_event_handler.getEvent(evt, nownext);
908 int eDVBServicePlay::getInfo(int w)
910 eDVBServicePMTHandler::program program;
912 if (m_service_handler.getProgramInfo(program))
918 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
920 ePtr<eServiceEvent> evt;
921 if (!m_event_handler.getEvent(evt, 0))
923 ePtr<eComponentData> data;
924 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
926 if ( data->getStreamContent() == 1 )
928 switch(data->getComponentType())
931 case 1: // 4:3 SD PAL
933 case 3: // 16:9 SD PAL
934 case 4: // > 16:9 PAL
935 case 5: // 4:3 SD NTSC
937 case 7: // 16:9 SD NTSC
938 case 8: // > 16:9 NTSC
941 case 9: // 4:3 HD PAL
943 case 0xB: // 16:9 HD PAL
944 case 0xC: // > 16:9 HD PAL
945 case 0xD: // 4:3 HD NTSC
947 case 0xF: // 16:9 HD NTSC
948 case 0x10: // > 16:9 HD PAL
949 return data->getComponentType();
956 case sIsCrypted: return program.isCrypted;
957 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
958 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
959 case sPCRPID: return program.pcrPid;
960 case sPMTPID: return program.pmtPid;
961 case sTXTPID: return program.textPid;
962 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
963 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
964 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
965 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
966 case sProvider: if (!m_dvb_service) return -1; return -2;
972 std::string eDVBServicePlay::getInfoString(int w)
977 if (!m_dvb_service) return "";
978 return m_dvb_service->m_provider_name;
984 int eDVBServicePlay::getNumberOfTracks()
986 eDVBServicePMTHandler::program program;
987 if (m_service_handler.getProgramInfo(program))
989 return program.audioStreams.size();
992 RESULT eDVBServicePlay::selectTrack(unsigned int i)
994 int ret = selectAudioStream(i);
996 if (m_decoder->start())
1002 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1004 eDVBServicePMTHandler::program program;
1006 if (m_service_handler.getProgramInfo(program))
1009 if (i >= program.audioStreams.size())
1012 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1013 info.m_description = "MPEG";
1014 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1015 info.m_description = "AC3";
1016 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1017 info.m_description = "DTS";
1019 info.m_description = "???";
1021 if (program.audioStreams[i].component_tag != -1)
1023 ePtr<eServiceEvent> evt;
1024 if (!m_event_handler.getEvent(evt, 0))
1026 ePtr<eComponentData> data;
1027 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1028 info.m_language = data->getText();
1032 if (info.m_language.empty())
1033 info.m_language = program.audioStreams[i].language_code;
1038 int eDVBServicePlay::selectAudioStream(int i)
1040 eDVBServicePMTHandler::program program;
1042 if (m_service_handler.getProgramInfo(program))
1045 if ((unsigned int)i >= program.audioStreams.size())
1051 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1054 if (m_dvb_service && !m_is_pvr)
1056 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1058 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1059 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1062 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1063 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1067 m_current_audio_stream = i;
1072 int eDVBServicePlay::getFrontendInfo(int w)
1076 eUsePtr<iDVBChannel> channel;
1077 if(m_service_handler.getChannel(channel))
1079 ePtr<iDVBFrontend> fe;
1080 if(channel->getFrontend(fe))
1082 return fe->readFrontendData(w);
1085 int eDVBServicePlay::getNumberOfSubservices()
1087 ePtr<eServiceEvent> evt;
1088 if (!m_event_handler.getEvent(evt, 0))
1089 return evt->getNumOfLinkageServices();
1093 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1095 ePtr<eServiceEvent> evt;
1096 if (!m_event_handler.getEvent(evt, 0))
1098 if (!evt->getLinkageService(sub, m_reference, n))
1101 sub.type=eServiceReference::idInvalid;
1105 RESULT eDVBServicePlay::startTimeshift()
1107 ePtr<iDVBDemux> demux;
1109 eDebug("Start timeshift!");
1111 if (m_timeshift_enabled)
1114 /* start recording with the data demux. */
1115 if (m_service_handler.getDataDemux(demux))
1118 demux->createTSRecorder(m_record);
1122 char templ[]=TSPATH "/timeshift.XXXXXX";
1123 m_timeshift_fd = mkstemp(templ);
1124 m_timeshift_file = templ;
1126 eDebug("recording to %s", templ);
1128 if (m_timeshift_fd < 0)
1134 m_record->setTargetFD(m_timeshift_fd);
1136 m_timeshift_enabled = 1;
1138 updateTimeshiftPids();
1144 RESULT eDVBServicePlay::stopTimeshift()
1146 if (!m_timeshift_enabled)
1151 m_timeshift_enabled = 0;
1156 close(m_timeshift_fd);
1157 eDebug("remove timeshift file");
1158 remove(m_timeshift_file.c_str());
1163 int eDVBServicePlay::isTimeshiftActive()
1165 return m_timeshift_enabled && m_timeshift_active;
1168 RESULT eDVBServicePlay::activateTimeshift()
1170 if (!m_timeshift_enabled)
1173 if (!m_timeshift_active)
1175 switchToTimeshift();
1182 PyObject *eDVBServicePlay::getCutList()
1184 PyObject *list = PyList_New(0);
1189 RESULT eDVBServicePlay::addCut(const pts_t &when, int what)
1194 RESULT eDVBServicePlay::removeCut(const pts_t &when, int what)
1199 void eDVBServicePlay::updateTimeshiftPids()
1204 eDVBServicePMTHandler::program program;
1205 if (m_service_handler.getProgramInfo(program))
1209 std::set<int> pids_to_record;
1210 pids_to_record.insert(0); // PAT
1211 if (program.pmtPid != -1)
1212 pids_to_record.insert(program.pmtPid); // PMT
1214 if (program.textPid != -1)
1215 pids_to_record.insert(program.textPid); // Videotext
1217 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1218 i(program.videoStreams.begin());
1219 i != program.videoStreams.end(); ++i)
1220 pids_to_record.insert(i->pid);
1222 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1223 i(program.audioStreams.begin());
1224 i != program.audioStreams.end(); ++i)
1225 pids_to_record.insert(i->pid);
1227 std::set<int> new_pids, obsolete_pids;
1229 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1230 m_pids_active.begin(), m_pids_active.end(),
1231 std::inserter(new_pids, new_pids.begin()));
1233 std::set_difference(
1234 m_pids_active.begin(), m_pids_active.end(),
1235 pids_to_record.begin(), pids_to_record.end(),
1236 std::inserter(new_pids, new_pids.begin())
1239 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1240 m_record->addPID(*i);
1242 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1243 m_record->removePID(*i);
1247 void eDVBServicePlay::switchToLive()
1249 if (!m_timeshift_active)
1254 /* free the timeshift service handler, we need the resources */
1255 m_service_handler_timeshift.free();
1256 m_timeshift_active = 0;
1258 m_event((iPlayableService*)this, evSeekableStatusChanged);
1263 void eDVBServicePlay::switchToTimeshift()
1265 if (m_timeshift_active)
1271 m_timeshift_active = 1;
1273 m_event((iPlayableService*)this, evSeekableStatusChanged);
1275 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1276 r.path = m_timeshift_file;
1278 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1281 void eDVBServicePlay::updateDecoder()
1283 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1284 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1286 eDVBServicePMTHandler::program program;
1287 if (h.getProgramInfo(program))
1288 eDebug("getting program info failed.");
1291 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1292 if (!program.videoStreams.empty())
1294 eDebugNoNewLine(" (");
1295 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1296 i(program.videoStreams.begin());
1297 i != program.videoStreams.end(); ++i)
1301 if (i != program.videoStreams.begin())
1302 eDebugNoNewLine(", ");
1303 eDebugNoNewLine("%04x", i->pid);
1305 eDebugNoNewLine(")");
1307 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1308 if (!program.audioStreams.empty())
1310 eDebugNoNewLine(" (");
1311 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1312 i(program.audioStreams.begin());
1313 i != program.audioStreams.end(); ++i)
1320 if (i != program.audioStreams.begin())
1321 eDebugNoNewLine(", ");
1322 eDebugNoNewLine("%04x", i->pid);
1324 eDebugNoNewLine(")");
1326 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1327 pcrpid = program.pcrPid;
1328 eDebug(", and the text pid is %04x", program.textPid);
1329 tpid = program.textPid;
1334 h.getDecodeDemux(m_decode_demux);
1336 m_decode_demux->getMPEGDecoder(m_decoder);
1338 m_cue->setDecodingDemux(m_decode_demux);
1343 m_decoder->setVideoPID(vpid);
1344 m_current_audio_stream = 0;
1345 m_decoder->setAudioPID(apid, apidtype);
1346 if (!(m_is_pvr || m_timeshift_active))
1347 m_decoder->setSyncPCR(pcrpid);
1349 m_decoder->setSyncPCR(-1);
1350 m_decoder->setTextPID(tpid);
1352 // how we can do this better?
1353 // update cache pid when the user changed the audio track or video track
1354 // TODO handling of difference audio types.. default audio types..
1356 /* don't worry about non-existing services, nor pvr services */
1357 if (m_dvb_service && !m_is_pvr)
1359 if (apidtype == eDVBAudio::aMPEG)
1361 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1362 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1366 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1367 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1369 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1370 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1371 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1376 DEFINE_REF(eDVBServicePlay)
1378 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");