from Components.Sources.Boolean import Boolean
from Components.config import config, ConfigBoolean, ConfigClock
from Components.SystemInfo import SystemInfo
+from Components.UsageConfig import preferredInstantRecordPath, defaultMoviePath
from EpgSelection import EPGSelection
from Plugins.Plugin import PluginDescriptor
from ServiceReference import ServiceReference
from Tools import Notifications
-from Tools.Directories import SCOPE_HDD, resolveFilename, fileExists
+from Tools.Directories import fileExists
from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \
iPlayableService, eServiceReference, eEPGCache
})
self.fast_winding_hint_message_showed = False
- self.minSpeedBackward = useSeekBackHack and 16 or 0
-
class InfoBarSeekActionMap(HelpableActionMap):
def __init__(self, screen, *args, **kwargs):
HelpableActionMap.__init__(self, screen, *args, **kwargs)
self.__seekableStatusChanged()
def makeStateForward(self, n):
- minspeed = config.seek.stepwise_minspeed.value
- repeat = int(config.seek.stepwise_repeat.value)
- if minspeed != "Never" and n >= int(minspeed) and repeat > 1:
- return (0, n * repeat, repeat, ">> %dx" % n)
- else:
+# minspeed = config.seek.stepwise_minspeed.value
+# repeat = int(config.seek.stepwise_repeat.value)
+# if minspeed != "Never" and n >= int(minspeed) and repeat > 1:
+# return (0, n * repeat, repeat, ">> %dx" % n)
+# else:
return (0, n, 0, ">> %dx" % n)
def makeStateBackward(self, n):
- minspeed = config.seek.stepwise_minspeed.value
- repeat = int(config.seek.stepwise_repeat.value)
- if self.minSpeedBackward and n < self.minSpeedBackward:
- r = (self.minSpeedBackward - 1)/ n + 1
- if minspeed != "Never" and n >= int(minspeed) and repeat > 1:
- r = max(r, repeat)
- return (0, -n * r, r, "<< %dx" % n)
- elif minspeed != "Never" and n >= int(minspeed) and repeat > 1:
- return (0, -n * repeat, repeat, "<< %dx" % n)
- else:
+# minspeed = config.seek.stepwise_minspeed.value
+# repeat = int(config.seek.stepwise_repeat.value)
+# if minspeed != "Never" and n >= int(minspeed) and repeat > 1:
+# return (0, -n * repeat, repeat, "<< %dx" % n)
+# else:
return (0, -n, 0, "<< %dx" % n)
def makeStateSlowMotion(self, n):
if config.seek.on_pause.value == "play":
self.unPauseService()
elif config.seek.on_pause.value == "step":
- self.doSeekRelative(0)
+ self.doSeekRelative(1)
elif config.seek.on_pause.value == "last":
self.setSeekState(self.lastseekstate)
self.lastseekstate = self.SEEK_STATE_PLAY
if not self.fast_winding_hint_message_showed and (seek.isCurrentlySeekable() & 1):
self.session.open(MessageBox, _("No fast winding possible yet.. but you can use the number buttons to skip forward/backward!"), MessageBox.TYPE_INFO, timeout=10)
self.fast_winding_hint_message_showed = True
- return
+ return
+ return 0 # trade as unhandled action
if self.seekstate == self.SEEK_STATE_PLAY:
self.setSeekState(self.makeStateForward(int(config.seek.enter_forward.value)))
elif self.seekstate == self.SEEK_STATE_PAUSE:
if not self.fast_winding_hint_message_showed and (seek.isCurrentlySeekable() & 1):
self.session.open(MessageBox, _("No fast winding possible yet.. but you can use the number buttons to skip forward/backward!"), MessageBox.TYPE_INFO, timeout=10)
self.fast_winding_hint_message_showed = True
- return
+ return
+ return 0 # trade as unhandled action
seekstate = self.seekstate
if seekstate == self.SEEK_STATE_PLAY:
self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value)))
self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value)))
self.doSeekRelative(-6)
elif seekstate == self.SEEK_STATE_PAUSE:
- self.doSeekRelative(-3)
+ self.doSeekRelative(-1)
elif self.isStateForward(seekstate):
speed = seekstate[1]
if seekstate[2]:
self.setSeekState(self.SEEK_STATE_PAUSE)
if back:
- self.doSeek(-5) # seek some gops before end
self.ts_rewind_timer.start(200, 1)
- else:
- self.doSeek(-1) # seek 1 gop before end
def rewindService(self):
self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value)))
if isinstance(serviceref, eServiceReference):
serviceref = ServiceReference(serviceref)
- recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = config.movielist.last_videodir.value)
+ recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = preferredInstantRecordPath())
recording.dontSave = True
if event is None or limitEvent == False:
self.session.nav.RecordTimer.timeChanged(entry)
def instantRecord(self):
- dir = config.movielist.last_videodir.value
- if not fileExists(dir, 'w'):
- dir = resolveFilename(SCOPE_HDD)
+ dir = preferredInstantRecordPath()
+ if not dir or not fileExists(dir, 'w'):
+ dir = defaultMoviePath()
try:
stat = os_stat(dir)
except:
else:
break
+ availableKeys = []
+ usedKeys = []
+
if SystemInfo["CanDownmixAC3"]:
- tlist = [(_("AC3 downmix") + " - " +(_("Off"), _("On"))[config.av.downmix_ac3.value and 1 or 0], "CALLFUNC", self.changeAC3Downmix),
- ((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode"),
- ("--", "")] + tlist
- keys = [ "red", "green", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
- selection += 3
- else:
- tlist = [((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode"), ("--", "")] + tlist
- keys = [ "red", "", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] + [""]*n
+ flist = [(_("AC3 downmix") + " - " +(_("Off"), _("On"))[config.av.downmix_ac3.value and 1 or 0], "CALLFUNC", self.changeAC3Downmix),
+ ((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode")]
+ usedKeys.extend(["red", "green"])
+ availableKeys.extend(["yellow", "blue"])
selection += 2
- self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys, skin_name = "AudioTrackSelection")
+ else:
+ flist = [((_("Left"), _("Stereo"), _("Right"))[self.audioChannel.getCurrentChannel()], "mode")]
+ usedKeys.extend(["red"])
+ availableKeys.extend(["green", "yellow", "blue"])
+ selection += 1
+
+ if hasattr(self, "runPlugin"):
+ class PluginCaller:
+ def __init__(self, fnc, *args):
+ self.fnc = fnc
+ self.args = args
+ def __call__(self, *args, **kwargs):
+ self.fnc(*self.args)
+
+ Plugins = [ (p.name, PluginCaller(self.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_AUDIOMENU) ]
+
+ for p in Plugins:
+ selection += 1
+ flist.append((p[0], "CALLFUNC", p[1]))
+ if availableKeys:
+ usedKeys.append(availableKeys[0])
+ del availableKeys[0]
+ else:
+ usedKeys.append("")
+
+ flist.append(("--", ""))
+ usedKeys.append("")
+ selection += 1
+
+ keys = usedKeys + [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" ] + [""] * n
+ self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = flist + tlist, selection = selection, keys = keys, skin_name = "AudioTrackSelection")
else:
del self.audioTracks
m_is_pvr = !m_reference.path.empty();
m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
- m_skipmode = 0;
+ m_skipmode = m_fastforward = m_slowmotion = 0;
CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
m_event((iPlayableService*)this, evUpdatedInfo);
break;
}
+ case eDVBServicePMTHandler::eventPreStart:
+ loadCuesheet();
+ break;
case eDVBServicePMTHandler::eventEOF:
m_event((iPlayableService*)this, evEOF);
break;
m_event_handler.inject(event, 0);
m_event_handler.inject(empty, 1);
}
- loadCuesheet();
m_event(this, evStart);
}
return 0;
eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
setFastForward_internal(0);
if (m_decoder)
+ {
+ m_slowmotion = ratio;
return m_decoder->setSlowMotion(ratio);
+ }
else
return -1;
}
return setFastForward_internal(ratio);
}
-RESULT eDVBServicePlay::setFastForward_internal(int ratio)
+RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
{
- int skipmode, ffratio;
-
+ int skipmode, ffratio, ret = 0;
+ pts_t pos=0;
+
if (ratio > 8)
{
skipmode = ratio;
if (m_cue)
m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
}
-
+
m_skipmode = skipmode;
-
+
+ if (final_seek)
+ eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
+
+ m_fastforward = ffratio;
+
if (!m_decoder)
return -1;
-
+
if (ffratio == 0)
; /* return m_decoder->play(); is done in caller*/
else if (ffratio != 1)
- return m_decoder->setFastForward(ffratio);
+ ret = m_decoder->setFastForward(ffratio);
else
- return m_decoder->setTrickmode();
- return 0;
+ ret = m_decoder->setTrickmode();
+
+ if (pos)
+ eDebug("final seek after trickplay ret %d", seekTo(pos));
+
+ return ret;
}
RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
RESULT eDVBServicePlay::pause()
{
eDebug("eDVBServicePlay::pause");
- setFastForward_internal(0);
+ setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
if (m_decoder)
{
+ m_slowmotion = 0;
m_is_paused = 1;
return m_decoder->pause();
} else
RESULT eDVBServicePlay::unpause()
{
eDebug("eDVBServicePlay::unpause");
- setFastForward_internal(0);
+ setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
if (m_decoder)
{
+ m_slowmotion = 0;
m_is_paused = 0;
return m_decoder->play();
} else
RESULT eDVBServicePlay::isCurrentlySeekable()
{
- return m_is_pvr || m_timeshift_active ? 3 : 0; // fast forward/backward possible and seeking possible
+ int ret = 0;
+ if (m_decoder)
+ {
+ ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
+ if (m_decoder->getVideoWidth() == -1)
+ ret &= ~2;
+ }
+ return ret;
}
RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
{
eDVBServicePMTHandler::program program;
eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
+ pts_t position = -1;
if (h.getProgramInfo(program))
return -1;
apidtype = program.audioStreams[stream].type;
}
+ if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
+ eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
+
m_current_audio_pid = apid;
if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
return -4;
}
+ if (position != -1)
+ eDebug("seekTo ret %d", seekTo(position));
+
int rdsPid = apid;
/* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
m_new_subtitle_page_connection = 0;
m_rds_decoder_event_connection = 0;
m_video_event_connection = 0;
- m_is_paused = m_skipmode = 0; /* not supported in live mode */
+ m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
/* free the timeshift service handler, we need the resources */
m_service_handler_timeshift.free();
r.path = m_timeshift_file;
m_cue = new eCueSheet();
+ m_cue->seekTo(0, -1000);
m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
pause();
updateDecoder(); /* mainly to switch off PCR, and to set pause */
-
+
m_event((iPlayableService*)this, evSeekableStatusChanged);
}
void eDVBServicePlay::updateDecoder()
{
int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
+ bool mustPlay = false;
eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
Py_DECREF(subs);
}
}
- m_decoder->play(); /* pids will be set later */
}
if (m_cue)
m_cue->setDecodingDemux(m_decode_demux, m_decoder);
- m_decoder->play(); /* pids will be set later. */
+ mustPlay = true;
}
m_timeshift_changed = 0;
}
}
- std::string config_delay;
- int config_delay_int = 0;
- if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
- config_delay_int = atoi(config_delay.c_str());
- m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
-
- if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
- config_delay_int = atoi(config_delay.c_str());
- else
- config_delay_int = 0;
- m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
+ setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
+ setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
m_decoder->setVideoPID(vpid, vpidtype);
selectAudioStream();
m_decoder->setRadioPic(radio_pic);
}
- m_decoder->set();
+ if (mustPlay)
+ m_decoder->play();
+ else
+ m_decoder->set();
+
m_decoder->setAudioChannel(achannel);
/* don't worry about non-existing services, nor pvr services */
{
if (m_dvb_service)
m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
- if (m_decoder)
- m_decoder->setAC3Delay(delay);
+ if (m_decoder) {
+ std::string config_delay;
+ int config_delay_int = 0;
+ if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
+ config_delay_int = atoi(config_delay.c_str());
+ m_decoder->setAC3Delay(delay + config_delay_int);
+ }
}
void eDVBServicePlay::setPCMDelay(int delay)
{
if (m_dvb_service)
m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
- if (m_decoder)
- m_decoder->setPCMDelay(delay);
+ if (m_decoder) {
+ std::string config_delay;
+ int config_delay_int = 0;
+ if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
+ config_delay_int = atoi(config_delay.c_str());
+ else
+ config_delay_int = 0;
+ m_decoder->setPCMDelay(delay + config_delay_int);
+ }
}
void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)