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_service_handler(0), m_is_paused(0)
490 m_is_pvr = !ref.path.empty();
491 m_timeshift_enabled = 0;
493 CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
494 CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
497 eDVBServicePlay::~eDVBServicePlay()
501 void eDVBServicePlay::gotNewEvent()
505 ePtr<eServiceEvent> m_event_now, m_event_next;
506 getEvent(m_event_now, 0);
507 getEvent(m_event_next, 1);
510 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
512 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
514 m_event((iPlayableService*)this, evUpdatedEventInfo);
517 void eDVBServicePlay::serviceEvent(int event)
521 case eDVBServicePMTHandler::eventTuned:
523 ePtr<iDVBDemux> m_demux;
524 if (!m_service_handler.getDemux(m_demux))
526 eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
527 int sid = ref.getParentServiceID().get();
529 sid = ref.getServiceID().get();
530 if ( ref.getParentTransportStreamID().get() &&
531 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
532 m_event_handler.startOther(m_demux, sid);
534 m_event_handler.start(m_demux, sid);
538 case eDVBServicePMTHandler::eventTuneFailed:
540 eDebug("DVB service failed to tune");
541 m_event((iPlayableService*)this, evTuneFailed);
544 case eDVBServicePMTHandler::eventNewProgramInfo:
546 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1;
547 eDVBServicePMTHandler::program program;
548 if (m_service_handler.getProgramInfo(program))
549 eDebug("getting program info failed.");
552 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
553 if (!program.videoStreams.empty())
555 eDebugNoNewLine(" (");
556 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
557 i(program.videoStreams.begin());
558 i != program.videoStreams.end(); ++i)
562 if (i != program.videoStreams.begin())
563 eDebugNoNewLine(", ");
564 eDebugNoNewLine("%04x", i->pid);
566 eDebugNoNewLine(")");
568 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
569 if (!program.audioStreams.empty())
571 eDebugNoNewLine(" (");
572 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
573 i(program.audioStreams.begin());
574 i != program.audioStreams.end(); ++i)
581 if (i != program.audioStreams.begin())
582 eDebugNoNewLine(", ");
583 eDebugNoNewLine("%04x", i->pid);
585 eDebugNoNewLine(")");
587 eDebug(", and the pcr pid is %04x", program.pcrPid);
588 if (program.pcrPid != 0x1fff)
589 pcrpid = program.pcrPid;
594 ePtr<iDVBDemux> demux;
595 m_service_handler.getDemux(demux);
597 demux->getMPEGDecoder(m_decoder);
602 m_decoder->setVideoPID(vpid);
603 m_current_audio_stream = 0;
604 m_decoder->setAudioPID(apid, apidtype);
606 m_decoder->setSyncPCR(pcrpid);
608 m_decoder->setSyncPCR(-1);
610 // how we can do this better?
611 // update cache pid when the user changed the audio track or video track
612 // TODO handling of difference audio types.. default audio types..
614 /* don't worry about non-existing services, nor pvr services */
615 if (m_dvb_service && !m_is_pvr)
617 if (apidtype == eDVBAudio::aMPEG)
619 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
620 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
624 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
625 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
627 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
628 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
632 m_event((iPlayableService*)this, evUpdatedInfo);
638 RESULT eDVBServicePlay::start()
641 eDebug("starting DVB service");
642 r = m_service_handler.tune((eServiceReferenceDVB&)m_reference);
643 eDebug("tune result: %d", r);
644 m_event(this, evStart);
648 RESULT eDVBServicePlay::stop()
650 eDebug("stopping..");
654 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
656 connection = new eConnection((iPlayableService*)this, m_event.connect(event));
660 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
672 RESULT eDVBServicePlay::setSlowMotion(int ratio)
675 return m_decoder->setSlowMotion(ratio);
680 RESULT eDVBServicePlay::setFastForward(int ratio)
683 return m_decoder->setFastForward(ratio);
688 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
700 RESULT eDVBServicePlay::getLength(pts_t &len)
702 ePtr<iDVBPVRChannel> pvr_channel;
704 if (m_service_handler.getPVRChannel(pvr_channel))
706 eDebug("getPVRChannel failed!");
710 return pvr_channel->getLength(len);
713 RESULT eDVBServicePlay::pause()
715 if (!m_is_paused && m_decoder)
718 return m_decoder->freeze(0);
723 RESULT eDVBServicePlay::unpause()
725 if (m_is_paused && m_decoder)
728 return m_decoder->unfreeze();
733 RESULT eDVBServicePlay::seekTo(pts_t to)
735 eDebug("eDVBServicePlay::seekTo: jump %lld", to);
737 ePtr<iDVBPVRChannel> pvr_channel;
739 if (m_service_handler.getPVRChannel(pvr_channel))
742 ePtr<iDVBDemux> demux;
743 m_service_handler.getDemux(demux);
747 return pvr_channel->seekTo(demux, 0, to);
750 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
752 eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
754 ePtr<iDVBPVRChannel> pvr_channel;
756 if (m_service_handler.getPVRChannel(pvr_channel))
761 ePtr<iDVBDemux> demux;
762 m_service_handler.getDemux(demux);
766 return pvr_channel->seekTo(demux, 1, to);
769 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
771 ePtr<iDVBPVRChannel> pvr_channel;
773 if (m_service_handler.getPVRChannel(pvr_channel))
776 ePtr<iDVBDemux> demux;
777 m_service_handler.getDemux(demux);
781 return pvr_channel->getCurrentPosition(demux, pos, 1);
784 RESULT eDVBServicePlay::setTrickmode(int trick)
787 m_decoder->setTrickmode(trick);
791 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
797 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
803 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
809 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
815 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
817 if (m_timeshift_enabled || !m_is_pvr)
826 RESULT eDVBServicePlay::getName(std::string &name)
830 m_dvb_service->getName(m_reference, name);
834 else if (!m_reference.name.empty())
835 eStaticServiceDVBInformation().getName(m_reference, name);
837 name = "DVB service";
841 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
843 return m_event_handler.getEvent(evt, nownext);
846 int eDVBServicePlay::getInfo(int w)
848 eDVBServicePMTHandler::program program;
850 if (m_service_handler.getProgramInfo(program))
856 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
858 ePtr<eServiceEvent> evt;
859 if (!m_event_handler.getEvent(evt, 0))
861 ePtr<eComponentData> data;
862 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
864 if ( data->getStreamContent() == 1 )
866 switch(data->getComponentType())
869 case 1: // 4:3 SD PAL
871 case 3: // 16:9 SD PAL
872 case 4: // > 16:9 PAL
873 case 5: // 4:3 SD NTSC
875 case 7: // 16:9 SD NTSC
876 case 8: // > 16:9 NTSC
879 case 9: // 4:3 HD PAL
881 case 0xB: // 16:9 HD PAL
882 case 0xC: // > 16:9 HD PAL
883 case 0xD: // 4:3 HD NTSC
885 case 0xF: // 16:9 HD NTSC
886 case 0x10: // > 16:9 HD PAL
887 return data->getComponentType();
894 case sIsCrypted: return program.isCrypted;
895 case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
896 case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
897 case sPCRPID: return program.pcrPid;
898 case sPMTPID: return program.pmtPid;
899 case sTXTPID: return -1;
900 case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
901 case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
902 case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
903 case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
904 case sProvider: if (!m_dvb_service) return -1; return -2;
910 std::string eDVBServicePlay::getInfoString(int w)
915 if (!m_dvb_service) return "";
916 return m_dvb_service->m_provider_name;
922 int eDVBServicePlay::getNumberOfTracks()
924 eDVBServicePMTHandler::program program;
925 if (m_service_handler.getProgramInfo(program))
927 return program.audioStreams.size();
930 RESULT eDVBServicePlay::selectTrack(unsigned int i)
932 int ret = selectAudioStream(i);
934 if (m_decoder->start())
940 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
942 eDVBServicePMTHandler::program program;
944 if (m_service_handler.getProgramInfo(program))
947 if (i >= program.audioStreams.size())
950 if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
951 info.m_description = "MPEG";
952 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
953 info.m_description = "AC3";
954 else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
955 info.m_description = "DTS";
957 info.m_description = "???";
959 if (program.audioStreams[i].component_tag != -1)
961 ePtr<eServiceEvent> evt;
962 if (!m_event_handler.getEvent(evt, 0))
964 ePtr<eComponentData> data;
965 if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
966 info.m_language = data->getText();
970 if (info.m_language.empty())
971 info.m_language = program.audioStreams[i].language_code;
976 int eDVBServicePlay::selectAudioStream(int i)
978 eDVBServicePMTHandler::program program;
980 if (m_service_handler.getProgramInfo(program))
983 if ((unsigned int)i >= program.audioStreams.size())
989 if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
992 if (m_dvb_service && !m_is_pvr)
994 if (m_dvb_service && !m_is_pvr)
996 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
998 m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
999 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1003 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1004 m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1009 m_current_audio_stream = i;
1014 int eDVBServicePlay::getFrontendInfo(int w)
1018 eUsePtr<iDVBChannel> channel;
1019 if(m_service_handler.getChannel(channel))
1021 ePtr<iDVBFrontend> fe;
1022 if(channel->getFrontend(fe))
1024 return fe->readFrontendData(w);
1027 int eDVBServicePlay::getNumberOfSubservices()
1029 ePtr<eServiceEvent> evt;
1030 if (!m_event_handler.getEvent(evt, 0))
1031 return evt->getNumOfLinkageServices();
1035 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1037 ePtr<eServiceEvent> evt;
1038 if (!m_event_handler.getEvent(evt, 0))
1040 if (!evt->getLinkageService(sub, m_reference, n))
1043 sub.type=eServiceReference::idInvalid;
1047 RESULT eDVBServicePlay::startTimeshift()
1049 if (m_timeshift_enabled)
1051 eDebug("TIMESHIFT - start!");
1055 RESULT eDVBServicePlay::stopTimeshift()
1057 if (!m_timeshift_enabled)
1059 m_timeshift_enabled = 0;
1060 eDebug("timeshift disabled");
1064 DEFINE_REF(eDVBServicePlay)
1066 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");