Merge remote-tracking branch 'origin/bug_453_multiepg_no_more_ask_bouquet' into exper...
authorghost <andreas.monzner@multimedia-labs.de>
Thu, 10 Mar 2011 18:34:07 +0000 (19:34 +0100)
committerghost <andreas.monzner@multimedia-labs.de>
Thu, 10 Mar 2011 18:34:07 +0000 (19:34 +0100)
1  2 
lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py
lib/python/Screens/ChannelSelection.py
lib/python/Screens/InfoBarGenerics.py

@@@ -1,6 -1,6 +1,6 @@@
  from Plugins.Plugin import PluginDescriptor
  from GraphMultiEpg import GraphMultiEPG
- from Screens.ChannelSelection import BouquetSelector
+ from Screens.ChannelSelection import SilentBouquetSelector
  from enigma import eServiceCenter, eServiceReference
  from ServiceReference import ServiceReference
  
@@@ -79,20 -79,20 +79,20 @@@ def main(session, servicelist, **kwargs
        global Servicelist
        Servicelist = servicelist
        bouquets = Servicelist.getBouquetList()
+       root = Servicelist.getRoot()
        if bouquets is None:
                cnt = 0
        else:
                cnt = len(bouquets)
-       if cnt > 1: # show bouquet list
+       if cnt > 1: # create bouquet list
                global bouquetSel
-               bouquetSel = Session.openWithCallback(closed, BouquetSelector, bouquets, openBouquetEPG, enableWrapAround=True)
-               dlg_stack.append(bouquetSel)
-       elif cnt == 1:
-               if not openBouquetEPG(bouquets[0][1]):
+               bouquetSel = SilentBouquetSelector(bouquets, True, Servicelist.getBouquetNumOffset(root))
+       if cnt >= 1: # open current bouquet
+               if not openBouquetEPG(root):
                        cleanup()
  
  def Plugins(**kwargs):
        name = _("Graphical Multi EPG")
        descr = _("A graphical EPG for all services of an specific bouquet")
 -      return [ PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EVENTINFO, fnc=main),
 -        PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main) ]
 +      return [PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EVENTINFO, needsRestart = False, fnc=main),
 +              PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart = False, fnc=main)]
@@@ -8,7 -8,7 +8,7 @@@ from Components.MenuList import MenuLis
  from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
  profile("ChannelSelection.py 1")
  from EpgSelection import EPGSelection
 -from enigma import eServiceReference, eEPGCache, eServiceCenter, eRCInput, eTimer, eDVBDB, iPlayableService, iServiceInformation, getPrevAsciiCode
 +from enigma import eServiceReference, eEPGCache, eServiceCenter, eRCInput, eTimer, eDVBDB, iPlayableService, iServiceInformation, getPrevAsciiCode, eEnv
  from Components.config import config, ConfigSubsection, ConfigText
  from Tools.NumericalTextInput import NumericalTextInput
  profile("ChannelSelection.py 2")
@@@ -20,6 -20,7 +20,6 @@@ from Components.Sources.ServiceEvent im
  profile("ChannelSelection.py 2.3")
  from Components.Input import Input
  profile("ChannelSelection.py 3")
 -from Components.ParentalControl import parentalControl
  from Components.ChoiceList import ChoiceList, ChoiceEntryComponent
  from Components.SystemInfo import SystemInfo
  from Screens.InputBox import InputBox, PinInput
@@@ -65,6 -66,24 +65,24 @@@ class BouquetSelector(Screen)
        def cancelClick(self):
                self.close(False)
  
+ class SilentBouquetSelector:
+       def __init__(self, bouquets, enableWrapAround=False, current=0):
+               self.bouquets = [b[1] for b in bouquets]
+               self.pos = current
+               self.count = len(bouquets)
+               self.enableWrapAround = enableWrapAround
+       def up(self):
+               if self.pos > 0 or self.enableWrapAround:
+                       self.pos = (self.pos - 1) % self.count
+       def down(self):
+               if self.pos < (self.count - 1) or self.enableWrapAround:
+                       self.pos = (self.pos + 1) % self.count
+       def getCurrent(self):
+               return self.bouquets[self.pos]
  # csel.bouquet_mark_edit values
  OFF = 0
  EDIT_BOUQUET = 1
