aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/dvb/metaparser.cpp3
-rw-r--r--lib/dvb/metaparser.h1
-rw-r--r--lib/python/Components/MovieList.py16
-rw-r--r--lib/python/Components/TimerList.py5
-rw-r--r--lib/python/Screens/EpgSelection.py21
-rw-r--r--lib/python/Screens/EventView.py21
-rw-r--r--lib/python/Screens/InfoBarGenerics.py16
-rw-r--r--lib/python/Screens/TimerEdit.py38
-rw-r--r--lib/python/Screens/TimerEntry.py3
-rw-r--r--lib/service/iservice.h16
-rw-r--r--lib/service/service.cpp10
-rw-r--r--lib/service/servicedvb.cpp67
-rw-r--r--lib/service/servicedvb.h9
-rw-r--r--lib/service/servicedvbrecord.cpp60
-rw-r--r--lib/service/servicemp3.h3
15 files changed, 185 insertions, 104 deletions
diff --git a/lib/dvb/metaparser.cpp b/lib/dvb/metaparser.cpp
index 90b02c06..5c098150 100644
--- a/lib/dvb/metaparser.cpp
+++ b/lib/dvb/metaparser.cpp
@@ -34,6 +34,9 @@ int eDVBMetaParser::parseFile(const std::string &tsname)
case 2:
m_description = line;
break;
+ case 3:
+ m_time_create = atoi(line);
+ break;
default:
break;
}
diff --git a/lib/dvb/metaparser.h b/lib/dvb/metaparser.h
index 7e2b6779..60329ace 100644
--- a/lib/dvb/metaparser.h
+++ b/lib/dvb/metaparser.h
@@ -11,6 +11,7 @@ public:
eServiceReferenceDVB m_ref;
std::string m_name, m_description;
+ int m_time_create;
};
#endif
diff --git a/lib/python/Components/MovieList.py b/lib/python/Components/MovieList.py
index 9ab58704..2e010ab6 100644
--- a/lib/python/Components/MovieList.py
+++ b/lib/python/Components/MovieList.py
@@ -1,7 +1,8 @@
from HTMLComponent import *
from GUIComponent import *
+from Tools.FuzzyDate import FuzzyTime
-from enigma import eListboxPythonMultiContent, eListbox, gFont
+from enigma import eListboxPythonMultiContent, eListbox, gFont, iServiceInformation
from enigma import eServiceReference, eServiceCenter, \
eServiceCenterPtr, iListableServicePtr, \
@@ -38,8 +39,17 @@ def MovieListEntry(serviceref, serviceHandler):
len = "?:??"
res.append((0, 0, 400, 30, 0, RT_HALIGN_LEFT, info.getName(serviceref)))
- res.append((0, 30, 200, 20, 1, RT_HALIGN_LEFT, "Toller Film"))
- res.append((0, 50, 200, 20, 1, RT_HALIGN_LEFT, "Aufgenommen: irgendwann"))
+
+ description = info.getInfoString(serviceref, iServiceInformation.sDescription)
+ begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate)
+
+ begin_string = ""
+ if begin > 0:
+ t = FuzzyTime(begin)
+ begin_string = t[0] + ", " + t[1]
+
+ res.append((0, 30, 200, 20, 1, RT_HALIGN_LEFT, description))
+ res.append((0, 50, 200, 20, 1, RT_HALIGN_LEFT, begin_string))
res.append((200, 50, 200, 20, 1, RT_HALIGN_RIGHT, len))
return res
diff --git a/lib/python/Components/TimerList.py b/lib/python/Components/TimerList.py
index b1e8bf45..f4176fad 100644
--- a/lib/python/Components/TimerList.py
+++ b/lib/python/Components/TimerList.py
@@ -26,9 +26,6 @@ RT_WRAP = 32
def TimerEntryComponent(timer, processed):
res = [ timer ]
- print time.strftime("%c", time.localtime(timer.begin))
- print time.strftime("%c", time.localtime(timer.end))
-
res.append((0, 0, 400, 30, 0, RT_HALIGN_LEFT, timer.service_ref.getServiceName()))
repeatedtext = ""
days = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" ]
@@ -46,7 +43,7 @@ def TimerEntryComponent(timer, processed):
else:
res.append((0, 30, 200, 20, 1, RT_HALIGN_LEFT, repeatedtext + ("%s, %s ... %s" % (FuzzyTime(timer.begin) + FuzzyTime(timer.end)[1:]))))
- res.append((300, 0, 200, 20, 1, RT_HALIGN_RIGHT, timer.description))
+ res.append((300, 0, 200, 20, 1, RT_HALIGN_RIGHT, timer.name))
if not processed:
if timer.state == TimerEntry.StateWait:
diff --git a/lib/python/Screens/EpgSelection.py b/lib/python/Screens/EpgSelection.py
index db8be2e1..4d288b00 100644
--- a/lib/python/Screens/EpgSelection.py
+++ b/lib/python/Screens/EpgSelection.py
@@ -5,7 +5,7 @@ from Components.ActionMap import ActionMap
from Screens.EventView import EventView
from enigma import eServiceReference, eServiceEventPtr
from Screens.FixedMenu import FixedMenu
-from RecordTimer import RecordTimerEntry
+from RecordTimer import RecordTimerEntry, parseEvent
from TimerEdit import TimerEditList
from TimerEntry import TimerEntry
from ServiceReference import ServiceReference
@@ -49,24 +49,15 @@ class EPGSelection(Screen):
self.session.open(EventView, event, self.currentService, self.eventViewCallback)
def timerAdd(self):
- epg = self["list"].getCurrent()
+ event = self["list"].getCurrent()
+
+ if event is None:
+ return
- if (epg == None):
- description = "unknown event"
- else:
- description = epg.getEventName()
- # FIXME we need a timestamp here:
- begin = epg.getBeginTime()
-
- print begin
- print epg.getDuration()
- end = begin + epg.getDuration()
-
-
# FIXME only works if already playing a service
serviceref = ServiceReference(self.session.nav.getCurrentlyPlayingServiceReference())
- newEntry = RecordTimerEntry(begin, end, serviceref, epg, description)
+ newEntry = RecordTimerEntry(serviceref, *parseEvent(event))
self.session.openWithCallback(self.timerEditFinished, TimerEntry, newEntry)
def timerEditFinished(self, answer):
diff --git a/lib/python/Screens/EventView.py b/lib/python/Screens/EventView.py
index 79d548af..e3585b67 100644
--- a/lib/python/Screens/EventView.py
+++ b/lib/python/Screens/EventView.py
@@ -4,7 +4,7 @@ from Components.Label import Label
from Components.ScrollLabel import ScrollLabel
from enigma import eServiceEventPtr
from ServiceReference import ServiceReference
-from RecordTimer import RecordTimerEntry
+from RecordTimer import RecordTimerEntry, parseEvent
from TimerEntry import TimerEntry
class EventView(Screen):
@@ -38,24 +38,7 @@ class EventView(Screen):
self.cbFunc(self.setEvent, +1)
def timerAdd(self):
- epg = self.event
-
- if (epg == None):
- description = "unknown event"
- else:
- description = epg.getEventName()
- # FIXME we need a timestamp here:
- begin = epg.getBeginTime()
-
- print begin
- print epg.getDuration()
- end = begin + epg.getDuration()
-
-
- # FIXME only works if already playing a service
- serviceref = ServiceReference(self.session.nav.getCurrentlyPlayingServiceReference())
-
- newEntry = RecordTimerEntry(begin, end, serviceref, epg, description)
+ newEntry = RecordTimerEntry(self.currentService, *parseEvent(self.event))
self.session.openWithCallback(self.timerEditFinished, TimerEntry, newEntry)
def timerEditFinished(self, answer):
diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py
index efcb0dad..77c4a415 100644
--- a/lib/python/Screens/InfoBarGenerics.py
+++ b/lib/python/Screens/InfoBarGenerics.py
@@ -562,6 +562,8 @@ class InfoBarPVR:
}
self.setSeekState(lookup[self.seekstate]);
+from RecordTimer import parseEvent
+
class InfoBarInstantRecord:
"""Instant Record - handles the instantRecord action in order to
start/stop instant records"""
@@ -582,19 +584,25 @@ class InfoBarInstantRecord:
def startInstantRecording(self):
serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
-
+
# try to get event info
- epg = None
+ event = None
try:
service = self.session.nav.getCurrentService()
info = service.info()
ev = info.getEvent(0)
- epg = ev
+ event = ev
except:
pass
+ if event is not None:
+ data = parseEvent(event)
+ data = (data[0], data[1] + 3600 * 10, data[2], data[3], data[4])
+ else:
+ data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
+
# fix me, description.
- self.recording = self.session.nav.recordWithTimer(time.time(), time.time() + 3600 * 10, serviceref, epg, "instant record")
+ self.recording = self.session.nav.recordWithTimer(serviceref, *data)
self.recording.dontSave = True
#self["BlinkingPoint"].setConnect(lambda: self.recording.isRunning())
diff --git a/lib/python/Screens/TimerEdit.py b/lib/python/Screens/TimerEdit.py
index 5233da9b..73733913 100644
--- a/lib/python/Screens/TimerEdit.py
+++ b/lib/python/Screens/TimerEdit.py
@@ -6,7 +6,7 @@ from Components.Label import Label
from Components.Button import Button
from Components.TextInput import TextInput
from TimerEntry import TimerEntry
-from RecordTimer import RecordTimerEntry
+from RecordTimer import RecordTimerEntry, parseEvent
from time import *
from ServiceReference import ServiceReference
from Components.config import *
@@ -54,34 +54,22 @@ class TimerEditList(Screen):
self["timerlist"].invalidate()
def addCurrentTimer(self):
- begin = time()
- end = time() + 60
-
- epg = None
- try:
- service = self.session.nav.getCurrentService()
+ event = None
+ service = self.session.nav.getCurrentService()
+ if service is not None:
info = service.info()
- ev = info.getEvent(0)
- epg = ev
- except:
- pass
-
- if (epg == None):
- description = "unknown event"
- else:
- description = ev.getEventName()
- # FIXME we need a timestamp here:
- begin = ev.getBeginTime()
-
- print begin
- print ev.getDuration()
- end = begin + ev.getDuration()
-
+ if info is not None:
+ event = info.getEvent(0)
# FIXME only works if already playing a service
serviceref = ServiceReference(self.session.nav.getCurrentlyPlayingServiceReference())
- self.addTimer(RecordTimerEntry(begin, end, serviceref, epg, description))
+ if event is None:
+ data = (int(time()), int(time() + 60), "unknown event", "", None)
+ else:
+ data = parseEvent(event)
+
+ self.addTimer(RecordTimerEntry(serviceref, *data))
def addTimer(self, timer):
self.session.openWithCallback(self.finishedAdd, TimerEntry, timer)
@@ -103,4 +91,4 @@ class TimerEditList(Screen):
def leave(self):
self.session.nav.RecordTimer.saveTimer()
- self.close() \ No newline at end of file
+ self.close()
diff --git a/lib/python/Screens/TimerEntry.py b/lib/python/Screens/TimerEntry.py
index a7cbad9b..966bbab4 100644
--- a/lib/python/Screens/TimerEntry.py
+++ b/lib/python/Screens/TimerEntry.py
@@ -78,6 +78,7 @@ class TimerEntry(Screen):
repeated = 0
config.timerentry.type = configElement_nonSave("config.timerentry.type", configSelection, type, (_("once"), _("repeated")))
+ config.timerentry.name = configElement_nonSave("config.timerentry.name", configText, self.timer.name, (configText.extendableSize, self.keyRightCallback))
config.timerentry.description = configElement_nonSave("config.timerentry.description", configText, self.timer.description, (configText.extendableSize, self.keyRightCallback))
config.timerentry.repeated = configElement_nonSave("config.timerentry.repeated", configSelection, repeated, (_("daily"), _("weekly"), _("Mon-Fri"), _("user defined")))
@@ -126,6 +127,7 @@ class TimerEntry(Screen):
def createSetup(self):
self.list = []
+ self.list.append(getConfigListEntry(_("Name"), config.timerentry.name))
self.list.append(getConfigListEntry(_("Description"), config.timerentry.description))
self.timerTypeEntry = getConfigListEntry(_("Timer Type"), config.timerentry.type)
self.list.append(self.timerTypeEntry)
@@ -227,6 +229,7 @@ class TimerEntry(Screen):
return int(mktime(dt.timetuple()))
def keyGo(self):
+ self.timer.name = config.timerentry.name.value
self.timer.description = config.timerentry.description.value
self.timer.resetRepeated()
diff --git a/lib/service/iservice.h b/lib/service/iservice.h
index 962e4a95..285063ec 100644
--- a/lib/service/iservice.h
+++ b/lib/service/iservice.h
@@ -180,6 +180,9 @@ public:
virtual SWIG_VOID(RESULT) getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time=0);
// returns true when not implemented
virtual bool isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
+
+ virtual int getInfo(const eServiceReference &ref, int w);
+ virtual std::string getInfoString(const eServiceReference &ref,int w);
};
TEMPLATE_TYPEDEF(ePtr<iStaticServiceInformation>, iStaticServiceInformationPtr);
@@ -216,6 +219,9 @@ public:
sTSID,
sNamespace,
sProvider,
+
+ sDescription,
+ sTimeCreate, // unix time or string
};
enum { resNA = -1, resIsString = -2 };
@@ -293,6 +299,15 @@ public:
TEMPLATE_TYPEDEF(ePtr<iSubserviceList>, iSubserviceListPtr);
+class iTimeshiftService: public iObject
+{
+public:
+ virtual RESULT startTimeshift()=0;
+ virtual RESULT stopTimeshift()=0;
+};
+
+TEMPLATE_TYPEDEF(ePtr<iTimeshiftService>, iTimeshiftServicePtr);
+
class iPlayableService: public iObject
{
friend class iServiceHandler;
@@ -316,6 +331,7 @@ public:
virtual SWIG_VOID(RESULT) audioTracks(ePtr<iAudioTrackSelection> &SWIG_OUTPUT)=0;
virtual SWIG_VOID(RESULT) subServices(ePtr<iSubserviceList> &SWIG_OUTPUT)=0;
virtual SWIG_VOID(RESULT) frontendStatusInfo(ePtr<iFrontendStatusInformation> &SWIG_OUTPUT)=0;
+ virtual SWIG_VOID(RESULT) timeshift(ePtr<iTimeshiftService> &SWIG_OUTPUT)=0;
};
TEMPLATE_TYPEDEF(ePtr<iPlayableService>, iPlayableServicePtr);
diff --git a/lib/service/service.cpp b/lib/service/service.cpp
index cc8a9315..150a0cd3 100644
--- a/lib/service/service.cpp
+++ b/lib/service/service.cpp
@@ -155,6 +155,16 @@ RESULT iServiceInformation::getEvent(ePtr<eServiceEvent> &evt, int m_nownext)
return -1;
}
+int iStaticServiceInformation::getInfo(const eServiceReference &ref, int w)
+{
+ return -1;
+}
+
+std::string iStaticServiceInformation::getInfoString(const eServiceReference &ref, int w)
+{
+ return "";
+}
+
int iServiceInformation::getInfo(int w)
{
return -1;
diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp
index a9d235ec..790bfca6 100644
--- a/lib/service/servicedvb.cpp
+++ b/lib/service/servicedvb.cpp
@@ -127,6 +127,9 @@ public:
eStaticServiceDVBPVRInformation(const eServiceReference &ref);
RESULT getName(const eServiceReference &ref, std::string &name);
int getLength(const eServiceReference &ref);
+
+ int getInfo(const eServiceReference &ref, int w);
+ std::string getInfoString(const eServiceReference &ref,int w);
};
DEFINE_REF(eStaticServiceDVBPVRInformation);
@@ -160,7 +163,32 @@ int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
return len / 90000;
}
+int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
+{
+ switch (w)
+ {
+ case iServiceInformation::sDescription:
+ return iServiceInformation::resIsString;
+ case iServiceInformation::sTimeCreate:
+ if (m_parser.m_time_create)
+ return m_parser.m_time_create;
+ else
+ return iServiceInformation::resNA;
+ default:
+ return iServiceInformation::resNA;
+ }
+}
+std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
+{
+ switch (w)
+ {
+ case iServiceInformation::sDescription:
+ return m_parser.m_description;
+ default:
+ return "";
+ }
+}
class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
{
@@ -459,6 +487,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
m_reference(ref), m_dvb_service(service), m_service_handler(0), m_is_paused(0)
{
m_is_pvr = !ref.path.empty();
+ m_timeshift_enabled = 0;
CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
@@ -619,14 +648,14 @@ RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &ev
RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
{
- if (m_is_pvr)
+ if (!m_is_pvr)
{
- ptr = this;
- return 0;
+ ptr = 0;
+ return -1;
}
- ptr = 0;
- return -1;
+ ptr = this;
+ return 0;
}
RESULT eDVBServicePlay::setSlowMotion(int ratio)
@@ -753,6 +782,17 @@ RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
return 0;
}
+RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
+{
+ if (m_timeshift_enabled || !m_is_pvr)
+ {
+ ptr = this;
+ return 0;
+ }
+ ptr = 0;
+ return -1;
+}
+
RESULT eDVBServicePlay::getName(std::string &name)
{
if (m_dvb_service)
@@ -939,6 +979,23 @@ RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
return -1;
}
+RESULT eDVBServicePlay::startTimeshift()
+{
+ if (m_timeshift_enabled)
+ return -1;
+ eDebug("TIMESHIFT - start!");
+ return 0;
+}
+
+RESULT eDVBServicePlay::stopTimeshift()
+{
+ if (!m_timeshift_enabled)
+ return -1;
+ m_timeshift_enabled = 0;
+ eDebug("timeshift disabled");
+ return 0;
+}
+
DEFINE_REF(eDVBServicePlay)
eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");
diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h
index 6b93469d..e99faffd 100644
--- a/lib/service/servicedvb.h
+++ b/lib/service/servicedvb.h
@@ -55,7 +55,7 @@ private:
class eDVBServicePlay: public iPlayableService, public iPauseableService,
public iSeekableService, public Object, public iServiceInformation,
public iAudioTrackSelection, public iFrontendStatusInformation,
- public iSubserviceList
+ public iSubserviceList, public iTimeshiftService
{
DECLARE_REF(eDVBServicePlay);
public:
@@ -71,6 +71,7 @@ public:
RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr);
RESULT frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr);
RESULT subServices(ePtr<iSubserviceList> &ptr);
+ RESULT timeshift(ePtr<iTimeshiftService> &ptr);
// iPauseableService
RESULT pause();
@@ -102,6 +103,10 @@ public:
int getNumberOfSubservices();
RESULT getSubservice(eServiceReference &subservice, unsigned int n);
+ // iTimeshiftService
+ RESULT startTimeshift();
+ RESULT stopTimeshift();
+
private:
friend class eServiceFactoryDVB;
eServiceReference m_reference;
@@ -120,7 +125,7 @@ private:
void serviceEvent(int event);
Signal2<void,iPlayableService*,int> m_event;
- int m_is_pvr, m_is_paused;
+ int m_is_pvr, m_is_paused, m_timeshift_enabled;
int m_current_audio_stream;
int selectAudioStream(int n);
diff --git a/lib/service/servicedvbrecord.cpp b/lib/service/servicedvbrecord.cpp
index 2f1dea0e..f05a35a3 100644
--- a/lib/service/servicedvbrecord.cpp
+++ b/lib/service/servicedvbrecord.cpp
@@ -20,6 +20,33 @@ void eDVBServiceRecord::serviceEvent(int event)
case eDVBServicePMTHandler::eventTuned:
{
eDebug("tuned..");
+ if (!m_record)
+ {
+ eDebug("Recording to %s...", m_filename.c_str());
+ ::remove(m_filename.c_str());
+ int fd = ::open(m_filename.c_str(), O_WRONLY|O_CREAT, 0644);
+ if (fd == -1)
+ {
+ eDebug("eDVBServiceRecord - can't open hardcoded recording file!");
+ return;
+// return -1;
+ }
+ ePtr<iDVBDemux> demux;
+ if (m_service_handler.getDemux(demux))
+ {
+ eDebug("eDVBServiceRecord - NO DEMUX available!");
+ return;
+// return -2;
+ }
+ demux->createTSRecorder(m_record);
+ if (!m_record)
+ {
+ eDebug("eDVBServiceRecord - no ts recorder available.");
+ return;
+// return -3;
+ }
+ m_record->setTargetFD(fd);
+ }
break;
}
case eDVBServicePMTHandler::eventNewProgramInfo:
@@ -38,7 +65,7 @@ RESULT eDVBServiceRecord::prepare(const char *filename)
{
m_filename = filename;
if (m_state == stateIdle)
- return m_service_handler.tune(m_ref);
+ doPrepare();
else
return -1;
}
@@ -74,33 +101,9 @@ int eDVBServiceRecord::doPrepare()
/* allocate a ts recorder if we don't already have one. */
if (m_state == stateIdle)
{
- eDebug("Recording to %s...", m_filename.c_str());
- ::remove(m_filename.c_str());
- int fd = ::open(m_filename.c_str(), O_WRONLY|O_CREAT, 0644);
- if (fd == -1)
- {
- eDebug("eDVBServiceRecord - can't open hardcoded recording file!");
- return -1;
- }
- ePtr<iDVBDemux> demux;
- if (m_service_handler.getDemux(demux))
- {
- eDebug("eDVBServiceRecord - NO DEMUX available!");
- return -2;
- }
- demux->createTSRecorder(m_record);
- if (!m_record)
- {
- eDebug("eDVBServiceRecord - no ts recorder available.");
- return -3;
- }
- m_record->setTargetFD(fd);
m_pids_active.clear();
m_state = statePrepared;
- } else if ((m_state == statePrepared) || (m_state == stateRecording))
- {
- /* when we're already recording, we already have a recorder allocated. */
- assert(m_record);
+ m_service_handler.tune(m_ref);
}
return 0;
}
@@ -111,6 +114,11 @@ int eDVBServiceRecord::doRecord()
if (err)
return err;
+ if (!m_record)
+ {
+ eDebug("demux not available (tune failed?). cannot record.");
+ return -1;
+ }
eDebug("starting recording..");
eDVBServicePMTHandler::program program;
diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h
index ac174c41..c08278b8 100644
--- a/lib/service/servicemp3.h
+++ b/lib/service/servicemp3.h
@@ -64,7 +64,8 @@ public:
RESULT audioTracks(ePtr<iAudioTrackSelection> &ptr) { ptr = 0; return -1; }
RESULT frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr) { ptr = 0; return -1; }
RESULT subServices(ePtr<iSubserviceList> &ptr) { ptr = 0; return -1; }
-
+ RESULT timeshift(ePtr<iTimeshiftService> &ptr) { ptr = 0; return -1; }
+
// iPausableService
RESULT pause();
RESULT unpause();