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);
558 void eDVBServicePlay::serviceEventTimeshift(int event)
562 case eDVBServicePMTHandler::eventNewProgramInfo:
563 if (m_timeshift_active)
569 RESULT eDVBServicePlay::start()
572 /* in pvr mode, we only want to use one demux. in tv mode, we're using
573 two (one for decoding, one for data source), as we must be prepared
574 to start recording from the data demux. */
575 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr);
576 m_event(this, evStart);
580 RESULT eDVBServicePlay::stop()
585 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
587 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
591 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
593 if ((!m_is_pvr) && (!m_timeshift_enabled))
603 RESULT eDVBServicePlay::setSlowMotion(int ratio)
606 return m_decoder->setSlowMotion(ratio);
611 RESULT eDVBServicePlay::setFastForward(int ratio)
614 return m_decoder->setFastForward(ratio);
619 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
621 if (m_is_pvr || m_timeshift_enabled)
631 RESULT eDVBServicePlay::getLength(pts_t &len)
633 ePtr<iDVBPVRChannel> pvr_channel;
635 if (m_service_handler.getPVRChannel(pvr_channel))
637 eDebug("getPVRChannel failed!");
641 return pvr_channel->getLength(len);
644 RESULT eDVBServicePlay::pause()
646 if (m_timeshift_enabled && !m_timeshift_active)
651 if (!m_is_paused && m_decoder)
654 return m_decoder->freeze(0);
659 RESULT eDVBServicePlay::unpause()
661 if (m_is_paused && m_decoder)
664 return m_decoder->unfreeze();
669 RESULT eDVBServicePlay::seekTo(pts_t to)
671 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
676 ePtr<iDVBPVRChannel> pvr_channel;
678 if (m_service_handler.getPVRChannel(pvr_channel))
681 return pvr_channel->seekTo(m_decode_demux, 0, to);
684 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
686 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
691 ePtr<iDVBPVRChannel> pvr_channel;
693 if (m_service_handler.getPVRChannel(pvr_channel))
698 return pvr_channel->seekTo(m_decode_demux, 1, to);
701 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
703 ePtr<iDVBPVRChannel> pvr_channel;
708 if (m_service_handler.getPVRChannel(pvr_channel))
711 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
714 RESULT eDVBServicePlay::setTrickmode(int trick)
717 m_decoder->setTrickmode(trick);
721 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
727 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
733 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
739 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
745 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
747 if (m_timeshift_enabled || !m_is_pvr)
756 RESULT eDVBServicePlay::getName(std::string &name)
760 m_dvb_service->getName(m_reference, name);
764 else if (!m_reference.name.empty())
765 eStaticServiceDVBInformation().getName(m_reference, name);
767 name = "DVB service";
771 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
773 return m_event_handler.getEvent(evt, nownext);
776 int eDVBServicePlay::getInfo(int w)
778 eDVBServicePMTHandler::program program;
780 if (m_service_handler.getProgramInfo(program))
786 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
788 ePtr<eServiceEvent> evt;
789 if (!m_event_handler.getEvent(evt, 0))
791 ePtr<eComponentData> data;
792 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
794 if ( data->getStreamContent() == 1 )
796 switch(data->getComponentType())
799 case 1: // 4:3 SD PAL
801 case 3: // 16:9 SD PAL
802 case 4: // > 16:9 PAL
803 case 5: // 4:3 SD NTSC
805 case 7: // 16:9 SD NTSC
806 case 8: // > 16:9 NTSC
809 case 9: // 4:3 HD PAL
811 case 0xB: // 16:9 HD PAL
812 case 0xC: // > 16:9 HD PAL
813 case 0xD: // 4:3 HD NTSC
815 case 0xF: // 16:9 HD NTSC
816 case 0x10: // > 16:9 HD PAL
817 return data->getComponentType();
824 case sIsCrypted: return program.isCrypted;
825 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
826 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
827 case sPCRPID: return program.pcrPid;
828 case sPMTPID: return program.pmtPid;
829 case sTXTPID: return -1;
830 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
831 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
832 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
833 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
834 case sProvider: if (!m_dvb_service) return -1; return -2;
840 std::string eDVBServicePlay::getInfoString(int w)
845 if (!m_dvb_service) return "";
846 return m_dvb_service->m_provider_name;
852 int eDVBServicePlay::getNumberOfTracks()
854 eDVBServicePMTHandler::program program;
855 if (m_service_handler.getProgramInfo(program))
857 return program.audioStreams.size();
860 RESULT eDVBServicePlay::selectTrack(unsigned int i)
862 int ret = selectAudioStream(i);
864 if (m_decoder->start())
870 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
872 eDVBServicePMTHandler::program program;
874 if (m_service_handler.getProgramInfo(program))
877 if (i >= program.audioStreams.size())
880 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
881 info.m_description = "MPEG";
882 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
883 info.m_description = "AC3";
884 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
885 info.m_description = "DTS";
887 info.m_description = "???";
889 if (program.audioStreams[i].component_tag != -1)
891 ePtr<eServiceEvent> evt;
892 if (!m_event_handler.getEvent(evt, 0))
894 ePtr<eComponentData> data;
895 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
896 info.m_language = data->getText();
900 if (info.m_language.empty())
901 info.m_language = program.audioStreams[i].language_code;
906 int eDVBServicePlay::selectAudioStream(int i)
908 eDVBServicePMTHandler::program program;
910 if (m_service_handler.getProgramInfo(program))
913 if ((unsigned int)i >= program.audioStreams.size())
919 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
922 if (m_dvb_service && !m_is_pvr)
924 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
926 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
927 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
930 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
931 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
935 m_current_audio_stream = i;
940 int eDVBServicePlay::getFrontendInfo(int w)
944 eUsePtr<iDVBChannel> channel;
945 if(m_service_handler.getChannel(channel))
947 ePtr<iDVBFrontend> fe;
948 if(channel->getFrontend(fe))
950 return fe->readFrontendData(w);
953 int eDVBServicePlay::getNumberOfSubservices()
955 ePtr<eServiceEvent> evt;
956 if (!m_event_handler.getEvent(evt, 0))
957 return evt->getNumOfLinkageServices();
961 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
963 ePtr<eServiceEvent> evt;
964 if (!m_event_handler.getEvent(evt, 0))
966 if (!evt->getLinkageService(sub, m_reference, n))
969 sub.type=eServiceReference::idInvalid;
973 RESULT eDVBServicePlay::startTimeshift()
975 ePtr<iDVBDemux> demux;
977 eDebug("Start timeshift!");
979 if (m_timeshift_enabled)
982 /* start recording with the data demux. */
983 if (m_service_handler.getDataDemux(demux))
986 demux->createTSRecorder(m_record);
990 char templ[]="/media/hdd/timeshift.XXXXXX";
991 m_timeshift_fd = mkstemp(templ);
992 m_timeshift_file = templ;
994 eDebug("recording to %s", templ);
996 if (m_timeshift_fd < 0)
1002 m_record->setTargetFD(m_timeshift_fd);
1004 m_timeshift_enabled = 1;
1006 updateTimeshiftPids();
1012 RESULT eDVBServicePlay::stopTimeshift()
1014 if (!m_timeshift_enabled)
1019 m_timeshift_enabled = 0;
1024 close(m_timeshift_fd);
1025 remove(m_timeshift_file.c_str());
1027 eDebug("timeshift disabled");
1031 void eDVBServicePlay::updateTimeshiftPids()
1036 eDVBServicePMTHandler::program program;
1037 if (m_service_handler.getProgramInfo(program))
1041 std::set<int> pids_to_record;
1042 pids_to_record.insert(0); // PAT
1043 if (program.pmtPid != -1)
1044 pids_to_record.insert(program.pmtPid); // PMT
1046 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1047 i(program.videoStreams.begin());
1048 i != program.videoStreams.end(); ++i)
1049 pids_to_record.insert(i->pid);
1051 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1052 i(program.audioStreams.begin());
1053 i != program.audioStreams.end(); ++i)
1054 pids_to_record.insert(i->pid);
1056 std::set<int> new_pids, obsolete_pids;
1058 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1059 m_pids_active.begin(), m_pids_active.end(),
1060 std::inserter(new_pids, new_pids.begin()));
1062 std::set_difference(
1063 m_pids_active.begin(), m_pids_active.end(),
1064 pids_to_record.begin(), pids_to_record.end(),
1065 std::inserter(new_pids, new_pids.begin())
1068 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1069 m_record->addPID(*i);
1071 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1072 m_record->removePID(*i);
1076 void eDVBServicePlay::switchToLive()
1078 eDebug("SwitchToLive");
1079 if (!m_timeshift_active)
1084 /* free the timeshift service handler, we need the resources */
1085 m_service_handler_timeshift.free();
1086 m_timeshift_active = 0;
1091 void eDVBServicePlay::switchToTimeshift()
1093 eDebug("SwitchToTimeshift");
1094 if (m_timeshift_active)
1100 m_timeshift_active = 1;
1102 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1103 r.path = m_timeshift_file;
1105 eDebug("ok, re-tuning to %s", r.toString().c_str());
1106 m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
1109 void eDVBServicePlay::updateDecoder()
1111 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1;
1112 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1114 eDVBServicePMTHandler::program program;
1115 if (h.getProgramInfo(program))
1116 eDebug("getting program info failed.");
1119 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1120 if (!program.videoStreams.empty())
1122 eDebugNoNewLine(" (");
1123 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1124 i(program.videoStreams.begin());
1125 i != program.videoStreams.end(); ++i)
1129 if (i != program.videoStreams.begin())
1130 eDebugNoNewLine(", ");
1131 eDebugNoNewLine("%04x", i->pid);
1133 eDebugNoNewLine(")");
1135 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1136 if (!program.audioStreams.empty())
1138 eDebugNoNewLine(" (");
1139 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1140 i(program.audioStreams.begin());
1141 i != program.audioStreams.end(); ++i)
1148 if (i != program.audioStreams.begin())
1149 eDebugNoNewLine(", ");
1150 eDebugNoNewLine("%04x", i->pid);
1152 eDebugNoNewLine(")");
1154 eDebug(", and the pcr pid is %04x", program.pcrPid);
1155 if (program.pcrPid != 0x1fff)
1156 pcrpid = program.pcrPid;
1161 h.getDecodeDemux(m_decode_demux);
1163 m_decode_demux->getMPEGDecoder(m_decoder);
1168 m_decoder->setVideoPID(vpid);
1169 m_current_audio_stream = 0;
1170 m_decoder->setAudioPID(apid, apidtype);
1171 if (!(m_is_pvr || m_timeshift_active))
1172 m_decoder->setSyncPCR(pcrpid);
1174 m_decoder->setSyncPCR(-1);
1176 // how we can do this better?
1177 // update cache pid when the user changed the audio track or video track
1178 // TODO handling of difference audio types.. default audio types..
1180 /* don't worry about non-existing services, nor pvr services */
1181 if (m_dvb_service && !m_is_pvr)
1183 if (apidtype == eDVBAudio::aMPEG)
1185 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1186 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1190 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1191 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1193 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1194 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1199 DEFINE_REF(eDVBServicePlay)
1201 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");