@@@ -76,7 -95,6 +94,7 @@@ def append_when_current_valid(current, 
  
  class ChannelContextMenu(Screen):
        def __init__(self, session, csel):
 +
                Screen.__init__(self, session)
                #raise Exception("we need a better summary screen here")
                self.csel = csel
                                isPlayable = not (current_sel_flags & (eServiceReference.isMarker|eServiceReference.isDirectory))
                                if isPlayable:
                                        if config.ParentalControl.configured.value:
 +                                              from Components.ParentalControl import parentalControl
                                                if parentalControl.getProtectionLevel(csel.getCurrentSelection().toCompareString()) == -1:
                                                        append_when_current_valid(current, menu, (_("add to parental protection"), boundFunction(self.addParentalProtection, csel.getCurrentSelection())), level = 0)
                                                else:
                                                        append_when_current_valid(current, menu, (_("remove from parental protection"), boundFunction(self.removeParentalProtection, csel.getCurrentSelection())), level = 0)
                                        if haveBouquets:
 -                                              append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level = 0)
 +                                              bouquets = self.csel.getBouquetList()
 +                                              if bouquets is None:
 +                                                      bouquetCnt = 0
 +                                              else:
 +                                                      bouquetCnt = len(bouquets)
 +                                              if not inBouquet or bouquetCnt > 1:
 +                                                      append_when_current_valid(current, menu, (_("add service to bouquet"), self.addServiceToBouquetSelected), level = 0)
                                        else:
 -                                              append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level = 0)
 +                                              if not inBouquet:
 +                                                      append_when_current_valid(current, menu, (_("add service to favourites"), self.addServiceToBouquetSelected), level = 0)
                                else:
                                        if current_root.getPath().find('FROM SATELLITES') != -1:
                                                append_when_current_valid(current, menu, (_("remove selected satellite"), self.removeSatelliteServices), level = 0)
                self.close()
  
        def addParentalProtection(self, service):
 +              from Components.ParentalControl import parentalControl
                parentalControl.protectService(service.toCompareString())
                self.close()
  
  
        def pinEntered(self, service, result):
                if result:
 +                      from Components.ParentalControl import parentalControl
                        parentalControl.unProtectService(service)
                        self.close()
                else:
                if cnt > 1: # show bouquet list
                        self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
                elif cnt == 1: # add to only one existing bouquet
 -                      self.addCurrentServiceToBouquet(bouquets[0][1])
 +                      self.addCurrentServiceToBouquet(bouquets[0][1], closeBouquetSelection = False)
  
        def bouquetSelClosed(self, recursive):
                self.bsel = None
                        self.csel.addMarker(marker)
                self.close()
  
 -      def addCurrentServiceToBouquet(self, dest):
 +      def addCurrentServiceToBouquet(self, dest, closeBouquetSelection = True):
                self.csel.addServiceToBouquet(dest)
                if self.bsel is not None:
                        self.bsel.close(True)
                else:
 -                      self.close(True) # close bouquet selection
 +                      self.close(closeBouquetSelection) # close bouquet selection
  
        def removeCurrentService(self):
                self.csel.removeCurrentService()
@@@ -459,7 -467,7 +477,7 @@@ class ChannelSelectionEdit
                                if mutableAlternatives:
                                        mutableAlternatives.setListName(name)
                                        if mutableAlternatives.addService(cur_service.ref):
 -                                              print "add", cur_service.toString(), "to new alternatives failed"
 +                                              print "add", cur_service.ref.toString(), "to new alternatives failed"
                                        mutableAlternatives.flushChanges()
                                        self.servicelist.addService(new_ref.ref, True)
                                        self.servicelist.removeCurrent()
                        refstr = refstr[pos+14:]
                        pos = refstr.find('"')
                        if pos != -1:
 -                              filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
 +                              filename = eEnv.resolve('${sysconfdir}/enigma2/') + refstr[:pos]
                self.removeCurrentService()
                try:
                        if filename is not None:
