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>
17 class eStaticServiceDVBInformation: public iStaticServiceInformation
19 DECLARE_REF(eStaticServiceDVBInformation);
21 RESULT getName(const eServiceReference &ref, std::string &name);
22 int getLength(const eServiceReference &ref);
25 DEFINE_REF(eStaticServiceDVBInformation);
27 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
29 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
30 if ( !ref.name.empty() )
32 if (service.getParentTransportStreamID().get()) // linkage subservice
34 ePtr<iServiceHandler> service_center;
35 if (!eServiceCenter::getInstance(service_center))
37 eServiceReferenceDVB parent = service;
38 parent.setTransportStreamID( service.getParentTransportStreamID() );
39 parent.setServiceID( service.getParentServiceID() );
40 parent.setParentTransportStreamID(eTransportStreamID(0));
41 parent.setParentServiceID(eServiceID(0));
43 ePtr<iStaticServiceInformation> service_info;
44 if (!service_center->info(parent, service_info))
46 if (!service_info->getName(parent, name))
48 // just show short name
49 unsigned int pos = name.find("\xc2\x86");
50 if ( pos != std::string::npos )
52 pos = name.find("\xc2\x87");
53 if ( pos != std::string::npos )
69 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
74 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
76 DECLARE_REF(eStaticServiceDVBBouquetInformation);
78 RESULT getName(const eServiceReference &ref, std::string &name);
79 int getLength(const eServiceReference &ref);
82 DEFINE_REF(eStaticServiceDVBBouquetInformation);
84 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
86 ePtr<iDVBChannelList> db;
87 ePtr<eDVBResourceManager> res;
90 if ((err = eDVBResourceManager::getInstance(res)) != 0)
92 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
95 if ((err = res->getChannelList(db)) != 0)
97 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
102 if ((err = db->getBouquet(ref, bouquet)) != 0)
104 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
108 if ( bouquet && bouquet->m_bouquet_name.length() )
110 name = bouquet->m_bouquet_name;
117 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
122 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
124 DECLARE_REF(eStaticServiceDVBPVRInformation);
125 eServiceReference m_ref;
126 eDVBMetaParser m_parser;
128 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
129 RESULT getName(const eServiceReference &ref, std::string &name);
130 int getLength(const eServiceReference &ref);
132 int getInfo(const eServiceReference &ref, int w);
133 std::string getInfoString(const eServiceReference &ref,int w);
136 DEFINE_REF(eStaticServiceDVBPVRInformation);
138 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
141 m_parser.parseFile(ref.path);
144 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
146 ASSERT(ref == m_ref);
147 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
151 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
153 ASSERT(ref == m_ref);
157 if (tstools.openFile(ref.path.c_str()))
161 if (tstools.calcLen(len))
167 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
171 case iServiceInformation::sDescription:
172 return iServiceInformation::resIsString;
173 case iServiceInformation::sTimeCreate:
174 if (m_parser.m_time_create)
175 return m_parser.m_time_create;
177 return iServiceInformation::resNA;
179 return iServiceInformation::resNA;
183 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
187 case iServiceInformation::sDescription:
188 return m_parser.m_description;
194 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
196 DECLARE_REF(eDVBPVRServiceOfflineOperations);
197 eServiceReferenceDVB m_ref;
199 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
201 RESULT deleteFromDisk(int simulate);
202 RESULT getListOfFilenames(std::list<std::string> &);
205 DEFINE_REF(eDVBPVRServiceOfflineOperations);
207 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
211 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
217 std::list<std::string> res;
218 if (getListOfFilenames(res))
221 /* TODO: deferred removing.. */
222 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
224 eDebug("Removing %s...", i->c_str());
225 ::unlink(i->c_str());
232 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
235 res.push_back(m_ref.path);
236 res.push_back(m_ref.path + ".meta");
240 DEFINE_REF(eServiceFactoryDVB)
242 eServiceFactoryDVB::eServiceFactoryDVB()
244 ePtr<eServiceCenter> sc;
246 eServiceCenter::getPrivInstance(sc);
248 sc->addServiceFactory(eServiceFactoryDVB::id, this);
251 eServiceFactoryDVB::~eServiceFactoryDVB()
253 ePtr<eServiceCenter> sc;
255 eServiceCenter::getPrivInstance(sc);
257 sc->removeServiceFactory(eServiceFactoryDVB::id);
260 DEFINE_REF(eDVBServiceList);
262 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
266 eDVBServiceList::~eDVBServiceList()
270 RESULT eDVBServiceList::startQuery()
272 ePtr<iDVBChannelList> db;
273 ePtr<eDVBResourceManager> res;
276 if ((err = eDVBResourceManager::getInstance(res)) != 0)
278 eDebug("no resource manager");
281 if ((err = res->getChannelList(db)) != 0)
283 eDebug("no channel list");
287 ePtr<eDVBChannelQuery> q;
289 if (!m_parent.path.empty())
291 eDVBChannelQuery::compile(q, m_parent.path);
294 eDebug("compile query failed");
299 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
301 eDebug("startQuery failed");
308 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
310 eServiceReferenceDVB ref;
315 while (!m_query->getNextResult(ref))
320 RESULT eDVBServiceList::getNext(eServiceReference &ref)
325 return m_query->getNextResult((eServiceReferenceDVB&)ref);
328 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
330 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
333 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
335 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
337 ePtr<iDVBChannelList> db;
338 ePtr<eDVBResourceManager> resm;
340 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
343 if (db->getBouquet(m_parent, m_bouquet) != 0)
354 RESULT eDVBServiceList::addService(eServiceReference &ref)
358 return m_bouquet->addService(ref);
361 RESULT eDVBServiceList::removeService(eServiceReference &ref)
365 return m_bouquet->removeService(ref);
368 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
372 return m_bouquet->moveService(ref, pos);
375 RESULT eDVBServiceList::flushChanges()
379 return m_bouquet->flushChanges();
382 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
384 ePtr<eDVBService> service;
385 int r = lookupService(service, ref);
388 // check resources...
389 ptr = new eDVBServicePlay(ref, service);
393 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
395 if (ref.path.empty())
397 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
406 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
408 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
409 if (list->startQuery())
419 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
421 /* is a listable service? */
422 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
424 if ( !ref.name.empty() ) // satellites or providers list
425 ptr = new eStaticServiceDVBInformation;
426 else // a dvb bouquet
427 ptr = new eStaticServiceDVBBouquetInformation;
429 else if (!ref.path.empty()) /* do we have a PVR service? */
430 ptr = new eStaticServiceDVBPVRInformation(ref);
431 else // normal dvb service
433 ePtr<eDVBService> service;
434 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
435 ptr = new eStaticServiceDVBInformation;
437 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
443 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
445 if (ref.path.empty())
451 ptr = new eDVBPVRServiceOfflineOperations(ref);
456 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
458 // TODO: handle the listing itself
459 // if (ref.... == -1) .. return "... bouquets ...";
460 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
462 ePtr<iDVBChannelList> db;
463 ePtr<eDVBResourceManager> res;
466 if ((err = eDVBResourceManager::getInstance(res)) != 0)
468 eDebug("no resource manager");
471 if ((err = res->getChannelList(db)) != 0)
473 eDebug("no channel list");
477 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
478 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
480 eDebug("getService failed!");
487 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
488 m_reference(ref), m_dvb_service(service), m_is_paused(0)
490 m_is_pvr = !ref.path.empty();
491 m_timeshift_enabled = m_timeshift_active = 0;
493 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
494 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
495 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
498 eDVBServicePlay::~eDVBServicePlay()
502 void eDVBServicePlay::gotNewEvent()
506 ePtr<eServiceEvent> m_event_now, m_event_next;
507 getEvent(m_event_now, 0);
508 getEvent(m_event_next, 1);
511 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
513 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
515 m_event((iPlayableService*)this, evUpdatedEventInfo);
518 void eDVBServicePlay::serviceEvent(int event)
522 case eDVBServicePMTHandler::eventTuned:
524 ePtr<iDVBDemux> m_demux;
525 if (!m_service_handler.getDataDemux(m_demux))
527 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
528 int sid = ref.getParentServiceID().get();
530 sid = ref.getServiceID().get();
531 if ( ref.getParentTransportStreamID().get() &&
532 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
533 m_event_handler.startOther(m_demux, sid);
535 m_event_handler.start(m_demux, sid);
539 case eDVBServicePMTHandler::eventTuneFailed:
541 eDebug("DVB service failed to tune");
542 m_event((iPlayableService*)this, evTuneFailed);
545 case eDVBServicePMTHandler::eventNewProgramInfo:
547 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
548 if (m_timeshift_enabled)
549 updateTimeshiftPids();
550 if (!m_timeshift_active)
552 m_event((iPlayableService*)this, evUpdatedInfo);
555 case eDVBServicePMTHandler::eventEOF:
557 m_event((iPlayableService*)this, evEnd);
563 void eDVBServicePlay::serviceEventTimeshift(int event)
567 case eDVBServicePMTHandler::eventNewProgramInfo:
568 if (m_timeshift_active)
571 case eDVBServicePMTHandler::eventEOF:
577 RESULT eDVBServicePlay::start()
580 /* in pvr mode, we only want to use one demux. in tv mode, we're using
581 two (one for decoding, one for data source), as we must be prepared
582 to start recording from the data demux. */
583 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr);
584 m_event(this, evStart);
585 m_event((iPlayableService*)this, evSeekableStatusChanged);
589 RESULT eDVBServicePlay::stop()
594 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
596 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
600 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
602 /* note: we check for timeshift to be enabled,
603 not neccessary active. if you pause when timeshift
604 is not active, you should activate it when unpausing */
605 if ((!m_is_pvr) && (!m_timeshift_enabled))
615 RESULT eDVBServicePlay::setSlowMotion(int ratio)
618 return m_decoder->setSlowMotion(ratio);
623 RESULT eDVBServicePlay::setFastForward(int ratio)
626 return m_decoder->setFastForward(ratio);
631 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
633 if (m_is_pvr || m_timeshift_active)
643 RESULT eDVBServicePlay::getLength(pts_t &len)
645 ePtr<iDVBPVRChannel> pvr_channel;
647 if (m_service_handler.getPVRChannel(pvr_channel))
649 eDebug("getPVRChannel failed!");
653 return pvr_channel->getLength(len);
656 RESULT eDVBServicePlay::pause()
658 if (!m_is_paused && m_decoder)
661 return m_decoder->freeze(0);
666 RESULT eDVBServicePlay::unpause()
668 if (m_is_paused && m_decoder)
671 return m_decoder->unfreeze();
676 RESULT eDVBServicePlay::seekTo(pts_t to)
678 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
683 ePtr<iDVBPVRChannel> pvr_channel;
685 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
688 return pvr_channel->seekTo(m_decode_demux, 0, to);
691 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
693 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
698 ePtr<iDVBPVRChannel> pvr_channel;
700 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
705 return pvr_channel->seekTo(m_decode_demux, 1, to);
708 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
710 ePtr<iDVBPVRChannel> pvr_channel;
715 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
718 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
721 RESULT eDVBServicePlay::setTrickmode(int trick)
724 m_decoder->setTrickmode(trick);
728 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
734 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
740 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
746 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
752 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
754 if (m_timeshift_enabled || !m_is_pvr)
763 RESULT eDVBServicePlay::getName(std::string &name)
767 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
768 return i->getName(m_reference, name);
772 m_dvb_service->getName(m_reference, name);
776 else if (!m_reference.name.empty())
777 eStaticServiceDVBInformation().getName(m_reference, name);
779 name = "DVB service";
783 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
785 return m_event_handler.getEvent(evt, nownext);
788 int eDVBServicePlay::getInfo(int w)
790 eDVBServicePMTHandler::program program;
792 if (m_service_handler.getProgramInfo(program))
798 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
800 ePtr<eServiceEvent> evt;
801 if (!m_event_handler.getEvent(evt, 0))
803 ePtr<eComponentData> data;
804 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
806 if ( data->getStreamContent() == 1 )
808 switch(data->getComponentType())
811 case 1: // 4:3 SD PAL
813 case 3: // 16:9 SD PAL
814 case 4: // > 16:9 PAL
815 case 5: // 4:3 SD NTSC
817 case 7: // 16:9 SD NTSC
818 case 8: // > 16:9 NTSC
821 case 9: // 4:3 HD PAL
823 case 0xB: // 16:9 HD PAL
824 case 0xC: // > 16:9 HD PAL
825 case 0xD: // 4:3 HD NTSC
827 case 0xF: // 16:9 HD NTSC
828 case 0x10: // > 16:9 HD PAL
829 return data->getComponentType();
836 case sIsCrypted: return program.isCrypted;
837 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
838 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
839 case sPCRPID: return program.pcrPid;
840 case sPMTPID: return program.pmtPid;
841 case sTXTPID: return program.textPid;
842 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
843 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
844 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
845 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
846 case sProvider: if (!m_dvb_service) return -1; return -2;
852 std::string eDVBServicePlay::getInfoString(int w)
857 if (!m_dvb_service) return "";
858 return m_dvb_service->m_provider_name;
864 int eDVBServicePlay::getNumberOfTracks()
866 eDVBServicePMTHandler::program program;
867 if (m_service_handler.getProgramInfo(program))
869 return program.audioStreams.size();
872 RESULT eDVBServicePlay::selectTrack(unsigned int i)
874 int ret = selectAudioStream(i);
876 if (m_decoder->start())
882 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
884 eDVBServicePMTHandler::program program;
886 if (m_service_handler.getProgramInfo(program))
889 if (i >= program.audioStreams.size())
892 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
893 info.m_description = "MPEG";
894 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
895 info.m_description = "AC3";
896 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
897 info.m_description = "DTS";
899 info.m_description = "???";
901 if (program.audioStreams[i].component_tag != -1)
903 ePtr<eServiceEvent> evt;
904 if (!m_event_handler.getEvent(evt, 0))
906 ePtr<eComponentData> data;
907 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
908 info.m_language = data->getText();
912 if (info.m_language.empty())
913 info.m_language = program.audioStreams[i].language_code;
918 int eDVBServicePlay::selectAudioStream(int i)
920 eDVBServicePMTHandler::program program;
922 if (m_service_handler.getProgramInfo(program))
925 if ((unsigned int)i >= program.audioStreams.size())
931 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
934 if (m_dvb_service && !m_is_pvr)
936 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
938 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
939 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
942 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
943 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
947 m_current_audio_stream = i;
952 int eDVBServicePlay::getFrontendInfo(int w)
956 eUsePtr<iDVBChannel> channel;
957 if(m_service_handler.getChannel(channel))
959 ePtr<iDVBFrontend> fe;
960 if(channel->getFrontend(fe))
962 return fe->readFrontendData(w);
965 int eDVBServicePlay::getNumberOfSubservices()
967 ePtr<eServiceEvent> evt;
968 if (!m_event_handler.getEvent(evt, 0))
969 return evt->getNumOfLinkageServices();
973 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
975 ePtr<eServiceEvent> evt;
976 if (!m_event_handler.getEvent(evt, 0))
978 if (!evt->getLinkageService(sub, m_reference, n))
981 sub.type=eServiceReference::idInvalid;
985 RESULT eDVBServicePlay::startTimeshift()
987 ePtr<iDVBDemux> demux;
989 eDebug("Start timeshift!");
991 if (m_timeshift_enabled)
994 /* start recording with the data demux. */
995 if (m_service_handler.getDataDemux(demux))
998 demux->createTSRecorder(m_record);
1002 char templ[]="/media/hdd/timeshift.XXXXXX";
1003 m_timeshift_fd = mkstemp(templ);
1004 m_timeshift_file = templ;
1006 eDebug("recording to %s", templ);
1008 if (m_timeshift_fd < 0)
1014 m_record->setTargetFD(m_timeshift_fd);
1016 m_timeshift_enabled = 1;
1018 updateTimeshiftPids();
1024 RESULT eDVBServicePlay::stopTimeshift()
1026 if (!m_timeshift_enabled)
1031 m_timeshift_enabled = 0;
1036 close(m_timeshift_fd);
1037 remove(m_timeshift_file.c_str());
1039 eDebug("timeshift disabled");
1043 int eDVBServicePlay::isTimeshiftActive()
1045 return m_timeshift_enabled && m_timeshift_active;
1048 RESULT eDVBServicePlay::activateTimeshift()
1050 if (!m_timeshift_enabled)
1053 if (!m_timeshift_active)
1055 switchToTimeshift();
1062 void eDVBServicePlay::updateTimeshiftPids()
1067 eDVBServicePMTHandler::program program;
1068 if (m_service_handler.getProgramInfo(program))
1072 std::set<int> pids_to_record;
1073 pids_to_record.insert(0); // PAT
1074 if (program.pmtPid != -1)
1075 pids_to_record.insert(program.pmtPid); // PMT
1077 if (program.textPid != -1)
1078 pids_to_record.insert(program.textPid); // Videotext
1080 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1081 i(program.videoStreams.begin());
1082 i != program.videoStreams.end(); ++i)
1083 pids_to_record.insert(i->pid);
1085 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1086 i(program.audioStreams.begin());
1087 i != program.audioStreams.end(); ++i)
1088 pids_to_record.insert(i->pid);
1090 std::set<int> new_pids, obsolete_pids;
1092 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1093 m_pids_active.begin(), m_pids_active.end(),
1094 std::inserter(new_pids, new_pids.begin()));
1096 std::set_difference(
1097 m_pids_active.begin(), m_pids_active.end(),
1098 pids_to_record.begin(), pids_to_record.end(),
1099 std::inserter(new_pids, new_pids.begin())
1102 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1103 m_record->addPID(*i);
1105 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1106 m_record->removePID(*i);
1110 void eDVBServicePlay::switchToLive()
1112 eDebug("SwitchToLive");
1113 if (!m_timeshift_active)
1118 /* free the timeshift service handler, we need the resources */
1119 m_service_handler_timeshift.free();
1120 m_timeshift_active = 0;
1122 m_event((iPlayableService*)this, evSeekableStatusChanged);
1127 void eDVBServicePlay::switchToTimeshift()
1129 eDebug("SwitchToTimeshift");
1130 if (m_timeshift_active)
1136 m_timeshift_active = 1;
1138 m_event((iPlayableService*)this, evSeekableStatusChanged);
1140 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1141 r.path = m_timeshift_file;
1143 eDebug("ok, re-tuning to %s", r.toString().c_str());
1144 m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
1147 void eDVBServicePlay::updateDecoder()
1149 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1150 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1152 eDVBServicePMTHandler::program program;
1153 if (h.getProgramInfo(program))
1154 eDebug("getting program info failed.");
1157 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1158 if (!program.videoStreams.empty())
1160 eDebugNoNewLine(" (");
1161 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1162 i(program.videoStreams.begin());
1163 i != program.videoStreams.end(); ++i)
1167 if (i != program.videoStreams.begin())
1168 eDebugNoNewLine(", ");
1169 eDebugNoNewLine("%04x", i->pid);
1171 eDebugNoNewLine(")");
1173 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1174 if (!program.audioStreams.empty())
1176 eDebugNoNewLine(" (");
1177 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1178 i(program.audioStreams.begin());
1179 i != program.audioStreams.end(); ++i)
1186 if (i != program.audioStreams.begin())
1187 eDebugNoNewLine(", ");
1188 eDebugNoNewLine("%04x", i->pid);
1190 eDebugNoNewLine(")");
1192 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1193 pcrpid = program.pcrPid;
1194 eDebug(", and the text pid is %04x", program.textPid);
1195 tpid = program.textPid;
1200 h.getDecodeDemux(m_decode_demux);
1202 m_decode_demux->getMPEGDecoder(m_decoder);
1207 m_decoder->setVideoPID(vpid);
1208 m_current_audio_stream = 0;
1209 m_decoder->setAudioPID(apid, apidtype);
1210 if (!(m_is_pvr || m_timeshift_active))
1211 m_decoder->setSyncPCR(pcrpid);
1213 m_decoder->setSyncPCR(-1);
1214 m_decoder->setTextPID(tpid);
1216 // how we can do this better?
1217 // update cache pid when the user changed the audio track or video track
1218 // TODO handling of difference audio types.. default audio types..
1220 /* don't worry about non-existing services, nor pvr services */
1221 if (m_dvb_service && !m_is_pvr)
1223 if (apidtype == eDVBAudio::aMPEG)
1225 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1226 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1230 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1231 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1233 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1234 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1235 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1240 DEFINE_REF(eDVBServicePlay)
1242 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");