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);
588 RESULT eDVBServicePlay::stop()
593 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
595 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
599 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
601 if ((!m_is_pvr) && (!m_timeshift_enabled))
611 RESULT eDVBServicePlay::setSlowMotion(int ratio)
614 return m_decoder->setSlowMotion(ratio);
619 RESULT eDVBServicePlay::setFastForward(int ratio)
622 return m_decoder->setFastForward(ratio);
627 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
629 if (m_is_pvr || m_timeshift_active)
639 RESULT eDVBServicePlay::getLength(pts_t &len)
641 ePtr<iDVBPVRChannel> pvr_channel;
643 if (m_service_handler.getPVRChannel(pvr_channel))
645 eDebug("getPVRChannel failed!");
649 return pvr_channel->getLength(len);
652 RESULT eDVBServicePlay::pause()
654 if (!m_is_paused && m_decoder)
657 return m_decoder->freeze(0);
662 RESULT eDVBServicePlay::unpause()
664 if (m_is_paused && m_decoder)
667 return m_decoder->unfreeze();
672 RESULT eDVBServicePlay::seekTo(pts_t to)
674 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
679 ePtr<iDVBPVRChannel> pvr_channel;
681 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
684 return pvr_channel->seekTo(m_decode_demux, 0, to);
687 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
689 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
694 ePtr<iDVBPVRChannel> pvr_channel;
696 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
701 return pvr_channel->seekTo(m_decode_demux, 1, to);
704 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
706 ePtr<iDVBPVRChannel> pvr_channel;
711 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
714 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
717 RESULT eDVBServicePlay::setTrickmode(int trick)
720 m_decoder->setTrickmode(trick);
724 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
730 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
736 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
742 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
748 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
750 if (m_timeshift_enabled || !m_is_pvr)
759 RESULT eDVBServicePlay::getName(std::string &name)
763 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
764 return i->getName(m_reference, name);
768 m_dvb_service->getName(m_reference, name);
772 else if (!m_reference.name.empty())
773 eStaticServiceDVBInformation().getName(m_reference, name);
775 name = "DVB service";
779 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
781 return m_event_handler.getEvent(evt, nownext);
784 int eDVBServicePlay::getInfo(int w)
786 eDVBServicePMTHandler::program program;
788 if (m_service_handler.getProgramInfo(program))
794 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
796 ePtr<eServiceEvent> evt;
797 if (!m_event_handler.getEvent(evt, 0))
799 ePtr<eComponentData> data;
800 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
802 if ( data->getStreamContent() == 1 )
804 switch(data->getComponentType())
807 case 1: // 4:3 SD PAL
809 case 3: // 16:9 SD PAL
810 case 4: // > 16:9 PAL
811 case 5: // 4:3 SD NTSC
813 case 7: // 16:9 SD NTSC
814 case 8: // > 16:9 NTSC
817 case 9: // 4:3 HD PAL
819 case 0xB: // 16:9 HD PAL
820 case 0xC: // > 16:9 HD PAL
821 case 0xD: // 4:3 HD NTSC
823 case 0xF: // 16:9 HD NTSC
824 case 0x10: // > 16:9 HD PAL
825 return data->getComponentType();
832 case sIsCrypted: return program.isCrypted;
833 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
834 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
835 case sPCRPID: return program.pcrPid;
836 case sPMTPID: return program.pmtPid;
837 case sTXTPID: return -1;
838 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
839 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
840 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
841 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
842 case sProvider: if (!m_dvb_service) return -1; return -2;
848 std::string eDVBServicePlay::getInfoString(int w)
853 if (!m_dvb_service) return "";
854 return m_dvb_service->m_provider_name;
860 int eDVBServicePlay::getNumberOfTracks()
862 eDVBServicePMTHandler::program program;
863 if (m_service_handler.getProgramInfo(program))
865 return program.audioStreams.size();
868 RESULT eDVBServicePlay::selectTrack(unsigned int i)
870 int ret = selectAudioStream(i);
872 if (m_decoder->start())
878 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
880 eDVBServicePMTHandler::program program;
882 if (m_service_handler.getProgramInfo(program))
885 if (i >= program.audioStreams.size())
888 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
889 info.m_description = "MPEG";
890 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
891 info.m_description = "AC3";
892 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
893 info.m_description = "DTS";
895 info.m_description = "???";
897 if (program.audioStreams[i].component_tag != -1)
899 ePtr<eServiceEvent> evt;
900 if (!m_event_handler.getEvent(evt, 0))
902 ePtr<eComponentData> data;
903 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
904 info.m_language = data->getText();
908 if (info.m_language.empty())
909 info.m_language = program.audioStreams[i].language_code;
914 int eDVBServicePlay::selectAudioStream(int i)
916 eDVBServicePMTHandler::program program;
918 if (m_service_handler.getProgramInfo(program))
921 if ((unsigned int)i >= program.audioStreams.size())
927 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
930 if (m_dvb_service && !m_is_pvr)
932 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
934 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
935 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
938 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
939 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
943 m_current_audio_stream = i;
948 int eDVBServicePlay::getFrontendInfo(int w)
952 eUsePtr<iDVBChannel> channel;
953 if(m_service_handler.getChannel(channel))
955 ePtr<iDVBFrontend> fe;
956 if(channel->getFrontend(fe))
958 return fe->readFrontendData(w);
961 int eDVBServicePlay::getNumberOfSubservices()
963 ePtr<eServiceEvent> evt;
964 if (!m_event_handler.getEvent(evt, 0))
965 return evt->getNumOfLinkageServices();
969 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
971 ePtr<eServiceEvent> evt;
972 if (!m_event_handler.getEvent(evt, 0))
974 if (!evt->getLinkageService(sub, m_reference, n))
977 sub.type=eServiceReference::idInvalid;
981 RESULT eDVBServicePlay::startTimeshift()
983 ePtr<iDVBDemux> demux;
985 eDebug("Start timeshift!");
987 if (m_timeshift_enabled)
990 /* start recording with the data demux. */
991 if (m_service_handler.getDataDemux(demux))
994 demux->createTSRecorder(m_record);
998 char templ[]="/media/hdd/timeshift.XXXXXX";
999 m_timeshift_fd = mkstemp(templ);
1000 m_timeshift_file = templ;
1002 eDebug("recording to %s", templ);
1004 if (m_timeshift_fd < 0)
1010 m_record->setTargetFD(m_timeshift_fd);
1012 m_timeshift_enabled = 1;
1014 updateTimeshiftPids();
1020 RESULT eDVBServicePlay::stopTimeshift()
1022 if (!m_timeshift_enabled)
1027 m_timeshift_enabled = 0;
1032 close(m_timeshift_fd);
1033 remove(m_timeshift_file.c_str());
1035 eDebug("timeshift disabled");
1039 int eDVBServicePlay::isTimeshiftActive()
1041 return m_timeshift_enabled && m_timeshift_active;
1044 RESULT eDVBServicePlay::activateTimeshift()
1046 if (!m_timeshift_enabled)
1049 if (!m_timeshift_active)
1051 switchToTimeshift();
1058 void eDVBServicePlay::updateTimeshiftPids()
1063 eDVBServicePMTHandler::program program;
1064 if (m_service_handler.getProgramInfo(program))
1068 std::set<int> pids_to_record;
1069 pids_to_record.insert(0); // PAT
1070 if (program.pmtPid != -1)
1071 pids_to_record.insert(program.pmtPid); // PMT
1073 if (program.textPid != -1)
1074 pids_to_record.insert(program.textPid); // Videotext
1076 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1077 i(program.videoStreams.begin());
1078 i != program.videoStreams.end(); ++i)
1079 pids_to_record.insert(i->pid);
1081 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1082 i(program.audioStreams.begin());
1083 i != program.audioStreams.end(); ++i)
1084 pids_to_record.insert(i->pid);
1086 std::set<int> new_pids, obsolete_pids;
1088 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1089 m_pids_active.begin(), m_pids_active.end(),
1090 std::inserter(new_pids, new_pids.begin()));
1092 std::set_difference(
1093 m_pids_active.begin(), m_pids_active.end(),
1094 pids_to_record.begin(), pids_to_record.end(),
1095 std::inserter(new_pids, new_pids.begin())
1098 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1099 m_record->addPID(*i);
1101 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1102 m_record->removePID(*i);
1106 void eDVBServicePlay::switchToLive()
1108 eDebug("SwitchToLive");
1109 if (!m_timeshift_active)
1114 /* free the timeshift service handler, we need the resources */
1115 m_service_handler_timeshift.free();
1116 m_timeshift_active = 0;
1118 m_event((iPlayableService*)this, evSeekableStatusChanged);
1123 void eDVBServicePlay::switchToTimeshift()
1125 eDebug("SwitchToTimeshift");
1126 if (m_timeshift_active)
1132 m_timeshift_active = 1;
1134 m_event((iPlayableService*)this, evSeekableStatusChanged);
1136 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1137 r.path = m_timeshift_file;
1139 eDebug("ok, re-tuning to %s", r.toString().c_str());
1140 m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
1143 void eDVBServicePlay::updateDecoder()
1145 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1146 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1148 eDVBServicePMTHandler::program program;
1149 if (h.getProgramInfo(program))
1150 eDebug("getting program info failed.");
1153 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1154 if (!program.videoStreams.empty())
1156 eDebugNoNewLine(" (");
1157 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1158 i(program.videoStreams.begin());
1159 i != program.videoStreams.end(); ++i)
1163 if (i != program.videoStreams.begin())
1164 eDebugNoNewLine(", ");
1165 eDebugNoNewLine("%04x", i->pid);
1167 eDebugNoNewLine(")");
1169 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1170 if (!program.audioStreams.empty())
1172 eDebugNoNewLine(" (");
1173 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1174 i(program.audioStreams.begin());
1175 i != program.audioStreams.end(); ++i)
1182 if (i != program.audioStreams.begin())
1183 eDebugNoNewLine(", ");
1184 eDebugNoNewLine("%04x", i->pid);
1186 eDebugNoNewLine(")");
1188 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1189 pcrpid = program.pcrPid;
1190 eDebug(", and the text pid is %04x", program.textPid);
1191 tpid = program.textPid;
1196 h.getDecodeDemux(m_decode_demux);
1198 m_decode_demux->getMPEGDecoder(m_decoder);
1203 m_decoder->setVideoPID(vpid);
1204 m_current_audio_stream = 0;
1205 m_decoder->setAudioPID(apid, apidtype);
1206 if (!(m_is_pvr || m_timeshift_active))
1207 m_decoder->setSyncPCR(pcrpid);
1209 m_decoder->setSyncPCR(-1);
1210 m_decoder->setTextPID(tpid);
1212 // how we can do this better?
1213 // update cache pid when the user changed the audio track or video track
1214 // TODO handling of difference audio types.. default audio types..
1216 /* don't worry about non-existing services, nor pvr services */
1217 if (m_dvb_service && !m_is_pvr)
1219 if (apidtype == eDVBAudio::aMPEG)
1221 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1222 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1226 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1227 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1229 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1230 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1231 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1236 DEFINE_REF(eDVBServicePlay)
1238 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");