lib/python/Screens/RecordPaths.py: fix spinners in some conditions
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
index 67bd2631a86d5a5f3333f7e397cf82bea7aa0756..f98d4c3398814653deea13416b28fbba943ea0b7 100644 (file)
@@ -10,6 +10,7 @@ from Components.ServiceEventTracker import ServiceEventTracker
 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
 
@@ -25,13 +26,14 @@ from Screens.PictureInPicture import PictureInPicture
 from Screens.SubtitleDisplay import SubtitleDisplay
 from Screens.RdsDisplay import RdsInfoDisplay, RassInteractive
 from Screens.TimeDateInput import TimeDateInput
+from Screens.UnhandledKey import UnhandledKey
 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
+       iPlayableService, eServiceReference, eEPGCache, eActionMap
 
 from time import time, localtime, strftime
 from os import stat as os_stat
@@ -46,6 +48,39 @@ class InfoBarDish:
        def __init__(self):
                self.dishDialog = self.session.instantiateDialog(Dish)
 
+class InfoBarUnhandledKey:
+       def __init__(self):
+               self.unhandledKeyDialog = self.session.instantiateDialog(UnhandledKey)
+               self.hideUnhandledKeySymbolTimer = eTimer()
+               self.hideUnhandledKeySymbolTimer.callback.append(self.unhandledKeyDialog.hide)
+               self.checkUnusedTimer = eTimer()
+               self.checkUnusedTimer.callback.append(self.checkUnused)
+               self.onLayoutFinish.append(self.unhandledKeyDialog.hide)
+               eActionMap.getInstance().bindAction('', -0x7FFFFFFF, self.actionA) #highest prio
+               eActionMap.getInstance().bindAction('', 0x7FFFFFFF, self.actionB) #lowest prio
+               self.flags = (1<<1);
+               self.uflags = 0;
+
+       #this function is called on every keypress!
+       def actionA(self, key, flag):
+               if flag != 4:
+                       if self.flags & (1<<1):
+                               self.flags = self.uflags = 0
+                       self.flags |= (1<<flag)
+                       if flag == 1: # break
+                               self.checkUnusedTimer.start(0, True)
+               return 0
+
+       #this function is only called when no other action has handled this key
+       def actionB(self, key, flag):
+               if flag != 4:
+                       self.uflags |= (1<<flag)
+
+       def checkUnused(self):
+               if self.flags == self.uflags:
+                       self.unhandledKeyDialog.show()
+                       self.hideUnhandledKeySymbolTimer.start(2000, True)
+
 class InfoBarShowHide:
        """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
        fancy animations. """
@@ -452,7 +487,7 @@ class InfoBarEPG:
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
                                "showEventInfo": (self.openEventView, _("show EPG...")),
-                               "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")),
+                               "showEventInfoPlugin": (self.showEventInfoPlugins, _("list of EPG views...")),
                                "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
 
@@ -692,8 +727,6 @@ class InfoBarSeek:
                        })
                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)
@@ -740,24 +773,19 @@ class InfoBarSeek:
                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):
@@ -878,7 +906,7 @@ class InfoBarSeek:
                        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
@@ -920,7 +948,8 @@ class InfoBarSeek:
                        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:
@@ -955,7 +984,8 @@ class InfoBarSeek:
                        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)))
@@ -963,7 +993,7 @@ class InfoBarSeek:
                        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]:
@@ -1080,15 +1110,21 @@ class InfoBarPVRState:
                        self.pvrStateDialog.hide()
                else:
                        self._mayShow()
-                       
 
 class InfoBarTimeshiftState(InfoBarPVRState):
        def __init__(self):
                InfoBarPVRState.__init__(self, screen=TimeshiftState, force_show = True)
+               self.__hideTimer = eTimer()
+               self.__hideTimer.callback.append(self.__hideTimeshiftState)
 
        def _mayShow(self):
-               if self.execing and self.timeshift_enabled and self.seekstate != self.SEEK_STATE_PLAY:
+               if self.execing and self.timeshift_enabled:
                        self.pvrStateDialog.show()
+                       if self.seekstate == self.SEEK_STATE_PLAY and not self.shown:
+                               self.__hideTimer.start(5*1000, True)
+
+       def __hideTimeshiftState(self):
+               self.pvrStateDialog.hide()
 
 class InfoBarShowMovies:
 
@@ -1226,10 +1262,7 @@ class InfoBarTimeshift:
                        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)))
@@ -1498,7 +1531,7 @@ class InfoBarInstantRecord:
                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:
@@ -1599,9 +1632,9 @@ class InfoBarInstantRecord:
                        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:
@@ -1683,17 +1716,46 @@ class InfoBarAudioSelection:
                                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
 
@@ -1958,8 +2020,10 @@ class InfoBarCueSheetSupport:
 
                        if last is not None:
                                self.resume_point = last
+                               
+                               l = last / 90000
                                if config.usage.on_movie_start.value == "ask":
-                                       Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Do you want to resume this playback?"), timeout=10)
+                                       Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Do you want to resume this playback?") + "\n" + (_("Resume position at %s") % ("%d:%02d:%02d" % (l/3600, l%3600/60, l%60))), timeout=10)
                                elif config.usage.on_movie_start.value == "resume":
 # TRANSLATORS: The string "Resuming playback" flashes for a moment
 # TRANSLATORS: at the start of a movie, when the user has selected