@@@ -1410,9 -1418,9 +1428,9 @@@ class ChannelSelectionRadio(ChannelSele
  
                self["actions"] = ActionMap(["OkCancelActions", "TvRadioActions"],
                        {
 -                              "keyTV": self.closeRadio,
 -                              "keyRadio": self.closeRadio,
 -                              "cancel": self.closeRadio,
 +                              "keyTV": self.cancel,
 +                              "keyRadio": self.cancel,
 +                              "cancel": self.cancel,
                                "ok": self.channelSelected,
                        })
  
                self["RdsActions"].setEnabled(state)
  ########## RDS Radiotext / Rass Support END
  
 -      def closeRadio(self):
 +      def cancel(self):
                self.infobar.rds_display.onRassInteractivePossibilityChanged.remove(self.RassInteractivePossibilityChanged)
                self.info.hide()
                #set previous tv service
@@@ -1,4 -1,4 +1,4 @@@
- from ChannelSelection import ChannelSelection, BouquetSelector
+ from ChannelSelection import ChannelSelection, BouquetSelector, SilentBouquetSelector
  
  from Components.ActionMap import ActionMap, HelpableActionMap
  from Components.ActionMap import NumberActionMap
@@@ -487,7 -487,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,
                        })
  
  
        def openMultiServiceEPG(self, withCallback=True):
                bouquets = self.servicelist.getBouquetList()
+               root = self.servicelist.getRoot()
                if bouquets is None:
                        cnt = 0
                else:
                        cnt = len(bouquets)
-               if cnt > 1: # show bouquet list
-                       if withCallback:
-                               self.bouquetSel = self.session.openWithCallback(self.closed, BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
-                               self.dlg_stack.append(self.bouquetSel)
-                       else:
-                               self.bouquetSel = self.session.open(BouquetSelector, bouquets, self.openBouquetEPG, enableWrapAround=True)
-               elif cnt == 1:
-                       self.openBouquetEPG(bouquets[0][1], withCallback)
+               if cnt > 1: # create bouquet list for bouq+/-
+                       self.bouquetSel = SilentBouquetSelector(bouquets, True, self.servicelist.getBouquetNumOffset(root))
+               if cnt >= 1:
+                       self.openBouquetEPG(root, withCallback)
  
        def changeServiceCB(self, direction, epg):
                if self.serviceSel:
  
                if list:
                        list.append((_("show single service EPG..."), self.openSingleServiceEPG))
 +                      list.append((_("Multi EPG"), self.openMultiServiceEPG))
                        self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list, skin_name = "EPGExtensionsList")
                else:
                        self.openSingleServiceEPG()
@@@ -717,7 -713,7 +714,7 @@@ class InfoBarSeek
        SEEK_STATE_PAUSE = (1, 0, 0, "||")
        SEEK_STATE_EOF = (1, 0, 0, "END")
  
 -      def __init__(self, actionmap = "InfobarSeekActions", useSeekBackHack=True):
 +      def __init__(self, actionmap = "InfobarSeekActions"):
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
                                iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
                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:
 -                      return (0, n, 0, ">> %dx" % 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 minspeed != "Never" and n >= int(minspeed) and repeat > 1:
 -#                     return (0, -n * repeat, repeat, "<< %dx" % n)
 -#             else:
 -                      return (0, -n, 0, "<< %dx" % n)
 +              return (0, -n, 0, "<< %dx" % n)
  
        def makeStateSlowMotion(self, n):
                return (0, 0, n, "/%d" % n)
@@@ -1101,21 -1107,15 +1098,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:
  
@@@ -1524,30 -1524,28 +1521,30 @@@ class InfoBarInstantRecord
  
                recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = preferredInstantRecordPath())
                recording.dontSave = True
 -              
 +
                if event is None or limitEvent == False:
                        recording.autoincrease = True
 -                      if recording.setAutoincreaseEnd():
 -                              self.session.nav.RecordTimer.record(recording)
 -                              self.recording.append(recording)
 +                      recording.setAutoincreaseEnd()
 +
 +              simulTimerList = self.session.nav.RecordTimer.record(recording)
 +
 +              if simulTimerList is None:      # no conflict
 +                      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:
 +                      if len(simulTimerList) > 1: # 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)
 +                      else:
 +                              self.session.open(MessageBox, _("Couldn't record due to invalid service %s") % serviceref, MessageBox.TYPE_INFO)
 +                      recording.autoincrease = False
  
        def isInstantRecordRunning(self):
                print "self.recording:", self.recording
