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>
18 class eStaticServiceDVBInformation: public iStaticServiceInformation
20 DECLARE_REF(eStaticServiceDVBInformation);
22 RESULT getName(const eServiceReference &ref, std::string &name);
23 int getLength(const eServiceReference &ref);
26 DEFINE_REF(eStaticServiceDVBInformation);
28 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
30 eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
31 if ( !ref.name.empty() )
33 if (service.getParentTransportStreamID().get()) // linkage subservice
35 ePtr<iServiceHandler> service_center;
36 if (!eServiceCenter::getInstance(service_center))
38 eServiceReferenceDVB parent = service;
39 parent.setTransportStreamID( service.getParentTransportStreamID() );
40 parent.setServiceID( service.getParentServiceID() );
41 parent.setParentTransportStreamID(eTransportStreamID(0));
42 parent.setParentServiceID(eServiceID(0));
44 ePtr<iStaticServiceInformation> service_info;
45 if (!service_center->info(parent, service_info))
47 if (!service_info->getName(parent, name))
49 // just show short name
50 unsigned int pos = name.find("\xc2\x86");
51 if ( pos != std::string::npos )
53 pos = name.find("\xc2\x87");
54 if ( pos != std::string::npos )
70 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
75 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
77 DECLARE_REF(eStaticServiceDVBBouquetInformation);
79 RESULT getName(const eServiceReference &ref, std::string &name);
80 int getLength(const eServiceReference &ref);
83 DEFINE_REF(eStaticServiceDVBBouquetInformation);
85 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
87 ePtr<iDVBChannelList> db;
88 ePtr<eDVBResourceManager> res;
91 if ((err = eDVBResourceManager::getInstance(res)) != 0)
93 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
96 if ((err = res->getChannelList(db)) != 0)
98 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
103 if ((err = db->getBouquet(ref, bouquet)) != 0)
105 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
109 if ( bouquet && bouquet->m_bouquet_name.length() )
111 name = bouquet->m_bouquet_name;
118 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
123 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
125 DECLARE_REF(eStaticServiceDVBPVRInformation);
126 eServiceReference m_ref;
127 eDVBMetaParser m_parser;
129 eStaticServiceDVBPVRInformation(const eServiceReference &ref);
130 RESULT getName(const eServiceReference &ref, std::string &name);
131 int getLength(const eServiceReference &ref);
133 int getInfo(const eServiceReference &ref, int w);
134 std::string getInfoString(const eServiceReference &ref,int w);
137 DEFINE_REF(eStaticServiceDVBPVRInformation);
139 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
142 m_parser.parseFile(ref.path);
145 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
147 ASSERT(ref == m_ref);
148 name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
152 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
154 ASSERT(ref == m_ref);
158 if (tstools.openFile(ref.path.c_str()))
162 if (tstools.calcLen(len))
168 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
172 case iServiceInformation::sDescription:
173 return iServiceInformation::resIsString;
174 case iServiceInformation::sTimeCreate:
175 if (m_parser.m_time_create)
176 return m_parser.m_time_create;
178 return iServiceInformation::resNA;
180 return iServiceInformation::resNA;
184 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
188 case iServiceInformation::sDescription:
189 return m_parser.m_description;
195 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
197 DECLARE_REF(eDVBPVRServiceOfflineOperations);
198 eServiceReferenceDVB m_ref;
200 eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
202 RESULT deleteFromDisk(int simulate);
203 RESULT getListOfFilenames(std::list<std::string> &);
206 DEFINE_REF(eDVBPVRServiceOfflineOperations);
208 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
212 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
218 std::list<std::string> res;
219 if (getListOfFilenames(res))
222 /* TODO: deferred removing.. */
223 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
225 eDebug("Removing %s...", i->c_str());
226 ::unlink(i->c_str());
233 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
236 res.push_back(m_ref.path);
237 res.push_back(m_ref.path + ".meta");
241 DEFINE_REF(eServiceFactoryDVB)
243 eServiceFactoryDVB::eServiceFactoryDVB()
245 ePtr<eServiceCenter> sc;
247 eServiceCenter::getPrivInstance(sc);
249 sc->addServiceFactory(eServiceFactoryDVB::id, this);
252 eServiceFactoryDVB::~eServiceFactoryDVB()
254 ePtr<eServiceCenter> sc;
256 eServiceCenter::getPrivInstance(sc);
258 sc->removeServiceFactory(eServiceFactoryDVB::id);
261 DEFINE_REF(eDVBServiceList);
263 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
267 eDVBServiceList::~eDVBServiceList()
271 RESULT eDVBServiceList::startQuery()
273 ePtr<iDVBChannelList> db;
274 ePtr<eDVBResourceManager> res;
277 if ((err = eDVBResourceManager::getInstance(res)) != 0)
279 eDebug("no resource manager");
282 if ((err = res->getChannelList(db)) != 0)
284 eDebug("no channel list");
288 ePtr<eDVBChannelQuery> q;
290 if (!m_parent.path.empty())
292 eDVBChannelQuery::compile(q, m_parent.path);
295 eDebug("compile query failed");
300 if ((err = db->startQuery(m_query, q, m_parent)) != 0)
302 eDebug("startQuery failed");
309 RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
311 eServiceReferenceDVB ref;
313 if (!m_query || !list || !PyList_Check(list))
316 std::list<eServiceReferenceDVB> tmplist;
318 while (!m_query->getNextResult(ref))
319 tmplist.push_back(ref);
322 tmplist.sort(iListableServiceCompare(this));
324 for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
325 it != tmplist.end(); ++it)
327 PyObject *refobj = New_eServiceReference(*it);
328 PyList_Append(list, refobj);
334 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
336 eServiceReferenceDVB ref;
341 while (!m_query->getNextResult(ref))
345 list.sort(iListableServiceCompare(this));
350 RESULT eDVBServiceList::getNext(eServiceReference &ref)
355 return m_query->getNextResult((eServiceReferenceDVB&)ref);
358 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
360 return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
363 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
365 if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
367 ePtr<iDVBChannelList> db;
368 ePtr<eDVBResourceManager> resm;
370 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
373 if (db->getBouquet(m_parent, m_bouquet) != 0)
384 RESULT eDVBServiceList::addService(eServiceReference &ref)
388 return m_bouquet->addService(ref);
391 RESULT eDVBServiceList::removeService(eServiceReference &ref)
395 return m_bouquet->removeService(ref);
398 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
402 return m_bouquet->moveService(ref, pos);
405 RESULT eDVBServiceList::flushChanges()
409 return m_bouquet->flushChanges();
412 RESULT eDVBServiceList::setListName(const std::string &name)
416 return m_bouquet->setListName(name);
419 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
421 ePtr<eDVBService> service;
422 int r = lookupService(service, ref);
425 // check resources...
426 ptr = new eDVBServicePlay(ref, service);
430 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
432 if (ref.path.empty())
434 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
443 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
445 ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
446 if (list->startQuery())
456 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
458 /* is a listable service? */
459 if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
461 if ( !ref.name.empty() ) // satellites or providers list
462 ptr = new eStaticServiceDVBInformation;
463 else // a dvb bouquet
464 ptr = new eStaticServiceDVBBouquetInformation;
466 else if (!ref.path.empty()) /* do we have a PVR service? */
467 ptr = new eStaticServiceDVBPVRInformation(ref);
468 else // normal dvb service
470 ePtr<eDVBService> service;
471 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
472 ptr = new eStaticServiceDVBInformation;
474 /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
480 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
482 if (ref.path.empty())
488 ptr = new eDVBPVRServiceOfflineOperations(ref);
493 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
495 // TODO: handle the listing itself
496 // if (ref.... == -1) .. return "... bouquets ...";
497 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
499 ePtr<iDVBChannelList> db;
500 ePtr<eDVBResourceManager> res;
503 if ((err = eDVBResourceManager::getInstance(res)) != 0)
505 eDebug("no resource manager");
508 if ((err = res->getChannelList(db)) != 0)
510 eDebug("no channel list");
514 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
515 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
517 eDebug("getService failed!");
524 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
525 m_reference(ref), m_dvb_service(service), m_is_paused(0)
527 m_is_pvr = !ref.path.empty();
528 m_timeshift_enabled = m_timeshift_active = 0;
530 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
531 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
532 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
535 eDVBServicePlay::~eDVBServicePlay()
539 void eDVBServicePlay::gotNewEvent()
543 ePtr<eServiceEvent> m_event_now, m_event_next;
544 getEvent(m_event_now, 0);
545 getEvent(m_event_next, 1);
548 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
550 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
552 m_event((iPlayableService*)this, evUpdatedEventInfo);
555 void eDVBServicePlay::serviceEvent(int event)
559 case eDVBServicePMTHandler::eventTuned:
561 ePtr<iDVBDemux> m_demux;
562 if (!m_service_handler.getDataDemux(m_demux))
564 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
565 int sid = ref.getParentServiceID().get();
567 sid = ref.getServiceID().get();
568 if ( ref.getParentTransportStreamID().get() &&
569 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
570 m_event_handler.startOther(m_demux, sid);
572 m_event_handler.start(m_demux, sid);
576 case eDVBServicePMTHandler::eventTuneFailed:
578 eDebug("DVB service failed to tune");
579 m_event((iPlayableService*)this, evTuneFailed);
582 case eDVBServicePMTHandler::eventNewProgramInfo:
584 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
585 if (m_timeshift_enabled)
586 updateTimeshiftPids();
587 if (!m_timeshift_active)
589 m_event((iPlayableService*)this, evUpdatedInfo);
592 case eDVBServicePMTHandler::eventEOF:
594 m_event((iPlayableService*)this, evEnd);
600 void eDVBServicePlay::serviceEventTimeshift(int event)
604 case eDVBServicePMTHandler::eventNewProgramInfo:
605 if (m_timeshift_active)
608 case eDVBServicePMTHandler::eventEOF:
614 RESULT eDVBServicePlay::start()
617 /* in pvr mode, we only want to use one demux. in tv mode, we're using
618 two (one for decoding, one for data source), as we must be prepared
619 to start recording from the data demux. */
620 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr);
621 m_event(this, evStart);
622 m_event((iPlayableService*)this, evSeekableStatusChanged);
626 RESULT eDVBServicePlay::stop()
631 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
633 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
637 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
639 /* note: we check for timeshift to be enabled,
640 not neccessary active. if you pause when timeshift
641 is not active, you should activate it when unpausing */
642 if ((!m_is_pvr) && (!m_timeshift_enabled))
652 RESULT eDVBServicePlay::setSlowMotion(int ratio)
655 return m_decoder->setSlowMotion(ratio);
660 RESULT eDVBServicePlay::setFastForward(int ratio)
663 return m_decoder->setFastForward(ratio);
668 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
670 if (m_is_pvr || m_timeshift_active)
680 RESULT eDVBServicePlay::getLength(pts_t &len)
682 ePtr<iDVBPVRChannel> pvr_channel;
684 if (m_service_handler.getPVRChannel(pvr_channel))
686 eDebug("getPVRChannel failed!");
690 return pvr_channel->getLength(len);
693 RESULT eDVBServicePlay::pause()
695 if (!m_is_paused && m_decoder)
698 return m_decoder->freeze(0);
703 RESULT eDVBServicePlay::unpause()
705 if (m_is_paused && m_decoder)
708 return m_decoder->unfreeze();
713 RESULT eDVBServicePlay::seekTo(pts_t to)
715 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
720 ePtr<iDVBPVRChannel> pvr_channel;
722 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
725 return pvr_channel->seekTo(m_decode_demux, 0, to);
728 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
730 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
735 ePtr<iDVBPVRChannel> pvr_channel;
737 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
742 return pvr_channel->seekTo(m_decode_demux, 1, to);
745 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
747 ePtr<iDVBPVRChannel> pvr_channel;
752 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
755 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
758 RESULT eDVBServicePlay::setTrickmode(int trick)
761 m_decoder->setTrickmode(trick);
765 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
771 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
777 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
783 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
789 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
791 if (m_timeshift_enabled || !m_is_pvr)
800 RESULT eDVBServicePlay::getName(std::string &name)
804 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
805 return i->getName(m_reference, name);
809 m_dvb_service->getName(m_reference, name);
813 else if (!m_reference.name.empty())
814 eStaticServiceDVBInformation().getName(m_reference, name);
816 name = "DVB service";
820 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
822 return m_event_handler.getEvent(evt, nownext);
825 int eDVBServicePlay::getInfo(int w)
827 eDVBServicePMTHandler::program program;
829 if (m_service_handler.getProgramInfo(program))
835 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
837 ePtr<eServiceEvent> evt;
838 if (!m_event_handler.getEvent(evt, 0))
840 ePtr<eComponentData> data;
841 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
843 if ( data->getStreamContent() == 1 )
845 switch(data->getComponentType())
848 case 1: // 4:3 SD PAL
850 case 3: // 16:9 SD PAL
851 case 4: // > 16:9 PAL
852 case 5: // 4:3 SD NTSC
854 case 7: // 16:9 SD NTSC
855 case 8: // > 16:9 NTSC
858 case 9: // 4:3 HD PAL
860 case 0xB: // 16:9 HD PAL
861 case 0xC: // > 16:9 HD PAL
862 case 0xD: // 4:3 HD NTSC
864 case 0xF: // 16:9 HD NTSC
865 case 0x10: // > 16:9 HD PAL
866 return data->getComponentType();
873 case sIsCrypted: return program.isCrypted;
874 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
875 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
876 case sPCRPID: return program.pcrPid;
877 case sPMTPID: return program.pmtPid;
878 case sTXTPID: return program.textPid;
879 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
880 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
881 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
882 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
883 case sProvider: if (!m_dvb_service) return -1; return -2;
889 std::string eDVBServicePlay::getInfoString(int w)
894 if (!m_dvb_service) return "";
895 return m_dvb_service->m_provider_name;
901 int eDVBServicePlay::getNumberOfTracks()
903 eDVBServicePMTHandler::program program;
904 if (m_service_handler.getProgramInfo(program))
906 return program.audioStreams.size();
909 RESULT eDVBServicePlay::selectTrack(unsigned int i)
911 int ret = selectAudioStream(i);
913 if (m_decoder->start())
919 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
921 eDVBServicePMTHandler::program program;
923 if (m_service_handler.getProgramInfo(program))
926 if (i >= program.audioStreams.size())
929 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
930 info.m_description = "MPEG";
931 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
932 info.m_description = "AC3";
933 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
934 info.m_description = "DTS";
936 info.m_description = "???";
938 if (program.audioStreams[i].component_tag != -1)
940 ePtr<eServiceEvent> evt;
941 if (!m_event_handler.getEvent(evt, 0))
943 ePtr<eComponentData> data;
944 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
945 info.m_language = data->getText();
949 if (info.m_language.empty())
950 info.m_language = program.audioStreams[i].language_code;
955 int eDVBServicePlay::selectAudioStream(int i)
957 eDVBServicePMTHandler::program program;
959 if (m_service_handler.getProgramInfo(program))
962 if ((unsigned int)i >= program.audioStreams.size())
968 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
971 if (m_dvb_service && !m_is_pvr)
973 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
975 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
976 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
979 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
980 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
984 m_current_audio_stream = i;
989 int eDVBServicePlay::getFrontendInfo(int w)
993 eUsePtr<iDVBChannel> channel;
994 if(m_service_handler.getChannel(channel))
996 ePtr<iDVBFrontend> fe;
997 if(channel->getFrontend(fe))
999 return fe->readFrontendData(w);
1002 int eDVBServicePlay::getNumberOfSubservices()
1004 ePtr<eServiceEvent> evt;
1005 if (!m_event_handler.getEvent(evt, 0))
1006 return evt->getNumOfLinkageServices();
1010 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1012 ePtr<eServiceEvent> evt;
1013 if (!m_event_handler.getEvent(evt, 0))
1015 if (!evt->getLinkageService(sub, m_reference, n))
1018 sub.type=eServiceReference::idInvalid;
1022 RESULT eDVBServicePlay::startTimeshift()
1024 ePtr<iDVBDemux> demux;
1026 eDebug("Start timeshift!");
1028 if (m_timeshift_enabled)
1031 /* start recording with the data demux. */
1032 if (m_service_handler.getDataDemux(demux))
1035 demux->createTSRecorder(m_record);
1039 char templ[]="/media/hdd/timeshift.XXXXXX";
1040 m_timeshift_fd = mkstemp(templ);
1041 m_timeshift_file = templ;
1043 eDebug("recording to %s", templ);
1045 if (m_timeshift_fd < 0)
1051 m_record->setTargetFD(m_timeshift_fd);
1053 m_timeshift_enabled = 1;
1055 updateTimeshiftPids();
1061 RESULT eDVBServicePlay::stopTimeshift()
1063 if (!m_timeshift_enabled)
1068 m_timeshift_enabled = 0;
1073 close(m_timeshift_fd);
1074 remove(m_timeshift_file.c_str());
1079 int eDVBServicePlay::isTimeshiftActive()
1081 return m_timeshift_enabled && m_timeshift_active;
1084 RESULT eDVBServicePlay::activateTimeshift()
1086 if (!m_timeshift_enabled)
1089 if (!m_timeshift_active)
1091 switchToTimeshift();
1098 void eDVBServicePlay::updateTimeshiftPids()
1103 eDVBServicePMTHandler::program program;
1104 if (m_service_handler.getProgramInfo(program))
1108 std::set<int> pids_to_record;
1109 pids_to_record.insert(0); // PAT
1110 if (program.pmtPid != -1)
1111 pids_to_record.insert(program.pmtPid); // PMT
1113 if (program.textPid != -1)
1114 pids_to_record.insert(program.textPid); // Videotext
1116 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1117 i(program.videoStreams.begin());
1118 i != program.videoStreams.end(); ++i)
1119 pids_to_record.insert(i->pid);
1121 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1122 i(program.audioStreams.begin());
1123 i != program.audioStreams.end(); ++i)
1124 pids_to_record.insert(i->pid);
1126 std::set<int> new_pids, obsolete_pids;
1128 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1129 m_pids_active.begin(), m_pids_active.end(),
1130 std::inserter(new_pids, new_pids.begin()));
1132 std::set_difference(
1133 m_pids_active.begin(), m_pids_active.end(),
1134 pids_to_record.begin(), pids_to_record.end(),
1135 std::inserter(new_pids, new_pids.begin())
1138 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1139 m_record->addPID(*i);
1141 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1142 m_record->removePID(*i);
1146 void eDVBServicePlay::switchToLive()
1148 if (!m_timeshift_active)
1153 /* free the timeshift service handler, we need the resources */
1154 m_service_handler_timeshift.free();
1155 m_timeshift_active = 0;
1157 m_event((iPlayableService*)this, evSeekableStatusChanged);
1162 void eDVBServicePlay::switchToTimeshift()
1164 if (m_timeshift_active)
1170 m_timeshift_active = 1;
1172 m_event((iPlayableService*)this, evSeekableStatusChanged);
1174 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1175 r.path = m_timeshift_file;
1177 m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
1180 void eDVBServicePlay::updateDecoder()
1182 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1183 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1185 eDVBServicePMTHandler::program program;
1186 if (h.getProgramInfo(program))
1187 eDebug("getting program info failed.");
1190 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1191 if (!program.videoStreams.empty())
1193 eDebugNoNewLine(" (");
1194 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1195 i(program.videoStreams.begin());
1196 i != program.videoStreams.end(); ++i)
1200 if (i != program.videoStreams.begin())
1201 eDebugNoNewLine(", ");
1202 eDebugNoNewLine("%04x", i->pid);
1204 eDebugNoNewLine(")");
1206 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1207 if (!program.audioStreams.empty())
1209 eDebugNoNewLine(" (");
1210 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1211 i(program.audioStreams.begin());
1212 i != program.audioStreams.end(); ++i)
1219 if (i != program.audioStreams.begin())
1220 eDebugNoNewLine(", ");
1221 eDebugNoNewLine("%04x", i->pid);
1223 eDebugNoNewLine(")");
1225 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1226 pcrpid = program.pcrPid;
1227 eDebug(", and the text pid is %04x", program.textPid);
1228 tpid = program.textPid;
1233 h.getDecodeDemux(m_decode_demux);
1235 m_decode_demux->getMPEGDecoder(m_decoder);
1240 m_decoder->setVideoPID(vpid);
1241 m_current_audio_stream = 0;
1242 m_decoder->setAudioPID(apid, apidtype);
1243 if (!(m_is_pvr || m_timeshift_active))
1244 m_decoder->setSyncPCR(pcrpid);
1246 m_decoder->setSyncPCR(-1);
1247 m_decoder->setTextPID(tpid);
1249 // how we can do this better?
1250 // update cache pid when the user changed the audio track or video track
1251 // TODO handling of difference audio types.. default audio types..
1253 /* don't worry about non-existing services, nor pvr services */
1254 if (m_dvb_service && !m_is_pvr)
1256 if (apidtype == eDVBAudio::aMPEG)
1258 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1259 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1263 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1264 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1266 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1267 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1268 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1273 DEFINE_REF(eDVBServicePlay)
1275 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");