diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2008-11-17 15:42:54 +0100 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2008-11-17 15:42:54 +0100 |
| commit | a34ef895210161a8820e96829ac87806566e7858 (patch) | |
| tree | 55b9f104dbbdd8a1d72e598b989421f839576b9a /lib/python | |
| parent | 588010098dbcc24b82ea736feec6b6056cffd2e3 (diff) | |
| parent | 153e0ed5048c79c600e1acd085b62015b7314ba7 (diff) | |
| download | enigma2-a34ef895210161a8820e96829ac87806566e7858.tar.gz enigma2-a34ef895210161a8820e96829ac87806566e7858.zip | |
Merge branch 'master' into tmbinc/FixTimingBugs
Conflicts:
lib/dvb/sec.cpp
lib/python/Components/Network.py
lib/python/Components/Playlist.py
lib/python/Plugins/Extensions/DVDBurn/Process.py
lib/python/Plugins/Extensions/MediaPlayer/plugin.py
lib/python/Screens/TimerEdit.py
po/lt.po
po/nl.po
po/tr.po
Diffstat (limited to 'lib/python')
48 files changed, 2302 insertions, 778 deletions
diff --git a/lib/python/Components/HelpMenuList.py b/lib/python/Components/HelpMenuList.py index 25c9b8b6..04815c8d 100644..100755 --- a/lib/python/Components/HelpMenuList.py +++ b/lib/python/Components/HelpMenuList.py @@ -1,7 +1,6 @@ from GUIComponent import GUIComponent from enigma import eListboxPythonMultiContent, eListbox, gFont - from Tools.KeyBindings import queryKeyBinding, getKeyDescription #getKeyPositions @@ -13,6 +12,7 @@ class HelpMenuList(GUIComponent): self.onSelChanged = [ ] self.l = eListboxPythonMultiContent() self.callback = callback + self.extendedHelp = False l = [ ] for (actionmap, context, actions) in list: @@ -36,17 +36,26 @@ class HelpMenuList(GUIComponent): if flags & 8: # for long keypresses, prepend l_ into the key name. name = (name[0], "long") - print "name:", name - entry.append( (actionmap, context, action, name ) ) - entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 28, 0, 0, help) ) - + + if type(help).__name__== 'list': + self.extendedHelp = True + print "extendedHelpEntry found" + entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 26, 0, 0, help[0]) ) + entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 28, 400, 20, 1, 0, help[1]) ) + else: + entry.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 400, 28, 0, 0, help) ) + l.append(entry) self.l.setList(l) - - self.l.setFont(0, gFont("Regular", 24)) - self.l.setItemHeight(38) + if self.extendedHelp is True: + self.l.setFont(0, gFont("Regular", 24)) + self.l.setFont(1, gFont("Regular", 18)) + self.l.setItemHeight(50) + else: + self.l.setFont(0, gFont("Regular", 24)) + self.l.setItemHeight(38) def ok(self): # a list entry has a "private" tuple as first entry... diff --git a/lib/python/Components/Language.py b/lib/python/Components/Language.py index acb50e51..6d1e31f3 100644 --- a/lib/python/Components/Language.py +++ b/lib/python/Components/Language.py @@ -35,6 +35,7 @@ class Language: self.addLanguage(_("Spanish"), "es", "ES") self.addLanguage(_("Swedish"), "sv", "SE") self.addLanguage(_("Turkish"), "tr", "TR") + self.addLanguage(_("Ukrainian"), "uk", "UA") self.callbacks = [] diff --git a/lib/python/Components/Lcd.py b/lib/python/Components/Lcd.py index 0471843c..0e501237 100644 --- a/lib/python/Components/Lcd.py +++ b/lib/python/Components/Lcd.py @@ -44,9 +44,14 @@ def InitLcd(): ilcd = LCD() - config.lcd.bright = ConfigSlider(default=10, limits=(0, 10)) + config.lcd.standby = ConfigSlider(default=0, limits=(0, 10)) + config.lcd.standby.addNotifier(setLCDbright); + config.lcd.standby.apply = lambda : setLCDbright(config.lcd.standby) + + config.lcd.bright = ConfigSlider(default=5, limits=(0, 10)) config.lcd.bright.addNotifier(setLCDbright); config.lcd.bright.apply = lambda : setLCDbright(config.lcd.bright) + config.lcd.bright.callNotifiersOnSaveAndCancel = True if not ilcd.isOled(): config.lcd.contrast = ConfigSlider(default=5, limits=(0, 20)) @@ -54,9 +59,6 @@ def InitLcd(): else: config.lcd.contrast = ConfigNothing() - config.lcd.standby = ConfigSlider(default=0, limits=(0, 10)) - config.lcd.standby.apply = lambda : setLCDbright(config.lcd.standby) - config.lcd.invert = ConfigYesNo(default=False) config.lcd.invert.addNotifier(setLCDinverted); else: diff --git a/lib/python/Components/MediaPlayer.py b/lib/python/Components/MediaPlayer.py index 791274fc..87ba977c 100644 --- a/lib/python/Components/MediaPlayer.py +++ b/lib/python/Components/MediaPlayer.py @@ -40,7 +40,7 @@ def PlaylistEntryComponent(serviceref, state): if png is not None: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 5, 0, 16, 16, png)) - + return res class PlayList(MenuList): @@ -76,6 +76,7 @@ class PlayList(MenuList): def setCurrentPlaying(self, index): self.oldCurrPlaying = self.currPlaying self.currPlaying = index + self.moveToIndex(index) def updateState(self, state): if len(self.list) > self.oldCurrPlaying and self.oldCurrPlaying != -1: diff --git a/lib/python/Components/MovieList.py b/lib/python/Components/MovieList.py index ace36012..8568f3d6 100644 --- a/lib/python/Components/MovieList.py +++ b/lib/python/Components/MovieList.py @@ -103,7 +103,8 @@ class MovieList(GUIComponent): txt = info.getName(serviceref) service = ServiceReference(info.getInfoString(serviceref, iServiceInformation.sServiceref)) description = info.getInfoString(serviceref, iServiceInformation.sDescription) - + tags = info.getInfoString(serviceref, iServiceInformation.sTags) + begin_string = "" if begin > 0: t = FuzzyTime(begin) @@ -111,23 +112,33 @@ class MovieList(GUIComponent): if self.list_type == MovieList.LISTTYPE_ORIGINAL: res.append(MultiContentEntryText(pos=(0, 0), size=(width-182, 30), font = 0, flags = RT_HALIGN_LEFT, text=txt)) - if service is not None: - res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = service.getServiceName())) + if self.tags: + res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = tags)) + if service is not None: + res.append(MultiContentEntryText(pos=(200, 50), size=(200, 20), font = 1, flags = RT_HALIGN_LEFT, text = service.getServiceName())) + else: + if service is not None: + res.append(MultiContentEntryText(pos=(width-180, 0), size=(180, 30), font = 2, flags = RT_HALIGN_RIGHT, text = service.getServiceName())) res.append(MultiContentEntryText(pos=(0, 30), size=(width, 20), font=1, flags=RT_HALIGN_LEFT, text=description)) - res.append(MultiContentEntryText(pos=(0, 50), size=(width-270, 20), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) - res.append(MultiContentEntryText(pos=(width-200, 50), size=(200, 20), font=1, flags=RT_HALIGN_RIGHT, text=len)) + res.append(MultiContentEntryText(pos=(0, 50), size=(200, 20), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) + res.append(MultiContentEntryText(pos=(width-200, 50), size=(198, 20), font=1, flags=RT_HALIGN_RIGHT, text=len)) elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION: res.append(MultiContentEntryText(pos=(0, 0), size=(width-120, 20), font = 0, flags = RT_HALIGN_LEFT, text = txt)) - if service is not None: - res.append(MultiContentEntryText(pos=(width-212, 20), size=(154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName())) res.append(MultiContentEntryText(pos=(0, 20), size=(width-212, 17), font=1, flags=RT_HALIGN_LEFT, text=description)) res.append(MultiContentEntryText(pos=(width-120, 6), size=(120, 20), font=1, flags=RT_HALIGN_RIGHT, text=begin_string)) + if service is not None: + res.append(MultiContentEntryText(pos=(width-212, 20), size=(154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName())) res.append(MultiContentEntryText(pos=(width-58, 20), size=(58, 20), font=1, flags=RT_HALIGN_RIGHT, text=len)) elif self.list_type == MovieList.LISTTYPE_COMPACT: res.append(MultiContentEntryText(pos=(0, 0), size=(width-77, 20), font = 0, flags = RT_HALIGN_LEFT, text = txt)) - if service is not None: - res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName())) - res.append(MultiContentEntryText(pos=(0, 20), size=(width-200, 17), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) + if self.tags: + res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = tags)) + if service is not None: + res.append(MultiContentEntryText(pos=(200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_LEFT, text = service.getServiceName())) + else: + if service is not None: + res.append(MultiContentEntryText(pos=(width-200, 20), size=(200, 17), font = 1, flags = RT_HALIGN_RIGHT, text = service.getServiceName())) + res.append(MultiContentEntryText(pos=(0, 20), size=(200, 17), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) res.append(MultiContentEntryText(pos=(width-75, 0), size=(75, 20), font=0, flags=RT_HALIGN_RIGHT, text=len)) else: assert(self.list_type == MovieList.LISTTYPE_MINIMAL) @@ -212,6 +223,7 @@ class MovieList(GUIComponent): if this_tags == ['']: this_tags = [] this_tags = set(this_tags) + tags |= this_tags # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, @@ -219,7 +231,6 @@ class MovieList(GUIComponent): if filter_tags is not None and not this_tags.issuperset(filter_tags): continue - tags |= this_tags self.list.append((serviceref, info, begin, -1)) if self.sort_type == MovieList.SORT_ALPHANUMERIC: @@ -243,8 +254,9 @@ class MovieList(GUIComponent): for x in self.list: if x[0] == serviceref: self.instance.moveSelectionTo(count) - break + return True count += 1 - + return False + def moveDown(self): self.instance.moveSelection(self.instance.moveDown) diff --git a/lib/python/Components/Network.py b/lib/python/Components/Network.py index bed9d95f..64b3aa6c 100644..100755 --- a/lib/python/Components/Network.py +++ b/lib/python/Components/Network.py @@ -7,11 +7,21 @@ from Components.Console import Console class Network: def __init__(self): self.ifaces = {} - self.configuredInterfaces = [] + self.configuredInterfaces = [] + self.configuredNetworkAdapters = [] + self.NetworkState = 0 + self.DnsState = 0 self.nameservers = [] self.ethtool_bin = "/usr/sbin/ethtool" self.container = eConsoleAppContainer() self.Console = Console() + self.LinkConsole = Console() + self.restartConsole = Console() + self.deactivateConsole = Console() + self.deactivateInterfaceConsole = Console() + self.activateConsole = Console() + self.resetNetworkConsole = Console() + self.DnsConsole = Console() self.getInterfaces() def getInterfaces(self, callback = None): @@ -28,6 +38,11 @@ class Network: self.getDataForInterface(device, callback) except AttributeError: pass + #print "self.ifaces:", self.ifaces + #self.writeNetworkConfig() + #print ord(' ') + #for line in result: + # print ord(line[0]) # helper function def regExpMatch(self, pattern, string): @@ -46,66 +61,60 @@ class Network: ip.append(int(x)) return ip + def getDataForInterface(self, iface,callback): + #get ip out of ip addr, as avahi sometimes overrides it in ifconfig. + if not self.Console: + self.Console = Console() + cmd = "ip -o addr" + self.Console.ePopen(cmd, self.IPaddrFinished, [iface,callback]) + def IPaddrFinished(self, result, retval, extra_args): (iface, callback ) = extra_args data = { 'up': False, 'dhcp': False, 'preup' : False, 'postdown' : False } globalIPpattern = re_compile("scope global") ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' - ipLinePattern = re_compile('inet ' + ipRegexp +'/') + netRegexp = '[0-9]{1,2}' + macRegexp = '[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}' + ipLinePattern = re_compile('inet ' + ipRegexp + '/') ipPattern = re_compile(ipRegexp) - + netmaskLinePattern = re_compile('/' + netRegexp) + netmaskPattern = re_compile(netRegexp) + bcastLinePattern = re_compile(' brd ' + ipRegexp) + upPattern = re_compile('UP') + macPattern = re_compile('[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}') + macLinePattern = re_compile('link/ether ' + macRegexp) + for line in result.splitlines(): split = line.strip().split(' ',2) + if (split[1][:-1] == iface): + up = self.regExpMatch(upPattern, split[2]) + mac = self.regExpMatch(macPattern, self.regExpMatch(macLinePattern, split[2])) + if up is not None: + data['up'] = True + if iface is not 'lo': + self.configuredInterfaces.append(iface) + if mac is not None: + data['mac'] = mac if (split[1] == iface): if re_search(globalIPpattern, split[2]): ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, split[2])) + netmask = self.calc_netmask(self.regExpMatch(netmaskPattern, self.regExpMatch(netmaskLinePattern, split[2]))) + bcast = self.regExpMatch(ipPattern, self.regExpMatch(bcastLinePattern, split[2])) if ip is not None: data['ip'] = self.convertIP(ip) + if netmask is not None: + data['netmask'] = self.convertIP(netmask) + if bcast is not None: + data['bcast'] = self.convertIP(bcast) + if not data.has_key('ip'): data['dhcp'] = True data['ip'] = [0, 0, 0, 0] data['netmask'] = [0, 0, 0, 0] data['gateway'] = [0, 0, 0, 0] - cmd = "ifconfig " + iface - self.Console.ePopen(cmd, self.ifconfigFinished, [iface, data, callback]) - - def getDataForInterface(self, iface,callback): - #get ip out of ip addr, as avahi sometimes overrides it in ifconfig. - cmd = "ip -o addr" - self.Console.ePopen(cmd, self.IPaddrFinished, [iface,callback]) - - def ifconfigFinished(self, result, retval, extra_args ): - (iface, data, callback ) = extra_args - ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' - ipLinePattern = re_compile('inet addr:' + ipRegexp) - netmaskLinePattern = re_compile('Mask:' + ipRegexp) - bcastLinePattern = re_compile('Bcast:' + ipRegexp) - ipPattern = re_compile(ipRegexp) - upPattern = re_compile('UP ') - macPattern = re_compile('[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}') - - for line in result.splitlines(): - #ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, line)) - netmask = self.regExpMatch(ipPattern, self.regExpMatch(netmaskLinePattern, line)) - bcast = self.regExpMatch(ipPattern, self.regExpMatch(bcastLinePattern, line)) - up = self.regExpMatch(upPattern, line) - mac = self.regExpMatch(macPattern, line) - #if ip is not None: - # data['ip'] = self.convertIP(ip) - if netmask is not None: - data['netmask'] = self.convertIP(netmask) - if bcast is not None: - data['bcast'] = self.convertIP(bcast) - if up is not None: - data['up'] = True - if iface is not 'lo': - self.configuredInterfaces.append(iface) - if mac is not None: - data['mac'] = mac - cmd = "route -n | grep " + iface - self.Console.ePopen(cmd,self.routeFinished,[iface,data,callback]) + self.Console.ePopen(cmd,self.routeFinished, [iface, data, callback]) def routeFinished(self, result, retval, extra_args): (iface, data, callback) = extra_args @@ -119,16 +128,7 @@ class Network: gateway = self.regExpMatch(ipPattern, line[16:31]) if gateway is not None: data['gateway'] = self.convertIP(gateway) - - for line in result.splitlines(): #get real netmask in case avahi has overridden ifconfig netmask - split = line.strip().split(' ') - if re_search(ipPattern, split[0]): - foundip = self.convertIP(split[0]) - if (foundip[0] == data['ip'][0] and foundip[1] == data['ip'][1]): - if re_search(ipPattern, split[4]): - mask = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, split[4])) - if mask is not None: - data['netmask'] = self.convertIP(mask) + self.ifaces[iface] = data self.loadNetworkConfig(iface,callback) @@ -214,13 +214,16 @@ class Network: for ifacename, iface in ifaces.items(): if self.ifaces.has_key(ifacename): self.ifaces[ifacename]["dhcp"] = iface["dhcp"] - if len(self.Console.appContainers) == 0: - # load ns only once - self.loadNameserverConfig() - print "read configured interfac:", ifaces - print "self.ifaces after loading:", self.ifaces - if callback is not None: - callback(True) + if self.Console: + if len(self.Console.appContainers) == 0: + # save configured interfacelist + self.configuredNetworkAdapters = self.configuredInterfaces + # load ns only once + self.loadNameserverConfig() + print "read configured interfac:", ifaces + print "self.ifaces after loading:", self.ifaces + if callback is not None: + callback(True) def loadNameserverConfig(self): ipRegexp = "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" @@ -244,16 +247,39 @@ class Network: print "nameservers:", self.nameservers - def deactivateNetworkConfig(self): + def deactivateNetworkConfig(self, callback = None): + self.deactivateConsole = Console() + self.commands = [] + self.commands.append("/etc/init.d/avahi-daemon stop") for iface in self.ifaces.keys(): - system("ip addr flush " + iface) - system("/etc/init.d/networking stop") - system("killall -9 udhcpc") - system("rm /var/run/udhcpc*") + cmd = "ip addr flush " + iface + self.commands.append(cmd) + self.commands.append("/etc/init.d/networking stop") + self.commands.append("killall -9 udhcpc") + self.commands.append("rm /var/run/udhcpc*") + self.deactivateConsole.eBatch(self.commands, self.deactivateNetworkFinished, callback, debug=True) + + def deactivateNetworkFinished(self,extra_args): + callback = extra_args + if len(self.deactivateConsole.appContainers) == 0: + if callback is not None: + callback(True) - def activateNetworkConfig(self): - system("/etc/init.d/networking start") - self.getInterfaces() + def activateNetworkConfig(self, callback = None): + self.activateConsole = Console() + self.commands = [] + self.commands.append("/etc/init.d/networking start") + self.commands.append("/etc/init.d/avahi-daemon start") + self.activateConsole.eBatch(self.commands, self.activateNetworkFinished, callback, debug=True) + + def activateNetworkFinished(self,extra_args): + callback = extra_args + if len(self.activateConsole.appContainers) == 0: + if callback is not None: + callback(True) + + def getConfiguredAdapters(self): + return self.configuredNetworkAdapters def getNumberOfAdapters(self): return len(self.ifaces) @@ -312,7 +338,24 @@ class Network: if self.nameservers[i] == oldnameserver: self.nameservers[i] = newnameserver - def writeDefaultNetworkConfig(self,mode='lan'): + def resetNetworkConfig(self, mode='lan', callback = None): + self.resetNetworkConsole = Console() + self.commands = [] + self.commands.append("/etc/init.d/avahi-daemon stop") + for iface in self.ifaces.keys(): + cmd = "ip addr flush " + iface + self.commands.append(cmd) + self.commands.append("/etc/init.d/networking stop") + self.commands.append("killall -9 udhcpc") + self.commands.append("rm /var/run/udhcpc*") + self.resetNetworkConsole.eBatch(self.commands, self.resetNetworkFinishedCB, [mode, callback], debug=True) + + def resetNetworkFinishedCB(self, extra_args): + (mode, callback) = extra_args + if len(self.resetNetworkConsole.appContainers) == 0: + self.writeDefaultNetworkConfig(mode, callback) + + def writeDefaultNetworkConfig(self,mode='lan', callback = None): fp = file('/etc/network/interfaces', 'w') fp.write("# automatically generated by enigma 2\n# do NOT change manually!\n\n") fp.write("auto lo\n") @@ -329,50 +372,100 @@ class Network: fp.write("\n") fp.close() - def resetNetworkConfig(self,mode='lan'): - self.deactivateNetworkConfig() - self.writeDefaultNetworkConfig(mode) + self.resetNetworkConsole = Console() + self.commands = [] if mode == 'wlan': - system("ifconfig eth0 down") - system("ifconfig ath0 down") - system("ifconfig wlan0 up") + self.commands.append("ifconfig eth0 down") + self.commands.append("ifconfig ath0 down") + self.commands.append("ifconfig wlan0 up") if mode == 'wlan-mpci': - system("ifconfig eth0 down") - system("ifconfig wlan0 down") - system("ifconfig ath0 up") + self.commands.append("ifconfig eth0 down") + self.commands.append("ifconfig wlan0 down") + self.commands.append("ifconfig ath0 up") if mode == 'lan': - system("ifconfig eth0 up") - system("ifconfig wlan0 down") - system("ifconfig ath0 down") - self.getInterfaces() - - def checkNetworkState(self): - # www.dream-multimedia-tv.de, www.heise.de, www.google.de - return system("ping -c 1 82.149.226.170") == 0 or \ - system("ping -c 1 193.99.144.85") == 0 or \ - system("ping -c 1 209.85.135.103") == 0 - - def restartNetwork(self): - iNetwork.deactivateNetworkConfig() - iNetwork.activateNetworkConfig() + self.commands.append("ifconfig eth0 up") + self.commands.append("ifconfig wlan0 down") + self.commands.append("ifconfig ath0 down") + self.commands.append("/etc/init.d/avahi-daemon start") + self.resetNetworkConsole.eBatch(self.commands, self.resetNetworkFinished, [mode,callback], debug=True) + + def resetNetworkFinished(self,extra_args): + (mode, callback) = extra_args + if len(self.resetNetworkConsole.appContainers) == 0: + if callback is not None: + callback(True,mode) + + def checkNetworkState(self,statecallback): + # www.dream-multimedia-tv.de, www.heise.de, www.google.de + cmd1 = "ping -c 1 82.149.226.170" + cmd2 = "ping -c 1 193.99.144.85" + cmd3 = "ping -c 1 209.85.135.103" + self.PingConsole = Console() + self.PingConsole.ePopen(cmd1, self.checkNetworkStateFinished,statecallback) + self.PingConsole.ePopen(cmd2, self.checkNetworkStateFinished,statecallback) + self.PingConsole.ePopen(cmd3, self.checkNetworkStateFinished,statecallback) + + def checkNetworkStateFinished(self, result, retval,extra_args): + (statecallback) = extra_args + if self.PingConsole is not None: + if retval == 0: + self.PingConsole = None + statecallback(self.NetworkState) + else: + self.NetworkState += 1 + if len(self.PingConsole.appContainers) == 0: + statecallback(self.NetworkState) + + def restartNetwork(self,callback = None): + self.restartConsole = Console() + self.commands = [] + self.commands.append("/etc/init.d/avahi-daemon stop") + for iface in self.ifaces.keys(): + cmd = "ip addr flush " + iface + self.commands.append(cmd) + self.commands.append("/etc/init.d/networking stop") + self.commands.append("killall -9 udhcpc") + self.commands.append("rm /var/run/udhcpc*") + self.commands.append("/etc/init.d/networking start") + self.commands.append("/etc/init.d/avahi-daemon start") + self.restartConsole.eBatch(self.commands, self.restartNetworkFinished, callback, debug=True) + + def restartNetworkFinished(self,extra_args): + ( callback ) = extra_args + if callback is not None: + callback(True) def getLinkState(self,iface,callback): - self.dataAvail = callback cmd = self.ethtool_bin + " " + iface - self.container.appClosed.append(self.cmdFinished) - self.container.dataAvail.append(callback) - self.container.execute(cmd) - - def cmdFinished(self,retval): - self.container.appClosed.remove(self.cmdFinished) - self.container.dataAvail.remove(self.dataAvail) - - def stopContainer(self): - self.container.kill() - - def ContainerRunning(self): - return self.container.running() - + self.LinkConsole = Console() + self.LinkConsole.ePopen(cmd, self.getLinkStateFinished,callback) + + def getLinkStateFinished(self, result, retval,extra_args): + (callback) = extra_args + if self.LinkConsole is not None: + if len(self.LinkConsole.appContainers) == 0: + callback(result) + + def stopLinkStateConsole(self): + if self.LinkConsole is not None: + self.LinkConsole = None + + def stopDNSConsole(self): + if self.DnsConsole is not None: + self.DnsConsole = None + + def stopRestartConsole(self): + if self.restartConsole is not None: + self.restartConsole = None + + def stopGetInterfacesConsole(self): + if self.Console is not None: + self.Console = None + + def stopDeactivateInterfaceConsole(self): + if self.deactivateInterfaceConsole: + self.deactivateInterfaceConsole = None + def checkforInterface(self,iface): if self.getAdapterAttribute(iface, 'up') is True: return True @@ -384,13 +477,41 @@ class Network: else: return False - def checkDNSLookup(self): - return system("nslookup www.dream-multimedia-tv.de") == 0 or \ - system("nslookup www.heise.de") == 0 or \ - system("nslookup www.google.de") - - def deactivateInterface(self,iface): - system("ifconfig " + iface + " down") + def checkDNSLookup(self,statecallback): + cmd1 = "nslookup www.dream-multimedia-tv.de" + cmd2 = "nslookup www.heise.de" + cmd3 = "nslookup www.google.de" + self.DnsConsole = Console() + self.DnsConsole.ePopen(cmd1, self.checkDNSLookupFinished,statecallback) + self.DnsConsole.ePopen(cmd2, self.checkDNSLookupFinished,statecallback) + self.DnsConsole.ePopen(cmd3, self.checkDNSLookupFinished,statecallback) + + def checkDNSLookupFinished(self, result, retval,extra_args): + (statecallback) = extra_args + if self.DnsConsole is not None: + if retval == 0: + self.DnsConsole = None + statecallback(self.DnsState) + else: + self.DnsState += 1 + if len(self.DnsConsole.appContainers) == 0: + statecallback(self.DnsState) + + def deactivateInterface(self,iface,callback = None): + self.deactivateInterfaceConsole = Console() + self.commands = [] + cmd1 = "ip addr flush " + iface + cmd2 = "ifconfig " + iface + " down" + self.commands.append(cmd1) + self.commands.append(cmd2) + self.deactivateInterfaceConsole.eBatch(self.commands, self.deactivateInterfaceFinished, callback, debug=True) + + def deactivateInterfaceFinished(self,extra_args): + callback = extra_args + if self.deactivateInterfaceConsole: + if len(self.deactivateInterfaceConsole.appContainers) == 0: + if callback is not None: + callback(True) def detectWlanModule(self): self.wlanmodule = None @@ -411,6 +532,20 @@ class Network: self.wlanmodule = 'zydas' return self.wlanmodule + def calc_netmask(self,nmask): + from struct import pack, unpack + from socket import inet_ntoa, inet_aton + mask = 1L<<31 + xnet = (1L<<32)-1 + cidr_range = range(0, 32) + cidr = long(nmask) + if cidr not in cidr_range: + print 'cidr invalid: %d' % cidr + return None + else: + nm = ((1L<<cidr)-1)<<(32-cidr) + netmask = str(inet_ntoa(pack('>L', nm))) + return netmask iNetwork = Network() diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py index 3c7a147e..f4e91083 100644 --- a/lib/python/Components/NimManager.py +++ b/lib/python/Components/NimManager.py @@ -1,3 +1,5 @@ +from Tools.HardwareInfo import HardwareInfo + from config import config, ConfigSubsection, ConfigSelection, ConfigFloat, \ ConfigSatlist, ConfigYesNo, ConfigInteger, ConfigSubList, ConfigNothing, \ ConfigSubDict, ConfigOnOff, ConfigDateTime @@ -37,8 +39,8 @@ class SecConfigure: sec.addSatellite(orbpos) self.configuredSatellites.add(orbpos) - def addLNBSimple(self, sec, slotid, diseqcmode, toneburstmode = diseqcParam.NO, diseqcpos = diseqcParam.SENDNO, orbpos = 0, longitude = 0, latitude = 0, loDirection = 0, laDirection = 0, turningSpeed = rotorParam.FAST, useInputPower=True, inputPowerDelta=50): - if orbpos is None: + def addLNBSimple(self, sec, slotid, diseqcmode, toneburstmode = diseqcParam.NO, diseqcpos = diseqcParam.SENDNO, orbpos = 0, longitude = 0, latitude = 0, loDirection = 0, laDirection = 0, turningSpeed = rotorParam.FAST, useInputPower=True, inputPowerDelta=50, fastDiSEqC = False, setVoltageTone = True): + if orbpos is None or orbpos == 3601: return #simple defaults sec.addLNB() @@ -54,10 +56,8 @@ class SecConfigure: sec.setLNBThreshold(11700000) sec.setLNBIncreasedVoltage(lnbParam.OFF) sec.setRepeats(0) - sec.setFastDiSEqC(0) + sec.setFastDiSEqC(fastDiSEqC) sec.setSeqRepeat(0) - sec.setVoltageMode(switchParam.HV) - sec.setToneMode(switchParam.HILO) sec.setCommandOrder(0) #user values @@ -69,6 +69,12 @@ class SecConfigure: if 0 <= diseqcmode < 3: self.addSatellite(sec, orbpos) + if setVoltageTone: + sec.setVoltageMode(switchParam.HV) + sec.setToneMode(switchParam.HILO) + else: + sec.setVoltageMode(switchParam._14V) + sec.setToneMode(switchParam.OFF) elif (diseqcmode == 3): # diseqc 1.2 if self.satposdepends.has_key(slotid): for slot in self.satposdepends[slotid]: @@ -153,6 +159,7 @@ class SecConfigure: for slot in nim_slots: x = slot.slot nim = slot.config + hw = HardwareInfo() if slot.isCompatible("DVB-S"): print "slot: " + str(x) + " configmode: " + str(nim.configMode.value) if nim.configMode.value in [ "loopthrough", "satposdepends", "nothing" ]: @@ -164,18 +171,25 @@ class SecConfigure: elif nim.configMode.value == "simple": #simple config print "diseqcmode: ", nim.diseqcMode.value if nim.diseqcMode.value == "single": #single - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO) + if nim.simpleSingleSendDiSEqC.value: + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA) + else: + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO) elif nim.diseqcMode.value == "toneburst_a_b": #Toneburst A/B self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.A, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO) self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.B, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO) elif nim.diseqcMode.value == "diseqc_a_b": #DiSEqC A/B - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA) - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB) + fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value + setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone) elif nim.diseqcMode.value == "diseqc_a_b_c_d": #DiSEqC A/B/C/D - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA) - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB) - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA) - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB) + fastDiSEqC = nim.simpleDiSEqCOnlyOnSatChange.value + setVoltageTone = nim.simpleDiSEqCSetVoltageTone.value + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone) elif nim.diseqcMode.value == "positioner": #Positioner if nim.latitudeOrientation.value == "north": laValue = rotorParam.NORTH @@ -185,12 +199,11 @@ class SecConfigure: loValue = rotorParam.EAST else: loValue = rotorParam.WEST - inputPowerDelta=50 + inputPowerDelta=nim.powerThreshold.value useInputPower=False turning_speed=0 if nim.powerMeasurement.value: useInputPower=True - inputPowerDelta=nim.powerThreshold.value turn_speed_dict = { "fast": rotorParam.FAST, "slow": rotorParam.SLOW } if turn_speed_dict.has_key(nim.turningSpeed.value): turning_speed = turn_speed_dict[nim.turningSpeed.value] @@ -656,7 +669,7 @@ class NimManager: def canEqualTo(self, slotid): type = self.getNimType(slotid) - if self.getNimConfig(slotid) == "DVB-S2": + if type == "DVB-S2": type = "DVB-S" nimList = self.getNimListOfType(type, slotid) for nim in nimList[:]: @@ -664,10 +677,10 @@ class NimManager: if mode.configMode.value == "loopthrough" or mode.configMode.value == "satposdepends": nimList.remove(nim) return nimList - + def canDependOn(self, slotid): type = self.getNimType(slotid) - if self.getNimConfig(slotid) == "DVB-S2": + if type == "DVB-S2": type = "DVB-S" nimList = self.getNimListOfType(type, slotid) positionerList = [] @@ -680,6 +693,13 @@ class NimManager: if lnb != 0: nimHaveRotor = True break + if not nimHaveRotor: + for sat in mode.advanced.sat.values(): + lnb_num = int(sat.lnb.value) + diseqcmode = lnb_num and mode.advanced.lnb[lnb_num].diseqcMode.value or "" + if diseqcmode == "1_2": + nimHaveRotor = True + break if nimHaveRotor: alreadyConnected = False for testnim in nimList: @@ -725,12 +745,16 @@ class NimManager: if configMode == "simple": dm = nim.diseqcMode.value if dm in ["single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]: - list.append(self.satList[nim.diseqcA.index]) + if nim.diseqcA.orbital_position != 3601: + list.append(self.satList[nim.diseqcA.index-1]) if dm in ["toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]: - list.append(self.satList[nim.diseqcB.index]) + if nim.diseqcB.orbital_position != 3601: + list.append(self.satList[nim.diseqcB.index-1]) if dm == "diseqc_a_b_c_d": - list.append(self.satList[nim.diseqcC.index]) - list.append(self.satList[nim.diseqcD.index]) + if nim.diseqcC.orbital_position != 3601: + list.append(self.satList[nim.diseqcC.index-1]) + if nim.diseqcD.orbital_position != 3601: + list.append(self.satList[nim.diseqcD.index-1]) if dm == "positioner": for x in self.satList: list.append(x) @@ -834,6 +858,14 @@ def InitSecParams(): x.addNotifier(lambda configElement: secClass.setParam(secClass.MOTOR_COMMAND_RETRIES, configElement.value)) config.sec.motor_command_retries = x + x = ConfigInteger(default=50, limits = (0, 9999)) + x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_RESET_CMD, configElement.value)) + config.sec.delay_after_diseqc_reset_cmd = x + + x = ConfigInteger(default=150, limits = (0, 9999)) + x.addNotifier(lambda configElement: secClass.setParam(secClass.DELAY_AFTER_DISEQC_PERIPHERIAL_POWERON_CMD, configElement.value)) + config.sec.delay_after_diseqc_peripherial_poweron_cmd = x + # TODO add support for satpos depending nims to advanced nim configuration # so a second/third/fourth cable from a motorized lnb can used behind a # diseqc 1.0 / diseqc 1.1 / toneburst switch @@ -842,6 +874,7 @@ def InitSecParams(): def InitNimManager(nimmgr): InitSecParams() + hw = HardwareInfo() config.Nims = ConfigSubList() for x in range(len(nimmgr.nim_slots)): @@ -883,10 +916,13 @@ def InitNimManager(nimmgr): if id != x: choices.append((str(id), nimmgr.getNimDescription(id))) nim.connectedTo = ConfigSelection(choices = choices) - nim.diseqcA = getConfigSatlist(192, nimmgr.satList) - nim.diseqcB = getConfigSatlist(130, nimmgr.satList) - nim.diseqcC = ConfigSatlist(list = nimmgr.satList) - nim.diseqcD = ConfigSatlist(list = nimmgr.satList) + nim.simpleSingleSendDiSEqC = ConfigYesNo(default=False) + nim.simpleDiSEqCSetVoltageTone = ConfigYesNo(default=True) + nim.simpleDiSEqCOnlyOnSatChange = ConfigYesNo(default=False) + nim.diseqcA = getConfigSatlist(192, [(3601, _('nothing connected'), 1)] + nimmgr.satList) + nim.diseqcB = getConfigSatlist(130, [(3601, _('nothing connected'), 1)] + nimmgr.satList) + nim.diseqcC = ConfigSatlist(list = [(3601, _('nothing connected'), 1)] + nimmgr.satList) + nim.diseqcD = ConfigSatlist(list = [(3601, _('nothing connected'), 1)] + nimmgr.satList) nim.positionerMode = ConfigSelection( choices = [ ("usals", _("USALS")), @@ -897,7 +933,7 @@ def InitNimManager(nimmgr): nim.latitude = ConfigFloat(default=[50,767], limits=[(0,359),(0,999)]) nim.latitudeOrientation = ConfigSelection(choices={"north": _("North"), "south": _("South")}, default="north") nim.powerMeasurement = ConfigYesNo(default=True) - nim.powerThreshold = ConfigInteger(default=50, limits=(0, 100)) + nim.powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100)) nim.turningSpeed = ConfigSelection(choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch")) ], default = "fast") btime = datetime(1970, 1, 1, 7, 0); nim.fastTurningBegin = ConfigDateTime(default = mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 900) @@ -972,7 +1008,7 @@ def InitNimManager(nimmgr): nim.advanced.lnb[x].latitude = ConfigFloat(default = [50,767], limits = [(0,359),(0,999)]) nim.advanced.lnb[x].latitudeOrientation = ConfigSelection(choices = [("north", _("North")), ("south", _("South"))], default = "north") nim.advanced.lnb[x].powerMeasurement = ConfigYesNo(default=True) - nim.advanced.lnb[x].powerThreshold = ConfigInteger(default=50, limits=(0, 100)) + nim.advanced.lnb[x].powerThreshold = ConfigInteger(default=hw.get_device_name() == "dm8000" and 15 or 50, limits=(0, 100)) nim.advanced.lnb[x].turningSpeed = ConfigSelection(choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch"))], default = "fast") btime = datetime(1970, 1, 1, 7, 0); nim.advanced.lnb[x].fastTurningBegin = ConfigDateTime(default=mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 600) diff --git a/lib/python/Components/Playlist.py b/lib/python/Components/Playlist.py index 744ee3af..c9ebe479 100644 --- a/lib/python/Components/Playlist.py +++ b/lib/python/Components/Playlist.py @@ -58,6 +58,7 @@ class PlaylistIOM3U(PlaylistIO): def open(self, filename): self.clear() + self.displayname = None try: file = open(filename, "r") except IOError: @@ -66,14 +67,22 @@ class PlaylistIOM3U(PlaylistIO): entry = file.readline().strip() if entry == "": break - if entry[0] != "#": + if entry.startswith("#EXTINF:"): + extinf = entry.split(',',1) + if len(extinf) > 1: + self.displayname = extinf[1] # TODO: use e2 facilities to create a service ref from file + elif entry[0] != "#": if entry[0] == "/": - self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry)) + sref = ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry) elif entry.startswith("http"): - self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry.replace(':',"%3a"))) + sref = ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry.replace(':',"%3a")) else: - self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + os.path.dirname(filename) + "/" + entry)) + sref = ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + os.path.dirname(filename) + "/" + entry) + if self.displayname: + sref.ref.setName(self.displayname) + self.displayname = None + self.addService(sref) file.close() return self.list diff --git a/lib/python/Components/TimerSanityCheck.py b/lib/python/Components/TimerSanityCheck.py index e793cdcd..031c9cae 100644 --- a/lib/python/Components/TimerSanityCheck.py +++ b/lib/python/Components/TimerSanityCheck.py @@ -1,9 +1,7 @@ -import string import NavigationInstance from time import localtime -from Components.NimManager import nimmanager from ServiceReference import ServiceReference -from enigma import iServiceInformation, eServiceCenter +from enigma import iServiceInformation, eServiceCenter, eServiceReference class TimerSanityCheck: def __init__(self, timerlist, newtimer=None): @@ -54,6 +52,7 @@ class TimerSanityCheck: # index -1 for the new Timer, 0..n index of the existing timers # count of running timers + serviceHandler = eServiceCenter.getInstance() print "checkTimerlist" # create a list with all start and end times # split it into recurring and singleshot timers @@ -149,9 +148,7 @@ class TimerSanityCheck: fakeRecList = [] ConflictTimer = None ConflictTunerType = None - ConflictSlot = None newTimerTunerType = None - newTimerTunerSlot = None cnt = 0 idx = 0 overlaplist = [] @@ -162,24 +159,45 @@ class TimerSanityCheck: else: timer = self.timerlist[event[2]] if event[1] == self.bflag: - fakeRecService = NavigationInstance.instance.recordService(timer.service_ref) - fakeRecResult = fakeRecService.start(True) - feinfo = fakeRecService.frontendInfo().getFrontendData() - tunerType = feinfo.get("tuner_type") - tunerSlot = feinfo.get("tuner_number") + tunerType = [ ] + fakeRecService = NavigationInstance.instance.recordService(timer.service_ref, True) + if fakeRecService: + fakeRecResult = fakeRecService.start(True) + else: + fakeRecResult = -1 + if not fakeRecResult: # tune okay + feinfo = fakeRecService.frontendInfo().getFrontendData() + tunerType.append(feinfo.get("tuner_type")) + else: # tune failed.. so we must go another way to get service type (DVB-S, DVB-T, DVB-C) + + def getServiceType(ref): # helper function to get a service type of a service reference + serviceInfo = serviceHandler.info(ref) + serviceInfo = serviceInfo and serviceInfo.getInfoObject(ref, iServiceInformation.sTransponderData) + if serviceInfo: + return { "Satellite" : "DVB-S", "Cable" : "DVB-C", "Terrestrial" : "DVB-T"}[serviceInfo["type"]] + + ref = timer.service_ref.ref + if ref.flags & eServiceReference.isGroup: # service group ? + serviceList = serviceHandler.list(ref) # get all alternative services + if serviceList: + for ref in serviceList.getContent("R"): # iterate over all group service references + type = getServiceType(ref) + if not type in tunerType: # just add single time + tunerType.append(type) + else: + tunerType.append(getServiceType(ref)) + if event[2] == -1: # new timer newTimerTunerType = tunerType - newTimerTunerSlot = tunerSlot - overlaplist.append((fakeRecResult, timer, tunerType, tunerSlot)) + overlaplist.append((fakeRecResult, timer, tunerType)) fakeRecList.append((timer, fakeRecService)) if fakeRecResult: if ConflictTimer is None: # just take care of the first conflict ConflictTimer = timer ConflictTunerType = tunerType - ConflictTunerSlot = tunerSlot elif event[1] == self.eflag: for fakeRec in fakeRecList: - if timer == fakeRec[0]: + if timer == fakeRec[0] and fakeRec[1]: NavigationInstance.instance.stopRecordService(fakeRec[1]) fakeRecList.remove(fakeRec) del fakeRec @@ -211,7 +229,6 @@ class TimerSanityCheck: if nt and kt: ConflictTimer = self.newtimer ConflictTunerType = newTimerTunerType - ConflictSlot = newTimerTunerSlot break self.simultimer = [ ConflictTimer ] @@ -223,8 +240,11 @@ class TimerSanityCheck: else: continue for entry in event[4]: - if not self.simultimer.count(entry[1]) and (entry[2] == ConflictTunerType or entry[3] == ConflictTunerSlot): - self.simultimer.append(entry[1]) + if not entry[1] in self.simultimer: + for x in entry[2]: + if x in ConflictTunerType: + self.simultimer.append(entry[1]) + break if len(self.simultimer) < 2: print "Bug: unknown Conflict!" diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py index 714d366d..6ed87840 100644 --- a/lib/python/Components/UsageConfig.py +++ b/lib/python/Components/UsageConfig.py @@ -1,5 +1,5 @@ from Components.Harddisk import harddiskmanager -from config import ConfigSubsection, ConfigYesNo, config, ConfigSelection, ConfigText, ConfigNumber, ConfigSet +from config import ConfigSubsection, ConfigYesNo, config, ConfigSelection, ConfigText, ConfigNumber, ConfigSet, ConfigLocations from enigma import Misc_Options, setTunerTypePriorityOrder; from SystemInfo import SystemInfo import os @@ -30,6 +30,9 @@ def InitUsageConfig(): ("standard", _("standard")), ("swap", _("swap PiP and main picture")), ("swapstop", _("move PiP to main picture")), ("stop", _("stop PiP")) ]) + config.usage.allowed_timeshift_paths = ConfigLocations(default = ["/media/hdd/"]) + config.usage.timeshift_path = ConfigText(default = "/media/hdd") + config.usage.on_movie_start = ConfigSelection(default = "ask", choices = [ ("ask", _("Ask user")), ("resume", _("Resume from last position")), ("beginning", _("Start from the beginning")) ]) config.usage.on_movie_stop = ConfigSelection(default = "ask", choices = [ diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py index b448ca6d..4d57bbb9 100644..100755 --- a/lib/python/Components/config.py +++ b/lib/python/Components/config.py @@ -34,6 +34,7 @@ class ConfigElement(object): self.save_disabled = False self.notifiers = [] self.enabled = True + self.callNotifiersOnSaveAndCancel = False # you need to override this to do input validation def setValue(self, value): @@ -66,9 +67,13 @@ class ConfigElement(object): self.saved_value = None else: self.saved_value = self.tostring(self.value) + if self.callNotifiersOnSaveAndCancel: + self.changed() def cancel(self): self.load() + if self.callNotifiersOnSaveAndCancel: + self.changed() def isChanged(self): sv = self.saved_value @@ -513,6 +518,7 @@ class ConfigIP(ConfigSequence): self.auto_jump = auto_jump def handleKey(self, key): + if key == KEY_LEFT: if self.marked_block > 0: self.marked_block -= 1 @@ -531,8 +537,14 @@ class ConfigIP(ConfigSequence): self.marked_block = len(self.limits)-1 self.overwrite = True - if key in KEY_NUMBERS: - number = getKeyNumber(key) + if key in KEY_NUMBERS or key == KEY_ASCII: + if key == KEY_ASCII: + code = getPrevAsciiCode() + if code < 48 or code > 57: + return + number = code - 48 + else: + number = getKeyNumber(key) oldvalue = self._value[self.marked_block] if self.overwrite: @@ -770,12 +782,12 @@ class ConfigText(ConfigElement, NumericalTextInput): def getValue(self): return self.text.encode("utf-8") - + def setValue(self, val): try: self.text = val.decode("utf-8") except UnicodeDecodeError: - self.text = val + self.text = val.decode("utf-8", "ignore") print "Broken UTF8!" value = property(getValue, setValue) diff --git a/lib/python/Plugins/DemoPlugins/TestPlugin/Makefile.am b/lib/python/Plugins/DemoPlugins/TestPlugin/Makefile.am index 8173b373..2c52330f 100644 --- a/lib/python/Plugins/DemoPlugins/TestPlugin/Makefile.am +++ b/lib/python/Plugins/DemoPlugins/TestPlugin/Makefile.am @@ -4,3 +4,4 @@ install_PYTHON = \ __init__.py \ plugin.py +install_DATA = maintainer.info diff --git a/lib/python/Plugins/DemoPlugins/TestPlugin/maintainer.info b/lib/python/Plugins/DemoPlugins/TestPlugin/maintainer.info new file mode 100644 index 00000000..4f285613 --- /dev/null +++ b/lib/python/Plugins/DemoPlugins/TestPlugin/maintainer.info @@ -0,0 +1,2 @@ +tmbinc@elitedvb.net +Demo-Plugin diff --git a/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py b/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py index 1f49a9e3..a63562c8 100644 --- a/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py +++ b/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py @@ -50,6 +50,8 @@ class Test(Screen): def mycallback(self, answer): print "answer:", answer + if answer: + raise "test-crash" self.close() def keyLeft(self): diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py b/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py index 8d02cb22..112a221e 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py @@ -1,5 +1,5 @@ from Tools.Directories import fileExists -from Components.config import config, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence +from Components.config import config, ConfigSubsection, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence class ConfigColor(ConfigSequence): def __init__(self): @@ -32,6 +32,7 @@ class DVDProject: self.settings = ConfigSubsection() self.settings.name = ConfigText(fixed_size = False, visible_width = 40) self.settings.authormode = ConfigSelection(choices = [("menu_linked", _("Linked titles with a DVD menu")), ("just_linked", _("Direct playback of linked titles without menu")), ("menu_seperate", _("Seperate titles with a main menu")), ("data_ts", _("Dreambox format data DVD (HDTV compatible)"))]) + self.settings.titlesetmode = ConfigSelection(choices = [("single", _("Simple titleset (compatibility for legacy players)")), ("multi", _("Complex (allows mixing audio tracks and aspects)"))], default="multi") self.settings.output = ConfigSelection(choices = [("iso", _("Create DVD-ISO")), ("dvd", _("Burn DVD"))]) self.settings.isopath = ConfigText(fixed_size = False, visible_width = 40) self.settings.dataformat = ConfigSelection(choices = [("iso9660_1", ("ISO9660 Level 1")), ("iso9660_4", ("ISO9660 version 2")), ("udf", ("UDF"))]) @@ -46,7 +47,6 @@ class DVDProject: self.settings.font_size = ConfigPixelvals() self.settings.space = ConfigPixelvals() self.settings.vmgm = ConfigFilename() - self.settings.autochapter = ConfigInteger(default = 0, limits = (0, 99)) self.filekeys = ["vmgm", "menubg", "menuaudio", "font_face", "isopath"] def addService(self, service): diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py b/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py index 1bfb3d64..b1c627aa 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py @@ -1,17 +1,32 @@ +from Components.config import config, ConfigSubsection, ConfigSubList, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence, ConfigYesNo + +class ConfigFixedText(ConfigText): + def __init__(self, text, visible_width=60): + ConfigText.__init__(self, default = text, fixed_size = True, visible_width = visible_width) + def handleKey(self, key): + pass + class DVDTitle: def __init__(self): + self.properties = ConfigSubsection() + self.properties.menutitle = ConfigText(fixed_size = False, visible_width = 80) + self.properties.menusubtitle = ConfigText(fixed_size = False, visible_width = 80) + self.DVBname = _("Title") + self.DVBdescr = _("Description") + self.DVBchannel = _("Channel") + self.properties.aspect = ConfigSelection(choices = [("4:3", _("4:3")), ("16:9", _("16:9"))]) + self.properties.widescreen = ConfigSelection(choices = [("nopanscan", "nopanscan"), ("noletterbox", "noletterbox")]) + self.properties.autochapter = ConfigInteger(default = 0, limits = (0, 60)) + self.properties.audiotracks = ConfigSubList() self.cuesheet = [ ] self.source = None - self.name = "" - self.descr = "" self.filesize = 0 self.estimatedDiskspace = 0 self.inputfile = "" self.cutlist = [ ] self.chaptermarks = [ ] - self.audiotracks = [ ] self.timeCreate = None - self.sVideoType = -1 + self.VideoType = -1 def addService(self, service): from os import path @@ -21,18 +36,61 @@ class DVDTitle: self.source = service serviceHandler = eServiceCenter.getInstance() info = serviceHandler.info(service) - self.descr = info and " " + info.getInfoString(service, iServiceInformation.sDescription) or "" + sDescr = info and " " + info.getInfoString(service, iServiceInformation.sDescription) or "" + self.DVBdescr = sDescr sTimeCreate = info.getInfo(service, iServiceInformation.sTimeCreate) if sTimeCreate > 1: self.timeCreate = localtime(sTimeCreate) serviceref = ServiceReference(info.getInfoString(service, iServiceInformation.sServiceref)) - self.name = info and info.getName(service) or "Title" + t.descr - self.channel = serviceref.getServiceName() + name = info and info.getName(service) or "Title" + sDescr + self.DVBname = name + self.DVBchannel = serviceref.getServiceName() self.inputfile = service.getPath() self.filesize = path.getsize(self.inputfile) self.estimatedDiskspace = self.filesize self.length = info.getLength(service) + def initDVDmenuText(self, project, track): + self.properties.menutitle.setValue(self.formatDVDmenuText(project.settings.titleformat.getValue(), track)) + self.properties.menusubtitle.setValue(self.formatDVDmenuText(project.settings.subtitleformat.getValue(), track)) + + def formatDVDmenuText(self, template, track): + properties = self.properties + template = template.replace("$i", str(track)) + template = template.replace("$t", self.DVBname) + template = template.replace("$d", self.DVBdescr) + template = template.replace("$c", str(len(self.chaptermarks)+1)) + template = template.replace("$f", self.inputfile) + template = template.replace("$C", self.DVBchannel) + + #if template.find("$A") >= 0: + from TitleProperties import languageChoices + audiolist = [ ] + for audiotrack in self.properties.audiotracks: + active = audiotrack.active.getValue() + if active: + trackstring = audiotrack.format.getValue() + language = audiotrack.language.getValue() + if languageChoices.langdict.has_key(language): + trackstring += ' (' + languageChoices.langdict[language] + ')' + audiolist.append(trackstring) + audiostring = ', '.join(audiolist) + template = template.replace("$A", audiostring) + + if template.find("$l") >= 0: + l = self.length + lengthstring = "%d:%02d:%02d" % (l/3600, l%3600/60, l%60) + template = template.replace("$l", lengthstring) + if self.timeCreate: + template = template.replace("$Y", str(self.timeCreate[0])) + template = template.replace("$M", str(self.timeCreate[1])) + template = template.replace("$D", str(self.timeCreate[2])) + timestring = "%d:%02d" % (self.timeCreate[3], self.timeCreate[4]) + template = template.replace("$T", timestring) + else: + template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "") + return template + def produceFinalCuesheet(self): CUT_TYPE_IN = 0 CUT_TYPE_OUT = 1 @@ -78,9 +136,21 @@ class DVDTitle: self.estimatedDiskspace = usedsize self.length = accumulated_in / 90000 - def produceAutoChapter(self, minutes): - if len(self.chaptermarks) < 1: - chapterpts = self.cutlist[0] - while chapterpts < self.length*90000: + def getChapterMarks(self, template="$h:$m:$s.$t"): + timestamps = [ ] + chapters = [ ] + minutes = self.properties.autochapter.getValue() + if len(self.chaptermarks) < 1 and minutes > 0: + chapterpts = 0 + while chapterpts < (self.length-60*minutes)*90000: chapterpts += 90000 * 60 * minutes - self.chaptermarks.append(chapterpts) + chapters.append(chapterpts) + else: + chapters = self.chaptermarks + for p in chapters: + timestring = template.replace("$h", str(p / (90000 * 3600))) + timestring = timestring.replace("$m", ("%02d" % (p % (90000 * 3600) / (90000 * 60)))) + timestring = timestring.replace("$s", ("%02d" % (p % (90000 * 60) / 90000))) + timestring = timestring.replace("$t", ("%03d" % ((p % 90000) / 90))) + timestamps.append(timestring) + return timestamps
\ No newline at end of file diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py index d4e6a375..836c9fbd 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py @@ -9,6 +9,7 @@ from Components.Task import Task, Job, job_manager, Condition from Components.ScrollLabel import ScrollLabel from Components.Harddisk import harddiskmanager from Components.Console import Console +from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier class DVDToolbox(Screen): skin = """ @@ -54,6 +55,7 @@ class DVDToolbox(Screen): "pageDown": self.pageDown }) self.update() + hotplugNotifier.append(self.update) def pageUp(self): self["details"].pageUp() @@ -61,7 +63,7 @@ class DVDToolbox(Screen): def pageDown(self): self["details"].pageDown() - def update(self): + def update(self, dev="", media_state=""): self["space_label"].text = _("Please wait... Loading list...") self["info"].text = "" self["details"].setText("") @@ -141,6 +143,7 @@ class DVDToolbox(Screen): def exit(self): del self.Console + hotplugNotifier.remove(self.update) self.close() class DVDformatJob(Job): diff --git a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml index d9831e63..7d8de8ce 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml +++ b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml @@ -3,8 +3,9 @@ <settings name="Dreambox DVD record" authormode="menu_linked" + titlesetmode="multi" titleformat="$i. $t" - subtitleformat="$D.$M.$Y, $T $C, $d ($c chapters)" + subtitleformat="$D.$M.$Y, $T $C, $d" vmgm="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/vmgmdream.mpg" menubg="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/dreamdvd_boat.jpg" menuaudio="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/silence.mp2" diff --git a/lib/python/Plugins/Extensions/DVDBurn/Makefile.am b/lib/python/Plugins/Extensions/DVDBurn/Makefile.am index cb65f56a..be89ebaa 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Makefile.am +++ b/lib/python/Plugins/Extensions/DVDBurn/Makefile.am @@ -3,7 +3,7 @@ installdir = $(LIBDIR)/enigma2/python/Plugins/Extensions/DVDBurn install_PYTHON = \ __init__.py \ plugin.py \ - DVDProject.py DVDTitle.py TitleCutter.py TitleList.py Process.py ProjectSettings.py DVDToolbox.py + DVDProject.py DVDTitle.py TitleCutter.py TitleList.py TitleProperties.py Process.py ProjectSettings.py DVDToolbox.py install_DATA = *.xml *.jpg *.mpg *.mp2 *.png diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 49054596..89ca90fd 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -85,23 +85,34 @@ class DemuxTask(Task): title = job.project.titles[job.i] self.global_preconditions.append(DiskspacePrecondition(title.estimatedDiskspace)) self.setTool("/usr/bin/projectx") - self.generated_files = [ ] + self.args += [inputfile, "-demux", "-out", self.job.workspace ] self.end = 300 self.prog_state = 0 self.weighting = 1000 self.cutfile = self.job.workspace + "/cut_%d.Xcl" % (job.i+1) self.cutlist = title.cutlist - self.args += [inputfile, "-demux", "-out", self.job.workspace ] + self.currentPID = None + self.relevantAudioPIDs = [ ] + self.getRelevantAudioPIDs(title) + self.generated_files = [ ] + self.mplex_streamfiles = [ ] if len(self.cutlist) > 1: self.args += [ "-cut", self.cutfile ] def prepare(self): self.writeCutfile() + def getRelevantAudioPIDs(self, title): + for audiotrack in title.properties.audiotracks: + if audiotrack.active.getValue(): + self.relevantAudioPIDs.append(audiotrack.pid.getValue()) + def processOutputLine(self, line): line = line[:-1] MSG_NEW_FILE = "---> new File: " MSG_PROGRESS = "[PROGRESS] " + MSG_NEW_MP2 = "--> MPEG Audio (0x" + MSG_NEW_AC3 = "--> AC-3/DTS Audio on PID " if line.startswith(MSG_NEW_FILE): file = line[len(MSG_NEW_FILE):] @@ -111,10 +122,14 @@ class DemuxTask(Task): elif line.startswith(MSG_PROGRESS): progress = line[len(MSG_PROGRESS):] self.haveProgress(progress) + elif line.startswith(MSG_NEW_MP2) or line.startswith(MSG_NEW_AC3): + self.currentPID = str(int(line.rstrip()[-6:].rsplit('0x',1)[-1],16)) def haveNewFile(self, file): - print "PRODUCED FILE [%s]" % file + print "[DemuxTask] produced file:", file, self.currentPID self.generated_files.append(file) + if self.currentPID in self.relevantAudioPIDs or file.endswith("m2v"): + self.mplex_streamfiles.append(file) def haveProgress(self, progress): #print "PROGRESS [%s]" % progress @@ -131,7 +146,6 @@ class DemuxTask(Task): if p > self.progress: self.progress = p except ValueError: - print "val error" pass def writeCutfile(self): @@ -151,8 +165,8 @@ class DemuxTask(Task): def cleanup(self, failed): if failed: import os - for f in self.generated_files: - os.remove(f) + for file in self.generated_files.itervalues(): + os.remove(file) class MplexTaskPostcondition(Condition): def check(self, task): @@ -185,9 +199,9 @@ class MplexTask(Task): # we don't want the ReturncodePostcondition in this case because for right now we're just gonna ignore the fact that mplex fails with a buffer underrun error on some streams (this always at the very end) def prepare(self): - self.error = None + self.error = None if self.demux_task: - self.args += self.demux_task.generated_files + self.args += self.demux_task.mplex_streamfiles def processOutputLine(self, line): print "[MplexTask] ", line[:-1] @@ -206,7 +220,7 @@ class RemoveESFiles(Task): def prepare(self): self.args += ["-f"] - self.args += self.demux_task.generated_files + self.args += self.demux_task.generated_files.values() self.args += [self.demux_task.cutfile] class DVDAuthorTask(Task): @@ -411,27 +425,6 @@ class PreviewTaskPostcondition(Condition): def getErrorMessage(self, task): return "Cancel" -def formatTitle(template, title, track): - template = template.replace("$i", str(track)) - template = template.replace("$t", title.name) - template = template.replace("$d", title.descr) - template = template.replace("$c", str(len(title.chaptermarks)+1)) - template = template.replace("$A", str(title.audiotracks)) - template = template.replace("$f", title.inputfile) - template = template.replace("$C", title.channel) - l = title.length - lengthstring = "%d:%02d:%02d" % (l/3600, l%3600/60, l%60) - template = template.replace("$l", lengthstring) - if title.timeCreate: - template = template.replace("$Y", str(title.timeCreate[0])) - template = template.replace("$M", str(title.timeCreate[1])) - template = template.replace("$D", str(title.timeCreate[2])) - timestring = "%d:%02d" % (title.timeCreate[3], title.timeCreate[4]) - template = template.replace("$T", timestring) - else: - template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "") - return template.decode("utf-8") - class ImagingPostcondition(Condition): def check(self, task): return task.returncode == 0 @@ -518,14 +511,13 @@ class MenuImageTask(Task): menu_end_title = nr_titles+1 menu_i = 0 for title_no in range( menu_start_title , menu_end_title ): - i = title_no-1 - top = s_top + ( menu_i * rowheight ) menu_i += 1 - title = self.job.project.titles[i] - titleText = formatTitle(s.titleformat.getValue(), title, title_no) + title = self.job.project.titles[title_no-1] + top = s_top + ( menu_i * rowheight ) + titleText = title.formatDVDmenuText(s.titleformat.getValue(), title_no).decode("utf-8") draw_bg.text((s_left,top), titleText, fill=self.Menus.color_button, font=fonts[1]) draw_high.text((s_left,top), titleText, fill=1, font=self.Menus.fonts[1]) - subtitleText = formatTitle(s.subtitleformat.getValue(), title, title_no) + subtitleText = title.formatDVDmenuText(s.subtitleformat.getValue(), title_no).decode("utf-8") draw_bg.text((s_left,top+36), subtitleText, fill=self.Menus.color_button, font=fonts[2]) bottom = top+rowheight if bottom > self.Menus.imgheight: @@ -607,7 +599,7 @@ class Menus: menuoutputfilename = job.workspace+"/dvdmenu"+num+".mpg" spumuxTask(job, spuxmlfilename, menubgmpgfilename, menuoutputfilename) -def CreateAuthoringXML(job): +def CreateAuthoringXML_singleset(job): nr_titles = len(job.project.titles) mode = job.project.settings.authormode.getValue() authorxml = [] @@ -649,9 +641,7 @@ def CreateAuthoringXML(job): authorxml.append(' </menus>\n') authorxml.append(' <titles>\n') for i in range( nr_titles ): - #for audiotrack in job.project.titles[i].audiotracks: - #authorxml.append(' <audio lang="'+audiotrack[0][:2]+'" format="'+audiotrack[1]+'" />\n') - chapters = ','.join(["%d:%02d:%02d.%03d" % (p / (90000 * 3600), p % (90000 * 3600) / (90000 * 60), p % (90000 * 60) / 90000, (p % 90000) / 90) for p in job.project.titles[i].chaptermarks]) + chapters = ','.join(job.project.titles[i].getChapterMarks()) title_no = i+1 title_filename = job.workspace + "/dvd_title_%d.mpg" % (title_no) if job.menupreview: @@ -677,6 +667,84 @@ def CreateAuthoringXML(job): f.write(x) f.close() +def CreateAuthoringXML_multiset(job): + nr_titles = len(job.project.titles) + mode = job.project.settings.authormode.getValue() + authorxml = [] + authorxml.append('<?xml version="1.0" encoding="utf-8"?>\n') + authorxml.append(' <dvdauthor dest="' + (job.workspace+"/dvd") + '" jumppad="yes">\n') + authorxml.append(' <vmgm>\n') + authorxml.append(' <menus>\n') + authorxml.append(' <video aspect="4:3"/>\n') + if mode.startswith("menu"): + for menu_count in range(1 , job.nr_menus+1): + authorxml.append(' <pgc>\n') + menu_start_title = (menu_count-1)*job.titles_per_menu + 1 + menu_end_title = (menu_count)*job.titles_per_menu + 1 + if menu_end_title > nr_titles: + menu_end_title = nr_titles+1 + for i in range( menu_start_title , menu_end_title ): + authorxml.append(' <button name="button' + (str(i).zfill(2)) + '"> jump titleset ' + str(i) +' title 1; </button>\n') + if menu_count > 1: + authorxml.append(' <button name="button_prev"> jump menu ' + str(menu_count-1) + '; </button>\n') + if menu_count < job.nr_menus: + authorxml.append(' <button name="button_next"> jump menu ' + str(menu_count+1) + '; </button>\n') + menuoutputfilename = job.workspace+"/dvdmenu"+str(menu_count)+".mpg" + authorxml.append(' <vob file="' + menuoutputfilename + '" pause="inf"/>\n') + authorxml.append(' </pgc>\n') + else: + authorxml.append(' <pgc>\n') + authorxml.append(' <vob file="' + job.project.settings.vmgm.getValue() + '" />\n' ) + authorxml.append(' <post> jump titleset 1 title 1; </post>\n') + authorxml.append(' </pgc>\n') + authorxml.append(' </menus>\n') + authorxml.append(' </vmgm>\n') + + for i in range( nr_titles ): + title = job.project.titles[i] + authorxml.append(' <titleset>\n') + authorxml.append(' <titles>\n') + for audiotrack in title.properties.audiotracks: + active = audiotrack.active.getValue() + if active: + format = audiotrack.format.getValue() + language = audiotrack.language.getValue() + audio_tag = ' <audio format="%s"' % format + if language != "nolang": + audio_tag += ' lang="%s"' % language + audio_tag += ' />\n' + authorxml.append(audio_tag) + aspect = title.properties.aspect.getValue() + video_tag = ' <video aspect="'+aspect+'"' + if title.properties.widescreen.getValue() == "4:3": + video_tag += ' widescreen="'+title.properties.widescreen.getValue()+'"' + video_tag += ' />\n' + authorxml.append(video_tag) + chapters = ','.join(title.getChapterMarks()) + title_no = i+1 + title_filename = job.workspace + "/dvd_title_%d.mpg" % (title_no) + if job.menupreview: + LinkTS(job, job.project.settings.vmgm.getValue(), title_filename) + else: + MakeFifoNode(job, title_no) + if mode.endswith("linked") and title_no < nr_titles: + post_tag = "jump titleset %d title 1;" % ( title_no+1 ) + elif mode.startswith("menu"): + post_tag = "call vmgm menu 1;" + else: post_tag = "" + + authorxml.append(' <pgc>\n') + authorxml.append(' <vob file="' + title_filename + '" chapters="' + chapters + '" />\n') + authorxml.append(' <post> ' + post_tag + ' </post>\n') + authorxml.append(' </pgc>\n') + authorxml.append(' </titles>\n') + authorxml.append(' </titleset>\n') + authorxml.append(' </dvdauthor>\n') + f = open(job.workspace+"/dvdauthor.xml", "w") + for x in authorxml: + f.write(x) + f.close() + def getISOfilename(isopath, volName): from Tools.Directories import fileExists i = 0 @@ -703,7 +771,10 @@ class DVDJob(Job): CheckDiskspaceTask(self) if self.project.settings.authormode.getValue().startswith("menu") or self.menupreview: Menus(self) - CreateAuthoringXML(self) + if self.project.settings.titlesetmode.getValue() == "multi": + CreateAuthoringXML_multiset(self) + else: + CreateAuthoringXML_singleset(self) DVDAuthorTask(self) @@ -713,14 +784,14 @@ class DVDJob(Job): PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/") else: for self.i in range(nr_titles): - title = self.project.titles[self.i] + self.title = self.project.titles[self.i] link_name = self.workspace + "/source_title_%d.ts" % (self.i+1) title_filename = self.workspace + "/dvd_title_%d.mpg" % (self.i+1) - LinkTS(self, title.inputfile, link_name) + LinkTS(self, self.title.inputfile, link_name) demux = DemuxTask(self, link_name) self.mplextask = MplexTask(self, outputfile=title_filename, demux_task=demux) self.mplextask.end = self.estimateddvdsize - RemoveESFiles(self, demux) + #RemoveESFiles(self, demux) WaitForResidentTasks(self) PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/") output = self.project.settings.output.getValue() diff --git a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py index 7491e046..b77383cf 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py +++ b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py @@ -148,8 +148,9 @@ class ProjectSettings(Screen,ConfigListScreen): self.list.append(getConfigListEntry(_("Menu")+' '+_("spaces (top, between rows, left)"), self.settings.space)) self.list.append(getConfigListEntry(_("Menu")+' '+_("Audio"), self.settings.menuaudio)) if authormode != "data_ts": - self.list.append(getConfigListEntry(_("VMGM (intro trailer)"), self.settings.vmgm)) - self.list.append(getConfigListEntry(_("Auto chapter split every ? minutes (0=never)"), self.settings.autochapter)) + self.list.append(getConfigListEntry(_("Titleset mode"), self.settings.titlesetmode)) + if self.settings.titlesetmode.getValue() == "single" or authormode == "just_linked": + self.list.append(getConfigListEntry(_("VMGM (intro trailer)"), self.settings.vmgm)) else: self.list.append(getConfigListEntry(("DVD data format"), self.settings.dataformat)) @@ -158,13 +159,13 @@ class ProjectSettings(Screen,ConfigListScreen): def keyLeft(self): ConfigListScreen.keyLeft(self) key = self.keydict[self["config"].getCurrent()[1]] - if key == "authormode" or key == "output": + if key == "authormode" or key == "output" or key=="titlesetmode": self.initConfigList() def keyRight(self): ConfigListScreen.keyRight(self) key = self.keydict[self["config"].getCurrent()[1]] - if key == "authormode" or key == "output": + if key == "authormode" or key == "output" or key=="titlesetmode": self.initConfigList() def exit(self): diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py b/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py index 163269c7..210a3d58 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py @@ -20,16 +20,31 @@ class TitleCutter(CutListEditor): audio = service and service.audioTracks() n = audio and audio.getNumberOfTracks() or 0 if n > 0: + from DVDTitle import ConfigFixedText + from TitleProperties import languageChoices + from Components.config import config, ConfigSubsection, ConfigSubList, ConfigSelection, ConfigYesNo + self.t.properties.audiotracks = ConfigSubList() for x in range(n): i = audio.getTrackInfo(x) - language = i.getLanguage() + DVB_lang = i.getLanguage() description = i.getDescription() + pid = str(i.getPID()) if description == "MPEG": description = "MP2" - self.t.audiotracks.append((language, description)) - print "[DVDBurn getAudioTracks]", self.t.audiotracks - self.t.sVideoType = service.info().getInfo(iServiceInformation.sVideoType) - print "[DVDBurn getVideoType]", self.t.sVideoType + print "[audiotrack] pid:", pid, "description:", description, "language:", DVB_lang + self.t.properties.audiotracks.append(ConfigSubsection()) + self.t.properties.audiotracks[-1].active = ConfigYesNo(default = True) + self.t.properties.audiotracks[-1].format = ConfigFixedText(description) + self.t.properties.audiotracks[-1].language = ConfigSelection(choices = languageChoices.choices, default=languageChoices.getLanguage(DVB_lang)) + self.t.properties.audiotracks[-1].pid = ConfigFixedText(pid) + self.t.properties.audiotracks[-1].DVB_lang = ConfigFixedText(DVB_lang) + sAspect = service.info().getInfo(iServiceInformation.sAspect) + if sAspect in ( 1, 2, 5, 6, 9, 0xA, 0xD, 0xE ): + aspect = "4:3" + else: + aspect = "16:9" + self.t.properties.aspect.setValue(aspect) + self.t.VideoType = service.info().getInfo(iServiceInformation.sVideoType) def exit(self): self.session.nav.stopService() diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py index 19380af4..345af877 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py @@ -1,4 +1,4 @@ -import DVDProject, TitleList, TitleCutter, ProjectSettings, DVDToolbox, Process +import DVDProject, TitleList, TitleCutter, TitleProperties, ProjectSettings, DVDToolbox, Process from Screens.Screen import Screen from Screens.ChoiceBox import ChoiceBox from Screens.InputBox import InputBox @@ -41,7 +41,7 @@ class TitleList(Screen, HelpableScreen): self["titleactions"] = HelpableActionMap(self, "DVDTitleList", { "addTitle": (self.addTitle, _("Add a new title"), _("Add title")), - "editTitle": (self.editTitle, _("Edit chapters of current title"), _("Edit title")), + "titleProperties": (self.titleProperties, _("Properties of current title"), _("Title properties")), "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")), "settings": (self.settings, _("Collection settings"), _("Settings")), "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")), @@ -59,7 +59,7 @@ class TitleList(Screen, HelpableScreen): self["key_red"] = StaticText(_("Remove title")) self["key_green"] = StaticText(_("Add title")) - self["key_yellow"] = StaticText(_("Edit title")) + self["key_yellow"] = StaticText(_("Title properties")) self["key_blue"] = StaticText(_("Settings")) self["title_label"] = StaticText() @@ -78,40 +78,31 @@ class TitleList(Screen, HelpableScreen): def showMenu(self): menu = [] if self.project.settings.output.getValue() == "dvd": - menu.append((_("Burn DVD"), "burn")); + menu.append((_("Burn DVD"), self.burnProject)) elif self.project.settings.output.getValue() == "iso": - menu.append((_("Create DVD-ISO"), "burn")); - menu.append((_("Preview menu"), "previewMenu")); - menu.append((_("DVD media toolbox"), "toolbox")); - menu.append((_("Collection settings"), "settings")); - menu.append((_("Add a new title"), "addtitle")); - menu.append((_("Remove title"), "removetitle")); - menu.append((_("Edit chapters of current title"), "edittitle")); - menu.append((_("Burn existing image to DVD"), "burniso")); - menu.append((_("Exit"), "exit")); + menu.append((_("Create DVD-ISO"), self.burnProject)) + menu.append((_("Burn existing image to DVD"), self.selectImage)) + menu.append((_("DVD media toolbox"), self.toolbox)) + menu.append((_("Preview menu"), self.previewMenu)) + menu.append((_("Collection settings"), self.settings)) + menu.append((_("Reset and renumerate title names"), self.resetTitles)) + menu.append((_("Edit chapters of current title"), self.editTitle)) + menu.append((_("Properties of current title"), self.titleProperties)) + menu.append((_("Add a new title"), self.addTitle)) + menu.append((_("Remove title"), self.removeCurrentTitle)) + menu.append((_("Exit"), self.leave)) self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu) def menuCallback(self, choice): - if choice is None: - return - if choice[1] == "removetitle": - self.removeCurrentTitle() - elif choice[1] == "addtitle": - self.addTitle() - elif choice[1] == "edittitle": - self.editTitle() - elif choice[1] == "toolbox": - self.toolbox() - elif choice[1] == "settings": - self.settings() - elif choice[1] == "previewMenu": - self.previewMenu() - elif choice[1] == "burn": - self.burnProject() - elif choice[1] == "burniso": - self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings) - elif choice[1] == "exit": - self.leave() + if choice: + choice[1]() + + def titleProperties(self): + if self.getCurrentTitle(): + self.session.openWithCallback(self.updateTitleList, TitleProperties.TitleProperties, self, self.project, self["titles"].getIndex()) + + def selectImage(self): + self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings) def newProject(self): self.project = DVDProject.DVDProject() @@ -197,10 +188,6 @@ class TitleList(Screen, HelpableScreen): job_manager.in_background = False self.session.openWithCallback(self.JobViewCB, JobView, job) else: - autochapter = self.project.settings.autochapter.getValue() - if autochapter > 0: - for title in self.project.titles: - title.produceAutoChapter(autochapter) job = Process.DVDJob(self.project) job_manager.AddJob(job) job_manager.in_background = False @@ -225,7 +212,7 @@ class TitleList(Screen, HelpableScreen): res = [ ] totalsize = 0 for title in self.project.titles: - a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.name) ] + a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue()) ] res.append(a) totalsize += title.estimatedDiskspace self["titles"].list = res @@ -263,13 +250,21 @@ class TitleList(Screen, HelpableScreen): def titleEditDone(self, cutlist): t = self.current_edit_title + t.initDVDmenuText(self.project,len(self.project.titles)) t.cuesheet = cutlist t.produceFinalCuesheet() - if t.sVideoType != 0: + if t.VideoType != 0: self.session.openWithCallback(self.DVDformatCB,MessageBox,text = _("The DVD standard doesn't support H.264 (HDTV) video streams. Do you want to create a Dreambox format data DVD (which will not play in stand-alone DVD players) instead?"), type = MessageBox.TYPE_YESNO) else: self.updateTitleList() + def resetTitles(self): + count = 0 + for title in self.project.titles: + count += 1 + title.initDVDmenuText(self.project,count) + self.updateTitleList() + def DVDformatCB(self, answer): t = self.current_edit_title if answer == True: diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py new file mode 100644 index 00000000..d5ba6c16 --- /dev/null +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py @@ -0,0 +1,169 @@ +from Screens.Screen import Screen +from Screens.ChoiceBox import ChoiceBox +from Screens.InputBox import InputBox +from Screens.MessageBox import MessageBox +from Screens.HelpMenu import HelpableScreen +from Components.ActionMap import HelpableActionMap, ActionMap +from Components.Sources.List import List +from Components.Sources.StaticText import StaticText +from Components.Sources.Progress import Progress +from Components.FileList import FileList +from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT +from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS, SCOPE_HDD +from Components.config import config, getConfigListEntry, ConfigInteger, ConfigSubsection, ConfigSelection +from Components.ConfigList import ConfigListScreen +import DVDTitle + +class TitleProperties(Screen,ConfigListScreen): + skin = """ + <screen position="90,83" size="560,445" title="Properties of current title" > + <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" /> + <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> + <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" /> + <widget name="config" position="10,50" size="540,300" scrollbarMode="showOnDemand" /> + <widget source="serviceinfo_headline" render="Label" position="20,360" size="520,20" font="Regular;20" /> + <widget source="serviceinfo" render="Label" position="20,382" size="520,66" font="Regular;16" /> + </screen>""" + + def __init__(self, session, parent, project, title_idx): + Screen.__init__(self, session) + self.parent = parent + self.project = project + self.title_idx = title_idx + + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("OK")) + self["key_blue"] = StaticText(_("Edit Title")) + self["serviceinfo_headline"] = StaticText("DVB info:") + self["serviceinfo"] = StaticText() + + self.properties = project.titles[title_idx].properties + ConfigListScreen.__init__(self, []) + self.properties.crop = DVDTitle.ConfigFixedText("crop") + self.properties.autochapter.addNotifier(self.initConfigList) + self.properties.aspect.addNotifier(self.initConfigList) + for audiotrack in self.properties.audiotracks: + audiotrack.active.addNotifier(self.initConfigList) + + self.initConfigList() + + self["setupActions"] = ActionMap(["SetupActions", "ColorActions"], + { + "green": self.exit, + "red": self.cancel, + "blue": self.editTitle, + "cancel": self.cancel, + "ok": self.ok, + }, -2) + + def initConfigList(self, element=None): + try: + self.properties.position = ConfigInteger(default = self.title_idx+1, limits = (1, len(self.project.titles))) + title = self.project.titles[self.title_idx] + self.list = [] + self.list.append(getConfigListEntry("DVD " + _("Track"), self.properties.position)) + self.list.append(getConfigListEntry("DVD " + _("Title"), self.properties.menutitle)) + self.list.append(getConfigListEntry("DVD " + _("Description"), self.properties.menusubtitle)) + for audiotrack in self.properties.audiotracks: + DVB_aud = audiotrack.DVB_lang.getValue() or audiotrack.pid.getValue() + self.list.append(getConfigListEntry(_("burn audio track (%s)") % DVB_aud, audiotrack.active)) + if audiotrack.active.getValue(): + self.list.append(getConfigListEntry(_("audio track (%s) format") % DVB_aud, audiotrack.format)) + self.list.append(getConfigListEntry(_("audio track (%s) language") % DVB_aud, audiotrack.language)) + + self.list.append(getConfigListEntry("DVD " + _("Aspect Ratio"), self.properties.aspect)) + if self.properties.aspect.getValue() == "16:9": + self.list.append(getConfigListEntry("DVD " + "widescreen", self.properties.widescreen)) + else: + self.list.append(getConfigListEntry("DVD " + "widescreen", self.properties.crop)) + + infotext = _("Available format variables") + ":\n$i=" + _("Track") + ", $t=" + _("Title") + ", $d=" + _("Description") + ", $l=" + _("length") + ", $c=" + _("chapters") + ",\n" + _("Record") + " $T=" + _("Begin time") + ", $Y=" + _("year") + ", $M=" + _("month") + ", $D=" + _("day") + ",\n$A=" + _("audio tracks") + ", $C=" + _("Channel") + ", $f=" + _("filename") + self["info"] = StaticText(infotext) + + if len(title.chaptermarks) == 0: + self.list.append(getConfigListEntry(_("Auto chapter split every ? minutes (0=never)"), self.properties.autochapter)) + infotext = _("Title") + ': ' + title.DVBname + "\n" + _("Description") + ': ' + title.DVBdescr + "\n" + _("Channel") + ': ' + title.DVBchannel + chaptermarks = title.getChapterMarks(template="$h:$m:$s") + chapters_count = len(chaptermarks) + if chapters_count >= 1: + infotext += ', ' + str(chapters_count+1) + ' ' + _("chapters") + ' (' + infotext += ' / '.join(chaptermarks) + ')' + self["serviceinfo"].setText(infotext) + self["config"].setList(self.list) + except AttributeError: + pass + + def editTitle(self): + self.parent.editTitle() + self.initConfigList() + + def changedConfigList(self): + self.initConfigList() + + def exit(self): + self.applySettings() + self.close() + + def applySettings(self): + for x in self["config"].list: + x[1].save() + current_pos = self.title_idx+1 + new_pos = self.properties.position.getValue() + if new_pos != current_pos: + print "title got repositioned from ", current_pos, "to", new_pos + swaptitle = self.project.titles.pop(current_pos-1) + self.project.titles.insert(new_pos-1, swaptitle) + + def ok(self): + #key = self.keydict[self["config"].getCurrent()[1]] + #if key in self.project.filekeys: + #self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, key, self.settings) + pass + + def cancel(self): + self.close() + +from Tools.ISO639 import LanguageCodes +class LanguageChoices(): + def __init__(self): + from Components.Language import language as syslanguage + syslang = syslanguage.getLanguage()[:2] + self.langdict = { } + self.choices = [] + for key, val in LanguageCodes.iteritems(): + if len(key) == 2: + self.langdict[key] = val[0] + for key, val in self.langdict.iteritems(): + if key not in [syslang, 'en']: + self.langdict[key] = val + self.choices.append((key, val)) + self.choices.sort() + self.choices.insert(0,("nolang", ("unspecified"))) + self.choices.insert(1,(syslang, self.langdict[syslang])) + self.choices.insert(2,("en", self.langdict["en"])) + + def getLanguage(self, DVB_lang): + DVB_lang = DVB_lang.lower() + stripwords = ["stereo", "audio", "description", "2ch", "dolby digital"] + for word in stripwords: + DVB_lang = DVB_lang.replace(word,"").strip() + for key, val in LanguageCodes.iteritems(): + if DVB_lang.find(key.lower()) == 0: + if len(key) == 2: + return key + else: + DVB_lang = (LanguageCodes[key])[0] + elif DVB_lang.find(val[0].lower()) > -1: + if len(key) == 2: + return key + else: + DVB_lang = (LanguageCodes[key])[0] + for key, val in self.langdict.iteritems(): + if val == DVB_lang: + return key + return "nolang" + +languageChoices = LanguageChoices()
\ No newline at end of file diff --git a/lib/python/Plugins/Extensions/DVDBurn/keymap.xml b/lib/python/Plugins/Extensions/DVDBurn/keymap.xml index 13fa3ee0..e8bc1045 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/keymap.xml +++ b/lib/python/Plugins/Extensions/DVDBurn/keymap.xml @@ -2,7 +2,7 @@ <map context="DVDTitleList"> <key id="KEY_RED" mapto="removeCurrentTitle" flags="m" /> <key id="KEY_GREEN" mapto="addTitle" flags="m" /> - <key id="KEY_YELLOW" mapto="editTitle" flags="m" /> + <key id="KEY_YELLOW" mapto="titleProperties" flags="m" /> <key id="KEY_BLUE" mapto="settings" flags="m" /> <key id="KEY_RECORD" mapto="burnProject" flags="m" /> <key id="KEY_0" mapto="burnProject" flags="m" /> diff --git a/lib/python/Plugins/Extensions/DVDBurn/plugin.py b/lib/python/Plugins/Extensions/DVDBurn/plugin.py index b658d804..29076cea 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/plugin.py +++ b/lib/python/Plugins/Extensions/DVDBurn/plugin.py @@ -12,5 +12,5 @@ def main_add(session, service, **kwargs): dvdburn.selectedSource(service) def Plugins(**kwargs): - return [PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main_add), - PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main) ] + return [PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main_add, icon="dvdburn.png"), + PluginDescriptor(name="DVD Burn", description=_("Burn to DVD..."), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main, icon="dvdburn.png") ] diff --git a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py index 4298642c..cb5f0e0d 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py @@ -371,13 +371,25 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP if retval > 0: self.zapToNumber(retval) + def getServiceInterface(self, iface): + service = self.service + if service: + attr = getattr(service, iface, None) + if callable(attr): + return attr() + return None + def __serviceStopped(self): self.dvdScreen.hide() - self.service.subtitle().disableSubtitles(self.session.current_dialog.instance) + subs = self.getServiceInterface("subtitle") + if subs: + subs.disableSubtitles(self.session.current_dialog.instance) def serviceStarted(self): #override InfoBarShowHide function self.dvdScreen.show() - self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None) + subs = self.getServiceInterface("subtitle") + if subs: + subs.enableSubtitles(self.dvdScreen.instance, None) def doEofInternal(self, playing): if self.in_menu: @@ -435,17 +447,19 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP print "StringAvail" def __osdAudioInfoAvail(self): - audioTuple = self.service.info().getInfoObject(iServiceInformation.sUser+6) + info = self.getServiceInterface("info") + audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6) print "AudioInfoAvail ", repr(audioTuple) if audioTuple: audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2]) self["audioLabel"].setText(audioString) if audioTuple != self.last_audioTuple and not self.in_menu: self.doShow() - self.last_audioTuple = audioTuple + self.last_audioTuple = audioTuple def __osdSubtitleInfoAvail(self): - subtitleTuple = self.service.info().getInfoObject(iServiceInformation.sUser+7) + info = self.getServiceInterface("info") + subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7) print "SubtitleInfoAvail ", repr(subtitleTuple) if subtitleTuple: subtitleString = "" @@ -454,21 +468,25 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP self["subtitleLabel"].setText(subtitleString) if subtitleTuple != self.last_subtitleTuple and not self.in_menu: self.doShow() - self.last_subtitleTuple = subtitleTuple + self.last_subtitleTuple = subtitleTuple def __chapterUpdated(self): - self.currentChapter = self.service.info().getInfo(iServiceInformation.sCurrentChapter) - self.totalChapters = self.service.info().getInfo(iServiceInformation.sTotalChapters) - self.setChapterLabel() - print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters) + info = self.getServiceInterface("info") + if info: + self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter) + self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters) + self.setChapterLabel() + print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters) def __titleUpdated(self): - self.currentTitle = self.service.info().getInfo(iServiceInformation.sCurrentTitle) - self.totalTitles = self.service.info().getInfo(iServiceInformation.sTotalTitles) - self.setChapterLabel() - print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles) - if not self.in_menu: - self.doShow() + info = self.getServiceInterface("info") + if info: + self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle) + self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles) + self.setChapterLabel() + print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles) + if not self.in_menu: + self.doShow() def askLeavePlayer(self): choices = [(_("Continue playing"), "play"), (_("Exit"), "exit")] @@ -476,73 +494,65 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP choices.insert(1,(_("Return to file browser"), "browser")) self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices) + def sendKey(self, key): + keys = self.getServiceInterface("keys") + if keys: + keys.keyPressed(key) + return keys + def nextAudioTrack(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser) + self.sendKey(iServiceKeys.keyUser) def nextSubtitleTrack(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+1) + self.sendKey(iServiceKeys.keyUser+1) def enterDVDAudioMenu(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+2) + self.sendKey(iServiceKeys.keyUser+2) def nextChapter(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+3) + self.sendKey(iServiceKeys.keyUser+3) def prevChapter(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+4) + self.sendKey(iServiceKeys.keyUser+4) def nextTitle(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+5) + self.sendKey(iServiceKeys.keyUser+5) def prevTitle(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+6) + self.sendKey(iServiceKeys.keyUser+6) def enterDVDMenu(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUser+7) + self.sendKey(iServiceKeys.keyUser+7) def seekBeginning(self): if self.service: seekable = self.getSeek() - if seekable is not None: + if seekable: seekable.seekTo(0) def zapToNumber(self, number): if self.service: seekable = self.getSeek() - if seekable is not None: + if seekable: print "seek to chapter %d" % number seekable.seekChapter(number) # MENU ACTIONS def keyRight(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyRight) + self.sendKey(iServiceKeys.keyRight) def keyLeft(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyLeft) + self.sendKey(iServiceKeys.keyLeft) def keyUp(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyUp) + self.sendKey(iServiceKeys.keyUp) def keyDown(self): - if self.service: - self.service.keys().keyPressed(iServiceKeys.keyDown) + self.sendKey(iServiceKeys.keyDown) def keyOk(self): - if self.service: - if not self.in_menu: - self.toggleInfo() - self.service.keys().keyPressed(iServiceKeys.keyOk) + if self.sendKey(iServiceKeys.keyOk) and not self.in_menu: + self.toggleInfo() def keyCancel(self): self.askLeavePlayer() @@ -606,9 +616,10 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP def playLastCB(self, answer): # overwrite infobar cuesheet function print "playLastCB", answer, self.resume_point if self.service: - seek = self.service.seek() if answer == True: - seek.seekTo(self.resume_point) + seekable = self.getSeek() + if seekable: + seekable.seekTo(self.resume_point) pause = self.service.pause() pause.unpause() self.hideAfterResume() diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py b/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py index 7afbe14a..21d1bfe8 100644 --- a/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py +++ b/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py @@ -93,4 +93,4 @@ def main(session, servicelist, **kwargs): 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_EXTENSIONSMENU, fnc=main) ] + return [ PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EVENTINFO, fnc=main) ] diff --git a/lib/python/Plugins/Extensions/MediaPlayer/Makefile.am b/lib/python/Plugins/Extensions/MediaPlayer/Makefile.am index e4ec5748..123df22d 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/Makefile.am +++ b/lib/python/Plugins/Extensions/MediaPlayer/Makefile.am @@ -1,5 +1,4 @@ installdir = $(LIBDIR)/enigma2/python/Plugins/Extensions/MediaPlayer install_PYTHON = \ - __init__.py \ - plugin.py + __init__.py plugin.py settings.py diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index ed1a8874..0d5305d7 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -1,25 +1,27 @@ from os import path as os_path, remove as os_remove, listdir as os_listdir from time import strftime -from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation +from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, loadPic +from ServiceReference import ServiceReference from Screens.Screen import Screen +from Screens.HelpMenu import HelpableScreen from Screens.MessageBox import MessageBox from Screens.InputBox import InputBox +from Screens.ChoiceBox import ChoiceBox +from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport from Components.ActionMap import NumberActionMap, HelpableActionMap from Components.Label import Label from Components.Pixmap import Pixmap,MultiPixmap -from Components.Label import Label from Components.FileList import FileList from Components.MediaPlayer import PlayList -from Tools.Directories import resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE from Components.ServicePosition import ServicePositionGauge from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase from Components.Playlist import PlaylistIOInternal, PlaylistIOM3U, PlaylistIOPLS -from Screens.InfoBarGenerics import InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport -from ServiceReference import ServiceReference -from Screens.ChoiceBox import ChoiceBox -from Screens.HelpMenu import HelpableScreen +from Components.AVSwitch import AVSwitch from Components.Harddisk import harddiskmanager -from Tools.Directories import fileExists, pathExists +from Components.config import config +from Tools.Directories import fileExists, pathExists, resolveFilename, SCOPE_CONFIG, SCOPE_PLAYLIST, SCOPE_SKIN_IMAGE +from settings import MediaPlayerSettings +from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier import random class MyPlayList(PlayList): @@ -42,6 +44,7 @@ class MediaPixmap(Pixmap): break if self.default_pixmap is None: self.default_pixmap = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png") + self.coverFileNames = ["folder.png", "folder.jpg"] return Pixmap.applySkin(self, desktop, screen) class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen): @@ -66,7 +69,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.addPlaylistParser(PlaylistIOInternal, "e2pls") # 'None' is magic to start at the list of mountpoints - self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") + defaultDir = config.mediaplayer.defaultDir.getValue() + self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() @@ -92,8 +96,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self["coverArt"] = MediaPixmap() self["repeat"] = MultiPixmap() - self.repeat = False self.seek_target = None + hotplugNotifier.append(self.hotplugCB) class MoviePlayerActionMap(NumberActionMap): def __init__(self, player, contexts = [ ], actions = { }, prio=0): @@ -169,7 +173,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.coverArtFileName = "" self.isAudioCD = False self.AudioCD_albuminfo = {} - self.savePlaylistOnExit = True + self.cdAudioTrackFiles = [] + self.applySettings() self.playlistIOInternal = PlaylistIOInternal() list = self.playlistIOInternal.open(resolveFilename(SCOPE_CONFIG, "playlist.e2pls")) @@ -192,16 +197,16 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB return MediaPlayerLCDScreen def exit(self): - self.session.openWithCallback(self.exitCB, MessageBox, _("Do you really want to exit?"), timeout=5) - - def exitCB(self, answer): - if answer == True: - self.playlistIOInternal.clear() - for x in self.playlist.list: - self.playlistIOInternal.addService(ServiceReference(x[0])) - if self.savePlaylistOnExit: - self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls")) - self.close() + self.playlistIOInternal.clear() + for x in self.playlist.list: + self.playlistIOInternal.addService(ServiceReference(x[0])) + if self.savePlaylistOnExit: + self.playlistIOInternal.save(resolveFilename(SCOPE_CONFIG, "playlist.e2pls")) + if config.mediaplayer.saveDirOnExit.getValue(): + config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory()) + config.mediaplayer.defaultDir.save() + hotplugNotifier.remove(self.hotplugCB) + self.close() def checkSkipShowHideLock(self): self.updatedSeekState() @@ -283,13 +288,15 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def updateCoverArtPixmap(self, path): while not path.endswith("/"): path = path[:-1] - pngname = path + "folder.png" - - if not fileExists(pngname): - pngname = self["coverArt"].default_pixmap - if self.coverArtFileName != pngname: - self.coverArtFileName = pngname - self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName) + new_coverArtFileName = self["coverArt"].default_pixmap + for filename in self["coverArt"].coverFileNames: + if fileExists(path + filename): + new_coverArtFileName = path + filename + if self.coverArtFileName != new_coverArtFileName: + self.coverArtFileName = new_coverArtFileName + pixmap = loadPic(self.coverArtFileName, 116, 116, AVSwitch().getAspectRatioSetting()/2,1,0,0) + if pixmap is not None: + self["coverArt"].instance.setPixmap(pixmap.__deref__()) def leftDown(self): self.lefttimer = True @@ -441,27 +448,25 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def showMenu(self): menu = [] + if len(self.cdAudioTrackFiles): + menu.insert(0,(_("Play Audio-CD..."), "audiocd")) if self.currList == "filelist": if self.filelist.canDescent(): menu.append((_("add directory to playlist"), "copydir")) else: menu.append((_("add files to playlist"), "copyfiles")) menu.append((_("switch to playlist"), "playlist")) + menu.append((_("delete file"), "deletefile")) else: menu.append((_("switch to filelist"), "filelist")) - menu.append((_("shuffle playlist"), "shuffle")) - - menu.append((_("delete"), "delete")) + menu.append((_("Delete entry"), "deleteentry")) menu.append((_("clear playlist"), "clear")) menu.append((_("hide player"), "hide")); menu.append((_("save playlist"), "saveplaylist")); menu.append((_("load playlist"), "loadplaylist")); menu.append((_("delete saved playlist"), "deleteplaylist")); - menu.append((_("repeat playlist"), "repeat")); - drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()) - if pathExists(drivepath): - menu.insert(0,(_("Play Audio-CD..."), "audiocd")) + menu.append((_("Edit settings"), "settings")) self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu) def menuCallback(self, choice): @@ -473,20 +478,19 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB elif choice[1] == "copyfiles": self.stopEntry() self.playlist.clear() + self.isAudioCD = False self.copyDirectory(os_path.dirname(self.filelist.getSelection()[0].getPath()) + "/", recursive = False) self.playServiceRefEntry(self.filelist.getServiceRef()) elif choice[1] == "playlist": self.switchToPlayList() elif choice[1] == "filelist": self.switchToFileList() - elif choice[1] == "delete": + elif choice[1] == "deleteentry": if self.playlist.getSelectionIndex() == self.playlist.getCurrentIndex(): self.stopEntry() self.deleteEntry() elif choice[1] == "clear": - self.stopEntry() - self.playlist.clear() - self.switchToFileList() + self.clear_playlist() elif choice[1] == "hide": self.hide() elif choice[1] == "saveplaylist": @@ -497,24 +501,11 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.delete_saved_playlist() elif choice[1] == "shuffle": self.playlist.PlayListShuffle() - elif choice[1] == "repeat": - if self.repeat == True: - self.repeat = False - self["repeat"].setPixmapNum(0) - else: - self.repeat = True - self["repeat"].setPixmapNum(1) + elif choice[1] == "deletefile": + self.deleteFile() + elif choice[1] == "settings": + self.session.openWithCallback(self.applySettings, MediaPlayerSettings, self) elif choice[1] == "audiocd": - from Components.Scanner import scanDevice - drivepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()) - self.cdAudioTrackFiles = [] - res = scanDevice(drivepath) - list = [ (r.description, r, res[r], self.session) for r in res ] - if list: - (desc, scanner, files, session) = list[0] - for file in files: - if file.mimetype == "audio/x-cda": - self.cdAudioTrackFiles.append(file.path) self.playAudioCD() def playAudioCD(self): @@ -533,6 +524,13 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.changeEntry(0) self.switchToPlayList() + def applySettings(self): + self.savePlaylistOnExit = config.mediaplayer.savePlaylistOnExit.getValue() + if config.mediaplayer.repeat.getValue() == True: + self["repeat"].setPixmapNum(1) + else: + self["repeat"].setPixmapNum(0) + def showEventInformation(self): from Screens.EventView import EventViewSimple from ServiceReference import ServiceReference @@ -617,9 +615,14 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def deleteConfirmed(self, confirmed): if confirmed: - os_remove(self.delname) + try: + os_remove(self.delname) + except OSError,e: + print "delete failed:", e + self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR) def clear_playlist(self): + self.isAudioCD = False self.stopEntry() self.playlist.clear() self.switchToFileList() @@ -632,20 +635,78 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB if x[0][1] == True: #isDir if recursive: self.copyDirectory(x[0][0]) - else: + elif filelist.getServiceRef() and filelist.getServiceRef().type == 4097: self.playlist.addFile(x[0][0]) self.playlist.updateList() + def deleteFile(self): + if self.currList == "filelist": + self.service = self.filelist.getServiceRef() + else: + self.service = self.playlist.getSelection() + if self.service is None: + return + if self.service.type != 4098 and self.session.nav.getCurrentlyPlayingServiceReference() is not None: + if self.service == self.session.nav.getCurrentlyPlayingServiceReference(): + self.stopEntry() + + serviceHandler = eServiceCenter.getInstance() + offline = serviceHandler.offlineOperations(self.service) + info = serviceHandler.info(self.service) + name = info and info.getName(self.service) + result = False + if offline is not None: + # simulate first + if not offline.deleteFromDisk(1): + result = True + if result == True: + self.session.openWithCallback(self.deleteConfirmed_offline, MessageBox, _("Do you really want to delete %s?") % (name)) + else: + self.session.openWithCallback(self.close, MessageBox, _("You cannot delete this!"), MessageBox.TYPE_ERROR) + + def deleteConfirmed_offline(self, confirmed): + if confirmed: + serviceHandler = eServiceCenter.getInstance() + offline = serviceHandler.offlineOperations(self.service) + result = False + if offline is not None: + # really delete! + if not offline.deleteFromDisk(0): + result = True + if result == False: + self.session.open(MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR) + else: + self.removeListEntry() + + def removeListEntry(self): + currdir = self.filelist.getCurrentDirectory() + self.filelist.changeDir(currdir) + deleteend = False + while not deleteend: + index = 0 + deleteend = True + if len(self.playlist) > 0: + for x in self.playlist.list: + if self.service == x[0]: + self.playlist.deleteFile(index) + deleteend = False + break + index += 1 + self.playlist.updateList() + if self.currList == "playlist": + if len(self.playlist) == 0: + self.switchToFileList() + def copyFile(self): if self.filelist.getServiceRef().type == 4098: # playlist ServiceRef = self.filelist.getServiceRef() extension = ServiceRef.getPath()[ServiceRef.getPath().rfind('.') + 1:] - print "extension:", extension if self.playlistparsers.has_key(extension): playlist = self.playlistparsers[extension]() list = playlist.open(ServiceRef.getPath()) for x in list: self.playlist.addFile(x.ref) + self.playlist.updateList() else: self.playlist.addFile(self.filelist.getServiceRef()) self.playlist.updateList() @@ -659,7 +720,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB next = self.playlist.getCurrentIndex() + 1 if next < len(self.playlist): self.changeEntry(next) - elif ( len(self.playlist) > 0 ) and ( self.repeat == True ): + elif ( len(self.playlist) > 0 ) and ( config.mediaplayer.repeat.getValue() == True ): self.stopEntry() self.changeEntry(0) @@ -700,6 +761,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB else: self.stopEntry() self.playlist.clear() + self.isAudioCD = False sel = self.filelist.getSelection() if sel: if sel[1]: # can descent @@ -762,7 +824,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.unPauseService() if needsInfoUpdate == True: - self.updateCoverArtPixmap(currref.getPath()) + path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath() + self.updateCoverArtPixmap(path) else: pngname = self["coverArt"].default_pixmap self.coverArtFileName = pngname @@ -797,7 +860,20 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def subtitleSelection(self): from Screens.Subtitles import Subtitles - self.session.open(Subtitles) + self.session.open(Subtitles) + + def hotplugCB(self, dev, media_state): + if dev == harddiskmanager.getCD(): + from Components.Scanner import scanDevice + devpath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()) + self.cdAudioTrackFiles = [] + res = scanDevice(devpath) + list = [ (r.description, r, res[r], self.session) for r in res ] + if list: + (desc, scanner, files, session) = list[0] + for file in files: + if file.mimetype == "audio/x-cda": + self.cdAudioTrackFiles.append(file.path) class MediaPlayerLCDScreen(Screen): skin = """ @@ -814,7 +890,6 @@ class MediaPlayerLCDScreen(Screen): self["text4"] = Label("") def setText(self, text, line): - print "lcd set text:", text, line if len(text) > 10: if text[-4:] == ".mp3": text = text[:-4] diff --git a/lib/python/Plugins/Extensions/MediaPlayer/settings.py b/lib/python/Plugins/Extensions/MediaPlayer/settings.py new file mode 100644 index 00000000..c6d274bd --- /dev/null +++ b/lib/python/Plugins/Extensions/MediaPlayer/settings.py @@ -0,0 +1,137 @@ +from Screens.Screen import Screen +from Screens.HelpMenu import HelpableScreen +from Components.Label import Label +from Components.FileList import FileList +from Components.MediaPlayer import PlayList +from Components.config import config, getConfigListEntry, ConfigSubsection, configfile, ConfigText, ConfigYesNo +from Components.ConfigList import ConfigListScreen +from Components.ActionMap import ActionMap + +class ConfigDirectory(ConfigText): + def __init__(self, default="", visible_width=60): + ConfigText.__init__(self, default, fixed_size = True, visible_width = visible_width) + def handleKey(self, key): + pass + def getValue(self): + if self.text == "": + return None + else: + return ConfigText.getValue(self) + def setValue(self, val): + if val == None: + val = "" + ConfigText.setValue(self, val) + def getMulti(self, selected): + if self.text == "": + return ("mtext"[1-selected:], _("List of Storage Devices"), range(0)) + else: + return ConfigText.getMulti(self, selected) + +config.mediaplayer = ConfigSubsection() +config.mediaplayer.repeat = ConfigYesNo(default=False) +config.mediaplayer.savePlaylistOnExit = ConfigYesNo(default=True) +config.mediaplayer.saveDirOnExit = ConfigYesNo(default=False) +config.mediaplayer.defaultDir = ConfigDirectory() + +class DirectoryBrowser(Screen, HelpableScreen): + skin = """ + <screen name="DirectoryBrowser" position="160,62" size="450,376" title="Directory browser" > + <ePixmap pixmap="skin_default/buttons/red.png" position="10,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/green.png" position="300,0" size="140,40" alphatest="on" /> + <widget source="key_red" render="Label" position="10,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="300,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> + <widget name="filelist" position="0,44" size="440,322" scrollbarMode="showOnDemand" /> + </screen>""" + def __init__(self, session, currDir): + from Components.Sources.StaticText import StaticText + Screen.__init__(self, session) + HelpableScreen.__init__(self) + + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("Use")) + + self.filelist = FileList(currDir, matchingPattern="") + self["filelist"] = self.filelist + + self["FilelistActions"] = ActionMap(["SetupActions", "ColorActions"], + { + "green": self.use, + "red": self.exit, + "ok": self.ok, + "cancel": self.exit + }) + + def ok(self): + if self.filelist.canDescent(): + self.filelist.descent() + + def use(self): + if self.filelist.canDescent() and len(self["filelist"].getFilename()) > len(self["filelist"].getCurrentDirectory()): + self.filelist.descent() + self.close(self["filelist"].getCurrentDirectory()) + + def exit(self): + self.close(False) + +class MediaPlayerSettings(Screen,ConfigListScreen): + skin = """ + <screen name="MediaPlayerSettings" position="160,150" size="450,200" title="Edit settings"> + <ePixmap pixmap="skin_default/buttons/red.png" position="10,0" size="140,40" alphatest="on" /> + <ePixmap pixmap="skin_default/buttons/green.png" position="300,0" size="140,40" alphatest="on" /> + <widget source="key_red" render="Label" position="10,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="300,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" /> + <widget name="config" position="10,44" size="430,146" /> + </screen>""" + + def __init__(self, session, parent): + from Components.Sources.StaticText import StaticText + Screen.__init__(self, session) + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("Save")) + + ConfigListScreen.__init__(self, []) + self.parent = parent + self.initConfigList() + config.mediaplayer.saveDirOnExit.addNotifier(self.initConfigList) + + self["setupActions"] = ActionMap(["SetupActions", "ColorActions"], + { + "green": self.save, + "red": self.cancel, + "cancel": self.cancel, + "ok": self.ok, + }, -2) + + def initConfigList(self, element=None): + print "[initConfigList]", element + try: + self.list = [] + self.list.append(getConfigListEntry(_("repeat playlist"), config.mediaplayer.repeat)) + self.list.append(getConfigListEntry(_("save playlist on exit"), config.mediaplayer.savePlaylistOnExit)) + self.list.append(getConfigListEntry(_("save last directory on exit"), config.mediaplayer.saveDirOnExit)) + if not config.mediaplayer.saveDirOnExit.getValue(): + self.list.append(getConfigListEntry(_("start directory"), config.mediaplayer.defaultDir)) + self["config"].setList(self.list) + except KeyError: + print "keyError" + + def changedConfigList(self): + self.initConfigList() + + def ok(self): + if self["config"].getCurrent()[1] == config.mediaplayer.defaultDir: + self.session.openWithCallback(self.DirectoryBrowserClosed, DirectoryBrowser, self.parent.filelist.getCurrentDirectory()) + + def DirectoryBrowserClosed(self, path): + print "PathBrowserClosed:" + str(path) + if path != False: + config.mediaplayer.defaultDir.setValue(path) + + def save(self): + for x in self["config"].list: + x[1].save() + self.close() + + def cancel(self): + self.close() + diff --git a/lib/python/Plugins/Extensions/PicturePlayer/plugin.py b/lib/python/Plugins/Extensions/PicturePlayer/plugin.py index a9d61ed9..ea906f0d 100644 --- a/lib/python/Plugins/Extensions/PicturePlayer/plugin.py +++ b/lib/python/Plugins/Extensions/PicturePlayer/plugin.py @@ -155,7 +155,7 @@ class ThumbView(Screen): if not createDir(cachedir): cachefile = "" - ptr = loadPic(self.path + self.thumblist[self.thumbindex], 180, 160, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value),1, cachefile) + ptr = loadPic(self.path + self.thumblist[self.thumbindex], 180, 160, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value), 1, cachefile, 1) if ptr != None: self["thumb"+str(self.thumbindex)].show() self["thumb"+str(self.thumbindex)].instance.setPixmap(ptr) @@ -486,7 +486,7 @@ class picmain(Screen): if not createDir(cachedir): cachefile = "" - ptr = loadPic(self.filelist.getCurrentDirectory() + self.filelist.getFilename(), 180, 160, self.aspect, int(config.pic.resize.value), 0, 0, cachefile) + ptr = loadPic(self.filelist.getCurrentDirectory() + self.filelist.getFilename(), 180, 160, self.aspect, int(config.pic.resize.value), 0, 0, cachefile, 1) if ptr != None: self["thumbnail"].show() self["thumbnail"].instance.setPixmap(ptr) diff --git a/lib/python/Plugins/Plugin.py b/lib/python/Plugins/Plugin.py index a0db1d66..6df4fce7 100644 --- a/lib/python/Plugins/Plugin.py +++ b/lib/python/Plugins/Plugin.py @@ -45,6 +45,10 @@ class PluginDescriptor: # or return a function which is called with session and the interface name for extended setup of this interface WHERE_NETWORKSETUP = 10 + # show up this plugin (or a choicebox with all of them) for long INFO keypress + # or return a function which is called with session and the interface name for extended setup of this interface + WHERE_EVENTINFO = 11 + def __init__(self, name = "Plugin", where = [ ], description = "", icon = None, fnc = None, wakeupfnc = None, internal = False): self.name = name self.internal = internal diff --git a/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py b/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py index 469b1dd0..97ddf4a1 100644 --- a/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py +++ b/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py @@ -8,6 +8,8 @@ DEVICEDB = \ "/devices/pci0000:00/0000:00:14.2/usb1/1-1/1-1:1.0/host0/target1:0:0/0:0:0:0": "SD Slot" } +hotplugNotifier = [ ] + class Hotplug(Protocol): def getUserfriendlyDeviceName(self, phys): return DEVICEDB.get(phys, "USB Storage") @@ -48,6 +50,12 @@ class Hotplug(Protocol): harddiskmanager.addHotplugPartition(dev, self.getUserfriendlyDeviceName(physdevpath)) elif media_state == '0': harddiskmanager.removeHotplugPartition(dev) + + for callback in hotplugNotifier: + try: + callback(dev, media_state) + except AttributeError: + hotplugNotifier.remove(callback) def autostart(reason, **kwargs): if reason == 0: diff --git a/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py b/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py index 7b3d08f6..ec223d3e 100644 --- a/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py +++ b/lib/python/Plugins/SystemPlugins/SatelliteEquipmentControl/plugin.py @@ -23,6 +23,8 @@ class SecParameterSetup(Screen, ConfigListScreen): Screen.__init__(self, session) list = [ + ("Delay after diseqc reset command", config.sec.delay_after_diseqc_reset_cmd), + ("Delay after diseqc peripherial poweron command", config.sec.delay_after_diseqc_peripherial_poweron_cmd), ("Delay after continuous tone change", config.sec.delay_after_continuous_tone_change), ("Delay after last voltage change", config.sec.delay_after_final_voltage_change), ("Delay between diseqc commands", config.sec.delay_between_diseqc_repeats), diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index aab2b649..cdaa2c1e 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -403,8 +403,8 @@ class InfoBarEPG: self.eventView = None self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", { - "showEventInfo": (self.openEventView, _("show EPG...")), - "showSingleServiceEPG": (self.openSingleServiceEPG, _("show single service EPG...")), + "showEventView": (self.openEventView, _("show EPG...")), + "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")), "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible, }) @@ -489,6 +489,23 @@ class InfoBarEPG: ref=self.session.nav.getCurrentlyPlayingServiceReference() self.session.open(EPGSelection, ref) + def showEventInfoPlugins(self): + list = [] + for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EVENTINFO): + list.append((p.name, boundFunction(self.runPlugin, p))) + if len(list): + list.append((_("show single service EPG..."), self.openSingleServiceEPG)) + self.session.openWithCallback(self.EventInfoPluginChosen, ChoiceBox, title=_("Please choose an extension..."), list = list) + 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) @@ -1258,7 +1275,6 @@ class InfoBarExtensions: from Tools.BoundFunction import boundFunction # depends on InfoBarExtensions -from Components.PluginComponent import plugins class InfoBarPlugins: def __init__(self): diff --git a/lib/python/Screens/InputBox.py b/lib/python/Screens/InputBox.py index 43b8a8b8..61ce356a 100644 --- a/lib/python/Screens/InputBox.py +++ b/lib/python/Screens/InputBox.py @@ -8,12 +8,14 @@ from Tools.BoundFunction import boundFunction from time import time class InputBox(Screen): - def __init__(self, session, title = "", windowTitle = _("Input"), **kwargs): + def __init__(self, session, title = "", windowTitle = _("Input"), useableChars = None, **kwargs): Screen.__init__(self, session) self["text"] = Label(title) self["input"] = Input(**kwargs) self.onShown.append(boundFunction(self.setTitle, windowTitle)) + if useableChars is not None: + self["input"].setUseableChars(useableChars) self["actions"] = NumberActionMap(["WizardActions", "InputBoxActions", "InputAsciiActions", "KeyboardInputActions"], { diff --git a/lib/python/Screens/LocationBox.py b/lib/python/Screens/LocationBox.py index 7cd6cbf9..68d4f772 100644 --- a/lib/python/Screens/LocationBox.py +++ b/lib/python/Screens/LocationBox.py @@ -503,3 +503,32 @@ class MovieLocationBox(LocationBox): def __init__(self, session, text, dir, minFree = None): inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"] LocationBox.__init__(self, session, text = text, currDir = dir, bookmarks = config.movielist.videodirs, autoAdd = True, editDir = True, inhibitDirs = inhibitDirs, minFree = minFree) + +class TimeshiftLocationBox(LocationBox): + + skinName = "LocationBox" # XXX: though we could use a custom skin or inherit the hardcoded one we stick with the original :-) + + def __init__(self, session): + inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"] + LocationBox.__init__( + self, + session, + text = _("Where to save temporary timeshift recordings?"), + currDir = config.usage.timeshift_path.value, + bookmarks = config.usage.allowed_timeshift_paths, + autoAdd = True, + editDir = True, + inhibitDirs = inhibitDirs, + minFree = 1024 # XXX: the same requirement is hardcoded in servicedvb.cpp + ) + + def cancel(self): + config.usage.timeshift_path.cancel() + LocationBox.cancel(self) + + def selectConfirmed(self, ret): + if ret: + config.usage.timeshift_path.value = self.getPreferredFolder() + config.usage.timeshift_path.save() + LocationBox.selectConfirmed(self, ret) + diff --git a/lib/python/Screens/Makefile.am b/lib/python/Screens/Makefile.am index 186c6f32..a3cf70bb 100644..100755 --- a/lib/python/Screens/Makefile.am +++ b/lib/python/Screens/Makefile.am @@ -13,5 +13,5 @@ install_PYTHON = \ TimerSelection.py PictureInPicture.py TimeDateInput.py \ SubtitleDisplay.py SubservicesQuickzap.py ParentalControlSetup.py NumericalTextInputHelpDialog.py \ SleepTimerEdit.py Ipkg.py RdsDisplay.py Globals.py DefaultWizard.py \ - SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py + SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py VirtualKeyBoard.py diff --git a/lib/python/Screens/MovieSelection.py b/lib/python/Screens/MovieSelection.py index c05f145f..5951653f 100644 --- a/lib/python/Screens/MovieSelection.py +++ b/lib/python/Screens/MovieSelection.py @@ -29,6 +29,28 @@ config.movielist.description = ConfigInteger(default=MovieList.HIDE_DESCRIPTION) config.movielist.last_videodir = ConfigText(default=resolveFilename(SCOPE_HDD)) config.movielist.last_timer_videodir = ConfigText(default=resolveFilename(SCOPE_HDD)) config.movielist.videodirs = ConfigLocations(default=[resolveFilename(SCOPE_HDD)]) +config.movielist.first_tags = ConfigText(default="") +config.movielist.second_tags = ConfigText(default="") + + +def setPreferredTagEditor(te): + global preferredTagEditor + try: + if preferredTagEditor == None: + preferredTagEditor = te + print "Preferred tag editor changed to ", preferredTagEditor + else: + print "Preferred tag editor already set to ", preferredTagEditor + print "ignoring ", te + except: + preferredTagEditor = te + print "Preferred tag editor set to ", preferredTagEditor + +def getPreferredTagEditor(): + global preferredTagEditor + return preferredTagEditor + +setPreferredTagEditor(None) class MovieContextMenu(Screen): def __init__(self, session, csel, service): @@ -71,10 +93,8 @@ class MovieContextMenu(Screen): def sortBy(self, newType): config.movielist.moviesort.value = newType - self.csel.selectedmovie = self.csel.getCurrent() self.csel.setSortType(newType) self.csel.reloadList() - self.csel.moveTo() self.close() def listType(self, newType): @@ -123,7 +143,7 @@ class MovieContextMenu(Screen): self.session.openWithCallback(self.close, MessageBox, _("Delete failed!"), MessageBox.TYPE_ERROR) else: self.csel["list"].removeService(self.service) - self.csel["freeDiskSpace"].update() + self.csel["freeDiskSpace"].update() self.close() class SelectionEventInfo: @@ -149,6 +169,7 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): self.tags = [ ] self.selected_tags = None + self.selected_tags_ele = None self.movemode = False self.bouquet_mark_edit = False @@ -178,7 +199,7 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): # Need list for init SelectionEventInfo.__init__(self) - self["key_red"] = Button(_("All...")) + self["key_red"] = Button(_("All")) self["key_green"] = Button("") self["key_yellow"] = Button("") self["key_blue"] = Button("") @@ -201,9 +222,9 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): self["ColorActions"] = HelpableActionMap(self, "ColorActions", { "red": (self.showAll, _("show all")), - "green": (self.showTagsFirst, _("show first tag")), - "yellow": (self.showTagsSecond, _("show second tag")), - "blue": (self.showTagsMenu, _("show tag menu")), + "green": (self.showTagsFirst, _("show first selected tag")), + "yellow": (self.showTagsSecond, _("show second selected tag")), + "blue": (self.showTagsSelect, _("show tag menu")), }) self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", @@ -246,11 +267,8 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): self.updateDescription() def updateHDDData(self): - self.reloadList() - if self.selectedmovie is not None: - self.moveTo() + self.reloadList(self.selectedmovie) self["waitingtext"].visible = False - self.updateTags() def moveTo(self): self["list"].moveTo(self.selectedmovie) @@ -285,26 +303,29 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): def updateTags(self): # get a list of tags available in this list self.tags = list(self["list"].tags) - - # by default, we do not display any filtering options - self.tag_first = "" - self.tag_second = "" - - # when tags are present, however, the first two are - # directly mapped to the second, third ("green", "yellow") buttons - if len(self.tags) > 0: - self.tag_first = self.getTagDescription(self.tags[0]) - - if len(self.tags) > 1: - self.tag_second = self.getTagDescription(self.tags[1]) - + + if not self.tags: + # by default, we do not display any filtering options + self.tag_first = "" + self.tag_second = "" + else: + tmp = config.movielist.first_tags.value + if tmp in self.tags: + self.tag_first = tmp + else: + self.tag_first = "<"+_("Tag 1")+">" + tmp = config.movielist.second_tags.value + if tmp in self.tags: + self.tag_second = tmp + else: + self.tag_second = "<"+_("Tag 2")+">" self["key_green"].text = self.tag_first self["key_yellow"].text = self.tag_second # the rest is presented in a list, available on the # fourth ("blue") button - if len(self.tags) > 2: - self["key_blue"].text = _("Other...") + if self.tags: + self["key_blue"].text = _("Tags")+"..." else: self["key_blue"].text = "" @@ -317,20 +338,26 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): def setSortType(self, type): self["list"].setSortType(type) - def reloadList(self): + def reloadList(self, sel = None, home = False): if not pathExists(config.movielist.last_videodir.value): path = resolveFilename(SCOPE_HDD) config.movielist.last_videodir.value = path config.movielist.last_videodir.save() self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + path) self["freeDiskSpace"].path = path + if sel is None: + sel = self.getCurrent() self["list"].reload(self.current_ref, self.selected_tags) title = _("Recorded files...") - if self.selected_tags is not None: - title += " - " + ','.join(self.selected_tags) if config.usage.setup_level.index >= 2: # expert+ title += " " + config.movielist.last_videodir.value + if self.selected_tags is not None: + title += " - " + ','.join(self.selected_tags) self.setTitle(title) + if not (sel and self["list"].moveTo(sel)): + if home: + self["list"].moveToIndex(0) + self.updateTags() self["freeDiskSpace"].update() def doPathSelect(self): @@ -348,7 +375,7 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): config.movielist.last_videodir.save() self.current_ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + res) self["freeDiskSpace"].path = res - self.reloadList() + self.reloadList(home = True) else: self.session.open( MessageBox, @@ -358,35 +385,41 @@ class MovieSelection(Screen, HelpableScreen, SelectionEventInfo): ) def showAll(self): + self.selected_tags_ele = None self.selected_tags = None - self.reloadList() + self.reloadList(home = True) - def showTagsN(self, n): - if len(self.tags) < n: + def showTagsN(self, tagele): + if not self.tags: self.showTagWarning() + elif not tagele or self.selected_tags_ele == tagele or not tagele.value in self.tags: + self.showTagsMenu(tagele) else: - print "select tag #%d, %s, %s" % (n, self.tags[n - 1], ','.join(self.tags)) - self.selected_tags = set([self.tags[n - 1]]) - self.reloadList() + self.selected_tags_ele = tagele + self.selected_tags = set([tagele.value]) + self.reloadList(home = True) def showTagsFirst(self): - self.showTagsN(1) + self.showTagsN(config.movielist.first_tags) def showTagsSecond(self): - self.showTagsN(2) + self.showTagsN(config.movielist.second_tags) + + def showTagsSelect(self): + self.showTagsN(None) def tagChosen(self, tag): if tag is not None: self.selected_tags = set([tag[0]]) - self.reloadList() + if self.selected_tags_ele: + self.selected_tags_ele.value = tag[0] + self.selected_tags_ele.save() + self.reloadList(home = True) - def showTagsMenu(self): - if len(self.tags) < 3: - self.showTagWarning() - else: - list = [(tag, self.getTagDescription(tag)) for tag in self.tags ] - self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select keyword to filter..."), list = list) + def showTagsMenu(self, tagele): + self.selected_tags_ele = tagele + list = [(tag, self.getTagDescription(tag)) for tag in self.tags ] + self.session.openWithCallback(self.tagChosen, ChoiceBox, title=_("Please select tag to filter..."), list = list) def showTagWarning(self): - # TODO - self.session.open(MessageBox, _("You need to define some keywords first!\nPress the menu-key to define keywords.\nDo you want to define keywords now?"), MessageBox.TYPE_ERROR) + self.session.open(MessageBox, _("No tags are set on these movies."), MessageBox.TYPE_ERROR) diff --git a/lib/python/Screens/NetworkSetup.py b/lib/python/Screens/NetworkSetup.py index 862bce46..ea2d17e6 100644..100755 --- a/lib/python/Screens/NetworkSetup.py +++ b/lib/python/Screens/NetworkSetup.py @@ -1,25 +1,25 @@ from Screen import Screen -from Components.ActionMap import ActionMap,NumberActionMap from Screens.MessageBox import MessageBox from Screens.InputBox import InputBox from Screens.Standby import * +from Screens.VirtualKeyBoard import VirtualKeyBoard +from Screens.HelpMenu import HelpableScreen from Components.Network import iNetwork from Components.Label import Label,MultiColorLabel from Components.Pixmap import Pixmap,MultiPixmap from Components.MenuList import MenuList -from Components.config import config, ConfigYesNo, ConfigIP, NoSave, ConfigText, ConfigSelection, getConfigListEntry, ConfigNothing +from Components.config import config, ConfigYesNo, ConfigIP, NoSave, ConfigText, ConfigPassword, ConfigSelection, getConfigListEntry, ConfigNothing from Components.ConfigList import ConfigListScreen from Components.PluginComponent import plugins from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest +from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap +from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE +from Tools.LoadPixmap import LoadPixmap from Plugins.Plugin import PluginDescriptor -from enigma import eTimer +from enigma import eTimer, ePoint, eSize, RT_HALIGN_LEFT, eListboxPythonMultiContent, gFont from os import path as os_path, system as os_system, unlink from re import compile as re_compile, search as re_search -from Tools.Directories import resolveFilename, SCOPE_PLUGINS -from Tools.Directories import SCOPE_SKIN_IMAGE,SCOPE_PLUGINS, resolveFilename -from Tools.LoadPixmap import LoadPixmap -from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, gFont class InterfaceList(MenuList): def __init__(self, list, enableWrapAround=False): @@ -30,11 +30,13 @@ class InterfaceList(MenuList): def InterfaceEntryComponent(index,name,default,active ): res = [ (index) ] res.append(MultiContentEntryText(pos=(80, 5), size=(430, 25), font=0, text=name)) - if default is True: - png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue.png")) - if default is False: - png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue_off.png")) - res.append(MultiContentEntryPixmapAlphaTest(pos=(10, 5), size=(25, 25), png = png)) + num_configured_if = len(iNetwork.getConfiguredAdapters()) + if num_configured_if >= 2: + if default is True: + png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue.png")) + if default is False: + png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/buttons/button_blue_off.png")) + res.append(MultiContentEntryPixmapAlphaTest(pos=(10, 5), size=(25, 25), png = png)) if active is True: png2 = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_on.png")) if active is False: @@ -43,41 +45,64 @@ def InterfaceEntryComponent(index,name,default,active ): return res -class NetworkAdapterSelection(Screen): +class NetworkAdapterSelection(Screen,HelpableScreen): def __init__(self, session): Screen.__init__(self, session) - - self.wlan_errortext = _("No working wireless networkadapter found.\nPlease verify that you have attached a compatible WLAN USB Stick and your Network is configured correctly.") - self.lan_errortext = _("No working local networkadapter found.\nPlease verify that you have attached a network cable and your Network is configured correctly.") + HelpableScreen.__init__(self) + + self.wlan_errortext = _("No working wireless network adapter found.\nPlease verify that you have attached a compatible WLAN device and your network is configured correctly.") + self.lan_errortext = _("No working local network adapter found.\nPlease verify that you have attached a network cable and your network is configured correctly.") + self.oktext = _("Press OK on your remote control to continue.") + self.restartLanRef = None self["ButtonBluetext"] = Label(_("Set as default Interface")) + self["ButtonBlue"] = Pixmap() self["ButtonRedtext"] = Label(_("Close")) self["introduction"] = Label(_("Press OK to edit the settings.")) self.adapters = [(iNetwork.getFriendlyAdapterName(x),x) for x in iNetwork.getAdapterList()] - + if len(self.adapters) == 0: self.onFirstExecBegin.append(self.NetworkFallback) - + + self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", + { + "cancel": (self.close, _("exit network interface list")), + "ok": (self.okbuttonClick, _("select interface")), + }) + + self["ColorActions"] = HelpableActionMap(self, "ColorActions", + { + "red": (self.close, _("exit network interface list")), + }) + + self["DefaultInterfaceAction"] = HelpableActionMap(self, "ColorActions", + { + "blue": (self.setDefaultInterface, [_("Set interface as default Interface"),_("* Only available if more than one interface is active.")] ), + }) + self.list = [] self["list"] = InterfaceList(self.list) self.updateList() - self["actions"] = ActionMap(["OkCancelActions", "ColorActions"], - { - "ok": self.okbuttonClick, - "cancel": self.close, - "blue": self.setDefaultInterface, - "red": self.close - }, -2) - + if len(self.adapters) == 1: self.onFirstExecBegin.append(self.okbuttonClick) + self.onClose.append(self.cleanup) + def updateList(self): - iNetwork.getInterfaces() self.list = [] default_gw = None - num_configured_if = len(iNetwork.configuredInterfaces) + num_configured_if = len(iNetwork.getConfiguredAdapters()) + if num_configured_if >= 2: + self["ButtonBlue"].show() + self["ButtonBluetext"].show() + self["DefaultInterfaceAction"].setEnabled(True) + else: + self["ButtonBlue"].hide() + self["ButtonBluetext"].hide() + self["DefaultInterfaceAction"].setEnabled(False) + if num_configured_if < 2 and os_path.exists("/etc/default_gw"): unlink("/etc/default_gw") @@ -86,7 +111,7 @@ class NetworkAdapterSelection(Screen): result = fp.read() fp.close() default_gw = result - + if len(self.adapters) == 0: # no interface available => display only eth0 self.list.append(InterfaceEntryComponent("eth0",iNetwork.getFriendlyAdapterName('eth0'),True,True )) else: @@ -106,24 +131,22 @@ class NetworkAdapterSelection(Screen): selection = self["list"].getCurrent() num_if = len(self.list) old_default_gw = None + num_configured_if = len(iNetwork.getConfiguredAdapters()) if os_path.exists("/etc/default_gw"): fp = open('/etc/default_gw', 'r') old_default_gw = fp.read() fp.close() - if num_if > 1 and (not old_default_gw or old_default_gw != selection[0]): + if num_configured_if > 1 and (not old_default_gw or old_default_gw != selection[0]): fp = open('/etc/default_gw', 'w+') fp.write(selection[0]) fp.close() - iNetwork.restartNetwork() - self.updateList() - elif old_default_gw and num_if < 2: + self.restartLan() + elif old_default_gw and num_configured_if < 2: unlink("/etc/default_gw") - iNetwork.restartNetwork() - self.updateList() + self.restartLan() def okbuttonClick(self): selection = self["list"].getCurrent() - print "selection",selection if selection is not None: self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, selection[0]) @@ -134,25 +157,48 @@ class NetworkAdapterSelection(Screen): self.updateList() def NetworkFallback(self): - if iNetwork.configuredInterfaces.has_key('wlan0') is True: + if iNetwork.configuredNetworkAdapters.has_key('wlan0') is True: self.session.openWithCallback(self.ErrorMessageClosed, MessageBox, self.wlan_errortext, type = MessageBox.TYPE_INFO,timeout = 10) - if iNetwork.configuredInterfaces.has_key('ath0') is True: + if iNetwork.configuredNetworkAdapters.has_key('ath0') is True: self.session.openWithCallback(self.ErrorMessageClosed, MessageBox, self.wlan_errortext, type = MessageBox.TYPE_INFO,timeout = 10) else: self.session.openWithCallback(self.ErrorMessageClosed, MessageBox, self.lan_errortext, type = MessageBox.TYPE_INFO,timeout = 10) def ErrorMessageClosed(self, *ret): - if iNetwork.configuredInterfaces.has_key('wlan0') is True: + if iNetwork.configuredNetworkAdapters.has_key('wlan0') is True: self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, 'wlan0') - elif iNetwork.configuredInterfaces.has_key('ath0') is True: + elif iNetwork.configuredNetworkAdapters.has_key('ath0') is True: self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, 'ath0') else: self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetupConfiguration, 'eth0') -class NameserverSetup(Screen, ConfigListScreen): + def cleanup(self): + iNetwork.stopLinkStateConsole() + iNetwork.stopRestartConsole() + iNetwork.stopGetInterfacesConsole() + + def restartLan(self): + iNetwork.restartNetwork(self.restartLanDataAvail) + self.restartLanRef = self.session.openWithCallback(self.restartfinishedCB, MessageBox, _("Please wait while we configure your network..."), type = MessageBox.TYPE_INFO, enable_input = False) + + def restartLanDataAvail(self, data): + if data is True: + iNetwork.getInterfaces(self.getInterfacesDataAvail) + + def getInterfacesDataAvail(self, data): + if data is True: + self.restartLanRef.close(True) + + def restartfinishedCB(self,data): + if data is True: + self.updateList() + self.session.open(MessageBox, _("Finished configuring your network"), type = MessageBox.TYPE_INFO, timeout = 10, default = False) + + +class NameserverSetup(Screen, ConfigListScreen, HelpableScreen): def __init__(self, session): Screen.__init__(self, session) - iNetwork.getInterfaces() + HelpableScreen.__init__(self) self.backupNameserverList = iNetwork.getNameserverList()[:] print "backup-list:", self.backupNameserverList @@ -162,14 +208,23 @@ class NameserverSetup(Screen, ConfigListScreen): self["introduction"] = Label(_("Press OK to activate the settings.")) self.createConfig() - self["actions"] = ActionMap(["OkCancelActions", "ColorActions"], + self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", + { + "cancel": (self.cancel, _("exit nameserver configuration")), + "ok": (self.ok, _("activate current configuration")), + }) + + self["ColorActions"] = HelpableActionMap(self, "ColorActions", + { + "red": (self.cancel, _("exit nameserver configuration")), + "green": (self.add, _("add a nameserver entry")), + "yellow": (self.remove, _("remove a nameserver entry")), + }) + + self["actions"] = NumberActionMap(["SetupActions"], { "ok": self.ok, - "cancel": self.cancel, - "red": self.cancel, - "green": self.add, - "yellow": self.remove - }, -2) + }, -2) self.list = [] ConfigListScreen.__init__(self, self.list) @@ -222,31 +277,55 @@ class NameserverSetup(Screen, ConfigListScreen): self.createConfig() self.createSetup() -class AdapterSetup(Screen, ConfigListScreen): - def __init__(self, session, iface,essid=None, aplist=None): +class AdapterSetup(Screen, ConfigListScreen, HelpableScreen): + def __init__(self, session, networkinfo, essid=None, aplist=None): Screen.__init__(self, session) + HelpableScreen.__init__(self) self.session = session - self.iface = iface - self.essid = essid - self.aplist = aplist + if isinstance(networkinfo, (list, tuple)): + self.iface = networkinfo[0] + self.essid = networkinfo[1] + self.aplist = networkinfo[2] + else: + self.iface = networkinfo + self.essid = essid + self.aplist = aplist self.extended = None + self.applyConfigRef = None + self.finished_cb = None + self.oktext = _("Press OK on your remote control to continue.") self.oldInterfaceState = iNetwork.getAdapterAttribute(self.iface, "up") - iNetwork.getInterfaces() self.createConfig() - - self["actions"] = NumberActionMap(["SetupActions", "ColorActions"], + + self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", + { + "cancel": (self.cancel, _("exit network adapter setup menu")), + "ok": (self.ok, _("select menu entry")), + }) + + self["ColorActions"] = HelpableActionMap(self, "ColorActions", + { + "red": (self.cancel, _("exit network adapter configuration")), + "blue": (self.KeyBlue, _("open nameserver configuration")), + }) + + self["VirtualKB"] = HelpableActionMap(self, "ColorActions", + { + "green": (self.KeyGreen, [_("open virtual keyboard input help"),_("* Only available when entering hidden SSID or network key")] ), + }) + + self["actions"] = NumberActionMap(["SetupActions"], { "ok": self.ok, - "cancel": self.cancel, - "red": self.cancel, - "blue": self.KeyBlue, }, -2) + self.list = [] ConfigListScreen.__init__(self, self.list,session = self.session) self.createSetup() self.onLayoutFinish.append(self.layoutFinished) + self.onClose.append(self.cleanup) self["DNS1text"] = Label(_("Primary DNS")) self["DNS2text"] = Label(_("Secondary DNS")) @@ -271,76 +350,105 @@ class AdapterSetup(Screen, ConfigListScreen): self["ButtonRedtext"] = Label(_("Close")) self["ButtonBlue"] = Pixmap() self["ButtonBluetext"] = Label(_("Edit DNS")) + self["ButtonGreen"] = Pixmap() + self["VKeyIcon"] = Pixmap() + self["HelpWindow"] = Pixmap() def layoutFinished(self): self["DNS1"].setText(self.primaryDNS.getText()) self["DNS2"].setText(self.secondaryDNS.getText()) if self.ipConfigEntry.getText() is not None: - self["IP"].setText(self.ipConfigEntry.getText()) + if self.ipConfigEntry.getText() == "0.0.0.0": + self["IP"].setText(_("N/A")) + else: + self["IP"].setText(self.ipConfigEntry.getText()) + else: + self["IP"].setText(_("N/A")) + if self.netmaskConfigEntry.getText() is not None: + if self.netmaskConfigEntry.getText() == "0.0.0.0": + self["Mask"].setText(_("N/A")) + else: + self["Mask"].setText(self.netmaskConfigEntry.getText()) else: - self["IP"].setText([0,0,0,0]) - self["Mask"].setText(self.netmaskConfigEntry.getText()) + self["IP"].setText(_("N/A")) if iNetwork.getAdapterAttribute(self.iface, "gateway"): - self["Gateway"].setText(self.gatewayConfigEntry.getText()) + if self.gatewayConfigEntry.getText() == "0.0.0.0": + self["Gateway"].setText(_("N/A")) + else: + self["Gateway"].setText(self.gatewayConfigEntry.getText()) else: self["Gateway"].hide() self["Gatewaytext"].hide() self["Adapter"].setText(iNetwork.getFriendlyAdapterName(self.iface)) + self["ButtonGreen"].hide() + self["VKeyIcon"].hide() + self["VirtualKB"].setEnabled(False) + self["HelpWindow"].hide() def createConfig(self): self.InterfaceEntry = None self.dhcpEntry = None self.gatewayEntry = None - self.SSIDscan = None + self.hiddenSSID = None self.wlanSSID = None - self.manualwlanSSID = None self.encryptionEnabled = None self.encryptionKey = None + self.encryptionType = None self.nwlist = None + self.encryptionlist = None + self.weplist = None self.wsconfig = None self.default = None if self.iface == "wlan0" or self.iface == "ath0" : from Plugins.SystemPlugins.WirelessLan.Wlan import wpaSupplicant,Wlan + self.w = Wlan(self.iface) self.ws = wpaSupplicant() - list = [] - list.append(_("WEP")) - list.append(_("WPA")) - list.append(_("WPA2")) + self.encryptionlist = [] + self.encryptionlist.append(("WEP", _("WEP"))) + self.encryptionlist.append(("WPA", _("WPA"))) + self.encryptionlist.append(("WPA2", _("WPA2"))) + self.encryptionlist.append(("WPA/WPA2", _("WPA or WPA2"))) + self.weplist = [] + self.weplist.append("ASCII") + self.weplist.append("HEX") if self.aplist is not None: self.nwlist = self.aplist self.nwlist.sort(key = lambda x: x[0]) else: self.nwlist = [] - self.w = None self.aps = None try: - self.w = Wlan(self.iface) self.aps = self.w.getNetworkList() if self.aps is not None: print "[NetworkSetup.py] got Accespoints!" - for ap in aps: - a = aps[ap] + for ap in self.aps: + a = self.aps[ap] if a['active']: if a['essid'] == "": a['essid'] = a['bssid'] - self.nwlist.append( a['essid']) + self.nwlist.append((a['essid'],a['essid'])) self.nwlist.sort(key = lambda x: x[0]) except: - self.nwlist.append("No Networks found") + self.nwlist.append(("No Networks found",_("No Networks found"))) self.wsconfig = self.ws.loadConfig() - self.default = self.essid or self.wsconfig['ssid'] - if self.default not in self.nwlist: - self.nwlist.append(self.default) - config.plugins.wlan.essidscan = NoSave(ConfigYesNo(default = self.wsconfig['ssidscan'])) - if self.wsconfig['ssidscan'] is True: - config.plugins.wlan.essid = NoSave(ConfigSelection(self.nwlist, default = self.default )) + if self.essid is not None: # ssid from wlan scan + self.default = self.essid else: - config.plugins.wlan.essid = NoSave(ConfigText(default = self.default, visible_width = 50, fixed_size = False)) + self.default = self.wsconfig['ssid'] + + if "hidden..." not in self.nwlist: + self.nwlist.append(("hidden...",_("hidden network"))) + if self.default not in self.nwlist: + self.nwlist.append((self.default,self.default)) + config.plugins.wlan.essid = NoSave(ConfigSelection(self.nwlist, default = self.default )) + config.plugins.wlan.hiddenessid = NoSave(ConfigText(default = self.wsconfig['hiddenessid'], visible_width = 50, fixed_size = False)) + config.plugins.wlan.encryption.enabled = NoSave(ConfigYesNo(default = self.wsconfig['encryption'] )) - config.plugins.wlan.encryption.type = NoSave(ConfigSelection(list, default = self.wsconfig['encryption_type'] )) - config.plugins.wlan.encryption.psk = NoSave(ConfigText(default = self.wsconfig['key'], visible_width = 50, fixed_size = False)) + config.plugins.wlan.encryption.type = NoSave(ConfigSelection(self.encryptionlist, default = self.wsconfig['encryption_type'] )) + config.plugins.wlan.encryption.wepkeytype = NoSave(ConfigSelection(self.weplist, default = self.wsconfig['encryption_wepkeytype'] )) + config.plugins.wlan.encryption.psk = NoSave(ConfigPassword(default = self.wsconfig['key'], visible_width = 50, fixed_size = False)) self.activateInterfaceEntry = NoSave(ConfigYesNo(default=iNetwork.getAdapterAttribute(self.iface, "up") or False)) self.dhcpConfigEntry = NoSave(ConfigYesNo(default=iNetwork.getAdapterAttribute(self.iface, "dhcp") or False)) @@ -382,26 +490,56 @@ class AdapterSetup(Screen, ConfigListScreen): self.configStrings = p.__call__["configStrings"] else: self.configStrings = None - self.SSIDscan = getConfigListEntry(_("Automatic SSID lookup"), config.plugins.wlan.essidscan) - self.list.append(self.SSIDscan) - self.wlanSSID = getConfigListEntry(_("Network SSID"), config.plugins.wlan.essid) - self.list.append(self.wlanSSID) + if config.plugins.wlan.essid.value == 'hidden...': + self.wlanSSID = getConfigListEntry(_("Network SSID"), config.plugins.wlan.essid) + self.list.append(self.wlanSSID) + self.hiddenSSID = getConfigListEntry(_("Hidden network SSID"), config.plugins.wlan.hiddenessid) + self.list.append(self.hiddenSSID) + else: + self.wlanSSID = getConfigListEntry(_("Network SSID"), config.plugins.wlan.essid) + self.list.append(self.wlanSSID) self.encryptionEnabled = getConfigListEntry(_("Encryption"), config.plugins.wlan.encryption.enabled) self.list.append(self.encryptionEnabled) if config.plugins.wlan.encryption.enabled.value: - self.list.append(getConfigListEntry(_("Encryption Type"), config.plugins.wlan.encryption.type)) - self.encryptionKey = getConfigListEntry(_("Encryption Key"), config.plugins.wlan.encryption.psk) - self.list.append(self.encryptionKey) + self.encryptionType = getConfigListEntry(_("Encryption Type"), config.plugins.wlan.encryption.type) + self.list.append(self.encryptionType) + if config.plugins.wlan.encryption.type.value == 'WEP': + self.list.append(getConfigListEntry(_("Encryption Keytype"), config.plugins.wlan.encryption.wepkeytype)) + self.encryptionKey = getConfigListEntry(_("Encryption Key"), config.plugins.wlan.encryption.psk) + self.list.append(self.encryptionKey) + else: + self.encryptionKey = getConfigListEntry(_("Encryption Key"), config.plugins.wlan.encryption.psk) + self.list.append(self.encryptionKey) + self["config"].list = self.list self["config"].l.setList(self.list) + if not self.selectionChanged in self["config"].onSelectionChanged: + self["config"].onSelectionChanged.append(self.selectionChanged) def KeyBlue(self): self.session.openWithCallback(self.NameserverSetupClosed, NameserverSetup) + def KeyGreen(self): + if self.iface == "wlan0" or self.iface == "ath0" : + if self["config"].getCurrent() == self.hiddenSSID: + if config.plugins.wlan.essid.value == 'hidden...': + self.session.openWithCallback(self.VirtualKeyBoardSSIDCallback, VirtualKeyBoard, title = (_("Enter WLAN network name/SSID:")), text = config.plugins.wlan.essid.value) + if self["config"].getCurrent() == self.encryptionKey: + self.session.openWithCallback(self.VirtualKeyBoardKeyCallback, VirtualKeyBoard, title = (_("Enter WLAN passphrase/key:")), text = config.plugins.wlan.encryption.psk.value) + + def VirtualKeyBoardSSIDCallback(self, callback = None): + if callback is not None and len(callback): + config.plugins.wlan.hiddenessid = NoSave(ConfigText(default = callback, visible_width = 50, fixed_size = False)) + self.createSetup() + + def VirtualKeyBoardKeyCallback(self, callback = None): + if callback is not None and len(callback): + config.plugins.wlan.encryption.psk = NoSave(ConfigPassword(default = callback, visible_width = 50, fixed_size = False)) + self.createSetup() + def newConfig(self): - print self["config"].getCurrent() if self["config"].getCurrent() == self.InterfaceEntry: self.createSetup() if self["config"].getCurrent() == self.dhcpEntry: @@ -409,15 +547,12 @@ class AdapterSetup(Screen, ConfigListScreen): if self["config"].getCurrent() == self.gatewayEntry: self.createSetup() if self.iface == "wlan0" or self.iface == "ath0" : - if self["config"].getCurrent() == self.SSIDscan: - if config.plugins.wlan.essidscan.value is True: - config.plugins.wlan.essid = NoSave(ConfigSelection(self.nwlist, default = self.default )) - else: - config.plugins.wlan.essid = NoSave(ConfigText(default = self.default, visible_width = 50, fixed_size = False)) + if self["config"].getCurrent() == self.wlanSSID: self.createSetup() if self["config"].getCurrent() == self.encryptionEnabled: self.createSetup() - + if self["config"].getCurrent() == self.encryptionType: + self.createSetup() def keyLeft(self): ConfigListScreen.keyLeft(self) self.newConfig() @@ -426,36 +561,109 @@ class AdapterSetup(Screen, ConfigListScreen): ConfigListScreen.keyRight(self) self.newConfig() + def selectionChanged(self): + current = self["config"].getCurrent() + if current == self.hiddenSSID and config.plugins.wlan.essid.value == 'hidden...': + helpwindowpos = self["HelpWindow"].getPosition() + if current[1].help_window.instance is not None: + current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1])) + self["ButtonGreen"].show() + self["VKeyIcon"].show() + self["VirtualKB"].setEnabled(True) + elif current == self.encryptionKey and config.plugins.wlan.encryption.enabled.value: + helpwindowpos = self["HelpWindow"].getPosition() + if current[1].help_window.instance is not None: + current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1])) + self["ButtonGreen"].show() + self["VKeyIcon"].show() + self["VirtualKB"].setEnabled(True) + else: + self["ButtonGreen"].hide() + self["VKeyIcon"].hide() + self["VirtualKB"].setEnabled(False) + def ok(self): - iNetwork.setAdapterAttribute(self.iface, "up", self.activateInterfaceEntry.value) - iNetwork.setAdapterAttribute(self.iface, "dhcp", self.dhcpConfigEntry.value) - iNetwork.setAdapterAttribute(self.iface, "ip", self.ipConfigEntry.value) - iNetwork.setAdapterAttribute(self.iface, "netmask", self.netmaskConfigEntry.value) - if self.hasGatewayConfigEntry.value: - iNetwork.setAdapterAttribute(self.iface, "gateway", self.gatewayConfigEntry.value) + current = self["config"].getCurrent() + if current == self.hiddenSSID and config.plugins.wlan.essid.value == 'hidden...': + if current[1].help_window.instance is not None: + current[1].help_window.instance.hide() + elif current == self.encryptionKey and config.plugins.wlan.encryption.enabled.value: + if current[1].help_window.instance is not None: + current[1].help_window.instance.hide() + self.session.openWithCallback(self.applyConfig, MessageBox, (_("Are you sure you want to activate this network configuration?\n\n") + self.oktext ) ) + + def applyConfig(self, ret = False): + if (ret == True): + iNetwork.setAdapterAttribute(self.iface, "up", self.activateInterfaceEntry.value) + iNetwork.setAdapterAttribute(self.iface, "dhcp", self.dhcpConfigEntry.value) + iNetwork.setAdapterAttribute(self.iface, "ip", self.ipConfigEntry.value) + iNetwork.setAdapterAttribute(self.iface, "netmask", self.netmaskConfigEntry.value) + if self.hasGatewayConfigEntry.value: + iNetwork.setAdapterAttribute(self.iface, "gateway", self.gatewayConfigEntry.value) + else: + iNetwork.removeAdapterAttribute(self.iface, "gateway") + if self.extended is not None and self.configStrings is not None: + iNetwork.setAdapterAttribute(self.iface, "configStrings", self.configStrings(self.iface)) + self.ws.writeConfig() + if self.activateInterfaceEntry.value is False: + iNetwork.deactivateInterface(self.iface) + iNetwork.writeNetworkConfig() + iNetwork.restartNetwork(self.applyConfigDataAvail) + self.applyConfigRef = self.session.openWithCallback(self.applyConfigfinishedCB, MessageBox, _("Please wait for activation of your network configuration..."), type = MessageBox.TYPE_INFO, enable_input = False) else: - iNetwork.removeAdapterAttribute(self.iface, "gateway") - if self.extended is not None and self.configStrings is not None: - iNetwork.setAdapterAttribute(self.iface, "configStrings", self.configStrings(self.iface)) - self.ws.writeConfig() - if self.activateInterfaceEntry.value is False: - iNetwork.deactivateInterface(self.iface) - iNetwork.writeNetworkConfig() - iNetwork.deactivateNetworkConfig() - iNetwork.activateNetworkConfig() - self.close() + self.cancel() + + def applyConfigDataAvail(self, data): + if data is True: + iNetwork.getInterfaces(self.getInterfacesDataAvail) + + def getInterfacesDataAvail(self, data): + if data is True: + self.applyConfigRef.close(True) + + def applyConfigfinishedCB(self,data): + if data is True: + num_configured_if = len(iNetwork.getConfiguredAdapters()) + if num_configured_if >= 2: + self.session.openWithCallback(self.secondIfaceFoundCB, MessageBox, _("Your network configuration has been activated.\nA second configured interface has been found.\n\nDo you want to disable the second network interface?"), default = True) + else: + if self.finished_cb: + self.session.openWithCallback(lambda x : self.finished_cb(), MessageBox, _("Your network configuration has been activated."), type = MessageBox.TYPE_INFO, timeout = 10) + else: + self.session.openWithCallback(self.ConfigfinishedCB, MessageBox, _("Your network configuration has been activated."), type = MessageBox.TYPE_INFO, timeout = 10) + + def secondIfaceFoundCB(self,data): + if data is False: + self.close('ok') + else: + configuredInterfaces = iNetwork.getConfiguredAdapters() + for interface in configuredInterfaces: + if interface == self.iface: + continue + iNetwork.setAdapterAttribute(interface, "up", False) + iNetwork.deactivateInterface(interface) + self.applyConfig(True) + + def ConfigfinishedCB(self,data): + if data is not None: + if data is True: + self.close('ok') def cancel(self): - iNetwork.setAdapterAttribute(self.iface, "up", self.oldInterfaceState) - self.activateInterfaceEntry.value = self.oldInterfaceState - if self.activateInterfaceEntry.value is False: - iNetwork.deactivateInterface(self.iface) - iNetwork.getInterfaces() - self.close() - - def run(self): + if self.oldInterfaceState is False: + iNetwork.deactivateInterface(self.iface,self.cancelCB) + else: + self.close('cancel') + + def cancelCB(self,data): + if data is not None: + if data is True: + self.close('cancel') + + def runAsync(self, finished_cb): + self.finished_cb = finished_cb self.ok() - + def NameserverSetupClosed(self, *ret): iNetwork.loadNameserverConfig() nameserver = (iNetwork.getNameserverList() + [[0,0,0,0]] * 2)[0:2] @@ -463,13 +671,18 @@ class AdapterSetup(Screen, ConfigListScreen): self.secondaryDNS = NoSave(ConfigIP(default=nameserver[1])) self.createSetup() self.layoutFinished() + + def cleanup(self): + iNetwork.stopLinkStateConsole() -class AdapterSetupConfiguration(Screen): +class AdapterSetupConfiguration(Screen, HelpableScreen): def __init__(self, session,iface): Screen.__init__(self, session) + HelpableScreen.__init__(self) self.session = session self.iface = iface + self.restartLanRef = None self.mainmenu = self.genMainMenu() self["menulist"] = MenuList(self.mainmenu) self["description"] = Label() @@ -485,8 +698,27 @@ class AdapterSetupConfiguration(Screen): self.oktext = _("Press OK on your remote control to continue.") self.reboottext = _("Your Dreambox will restart after pressing OK on your remote control.") - self.errortext = _("No working wireless interface found.\n Please verify that you have attached a compatible WLAN device or enable your local network interface.") + self.errortext = _("No working wireless network interface found.\n Please verify that you have attached a compatible WLAN device or enable your local network interface.") + self["WizardActions"] = HelpableActionMap(self, "WizardActions", + { + "up": (self.up, _("move up to previous entry")), + "down": (self.down, _("move down to next entry")), + "left": (self.left, _("move up to first entry")), + "right": (self.right, _("move down to last entry")), + }) + + self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", + { + "cancel": (self.close, _("exit networkadapter setup menu")), + "ok": (self.ok, _("select menu entry")), + }) + + self["ColorActions"] = HelpableActionMap(self, "ColorActions", + { + "red": (self.close, _("exit networkadapter setup menu")), + }) + self["actions"] = NumberActionMap(["WizardActions","ShortcutActions"], { "ok": self.ok, @@ -498,9 +730,9 @@ class AdapterSetupConfiguration(Screen): "right": self.right, }, -2) - iNetwork.getInterfaces() - self.onLayoutFinish.append(self.layoutFinished) self.updateStatusbar() + self.onLayoutFinish.append(self.layoutFinished) + self.onClose.append(self.cleanup) def ok(self): if self["menulist"].getCurrent()[1] == 'edit': @@ -548,8 +780,7 @@ class AdapterSetupConfiguration(Screen): ifobj = Wireless(self.iface) # a Wireless NIC Object self.wlanresponse = ifobj.getStatistics() if self.wlanresponse[0] != 19: - self.session.openWithCallback(self.AdapterSetupClosed, WlanStatus,self.iface) - #self.session.open(WlanStatus,self.iface) + self.session.openWithCallback(self.WlanStatusClosed, WlanStatus,self.iface) else: # Display Wlan not available Message self.showErrorMessage() @@ -584,6 +815,7 @@ class AdapterSetupConfiguration(Screen): self.loadDescription() def loadDescription(self): + print self["menulist"].getCurrent()[1] if self["menulist"].getCurrent()[1] == 'edit': self["description"].setText(_("Edit the network configuration of your Dreambox.\n" ) + self.oktext ) if self["menulist"].getCurrent()[1] == 'test': @@ -601,26 +833,21 @@ class AdapterSetupConfiguration(Screen): if self["menulist"].getCurrent()[1][0] == 'extendedSetup': self["description"].setText(_(self["menulist"].getCurrent()[1][1]) + self.oktext ) - def updateStatusbar(self): + def updateStatusbar(self, data = None): self["IFtext"].setText(_("Network:")) self["IF"].setText(iNetwork.getFriendlyAdapterName(self.iface)) self["Statustext"].setText(_("Link:")) if self.iface == 'wlan0' or self.iface == 'ath0': try: - from Plugins.SystemPlugins.WirelessLan.Wlan import Wlan - w = Wlan(self.iface) - stats = w.getStatus() - if stats['BSSID'] == "00:00:00:00:00:00": - self["statuspic"].setPixmapNum(1) - else: - self["statuspic"].setPixmapNum(0) - self["statuspic"].show() + from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status except: self["statuspic"].setPixmapNum(1) self["statuspic"].show() + else: + iStatus.getDataForInterface(self.iface,self.getInfoCB) else: - self.getLinkState(self.iface) + iNetwork.getLinkState(self.iface,self.dataAvail) def doNothing(self): pass @@ -661,24 +888,64 @@ class AdapterSetupConfiguration(Screen): return menu def AdapterSetupClosed(self, *ret): - self.mainmenu = self.genMainMenu() - self["menulist"].l.setList(self.mainmenu) - iNetwork.getInterfaces() - self.updateStatusbar() + if ret is not None and len(ret): + if ret[0] == 'ok' and (self.iface == 'wlan0' or self.iface == 'ath0') and iNetwork.getAdapterAttribute(self.iface, "up") is True: + try: + from Plugins.SystemPlugins.WirelessLan.plugin import WlanStatus + from Plugins.SystemPlugins.WirelessLan.iwlibs import Wireless + except ImportError: + self.session.open(MessageBox, _("The wireless LAN plugin is not installed!\nPlease install it."), type = MessageBox.TYPE_INFO,timeout = 10 ) + else: + ifobj = Wireless(self.iface) # a Wireless NIC Object + self.wlanresponse = ifobj.getStatistics() + if self.wlanresponse[0] != 19: + self.session.openWithCallback(self.WlanStatusClosed, WlanStatus,self.iface) + else: + # Display Wlan not available Message + self.showErrorMessage() + else: + self.mainmenu = self.genMainMenu() + self["menulist"].l.setList(self.mainmenu) + self.updateStatusbar() + else: + self.mainmenu = self.genMainMenu() + self["menulist"].l.setList(self.mainmenu) + self.updateStatusbar() + + def WlanStatusClosed(self, *ret): + if ret is not None and len(ret): + from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status + iStatus.stopWlanConsole() + self.mainmenu = self.genMainMenu() + self["menulist"].l.setList(self.mainmenu) + self.updateStatusbar() def WlanScanClosed(self,*ret): if ret[0] is not None: self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetup, self.iface,ret[0],ret[1]) else: - self.session.openWithCallback(self.AdapterSetupClosed, AdapterSetup, self.iface,None,ret[0]) - - + from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status + iStatus.stopWlanConsole() + self.mainmenu = self.genMainMenu() + self["menulist"].l.setList(self.mainmenu) + self.updateStatusbar() + def restartLan(self, ret = False): if (ret == True): - iNetwork.restartNetwork() + iNetwork.restartNetwork(self.restartLanDataAvail) + self.restartLanRef = self.session.openWithCallback(self.restartfinishedCB, MessageBox, _("Please wait while your network is restarting..."), type = MessageBox.TYPE_INFO, enable_input = False) + + def restartLanDataAvail(self, data): + if data is True: + iNetwork.getInterfaces(self.getInterfacesDataAvail) - def getLinkState(self,iface): - iNetwork.getLinkState(iface,self.dataAvail) + def getInterfacesDataAvail(self, data): + if data is True: + self.restartLanRef.close(True) + + def restartfinishedCB(self,data): + if data is True: + self.session.open(MessageBox, _("Finished restarting your network"), type = MessageBox.TYPE_INFO, timeout = 10, default = False) def dataAvail(self,data): self.output = data.strip() @@ -693,14 +960,35 @@ class AdapterSetupConfiguration(Screen): def showErrorMessage(self): self.session.open(MessageBox, self.errortext, type = MessageBox.TYPE_INFO,timeout = 10 ) - + + def cleanup(self): + iNetwork.stopLinkStateConsole() + iNetwork.stopDeactivateInterfaceConsole() + try: + from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status + except ImportError: + pass + else: + iStatus.stopWlanConsole() + + def getInfoCB(self,data,status): + if data is not None: + if data is True: + if status is not None: + if status[self.iface]["acesspoint"] == "No Connection" or status[self.iface]["acesspoint"] == "Not-Associated" or status[self.iface]["acesspoint"] == False: + self["statuspic"].setPixmapNum(1) + else: + self["statuspic"].setPixmapNum(0) + self["statuspic"].show() class NetworkAdapterTest(Screen): def __init__(self, session,iface): Screen.__init__(self, session) self.iface = iface - iNetwork.getInterfaces() + self.oldInterfaceState = iNetwork.getAdapterAttribute(self.iface, "up") self.setLabels() + self.onClose.append(self.cleanup) + self.onHide.append(self.cleanup) self["updown_actions"] = NumberActionMap(["WizardActions","ShortcutActions"], { @@ -713,8 +1001,8 @@ class NetworkAdapterTest(Screen): self["shortcuts"] = ActionMap(["ShortcutActions","WizardActions"], { - "red": self.close, - "back": self.close, + "red": self.cancel, + "back": self.cancel, }, -2) self["infoshortcuts"] = ActionMap(["ShortcutActions","WizardActions"], { @@ -745,6 +1033,12 @@ class NetworkAdapterTest(Screen): self.nextStepTimer = eTimer() self.nextStepTimer.callback.append(self.nextStepTimerFire) + def cancel(self): + if self.oldInterfaceState is False: + iNetwork.setAdapterAttribute(self.iface, "up", self.oldInterfaceState) + iNetwork.deactivateInterface(self.iface) + self.close() + def closeInfo(self): self["shortcuts"].setEnabled(True) self["infoshortcuts"].setEnabled(False) @@ -852,6 +1146,7 @@ class NetworkAdapterTest(Screen): def doStep3(self): self["Networktext"].setForegroundColorNum(1) + self["Network"].setText(_("Please wait...")) self.getLinkState(self.iface) self["NetworkInfo_Text"].setForegroundColorNum(1) self.steptimer = True @@ -874,48 +1169,15 @@ class NetworkAdapterTest(Screen): def doStep5(self): self["IPtext"].setForegroundColorNum(1) - ret = iNetwork.checkNetworkState() - if ret == True: - self["IP"].setForegroundColorNum(2) - self["IP"].setText(_("confirmed")) - self["IPInfo_Check"].setPixmapNum(0) - else: - self["IP"].setForegroundColorNum(1) - self["IP"].setText(_("unconfirmed")) - self["IPInfo_Check"].setPixmapNum(1) - self["IPInfo_Check"].show() - self["IPInfo_Text"].setForegroundColorNum(1) - self.steptimer = True - self.nextStepTimer.start(3000) + self["IP"].setText(_("Please wait...")) + iNetwork.checkNetworkState(self.NetworkStatedataAvail) def doStep6(self): self.steptimer = False self.nextStepTimer.stop() self["DNStext"].setForegroundColorNum(1) - ret = iNetwork.checkDNSLookup() - if ret == True: - self["DNS"].setForegroundColorNum(2) - self["DNS"].setText(_("confirmed")) - self["DNSInfo_Check"].setPixmapNum(0) - else: - self["DNS"].setForegroundColorNum(1) - self["DNS"].setText(_("unconfirmed")) - self["DNSInfo_Check"].setPixmapNum(1) - self["DNSInfo_Check"].show() - self["DNSInfo_Text"].setForegroundColorNum(1) - - self["EditSettings_Text"].show() - self["EditSettingsButton"].setPixmapNum(1) - self["EditSettings_Text"].setForegroundColorNum(2) # active - self["EditSettingsButton"].show() - self["ButtonYellow_Check"].setPixmapNum(1) - self["ButtonGreentext"].setText(_("Restart test")) - self["ButtonGreen_Check"].setPixmapNum(0) - self["shortcutsgreen"].setEnabled(False) - self["shortcutsgreen_restart"].setEnabled(True) - self["shortcutsyellow"].setEnabled(False) - self["updown_actions"].setEnabled(True) - self.activebutton = 6 + self["DNS"].setText(_("Please wait...")) + iNetwork.checkDNSLookup(self.DNSLookupdataAvail) def KeyGreen(self): self["shortcutsgreen"].setEnabled(False) @@ -1057,28 +1319,18 @@ class NetworkAdapterTest(Screen): def getLinkState(self,iface): if iface == 'wlan0' or iface == 'ath0': try: - from Plugins.SystemPlugins.WirelessLan.Wlan import Wlan - w = Wlan(iface) - stats = w.getStatus() - if stats['BSSID'] == "00:00:00:00:00:00": - self["Network"].setForegroundColorNum(1) - self["Network"].setText(_("disconnected")) - self["NetworkInfo_Check"].setPixmapNum(1) - self["NetworkInfo_Check"].show() - else: - self["Network"].setForegroundColorNum(2) - self["Network"].setText(_("connected")) - self["NetworkInfo_Check"].setPixmapNum(0) - self["NetworkInfo_Check"].show() + from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status except: self["Network"].setForegroundColorNum(1) self["Network"].setText(_("disconnected")) self["NetworkInfo_Check"].setPixmapNum(1) self["NetworkInfo_Check"].show() + else: + iStatus.getDataForInterface(self.iface,self.getInfoCB) else: - iNetwork.getLinkState(iface,self.dataAvail) + iNetwork.getLinkState(iface,self.LinkStatedataAvail) - def dataAvail(self,data): + def LinkStatedataAvail(self,data): self.output = data.strip() result = self.output.split('\n') pattern = re_compile("Link detected: yes") @@ -1093,4 +1345,66 @@ class NetworkAdapterTest(Screen): self["NetworkInfo_Check"].setPixmapNum(1) self["NetworkInfo_Check"].show() + def NetworkStatedataAvail(self,data): + if data <= 2: + self["IP"].setForegroundColorNum(2) + self["IP"].setText(_("confirmed")) + self["IPInfo_Check"].setPixmapNum(0) + else: + self["IP"].setForegroundColorNum(1) + self["IP"].setText(_("unconfirmed")) + self["IPInfo_Check"].setPixmapNum(1) + self["IPInfo_Check"].show() + self["IPInfo_Text"].setForegroundColorNum(1) + self.steptimer = True + self.nextStepTimer.start(3000) + + def DNSLookupdataAvail(self,data): + if data <= 2: + self["DNS"].setForegroundColorNum(2) + self["DNS"].setText(_("confirmed")) + self["DNSInfo_Check"].setPixmapNum(0) + else: + self["DNS"].setForegroundColorNum(1) + self["DNS"].setText(_("unconfirmed")) + self["DNSInfo_Check"].setPixmapNum(1) + self["DNSInfo_Check"].show() + self["DNSInfo_Text"].setForegroundColorNum(1) + self["EditSettings_Text"].show() + self["EditSettingsButton"].setPixmapNum(1) + self["EditSettings_Text"].setForegroundColorNum(2) # active + self["EditSettingsButton"].show() + self["ButtonYellow_Check"].setPixmapNum(1) + self["ButtonGreentext"].setText(_("Restart test")) + self["ButtonGreen_Check"].setPixmapNum(0) + self["shortcutsgreen"].setEnabled(False) + self["shortcutsgreen_restart"].setEnabled(True) + self["shortcutsyellow"].setEnabled(False) + self["updown_actions"].setEnabled(True) + self.activebutton = 6 + def getInfoCB(self,data,status): + if data is not None: + if data is True: + if status is not None: + if status[self.iface]["acesspoint"] == "No Connection" or status[self.iface]["acesspoint"] == "Not-Associated" or status[self.iface]["acesspoint"] == False: + self["Network"].setForegroundColorNum(1) + self["Network"].setText(_("disconnected")) + self["NetworkInfo_Check"].setPixmapNum(1) + self["NetworkInfo_Check"].show() + else: + self["Network"].setForegroundColorNum(2) + self["Network"].setText(_("connected")) + self["NetworkInfo_Check"].setPixmapNum(0) + self["NetworkInfo_Check"].show() + + def cleanup(self): + iNetwork.stopLinkStateConsole() + iNetwork.stopDNSConsole() + try: + from Plugins.SystemPlugins.WirelessLan.Wlan import iStatus,Status + except ImportError: + pass + else: + iStatus.stopWlanConsole() + diff --git a/lib/python/Screens/Satconfig.py b/lib/python/Screens/Satconfig.py index ccb776ea..6489f28f 100644 --- a/lib/python/Screens/Satconfig.py +++ b/lib/python/Screens/Satconfig.py @@ -14,16 +14,21 @@ from datetime import datetime class NimSetup(Screen, ConfigListScreen): def createSimpleSetup(self, list, mode): + nim = self.nimConfig if mode == "single": - list.append(getConfigListEntry(_("Satellite"), self.nimConfig.diseqcA)) + list.append(getConfigListEntry(_("Satellite"), nim.diseqcA)) + list.append(getConfigListEntry(_("Send DiSEqC"), nim.simpleSingleSendDiSEqC)) else: - list.append(getConfigListEntry(_("Port A"), self.nimConfig.diseqcA)) + list.append(getConfigListEntry(_("Port A"), nim.diseqcA)) if mode in ["toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]: - list.append(getConfigListEntry(_("Port B"), self.nimConfig.diseqcB)) + list.append(getConfigListEntry(_("Port B"), nim.diseqcB)) if mode == "diseqc_a_b_c_d": - list.append(getConfigListEntry(_("Port C"), self.nimConfig.diseqcC)) - list.append(getConfigListEntry(_("Port D"), self.nimConfig.diseqcD)) + list.append(getConfigListEntry(_("Port C"), nim.diseqcC)) + list.append(getConfigListEntry(_("Port D"), nim.diseqcD)) + if mode != "toneburst_a_b": + list.append(getConfigListEntry(_("Set Voltage and 22KHz"), nim.simpleDiSEqCSetVoltageTone)) + list.append(getConfigListEntry(_("Send DiSEqC only on satellite change"), nim.simpleDiSEqCOnlyOnSatChange)) def createPositionerSetup(self, list): nim = self.nimConfig @@ -88,7 +93,7 @@ class NimSetup(Screen, ConfigListScreen): self.list.append(self.configMode) if self.nimConfig.configMode.value == "simple": #simple setup - self.diseqcModeEntry = getConfigListEntry(_("DiSEqC Mode"), self.nimConfig.diseqcMode) + self.diseqcModeEntry = getConfigListEntry(_("Mode"), self.nimConfig.diseqcMode) self.list.append(self.diseqcModeEntry) if self.nimConfig.diseqcMode.value in ["single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]: self.createSimpleSetup(self.list, self.nimConfig.diseqcMode.value) @@ -407,12 +412,17 @@ class NimSelection(Screen): text = _("nothing connected") elif nimConfig.configMode.value == "simple": if nimConfig.diseqcMode.value in ["single", "toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]: - text = _("Sats") + ": " + nimmanager.getSatName(int(nimConfig.diseqcA.value)) + text = _("Sats") + ": " + if nimConfig.diseqcA.orbital_position != 3601: + text += nimmanager.getSatName(int(nimConfig.diseqcA.value)) if nimConfig.diseqcMode.value in ["toneburst_a_b", "diseqc_a_b", "diseqc_a_b_c_d"]: - text += "," + nimmanager.getSatName(int(nimConfig.diseqcB.value)) + if nimConfig.diseqcB.orbital_position != 3601: + text += "," + nimmanager.getSatName(int(nimConfig.diseqcB.value)) if nimConfig.diseqcMode.value == "diseqc_a_b_c_d": - text += "," + nimmanager.getSatName(int(nimConfig.diseqcC.value)) - text += "," + nimmanager.getSatName(int(nimConfig.diseqcD.value)) + if nimConfig.diseqcC.orbital_position != 3601: + text += "," + nimmanager.getSatName(int(nimConfig.diseqcC.value)) + if nimConfig.diseqcD.orbital_position != 3601: + text += "," + nimmanager.getSatName(int(nimConfig.diseqcD.value)) elif nimConfig.diseqcMode.value == "positioner": text = _("Positioner") + ":" if nimConfig.positionerMode.value == "usals": diff --git a/lib/python/Screens/ScanSetup.py b/lib/python/Screens/ScanSetup.py index ab110a24..608dcb2d 100644 --- a/lib/python/Screens/ScanSetup.py +++ b/lib/python/Screens/ScanSetup.py @@ -394,8 +394,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.modulationEntry = getConfigListEntry(_('Modulation'), self.scan_sat.modulation) self.list.append(self.modulationEntry) self.list.append(getConfigListEntry(_('Rolloff'), self.scan_sat.rolloff)) - if self.scan_sat.modulation.value == "8psk": - self.list.append(getConfigListEntry(_('Pilot'), self.scan_sat.pilot)) + self.list.append(getConfigListEntry(_('Pilot'), self.scan_sat.pilot)) elif self.scan_type.value == "single_satellite": self.updateSatList() print self.scan_satselection[index_to_scan] diff --git a/lib/python/Screens/TimerEdit.py b/lib/python/Screens/TimerEdit.py index 800bab33..aae345db 100644 --- a/lib/python/Screens/TimerEdit.py +++ b/lib/python/Screens/TimerEdit.py @@ -317,6 +317,7 @@ class TimerSanityConflict(Screen): EMPTY = 0 ENABLE = 1 DISABLE = 2 + EDIT = 3 def __init__(self, session, timer): Screen.__init__(self, session) @@ -338,10 +339,11 @@ class TimerSanityConflict(Screen): self["key_red"] = Button("Edit") self["key_green"] = Button(" ") - self["key_yellow"] = Button("Edit") + self["key_yellow"] = Button(" ") self["key_blue"] = Button(" ") self.key_green_choice = self.EMPTY + self.key_yellow_choice = self.EMPTY self.key_blue_choice = self.EMPTY self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ShortcutActions", "TimerEditActions"], @@ -415,9 +417,14 @@ class TimerSanityConflict(Screen): self["actions"].actions.update({"green":self.toggleTimer1}) self["key_green"].setText(_("Disable")) self.key_green_choice = self.DISABLE + if len(self.timer) > 1: x = self["list"].getSelectedIndex() if self.timer[x] is not None: + if self.key_yellow_choice == self.EMPTY: + self["actions"].actions.update({"yellow":self.editTimer2}) + self["key_yellow"].setText(_("Edit")) + self.key_yellow_choice = self.EDIT if self.timer[x].disabled and self.key_blue_choice != self.ENABLE: self["actions"].actions.update({"blue":self.toggleTimer2}) self["key_blue"].setText(_("Enable")) @@ -432,9 +439,11 @@ class TimerSanityConflict(Screen): self.key_blue_choice = self.DISABLE else: #FIXME.... this doesnt hide the buttons self.... just the text - self.removeAction("yellow") - self["key_yellow"].setText(" ") - self.key_yellow_choice = self.EMPTY - self.removeAction("blue") - self["key_blue"].setText(" ") - self.key_blue_choice = self.EMPTY + if self.key_yellow_choice != self.EMPTY: + self.removeAction("yellow") + self["key_yellow"].setText(" ") + self.key_yellow_choice = self.EMPTY + if self.key_blue_choice != self.EMPTY: + self.removeAction("blue") + self["key_blue"].setText(" ") + self.key_blue_choice = self.EMPTY diff --git a/lib/python/Screens/TimerEntry.py b/lib/python/Screens/TimerEntry.py index c4dfff72..1774061d 100644 --- a/lib/python/Screens/TimerEntry.py +++ b/lib/python/Screens/TimerEntry.py @@ -8,6 +8,7 @@ from Components.MenuList import MenuList from Components.Button import Button from Components.Label import Label from Components.Pixmap import Pixmap +from Screens.MovieSelection import getPreferredTagEditor from Screens.LocationBox import MovieLocationBox from Screens.ChoiceBox import ChoiceBox from RecordTimer import AFTEREVENT @@ -21,8 +22,7 @@ class TimerEntry(Screen, ConfigListScreen): Screen.__init__(self, session) self.timer = timer - self.entryStartDate = None - self.entryEndDate = None + self.entryDate = None self.entryService = None self["oktext"] = Label(_("OK")) @@ -88,13 +88,13 @@ class TimerEntry(Screen, ConfigListScreen): self.timerentry_type = ConfigSelection(choices = [("once",_("once")), ("repeated", _("repeated"))], default = type) self.timerentry_name = ConfigText(default = self.timer.name, visible_width = 50, fixed_size = False) self.timerentry_description = ConfigText(default = self.timer.description, visible_width = 50, fixed_size = False) + self.timerentry_tags = self.timer.tags + [] + self.timerentry_tagsset = ConfigSelection(choices = [len(self.timerentry_tags) == 0 and "None" or " ".join(self.timerentry_tags)]) self.timerentry_repeated = ConfigSelection(default = repeated, choices = [("daily", _("daily")), ("weekly", _("weekly")), ("weekdays", _("Mon-Fri")), ("user", _("user defined"))]) - self.timerentry_startdate = ConfigDateTime(default = self.timer.begin, formatstring = _("%d.%B %Y"), increment = 86400) + self.timerentry_date = ConfigDateTime(default = self.timer.begin, formatstring = _("%d.%B %Y"), increment = 86400) self.timerentry_starttime = ConfigClock(default = self.timer.begin) - - self.timerentry_enddate = ConfigDateTime(default = self.timer.end, formatstring = _("%d.%B %Y"), increment = 86400) self.timerentry_endtime = ConfigClock(default = self.timer.end) default = self.timer.dirname or resolveFilename(SCOPE_HDD) @@ -120,19 +120,6 @@ class TimerEntry(Screen, ConfigListScreen): self.timerentry_service_ref = self.timer.service_ref self.timerentry_service = ConfigSelection([servicename]) - self.timerentry_startdate.addNotifier(self.checkDate) - self.timerentry_enddate.addNotifier(self.checkDate) - - def checkDate(self, configElement): - if configElement is self.timerentry_startdate: - if self.timerentry_enddate.value < self.timerentry_startdate.value: - self.timerentry_enddate.value = self.timerentry_startdate.value - self["config"].invalidate(self.entryEndDate) - if configElement is self.timerentry_enddate: - if (self.timerentry_enddate.value < self.timerentry_startdate.value): - self.timerentry_startdate.value = self.timerentry_enddate.value - self["config"].invalidate(self.entryStartDate) - def createSetup(self, widget): self.list = [] self.list.append(getConfigListEntry(_("Name"), self.timerentry_name)) @@ -165,34 +152,24 @@ class TimerEntry(Screen, ConfigListScreen): self.list.append(getConfigListEntry(_("Saturday"), self.timerentry_day[5])) self.list.append(getConfigListEntry(_("Sunday"), self.timerentry_day[6])) - #self.list.append(getConfigListEntry("StartDate", self.timerentry_startdate)) -# self.list.append(getConfigListEntry("Weekday", self.timerentry_weekday)) - - self.entryStartDate = getConfigListEntry(_("Start"), self.timerentry_startdate) - if self.timerentry_type.value == "once": - self.list.append(self.entryStartDate) - self.list.append(getConfigListEntry(" ", self.timerentry_starttime)) - else: - self.list.append(getConfigListEntry(_("StartTime"), self.timerentry_starttime)) - - self.entryEndDate = getConfigListEntry(_("End"), self.timerentry_enddate) + self.entryDate = getConfigListEntry(_("Date"), self.timerentry_date) if self.timerentry_type.value == "once": - if self.timerentry_justplay.value != "zap": - self.list.append(self.entryEndDate) - self.list.append(getConfigListEntry(" ", self.timerentry_endtime)) - else: - if self.timerentry_justplay.value != "zap": - self.list.append(getConfigListEntry(_("EndTime"), self.timerentry_endtime)) + self.list.append(self.entryDate) + self.list.append(getConfigListEntry(_("StartTime"), self.timerentry_starttime)) + if self.timerentry_justplay.value != "zap": + self.list.append(getConfigListEntry(_("EndTime"), self.timerentry_endtime)) + self.channelEntry = getConfigListEntry(_("Channel"), self.timerentry_service) + self.list.append(self.channelEntry) + self.dirname = getConfigListEntry(_("Location"), self.timerentry_dirname) + self.tagsSet = getConfigListEntry(_("Tags"), self.timerentry_tagsset) if self.timerentry_justplay.value != "zap": if config.usage.setup_level.index >= 2: # expert+ - self.dirname = getConfigListEntry(_("Location"), self.timerentry_dirname) self.list.append(self.dirname) + if getPreferredTagEditor(): + self.list.append(self.tagsSet) self.list.append(getConfigListEntry(_("After event"), self.timerentry_afterevent)) - self.channelEntry = getConfigListEntry(_("Channel"), self.timerentry_service) - self.list.append(self.channelEntry) - self[widget].list = self.list self[widget].l.setList(self.list) @@ -206,14 +183,14 @@ class TimerEntry(Screen, ConfigListScreen): self.createSetup("config") def keyLeft(self): - if self["config"].getCurrent() is self.channelEntry: + if self["config"].getCurrent() in [self.channelEntry, self.tagsSet]: self.keySelect() else: ConfigListScreen.keyLeft(self) self.newConfig() def keyRight(self): - if self["config"].getCurrent() is self.channelEntry: + if self["config"].getCurrent() in [self.channelEntry, self.tagsSet]: self.keySelect() else: ConfigListScreen.keyRight(self) @@ -235,6 +212,12 @@ class TimerEntry(Screen, ConfigListScreen): self.timerentry_dirname.value, minFree = 100 # We require at least 100MB free space ) + elif getPreferredTagEditor() and cur == self.tagsSet: + self.session.openWithCallback( + self.tagEditFinished, + getPreferredTagEditor(), + self.timerentry_tags + ) else: self.keyGo() @@ -249,24 +232,15 @@ class TimerEntry(Screen, ConfigListScreen): dt = datetime(d.tm_year, d.tm_mon, d.tm_mday, mytime[0], mytime[1]) return int(mktime(dt.timetuple())) - def buildRepeatedBegin(self, rep_time, start_time): - d = localtime(rep_time) - dt = datetime(d.tm_year, d.tm_mon, d.tm_mday, start_time[0], start_time[1]) - return int(mktime(dt.timetuple())) - def getBeginEnd(self): - enddate = self.timerentry_enddate.value + date = self.timerentry_date.value endtime = self.timerentry_endtime.value - - startdate = self.timerentry_startdate.value starttime = self.timerentry_starttime.value - begin = self.getTimestamp(startdate, starttime) - end = self.getTimestamp(enddate, endtime) + begin = self.getTimestamp(date, starttime) + end = self.getTimestamp(date, endtime) - # because of the dateChecks, startdate can't be < enddate. - # however, the endtime can be less than the starttime. - # in this case, add 1 day. + # if the endtime is less than the starttime, add 1 day. if end < begin: end += 86400 return begin, end @@ -278,6 +252,7 @@ class TimerEntry(Screen, ConfigListScreen): self.timer.resetRepeated() self.timer.afterEvent = {"nothing": AFTEREVENT.NONE, "deepstandby": AFTEREVENT.DEEPSTANDBY, "standby": AFTEREVENT.STANDBY}[self.timerentry_afterevent.value] self.timer.service_ref = self.timerentry_service_ref + self.timer.tags = self.timerentry_tags self.timer.dirname = self.timerentry_dirname.value config.movielist.last_timer_videodir.value = self.timer.dirname @@ -352,6 +327,12 @@ class TimerEntry(Screen, ConfigListScreen): self.timerentry_dirname.setChoices(config.movielist.videodirs.value, default=res) self.timerentry_dirname.value = res + def tagEditFinished(self, ret): + if ret is not None: + self.timerentry_tags = ret + self.timerentry_tagsset.setChoices([len(ret) == 0 and "None" or " ".join(ret)]) + self["config"].invalidate(self.tagsSet) + class TimerLog(Screen): def __init__(self, session, timer): Screen.__init__(self, session) diff --git a/lib/python/Screens/VirtualKeyBoard.py b/lib/python/Screens/VirtualKeyBoard.py new file mode 100755 index 00000000..53970ab8 --- /dev/null +++ b/lib/python/Screens/VirtualKeyBoard.py @@ -0,0 +1,287 @@ +# -*- coding: iso-8859-1 -*-
+from Components.Language import language
+from Components.ActionMap import ActionMap
+from Components.Label import Label
+from Components.Pixmap import Pixmap
+from Components.MenuList import MenuList
+from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
+from enigma import eListboxPythonMultiContent, gFont, loadPNG, RT_HALIGN_CENTER, RT_VALIGN_CENTER
+from Screen import Screen
+from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE
+
+key_backspace = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_backspace.png"))
+key_bg = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_bg.png"))
+key_clr = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_clr.png"))
+key_esc = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_esc.png"))
+key_ok = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_ok.png"))
+key_sel = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_sel.png"))
+key_shift = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_shift.png"))
+key_shift_sel = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_shift_sel.png"))
+key_space = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/vkey_space.png"))
+
+class VirtualKeyBoardList(MenuList):
+ def __init__(self, list, enableWrapAround=False):
+ MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
+ self.l.setFont(0, gFont("Regular", 22))
+ self.l.setItemHeight(45)
+
+def VirtualKeyBoardEntryComponent(keys, selectedKey,shiftMode=False):
+ res = [ (keys) ]
+
+ x = 0
+ count = 0
+ if shiftMode:
+ shiftkey_png = key_shift_sel
+ else:
+ shiftkey_png = key_shift
+ for key in keys:
+ if key == "EXIT":
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_esc))
+ elif key == "BACKSPACE":
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_backspace))
+ elif key == "CLEAR":
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_clr))
+ elif key == "SHIFT":
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=shiftkey_png))
+ elif key == "SPACE":
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_space))
+ elif key == "OK":
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_ok))
+ #elif key == "<-":
+ # res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_left))
+ #elif key == "->":
+ # res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_right))
+
+ else:
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_bg))
+ res.append(MultiContentEntryText(pos=(x, 0), size=(45, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER))
+
+ if selectedKey == count:
+ res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_sel))
+
+ x += 45
+ count += 1
+
+ return res
+
+
+class VirtualKeyBoard(Screen):
+
+ def __init__(self, session, title="", text=""):
+ Screen.__init__(self, session)
+ self.keys_list = []
+ self.shiftkeys_list = []
+ self.lang = language.getLanguage()
+ if self.lang == 'de_DE':
+ self.keys_list = [
+ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"],
+ [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ü", u"+"],
+ [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"],
+ [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"@", u"ß", u"OK"]]
+
+ self.shiftkeys_list = [
+ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"],
+ [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ü", u"*"],
+ [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"],
+ [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"?", u"\\", u"OK"]]
+
+ elif self.lang == 'es_ES':
+ #still missing keys (u"ùÙ")
+ self.keys_list = [
+ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"],
+ [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"],
+ [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ó", u"á", u"#"],
+ [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"@", u"£", u"à", u"é", u"è", u"í", u"ì", u"ñ", u"ò", u"OK"]]
+
+ self.shiftkeys_list = [
+ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"],
+ [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ú", u"*"],
+ [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ó", u"Á", u"'"],
+ [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"?", u"\\", u"À", u"É", u"È", u"Í", u"Ì", u"Ñ", u"Ò", u"OK"]]
+
+ elif self.lang in ['sv_SE', 'fi_FI']:
+ self.keys_list = [
+ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"],
+ [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"],
+ [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"],
+ [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"@", u"ß", u"å", u"OK"]]
+
+ self.shiftkeys_list = [
+ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"],
+ [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"],
+ [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"],
+ [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"?", u"\\", u"Å", u"OK"]]
+ else:
+ self.keys_list = [
+ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"],
+ [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"+", u"@"],
+ [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"#", u"\\"],
+ [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"OK"]]
+
+ self.shiftkeys_list = [
+ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"],
+ [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"*"],
+ [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"'", u"?"],
+ [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"],
+ [u"SHIFT", u"SPACE", u"OK"]]
+
+ self.shiftMode = False
+ self.text = text
+ self.selectedKey = 0
+
+ self["header"] = Label(title)
+ self["text"] = Label(self.text)
+ self["list"] = VirtualKeyBoardList([])
+
+ self["actions"] = ActionMap(["OkCancelActions", "WizardActions", "ColorActions"],
+ {
+ "ok": self.okClicked,
+ "cancel": self.exit,
+ "left": self.left,
+ "right": self.right,
+ "up": self.up,
+ "down": self.down,
+ "red": self.backClicked,
+ "green": self.ok
+ }, -2)
+
+ self.onLayoutFinish.append(self.buildVirtualKeyBoard)
+
+ def buildVirtualKeyBoard(self, selectedKey=0):
+ list = []
+
+ if self.shiftMode:
+ self.k_list = self.shiftkeys_list
+ for keys in self.k_list:
+ if selectedKey < 12 and selectedKey > -1:
+ list.append(VirtualKeyBoardEntryComponent(keys, selectedKey,True))
+ else:
+ list.append(VirtualKeyBoardEntryComponent(keys, -1,True))
+ selectedKey -= 12
+ else:
+ self.k_list = self.keys_list
+ for keys in self.k_list:
+ if selectedKey < 12 and selectedKey > -1:
+ list.append(VirtualKeyBoardEntryComponent(keys, selectedKey))
+ else:
+ list.append(VirtualKeyBoardEntryComponent(keys, -1))
+ selectedKey -= 12
+
+ self["list"].setList(list)
+
+
+ def backClicked(self):
+ self.text = self["text"].getText()[:-1]
+ self["text"].setText(self.text)
+
+ def okClicked(self):
+ if self.shiftMode:
+ list = self.shiftkeys_list
+ else:
+ list = self.keys_list
+
+ selectedKey = self.selectedKey
+
+ for x in list:
+ if selectedKey < 12:
+ text = x[selectedKey]
+ break
+ else:
+ selectedKey -= 12
+
+ text = text.encode("utf-8")
+
+ if text == "EXIT":
+ self.close(None)
+
+ elif text == "BACKSPACE":
+ self.text = self["text"].getText()[:-1]
+ self["text"].setText(self.text)
+
+ elif text == "CLEAR":
+ self.text = ""
+ self["text"].setText(self.text)
+
+ elif text == "SHIFT":
+ if self.shiftMode:
+ self.shiftMode = False
+ else:
+ self.shiftMode = True
+
+ self.buildVirtualKeyBoard(self.selectedKey)
+
+ elif text == "SPACE":
+ self.text += " "
+ self["text"].setText(self.text)
+
+ elif text == "OK":
+ self.close(self["text"].getText())
+
+ else:
+ self.text = self["text"].getText()
+ self.text += text
+ self["text"].setText(self.text)
+
+ def ok(self):
+ self.close(self["text"].getText())
+
+ def exit(self):
+ self.close(None)
+
+ def left(self):
+ self.selectedKey -= 1
+
+ if self.selectedKey == -1:
+ self.selectedKey = 11
+ elif self.selectedKey == 11:
+ self.selectedKey = 23
+ elif self.selectedKey == 23:
+ self.selectedKey = 35
+ elif self.selectedKey == 35:
+ self.selectedKey = 47
+ elif self.selectedKey == 47:
+ self.selectedKey = 59
+
+ self.showActiveKey()
+
+ def right(self):
+ self.selectedKey += 1
+
+ if self.selectedKey == 12:
+ self.selectedKey = 0
+ elif self.selectedKey == 24:
+ self.selectedKey = 12
+ elif self.selectedKey == 36:
+ self.selectedKey = 24
+ elif self.selectedKey == 48:
+ self.selectedKey = 36
+ elif self.selectedKey == 60:
+ self.selectedKey = 48
+
+ self.showActiveKey()
+
+ def up(self):
+ self.selectedKey -= 12
+
+ if self.selectedKey < 0:
+ self.selectedKey += 60
+
+ self.showActiveKey()
+
+ def down(self):
+ self.selectedKey += 12
+
+ if self.selectedKey > 59:
+ self.selectedKey -= 60
+
+ self.showActiveKey()
+
+ def showActiveKey(self):
+ self.buildVirtualKeyBoard(self.selectedKey)
diff --git a/lib/python/Screens/Wizard.py b/lib/python/Screens/Wizard.py index cee057dc..23d6253a 100644 --- a/lib/python/Screens/Wizard.py +++ b/lib/python/Screens/Wizard.py @@ -84,7 +84,7 @@ class Wizard(Screen): timeoutstep = str(attrs.get('timeoutstep')) else: timeoutstep = '' - self.wizard[self.lastStep] = {"id": id, "condition": "", "text": "", "timeout": timeout, "timeoutaction": timeoutaction, "timeoutstep": timeoutstep, "list": [], "config": {"screen": None, "args": None, "type": "" }, "code": "", "codeafter": "", "nextstep": nextstep} + self.wizard[self.lastStep] = {"id": id, "condition": "", "text": "", "timeout": timeout, "timeoutaction": timeoutaction, "timeoutstep": timeoutstep, "list": [], "config": {"screen": None, "args": None, "type": "" }, "code": "", "codeafter": "", "code_async": "", "codeafter_async": "", "nextstep": nextstep} elif (name == "text"): self.wizard[self.lastStep]["text"] = string.replace(str(attrs.get('value')), "\\n", "\n") elif (name == "displaytext"): @@ -119,6 +119,7 @@ class Wizard(Screen): if (attrs.has_key('evaluation')): self.wizard[self.lastStep]["config"]["evaluation"] = str(attrs.get('evaluation')) elif (name == "code"): + self.async_code = attrs.has_key('async') and str(attrs.get('async')) == "yes" if attrs.has_key('pos') and str(attrs.get('pos')) == "after": self.codeafter = True else: @@ -129,10 +130,16 @@ class Wizard(Screen): def endElement(self, name): self.currContent = "" if name == 'code': - if self.codeafter: - self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"].strip() + if self.async_code: + if self.codeafter: + self.wizard[self.lastStep]["codeafter_async"] = self.wizard[self.lastStep]["codeafter_async"].strip() + else: + self.wizard[self.lastStep]["code_async"] = self.wizard[self.lastStep]["code_async"].strip() else: - self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"].strip() + if self.codeafter: + self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"].strip() + else: + self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"].strip() elif name == 'condition': self.wizard[self.lastStep]["condition"] = self.wizard[self.lastStep]["condition"].strip() elif name == 'step': @@ -141,13 +148,19 @@ class Wizard(Screen): def characters(self, ch): if self.currContent == "code": - if self.codeafter: - self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"] + ch + if self.async_code: + if self.codeafter: + self.wizard[self.lastStep]["codeafter_async"] = self.wizard[self.lastStep]["codeafter_async"] + ch + else: + self.wizard[self.lastStep]["code_async"] = self.wizard[self.lastStep]["code_async"] + ch else: - self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"] + ch + if self.codeafter: + self.wizard[self.lastStep]["codeafter"] = self.wizard[self.lastStep]["codeafter"] + ch + else: + self.wizard[self.lastStep]["code"] = self.wizard[self.lastStep]["code"] + ch elif self.currContent == "condition": self.wizard[self.lastStep]["condition"] = self.wizard[self.lastStep]["condition"] + ch - + def __init__(self, session, showSteps = True, showStepSlider = True, showList = True, showConfig = True): Screen.__init__(self, session) @@ -312,21 +325,24 @@ class Wizard(Screen): else: self.currStep = self.getStepWithID(nextStep) + print_now = True if ((currStep == self.numSteps and self.wizard[currStep]["nextstep"] is None) or self.wizard[currStep]["id"] == "end"): # wizard finished print "wizard finished" self.markDone() self.close() else: + self.codeafter = True self.runCode(self.wizard[currStep]["codeafter"]) - if self.wizard[currStep]["nextstep"] is not None: - self.currStep = self.getStepWithID(self.wizard[currStep]["nextstep"]) - if gotoStep is not None: - self.currStep = self.getStepWithID(gotoStep) - self.currStep += 1 - self.updateValues() - - print "Now: " + str(self.currStep) + self.prevStep = currStep + self.gotoStep = gotoStep + if not self.runCode(self.wizard[currStep]["codeafter_async"]): + self.afterAsyncCode() + else: + if self.updateValues in self.onShown: + self.onShown.remove(self.updateValues) + if print_now: + print "Now: " + str(self.currStep) def ok(self): print "OK" @@ -341,7 +357,8 @@ class Wizard(Screen): # for this. If there is one, please do a more specific check # and/or a comment in which situation there is no run() if callable(getattr(self.configInstance, "runAsync", None)): - self.onShown.remove(self.updateValues) + if self.updateValues in self.onShown: + self.onShown.remove(self.updateValues) self.configInstance.runAsync(self.finished) return else: @@ -371,7 +388,7 @@ class Wizard(Screen): def up(self): self.resetCounter() if (self.showConfig and self.wizard[self.currStep]["config"]["screen"] != None or self.wizard[self.currStep]["config"]["type"] == "dynamic"): - self["config"].instance.moveSelection(self["config"].instance.moveUp) + self["config"].instance.moveSelection(self["config"].instance.moveUp) elif (self.showList and len(self.wizard[self.currStep]["evaluatedlist"]) > 0): self["list"].selectPrevious() if self.wizard[self.currStep].has_key("onselect"): @@ -415,7 +432,9 @@ class Wizard(Screen): if code != "": print "code", code exec(code) - + return True + return False + def getTranslation(self, text): return _(text) @@ -445,10 +464,13 @@ class Wizard(Screen): del self.configInstance["config"] self.configInstance.doClose() self.configInstance = None - + self.condition = True exec (self.wizard[self.currStep]["condition"]) - if self.condition: + if not self.condition: + self.currStep += 1 + self.updateValues() + else: if len(self.stepHistory) == 0 or self.stepHistory[-1] != self.currStep: self.stepHistory.append(self.currStep) print "wizard step:", self.wizard[self.currStep] @@ -470,8 +492,27 @@ class Wizard(Screen): for x in self.lcdCallbacks: x(displaytext) + self.codeafter=False self.runCode(self.wizard[self.currStep]["code"]) - + if self.runCode(self.wizard[self.currStep]["code_async"]): + if self.updateValues in self.onShown: + self.onShown.remove(self.updateValues) + else: + self.afterAsyncCode() + + def afterAsyncCode(self): + if not self.updateValues in self.onShown: + self.onShown.append(self.updateValues) + + if self.codeafter: + if self.wizard[self.prevStep]["nextstep"] is not None: + self.currStep = self.getStepWithID(self.wizard[self.prevStep]["nextstep"]) + if self.gotoStep is not None: + self.currStep = self.getStepWithID(self.gotoStep) + self.currStep += 1 + self.updateValues() + print "Now: " + str(self.currStep) + else: if self.showList: print "showing list,", self.currStep for renderer in self.renderer: @@ -482,7 +523,7 @@ class Wizard(Screen): print "setZPosition" rootrenderer.instance.setZPosition(1) renderer = renderer.source - + #self["list"].instance.setZPosition(1) self.list = [] if (self.wizard[self.currStep].has_key("dynamiclist")): @@ -524,7 +565,7 @@ class Wizard(Screen): self["config"].l.setList(self.configInstance["config"].list) callbacks = self.configInstance["config"].onSelectionChanged self.configInstance["config"].destroy() - print "clearConfigList", self.configInstance["config"], self["config"] + print "clearConfigList", self.configInstance["config"], self["config"] self.configInstance["config"] = self["config"] self.configInstance["config"].onSelectionChanged = callbacks print "clearConfigList", self.configInstance["config"], self["config"] @@ -533,10 +574,7 @@ class Wizard(Screen): else: if self.has_key("config"): self["config"].hide() - else: # condition false - self.currStep += 1 - self.updateValues() - + def timeoutCounterFired(self): self.timeoutCounter -= 1 print "timeoutCounter:", self.timeoutCounter diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index 8f05d53d..7de05d2b 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -282,9 +282,9 @@ PyObject *New_iRecordableServicePtr(const ePtr<iRecordableService> &ptr) /* needed for service groups */ -PyObject *getBestPlayableServiceReference(const eServiceReference &bouquet_ref, const eServiceReference &ignore); +PyObject *getBestPlayableServiceReference(const eServiceReference &bouquet_ref, const eServiceReference &ignore, bool simulate=false); %{ -PyObject *getBestPlayableServiceReference(const eServiceReference &bouquet_ref, const eServiceReference &ignore) +PyObject *getBestPlayableServiceReference(const eServiceReference &bouquet_ref, const eServiceReference &ignore, bool simulate=false) { eStaticServiceDVBBouquetInformation info; if (info.isPlayable(bouquet_ref, ignore)) |
