fixes bug #556
[enigma2.git] / lib / python / Screens / InfoBarGenerics.py
index 31a9d5a98ef20785b957ccfd5c4ef26fd9adb852..f98d4c3398814653deea13416b28fbba943ea0b7 100644 (file)
@@ -2,16 +2,15 @@ from ChannelSelection import ChannelSelection, BouquetSelector
 
 from Components.ActionMap import ActionMap, HelpableActionMap
 from Components.ActionMap import NumberActionMap
 
 from Components.ActionMap import ActionMap, HelpableActionMap
 from Components.ActionMap import NumberActionMap
-from Components.BlinkingPixmap import BlinkingPixmapConditional
 from Components.Harddisk import harddiskmanager
 from Components.Input import Input
 from Components.Label import Label
 from Components.Harddisk import harddiskmanager
 from Components.Input import Input
 from Components.Label import Label
-from Components.Pixmap import Pixmap
 from Components.PluginComponent import plugins
 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.PluginComponent import plugins
 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
 
 from EpgSelection import EPGSelection
 from Plugins.Plugin import PluginDescriptor
 
@@ -26,20 +25,22 @@ from Screens.TimerSelection import TimerSelection
 from Screens.PictureInPicture import PictureInPicture
 from Screens.SubtitleDisplay import SubtitleDisplay
 from Screens.RdsDisplay import RdsInfoDisplay, RassInteractive
 from Screens.PictureInPicture import PictureInPicture
 from Screens.SubtitleDisplay import SubtitleDisplay
 from Screens.RdsDisplay import RdsInfoDisplay, RassInteractive
-from Screens.SleepTimerEdit import SleepTimerEdit
 from Screens.TimeDateInput import TimeDateInput
 from Screens.TimeDateInput import TimeDateInput
+from Screens.UnhandledKey import UnhandledKey
 from ServiceReference import ServiceReference
 
 from Tools import Notifications
 from ServiceReference import ServiceReference
 
 from Tools import Notifications
-from Tools.Directories import SCOPE_HDD, resolveFilename
+from Tools.Directories import fileExists
 
 from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \
 
 from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \
-       iPlayableService, eServiceReference, eDVBResourceManager, iFrontendInformation, eEPGCache
+       iPlayableService, eServiceReference, eEPGCache, eActionMap
 
 from time import time, localtime, strftime
 from os import stat as os_stat
 from bisect import insort
 
 
 from time import time, localtime, strftime
 from os import stat as os_stat
 from bisect import insort
 
+from RecordTimer import RecordTimerEntry, RecordTimer
+
 # hack alert!
 from Menu import MainMenu, mdom
 
 # hack alert!
 from Menu import MainMenu, mdom
 