@@@ -1665,11 -1663,126 +1662,11 @@@ class InfoBarAudioSelection
                        })
  
        def audioSelection(self):
 -              service = self.session.nav.getCurrentService()
 -              self.audioTracks = audio = service and service.audioTracks()
 -              n = audio and audio.getNumberOfTracks() or 0
 -              tlist = []
 -              if n > 0:
 -                      self.audioChannel = service.audioChannel()
 -
 -                      idx = 0
 -                      while idx < n:
 -                              cnt = 0
 -                              i = audio.getTrackInfo(idx)
 -                              languages = i.getLanguage().split('/')
 -                              description = i.getDescription()
 -                              language = ""
 -
 -                              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
 -
 -                              tlist.append((description, idx))
 -                              idx += 1
 -
 -                      tlist.sort(key=lambda x: x[0])
 -
 -                      selectedAudio = self.audioTracks.getCurrentTrack()
 -
 -                      selection = 0
 -
 -                      for x in tlist:
 -                              if x[1] != selectedAudio:
 -                                      selection += 1
 -                              else:
 -                                      break
 -
 -                      availableKeys = []
 -                      usedKeys = []
 -
 -                      if SystemInfo["CanDownmixAC3"]:
 -                              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
 -                      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
 -
 -      def changeAC3Downmix(self, arg):
 -              choicelist = self.session.current_dialog["list"]
 -              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])
 -              choicelist.setList(list)
 -              if config.av.downmix_ac3.value:
 -                      config.av.downmix_ac3.value = False
 -              else:
 -                      config.av.downmix_ac3.value = True
 -              config.av.downmix_ac3.save()
 -
 -      def audioSelected(self, audio):
 -              if audio is not None:
 -                      if isinstance(audio[1], str):
 -                              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, skin_name ="AudioModeSelection")
 -                      else:
 -                              del self.audioChannel
 -                              if self.session.nav.getCurrentService().audioTracks().getNumberOfTracks() > audio[1]:
 -                                      self.audioTracks.selectTrack(audio[1])
 -              else:
 -                      del self.audioChannel
 -              del self.audioTracks
 -
 -      def modeSelected(self, mode):
 -              if mode is not None:
 -                      self.audioChannel.selectChannel(mode[1])
 -              del self.audioChannel
 +              from Screens.AudioSelection import AudioSelection
 +              self.session.openWithCallback(self.audioSelected, AudioSelection, infobar=self)
 +              
 +      def audioSelected(self, ret=None):
 +              print "[infobar::audioSelected]", ret
  
  class InfoBarSubserviceSelection:
        def __init__(self):
@@@ -1962,21 -2075,20 +1959,21 @@@ class InfoBarCueSheetSupport
                return True
  
        def jumpPreviousMark(self):
 -              # we add 2 seconds, so if the play position is <2s after
 +              # we add 5 seconds, so if the play position is <5s after
                # the mark, the mark before will be used
                self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True)
  
        def jumpNextMark(self):
 -              if not self.jumpPreviousNextMark(lambda x: x):
 +              if not self.jumpPreviousNextMark(lambda x: x-90000):
                        self.doSeek(-1)
  
        def getNearestCutPoint(self, pts, cmp=abs, start=False):
                # can be optimized
 -              beforecut = False
 +              beforecut = True
                nearest = None
 +              bestdiff = -1
 +              instate = True
                if start:
 -                      beforecut = True
                        bestdiff = cmp(0 - pts)
                        if bestdiff >= 0:
                                nearest = [0, False]
                                beforecut = False
                                if cp[1] == self.CUT_TYPE_IN:  # Start is here, disregard previous marks
                                        diff = cmp(cp[0] - pts)
 -                                      if diff >= 0:
 +                                      if start and diff >= 0:
                                                nearest = cp
                                                bestdiff = diff
                                        else:
                                                nearest = None
 -                      if cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST):
 +                                              bestdiff = -1
 +                      if cp[1] == self.CUT_TYPE_IN:
 +                              instate = True
 +                      elif cp[1] == self.CUT_TYPE_OUT:
 +                              instate = False
 +                      elif 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):
 +                              if instate and diff >= 0 and (nearest is None or bestdiff > diff):
                                        nearest = cp
                                        bestdiff = diff
                return nearest