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;
531 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
532 CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
533 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
536 eDVBServicePlay::~eDVBServicePlay()
540 void eDVBServicePlay::gotNewEvent()
544 ePtr<eServiceEvent> m_event_now, m_event_next;
545 getEvent(m_event_now, 0);
546 getEvent(m_event_next, 1);
549 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
551 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
553 m_event((iPlayableService*)this, evUpdatedEventInfo);
556 void eDVBServicePlay::serviceEvent(int event)
560 case eDVBServicePMTHandler::eventTuned:
562 ePtr<iDVBDemux> m_demux;
563 if (!m_service_handler.getDataDemux(m_demux))
565 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
566 int sid = ref.getParentServiceID().get();
568 sid = ref.getServiceID().get();
569 if ( ref.getParentTransportStreamID().get() &&
570 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
571 m_event_handler.startOther(m_demux, sid);
573 m_event_handler.start(m_demux, sid);
577 case eDVBServicePMTHandler::eventTuneFailed:
579 eDebug("DVB service failed to tune");
580 m_event((iPlayableService*)this, evTuneFailed);
583 case eDVBServicePMTHandler::eventNewProgramInfo:
585 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
586 if (m_timeshift_enabled)
587 updateTimeshiftPids();
588 if (!m_timeshift_active)
590 m_event((iPlayableService*)this, evUpdatedInfo);
593 case eDVBServicePMTHandler::eventEOF:
594 m_event((iPlayableService*)this, evEOF);
596 case eDVBServicePMTHandler::eventSOF:
597 m_event((iPlayableService*)this, evSOF);
602 void eDVBServicePlay::serviceEventTimeshift(int event)
606 case eDVBServicePMTHandler::eventNewProgramInfo:
607 if (m_timeshift_active)
610 case eDVBServicePMTHandler::eventEOF:
616 RESULT eDVBServicePlay::start()
619 /* in pvr mode, we only want to use one demux. in tv mode, we're using
620 two (one for decoding, one for data source), as we must be prepared
621 to start recording from the data demux. */
622 m_cue = new eCueSheet();
623 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
624 m_event(this, evStart);
625 m_event((iPlayableService*)this, evSeekableStatusChanged);
629 RESULT eDVBServicePlay::stop()
631 eDebug("stop timeshift");
632 stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
634 eDebug("free ts handler");
635 m_service_handler_timeshift.free();
636 eDebug("stop service handler");
637 m_service_handler.free();
643 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
645 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
649 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
651 /* note: we check for timeshift to be enabled,
652 not neccessary active. if you pause when timeshift
653 is not active, you should activate it when unpausing */
654 if ((!m_is_pvr) && (!m_timeshift_enabled))
664 RESULT eDVBServicePlay::setSlowMotion(int ratio)
667 return m_decoder->setSlowMotion(ratio);
672 RESULT eDVBServicePlay::setFastForward(int ratio)
674 int skipmode, ffratio;
680 } else if (ratio > 0)
688 } else if (ratio < 0)
694 if (m_skipmode != skipmode)
696 eDebug("setting cue skipmode to %d", skipmode);
698 m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
701 m_skipmode = skipmode;
706 return m_decoder->setFastForward(ffratio);
709 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
711 if (m_is_pvr || m_timeshift_active)
721 RESULT eDVBServicePlay::getLength(pts_t &len)
723 ePtr<iDVBPVRChannel> pvr_channel;
725 if (m_service_handler.getPVRChannel(pvr_channel))
727 eDebug("getPVRChannel failed!");
731 return pvr_channel->getLength(len);
734 RESULT eDVBServicePlay::pause()
736 if (!m_is_paused && m_decoder)
739 return m_decoder->freeze(0);
744 RESULT eDVBServicePlay::unpause()
746 if (m_is_paused && m_decoder)
749 return m_decoder->unfreeze();
754 RESULT eDVBServicePlay::seekTo(pts_t to)
756 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
761 ePtr<iDVBPVRChannel> pvr_channel;
763 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
769 m_cue->seekTo(0, to);
773 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
775 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
780 ePtr<iDVBPVRChannel> pvr_channel;
782 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
790 m_cue->seekTo(1, to);
794 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
796 ePtr<iDVBPVRChannel> pvr_channel;
801 if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
804 return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
807 RESULT eDVBServicePlay::setTrickmode(int trick)
810 m_decoder->setTrickmode(trick);
814 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
820 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
826 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
832 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
838 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
840 if (m_timeshift_enabled || !m_is_pvr)
849 RESULT eDVBServicePlay::getName(std::string &name)
853 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
854 return i->getName(m_reference, name);
858 m_dvb_service->getName(m_reference, name);
862 else if (!m_reference.name.empty())
863 eStaticServiceDVBInformation().getName(m_reference, name);
865 name = "DVB service";
869 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
871 return m_event_handler.getEvent(evt, nownext);
874 int eDVBServicePlay::getInfo(int w)
876 eDVBServicePMTHandler::program program;
878 if (m_service_handler.getProgramInfo(program))
884 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
886 ePtr<eServiceEvent> evt;
887 if (!m_event_handler.getEvent(evt, 0))
889 ePtr<eComponentData> data;
890 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
892 if ( data->getStreamContent() == 1 )
894 switch(data->getComponentType())
897 case 1: // 4:3 SD PAL
899 case 3: // 16:9 SD PAL
900 case 4: // > 16:9 PAL
901 case 5: // 4:3 SD NTSC
903 case 7: // 16:9 SD NTSC
904 case 8: // > 16:9 NTSC
907 case 9: // 4:3 HD PAL
909 case 0xB: // 16:9 HD PAL
910 case 0xC: // > 16:9 HD PAL
911 case 0xD: // 4:3 HD NTSC
913 case 0xF: // 16:9 HD NTSC
914 case 0x10: // > 16:9 HD PAL
915 return data->getComponentType();
922 case sIsCrypted: return program.isCrypted;
923 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
924 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
925 case sPCRPID: return program.pcrPid;
926 case sPMTPID: return program.pmtPid;
927 case sTXTPID: return program.textPid;
928 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
929 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
930 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
931 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
932 case sProvider: if (!m_dvb_service) return -1; return -2;
938 std::string eDVBServicePlay::getInfoString(int w)
943 if (!m_dvb_service) return "";
944 return m_dvb_service->m_provider_name;
950 int eDVBServicePlay::getNumberOfTracks()
952 eDVBServicePMTHandler::program program;
953 if (m_service_handler.getProgramInfo(program))
955 return program.audioStreams.size();
958 RESULT eDVBServicePlay::selectTrack(unsigned int i)
960 int ret = selectAudioStream(i);
962 if (m_decoder->start())
968 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
970 eDVBServicePMTHandler::program program;
972 if (m_service_handler.getProgramInfo(program))
975 if (i >= program.audioStreams.size())
978 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
979 info.m_description = "MPEG";
980 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
981 info.m_description = "AC3";
982 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
983 info.m_description = "DTS";
985 info.m_description = "???";
987 if (program.audioStreams[i].component_tag != -1)
989 ePtr<eServiceEvent> evt;
990 if (!m_event_handler.getEvent(evt, 0))
992 ePtr<eComponentData> data;
993 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
994 info.m_language = data->getText();
998 if (info.m_language.empty())
999 info.m_language = program.audioStreams[i].language_code;
1004 int eDVBServicePlay::selectAudioStream(int i)
1006 eDVBServicePMTHandler::program program;
1008 if (m_service_handler.getProgramInfo(program))
1011 if ((unsigned int)i >= program.audioStreams.size())
1017 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1020 if (m_dvb_service && !m_is_pvr)
1022 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1024 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1025 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1028 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1029 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1033 m_current_audio_stream = i;
1038 int eDVBServicePlay::getFrontendInfo(int w)
1042 eUsePtr<iDVBChannel> channel;
1043 if(m_service_handler.getChannel(channel))
1045 ePtr<iDVBFrontend> fe;
1046 if(channel->getFrontend(fe))
1048 return fe->readFrontendData(w);
1051 int eDVBServicePlay::getNumberOfSubservices()
1053 ePtr<eServiceEvent> evt;
1054 if (!m_event_handler.getEvent(evt, 0))
1055 return evt->getNumOfLinkageServices();
1059 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1061 ePtr<eServiceEvent> evt;
1062 if (!m_event_handler.getEvent(evt, 0))
1064 if (!evt->getLinkageService(sub, m_reference, n))
1067 sub.type=eServiceReference::idInvalid;
1071 RESULT eDVBServicePlay::startTimeshift()
1073 ePtr<iDVBDemux> demux;
1075 eDebug("Start timeshift!");
1077 if (m_timeshift_enabled)
1080 /* start recording with the data demux. */
1081 if (m_service_handler.getDataDemux(demux))
1084 demux->createTSRecorder(m_record);
1088 char templ[]="/media/hdd/timeshift.XXXXXX";
1089 m_timeshift_fd = mkstemp(templ);
1090 m_timeshift_file = templ;
1092 eDebug("recording to %s", templ);
1094 if (m_timeshift_fd < 0)
1100 m_record->setTargetFD(m_timeshift_fd);
1102 m_timeshift_enabled = 1;
1104 updateTimeshiftPids();
1110 RESULT eDVBServicePlay::stopTimeshift()
1112 if (!m_timeshift_enabled)
1117 m_timeshift_enabled = 0;
1122 close(m_timeshift_fd);
1123 remove(m_timeshift_file.c_str());
1128 int eDVBServicePlay::isTimeshiftActive()
1130 return m_timeshift_enabled && m_timeshift_active;
1133 RESULT eDVBServicePlay::activateTimeshift()
1135 if (!m_timeshift_enabled)
1138 if (!m_timeshift_active)
1140 switchToTimeshift();
1147 void eDVBServicePlay::updateTimeshiftPids()
1152 eDVBServicePMTHandler::program program;
1153 if (m_service_handler.getProgramInfo(program))
1157 std::set<int> pids_to_record;
1158 pids_to_record.insert(0); // PAT
1159 if (program.pmtPid != -1)
1160 pids_to_record.insert(program.pmtPid); // PMT
1162 if (program.textPid != -1)
1163 pids_to_record.insert(program.textPid); // Videotext
1165 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1166 i(program.videoStreams.begin());
1167 i != program.videoStreams.end(); ++i)
1168 pids_to_record.insert(i->pid);
1170 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1171 i(program.audioStreams.begin());
1172 i != program.audioStreams.end(); ++i)
1173 pids_to_record.insert(i->pid);
1175 std::set<int> new_pids, obsolete_pids;
1177 std::set_difference(pids_to_record.begin(), pids_to_record.end(),
1178 m_pids_active.begin(), m_pids_active.end(),
1179 std::inserter(new_pids, new_pids.begin()));
1181 std::set_difference(
1182 m_pids_active.begin(), m_pids_active.end(),
1183 pids_to_record.begin(), pids_to_record.end(),
1184 std::inserter(new_pids, new_pids.begin())
1187 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1188 m_record->addPID(*i);
1190 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1191 m_record->removePID(*i);
1195 void eDVBServicePlay::switchToLive()
1197 if (!m_timeshift_active)
1202 /* free the timeshift service handler, we need the resources */
1203 m_service_handler_timeshift.free();
1204 m_timeshift_active = 0;
1206 m_event((iPlayableService*)this, evSeekableStatusChanged);
1211 void eDVBServicePlay::switchToTimeshift()
1213 if (m_timeshift_active)
1219 m_timeshift_active = 1;
1221 m_event((iPlayableService*)this, evSeekableStatusChanged);
1223 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1224 r.path = m_timeshift_file;
1226 m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1229 void eDVBServicePlay::updateDecoder()
1231 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1232 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1234 eDVBServicePMTHandler::program program;
1235 if (h.getProgramInfo(program))
1236 eDebug("getting program info failed.");
1239 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1240 if (!program.videoStreams.empty())
1242 eDebugNoNewLine(" (");
1243 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1244 i(program.videoStreams.begin());
1245 i != program.videoStreams.end(); ++i)
1249 if (i != program.videoStreams.begin())
1250 eDebugNoNewLine(", ");
1251 eDebugNoNewLine("%04x", i->pid);
1253 eDebugNoNewLine(")");
1255 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1256 if (!program.audioStreams.empty())
1258 eDebugNoNewLine(" (");
1259 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1260 i(program.audioStreams.begin());
1261 i != program.audioStreams.end(); ++i)
1268 if (i != program.audioStreams.begin())
1269 eDebugNoNewLine(", ");
1270 eDebugNoNewLine("%04x", i->pid);
1272 eDebugNoNewLine(")");
1274 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1275 pcrpid = program.pcrPid;
1276 eDebug(", and the text pid is %04x", program.textPid);
1277 tpid = program.textPid;
1282 h.getDecodeDemux(m_decode_demux);
1284 m_decode_demux->getMPEGDecoder(m_decoder);
1286 m_cue->setDecodingDemux(m_decode_demux);
1291 m_decoder->setVideoPID(vpid);
1292 m_current_audio_stream = 0;
1293 m_decoder->setAudioPID(apid, apidtype);
1294 if (!(m_is_pvr || m_timeshift_active))
1295 m_decoder->setSyncPCR(pcrpid);
1297 m_decoder->setSyncPCR(-1);
1298 m_decoder->setTextPID(tpid);
1300 // how we can do this better?
1301 // update cache pid when the user changed the audio track or video track
1302 // TODO handling of difference audio types.. default audio types..
1304 /* don't worry about non-existing services, nor pvr services */
1305 if (m_dvb_service && !m_is_pvr)
1307 if (apidtype == eDVBAudio::aMPEG)
1309 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1310 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1314 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1315 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1317 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1318 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1319 m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1324 DEFINE_REF(eDVBServicePlay)
1326 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");