@@ -47,6 +48,39 @@ class InfoBarDish:
        def __init__(self):
                self.dishDialog = self.session.instantiateDialog(Dish)
 
        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. """
 class InfoBarShowHide:
        """ InfoBar show/hide control, accepts toggleShow and hide actions, might start
        fancy animations. """
@@ -348,14 +382,14 @@ class InfoBarMenu:
 
        def mainMenu(self):
                print "loading mainmenu XML..."
 
        def mainMenu(self):
                print "loading mainmenu XML..."
-               menu = mdom.childNodes[0]
-               assert menu.tagName == "menu", "root element in menu must be 'menu'!"
+               menu = mdom.getroot()
+               assert menu.tag == "menu", "root element in menu must be 'menu'!"
 
                self.session.infobar = self
                # so we can access the currently active infobar from screens opened from within the mainmenu
                # at the moment used from the SubserviceSelection
 
 
                self.session.infobar = self
                # so we can access the currently active infobar from screens opened from within the mainmenu
                # at the moment used from the SubserviceSelection
 
-               self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu, menu.childNodes)
+               self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu)
 
        def mainMenuClosed(self, *val):
                self.session.infobar = None
 
        def mainMenuClosed(self, *val):
                self.session.infobar = None
@@ -366,28 +400,77 @@ class InfoBarSimpleEventView:
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
                                "showEventInfo": (self.openEventView, _("show event details")),
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
                                "showEventInfo": (self.openEventView, _("show event details")),
+                               "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
 
                        })
 
+       def showEventInfoWhenNotVisible(self):
+               if self.shown:
+                       self.openEventView()
+               else:
+                       self.toggleShow()
+                       return 1
+
        def openEventView(self):
        def openEventView(self):
-               self.epglist = [ ]
+               epglist = [ ]
+               self.epglist = epglist
                service = self.session.nav.getCurrentService()
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                info = service.info()
                ptr=info.getEvent(0)
                if ptr:
                service = self.session.nav.getCurrentService()
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                info = service.info()
                ptr=info.getEvent(0)
                if ptr:
-                       self.epglist.append(ptr)
+                       epglist.append(ptr)
                ptr=info.getEvent(1)
                if ptr:
                ptr=info.getEvent(1)
                if ptr:
-                       self.epglist.append(ptr)
-               if len(self.epglist) > 0:
-                       self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
+                       epglist.append(ptr)
+               if epglist:
+                       self.session.open(EventViewSimple, epglist[0], ServiceReference(ref), self.eventViewCallback)
 
        def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
 
        def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
-               if len(self.epglist) > 1:
-                       tmp = self.epglist[0]
-                       self.epglist[0]=self.epglist[1]
-                       self.epglist[1]=tmp
-                       setEvent(self.epglist[0])
+               epglist = self.epglist
+               if len(epglist) > 1:
+                       tmp = epglist[0]
+                       epglist[0] = epglist[1]
+                       epglist[1] = tmp
+                       setEvent(epglist[0])
+
+class SimpleServicelist:
+       def __init__(self, services):
+               self.services = services
+               self.length = len(services)
+               self.current = 0
+
+       def selectService(self, service):
+               if not self.length:
+                       self.current = -1
+                       return False
+               else:
+                       self.current = 0
+                       while self.services[self.current].ref != service:
+                               self.current += 1
+                               if self.current >= self.length:
+                                       return False
+               return True
+
+       def nextService(self):
+               if not self.length:
+                       return
+               if self.current+1 < self.length:
+                       self.current += 1
+               else:
+                       self.current = 0
+
+       def prevService(self):
+               if not self.length:
+                       return
+               if self.current-1 > -1:
+                       self.current -= 1
+               else:
+                       self.current = self.length - 1
+
+       def currentService(self):
+               if not self.length or self.current >= self.length:
+                       return None
+               return self.services[self.current]
 
 class InfoBarEPG:
        """ EPG - Opens an EPG list when the showEPGList action fires """
 
 class InfoBarEPG:
        """ EPG - Opens an EPG list when the showEPGList action fires """
@@ -404,7 +487,7 @@ class InfoBarEPG:
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
                                "showEventInfo": (self.openEventView, _("show EPG...")),
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
                                "showEventInfo": (self.openEventView, _("show EPG...")),
-                               "showSingleServiceEPG": (self.openSingleServiceEPG, _("show single service EPG...")),
+                               "showEventInfoPlugin": (self.showEventInfoPlugins, _("list of EPG views...")),
                                "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
 
                                "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
 
@@ -440,7 +523,7 @@ class InfoBarEPG:
 
        def openBouquetEPG(self, bouquet, withCallback=True):
                services = self.getBouquetServices(bouquet)
 
        def openBouquetEPG(self, bouquet, withCallback=True):
                services = self.getBouquetServices(bouquet)
-               if len(services):
+               if services:
                        self.epg_bouquet = bouquet
                        if withCallback:
                                self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
                        self.epg_bouquet = bouquet
                        if withCallback:
                                self.dlg_stack.append(self.session.openWithCallback(self.closed, EPGSelection, services, self.zapToService, None, self.changeBouquetCB))
@@ -455,7 +538,7 @@ class InfoBarEPG:
                                self.bouquetSel.up()
                        bouquet = self.bouquetSel.getCurrent()
                        services = self.getBouquetServices(bouquet)
                                self.bouquetSel.up()
                        bouquet = self.bouquetSel.getCurrent()
                        services = self.getBouquetServices(bouquet)
-                       if len(services):
+                       if services:
                                self.epg_bouquet = bouquet
                                epg.setServices(services)
 
                                self.epg_bouquet = bouquet
                                epg.setServices(services)
 
@@ -485,46 +568,85 @@ class InfoBarEPG:
                elif cnt == 1:
                        self.openBouquetEPG(bouquets[0][1], withCallback)
 
                elif cnt == 1:
                        self.openBouquetEPG(bouquets[0][1], withCallback)
 
+       def changeServiceCB(self, direction, epg):
+               if self.serviceSel:
+                       if direction > 0:
+                               self.serviceSel.nextService()
+                       else:
+                               self.serviceSel.prevService()
+                       epg.setService(self.serviceSel.currentService())
+
+       def SingleServiceEPGClosed(self, ret=False):
+               self.serviceSel = None
+
        def openSingleServiceEPG(self):
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
        def openSingleServiceEPG(self):
                ref=self.session.nav.getCurrentlyPlayingServiceReference()
-               self.session.open(EPGSelection, ref)
+               if ref:
+                       if self.servicelist.getMutableList() is not None: # bouquet in channellist
+                               current_path = self.servicelist.getRoot()
+                               services = self.getBouquetServices(current_path)
+                               self.serviceSel = SimpleServicelist(services)
+                               if self.serviceSel.selectService(ref):
+                                       self.session.openWithCallback(self.SingleServiceEPGClosed, EPGSelection, ref, serviceChangeCB = self.changeServiceCB)
+                               else:
+                                       self.session.openWithCallback(self.SingleServiceEPGClosed, EPGSelection, ref)
+                       else:
+                               self.session.open(EPGSelection, ref)
+
+       def showEventInfoPlugins(self):
+               list = [(p.name, boundFunction(self.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EVENTINFO)]
+
+               if list:
+                       list.append((_("show single service EPG..."), self.openSingleServiceEPG))
+                       self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list, skin_name = "EPGExtensionsList")
+               else:
+                       self.openSingleServiceEPG()
+
+       def runPlugin(self, plugin):
+               plugin(session = self.session, servicelist = self.servicelist)
+               
+       def EventInfoPluginChosen(self, answer):
+               if answer is not None:
+                       answer[1]()
 
        def openSimilarList(self, eventid, refstr):
                self.session.open(EPGSelection, refstr, None, eventid)
 
        def getNowNext(self):
 
        def openSimilarList(self, eventid, refstr):
                self.session.open(EPGSelection, refstr, None, eventid)
 
        def getNowNext(self):
-               self.epglist = [ ]
+               epglist = [ ]
                service = self.session.nav.getCurrentService()
                info = service and service.info()
                ptr = info and info.getEvent(0)
                if ptr:
                service = self.session.nav.getCurrentService()
                info = service and service.info()
                ptr = info and info.getEvent(0)
                if ptr:
-                       self.epglist.append(ptr)
+                       epglist.append(ptr)
                ptr = info and info.getEvent(1)
                if ptr:
                ptr = info and info.getEvent(1)
                if ptr:
-                       self.epglist.append(ptr)
+                       epglist.append(ptr)
+               self.epglist = epglist
 
        def __evEventInfoChanged(self):
                if self.is_now_next and len(self.dlg_stack) == 1:
                        self.getNowNext()
                        assert self.eventView
 
        def __evEventInfoChanged(self):
                if self.is_now_next and len(self.dlg_stack) == 1:
                        self.getNowNext()
                        assert self.eventView
-                       if len(self.epglist):
+                       if self.epglist:
                                self.eventView.setEvent(self.epglist[0])
 
        def openEventView(self):
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                self.getNowNext()
                                self.eventView.setEvent(self.epglist[0])
 
        def openEventView(self):
                ref = self.session.nav.getCurrentlyPlayingServiceReference()
                self.getNowNext()
-               if len(self.epglist) == 0:
+               epglist = self.epglist
+               if not epglist:
                        self.is_now_next = False
                        epg = eEPGCache.getInstance()
                        ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
                        if ptr:
                        self.is_now_next = False
                        epg = eEPGCache.getInstance()
                        ptr = ref and ref.valid() and epg.lookupEventTime(ref, -1)
                        if ptr:
-                               self.epglist.append(ptr)
+                               epglist.append(ptr)
                                ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
                                if ptr:
                                ptr = epg.lookupEventTime(ref, ptr.getBeginTime(), +1)
                                if ptr:
-                                       self.epglist.append(ptr)
+                                       epglist.append(ptr)
                else:
                        self.is_now_next = True
                else:
                        self.is_now_next = True
-               if len(self.epglist) > 0:
+               if epglist:
                        self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
                        self.dlg_stack.append(self.eventView)
                else:
                        self.eventView = self.session.openWithCallback(self.closed, EventViewEPGSelect, self.epglist[0], ServiceReference(ref), self.eventViewCallback, self.openSingleServiceEPG, self.openMultiServiceEPG, self.openSimilarList)
                        self.dlg_stack.append(self.eventView)
                else:
@@ -532,11 +654,12 @@ class InfoBarEPG:
                        self.openMultiServiceEPG(False)
 
        def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
                        self.openMultiServiceEPG(False)
 
        def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
-               if len(self.epglist) > 1:
-                       tmp = self.epglist[0]
-                       self.epglist[0]=self.epglist[1]
-                       self.epglist[1]=tmp
-                       setEvent(self.epglist[0])
+               epglist = self.epglist
+               if len(epglist) > 1:
+                       tmp = epglist[0]
+                       epglist[0]=epglist[1]
+                       epglist[1]=tmp
+                       setEvent(epglist[0])
 
 class InfoBarRdsDecoder:
        """provides RDS and Rass support/display"""
 
 class InfoBarRdsDecoder:
        """provides RDS and Rass support/display"""
@@ -602,13 +725,7 @@ class InfoBarSeek:
                                iPlayableService.evEOF: self.__evEOF,
                                iPlayableService.evSOF: self.__evSOF,
                        })
                                iPlayableService.evEOF: self.__evEOF,
                                iPlayableService.evSOF: self.__evSOF,
                        })
-               self.eofState = 0
-               self.eofTimer = eTimer()
-               self.eofTimer.timeout.get().append(self.doEof)
-               self.eofInhibitTimer = eTimer()
-               self.eofInhibitTimer.timeout.get().append(self.inhibitEof)
-
-               self.minSpeedBackward = useSeekBackHack and 16 or 0
+               self.fast_winding_hint_message_showed = False
 
                class InfoBarSeekActionMap(HelpableActionMap):
                        def __init__(self, screen, *args, **kwargs):
 
                class InfoBarSeekActionMap(HelpableActionMap):
                        def __init__(self, screen, *args, **kwargs):
@@ -623,9 +740,9 @@ class InfoBarSeek:
                                        return 1
                                elif action[:8] == "seekdef:":
                                        key = int(action[8:])
                                        return 1
                                elif action[:8] == "seekdef:":
                                        key = int(action[8:])
-                                       time = [-config.seek.selfdefined_13.value, False, config.seek.selfdefined_13.value,
+                                       time = (-config.seek.selfdefined_13.value, False, config.seek.selfdefined_13.value,
                                                -config.seek.selfdefined_46.value, False, config.seek.selfdefined_46.value,
                                                -config.seek.selfdefined_46.value, False, config.seek.selfdefined_46.value,
-                                               -config.seek.selfdefined_79.value, False, config.seek.selfdefined_79.value][key-1]
+                                               -config.seek.selfdefined_79.value, False, config.seek.selfdefined_79.value)[key-1]
                                        self.screen.doSeekRelative(time * 90000)
                                        return 1                                        
                                else:
                                        self.screen.doSeekRelative(time * 90000)
                                        return 1                                        
                                else:
@@ -656,24 +773,19 @@ class InfoBarSeek:
                self.__seekableStatusChanged()
 
        def makeStateForward(self, n):
                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):
                        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):
                        return (0, -n, 0, "<< %dx" % n)
 
        def makeStateSlowMotion(self, n):
@@ -695,7 +807,7 @@ class InfoBarSeek:
                return False
 
        def getLower(self, n, lst):
                return False
 
        def getLower(self, n, lst):
-               lst = lst+[]
+               lst = lst[:]
                lst.reverse()
                for x in lst:
                        if x < n:
                lst.reverse()
                for x in lst:
                        if x < n:
@@ -730,21 +842,19 @@ class InfoBarSeek:
                return True
 
        def __seekableStatusChanged(self):
                return True
 
        def __seekableStatusChanged(self):
-               print "seekable status changed!"
+#              print "seekable status changed!"
                if not self.isSeekable():
                        self["SeekActions"].setEnabled(False)
                if not self.isSeekable():
                        self["SeekActions"].setEnabled(False)
-                       print "not seekable, return to play"
+#                      print "not seekable, return to play"
                        self.setSeekState(self.SEEK_STATE_PLAY)
                else:
                        self["SeekActions"].setEnabled(True)
                        self.setSeekState(self.SEEK_STATE_PLAY)
                else:
                        self["SeekActions"].setEnabled(True)
-                       print "seekable"
+#                      print "seekable"
 
        def __serviceStarted(self):
 
        def __serviceStarted(self):
+               self.fast_winding_hint_message_showed = False
                self.seekstate = self.SEEK_STATE_PLAY
                self.__seekableStatusChanged()
                self.seekstate = self.SEEK_STATE_PLAY
                self.__seekableStatusChanged()
-               if self.eofState != 0:
-                       self.eofTimer.stop()
-               self.eofState = 0
 
        def setSeekState(self, state):
                service = self.session.nav.getCurrentService()
 
        def setSeekState(self, state):
                service = self.session.nav.getCurrentService()
@@ -753,7 +863,7 @@ class InfoBarSeek:
                        return False
 
                if not self.isSeekable():
                        return False
 
                if not self.isSeekable():
-                       if state not in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
+                       if state not in (self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE):
                                state = self.SEEK_STATE_PLAY
 
                pauseable = service.pause()
                                state = self.SEEK_STATE_PLAY
 
                pauseable = service.pause()
@@ -762,12 +872,21 @@ class InfoBarSeek:
                        print "not pauseable."
                        state = self.SEEK_STATE_PLAY
 
                        print "not pauseable."
                        state = self.SEEK_STATE_PLAY
 
-               oldstate = self.seekstate
                self.seekstate = state
 
                self.seekstate = state
 
-               for i in range(3):
-                       if oldstate[i] != self.seekstate[i]:
-                               (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
+               if pauseable is not None:
+                       if self.seekstate[0]:
+                               print "resolved to PAUSE"
+                               pauseable.pause()
+                       elif self.seekstate[1]:
+                               print "resolved to FAST FORWARD"
+                               pauseable.setFastForward(self.seekstate[1])
+                       elif self.seekstate[2]:
+                               print "resolved to SLOW MOTION"
+                               pauseable.setSlowMotion(self.seekstate[2])
+                       else:
+                               print "resolved to PLAY"
+                               pauseable.unpause()
 
                for c in self.onPlayStateChanged:
                        c(self.seekstate)
 
                for c in self.onPlayStateChanged:
                        c(self.seekstate)
@@ -787,7 +906,7 @@ class InfoBarSeek:
                        if config.seek.on_pause.value == "play":
                                self.unPauseService()
                        elif config.seek.on_pause.value == "step":
                        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
                        elif config.seek.on_pause.value == "last":
                                self.setSeekState(self.lastseekstate)
                                self.lastseekstate = self.SEEK_STATE_PLAY
@@ -806,16 +925,6 @@ class InfoBarSeek:
                seekable = self.getSeek()
                if seekable is None:
                        return
                seekable = self.getSeek()
                if seekable is None:
                        return
-               prevstate = self.seekstate
-               if self.eofState == 1:
-                       self.eofState = 2
-                       self.inhibitEof()
-               if self.seekstate == self.SEEK_STATE_EOF:
-                       if prevstate == self.SEEK_STATE_PAUSE:
-                               self.setSeekState(self.SEEK_STATE_PAUSE)
-                       else:
-                               self.setSeekState(self.SEEK_STATE_PLAY)
-               self.eofInhibitTimer.start(200, True)
                seekable.seekTo(pts)
 
        def doSeekRelative(self, pts):
                seekable.seekTo(pts)
 
        def doSeekRelative(self, pts):
@@ -823,20 +932,24 @@ class InfoBarSeek:
                if seekable is None:
                        return
                prevstate = self.seekstate
                if seekable is None:
                        return
                prevstate = self.seekstate
-               if self.eofState == 1:
-                       self.eofState = 2
-                       self.inhibitEof()
+
                if self.seekstate == self.SEEK_STATE_EOF:
                        if prevstate == self.SEEK_STATE_PAUSE:
                                self.setSeekState(self.SEEK_STATE_PAUSE)
                        else:
                                self.setSeekState(self.SEEK_STATE_PLAY)
                if self.seekstate == self.SEEK_STATE_EOF:
                        if prevstate == self.SEEK_STATE_PAUSE:
                                self.setSeekState(self.SEEK_STATE_PAUSE)
                        else:
                                self.setSeekState(self.SEEK_STATE_PLAY)
-               self.eofInhibitTimer.start(200, True)
                seekable.seekRelative(pts<0 and -1 or 1, abs(pts))
                if abs(pts) > 100 and config.usage.show_infobar_on_skip.value:
                        self.showAfterSeek()
 
        def seekFwd(self):
                seekable.seekRelative(pts<0 and -1 or 1, abs(pts))
                if abs(pts) > 100 and config.usage.show_infobar_on_skip.value:
                        self.showAfterSeek()
 
        def seekFwd(self):
+               seek = self.getSeek()
+               if seek and not (seek.isCurrentlySeekable() & 2):
+                       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 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 self.seekstate == self.SEEK_STATE_PLAY:
                        self.setSeekState(self.makeStateForward(int(config.seek.enter_forward.value)))
                elif self.seekstate == self.SEEK_STATE_PAUSE:
@@ -866,30 +979,38 @@ class InfoBarSeek:
                        self.setSeekState(self.makeStateSlowMotion(speed))
 
        def seekBack(self):
                        self.setSeekState(self.makeStateSlowMotion(speed))
 
        def seekBack(self):
-               if self.seekstate == self.SEEK_STATE_PLAY:
+               seek = self.getSeek()
+               if seek and not (seek.isCurrentlySeekable() & 2):
+                       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 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)))
-               elif self.seekstate == self.SEEK_STATE_EOF:
+               elif seekstate == self.SEEK_STATE_EOF:
                        self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value)))
                        self.doSeekRelative(-6)
                        self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value)))
                        self.doSeekRelative(-6)
-               elif self.seekstate == self.SEEK_STATE_PAUSE:
-                       self.doSeekRelative(-3)
-               elif self.isStateForward(self.seekstate):
-                       speed = self.seekstate[1]
-                       if self.seekstate[2]:
-                               speed /= self.seekstate[2]
+               elif seekstate == self.SEEK_STATE_PAUSE:
+                       self.doSeekRelative(-1)
+               elif self.isStateForward(seekstate):
+                       speed = seekstate[1]
+                       if seekstate[2]:
+                               speed /= seekstate[2]
                        speed = self.getLower(speed, config.seek.speeds_forward.value)
                        if speed:
                                self.setSeekState(self.makeStateForward(speed))
                        else:
                                self.setSeekState(self.SEEK_STATE_PLAY)
                        speed = self.getLower(speed, config.seek.speeds_forward.value)
                        if speed:
                                self.setSeekState(self.makeStateForward(speed))
                        else:
                                self.setSeekState(self.SEEK_STATE_PLAY)
-               elif self.isStateBackward(self.seekstate):
-                       speed = -self.seekstate[1]
-                       if self.seekstate[2]:
-                               speed /= self.seekstate[2]
+               elif self.isStateBackward(seekstate):
+                       speed = -seekstate[1]
+                       if seekstate[2]:
+                               speed /= seekstate[2]
                        speed = self.getHigher(speed, config.seek.speeds_backward.value) or config.seek.speeds_backward.value[-1]
                        self.setSeekState(self.makeStateBackward(speed))
                        speed = self.getHigher(speed, config.seek.speeds_backward.value) or config.seek.speeds_backward.value[-1]
                        self.setSeekState(self.makeStateBackward(speed))
-               elif self.isStateSlowMotion(self.seekstate):
-                       speed = self.getHigher(self.seekstate[2], config.seek.speeds_slowmotion.value)
+               elif self.isStateSlowMotion(seekstate):
+                       speed = self.getHigher(seekstate[2], config.seek.speeds_slowmotion.value)
                        if speed:
                                self.setSeekState(self.makeStateSlowMotion(speed))
                        else:
                        if speed:
                                self.setSeekState(self.makeStateSlowMotion(speed))
                        else:
@@ -942,44 +1063,19 @@ class InfoBarSeek:
                return False
                
        def __evEOF(self):
                return False
                
        def __evEOF(self):
-               if self.eofState == 0 and self.seekstate != self.SEEK_STATE_EOF:
-                       self.eofState = 1
-                       time = self.calcRemainingTime()
-                       if not time:
-                               time = 3000   # Failed to calc, use default
-                       elif time == 0:
-                               time = 300    # Passed end, shortest wait
-                       elif time > 15000:
-                               self.eofState = -2  # Too long, block eof
-                               time = 15000
-                       else:
-                               time += 1000  # Add margin
-                       self.eofTimer.start(time, True)
-
-       def inhibitEof(self):
-               if self.eofState >= 1:
-                       self.eofState = -self.eofState
-                       self.eofTimer.stop()
-                       self.doEof()
-
-       def doEof(self):
                if self.seekstate == self.SEEK_STATE_EOF:
                        return
                if self.seekstate == self.SEEK_STATE_EOF:
                        return
-               if self.eofState == -2 or self.isStateBackward(self.seekstate):
-                       self.eofState = 0
-                       return
 
 
-               # if we are seeking, we try to end up ~1s before the end, and pause there.
-               eofstate = self.eofState
+               # if we are seeking forward, we try to end up ~1s before the end, and pause there.
                seekstate = self.seekstate
                seekstate = self.seekstate
-               self.eofState = 0
-               if not self.seekstate == self.SEEK_STATE_PAUSE:
+               if self.seekstate != self.SEEK_STATE_PAUSE:
                        self.setSeekState(self.SEEK_STATE_EOF)
                        self.setSeekState(self.SEEK_STATE_EOF)
-               if eofstate == -1 or not seekstate in [self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE]:
+
+               if seekstate not in (self.SEEK_STATE_PLAY, self.SEEK_STATE_PAUSE): # if we are seeking
                        seekable = self.getSeek()
                        if seekable is not None:
                                seekable.seekTo(-1)
                        seekable = self.getSeek()
                        if seekable is not None:
                                seekable.seekTo(-1)
-               if eofstate == 1 and seekstate == self.SEEK_STATE_PLAY:
+               if seekstate == self.SEEK_STATE_PLAY: # regular EOF
                        self.doEofInternal(True)
                else:
                        self.doEofInternal(False)
                        self.doEofInternal(True)
                else:
                        self.doEofInternal(False)
@@ -994,11 +1090,12 @@ class InfoBarSeek:
 from Screens.PVRState import PVRState, TimeshiftState
 
 class InfoBarPVRState:
 from Screens.PVRState import PVRState, TimeshiftState
 
 class InfoBarPVRState:
-       def __init__(self, screen=PVRState):
+       def __init__(self, screen=PVRState, force_show = False):
                self.onPlayStateChanged.append(self.__playStateChanged)
                self.pvrStateDialog = self.session.instantiateDialog(screen)
                self.onShow.append(self._mayShow)
                self.onHide.append(self.pvrStateDialog.hide)
                self.onPlayStateChanged.append(self.__playStateChanged)
                self.pvrStateDialog = self.session.instantiateDialog(screen)
                self.onShow.append(self._mayShow)
                self.onHide.append(self.pvrStateDialog.hide)
+               self.force_show = force_show
 
        def _mayShow(self):
                if self.execing and self.seekstate != self.SEEK_STATE_PLAY:
 
        def _mayShow(self):
                if self.execing and self.seekstate != self.SEEK_STATE_PLAY:
@@ -1007,15 +1104,27 @@ class InfoBarPVRState:
        def __playStateChanged(self, state):
                playstateString = state[3]
                self.pvrStateDialog["state"].setText(playstateString)
        def __playStateChanged(self, state):
                playstateString = state[3]
                self.pvrStateDialog["state"].setText(playstateString)
-               self._mayShow()
+               
+               # if we return into "PLAY" state, ensure that the dialog gets hidden if there will be no infobar displayed
+               if not config.usage.show_infobar_on_skip.value and self.seekstate == self.SEEK_STATE_PLAY and not self.force_show:
+                       self.pvrStateDialog.hide()
+               else:
+                       self._mayShow()
 
 class InfoBarTimeshiftState(InfoBarPVRState):
        def __init__(self):
 
 class InfoBarTimeshiftState(InfoBarPVRState):
        def __init__(self):
-               InfoBarPVRState.__init__(self, screen=TimeshiftState)
+               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:
                        self.pvrStateDialog.show()
 
        def _mayShow(self):
                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:
 
 
 class InfoBarShowMovies:
 
@@ -1153,10 +1262,7 @@ class InfoBarTimeshift:
                        self.setSeekState(self.SEEK_STATE_PAUSE)
 
                if back:
                        self.setSeekState(self.SEEK_STATE_PAUSE)
 
                if back:
-                       self.doSeek(-5) # seek some gops before end
                        self.ts_rewind_timer.start(200, 1)
                        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)))
 
        def rewindService(self):
                self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value)))
@@ -1170,8 +1276,8 @@ class InfoBarTimeshift:
        def __seekableStatusChanged(self):
                enabled = False
 
        def __seekableStatusChanged(self):
                enabled = False
 
-               print "self.isSeekable", self.isSeekable()
-               print "self.timeshift_enabled", self.timeshift_enabled
+#              print "self.isSeekable", self.isSeekable()
+#              print "self.timeshift_enabled", self.timeshift_enabled
 
                # when this service is not seekable, but timeshift
                # is enabled, this means we can activate
 
                # when this service is not seekable, but timeshift
                # is enabled, this means we can activate
@@ -1179,7 +1285,7 @@ class InfoBarTimeshift:
                if not self.isSeekable() and self.timeshift_enabled:
                        enabled = True
 
                if not self.isSeekable() and self.timeshift_enabled:
                        enabled = True
 
-               print "timeshift activate:", enabled
+#              print "timeshift activate:", enabled
                self["TimeshiftActivateActions"].setEnabled(enabled)
 
        def __serviceStarted(self):
                self["TimeshiftActivateActions"].setEnabled(enabled)
 
        def __serviceStarted(self):
@@ -1198,7 +1304,7 @@ class InfoBarExtensions:
                self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
                        {
                                "extensions": (self.showExtensionSelection, _("view extensions...")),
                self["InstantExtensionsActions"] = HelpableActionMap(self, "InfobarExtensions",
                        {
                                "extensions": (self.showExtensionSelection, _("view extensions...")),
-                       })
+                       }, 1) # lower priority
 
        def addExtension(self, extension, key = None, type = EXTENSION_SINGLE):
                self.list.append((type, extension, key))
 
        def addExtension(self, extension, key = None, type = EXTENSION_SINGLE):
                self.list.append((type, extension, key))
@@ -1246,10 +1352,10 @@ class InfoBarExtensions:
                                        extensionsList.remove(extension)
                                else:
                                        extensionsList.remove(extension)
                                        extensionsList.remove(extension)
                                else:
                                        extensionsList.remove(extension)
-               for x in extensionsList:
-                       list.append((x[0](), x))
+               list.extend([(x[0](), x) for x in extensionsList])
+
                keys += [""] * len(extensionsList)
                keys += [""] * len(extensionsList)
-               self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list, keys = keys)
+               self.session.openWithCallback(self.extensionCallback, ChoiceBox, title=_("Please choose an extension..."), list = list, keys = keys, skin_name = "ExtensionsList")
 
        def extensionCallback(self, answer):
                if answer is not None:
 
        def extensionCallback(self, answer):
                if answer is not None:
@@ -1258,7 +1364,6 @@ class InfoBarExtensions:
 from Tools.BoundFunction import boundFunction
 
 # depends on InfoBarExtensions
 from Tools.BoundFunction import boundFunction
 
 # depends on InfoBarExtensions
-from Components.PluginComponent import plugins
 
 class InfoBarPlugins:
        def __init__(self):
 
 class InfoBarPlugins:
        def __init__(self):
@@ -1268,33 +1373,50 @@ class InfoBarPlugins:
                return name
 
        def getPluginList(self):
                return name
 
        def getPluginList(self):
-               list = []
-               for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU):
-                       list.append(((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None))
+               list = [((boundFunction(self.getPluginName, p.name), boundFunction(self.runPlugin, p), lambda: True), None, p.name) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EXTENSIONSMENU)]
+               list.sort(key = lambda e: e[2]) # sort by name
                return list
 
        def runPlugin(self, plugin):
                return list
 
        def runPlugin(self, plugin):
-               plugin(session = self.session, servicelist = self.servicelist)
+               if isinstance(self, InfoBarChannelSelection):
+                       plugin(session = self.session, servicelist = self.servicelist)
+               else:
+                       plugin(session = self.session)
 
 
-# depends on InfoBarExtensions
-class InfoBarSleepTimer:
+from Components.Task import job_manager
+class InfoBarJobman:
        def __init__(self):
        def __init__(self):
-               self.addExtension((self.getSleepTimerName, self.showSleepTimerSetup, lambda: True), "1")
+               self.addExtension(extension = self.getJobList, type = InfoBarExtensions.EXTENSION_LIST)
+
+       def getJobList(self):
+               return [((boundFunction(self.getJobName, job), boundFunction(self.showJobView, job), lambda: True), None) for job in job_manager.getPendingJobs()]
 
 
-       def getSleepTimerName(self):
-               return _("Sleep Timer")
+       def getJobName(self, job):
+               return "%s: %s (%d%%)" % (job.getStatustext(), job.name, int(100*job.progress/float(job.end)))
 
 
-       def showSleepTimerSetup(self):
-               self.session.open(SleepTimerEdit)
+       def showJobView(self, job):
+               from Screens.TaskView import JobView
+               job_manager.in_background = False
+               self.session.openWithCallback(self.JobViewCB, JobView, job)
+       
+       def JobViewCB(self, in_background):
+               job_manager.in_background = in_background
 
 # depends on InfoBarExtensions
 class InfoBarPiP:
        def __init__(self):
 
 # depends on InfoBarExtensions
 class InfoBarPiP:
        def __init__(self):
-               self.session.pipshown = False
+               try:
+                       self.session.pipshown
+               except:
+                       self.session.pipshown = False
                if SystemInfo.get("NumVideoDecoders", 1) > 1:
                if SystemInfo.get("NumVideoDecoders", 1) > 1:
-                       self.addExtension((self.getShowHideName, self.showPiP, lambda: True), "blue")
-                       self.addExtension((self.getMoveName, self.movePiP, self.pipShown), "green")
-                       self.addExtension((self.getSwapName, self.swapPiP, self.pipShown), "yellow")
+                       if (self.allowPiP):
+                               self.addExtension((self.getShowHideName, self.showPiP, lambda: True), "blue")
+                               self.addExtension((self.getMoveName, self.movePiP, self.pipShown), "green")
+                               self.addExtension((self.getSwapName, self.swapPiP, self.pipShown), "yellow")
+                       else:
+                               self.addExtension((self.getShowHideName, self.showPiP, self.pipShown), "blue")
+                               self.addExtension((self.getMoveName, self.movePiP, self.pipShown), "green")
 
        def pipShown(self):
                return self.session.pipshown
 
        def pipShown(self):
                return self.session.pipshown
@@ -1356,7 +1478,7 @@ class InfoBarPiP:
                elif "stop" == use:
                        self.showPiP()
 
                elif "stop" == use:
                        self.showPiP()
 
-from RecordTimer import parseEvent
+from RecordTimer import parseEvent, RecordTimerEntry
 
 class InfoBarInstantRecord:
        """Instant Record - handles the instantRecord action in order to
 
 class InfoBarInstantRecord:
        """Instant Record - handles the instantRecord action in order to
@@ -1389,8 +1511,8 @@ class InfoBarInstantRecord:
                except:
                        pass
 
                except:
                        pass
 
-               begin = time()
-               end = time() + 3600 * 10
+               begin = int(time())
+               end = begin + 3600      # dummy
                name = "instant record"
                description = ""
                eventid = None
                name = "instant record"
                description = ""
                eventid = None
@@ -1406,15 +1528,37 @@ class InfoBarInstantRecord:
                        if limitEvent:
                                self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
 
                        if limitEvent:
                                self.session.open(MessageBox, _("No event info found, recording indefinitely."), MessageBox.TYPE_INFO)
 
-               data = (begin, end, name, description, eventid)
+               if isinstance(serviceref, eServiceReference):
+                       serviceref = ServiceReference(serviceref)
 
 
-               recording = self.session.nav.recordWithTimer(serviceref, *data)
+               recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = preferredInstantRecordPath())
                recording.dontSave = True
                recording.dontSave = True
-               self.recording.append(recording)
+               
+               if event is None or limitEvent == False:
+                       recording.autoincrease = True
+                       if recording.setAutoincreaseEnd():
+                               self.session.nav.RecordTimer.record(recording)
+                               self.recording.append(recording)
+               else:
+                               simulTimerList = self.session.nav.RecordTimer.record(recording)
+                               if simulTimerList is not None:  # conflict with other recording
+                                       name = simulTimerList[1].name
+                                       name_date = ' '.join((name, strftime('%c', localtime(simulTimerList[1].begin))))
+                                       print "[TIMER] conflicts with", name_date
+                                       recording.autoincrease = True   # start with max available length, then increment
+                                       if recording.setAutoincreaseEnd():
+                                               self.session.nav.RecordTimer.record(recording)
+                                               self.recording.append(recording)
+                                               self.session.open(MessageBox, _("Record time limited due to conflicting timer %s") % name_date, MessageBox.TYPE_INFO)
+                                       else:
+                                               self.session.open(MessageBox, _("Couldn't record due to conflicting timer %s") % name, MessageBox.TYPE_INFO)
+                                       recording.autoincrease = False
+                               else:
+                                       self.recording.append(recording)
 
        def isInstantRecordRunning(self):
                print "self.recording:", self.recording
 
        def isInstantRecordRunning(self):
                print "self.recording:", self.recording
-               if len(self.recording) > 0:
+               if self.recording:
                        for x in self.recording:
                                if x.isRunning():
                                        return True
                        for x in self.recording:
                                if x.isRunning():
                                        return True
@@ -1457,7 +1601,7 @@ class InfoBarInstantRecord:
                print "after:\n", self.recording
 
        def setEndtime(self, entry):
                print "after:\n", self.recording
 
        def setEndtime(self, entry):
-               if entry is not None:
+               if entry is not None and entry >= 0:
                        self.selectedEntry = entry
                        self.endtime=ConfigClock(default = self.recording[self.selectedEntry].end)
                        dlg = self.session.openWithCallback(self.TimeDateInputClosed, TimeDateInput, self.endtime)
                        self.selectedEntry = entry
                        self.endtime=ConfigClock(default = self.recording[self.selectedEntry].end)
                        dlg = self.session.openWithCallback(self.TimeDateInputClosed, TimeDateInput, self.endtime)
@@ -1468,46 +1612,55 @@ class InfoBarInstantRecord:
                        if ret[0]:
                                localendtime = localtime(ret[1])
                                print "stopping recording at", strftime("%c", localendtime)
                        if ret[0]:
                                localendtime = localtime(ret[1])
                                print "stopping recording at", strftime("%c", localendtime)
+                               if self.recording[self.selectedEntry].end != ret[1]:
+                                       self.recording[self.selectedEntry].autoincrease = False
                                self.recording[self.selectedEntry].end = ret[1]
                                self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
 
        def changeDuration(self, entry):
                                self.recording[self.selectedEntry].end = ret[1]
                                self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
 
        def changeDuration(self, entry):
-               if entry is not None:
+               if entry is not None and entry >= 0:
                        self.selectedEntry = entry
                        self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
 
        def inputCallback(self, value):
                if value is not None:
                        print "stopping recording after", int(value), "minutes."
                        self.selectedEntry = entry
                        self.session.openWithCallback(self.inputCallback, InputBox, title=_("How many minutes do you want to record?"), text="5", maxSize=False, type=Input.NUMBER)
 
        def inputCallback(self, value):
                if value is not None:
                        print "stopping recording after", int(value), "minutes."
-                       self.recording[self.selectedEntry].end = time() + 60 * int(value)
-                       self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
+                       entry = self.recording[self.selectedEntry]
+                       if int(value) != 0:
+                               entry.autoincrease = False
+                       entry.end = int(time()) + 60 * int(value)
+                       self.session.nav.RecordTimer.timeChanged(entry)
 
        def instantRecord(self):
 
        def instantRecord(self):
+               dir = preferredInstantRecordPath()
+               if not dir or not fileExists(dir, 'w'):
+                       dir = defaultMoviePath()
                try:
                try:
-                       stat = os_stat(resolveFilename(SCOPE_HDD))
+                       stat = os_stat(dir)
                except:
                except:
+                       # XXX: this message is a little odd as we might be recording to a remote device
                        self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
                        return
 
                if self.isInstantRecordRunning():
                        self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
                                title=_("A recording is currently running.\nWhat do you want to do?"), \
                        self.session.open(MessageBox, _("No HDD found or HDD not initialized!"), MessageBox.TYPE_ERROR)
                        return
 
                if self.isInstantRecordRunning():
                        self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
                                title=_("A recording is currently running.\nWhat do you want to do?"), \
-                               list=[(_("stop recording"), "stop"), \
-                               (_("change recording (duration)"), "changeduration"), \
-                               (_("change recording (endtime)"), "changeendtime"), \
-                               (_("add recording (indefinitely)"), "indefinitely"), \
+                               list=((_("stop recording"), "stop"), \
                                (_("add recording (stop after current event)"), "event"), \
                                (_("add recording (stop after current event)"), "event"), \
+                               (_("add recording (indefinitely)"), "indefinitely"), \
                                (_("add recording (enter recording duration)"), "manualduration"), \
                                (_("add recording (enter recording endtime)"), "manualendtime"), \
                                (_("add recording (enter recording duration)"), "manualduration"), \
                                (_("add recording (enter recording endtime)"), "manualendtime"), \
-                               (_("do nothing"), "no")])
+                               (_("change recording (duration)"), "changeduration"), \
+                               (_("change recording (endtime)"), "changeendtime"), \
+                               (_("do nothing"), "no")))
                else:
                        self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
                                title=_("Start recording?"), \
                else:
                        self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
                                title=_("Start recording?"), \
-                               list=[(_("add recording (indefinitely)"), "indefinitely"), \
-                               (_("add recording (stop after current event)"), "event"), \
+                               list=((_("add recording (stop after current event)"), "event"), \
+                               (_("add recording (indefinitely)"), "indefinitely"), \
                                (_("add recording (enter recording duration)"), "manualduration"), \
                                (_("add recording (enter recording endtime)"), "manualendtime"), \
                                (_("add recording (enter recording duration)"), "manualduration"), \
                                (_("add recording (enter recording endtime)"), "manualendtime"), \
-                               (_("don't record"), "no")])
+                               (_("don't record"), "no")))
 
 from Tools.ISO639 import LanguageCodes
 
 
 from Tools.ISO639 import LanguageCodes
 
@@ -1526,20 +1679,30 @@ class InfoBarAudioSelection:
                if n > 0:
                        self.audioChannel = service.audioChannel()
 
                if n > 0:
                        self.audioChannel = service.audioChannel()
 
-                       for x in range(n):
-                               i = audio.getTrackInfo(x)
-                               language = i.getLanguage()
+                       idx = 0
+                       while idx < n:
+                               cnt = 0
+                               i = audio.getTrackInfo(idx)
+                               languages = i.getLanguage().split('/')
                                description = i.getDescription()
                                description = i.getDescription()
+                               language = ""
 
 
-                               if LanguageCodes.has_key(language):
-                                       language = LanguageCodes[language][0]
+                               for lang in languages:
+                                       if cnt:
+                                               language += ' / '
+                                       if LanguageCodes.has_key(lang):
+                                               language += LanguageCodes[lang][0]
+                                       else:
+                                               language += lang
+                                       cnt += 1
 
                                if len(description):
                                        description += " (" + language + ")"
                                else:
                                        description = language
 
 
                                if len(description):
                                        description += " (" + language + ")"
                                else:
                                        description = language
 
-                               tlist.append((description, x))
+                               tlist.append((description, idx))
+                               idx += 1
 
                        tlist.sort(key=lambda x: x[0])
 
 
                        tlist.sort(key=lambda x: x[0])
 
@@ -1553,17 +1716,46 @@ class InfoBarAudioSelection:
                                else:
                                        break
 
                                else:
                                        break
 
+                       availableKeys = []
+                       usedKeys = []
+
                        if SystemInfo["CanDownmixAC3"]:
                        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
                                selection += 2
-                       self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection, keys = keys)
+                       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
 
                else:
                        del self.audioTracks
 
@@ -1572,7 +1764,7 @@ class InfoBarAudioSelection:
                list = choicelist.list
                t = list[0][1]
                list[0][1]=(t[0], t[1], t[2], t[3], t[4], t[5], t[6],
                list = choicelist.list
                t = list[0][1]
                list[0][1]=(t[0], t[1], t[2], t[3], t[4], t[5], t[6],
-                       _("AC3 downmix") + " - " +[_("On"), _("Off")][config.av.downmix_ac3.value and 1 or 0])
+                       _("AC3 downmix") + " - " + (_("On"), _("Off"))[config.av.downmix_ac3.value and 1 or 0])
                choicelist.setList(list)
                if config.av.downmix_ac3.value:
                        config.av.downmix_ac3.value = False
                choicelist.setList(list)
                if config.av.downmix_ac3.value:
                        config.av.downmix_ac3.value = False
@@ -1586,8 +1778,8 @@ class InfoBarAudioSelection:
                                if audio[1] == "mode":
                                        keys = ["red", "green", "yellow"]
                                        selection = self.audioChannel.getCurrentChannel()
                                if audio[1] == "mode":
                                        keys = ["red", "green", "yellow"]
                                        selection = self.audioChannel.getCurrentChannel()
-                                       tlist = [(_("left"), 0), (_("stereo"), 1), (_("right"), 2)]
-                                       self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys)
+                                       tlist = ((_("left"), 0), (_("stereo"), 1), (_("right"), 2))
+                                       self.session.openWithCallback(self.modeSelected, ChoiceBox, title=_("Select audio mode"), list = tlist, selection = selection, keys = keys, skin_name ="AudioModeSelection")
                        else:
                                del self.audioChannel
                                if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
                        else:
                                del self.audioChannel
                                if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
@@ -1615,16 +1807,18 @@ class InfoBarSubserviceSelection:
                        }, -1)
                self["SubserviceQuickzapAction"].setEnabled(False)
 
                        }, -1)
                self["SubserviceQuickzapAction"].setEnabled(False)
 
-               self.session.nav.event.append(self.checkSubservicesAvail) # we like to get service events
+               self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
+                       {
+                               iPlayableService.evUpdatedEventInfo: self.checkSubservicesAvail
+                       })
 
                self.bsel = None
 
 
                self.bsel = None
 
-       def checkSubservicesAvail(self, ev):
-               if ev == iPlayableService.evUpdatedEventInfo:
-                       service = self.session.nav.getCurrentService()
-                       subservices = service and service.subServices()
-                       if not subservices or subservices.getNumberOfSubservices() == 0:
-                               self["SubserviceQuickzapAction"].setEnabled(False)
+       def checkSubservicesAvail(self):
+               service = self.session.nav.getCurrentService()
+               subservices = service and service.subServices()
+               if not subservices or subservices.getNumberOfSubservices() == 0:
+                       self["SubserviceQuickzapAction"].setEnabled(False)
 
        def nextSubservice(self):
                self.changeSubservice(+1)
 
        def nextSubservice(self):
                self.changeSubservice(+1)
@@ -1639,9 +1833,12 @@ class InfoBarSubserviceSelection:
                if n and n > 0:
                        selection = -1
                        ref = self.session.nav.getCurrentlyPlayingServiceReference()
                if n and n > 0:
                        selection = -1
                        ref = self.session.nav.getCurrentlyPlayingServiceReference()
-                       for x in range(n):
-                               if subservices.getSubservice(x).toString() == ref.toString():
-                                       selection = x
+                       idx = 0
+                       while idx < n:
+                               if subservices.getSubservice(idx).toString() == ref.toString():
+                                       selection = idx
+                                       break
+                               idx += 1
                        if selection != -1:
                                selection += direction
                                if selection >= n:
                        if selection != -1:
                                selection += direction
                                if selection >= n:
@@ -1663,14 +1860,16 @@ class InfoBarSubserviceSelection:
                if n and n > 0:
                        ref = self.session.nav.getCurrentlyPlayingServiceReference()
                        tlist = []
                if n and n > 0:
                        ref = self.session.nav.getCurrentlyPlayingServiceReference()
                        tlist = []
-                       for x in range(n):
-                               i = subservices.getSubservice(x)
+                       idx = 0
+                       while idx < n:
+                               i = subservices.getSubservice(idx)
                                if i.toString() == ref.toString():
                                if i.toString() == ref.toString():
-                                       selection = x
+                                       selection = idx
                                tlist.append((i.getName(), i))
                                tlist.append((i.getName(), i))
+                               idx += 1
 
                        if self.bouquets and len(self.bouquets):
 
                        if self.bouquets and len(self.bouquets):
-                               keys = ["red", "green", "",  "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] + [""] * n
+                               keys = ["red", "blue", "",  "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] + [""] * n
                                if config.usage.multibouquet.value:
                                        tlist = [(_("Quickzap"), "quickzap", service.subServices()), (_("Add to bouquet"), "CALLFUNC", self.addSubserviceToBouquetCallback), ("--", "")] + tlist
                                else:
                                if config.usage.multibouquet.value:
                                        tlist = [(_("Quickzap"), "quickzap", service.subServices()), (_("Add to bouquet"), "CALLFUNC", self.addSubserviceToBouquetCallback), ("--", "")] + tlist
                                else:
@@ -1681,7 +1880,7 @@ class InfoBarSubserviceSelection:
                                keys = ["red", "",  "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] + [""] * n
                                selection += 2
 
                                keys = ["red", "",  "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ] + [""] * n
                                selection += 2
 
-                       self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection, keys = keys)
+                       self.session.openWithCallback(self.subserviceSelected, ChoiceBox, title=_("Please select a subservice..."), list = tlist, selection = selection, keys = keys, skin_name = "SubserviceSelection")
 
        def subserviceSelected(self, service):
                del self.bouquets
 
        def subserviceSelected(self, service):
                del self.bouquets
@@ -1723,8 +1922,11 @@ class InfoBarSubserviceSelection:
 class InfoBarAdditionalInfo:
        def __init__(self):
 
 class InfoBarAdditionalInfo:
        def __init__(self):
 
-               self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0)
+               self["RecordingPossible"] = Boolean(fixed=harddiskmanager.HDDCount() > 0 and config.misc.rcused.value == 1)
                self["TimeshiftPossible"] = self["RecordingPossible"]
                self["TimeshiftPossible"] = self["RecordingPossible"]
+               self["ShowTimeshiftOnYellow"] = Boolean(fixed=(not config.misc.rcused.value == 0))
+               self["ShowAudioOnYellow"] = Boolean(fixed=config.misc.rcused.value == 0)
+               self["ShowRecordOnRed"] = Boolean(fixed=config.misc.rcused.value == 1)
                self["ExtensionsAvailable"] = Boolean(fixed=1)
 
 class InfoBarNotifications:
                self["ExtensionsAvailable"] = Boolean(fixed=1)
 
 class InfoBarNotifications:
@@ -1741,10 +1943,11 @@ class InfoBarNotifications:
                        self.checkNotifications()
 
        def checkNotifications(self):
                        self.checkNotifications()
 
        def checkNotifications(self):
-               if len(Notifications.notifications):
-                       n = Notifications.notifications[0]
+               notifications = Notifications.notifications
+               if notifications:
+                       n = notifications[0]
 
 
-                       Notifications.notifications = Notifications.notifications[1:]
+                       del notifications[0]
                        cb = n[0]
 
                        if n[3].has_key("onSessionOpenCallback"):
                        cb = n[0]
 
                        if n[3].has_key("onSessionOpenCallback"):
@@ -1817,8 +2020,10 @@ class InfoBarCueSheetSupport:
 
                        if last is not None:
                                self.resume_point = last
 
                        if last is not None:
                                self.resume_point = last
+                               
+                               l = last / 90000
                                if config.usage.on_movie_start.value == "ask":
                                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
                                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
@@ -1897,7 +2102,7 @@ class InfoBarCueSheetSupport:
                        if bestdiff >= 0:
                                nearest = [0, False]
                for cp in self.cut_list:
                        if bestdiff >= 0:
                                nearest = [0, False]
                for cp in self.cut_list:
-                       if beforecut and cp[1] in [self.CUT_TYPE_IN, self.CUT_TYPE_OUT]:
+                       if beforecut and cp[1] in (self.CUT_TYPE_IN, self.CUT_TYPE_OUT):
                                beforecut = False
                                if cp[1] == self.CUT_TYPE_IN:  # Start is here, disregard previous marks
                                        diff = cmp(cp[0] - pts)
                                beforecut = False
                                if cp[1] == self.CUT_TYPE_IN:  # Start is here, disregard previous marks
                                        diff = cmp(cp[0] - pts)
@@ -1906,7 +2111,7 @@ class InfoBarCueSheetSupport:
                                                bestdiff = diff
                                        else:
                                                nearest = None
                                                bestdiff = diff
                                        else:
                                                nearest = None
-                       if cp[1] in [self.CUT_TYPE_MARK, self.CUT_TYPE_LAST]:
+                       if cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST):
                                diff = cmp(cp[0] - pts)
                                if diff >= 0 and (nearest is None or bestdiff > diff):
                                        nearest = cp
                                diff = cmp(cp[0] - pts)
                                if diff >= 0 and (nearest is None or bestdiff > diff):
                                        nearest = cp
@@ -1992,9 +2197,6 @@ class InfoBarSummary(Screen):
 #                      <convert type="ServiceName">Reference</convert>
 #              </widget>
 
 #                      <convert type="ServiceName">Reference</convert>
 #              </widget>
 
-       def __init__(self, session, parent):
-               Screen.__init__(self, session, parent = parent)
-
 class InfoBarSummarySupport:
        def __init__(self):
                pass
 class InfoBarSummarySupport:
        def __init__(self):
                pass
@@ -2020,9 +2222,6 @@ class InfoBarMoviePlayerSummary(Screen):
                </widget>
        </screen>"""
 
                </widget>
        </screen>"""
 
-       def __init__(self, session, parent):
-               Screen.__init__(self, session)
-
 class InfoBarMoviePlayerSummarySupport:
        def __init__(self):
                pass
 class InfoBarMoviePlayerSummarySupport:
        def __init__(self):
                pass
@@ -2063,19 +2262,19 @@ class InfoBarSubtitleSupport(object):
                self.__selected_subtitle = None
 
        def __serviceStopped(self):
                self.__selected_subtitle = None
 
        def __serviceStopped(self):
-               self.subtitle_window.hide()
-               self.__subtitles_enabled = False
                self.cached_subtitle_checked = False
                self.cached_subtitle_checked = False
+               if self.__subtitles_enabled:
+                       self.subtitle_window.hide()
+                       self.__subtitles_enabled = False
+                       self.__selected_subtitle = None
 
        def __updatedInfo(self):
                if not self.cached_subtitle_checked:
 
        def __updatedInfo(self):
                if not self.cached_subtitle_checked:
-                       subtitle = self.getCurrentServiceSubtitle()
                        self.cached_subtitle_checked = True
                        self.cached_subtitle_checked = True
-                       self.__selected_subtitle = subtitle and subtitle.getCachedSubtitle()
+                       subtitle = self.getCurrentServiceSubtitle()
+                       self.setSelectedSubtitle(subtitle and subtitle.getCachedSubtitle())
                        if self.__selected_subtitle:
                        if self.__selected_subtitle:
-                               subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
-                               self.subtitle_window.show()
-                               self.__subtitles_enabled = True
+                               self.setSubtitlesEnable(True)
 
        def getCurrentServiceSubtitle(self):
                service = self.session.nav.getCurrentService()
 
        def getCurrentServiceSubtitle(self):
                service = self.session.nav.getCurrentService()
@@ -2083,14 +2282,16 @@ class InfoBarSubtitleSupport(object):
 
        def setSubtitlesEnable(self, enable=True):
                subtitle = self.getCurrentServiceSubtitle()
 
        def setSubtitlesEnable(self, enable=True):
                subtitle = self.getCurrentServiceSubtitle()
-               if enable and self.__selected_subtitle is not None:
-                       if subtitle and not self.__subtitles_enabled:
-                               subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
-                               self.subtitle_window.show()
-                               self.__subtitles_enabled = True
+               if enable:
+                       if self.__selected_subtitle:
+                               if subtitle and not self.__subtitles_enabled:
+                                       subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle)
+                                       self.subtitle_window.show()
+                                       self.__subtitles_enabled = True
                else:
                        if subtitle:
                                subtitle.disableSubtitles(self.subtitle_window.instance)
                else:
                        if subtitle:
                                subtitle.disableSubtitles(self.subtitle_window.instance)
+                       self.__selected_subtitle = False
                        self.__subtitles_enabled = False
                        self.subtitle_window.hide()
 
                        self.__subtitles_enabled = False
                        self.subtitle_window.hide()
 
@@ -2123,7 +2324,7 @@ class InfoBarServiceErrorPopupSupport:
                else:
                        self.last_error = error
 
                else:
                        self.last_error = error
 
-               errors = {
+               error = {
                        eDVBServicePMTHandler.eventNoResources: _("No free tuner!"),
                        eDVBServicePMTHandler.eventTuneFailed: _("Tune failed!"),
                        eDVBServicePMTHandler.eventNoPAT: _("No data on transponder!\n(Timeout reading PAT)"),
                        eDVBServicePMTHandler.eventNoResources: _("No free tuner!"),
                        eDVBServicePMTHandler.eventTuneFailed: _("Tune failed!"),
                        eDVBServicePMTHandler.eventNoPAT: _("No data on transponder!\n(Timeout reading PAT)"),
@@ -2134,9 +2335,7 @@ class InfoBarServiceErrorPopupSupport:
                        eDVBServicePMTHandler.eventSOF: None,
                        eDVBServicePMTHandler.eventEOF: None,
                        eDVBServicePMTHandler.eventMisconfiguration: _("Service unavailable!\nCheck tuner configuration!"),
                        eDVBServicePMTHandler.eventSOF: None,
                        eDVBServicePMTHandler.eventEOF: None,
                        eDVBServicePMTHandler.eventMisconfiguration: _("Service unavailable!\nCheck tuner configuration!"),
-               }
-
-               error = errors.get(error) #this returns None when the key not exist in the dict
+               }.get(error) #this returns None when the key not exist in the dict
 
                if error is not None:
                        Notifications.AddPopup(text = error, type = MessageBox.TYPE_ERROR, timeout = 5, id = "ZapError")
 
                if error is not None:
                        Notifications.AddPopup(text = error, type = MessageBox.TYPE_ERROR, timeout = 5, id = "ZapError")