diff options
Diffstat (limited to 'lib/python')
92 files changed, 4697 insertions, 1993 deletions
diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py index 8f99b98e..3188469a 100644 --- a/lib/python/Components/AVSwitch.py +++ b/lib/python/Components/AVSwitch.py @@ -1,33 +1,43 @@ from config import config, ConfigSlider, ConfigSelection, ConfigYesNo, ConfigEnableDisable, ConfigSubsection, ConfigBoolean -from enigma import eAVSwitch +from enigma import eAVSwitch, getDesktop from SystemInfo import SystemInfo class AVSwitch: - INPUT = { "ENCODER": (0, 4), "SCART": (1, 3), "AUX": (2, 4) } - def setInput(self, input): - eAVSwitch.getInstance().setInput(self.INPUT[input][0]) - if self.INPUT[input][1] == 4: - aspect = self.getAspectRatioSetting() - self.setAspectWSS(aspect) - self.setAspectSlowBlank(aspect) - else: - eAVSwitch.getInstance().setSlowblank(self.INPUT[input][1]) - # FIXME why do we have to reset the colorformat? bug in avs-driver? - map = {"cvbs": 0, "rgb": 1, "svideo": 2, "yuv": 3} - eAVSwitch.getInstance().setColorFormat(map[config.av.colorformat.value]) + INPUT = { "ENCODER": 0, "SCART": 1, "AUX": 2 } + eAVSwitch.getInstance().setInput(INPUT[input]) def setColorFormat(self, value): eAVSwitch.getInstance().setColorFormat(value) def setAspectRatio(self, value): eAVSwitch.getInstance().setAspectRatio(value) - self.setAspectWSS(value) - self.setAspectSlowBlank(value) def setSystem(self, value): eAVSwitch.getInstance().setVideomode(value) + def getOutputAspect(self): + valstr = config.av.aspectratio.value + if valstr in ("4_3_letterbox", "4_3_panscan"): # 4:3 + return (4,3) + elif valstr == "16_9": # auto ... 4:3 or 16:9 + try: + aspect_str = open("/proc/stb/vmpeg/0/aspect", "r").read() + if aspect_str == "1": # 4:3 + return (4,3) + except IOError: + pass + elif valstr in ("16_9_always", "16_9_letterbox"): # 16:9 + pass + elif valstr in ("16_10_letterbox", "16_10_panscan"): # 16:10 + return (16,10) + return (16,9) + + def getFramebufferScale(self): + aspect = self.getOutputAspect() + fb_size = getDesktop(0).size() + return (aspect[0] * fb_size.height(), aspect[1] * fb_size.width()) + def getAspectRatioSetting(self): valstr = config.av.aspectratio.value if valstr == "4_3_letterbox": @@ -47,35 +57,12 @@ class AVSwitch: return val def setAspectWSS(self, aspect=None): - if aspect is None: - aspect = self.getAspectRatioSetting() - if aspect == 0 or aspect == 1: # letterbox or panscan - if not config.av.wss.value: - value = 0 # wss off - else: - value = 3 # 4:3_full_format - elif aspect == 2: # 16:9 - if not config.av.wss.value: - value = 2 # auto(4:3_off) - else: - value = 1 # auto - elif aspect == 3 or aspect == 6: # always 16:9 - value = 4 # 16:9_full_format - elif aspect == 4 or aspect == 5: # 16:10 - value = 10 # 14:9_full_format + if not config.av.wss.value: + value = 2 # auto(4:3_off) + else: + value = 1 # auto eAVSwitch.getInstance().setWSS(value) - def setAspectSlowBlank(self, aspect=None): - if aspect is None: - aspect = self.getAspectRatioSetting() - if aspect == 0 or aspect == 1: # letterbox or panscan - value = 2 # 12 V - elif aspect == 2: # 16:9 - value = 4 # auto - elif aspect == 3 or aspect == 4 or aspect == 5 or aspect == 6: # always 16:9 - value = 1 # 6V - eAVSwitch.getInstance().setSlowblank(value) - def InitAVSwitch(): config.av = ConfigSubsection() config.av.yuvenabled = ConfigBoolean(default=False) diff --git a/lib/python/Components/Console.py b/lib/python/Components/Console.py index c5fa5f98..f1f3fd95 100644 --- a/lib/python/Components/Console.py +++ b/lib/python/Components/Console.py @@ -8,7 +8,7 @@ class Console(object): self.callbacks = {} self.extra_args = {} - def ePopen(self, cmd, callback, extra_args=[]): + def ePopen(self, cmd, callback=None, extra_args=[]): name = cmd i = 0 while self.appContainers.has_key(name): @@ -21,7 +21,9 @@ class Console(object): self.appContainers[name] = eConsoleAppContainer() self.appContainers[name].dataAvail.append(boundFunction(self.dataAvailCB,name)) self.appContainers[name].appClosed.append(boundFunction(self.finishedCB,name)) - retval = self.appContainers[name].execute(cmd) + if isinstance(cmd, str): # until .execute supports a better api + cmd = [cmd] + retval = self.appContainers[name].execute(*cmd) if retval: self.finishedCB(name, retval) @@ -50,5 +52,6 @@ class Console(object): extra_args = self.extra_args[name] del self.appContainers[name] del self.extra_args[name] - self.callbacks[name](data,retval,extra_args) + if self.callbacks[name]: + self.callbacks[name](data,retval,extra_args) del self.callbacks[name] diff --git a/lib/python/Components/Converter/EventTime.py b/lib/python/Components/Converter/EventTime.py index 966f2ca8..41f1ebf3 100644 --- a/lib/python/Components/Converter/EventTime.py +++ b/lib/python/Components/Converter/EventTime.py @@ -1,7 +1,7 @@ from Converter import Converter from Poll import Poll from time import time -from Components.Element import cached +from Components.Element import cached, ElementError class EventTime(Poll, Converter, object): STARTTIME = 0 @@ -28,7 +28,7 @@ class EventTime(Poll, Converter, object): self.poll_interval = 30*1000 self.poll_enabled = True else: - raise str("'%s' is not <StartTime|EndTime|Remaining|Duration|Progress> for EventTime converter" % type) + raise ElementError("'%s' is not <StartTime|EndTime|Remaining|Duration|Progress> for EventTime converter" % type) @cached def getTime(self): diff --git a/lib/python/Components/Converter/MovieInfo.py b/lib/python/Components/Converter/MovieInfo.py index 068d24d3..be28dcce 100644 --- a/lib/python/Components/Converter/MovieInfo.py +++ b/lib/python/Components/Converter/MovieInfo.py @@ -1,5 +1,5 @@ from Components.Converter.Converter import Converter -from Components.Element import cached +from Components.Element import cached, ElementError from enigma import iServiceInformation from ServiceReference import ServiceReference @@ -16,7 +16,7 @@ class MovieInfo(Converter, object): elif type == "RecordServiceName": self.type = self.MOVIE_REC_SERVICE_NAME else: - raise str("'%s' is not <ShortDescription|MetaDescription|RecordServiceName> for MovieInfo converter" % type) + raise ElementError("'%s' is not <ShortDescription|MetaDescription|RecordServiceName> for MovieInfo converter" % type) Converter.__init__(self, type) @cached diff --git a/lib/python/Components/Converter/RemainingToText.py b/lib/python/Components/Converter/RemainingToText.py index adefe9cf..4249e30a 100644 --- a/lib/python/Components/Converter/RemainingToText.py +++ b/lib/python/Components/Converter/RemainingToText.py @@ -2,19 +2,43 @@ from Components.Converter.Converter import Converter from Components.Element import cached class RemainingToText(Converter, object): + DEFAULT = 0 + WITH_SECONDS = 1 + NO_SECONDS = 2 + def __init__(self, type): Converter.__init__(self, type) + if type == "WithSeconds": + self.type = self.WITH_SECONDS + elif type == "NoSeconds": + self.type = self.NO_SECONDS + else: + self.type = self.DEFAULT @cached def getText(self): - r = self.source.time - if r is None: + time = self.source.time + if time is None: return "" (duration, remaining) = self.source.time - if remaining is not None: - return "+%d min" % (remaining / 60) + + if self.type == self.WITH_SECONDS: + if remaining is not None: + return "%d:%02d:%02d" % (remaining / 3600, (remaining / 60) - ((remaining / 3600) * 60), remaining % 60) + else: + return "%02d:%02d:%02d" % (duration / 3600, (duration / 60) - ((duration / 3600) * 60), duration % 60) + elif self.type == self.NO_SECONDS: + if remaining is not None: + return "+%d:%02d" % (remaining / 3600, (remaining / 60) - ((remaining / 3600) * 60)) + else: + return "%02d:%02d" % (duration / 3600, (duration / 60) - ((duration / 3600) * 60)) + elif self.type == self.DEFAULT: + if remaining is not None: + return "+%d min" % (remaining / 60) + else: + return "%d min" % (duration / 60) else: - return "%d min" % (duration / 60) + return "???" text = property(getText) diff --git a/lib/python/Components/Converter/ServicePosition.py b/lib/python/Components/Converter/ServicePosition.py index b488258b..2bcc5492 100644 --- a/lib/python/Components/Converter/ServicePosition.py +++ b/lib/python/Components/Converter/ServicePosition.py @@ -1,7 +1,7 @@ from Converter import Converter from Poll import Poll from enigma import iPlayableService -from Components.Element import cached +from Components.Element import cached, ElementError class ServicePosition(Converter, Poll, object): TYPE_LENGTH = 0 @@ -19,6 +19,7 @@ class ServicePosition(Converter, Poll, object): self.negate = 'Negate' in args self.detailed = 'Detailed' in args self.showHours = 'ShowHours' in args + self.showNoSeconds = 'ShowNoSeconds' in args if self.detailed: self.poll_interval = 100 @@ -34,7 +35,7 @@ class ServicePosition(Converter, Poll, object): elif type == "Gauge": self.type = self.TYPE_GAUGE else: - raise "type must be {Length|Position|Remaining|Gauge} with optional arguments {Negate|Detailed|ShowHours}" + raise ElementError("type must be {Length|Position|Remaining|Gauge} with optional arguments {Negate|Detailed|ShowHours|NoSeconds}") self.poll_enabled = self.type != self.TYPE_LENGTH @@ -94,9 +95,15 @@ class ServicePosition(Converter, Poll, object): if not self.detailed: if self.showHours: - return sign + "%d:%02d:%02d" % (l/3600, l%3600/60, l%60) + if self.showNoSeconds: + return sign + "%d:%02d" % (l/3600, l%3600/60) + else: + return sign + "%d:%02d:%02d" % (l/3600, l%3600/60, l%60) else: - return sign + "%d:%02d" % (l/60, l%60) + if self.showNoSeconds: + return sign + "%d" % (l/60) + else: + return sign + "%d:%02d" % (l/60, l%60) else: if self.showHours: return sign + "%d:%02d:%02d:%03d" % ((l/3600/90000), (l/90000)%3600/60, (l/90000)%60, (l%90000)/90) diff --git a/lib/python/Components/Converter/ServiceTime.py b/lib/python/Components/Converter/ServiceTime.py index 16bcae3a..89965067 100644 --- a/lib/python/Components/Converter/ServiceTime.py +++ b/lib/python/Components/Converter/ServiceTime.py @@ -1,5 +1,5 @@ from Converter import Converter -from Components.Element import cached +from Components.Element import cached, ElementError from enigma import iServiceInformation class ServiceTime(Converter, object): @@ -16,7 +16,7 @@ class ServiceTime(Converter, object): elif type == "Duration": self.type = self.DURATION else: - raise str("'%s' is not <StartTime|EndTime|Duration> for eEventTime converter" % type) + raise ElementError("'%s' is not <StartTime|EndTime|Duration> for eEventTime converter" % type) @cached def getTime(self): diff --git a/lib/python/Components/Converter/TemplatedMultiContent.py b/lib/python/Components/Converter/TemplatedMultiContent.py index a1b601d6..5f1d4f24 100644 --- a/lib/python/Components/Converter/TemplatedMultiContent.py +++ b/lib/python/Components/Converter/TemplatedMultiContent.py @@ -5,22 +5,27 @@ class TemplatedMultiContent(StringList): def __init__(self, args): StringList.__init__(self, args) from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_HALIGN_RIGHT, RT_VALIGN_TOP, RT_VALIGN_CENTER, RT_VALIGN_BOTTOM - from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmap, MultiContentEntryPixmapAlphaTest + from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmap, MultiContentEntryPixmapAlphaTest, MultiContentTemplateColor l = locals() del l["self"] # cleanup locals a bit del l["args"] self.template = eval(args, {}, l) + self.active_style = None assert "fonts" in self.template assert "itemHeight" in self.template - assert "template" in self.template + assert "template" in self.template or "templates" in self.template + assert "template" in self.template or "default" in self.template["templates"] # we need to have a default template + + if not "template" in self.template: # default template can be ["template"] or ["templates"]["default"] + self.template["template"] = self.template["templates"]["default"] def changed(self, what): if not self.content: from enigma import eListboxPythonMultiContent self.content = eListboxPythonMultiContent() self.content.setItemHeight(self.template["itemHeight"]) - self.content.setTemplate(self.template["template"]) + self.setTemplate() # also setup fonts (also given by source) index = 0 @@ -28,7 +33,28 @@ class TemplatedMultiContent(StringList): self.content.setFont(index, f) index += 1 + # if only template changed, don't reload list + if what[0] == self.CHANGED_SPECIFIC and what[1] == "style": + self.setTemplate() + return + if self.source: self.content.setList(self.source.list) + self.setTemplate() self.downstream_elements.changed(what) + + def setTemplate(self): + if self.source: + style = self.source.style + if style == self.active_style: + return # style did not change + + # if skin defined "templates", that means that it defines multiple styles in a dict. template should still be a default + templates = self.template.get("templates") + template = self.template.get("template") + + if templates and style: # if we have a custom style defined in the source, and different templates in the skin, look it up + template = templates.get(self.source.style, template) # default to default template + + self.content.setTemplate(template) diff --git a/lib/python/Components/Element.py b/lib/python/Components/Element.py index 2af57793..f4a8f127 100644 --- a/lib/python/Components/Element.py +++ b/lib/python/Components/Element.py @@ -16,6 +16,13 @@ def cached(f): return cache[name][1] return wrapper +class ElementError(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + class Element(object): CHANGED_DEFAULT = 0 # initial "pull" state CHANGED_ALL = 1 # really everything changed diff --git a/lib/python/Components/EpgList.py b/lib/python/Components/EpgList.py index dbcd572b..8a7c8d45 100644 --- a/lib/python/Components/EpgList.py +++ b/lib/python/Components/EpgList.py @@ -52,6 +52,10 @@ class EPGList(HTMLComponent, GUIComponent): self.l.setBuildFunc(self.buildSimilarEntry) self.epgcache = eEPGCache.getInstance() self.clock_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock.png')) + self.clock_add_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_add.png')) + self.clock_pre_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_pre.png')) + self.clock_post_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_post.png')) + self.clock_prepost_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_prepost.png')) def getEventFromId(self, service, eventid): event = None @@ -60,7 +64,7 @@ class EPGList(HTMLComponent, GUIComponent): return event def getCurrentChangeCount(self): - if self.type == EPG_TYPE_MULTI: + if self.type == EPG_TYPE_MULTI and self.l.getCurrentSelection() is not None: return self.l.getCurrentSelection()[0] return 0 @@ -92,11 +96,12 @@ class EPGList(HTMLComponent, GUIComponent): def selectionChanged(self): for x in self.onSelChanged: if x is not None: - try: - x() - except: # FIXME!!! - print "FIXME in EPGList.selectionChanged" - pass + x() +# try: +# x() +# except: # FIXME!!! +# print "FIXME in EPGList.selectionChanged" +# pass GUI_WIDGET = eListbox @@ -135,8 +140,32 @@ class EPGList(HTMLComponent, GUIComponent): self.datetime_rect = Rect(width/20*2, 0, width/20*5-15, height) self.service_rect = Rect(width/20*7, 0, width/20*13, height) + def getClockPixmap(self, refstr, beginTime, duration, eventId): + pre_clock = 1 + post_clock = 2 + clock_type = 0 + endTime = beginTime + duration + for x in self.timer.timer_list: + if x.service_ref.ref.toString() == refstr: + if x.eit == eventId: + return self.clock_pixmap + beg = x.begin + end = x.end + if beginTime > beg and beginTime < end and endTime > end: + clock_type |= pre_clock + elif beginTime < beg and endTime > beg and endTime < end: + clock_type |= post_clock + if clock_type == 0: + return self.clock_add_pixmap + elif clock_type == pre_clock: + return self.clock_pre_pixmap + elif clock_type == post_clock: + return self.clock_post_pixmap + else: + return self.clock_prepost_pixmap + def buildSingleEntry(self, service, eventId, beginTime, duration, EventName): - rec=beginTime and (self.timer.isInTimer(eventId, beginTime, duration, service) > ((duration/10)*8)) + rec=beginTime and (self.timer.isInTimer(eventId, beginTime, duration, service)) r1=self.weekday_rect r2=self.datetime_rect r3=self.descr_rect @@ -145,14 +174,15 @@ class EPGList(HTMLComponent, GUIComponent): res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_RIGHT, self.days[t[6]])) res.append((eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_RIGHT, "%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4]))) if rec: - res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, self.clock_pixmap)) + clock_pic = self.getClockPixmap(service, beginTime, duration, eventId) + res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic)) res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 25, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, EventName)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, EventName)) return res def buildSimilarEntry(self, service, eventId, beginTime, service_name, duration): - rec=beginTime and (self.timer.isInTimer(eventId, beginTime, duration, service) > ((duration/10)*8)) + rec=beginTime and (self.timer.isInTimer(eventId, beginTime, duration, service)) r1=self.weekday_rect r2=self.datetime_rect r3=self.service_rect @@ -161,22 +191,24 @@ class EPGList(HTMLComponent, GUIComponent): res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_RIGHT, self.days[t[6]])) res.append((eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_RIGHT, "%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4]))) if rec: - res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, self.clock_pixmap)) + clock_pic = self.getClockPixmap(service, beginTime, duration, eventId) + res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic)) res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 25, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, service_name)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, service_name)) return res def buildMultiEntry(self, changecount, service, eventId, begTime, duration, EventName, nowTime, service_name): - rec=begTime and (self.timer.isInTimer(eventId, begTime, duration, service) > ((duration/10)*8)) + rec=begTime and (self.timer.isInTimer(eventId, begTime, duration, service)) r1=self.service_rect r2=self.progress_rect r3=self.descr_rect r4=self.start_end_rect res = [ None ] # no private data needed if rec: + clock_pic = self.getClockPixmap(service, begTime, duration, eventId) res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width()-21, r1.height(), 0, RT_HALIGN_LEFT, service_name)) - res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r1.left()+r1.width()-16, r1.top(), 21, 21, self.clock_pixmap)) + res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r1.left()+r1.width()-16, r1.top(), 21, 21, clock_pic)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_LEFT, service_name)) if begTime is not None: @@ -252,6 +284,12 @@ class EPGList(HTMLComponent, GUIComponent): x = self.l.getCurrentSelection() return x and x[1] + def moveToService(self,serviceref): + for x in range(len(self.list)): + if self.list[x][1] == serviceref.toString(): + self.instance.moveSelectionTo(x) + break + def moveToEventId(self, eventId): index = 0 for x in self.list: diff --git a/lib/python/Components/FileList.py b/lib/python/Components/FileList.py index e028ec3a..84abf328 100644 --- a/lib/python/Components/FileList.py +++ b/lib/python/Components/FileList.py @@ -10,6 +10,7 @@ from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, \ from Tools.LoadPixmap import LoadPixmap EXTENSIONS = { + "m4a": "music", "mp2": "music", "mp3": "music", "wav": "music", @@ -21,6 +22,7 @@ EXTENSIONS = { "bmp": "picture", "ts": "movie", "avi": "movie", + "divx": "movie", "mpg": "movie", "mpeg": "movie", "mkv": "movie", @@ -117,8 +119,6 @@ class FileList(MenuList): def changeDir(self, directory, select = None): self.list = [] - if directory and not os_path.isdir(directory): - directory = None # if we are just entering from the list of mount points: if self.current_directory is None: if directory and self.showMountpoints: @@ -136,6 +136,9 @@ class FileList(MenuList): self.list.append(FileEntryComponent(name = p.description, absolute = path, isDir = True)) files = [ ] directories = [ ] + elif directory is None: + files = [ ] + directories = [ ] elif self.useServiceRef: root = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + directory) if self.additional_extensions: diff --git a/lib/python/Components/Harddisk.py b/lib/python/Components/Harddisk.py index f7c3a7cb..6c6c3c6c 100644 --- a/lib/python/Components/Harddisk.py +++ b/lib/python/Components/Harddisk.py @@ -2,6 +2,8 @@ from os import system, listdir, statvfs, popen, makedirs, readlink, stat, major, from Tools.Directories import SCOPE_HDD, resolveFilename from Tools.CList import CList from SystemInfo import SystemInfo +import string, time +from Components.Console import Console def tryOpen(filename): try: @@ -17,22 +19,33 @@ class Harddisk: tmp = procfile.readline().split(':') s_major = int(tmp[0]) s_minor = int(tmp[1]) + self.max_idle_time = 0 + self.idle_running = False + self.timer = None for disc in listdir("/dev/discs"): path = readlink('/dev/discs/'+disc) - devidex = '/dev'+path[2:]+'/' - disc = devidex+'disc' + devidex = '/dev/discs/'+disc+'/' + devidex2 = '/dev'+path[2:]+'/' + disc = devidex2+'disc' ret = stat(disc).st_rdev if s_major == major(ret) and s_minor == minor(ret): self.devidex = devidex - print "new Harddisk", device, self.devidex + self.devidex2 = devidex2 + print "new Harddisk", device, '->', self.devidex, '->', self.devidex2 + self.startIdle() break def __lt__(self, ob): return self.device < ob.device + def stop(self): + if self.timer: + self.timer.stop() + self.timer.callback.remove(self.runIdle) + def bus(self): - ide_cf = self.device.find("hd") == 0 and self.devidex.find("host0") == -1 # 7025 specific - internal = self.device.find("hd") == 0 and self.devidex + ide_cf = self.device.find("hd") == 0 and self.devidex2.find("host0") == -1 # 7025 specific + internal = self.device.find("hd") == 0 if ide_cf: ret = "External (CF)" elif internal: @@ -90,7 +103,7 @@ class Harddisk: line = procfile.readline() if line == "": break - if line.startswith(self.devidex): + if line.startswith(self.devidex) or line.startswith(self.devidex2): parts = line.strip().split(" ") try: stat = statvfs(parts[1]) @@ -123,7 +136,7 @@ class Harddisk: cmd = "/bin/umount" for line in procfile: - if line.startswith(self.devidex): + if line.startswith(self.devidex) or line.startswith(self.devidex2): parts = line.split() cmd = ' '.join([cmd, parts[1]]) @@ -210,12 +223,77 @@ class Harddisk: def getDeviceName(self): return self.getDeviceDir() + "disc" + # the HDD idle poll daemon. + # as some harddrives have a buggy standby timer, we are doing this by hand here. + # first, we disable the hardware timer. then, we check every now and then if + # any access has been made to the disc. If there has been no access over a specifed time, + # we set the hdd into standby. + def readStats(self): + l = open("/sys/block/%s/stat" % self.device).read() + nr_read = int(l[:8].strip()) + nr_write = int(l[4*9:4*9+8].strip()) + return nr_read, nr_write + + def startIdle(self): + self.last_access = time.time() + self.last_stat = 0 + self.is_sleeping = False + from enigma import eTimer + + # disable HDD standby timer + Console().ePopen(("hdparm", "hdparm", "-S0", (self.devidex + "disc"))) + self.timer = eTimer() + self.timer.callback.append(self.runIdle) + self.idle_running = True + self.setIdleTime(self.max_idle_time) # kick the idle polling loop + + def runIdle(self): + if not self.max_idle_time: + return + t = time.time() + + idle_time = t - self.last_access + + stats = self.readStats() + print "nr_read", stats[0], "nr_write", stats[1] + l = sum(stats) + print "sum", l, "prev_sum", self.last_stat + + if l != self.last_stat: # access + print "hdd was accessed since previous check!" + self.last_stat = l + self.last_access = t + idle_time = 0 + self.is_sleeping = False + else: + print "hdd IDLE!" + + print "[IDLE]", idle_time, self.max_idle_time, self.is_sleeping + if idle_time >= self.max_idle_time and not self.is_sleeping: + self.setSleep() + self.is_sleeping = True + + def setSleep(self): + Console().ePopen(("hdparm", "hdparm", "-y", (self.devidex + "disc"))) + + def setIdleTime(self, idle): + self.max_idle_time = idle + if self.idle_running: + if not idle: + self.timer.stop() + else: + self.timer.start(idle * 100, False) # poll 10 times per period. + + def isSleeping(self): + return self.is_sleeping + class Partition: - def __init__(self, mountpoint, description = "", force_mounted = False): + def __init__(self, mountpoint, device = None, description = "", force_mounted = False): self.mountpoint = mountpoint self.description = description self.force_mounted = force_mounted self.is_hotplug = force_mounted # so far; this might change. + self.device = device def stat(self): return statvfs(self.mountpoint) @@ -245,6 +323,15 @@ class Partition: return True return False +DEVICEDB = \ + { + # dm8000: + "/devices/platform/brcm-ehci.0/usb1/1-1/1-1.1/1-1.1:1.0": "Front USB Slot", + "/devices/platform/brcm-ehci.0/usb1/1-1/1-1.2/1-1.2:1.0": "Back, upper USB Slot", + "/devices/platform/brcm-ehci.0/usb1/1-1/1-1.3/1-1.3:1.0": "Back, lower USB Slot", + "/devices/platform/brcm-ehci-1.1/usb2/2-1/2-1:1.0/host1/target1:0:0/1:0:0:0": "DVD Drive", + } + class HarddiskManager: def __init__(self): self.hdd = [ ] @@ -305,37 +392,62 @@ class HarddiskManager: self.cd = blockdev except IOError: error = True - return error, blacklisted, removable, is_cdrom, partitions + # check for medium + medium_found = True + try: + open("/dev/" + blockdev).close() + except IOError, err: + if err.errno == 159: # no medium present + medium_found = False + + return error, blacklisted, removable, is_cdrom, partitions, medium_found def enumerateBlockDevices(self): print "enumerating block devices..." for blockdev in listdir("/sys/block"): - error, blacklisted, removable, is_cdrom, partitions = self.getBlockDevInfo(blockdev) + error, blacklisted, removable, is_cdrom, partitions, medium_found = self.getBlockDevInfo(blockdev) print "found block device '%s':" % blockdev, if error: print "error querying properties" elif blacklisted: print "blacklisted" + elif not medium_found: + print "no medium" else: print "ok, removable=%s, cdrom=%s, partitions=%s, device=%s" % (removable, is_cdrom, partitions, blockdev) - self.addHotplugPartition(blockdev, blockdev) + + self.addHotplugPartition(blockdev) for part in partitions: - self.addHotplugPartition(part, part) + self.addHotplugPartition(part) def getAutofsMountpoint(self, device): return "/autofs/%s/" % (device) - def addHotplugPartition(self, device, description): - p = Partition(mountpoint = self.getAutofsMountpoint(device), description = description, force_mounted = True) + def addHotplugPartition(self, device, physdev = None): + if not physdev: + dev, part = self.splitDeviceName(device) + try: + physdev = readlink("/sys/block/" + dev + "/device")[5:] + except OSError: + physdev = dev + print "couldn't determine blockdev physdev for device", device + + # device is the device name, without /dev + # physdev is the physical device path, which we (might) use to determine the userfriendly name + description = self.getUserfriendlyDeviceName(device, physdev) + + p = Partition(mountpoint = self.getAutofsMountpoint(device), description = description, force_mounted = True, device = device) self.partitions.append(p) self.on_partition_list_change("add", p) + + # see if this is a harddrive l = len(device) - if l and device[l-1] not in ('0','1','2','3','4','5','6','7','8','9'): - error, blacklisted, removable, is_cdrom, partitions = self.getBlockDevInfo(device) - if not blacklisted and not removable and not is_cdrom: + if l and device[l-1] not in string.digits: + error, blacklisted, removable, is_cdrom, partitions, medium_found = self.getBlockDevInfo(device) + if not blacklisted and not removable and not is_cdrom and medium_found: self.hdd.append(Harddisk(device)) self.hdd.sort() - SystemInfo["Harddisc"] = len(self.hdd) > 0 + SystemInfo["Harddisk"] = len(self.hdd) > 0 def removeHotplugPartition(self, device): mountpoint = self.getAutofsMountpoint(device) @@ -344,13 +456,14 @@ class HarddiskManager: self.partitions.remove(x) self.on_partition_list_change("remove", x) l = len(device) - if l and device[l-1] not in ('0','1','2','3','4','5','6','7','8','9'): + if l and device[l-1] not in string.digits: idx = 0 for hdd in self.hdd: if hdd.device == device: + self.hdd[x].stop() del self.hdd[idx] break - SystemInfo["Harddisc"] = len(self.hdd) > 0 + SystemInfo["Harddisk"] = len(self.hdd) > 0 def HDDCount(self): return len(self.hdd) @@ -369,6 +482,41 @@ class HarddiskManager: return self.cd def getMountedPartitions(self, onlyhotplug = False): - return [x for x in self.partitions if (x.is_hotplug or not onlyhotplug) and x.mounted()] + parts = [x for x in self.partitions if (x.is_hotplug or not onlyhotplug) and x.mounted()] + devs = set([x.device for x in parts]) + for devname in devs.copy(): + if not devname: + continue + dev, part = self.splitDeviceName(devname) + if part and dev in devs: # if this is a partition and we still have the wholedisk, remove wholedisk + devs.remove(dev) + + # return all devices which are not removed due to being a wholedisk when a partition exists + return [x for x in parts if not x.device or x.device in devs] + + def splitDeviceName(self, devname): + # this works for: sdaX, hdaX, sr0 (which is in fact dev="sr0", part=""). It doesn't work for other names like mtdblock3, but they are blacklisted anyway. + dev = devname[:3] + part = devname[3:] + for p in part: + if p not in string.digits: + return devname, 0 + return dev, part and int(part) or 0 + + def getUserfriendlyDeviceName(self, dev, phys): + dev, part = self.splitDeviceName(dev) + description = "External Storage %s" % dev + try: + description = open("/sys" + phys + "/model").read().strip() + except IOError, s: + print "couldn't read model: ", s + for physdevprefix, pdescription in DEVICEDB.items(): + if phys.startswith(physdevprefix): + description = pdescription + + # not wholedisk and not partition 1 + if part and part != 1: + description += " (Partition %d)" % part + return description harddiskmanager = HarddiskManager() diff --git a/lib/python/Components/Language.py b/lib/python/Components/Language.py index 6d1e31f3..395f6829 100644 --- a/lib/python/Components/Language.py +++ b/lib/python/Components/Language.py @@ -36,6 +36,7 @@ class Language: self.addLanguage(_("Swedish"), "sv", "SE") self.addLanguage(_("Turkish"), "tr", "TR") self.addLanguage(_("Ukrainian"), "uk", "UA") + self.addLanguage(_("Frisian"), "fy", "x-FY") # there is no separate country for frisian self.callbacks = [] diff --git a/lib/python/Components/Makefile.am b/lib/python/Components/Makefile.am index fda58bf3..67cec18d 100644 --- a/lib/python/Components/Makefile.am +++ b/lib/python/Components/Makefile.am @@ -18,4 +18,4 @@ install_PYTHON = \ MultiContent.py MediaPlayer.py TunerInfo.py VideoWindow.py ChoiceList.py \ Element.py Playlist.py ParentalControl.py ParentalControlList.py \ Ipkg.py SelectionList.py Scanner.py SystemInfo.py DreamInfoHandler.py \ - Task.py language_cache.py Console.py + Task.py language_cache.py Console.py ResourceManager.py TuneTest.py diff --git a/lib/python/Components/MovieList.py b/lib/python/Components/MovieList.py index 8568f3d6..5c98e4be 100644 --- a/lib/python/Components/MovieList.py +++ b/lib/python/Components/MovieList.py @@ -93,10 +93,7 @@ class MovieList(GUIComponent): if len > 0: len = "%d:%02d" % (len / 60, len % 60) else: - if config.usage.load_length_of_movies_in_moviellist.value: - len = "?:??" - else: - len = "X:XX" + len = "" res = [ None ] diff --git a/lib/python/Components/MultiContent.py b/lib/python/Components/MultiContent.py index 71096df8..ff0219ff 100644 --- a/lib/python/Components/MultiContent.py +++ b/lib/python/Components/MultiContent.py @@ -1,5 +1,7 @@ from enigma import eListboxPythonMultiContent, RT_HALIGN_LEFT, RT_VALIGN_TOP +def MultiContentTemplateColor(n): return 0xff000000 | n + def MultiContentEntryText(pos = (0, 0), size = (0, 0), font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_TOP, text = "", color = None, color_sel = None, backcolor = None, backcolor_sel = None, border_width = None, border_color = None): return (eListboxPythonMultiContent.TYPE_TEXT, pos[0], pos[1], size[0], size[1], font, flags, text, color, color_sel, backcolor, backcolor_sel, border_width, border_color) diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py index f4e91083..4be10d53 100644 --- a/lib/python/Components/NimManager.py +++ b/lib/python/Components/NimManager.py @@ -14,8 +14,6 @@ from enigma import eDVBSatelliteEquipmentControl as secClass, \ from time import localtime, mktime from datetime import datetime -from sets import Set - def getConfigSatlist(orbpos, satlist): default_orbpos = None for x in satlist: @@ -39,7 +37,7 @@ 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, fastDiSEqC = False, setVoltageTone = True): + 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, diseqc13V = False): if orbpos is None or orbpos == 3601: return #simple defaults @@ -51,6 +49,8 @@ class SecConfigure: elif self.linked.has_key(slotid): for slot in self.linked[slotid]: tunermask |= (1 << slot) + sec.setLNBSatCR(-1) + sec.setLNBNum(1) sec.setLNBLOFL(9750000) sec.setLNBLOFH(10600000) sec.setLNBThreshold(11700000) @@ -70,7 +70,10 @@ class SecConfigure: if 0 <= diseqcmode < 3: self.addSatellite(sec, orbpos) if setVoltageTone: - sec.setVoltageMode(switchParam.HV) + if diseqc13V: + sec.setVoltageMode(switchParam.HV_13) + else: + sec.setVoltageMode(switchParam.HV) sec.setToneMode(switchParam.HILO) else: sec.setVoltageMode(switchParam._14V) @@ -90,7 +93,10 @@ class SecConfigure: for x in self.NimManager.satList: print "Add sat " + str(x[0]) self.addSatellite(sec, int(x[0])) - sec.setVoltageMode(switchParam.HV) + if diseqc13V: + sec.setVoltageMode(switchParam.HV_13) + else: + sec.setVoltageMode(switchParam.HV) sec.setToneMode(switchParam.HILO) sec.setRotorPosNum(0) # USALS @@ -115,7 +121,7 @@ class SecConfigure: def update(self): sec = secClass.getInstance() - self.configuredSatellites = Set() + self.configuredSatellites = set() sec.clear() ## this do unlinking NIMs too !! print "sec config cleared" @@ -172,24 +178,24 @@ class SecConfigure: print "diseqcmode: ", nim.diseqcMode.value if nim.diseqcMode.value == "single": #single if nim.simpleSingleSendDiSEqC.value: - 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.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, diseqc13V = nim.diseqc13V.value) else: - self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.NONE, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value) 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) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.A, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.B, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.SENDNO, diseqc13V = nim.diseqc13V.value) elif nim.diseqcMode.value == "diseqc_a_b": #DiSEqC A/B 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.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value) elif nim.diseqcMode.value == "diseqc_a_b_c_d": #DiSEqC A/B/C/D 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) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcA.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcB.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.AB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcC.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BA, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value) + self.addLNBSimple(sec, slotid = x, orbpos = nim.diseqcD.orbital_position, toneburstmode = diseqcParam.NO, diseqcmode = diseqcParam.V1_0, diseqcpos = diseqcParam.BB, fastDiSEqC = fastDiSEqC, setVoltageTone = setVoltageTone, diseqc13V = nim.diseqc13V.value) elif nim.diseqcMode.value == "positioner": #Positioner if nim.latitudeOrientation.value == "north": laValue = rotorParam.NORTH @@ -219,7 +225,8 @@ class SecConfigure: laDirection = laValue, turningSpeed = turning_speed, useInputPower = useInputPower, - inputPowerDelta = inputPowerDelta) + inputPowerDelta = inputPowerDelta, + diseqc13V = nim.diseqc13V.value) elif nim.configMode.value == "advanced": #advanced config self.updateAdvanced(sec, x) print "sec config completed" @@ -248,6 +255,9 @@ class SecConfigure: currLnb = config.Nims[slotid].advanced.lnb[x] sec.addLNB() + if x < 33: + sec.setLNBNum(x) + tunermask = 1 << slotid if self.equal.has_key(slotid): for slot in self.equal[slotid]: @@ -256,10 +266,32 @@ class SecConfigure: for slot in self.linked[slotid]: tunermask |= (1 << slot) + if currLnb.lof.value != "unicable": + sec.setLNBSatCR(-1) + if currLnb.lof.value == "universal_lnb": sec.setLNBLOFL(9750000) sec.setLNBLOFH(10600000) sec.setLNBThreshold(11700000) + elif currLnb.lof.value == "unicable": + sec.setLNBLOFL(9750000) + sec.setLNBLOFH(10600000) + sec.setLNBThreshold(11700000) + if currLnb.unicable.value == "unicable_user": + sec.setLNBSatCR(currLnb.satcruser.index) + sec.setLNBSatCRvco(currLnb.satcrvcouser[currLnb.satcruser.index].value*1000) + elif currLnb.unicable.value == "unicable_matrix": + manufacturer_name = currLnb.unicableMatrixManufacturer.value + manufacturer = currLnb.unicableMatrix[manufacturer_name] + product_name = manufacturer.product.value + sec.setLNBSatCR(manufacturer.scr[product_name].index) + sec.setLNBSatCRvco(manufacturer.vco[product_name][manufacturer.scr[product_name].index].value*1000) + elif currLnb.unicable.value == "unicable_lnb": + manufacturer_name = currLnb.unicableMatrixManufacturer.value + manufacturer = currLnb.unicableMatrix[manufacturer_name] + product_name = manufacturer.product.value + sec.setLNBSatCR(manufacturer.scr[product_name].index) + sec.setLNBSatCRvco(manufacturer.vco[product_name][manufacturer.scr[product_name].index].value*1000) elif currLnb.lof.value == "c_band": sec.setLNBLOFL(5150000) sec.setLNBLOFH(5150000) @@ -374,6 +406,8 @@ class SecConfigure: sec.setLNBSlotMask(tunermask) + sec.setLNBPrio(int(currLnb.prio.value)) + # finally add the orbital positions for y in lnbSat[x]: self.addSatellite(sec, y) @@ -383,7 +417,10 @@ class SecConfigure: satpos = y currSat = config.Nims[slotid].advanced.sat[satpos] if currSat.voltage.value == "polarization": - sec.setVoltageMode(switchParam.HV) + if config.Nims[slotid].diseqc13V.value: + sec.setVoltageMode(switchParam.HV_13) + else: + sec.setVoltageMode(switchParam.HV) elif currSat.voltage.value == "13V": sec.setVoltageMode(switchParam._14V) elif currSat.voltage.value == "18V": @@ -403,7 +440,7 @@ class SecConfigure: def __init__(self, nimmgr): self.NimManager = nimmgr - self.configuredSatellites = Set() + self.configuredSatellites = set() self.update() class NIM(object): @@ -880,61 +917,197 @@ def InitNimManager(nimmgr): for x in range(len(nimmgr.nim_slots)): config.Nims.append(ConfigSubsection()) + lnb_choices = { + "universal_lnb": _("Universal LNB"), + "unicable": _("Unicable"), + "c_band": _("C-Band"), + "user_defined": _("User defined")} + lnb_choices_default = "universal_lnb" + + unicablelnbproducts = { + "Humax": {"150 SCR":["1210","1420","1680","2040"]}, + "Inverto": {"IDLP-40UNIQD+S":["1680","1420","2040","1210"]}, + "Kathrein": {"UAS481":["1400","1516","1632","1748"]}, + "Kreiling": {"KR1440":["1680","1420","2040","1210"]}, + "Radix": {"Unicable LNB":["1680","1420","2040","1210"]}, + "Wisi": {"OC 05":["1210","1420","1680","2040"]}} + UnicableLnbManufacturers = unicablelnbproducts.keys() + UnicableLnbManufacturers.sort() + + unicablematrixproducts = { + "Ankaro": { + "UCS 51440":["1400","1632","1284","1516"], + "UCS 51820":["1400","1632","1284","1516","1864","2096","1748","1980"], + "UCS 51840":["1400","1632","1284","1516","1864","2096","1748","1980"], + "UCS 52240":["1400","1632"], + "UCS 52420":["1400","1632","1284","1516"], + "UCS 52440":["1400","1632","1284","1516"], + "UCS 91440":["1400","1632","1284","1516"], + "UCS 91820":["1400","1632","1284","1516","1864","2096","1748","1980"], + "UCS 91840":["1400","1632","1284","1516","1864","2096","1748","1980"], + "UCS 92240":["1400","1632"], + "UCS 92420":["1400","1632","1284","1516"], + "UCS 92440":["1400","1632","1284","1516"]}, + "DCT Delta": { + "SUM518":["1284","1400","1516","1632","1748","1864","1980","2096"], + "SUM918":["1284","1400","1516","1632","1748","1864","1980","2096"], + "SUM928":["1284","1400","1516","1632","1748","1864","1980","2096"]}, + "Inverto": { + "IDLP-UST11O-CUO1O-8PP":["1076","1178","1280","1382","1484","1586","1688","1790"]}, + "Kathrein": { + "EXR501":["1400","1516","1632","1748"], + "EXR551":["1400","1516","1632","1748"], + "EXR552":["1400","1516"]}, + "ROTEK": { + "EKL2/1":["1400","1516"], + "EKL2/1E":["0","0","1632","1748"]}, + "Smart": { + "DPA 51":["1284","1400","1516","1632","1748","1864","1980","2096"]}, + "Technisat": { + "TechniRouter 5/1x8 G":["1284","1400","1516","1632","1748","1864","1980","2096"], + "TechniRouter 5/1x8 K":["1284","1400","1516","1632","1748","1864","1980","2096"], + "TechniRouter 5/2x4 G":["1284","1400","1516","1632"], + "TechniRouter 5/2x4 K":["1284","1400","1516","1632"]}, + "Telstar": { + "SCR 5/1x8 G":["1284","1400","1516","1632","1748","1864","1980","2096"], + "SCR 5/1x8 K":["1284","1400","1516","1632","1748","1864","1980","2096"], + "SCR 5/2x4 G":["1284","1400","1516","1632"], + "SCR 5/2x4 K":["1284","1400","1516","1632"]}} + UnicableMatrixManufacturers = unicablematrixproducts.keys() + UnicableMatrixManufacturers.sort() + + unicable_choices = { + "unicable_lnb": _("Unicable LNB"), + "unicable_matrix": _("Unicable Martix"), + "unicable_user": "Unicable "+_("User defined")} + unicable_choices_default = "unicable_lnb" + + unicableLnb = ConfigSubDict() + for y in unicablelnbproducts: + products = unicablelnbproducts[y].keys() + products.sort() + unicableLnb[y] = ConfigSubsection() + unicableLnb[y].product = ConfigSelection(choices = products, default = products[0]) + unicableLnb[y].scr = ConfigSubDict() + unicableLnb[y].vco = ConfigSubDict() + for z in products: + scrlist = [] + vcolist = unicablelnbproducts[y][z] + unicableLnb[y].vco[z] = ConfigSubList() + for cnt in range(1,1+len(vcolist)): + scrlist.append(("%d" %cnt,"SCR %d" %cnt)) + vcofreq = int(vcolist[cnt-1]) + unicableLnb[y].vco[z].append(ConfigInteger(default=vcofreq, limits = (vcofreq, vcofreq))) + unicableLnb[y].scr[z] = ConfigSelection(choices = scrlist, default = scrlist[0][0]) + + unicableMatrix = ConfigSubDict() + + for y in unicablematrixproducts: + products = unicablematrixproducts[y].keys() + products.sort() + unicableMatrix[y] = ConfigSubsection() + unicableMatrix[y].product = ConfigSelection(choices = products, default = products[0]) + unicableMatrix[y].scr = ConfigSubDict() + unicableMatrix[y].vco = ConfigSubDict() + for z in products: + scrlist = [] + vcolist = unicablematrixproducts[y][z] + unicableMatrix[y].vco[z] = ConfigSubList() + for cnt in range(1,1+len(vcolist)): + vcofreq = int(vcolist[cnt-1]) + if vcofreq == 0: + scrlist.append(("%d" %cnt,"SCR %d " %cnt +_("not used"))) + else: + scrlist.append(("%d" %cnt,"SCR %d" %cnt)) + unicableMatrix[y].vco[z].append(ConfigInteger(default=vcofreq, limits = (vcofreq, vcofreq))) + unicableMatrix[y].scr[z] = ConfigSelection(choices = scrlist, default = scrlist[0][0]) + + advanced_lnb_satcruser_choices = [ ("1", "SatCR 1"), ("2", "SatCR 2"), ("3", "SatCR 3"), ("4", "SatCR 4"), + ("5", "SatCR 5"), ("6", "SatCR 6"), ("7", "SatCR 7"), ("8", "SatCR 8")] + + satcrvcouser = ConfigSubList() + satcrvcouser.append(ConfigInteger(default=1284, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=1400, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=1516, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=1632, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=1748, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=1864, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=1980, limits = (0, 9999))) + satcrvcouser.append(ConfigInteger(default=2096, limits = (0, 9999))) + + prio_list = [ ("-1", _("Auto")) ] + prio_list += [(str(prio), str(prio)) for prio in range(65)+range(14000,14065)+range(19000,19065)] + + advanced_lnb_csw_choices = [("none", _("None")), ("AA", _("AA")), ("AB", _("AB")), ("BA", _("BA")), ("BB", _("BB"))] + advanced_lnb_csw_choices += [(str(0xF0|y), "Input " + str(y+1)) for y in range(0, 16)] + + advanced_lnb_ucsw_choices = [("0", _("None"))] + [(str(y), "Input " + str(y)) for y in range(1, 17)] + + diseqc_mode_choices = [ + ("single", _("Single")), ("toneburst_a_b", _("Toneburst A/B")), + ("diseqc_a_b", _("DiSEqC A/B")), ("diseqc_a_b_c_d", _("DiSEqC A/B/C/D")), + ("positioner", _("Positioner"))] + + positioner_mode_choices = [("usals", _("USALS")), ("manual", _("manual"))] + + diseqc_satlist_choices = [(3601, _('nothing connected'), 1)] + nimmgr.satList + + longitude_orientation_choices = [("east", _("East")), ("west", _("West"))] + latitude_orientation_choices = [("north", _("North")), ("south", _("South"))] + turning_speed_choices = [("fast", _("Fast")), ("slow", _("Slow")), ("fast epoch", _("Fast epoch"))] + + advanced_satlist_choices = nimmgr.satList + [ + (3601, _('All Satellites')+' 1', 1), (3602, _('All Satellites')+' 2', 1), + (3603, _('All Satellites')+' 3', 1), (3604, _('All Satellites')+' 4', 1)] + advanced_lnb_choices = [("0", "not available")] + [(str(y), "LNB " + str(y)) for y in range(1, 33)] + advanced_voltage_choices = [("polarization", _("Polarization")), ("13V", _("13 V")), ("18V", _("18 V"))] + advanced_tonemode_choices = [("band", _("Band")), ("on", _("On")), ("off", _("Off"))] + advanced_lnb_toneburst_choices = [("none", _("None")), ("A", _("A")), ("B", _("B"))] + advanced_lnb_allsat_diseqcmode_choices = [("1_2", _("1.2"))] + advanced_lnb_diseqcmode_choices = [("none", _("None")), ("1_0", _("1.0")), ("1_1", _("1.1")), ("1_2", _("1.2"))] + advanced_lnb_commandOrder1_0_choices = [("ct", "committed, toneburst"), ("tc", "toneburst, committed")] + advanced_lnb_commandOrder_choices = [ + ("ct", "committed, toneburst"), ("tc", "toneburst, committed"), + ("cut", "committed, uncommitted, toneburst"), ("tcu", "toneburst, committed, uncommitted"), + ("uct", "uncommitted, committed, toneburst"), ("tuc", "toneburst, uncommitted, commmitted")] + advanced_lnb_diseqc_repeat_choices = [("none", _("None")), ("one", _("One")), ("two", _("Two")), ("three", _("Three"))] + advanced_lnb_fast_turning_btime = mktime(datetime(1970, 1, 1, 7, 0).timetuple()); + advanced_lnb_fast_turning_etime = mktime(datetime(1970, 1, 1, 19, 0).timetuple()); for slot in nimmgr.nim_slots: x = slot.slot nim = config.Nims[x] if slot.isCompatible("DVB-S"): - choices = { "nothing": _("nothing connected"), - "simple": _("simple"), - "advanced": _("advanced")} + config_mode_choices = [ ("nothing", _("nothing connected")), + ("simple", _("simple")), ("advanced", _("advanced"))] if len(nimmgr.getNimListOfType(slot.type, exception = x)) > 0: - choices["equal"] = _("equal to") - choices["satposdepends"] = _("second cable of motorized LNB") + config_mode_choices.append(("equal", _("equal to"))) + config_mode_choices.append(("satposdepends", _("second cable of motorized LNB"))) if len(nimmgr.canConnectTo(x)) > 0: - choices["loopthrough"] = _("loopthrough to") - nim.configMode = ConfigSelection(choices = choices, default = "nothing") - -# for y in nimmgr.nim_slots: -# if y.slot == 0: -# if not y.isCompatible("DVB-S"): -# # reset to simple -# nim.configMode.value = "simple" -# nim.configMode.save() - - nim.diseqcMode = ConfigSelection( - choices = [ - ("single", _("Single")), - ("toneburst_a_b", _("Toneburst A/B")), - ("diseqc_a_b", _("DiSEqC A/B")), - ("diseqc_a_b_c_d", _("DiSEqC A/B/C/D")), - ("positioner", _("Positioner"))], - default = "diseqc_a_b") - - choices = [] - for id in nimmgr.getNimListOfType("DVB-S"): - if id != x: - choices.append((str(id), nimmgr.getNimDescription(id))) - nim.connectedTo = ConfigSelection(choices = choices) - 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")), - ("manual", _("manual"))], - default = "usals") + config_mode_choices.append(("loopthrough", _("loopthrough to"))) + nim.configMode = ConfigSelection(config_mode_choices, "nothing") + + nim.diseqc13V = ConfigYesNo(False) + + nim.diseqcMode = ConfigSelection(diseqc_mode_choices, "diseqc_a_b") + + nim.connectedTo = ConfigSelection([(str(id), nimmgr.getNimDescription(id)) for id in nimmgr.getNimListOfType("DVB-S") if id != x]) + + nim.simpleSingleSendDiSEqC = ConfigYesNo(False) + nim.simpleDiSEqCSetVoltageTone = ConfigYesNo(True) + nim.simpleDiSEqCOnlyOnSatChange = ConfigYesNo(False) + nim.diseqcA = getConfigSatlist(192, diseqc_satlist_choices) + nim.diseqcB = getConfigSatlist(130, diseqc_satlist_choices) + nim.diseqcC = ConfigSatlist(list = diseqc_satlist_choices) + nim.diseqcD = ConfigSatlist(list = diseqc_satlist_choices) + nim.positionerMode = ConfigSelection(positioner_mode_choices, "usals") nim.longitude = ConfigFloat(default=[5,100], limits=[(0,359),(0,999)]) - nim.longitudeOrientation = ConfigSelection(choices={"east": _("East"), "west": _("West")}, default = "east") + nim.longitudeOrientation = ConfigSelection(longitude_orientation_choices, "east") 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.latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north") + nim.powerMeasurement = ConfigYesNo(True) 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") + nim.turningSpeed = ConfigSelection(turning_speed_choices, "fast") btime = datetime(1970, 1, 1, 7, 0); nim.fastTurningBegin = ConfigDateTime(default = mktime(btime.timetuple()), formatstring = _("%H:%M"), increment = 900) etime = datetime(1970, 1, 1, 19, 0); @@ -942,78 +1115,72 @@ def InitNimManager(nimmgr): # advanced config: nim.advanced = ConfigSubsection() - tmp = [(3601, _('All Satellites')+' 1', 1), (3602, _('All Satellites')+' 2', 1), (3603, _('All Satellites')+' 3', 1), (3604, _('All Satellites')+' 4', 1)] - nim.advanced.sats = getConfigSatlist(192,nimmgr.satList+tmp) + nim.advanced.sats = getConfigSatlist(192, advanced_satlist_choices) nim.advanced.sat = ConfigSubDict() - lnbs = [("0", "not available")] - for y in range(1, 33): - lnbs.append((str(y), "LNB " + str(y))) for x in nimmgr.satList: nim.advanced.sat[x[0]] = ConfigSubsection() - nim.advanced.sat[x[0]].voltage = ConfigSelection(choices={"polarization": _("Polarization"), "13V": _("13 V"), "18V": _("18 V")}, default = "polarization") - nim.advanced.sat[x[0]].tonemode = ConfigSelection(choices={"band": _("Band"), "on": _("On"), "off": _("Off")}, default = "band") - nim.advanced.sat[x[0]].usals = ConfigYesNo(default=True) + nim.advanced.sat[x[0]].voltage = ConfigSelection(advanced_voltage_choices, "polarization") + nim.advanced.sat[x[0]].tonemode = ConfigSelection(advanced_tonemode_choices, "band") + nim.advanced.sat[x[0]].usals = ConfigYesNo(True) nim.advanced.sat[x[0]].rotorposition = ConfigInteger(default=1, limits=(1, 255)) - nim.advanced.sat[x[0]].lnb = ConfigSelection(choices = lnbs) + nim.advanced.sat[x[0]].lnb = ConfigSelection(advanced_lnb_choices, "0") for x in range(3601, 3605): nim.advanced.sat[x] = ConfigSubsection() - nim.advanced.sat[x].voltage = ConfigSelection(choices={"polarization": _("Polarization"), "13V": _("13 V"), "18V": _("18 V")}, default = "polarization") - nim.advanced.sat[x].tonemode = ConfigSelection(choices={"band": _("Band"), "on": _("On"), "off": _("Off")}, default = "band") + nim.advanced.sat[x].voltage = ConfigSelection(advanced_voltage_choices, "polarization") + nim.advanced.sat[x].tonemode = ConfigSelection(advanced_tonemode_choices, "band") nim.advanced.sat[x].usals = ConfigYesNo(default=True) nim.advanced.sat[x].rotorposition = ConfigInteger(default=1, limits=(1, 255)) lnbnum = 33+x-3601 - nim.advanced.sat[x].lnb = ConfigSelection(choices = [("0", "not available"), (str(lnbnum), "LNB %d"%(lnbnum))], default="0") - - csw = [("none", _("None")), ("AA", _("AA")), ("AB", _("AB")), ("BA", _("BA")), ("BB", _("BB"))] - for y in range(0, 16): - csw.append((str(0xF0|y), "Input " + str(y+1))) - - ucsw = [("0", _("None"))] - for y in range(1, 17): - ucsw.append((str(y), "Input " + str(y))) + nim.advanced.sat[x].lnb = ConfigSelection([("0", "not available"), (str(lnbnum), "LNB %d"%(lnbnum))], "0") nim.advanced.lnb = ConfigSubList() nim.advanced.lnb.append(ConfigNothing()) + for x in range(1, 37): nim.advanced.lnb.append(ConfigSubsection()) - nim.advanced.lnb[x].lof = ConfigSelection(choices={"universal_lnb": _("Universal LNB"), "c_band": _("C-Band"), "user_defined": _("User defined")}, default="universal_lnb") + nim.advanced.lnb[x].lof = ConfigSelection(lnb_choices, lnb_choices_default) + nim.advanced.lnb[x].lofl = ConfigInteger(default=9750, limits = (0, 99999)) nim.advanced.lnb[x].lofh = ConfigInteger(default=10600, limits = (0, 99999)) nim.advanced.lnb[x].threshold = ConfigInteger(default=11700, limits = (0, 99999)) + + nim.advanced.lnb[x].unicable = ConfigSelection(unicable_choices, unicable_choices_default) + + nim.advanced.lnb[x].unicableLnb = unicableLnb # is this okay? all lnb use the same ConfigSubDict ? ! ? + nim.advanced.lnb[x].unicableLnbManufacturer = ConfigSelection(UnicableLnbManufacturers, UnicableLnbManufacturers[0]) + + nim.advanced.lnb[x].unicableMatrix = unicableMatrix # is this okay? all lnb use the same ConfigSubDict ? ! ? + nim.advanced.lnb[x].unicableMatrixManufacturer = ConfigSelection(UnicableMatrixManufacturers, UnicableMatrixManufacturers[0]) + + nim.advanced.lnb[x].satcruser = ConfigSelection(advanced_lnb_satcruser_choices, "1") + nim.advanced.lnb[x].satcrvcouser = satcrvcouser # is this okay? all lnb use the same ConfigSubDict ? ! ? + # nim.advanced.lnb[x].output_12v = ConfigSelection(choices = [("0V", _("0 V")), ("12V", _("12 V"))], default="0V") - nim.advanced.lnb[x].increased_voltage = ConfigYesNo(default=False) - nim.advanced.lnb[x].toneburst = ConfigSelection(choices = [("none", _("None")), ("A", _("A")), ("B", _("B"))], default = "none") + nim.advanced.lnb[x].increased_voltage = ConfigYesNo(False) + nim.advanced.lnb[x].toneburst = ConfigSelection(advanced_lnb_toneburst_choices, "none") if x > 32: - nim.advanced.lnb[x].diseqcMode = ConfigSelection(choices = [("1_2", _("1.2"))], default = "1_2") + nim.advanced.lnb[x].diseqcMode = ConfigSelection(advanced_lnb_allsat_diseqcmode_choices, "1_2") else: - nim.advanced.lnb[x].diseqcMode = ConfigSelection(choices = [("none", _("None")), ("1_0", _("1.0")), ("1_1", _("1.1")), ("1_2", _("1.2"))], default = "none") - nim.advanced.lnb[x].commitedDiseqcCommand = ConfigSelection(choices = csw) - nim.advanced.lnb[x].fastDiseqc = ConfigYesNo(default=False) - nim.advanced.lnb[x].sequenceRepeat = ConfigYesNo(default=False) - nim.advanced.lnb[x].commandOrder1_0 = ConfigSelection(choices = [("ct", "committed, toneburst"), ("tc", "toneburst, committed")], default = "ct") - nim.advanced.lnb[x].commandOrder = ConfigSelection(choices = [ - ("ct", "committed, toneburst"), - ("tc", "toneburst, committed"), - ("cut", "committed, uncommitted, toneburst"), - ("tcu", "toneburst, committed, uncommitted"), - ("uct", "uncommitted, committed, toneburst"), - ("tuc", "toneburst, uncommitted, commmitted")], - default="ct") - nim.advanced.lnb[x].uncommittedDiseqcCommand = ConfigSelection(choices = ucsw) - nim.advanced.lnb[x].diseqcRepeats = ConfigSelection(choices = [("none", _("None")), ("one", _("One")), ("two", _("Two")), ("three", _("Three"))], default = "none") + nim.advanced.lnb[x].diseqcMode = ConfigSelection(advanced_lnb_diseqcmode_choices, "none") + nim.advanced.lnb[x].commitedDiseqcCommand = ConfigSelection(advanced_lnb_csw_choices) + nim.advanced.lnb[x].fastDiseqc = ConfigYesNo(False) + nim.advanced.lnb[x].sequenceRepeat = ConfigYesNo(False) + nim.advanced.lnb[x].commandOrder1_0 = ConfigSelection(advanced_lnb_commandOrder1_0_choices, "ct") + nim.advanced.lnb[x].commandOrder = ConfigSelection(advanced_lnb_commandOrder_choices, "ct") + nim.advanced.lnb[x].uncommittedDiseqcCommand = ConfigSelection(advanced_lnb_ucsw_choices) + nim.advanced.lnb[x].diseqcRepeats = ConfigSelection(advanced_lnb_diseqc_repeat_choices, "none") nim.advanced.lnb[x].longitude = ConfigFloat(default = [5,100], limits = [(0,359),(0,999)]) - nim.advanced.lnb[x].longitudeOrientation = ConfigSelection(choices = [("east", _("East")), ("west", _("West"))], default = "east") + nim.advanced.lnb[x].longitudeOrientation = ConfigSelection(longitude_orientation_choices, "east") 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].latitudeOrientation = ConfigSelection(latitude_orientation_choices, "north") nim.advanced.lnb[x].powerMeasurement = ConfigYesNo(default=True) 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) - etime = datetime(1970, 1, 1, 19, 0); - nim.advanced.lnb[x].fastTurningEnd = ConfigDateTime(default=mktime(etime.timetuple()), formatstring = _("%H:%M"), increment = 600) + nim.advanced.lnb[x].turningSpeed = ConfigSelection(turning_speed_choices, "fast") + nim.advanced.lnb[x].fastTurningBegin = ConfigDateTime(default=advanced_lnb_fast_turning_btime, formatstring = _("%H:%M"), increment = 600) + nim.advanced.lnb[x].fastTurningEnd = ConfigDateTime(default=advanced_lnb_fast_turning_etime, formatstring = _("%H:%M"), increment = 600) + nim.advanced.lnb[x].prio = ConfigSelection(prio_list, "-1") elif slot.isCompatible("DVB-C"): nim.configMode = ConfigSelection( choices = { diff --git a/lib/python/Components/Renderer/Canvas.py b/lib/python/Components/Renderer/Canvas.py index bd7ffb5e..acf0dbf7 100644 --- a/lib/python/Components/Renderer/Canvas.py +++ b/lib/python/Components/Renderer/Canvas.py @@ -35,7 +35,7 @@ class Canvas(Renderer): self.instance.writeText(eRect(l[1], l[2], l[3], l[4]), gRGB(l[5]), gRGB(l[6]), l[7], l[8], l[9]) else: print "drawlist entry:", l - raise "invalid drawlist entry" + raise RuntimeError("invalid drawlist entry") def changed(self, what): self.pull_updates() diff --git a/lib/python/Components/ResourceManager.py b/lib/python/Components/ResourceManager.py new file mode 100644 index 00000000..fb6be4a8 --- /dev/null +++ b/lib/python/Components/ResourceManager.py @@ -0,0 +1,23 @@ +class ResourceManager: + def __init__(self): + self.resourceList = {} + + def addResource(self, name, resource): + print "adding Resource", name + self.resourceList[name] = resource + print "resources:", self.resourceList + + + def getResource(self, name): + if not self.hasResource(name): + return None + return self.resourceList[name] + + def hasResource(self, name): + return self.resourceList.has_key(name) + + def removeResource(self, name): + if self.hasResource(name): + del self.resourceList[name] + +resourcemanager = ResourceManager()
\ No newline at end of file diff --git a/lib/python/Components/Scanner.py b/lib/python/Components/Scanner.py index 766d1966..86a5431d 100644 --- a/lib/python/Components/Scanner.py +++ b/lib/python/Components/Scanner.py @@ -135,7 +135,7 @@ def scanDevice(mountpoint): from Components.Harddisk import harddiskmanager blockdev = mountpoint.rstrip("/").rsplit('/',1)[-1] - error, blacklisted, removable, is_cdrom, partitions = harddiskmanager.getBlockDevInfo(blockdev) + error, blacklisted, removable, is_cdrom, partitions, medium_found = harddiskmanager.getBlockDevInfo(blockdev) # now scan the paths for p in paths_to_scan: diff --git a/lib/python/Components/ServiceScan.py b/lib/python/Components/ServiceScan.py index 5a7b3dea..78cd758e 100644 --- a/lib/python/Components/ServiceScan.py +++ b/lib/python/Components/ServiceScan.py @@ -36,54 +36,58 @@ class ServiceScan: tp_text = "" if transponder: tp_type = transponder.getSystem() - if not tp_type[0]: - tp_type = tp_type[1] - if tp_type == iDVBFrontend.feSatellite: - network = _("Satellite") - tp = transponder.getDVBS() - if not tp[0]: - tp = tp[1] - orb_pos = tp.orbital_position - try: - sat_name = str(nimmgr.getSatDescription(orb_pos)) - except KeyError: - sat_name = "" - if orb_pos > 1800: # west - orb_pos = 3600 - orb_pos - h = _("W") - else: - h = _("E") - if sat_name.find("%d.%d" % (orb_pos/10, orb_pos%10)) != -1: - network = sat_name - else: - network = ("%s %d.%d %s") % (sat_name, orb_pos / 10, orb_pos % 10, h) - tp_text = ("%s %s %d%c / %d / %s") %( { 0 : "DVB-S", 1 : "DVB-S2" }[tp.system], - { 0 : "Auto", 1 : "QPSK", 2 : "M8PSK", 3 : "QAM16" }[tp.modulation], - tp.frequency/1000, - { 0 : 'H', 1 : 'V', 2 : 'L', 3 : 'R' }[tp.polarisation], - tp.symbol_rate/1000, - { 0 : "AUTO", 1 : "1/2", 2 : "2/3", 3 : "3/4", 4 : "5/6", - 5 : "7/8", 6 : "8/9", 7 : "3/5", 8 : "4/5", 9 : "9/10", - 15 : "NONE" }[tp.fec] ) - elif tp_type == iDVBFrontend.feCable: - network = _("Cable") - tp = transponder.getDVBC() - if not tp[0]: - tp = tp[1] - tp_text = ("DVB-C %s %d / %d / %s") %( { 0 : "AUTO", 1 : "QAM16", 2 : "QAM32", 3 : "QAM64", 4 : "QAM128", 5 : "QAM256" }[tp.modulation], - tp.frequency, - tp.symbol_rate/1000, - { 0 : "AUTO", 1 : "1/2", 2 : "2/3", 3 : "3/4", 4 : "5/6", 5 : "7/8", 6 : "8/9", 15 : "NONE" }[tp.fec_inner] ) - elif tp_type == iDVBFrontend.feTerrestrial: - network = _("Terrestrial") - tp = transponder.getDVBT() - if not tp[0]: - tp = tp[1] - tp_text = ("DVB-T %s %d %s") %( { 0 : "QPSK", 1 : "QAM16", 2 : "QAM64", 3 : "AUTO"}[tp.modulation], - tp.frequency, - { 0 : "Bw 8MHz", 1 : "Bw 7MHz", 2 : "Bw 6MHz", 3 : "Bw Auto" }[tp.bandwidth]) + if tp_type == iDVBFrontend.feSatellite: + network = _("Satellite") + tp = transponder.getDVBS() + orb_pos = tp.orbital_position + try: + sat_name = str(nimmgr.getSatDescription(orb_pos)) + except KeyError: + sat_name = "" + if orb_pos > 1800: # west + orb_pos = 3600 - orb_pos + h = _("W") else: - print "unknown transponder type in scanStatusChanged" + h = _("E") + if sat_name.find("%d.%d" % (orb_pos/10, orb_pos%10)) != -1: + network = sat_name + else: + network = ("%s %d.%d %s") % (sat_name, orb_pos / 10, orb_pos % 10, h) + tp_text = ("%s %s %d%c / %d / %s") %( { tp.System_DVB_S : "DVB-S", + tp.System_DVB_S2 : "DVB-S2" }.get(tp.system, tp.System_DVB_S), + { tp.Modulation_Auto : "Auto", tp.Modulation_QPSK : "QPSK", + tp.Modulation_8PSK : "8PSK", tp.Modulation_QAM16 : "QAM16" }.get(tp.modulation, tp.Modulation_QPSK), + tp.frequency/1000, + { tp.Polarisation_Horizontal : 'H', tp.Polarisation_Vertical : 'V', tp.Polarisation_CircularLeft : 'L', + tp.Polarisation_CircularRight : 'R' }.get(tp.polarisation, tp.Polarisation_Horizontal), + tp.symbol_rate/1000, + { tp.FEC_Auto : "AUTO", tp.FEC_1_2 : "1/2", tp.FEC_2_3 : "2/3", + tp.FEC_3_4 : "3/4", tp.FEC_5_6 : "5/6", tp.FEC_7_8 : "7/8", + tp.FEC_8_9 : "8/9", tp.FEC_3_5 : "3/5", tp.FEC_4_5 : "4/5", + tp.FEC_9_10 : "9/10", tp.FEC_None : "NONE" }.get(tp.fec, tp.FEC_Auto)) + elif tp_type == iDVBFrontend.feCable: + network = _("Cable") + tp = transponder.getDVBC() + tp_text = ("DVB-C %s %d / %d / %s") %( { tp.Modulation_Auto : "AUTO", + tp.Modulation_QAM16 : "QAM16", tp.Modulation_QAM32 : "QAM32", + tp.Modulation_QAM64 : "QAM64", tp.Modulation_QAM128 : "QAM128", + tp.Modulation_QAM256 : "QAM256" }.get(tp.modulation, tp.Modulation_Auto), + tp.frequency, + tp.symbol_rate/1000, + { tp.FEC_Auto : "AUTO", tp.FEC_1_2 : "1/2", tp.FEC_2_3 : "2/3", + tp.FEC_3_4 : "3/4", tp.FEC_5_6 : "5/6", tp.FEC_7_8 : "7/8", + tp.FEC_8_9 : "8/9", tp.FEC_None : "NONE" }.get(tp.fec_inner, tp.FEC_Auto)) + elif tp_type == iDVBFrontend.feTerrestrial: + network = _("Terrestrial") + tp = transponder.getDVBT() + tp_text = ("DVB-T %s %d %s") %( { tp.Modulation_QPSK : "QPSK", + tp.Modulation_QAM16 : "QAM16", tp.Modulation_QAM64 : "QAM64", + tp.Modulation_Auto : "AUTO" }.get(tp.modulation, tp.Modulation_Auto), + tp.frequency, + { tp.Bandwidth_8MHz : "Bw 8MHz", tp.Bandwidth_7MHz : "Bw 7MHz", tp.Bandwidth_6MHz : "Bw 6MHz", + tp.Bandwidth_Auto : "Bw Auto" }.get(tp.bandwidth, tp.Bandwidth_Auto)) + else: + print "unknown transponder type in scanStatusChanged" self.network.setText(network) self.transponder.setText(tp_text) diff --git a/lib/python/Components/Sources/List.py b/lib/python/Components/Sources/List.py index ef9c1c89..23b53957 100644 --- a/lib/python/Components/Sources/List.py +++ b/lib/python/Components/Sources/List.py @@ -17,6 +17,7 @@ to generate HTML.""" self.fonts = fonts self.disable_callbacks = False self.enableWrapAround = enableWrapAround + self.__style = "default" # style might be an optional string which can be used to define different visualisations in the skin def setList(self, list): self.__list = list @@ -27,7 +28,11 @@ to generate HTML.""" def entry_changed(self, index): if not self.disable_callbacks: self.downstream_elements.entry_changed(self, index) - + + def modifyEntry(self, index, data): + self.__list[index] = data + self.entry_changed(index) + def count(self): return len(self.__list) @@ -76,17 +81,21 @@ to generate HTML.""" self.index -= 1 self.setIndex(self.index) + @cached + def getStyle(self): + return self.__style + + def setStyle(self, style): + self.__style = style + self.changed((self.CHANGED_SPECIFIC, "style")) + + style = property(getStyle, setStyle) + def updateList(self, list): """Changes the list without changing the selection or emitting changed Events""" assert len(list) == len(self.__list) - print "get old index" old_index = self.index - print "disable callback" self.disable_callbacks = True - print "set list" self.list = list - print "set index" self.index = old_index - print "reenable callbacks" self.disable_callbacks = False - print "done" diff --git a/lib/python/Components/Sources/Progress.py b/lib/python/Components/Sources/Progress.py index b96065b3..d57a6179 100644 --- a/lib/python/Components/Sources/Progress.py +++ b/lib/python/Components/Sources/Progress.py @@ -12,5 +12,12 @@ class Progress(Source): def setValue(self, value): self.__value = value self.changed((self.CHANGED_ALL,)) + + def setRange(self, range = 100): + self.range = range + self.changed((self.CHANGED_ALL,)) + + def getRange(self): + return self.range value = property(getValue, setValue) diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index 9a768425..df94f8a6 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -127,9 +127,11 @@ class Task(object): self.cmd = None self.cwd = "/tmp" self.args = [ ] + self.cmdline = None self.task_progress_changed = None self.output_line = "" job.addTask(self) + self.container = None def setCommandline(self, cmd, args): self.cmd = cmd @@ -141,6 +143,9 @@ class Task(object): self.global_preconditions.append(ToolExistsPrecondition()) self.postconditions.append(ReturncodePostcondition()) + def setCmdline(self, cmdline): + self.cmdline = cmdline + def checkPreconditions(self, immediate = False): not_met = [ ] if immediate: @@ -166,13 +171,15 @@ class Task(object): self.container.stdoutAvail.append(self.processStdout) self.container.stderrAvail.append(self.processStderr) - assert self.cmd is not None - assert len(self.args) >= 1 - if self.cwd is not None: self.container.setCWD(self.cwd) - print "execute:", self.container.execute(self.cmd, *self.args), self.cmd, self.args + if not self.cmd and self.cmdline: + print "execute:", self.container.execute(self.cmdline), self.cmdline + else: + assert self.cmd is not None + assert len(self.args) >= 1 + print "execute:", self.container.execute(self.cmd, *self.args), ' '.join(self.args) if self.initial_input: self.writeInput(self.initial_input) @@ -205,7 +212,8 @@ class Task(object): self.finish() def abort(self): - self.container.kill() + if self.container: + self.container.kill() self.finish(aborted = True) def finish(self, aborted = False): diff --git a/lib/python/Components/TimerSanityCheck.py b/lib/python/Components/TimerSanityCheck.py index 031c9cae..99b2fba5 100644 --- a/lib/python/Components/TimerSanityCheck.py +++ b/lib/python/Components/TimerSanityCheck.py @@ -173,8 +173,7 @@ class TimerSanityCheck: 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"]] + return serviceInfo and serviceInfo["tuner_type"] or "" ref = timer.service_ref.ref if ref.flags & eServiceReference.isGroup: # service group ? @@ -200,7 +199,7 @@ class TimerSanityCheck: if timer == fakeRec[0] and fakeRec[1]: NavigationInstance.instance.stopRecordService(fakeRec[1]) fakeRecList.remove(fakeRec) - del fakeRec + fakeRec = None for entry in overlaplist: if entry[1] == timer: overlaplist.remove(entry) diff --git a/lib/python/Components/TuneTest.py b/lib/python/Components/TuneTest.py new file mode 100644 index 00000000..de7b0098 --- /dev/null +++ b/lib/python/Components/TuneTest.py @@ -0,0 +1,235 @@ +from enigma import eDVBFrontendParametersSatellite, eDVBFrontendParameters, eDVBResourceManager, eTimer + +class Tuner: + def __init__(self, frontend): + self.frontend = frontend + + # transponder = (frequency, symbolrate, polarisation, fec, inversion, orbpos, system, modulation) + # 0 1 2 3 4 5 6 7 + def tune(self, transponder): + if self.frontend: + print "tuning to transponder with data", transponder + parm = eDVBFrontendParametersSatellite() + parm.frequency = transponder[0] * 1000 + parm.symbol_rate = transponder[1] * 1000 + parm.polarisation = transponder[2] + parm.fec = transponder[3] + parm.inversion = transponder[4] + parm.orbital_position = transponder[5] + parm.system = transponder[6] + parm.modulation = transponder[7] + parm.rolloff = transponder[8] + parm.pilot = transponder[9] + feparm = eDVBFrontendParameters() + feparm.setDVBS(parm) + self.lastparm = feparm + self.frontend.tune(feparm) + + def retune(self): + if self.frontend: + self.frontend.tune(self.lastparm) + + def getTransponderData(self): + ret = { } + if self.frontend: + self.frontend.getTransponderData(ret, True) + return ret + +# tunes a list of transponders and checks, if they lock and optionally checks the onid/tsid combination +# 1) add transponders with addTransponder() +# 2) call run(<checkPIDs = True>) +# 3) finishedChecking() is called, when the run is finished +class TuneTest: + def __init__(self, feid, stopOnSuccess = -1, stopOnError = -1): + self.stopOnSuccess = stopOnSuccess + self.stopOnError = stopOnError + self.feid = feid + self.transponderlist = [] + self.currTuned = None + print "TuneTest for feid %d" % self.feid + if not self.openFrontend(): + self.oldref = self.session.nav.getCurrentlyPlayingServiceReference() + self.session.nav.stopService() # try to disable foreground service + if not self.openFrontend(): + if self.session.pipshown: # try to disable pip + self.session.pipshown = False + del self.session.pip + if not self.openFrontend(): + self.frontend = None # in normal case this should not happen + self.tuner = Tuner(self.frontend) + self.timer = eTimer() + self.timer.callback.append(self.updateStatus) + + def gotTsidOnid(self, tsid, onid): + print "******** got tsid, onid:", tsid, onid + if tsid is not None and onid is not None: + self.pidStatus = self.INTERNAL_PID_STATUS_SUCCESSFUL + self.tsid = tsid + self.onid = onid + else: + self.pidStatus = self.INTERNAL_PID_STATUS_FAILED + self.tsid = -1 + self.onid = -1 + self.timer.start(100, True) + + def updateStatus(self): + dict = {} + self.frontend.getFrontendStatus(dict) + stop = False + + print "status:", dict + if dict["tuner_state"] == "TUNING": + print "TUNING" + self.timer.start(100, True) + self.progressCallback((self.getProgressLength(), self.tuningtransponder, self.STATUS_TUNING, self.currTuned)) + elif self.checkPIDs and self.pidStatus == self.INTERNAL_PID_STATUS_NOOP: + print "2nd choice" + if dict["tuner_state"] == "LOCKED": + print "acquiring TSID/ONID" + self.raw_channel.requestTsidOnid(self.gotTsidOnid) + self.pidStatus = self.INTERNAL_PID_STATUS_WAITING + else: + self.pidStatus = self.INTERNAL_PID_STATUS_FAILED + elif self.checkPIDs and self.pidStatus == self.INTERNAL_PID_STATUS_WAITING: + print "waiting for pids" + else: + if dict["tuner_state"] == "LOSTLOCK" or dict["tuner_state"] == "FAILED": + self.tuningtransponder = self.nextTransponder() + self.failedTune.append([self.currTuned, self.oldTuned, "tune_failed"]) + if self.stopOnError != -1 and self.stopOnError <= len(self.failedTune): + stop = True + elif dict["tuner_state"] == "LOCKED": + pidsFailed = False + if self.checkPIDs: + if self.currTuned is not None: + if self.tsid != self.currTuned[8] or self.onid != self.currTuned[9]: + self.failedTune.append([self.currTuned, self.oldTuned, "pids_failed", {"real": (self.tsid, self.onid), "expected": (self.currTuned[8], self.currTuned[9])}]) + pidsFailed = True + else: + self.successfullyTune.append([self.currTuned, self.oldTuned]) + if self.stopOnSuccess != -1 and self.stopOnSuccess <= len(self.successfullyTune): + stop = True + elif not self.checkPIDs or (self.checkPids and not pidsFailed): + self.successfullyTune.append([self.currTuned, self.oldTuned]) + if self.stopOnSuccess != -1 and self.stopOnSuccess <= len(self.successfullyTune): + stop = True + self.tuningtransponder = self.nextTransponder() + else: + print "************* tuner_state:", dict["tuner_state"] + + self.progressCallback((self.getProgressLength(), self.tuningtransponder, self.STATUS_NOOP, self.currTuned)) + + if not stop: + self.tune() + if self.tuningtransponder < len(self.transponderlist) and not stop: + if self.pidStatus != self.INTERNAL_PID_STATUS_WAITING: + self.timer.start(100, True) + print "restart timer" + else: + print "not restarting timers (waiting for pids)" + else: + self.progressCallback((self.getProgressLength(), len(self.transponderlist), self.STATUS_DONE, self.currTuned)) + print "finishedChecking" + self.finishedChecking() + + def firstTransponder(self): + print "firstTransponder:" + index = 0 + if self.checkPIDs: + print "checkPIDs-loop" + # check for tsid != -1 and onid != -1 + print "index:", index + print "len(self.transponderlist):", len(self.transponderlist) + while (index < len(self.transponderlist) and (self.transponderlist[index][8] == -1 or self.transponderlist[index][9] == -1)): + index += 1 + print "FirstTransponder final index:", index + return index + + def nextTransponder(self): + print "getting next transponder", self.tuningtransponder + index = self.tuningtransponder + 1 + if self.checkPIDs: + print "checkPIDs-loop" + # check for tsid != -1 and onid != -1 + print "index:", index + print "len(self.transponderlist):", len(self.transponderlist) + while (index < len(self.transponderlist) and (self.transponderlist[index][8] == -1 or self.transponderlist[index][9] == -1)): + index += 1 + + print "next transponder index:", index + return index + + def finishedChecking(self): + print "finished testing" + print "successfull:", self.successfullyTune + print "failed:", self.failedTune + + def openFrontend(self): + res_mgr = eDVBResourceManager.getInstance() + if res_mgr: + self.raw_channel = res_mgr.allocateRawChannel(self.feid) + if self.raw_channel: + self.frontend = self.raw_channel.getFrontend() + if self.frontend: + return True + else: + print "getFrontend failed" + else: + print "getRawChannel failed" + else: + print "getResourceManager instance failed" + return False + + def tune(self): + print "tuning to", self.tuningtransponder + if self.tuningtransponder < len(self.transponderlist): + self.pidStatus = self.INTERNAL_PID_STATUS_NOOP + self.oldTuned = self.currTuned + self.currTuned = self.transponderlist[self.tuningtransponder] + self.tuner.tune(self.transponderlist[self.tuningtransponder]) + + INTERNAL_PID_STATUS_NOOP = 0 + INTERNAL_PID_STATUS_WAITING = 1 + INTERNAL_PID_STATUS_SUCCESSFUL = 2 + INTERNAL_PID_STATUS_FAILED = 3 + + def run(self, checkPIDs = False): + self.checkPIDs = checkPIDs + self.pidStatus = self.INTERNAL_PID_STATUS_NOOP + self.failedTune = [] + self.successfullyTune = [] + self.tuningtransponder = self.firstTransponder() + self.tune() + self.progressCallback((self.getProgressLength(), self.tuningtransponder, self.STATUS_START, self.currTuned)) + self.timer.start(100, True) + + # transponder = (frequency, symbolrate, polarisation, fec, inversion, orbpos, <system>, <modulation>, <tsid>, <onid>) + # 0 1 2 3 4 5 6 7 8 9 + def addTransponder(self, transponder): + self.transponderlist.append(transponder) + + def clearTransponder(self): + self.transponderlist = [] + + def getProgressLength(self): + count = 0 + if self.stopOnError == -1: + count = len(self.transponderlist) + else: + if count < self.stopOnError: + count = self.stopOnError + if self.stopOnSuccess == -1: + count = len(self.transponderlist) + else: + if count < self.stopOnSuccess: + count = self.stopOnSuccess + return count + + STATUS_START = 0 + STATUS_TUNING = 1 + STATUS_DONE = 2 + STATUS_NOOP = 3 + # can be overwritten + # progress = (range, value, status, transponder) + def progressCallback(self, progress): + pass
\ No newline at end of file diff --git a/lib/python/Components/TunerInfo.py b/lib/python/Components/TunerInfo.py index d8b4d064..39f54c0b 100644 --- a/lib/python/Components/TunerInfo.py +++ b/lib/python/Components/TunerInfo.py @@ -10,13 +10,14 @@ class TunerInfo(GUIComponent): BER = 2 LOCK = 3 SNR_PERCENTAGE = 0 - AGC_PERCENTAGE = 1 - BER_VALUE = 2 - SNR_BAR = 3 - AGC_BAR = 4 - BER_BAR = 5 - LOCK_STATE = 6 - SYNC_STATE = 7 + SNR_DB = 1 + AGC_PERCENTAGE = 2 + BER_VALUE = 3 + SNR_BAR = 4 + AGC_BAR = 5 + BER_BAR = 6 + LOCK_STATE = 7 + SYNC_STATE = 8 def __init__(self, type, servicefkt = None, frontendfkt = None, statusDict = None): GUIComponent.__init__(self) @@ -47,7 +48,9 @@ class TunerInfo(GUIComponent): return val*100/65535 def update(self): - if self.type == self.SNR_PERCENTAGE or self.type == self.SNR_BAR: + if self.type == self.SNR_DB: + value = self.getValue(self.SNR_DB) + elif self.type == self.SNR_PERCENTAGE or self.type == self.SNR_BAR: value = self.getValue(self.SNR) * 100 / 65536 elif self.type == self.AGC_PERCENTAGE or self.type == self.AGC_BAR: value = self.getValue(self.AGC) * 100 / 65536 @@ -55,8 +58,13 @@ class TunerInfo(GUIComponent): value = self.getValue(self.BER) elif self.type == self.LOCK_STATE: value = self.getValue(self.LOCK) - - if self.type == self.SNR_PERCENTAGE or self.type == self.AGC_PERCENTAGE: + + if self.type == self.SNR_DB: + if value != 0x12345678: + self.setText("%3.02f dB" % (value / 100.0)) + else: + self.setText("") + elif self.type == self.SNR_PERCENTAGE or self.type == self.AGC_PERCENTAGE: self.setText("%d%%" % (value)) elif self.type == self.BER_VALUE: self.setText("%d" % (value)) @@ -72,7 +80,9 @@ class TunerInfo(GUIComponent): def getValue(self, what): if self.statusDict: - if what == self.SNR: + if what == self.SNR_DB: + return self.statusDict.get("tuner_signal_quality_db", 0x12345678) + elif what == self.SNR: return self.statusDict.get("tuner_signal_quality", 0) elif what == self.AGC: return self.statusDict.get("tuner_signal_power", 0) @@ -85,7 +95,9 @@ class TunerInfo(GUIComponent): if service is not None: feinfo = service.frontendInfo() if feinfo is not None: - if what == self.SNR: + if what == self.SNR_DB: + return feinfo.getFrontendInfo(iFrontendInformation.signalQualitydB) + elif what == self.SNR: return feinfo.getFrontendInfo(iFrontendInformation.signalQuality) elif what == self.AGC: return feinfo.getFrontendInfo(iFrontendInformation.signalPower) @@ -96,7 +108,9 @@ class TunerInfo(GUIComponent): elif self.frontendfkt: frontend = self.frontendfkt() if frontend: - if what == self.SNR: + if what == self.SNR_DB: + return frontend.readFrontendData(iFrontendInformation.signalQualitydB) + elif what == self.SNR: return frontend.readFrontendData(iFrontendInformation.signalQuality) elif what == self.AGC: return frontend.readFrontendData(iFrontendInformation.signalPower) diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py index 6ed87840..21e057f2 100644 --- a/lib/python/Components/UsageConfig.py +++ b/lib/python/Components/UsageConfig.py @@ -17,12 +17,12 @@ def InitUsageConfig(): config.usage.show_infobar_on_zap = ConfigYesNo(default = True) config.usage.show_infobar_on_skip = ConfigYesNo(default = True) config.usage.show_infobar_on_event_change = ConfigYesNo(default = True) - config.usage.hdd_standby = ConfigSelection(default = "120", choices = [ - ("0", _("no standby")), ("2", "10 " + _("seconds")), ("6", "30 " + _("seconds")), - ("12", "1 " + _("minute")), ("24", "2 " + _("minutes")), - ("60", "5 " + _("minutes")), ("120", "10 " + _("minutes")), ("240", "20 " + _("minutes")), - ("241", "30 " + _("minutes")), ("242", "1 " + _("hour")), ("244", "2 " + _("hours")), - ("248", "4 " + _("hours")) ]) + config.usage.hdd_standby = ConfigSelection(default = "600", choices = [ + ("0", _("no standby")), ("10", "10 " + _("seconds")), ("30", "30 " + _("seconds")), + ("60", "1 " + _("minute")), ("120", "2 " + _("minutes")), + ("300", "5 " + _("minutes")), ("600", "10 " + _("minutes")), ("1200", "20 " + _("minutes")), + ("1800", "30 " + _("minutes")), ("3600", "1 " + _("hour")), ("7200", "2 " + _("hours")), + ("14400", "4 " + _("hours")) ]) config.usage.output_12V = ConfigSelection(default = "do not change", choices = [ ("do not change", _("do not change")), ("off", _("off")), ("on", _("on")) ]) @@ -66,7 +66,7 @@ def InitUsageConfig(): def setHDDStandby(configElement): for hdd in harddiskmanager.HDDList(): - os.system("hdparm -S%s %s" % (configElement.value, hdd[1].getDeviceName())) + hdd[1].setIdleTime(int(configElement.value)) config.usage.hdd_standby.addNotifier(setHDDStandby) def set12VOutput(configElement): @@ -89,8 +89,8 @@ def InitUsageConfig(): config.seek.speeds_backward = ConfigSet(default=[8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) config.seek.speeds_slowmotion = ConfigSet(default=[2, 4, 8], choices=[2, 4, 6, 8, 12, 16, 25]) - config.seek.enter_forward = ConfigSelection(default = "2", choices = ["2"]) - config.seek.enter_backward = ConfigSelection(default = "2", choices = ["2"]) + config.seek.enter_forward = ConfigSelection(default = "2", choices = ["2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) + config.seek.enter_backward = ConfigSelection(default = "1", choices = ["1", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) config.seek.stepwise_minspeed = ConfigSelection(default = "16", choices = ["Never", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) config.seek.stepwise_repeat = ConfigSelection(default = "3", choices = ["2", "3", "4", "5", "6"]) @@ -104,14 +104,14 @@ def InitUsageConfig(): configElement.value = [2] updateChoices(config.seek.enter_forward, configElement.value) - config.seek.speeds_forward.addNotifier(updateEnterForward) + config.seek.speeds_forward.addNotifier(updateEnterForward, immediate_feedback = False) def updateEnterBackward(configElement): if not configElement.value: configElement.value = [2] updateChoices(config.seek.enter_backward, configElement.value) - config.seek.speeds_backward.addNotifier(updateEnterBackward) + config.seek.speeds_backward.addNotifier(updateEnterBackward, immediate_feedback = False) def updateChoices(sel, choices): if choices: diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py index 4d57bbb9..eaf07180 100755 --- a/lib/python/Components/config.py +++ b/lib/python/Components/config.py @@ -1,10 +1,10 @@ -import time from enigma import getPrevAsciiCode from Tools.NumericalTextInput import NumericalTextInput from Tools.Directories import resolveFilename, SCOPE_CONFIG from Components.Harddisk import harddiskmanager -import copy -import os +from copy import copy as copy_copy +from os import path as os_path +from time import localtime, strftime # ConfigElement, the base class of all ConfigElements. @@ -28,11 +28,12 @@ import os # class ConfigElement(object): def __init__(self): - object.__init__(self) self.saved_value = None + self.last_value = None self.save_disabled = False self.notifiers = [] + self.notifiers_final = [] self.enabled = True self.callNotifiersOnSaveAndCancel = False @@ -85,10 +86,16 @@ class ConfigElement(object): for x in self.notifiers: x(self) - def addNotifier(self, notifier, initial_call = True): + def changedFinal(self): + for x in self.notifiers_final: + x(self) + + def addNotifier(self, notifier, initial_call = True, immediate_feedback = True): assert callable(notifier), "notifiers must be callable" - self.notifiers.append(notifier) - + if immediate_feedback: + self.notifiers.append(notifier) + else: + self.notifiers_final.append(notifier) # CHECKME: # do we want to call the notifier # - at all when adding it? (yes, though optional) @@ -110,7 +117,9 @@ class ConfigElement(object): pass def onDeselect(self, session): - pass + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value KEY_LEFT = 0 KEY_RIGHT = 1 @@ -130,6 +139,107 @@ def getKeyNumber(key): assert key in KEY_NUMBERS return key - KEY_0 +class choicesList(object): # XXX: we might want a better name for this + LIST_TYPE_LIST = 1 + LIST_TYPE_DICT = 2 + + def __init__(self, choices, type = None): + object.__init__(self) + self.choices = choices + if type is None: + if isinstance(choices, list): + self.type = choicesList.LIST_TYPE_LIST + elif isinstance(choices, dict): + self.type = choicesList.LIST_TYPE_DICT + else: + assert False, "choices must be dict or list!" + else: + self.type = type + + def __list__(self): + if self.type == choicesList.LIST_TYPE_LIST: + ret = [isinstance(x, tuple) and x[0] or x for x in self.choices] + else: + ret = self.choices.keys() + return ret or [""] + + def __iter__(self): + if self.type == choicesList.LIST_TYPE_LIST: + ret = [isinstance(x, tuple) and x[0] or x for x in self.choices] + else: + ret = self.choices + return iter(ret or [""]) + + def __len__(self): + return len(self.choices) or 1 + + def __getitem__(self, index): + if self.type == choicesList.LIST_TYPE_LIST: + ret = self.choices[index] + if isinstance(ret, tuple): + ret = ret[0] + return ret + return self.choices.keys()[index] + + def index(self, value): + return self.__list__().index(value) + + def __setitem__(self, index, value): + if self.type == choicesList.LIST_TYPE_LIST: + orig = self.choices[index] + if isinstance(orig, tuple): + self.choices[index] = (value, orig[1]) + else: + self.choices[index] = value + else: + key = self.choices.keys()[index] + orig = self.choices[key] + del self.choices[key] + self.choices[value] = orig + + def default(self): + if self.type is choicesList.LIST_TYPE_LIST: + default = self.choices[0] + if isinstance(default, tuple): + default = default[0] + else: + default = self.choices.keys()[0] + return default + +class descriptionList(choicesList): # XXX: we might want a better name for this + def __list__(self): + if self.type == choicesList.LIST_TYPE_LIST: + ret = [isinstance(x, tuple) and x[1] or x for x in self.choices] + else: + ret = self.choices.values() + return ret or [""] + + def __iter__(self): + return iter(self.__list__()) + + def __getitem__(self, index): + if self.type == choicesList.LIST_TYPE_LIST: + for x in self.choices: + if isinstance(x, tuple): + if x[0] == index: + return str(x[1]) + elif x == index: + return str(x) + return str(index) # Fallback! + else: + return str(self.choices.get(index, "")) + + def __setitem__(self, index, value): + if self.type == choicesList.LIST_TYPE_LIST: + i = self.index(index) + orig = self.choices[i] + if isinstance(orig, tuple): + self.choices[i] = (orig[0], value) + else: + self.choices[i] = value + else: + self.choices[index] = value + # # ConfigSelection is a "one of.."-type. # it has the "choices", usually a list, which contains @@ -141,43 +251,21 @@ def getKeyNumber(key): class ConfigSelection(ConfigElement): def __init__(self, choices, default = None): ConfigElement.__init__(self) - self._value = None - self.setChoices(choices, default) + self.choices = choicesList(choices) + + if default is None: + default = self.choices.default() + + self.default = self._value = self.last_value = default + self.changed() def setChoices(self, choices, default = None): - self.choices = [] - self.description = {} - - if isinstance(choices, list): - for x in choices: - if isinstance(x, tuple): - self.choices.append(x[0]) - self.description[x[0]] = x[1] - else: - self.choices.append(x) - self.description[x] = x - elif isinstance(choices, dict): - for (key, val) in choices.items(): - self.choices.append(key) - self.description[key] = val - else: - assert False, "ConfigSelection choices must be dict or list!" - - #assert len(self.choices), "you can't have an empty configselection" - if len(self.choices) == 0: - self.choices = [""] - self.description[""] = "" + self.choices = choicesList(choices) if default is None: - default = self.choices[0] - - assert default in self.choices, "default must be in choice list, but " + repr(default) + " is not!" - for x in self.choices: - assert isinstance(x, str), "ConfigSelection choices must be strings" - - self.default = default + default = self.choices.default() - if self.value == None or not self.value in self.choices: + if self.value not in self.choices: self.value = default def setValue(self, value): @@ -185,7 +273,6 @@ class ConfigSelection(ConfigElement): self._value = value else: self._value = self.default - self.changed() def tostring(self, val): @@ -196,7 +283,6 @@ class ConfigSelection(ConfigElement): def setCurrentText(self, text): i = self.choices.index(self.value) - del self.description[self.choices[i]] self.choices[i] = text self.description[text] = text self._value = text @@ -220,7 +306,7 @@ class ConfigSelection(ConfigElement): self.value = self.choices[0] elif key == KEY_END: self.value = self.choices[nchoices - 1] - + def selectNext(self): nchoices = len(self.choices) i = self.choices.index(self.value) @@ -242,27 +328,32 @@ class ConfigSelection(ConfigElement): def getHTML(self, id): res = "" for v in self.choices: + descr = self.description[v] if self.value == v: checked = 'checked="checked" ' else: checked = '' - res += '<input type="radio" name="' + id + '" ' + checked + 'value="' + v + '">' + self.description[v] + "</input></br>\n" + res += '<input type="radio" name="' + id + '" ' + checked + 'value="' + v + '">' + descr + "</input></br>\n" return res; def unsafeAssign(self, value): # setValue does check if value is in choices. This is safe enough. self.value = value + description = property(lambda self: descriptionList(self.choices.choices, self.choices.type)) + # a binary decision. # # several customized versions exist for different # descriptions. # +boolean_descriptions = {False: "false", True: "true"} class ConfigBoolean(ConfigElement): - def __init__(self, default = False, descriptions = {False: "false", True: "true"}): + def __init__(self, default = False, descriptions = boolean_descriptions): ConfigElement.__init__(self) self.descriptions = descriptions - self.value = self.default = default + self.value = self.last_value = self.default = default + def handleKey(self, key): if key in [KEY_LEFT, KEY_RIGHT]: self.value = not self.value @@ -309,24 +400,32 @@ class ConfigBoolean(ConfigElement): else: self.value = False + def onDeselect(self, session): + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value + +yes_no_descriptions = {False: _("no"), True: _("yes")} class ConfigYesNo(ConfigBoolean): def __init__(self, default = False): - ConfigBoolean.__init__(self, default = default, descriptions = {False: _("no"), True: _("yes")}) + ConfigBoolean.__init__(self, default = default, descriptions = yes_no_descriptions) +on_off_descriptions = {False: _("off"), True: _("on")} class ConfigOnOff(ConfigBoolean): def __init__(self, default = False): - ConfigBoolean.__init__(self, default = default, descriptions = {False: _("off"), True: _("on")}) + ConfigBoolean.__init__(self, default = default, descriptions = on_off_descriptions) +enable_disable_descriptions = {False: _("disable"), True: _("enable")} class ConfigEnableDisable(ConfigBoolean): def __init__(self, default = False): - ConfigBoolean.__init__(self, default = default, descriptions = {False: _("disable"), True: _("enable")}) + ConfigBoolean.__init__(self, default = default, descriptions = enable_disable_descriptions) class ConfigDateTime(ConfigElement): def __init__(self, default, formatstring, increment = 86400): ConfigElement.__init__(self) self.increment = increment self.formatstring = formatstring - self.value = self.default = int(default) + self.value = self.last_value = self.default = int(default) def handleKey(self, key): if key == KEY_LEFT: @@ -337,10 +436,10 @@ class ConfigDateTime(ConfigElement): self.value = self.default def getText(self): - return time.strftime(self.formatstring, time.localtime(self.value)) + return strftime(self.formatstring, localtime(self.value)) def getMulti(self, selected): - return ("text", time.strftime(self.formatstring, time.localtime(self.value))) + return ("text", strftime(self.formatstring, localtime(self.value))) def fromstring(self, val): return int(val) @@ -352,7 +451,7 @@ class ConfigDateTime(ConfigElement): # several helper exist to ease this up a bit. # class ConfigSequence(ConfigElement): - def __init__(self, seperator, limits, censor_char = "", default = None): + def __init__(self, seperator, limits, default, censor_char = ""): ConfigElement.__init__(self) assert isinstance(limits, list) and len(limits[0]) == 2, "limits must be [(min, max),...]-tuple-list" assert censor_char == "" or len(censor_char) == 1, "censor char must be a single char (or \"\")" @@ -364,11 +463,10 @@ class ConfigSequence(ConfigElement): self.seperator = seperator self.limits = limits self.censor_char = censor_char - - self.default = default - self.value = copy.copy(default) - - self.endNotifier = [] + + self.last_value = self.default = default + self.value = copy_copy(default) + self.endNotifier = None def validate(self): max_pos = 0 @@ -385,8 +483,9 @@ class ConfigSequence(ConfigElement): num += 1 if self.marked_pos >= max_pos: - for x in self.endNotifier: - x(self) + if endNotifier: + for x in self.endNotifier: + x(self) self.marked_pos = max_pos - 1 if self.marked_pos < 0: @@ -395,13 +494,15 @@ class ConfigSequence(ConfigElement): def validatePos(self): if self.marked_pos < 0: self.marked_pos = 0 - + total_len = sum([len(str(x[1])) for x in self.limits]) if self.marked_pos >= total_len: self.marked_pos = total_len - 1 - + def addEndNotifier(self, notifier): + if endNotifier is None: + endNotifier = [] self.endNotifier.append(notifier) def handleKey(self, key): @@ -412,7 +513,7 @@ class ConfigSequence(ConfigElement): if key == KEY_RIGHT: self.marked_pos += 1 self.validatePos() - + if key == KEY_HOME: self.marked_pos = 0 self.validatePos() @@ -425,7 +526,7 @@ class ConfigSequence(ConfigElement): num += 1 self.marked_pos = max_pos - 1 self.validatePos() - + if key in KEY_NUMBERS or key == KEY_ASCII: if key == KEY_ASCII: code = getPrevAsciiCode() @@ -434,11 +535,11 @@ class ConfigSequence(ConfigElement): number = code - 48 else: number = getKeyNumber(key) - + block_len = [] for x in self.limits: block_len.append(len(str(x[1]))) - + total_len = sum(block_len) pos = 0 @@ -457,17 +558,17 @@ class ConfigSequence(ConfigElement): # position in the block posinblock = self.marked_pos - block_len_total[blocknumber] - + oldvalue = self._value[blocknumber] olddec = oldvalue % 10 ** (number_len - posinblock) - (oldvalue % 10 ** (number_len - posinblock - 1)) newvalue = oldvalue - olddec + (10 ** (number_len - posinblock - 1) * number) - + self._value[blocknumber] = newvalue self.marked_pos += 1 - + self.validate() self.changed() - + def genText(self): value = "" mPos = self.marked_pos @@ -477,18 +578,17 @@ class ConfigSequence(ConfigElement): value += self.seperator if mPos >= len(value) - 1: mPos += 1 - if self.censor_char == "": value += ("%0" + str(len(str(self.limits[num][1]))) + "d") % i else: value += (self.censor_char * len(str(self.limits[num][1]))) num += 1 return (value, mPos) - + def getText(self): (value, mPos) = self.genText() return value - + def getMulti(self, selected): (value, mPos) = self.genText() # only mark cursor when we are selected @@ -500,16 +600,22 @@ class ConfigSequence(ConfigElement): def tostring(self, val): return self.seperator.join([self.saveSingle(x) for x in val]) - + def saveSingle(self, v): return str(v) def fromstring(self, value): return [int(x) for x in value.split(self.seperator)] + def onDeselect(self, session): + if self.last_value != self._value: + self.changedFinal() + self.last_value = copy_copy(self._value) + +ip_limits = [(0,255),(0,255),(0,255),(0,255)] class ConfigIP(ConfigSequence): def __init__(self, default, auto_jump = False): - ConfigSequence.__init__(self, seperator = ".", limits = [(0,255),(0,255),(0,255),(0,255)], default = default) + ConfigSequence.__init__(self, seperator = ".", limits = ip_limits, default = default) self.block_len = [] for x in self.limits: self.block_len.append(len(str(x[1]))) @@ -590,22 +696,54 @@ class ConfigIP(ConfigSequence): # we definitely don't want leading zeros return '.'.join(["%d" % d for d in self.value]) +mac_limits = [(1,255),(1,255),(1,255),(1,255),(1,255),(1,255)] class ConfigMAC(ConfigSequence): def __init__(self, default): - ConfigSequence.__init__(self, seperator = ":", limits = [(1,255),(1,255),(1,255),(1,255),(1,255),(1,255)], default = default) + ConfigSequence.__init__(self, seperator = ":", limits = mac_limits, default = default) class ConfigPosition(ConfigSequence): def __init__(self, default, args): ConfigSequence.__init__(self, seperator = ",", limits = [(0,args[0]),(0,args[1]),(0,args[2]),(0,args[3])], default = default) +clock_limits = [(0,23),(0,59)] class ConfigClock(ConfigSequence): def __init__(self, default): - import time - t = time.localtime(default) - ConfigSequence.__init__(self, seperator = ":", limits = [(0,23),(0,59)], default = [t.tm_hour, t.tm_min]) + t = localtime(default) + ConfigSequence.__init__(self, seperator = ":", limits = clock_limits, default = [t.tm_hour, t.tm_min]) + + def increment(self): + # Check if Minutes maxed out + if self._value[1] == 59: + # Increment Hour, reset Minutes + if self._value[0] < 23: + self._value[0] += 1 + else: + self._value[0] = 0 + self._value[1] = 0 + else: + # Increment Minutes + self._value[1] += 1 + # Trigger change + self.changed() + + def decrement(self): + # Check if Minutes is minimum + if self._value[1] == 0: + # Decrement Hour, set Minutes to 59 + if self._value[0] > 0: + self._value[0] -= 1 + else: + self._value[0] = 23 + self._value[1] = 59 + else: + # Decrement Minutes + self._value[1] -= 1 + # Trigger change + self.changed() +integer_limits = (0, 9999999999) class ConfigInteger(ConfigSequence): - def __init__(self, default, limits = (0, 9999999999)): + def __init__(self, default, limits = integer_limits): ConfigSequence.__init__(self, seperator = ":", limits = [limits], default = default) # you need to override this to do input validation @@ -615,7 +753,7 @@ class ConfigInteger(ConfigSequence): def getValue(self): return self._value[0] - + value = property(getValue, setValue) def fromstring(self, value): @@ -657,7 +795,7 @@ class ConfigText(ConfigElement, NumericalTextInput): self.offset = 0 self.overwrite = fixed_size self.help_window = None - self.value = self.default = default + self.value = self.last_value = self.default = default def validateMarker(self): if self.fixed_size: @@ -823,6 +961,9 @@ class ConfigText(ConfigElement, NumericalTextInput): if self.help_window: session.deleteDialog(self.help_window) self.help_window = None + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value def getHTML(self, id): return '<input type="text" name="' + id + '" value="' + self.value + '" /><br>\n' @@ -897,12 +1038,40 @@ class ConfigNumber(ConfigText): def onDeselect(self, session): self.marked_pos = 0 self.offset = 0 + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value + +class ConfigSearchText(ConfigText): + def __init__(self, default = "", fixed_size = False, visible_width = False): + ConfigText.__init__(self, default = default, fixed_size = fixed_size, visible_width = visible_width) + NumericalTextInput.__init__(self, nextFunc = self.nextFunc, handleTimeout = False, search = True) + +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) # a slider. class ConfigSlider(ConfigElement): def __init__(self, default = 0, increment = 1, limits = (0, 100)): ConfigElement.__init__(self) - self.value = self.default = default + self.value = self.last_value = self.default = default self.min = limits[0] self.max = limits[1] self.increment = increment @@ -954,28 +1123,17 @@ class ConfigSatlist(ConfigSelection): class ConfigSet(ConfigElement): def __init__(self, choices, default = []): ConfigElement.__init__(self) - self.choices = [] - self.description = {} if isinstance(choices, list): choices.sort() - for x in choices: - if isinstance(x, tuple): - self.choices.append(x[0]) - self.description[x[0]] = str(x[1]) - else: - self.choices.append(x) - self.description[x] = str(x) + self.choices = choicesList(choices, choicesList.LIST_TYPE_LIST) else: assert False, "ConfigSet choices must be a list!" - if len(self.choices) == 0: - self.choices = [""] - self.description[""] = "" if default is None: default = [] self.pos = -1 default.sort() - self.default = default - self.value = default+[] + self.last_value = self.default = default + self.value = default[:] def toggleChoice(self, choice): if choice in self.value: @@ -983,6 +1141,7 @@ class ConfigSet(ConfigElement): else: self.value.append(choice) self.value.sort() + self.changed() def handleKey(self, key): if key in KEY_NUMBERS + [KEY_DELETE, KEY_BACKSPACE]: @@ -1012,7 +1171,7 @@ class ConfigSet(ConfigElement): if not selected or self.pos == -1: return ("text", self.genString(self.value)) else: - tmp = self.value+[] + tmp = self.value[:] ch = self.choices[self.pos] mem = ch in self.value if not mem: @@ -1029,7 +1188,9 @@ class ConfigSet(ConfigElement): def onDeselect(self, session): self.pos = -1 - self.changed() + if not self.last_value == self.value: + self.changedFinal() + self.last_value = self.value[:] def tostring(self, value): return str(value) @@ -1037,6 +1198,8 @@ class ConfigSet(ConfigElement): def fromstring(self, val): return eval(val) + description = property(lambda self: descriptionList(self.choices.choices, choicesList.LIST_TYPE_LIST)) + class ConfigLocations(ConfigElement): def __init__(self, default = [], visible_width = False): ConfigElement.__init__(self) @@ -1046,6 +1209,7 @@ class ConfigLocations(ConfigElement): self.locations = [] self.mountpoints = [] harddiskmanager.on_partition_list_change.append(self.mountpointsChanged) + self.value = default+[] def setValue(self, value): loc = [x[0] for x in self.locations if x[3]] @@ -1078,7 +1242,7 @@ class ConfigLocations(ConfigElement): self.locations = [[x, None, False, False] for x in tmp] self.refreshMountpoints() for x in self.locations: - if os.path.exists(x[0]): + if os_path.exists(x[0]): x[1] = self.getMountpoint(x[0]) x[2] = True @@ -1107,7 +1271,7 @@ class ConfigLocations(ConfigElement): for x in self.locations: if x[1] == mp: x[2] = True - elif x[1] == None and os.path.exists(x[0]): + elif x[1] == None and os_path.exists(x[0]): x[1] = self.getMountpoint(x[0]) x[2] = True @@ -1133,7 +1297,7 @@ class ConfigLocations(ConfigElement): self.addedMount(x) def getMountpoint(self, file): - file = os.path.realpath(file)+"/" + file = os_path.realpath(file)+"/" for m in self.mountpoints: if file.startswith(m): return m @@ -1230,7 +1394,7 @@ class ConfigSubList(list, object): x.load() def getSavedValue(self): - res = {} + res = { } for i in range(len(self)): sv = self[i].saved_value if sv is not None: @@ -1253,10 +1417,7 @@ class ConfigSubList(list, object): item.load() def dict(self): - res = dict() - for index in range(len(self)): - res[str(index)] = self[index] - return res + return dict([(str(index), value) for index, value in self.enumerate()]) # same as ConfigSubList, just as a dictionary. # care must be taken that the 'key' has a proper @@ -1322,11 +1483,12 @@ class ConfigSubsection(object): def __setattr__(self, name, value): if name == "saved_value": return self.setSavedValue(value) - assert isinstance(value, ConfigSubsection) or isinstance(value, ConfigElement) or isinstance(value, ConfigSubList) or isinstance(value, ConfigSubDict), "ConfigSubsections can only store ConfigSubsections, ConfigSubLists, ConfigSubDicts or ConfigElements" + assert isinstance(value, (ConfigSubsection, ConfigElement, ConfigSubList, ConfigSubDict)), "ConfigSubsections can only store ConfigSubsections, ConfigSubLists, ConfigSubDicts or ConfigElements" self.content.items[name] = value - if name in self.content.stored_values: - #print "ok, now we have a new item,", name, "and have the following value for it:", self.content.stored_values[name] - value.saved_value = self.content.stored_values[name] + x = self.content.stored_values.get(name, None) + if x is not None: + #print "ok, now we have a new item,", name, "and have the following value for it:", x + value.saved_value = x value.load() def __getattr__(self, name): @@ -1344,12 +1506,11 @@ class ConfigSubsection(object): def setSavedValue(self, values): values = dict(values) - self.content.stored_values = values - for (key, val) in self.content.items.items(): - if key in values: - val.saved_value = values[key] + value = values.get(key, None) + if value is not None: + val.saved_value = value saved_value = property(getSavedValue, setSavedValue) @@ -1377,19 +1538,18 @@ class Config(ConfigSubsection): def pickle_this(self, prefix, topickle, result): for (key, val) in topickle.items(): - name = prefix + "." + key - + name = ''.join((prefix, '.', key)) if isinstance(val, dict): self.pickle_this(name, val, result) elif isinstance(val, tuple): - result.append(name + "=" + val[0]) # + " ; " + val[1]) + result += [name, '=', val[0], '\n'] else: - result.append(name + "=" + val) + result += [name, '=', val, '\n'] def pickle(self): - result = [ ] + result = [] self.pickle_this("config", self.saved_value, result) - return '\n'.join(result) + "\n" + return ''.join(result) def unpickle(self, lines): tree = { } diff --git a/lib/python/Components/language_cache.py b/lib/python/Components/language_cache.py index 046f281d..a9c02bc0 100644 --- a/lib/python/Components/language_cache.py +++ b/lib/python/Components/language_cache.py @@ -4,6 +4,7 @@ LANG_TEXT = { "fr_FR": "French", "fi_FI": "Finnish", "pt_PT": "Portuguese", + "fy_x-FY": "Frisian", "it_IT": "Italian", "no_NO": "Norwegian", "nl_NL": "Dutch", @@ -21,6 +22,7 @@ LANG_TEXT = { "tr_TR": "Turkish", "de_DE": "German", "ar_AE": "Arabic", + "uk_UA": "Ukrainian", "sv_SE": "Swedish", "pl_PL": "Polish", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -30,6 +32,7 @@ LANG_TEXT = { "fr_FR": "Französisch", "fi_FI": "Finnisch", "pt_PT": "portugiesisch", + "fy_x-FY": "Frisian", "it_IT": "Italienisch", "no_NO": "Norwegisch", "nl_NL": "Holländisch", @@ -47,6 +50,7 @@ LANG_TEXT = { "tr_TR": "Türkisch", "de_DE": "Deutsch", "ar_AE": "Arabisch", + "uk_UA": "Ukrainian", "sv_SE": "Schwedisch", "pl_PL": "Polnisch", "T1": "Bitte benutzen Sie die Hoch/Runter-Tasten, um Ihre Sprache auszuwählen. Danach drücken Sie bitte OK.", @@ -56,6 +60,7 @@ LANG_TEXT = { "fr_FR": "French", "fi_FI": "Finnish", "pt_PT": "Portuguese", + "fy_x-FY": "Frisian", "it_IT": "Italian", "no_NO": "Norwegian", "nl_NL": "Dutch", @@ -73,6 +78,7 @@ LANG_TEXT = { "tr_TR": "Turkish", "de_DE": "المانـى", "ar_AE": "Arabic", + "uk_UA": "Ukrainian", "sv_SE": "Swedish", "pl_PL": "Polish", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -82,6 +88,7 @@ LANG_TEXT = { "fr_FR": "Francès", "fi_FI": "Finlandès", "pt_PT": "Portuguès", + "fy_x-FY": "Frisian", "it_IT": "Italià", "no_NO": "Noruec", "nl_NL": "Holandès", @@ -99,6 +106,7 @@ LANG_TEXT = { "tr_TR": "Turc", "de_DE": "Alemany", "ar_AE": "Àrab", + "uk_UA": "Ukrainian", "sv_SE": "Suec", "pl_PL": "Polish", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -108,6 +116,7 @@ LANG_TEXT = { "fr_FR": "Francuski", "fi_FI": "Finski", "pt_PT": "Portugalski", + "fy_x-FY": "Frisian", "it_IT": "Talijanski", "no_NO": "Norveški", "nl_NL": "Nizozemski", @@ -125,6 +134,7 @@ LANG_TEXT = { "tr_TR": "Turski", "de_DE": "Njemački", "ar_AE": "Arabski", + "uk_UA": "Ukrainian", "sv_SE": "Švedski", "pl_PL": "Poljski", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -134,6 +144,7 @@ LANG_TEXT = { "fr_FR": "Francouzsky", "fi_FI": "Finsky", "pt_PT": "Portugalsky", + "fy_x-FY": "Frisian", "it_IT": "Italsky", "no_NO": "Norsky", "nl_NL": "Holandsky", @@ -151,6 +162,7 @@ LANG_TEXT = { "tr_TR": "Turecky", "de_DE": "Německy", "ar_AE": "Arabsky", + "uk_UA": "Ukrainian", "sv_SE": "Švédsky", "pl_PL": "Polsky", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -160,6 +172,7 @@ LANG_TEXT = { "fr_FR": "Fransk", "fi_FI": "Finsk", "pt_PT": "Portugisisk", + "fy_x-FY": "Frisian", "it_IT": "Italiensk", "no_NO": "Norsk", "nl_NL": "Hollandsk", @@ -177,6 +190,7 @@ LANG_TEXT = { "tr_TR": "Tyrkisk", "de_DE": "Tysk", "ar_AE": "Arabisk", + "uk_UA": "Ukrainian", "sv_SE": "Svensk", "pl_PL": "Polsk", "T1": "Benyt venligst OP og NED tasten til at vælge sprog. Tryk bagefter på OK knappen.", @@ -186,6 +200,7 @@ LANG_TEXT = { "fr_FR": "Frans", "fi_FI": "Fins", "pt_PT": "Portugees", + "fy_x-FY": "Frisian", "it_IT": "Italiaans", "no_NO": "Noors", "nl_NL": "Nederlands", @@ -203,6 +218,7 @@ LANG_TEXT = { "tr_TR": "Turks", "de_DE": "Duits", "ar_AE": "Arabisch", + "uk_UA": "Ukrainian", "sv_SE": "Zweeds", "pl_PL": "Pools", "T1": "Gebruik de omhoog/omlaag toeten om de gewenste taal te selecteren. Druk daarna op OK.", @@ -212,6 +228,7 @@ LANG_TEXT = { "fr_FR": "Ranska", "fi_FI": "Suomi", "pt_PT": "Portugali", + "fy_x-FY": "Frisian", "it_IT": "Italia", "no_NO": "Norja", "nl_NL": "Hollanti", @@ -229,15 +246,17 @@ LANG_TEXT = { "tr_TR": "Turkki", "de_DE": "Saksa", "ar_AE": "Arabia", + "uk_UA": "Ukrainian", "sv_SE": "Ruotsi", "pl_PL": "Puola", - "T1": "Valitse kieli ylös/alas nappuloilla ja paina OK.", + "T1": "Valitse kieli ylös/alas näppäimillä ja paina OK-näppäintä.", "T2": "Kielivalinta", }, "fr_FR": { "fr_FR": "Français", "fi_FI": "Finlandais", "pt_PT": "Portugais", + "fy_x-FY": "Frisian", "it_IT": "Italien", "no_NO": "Norvégien", "nl_NL": "Hollandais", @@ -255,6 +274,7 @@ LANG_TEXT = { "tr_TR": "Turke", "de_DE": "Allemand", "ar_AE": "Arabe", + "uk_UA": "Ukrainian", "sv_SE": "Suédois", "pl_PL": "Polonais", "T1": "Veuillez utiliser les touches HAUT et BAS pour choisir votre langage. Ensuite presser le bouton OK.", @@ -264,6 +284,7 @@ LANG_TEXT = { "fr_FR": "Γαλλικά", "fi_FI": "Φιλλανδικά", "pt_PT": "Πορτογαλλικά", + "fy_x-FY": "Frisian", "it_IT": "Ιταλικά", "no_NO": "Νορβηφικά", "nl_NL": "Ολλανδικά", @@ -281,6 +302,7 @@ LANG_TEXT = { "tr_TR": "Τούρκικα", "de_DE": "Γερμανικά", "ar_AE": "Αραβικά", + "uk_UA": "Ukrainian", "sv_SE": "Σουιδεζικά", "pl_PL": "Πολωνικά", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -290,6 +312,7 @@ LANG_TEXT = { "fr_FR": "Francia", "fi_FI": "Finn", "pt_PT": "Portugál", + "fy_x-FY": "Frisian", "it_IT": "Olasz", "no_NO": "Norvég", "nl_NL": "Holland", @@ -307,6 +330,7 @@ LANG_TEXT = { "tr_TR": "Török", "de_DE": "Német", "ar_AE": "Arab", + "uk_UA": "Ukrainian", "sv_SE": "Svéd", "pl_PL": "Lengyel", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -316,6 +340,7 @@ LANG_TEXT = { "fr_FR": "Prancūzų", "fi_FI": "Suomių", "pt_PT": "Portugalų", + "fy_x-FY": "Frisian", "it_IT": "Italų", "no_NO": "Norvegų", "nl_NL": "Olandų", @@ -333,6 +358,7 @@ LANG_TEXT = { "tr_TR": "Turkų", "de_DE": "Vokiečių", "ar_AE": "Arabų", + "uk_UA": "Ukrainiečių", "sv_SE": "Švedų", "pl_PL": "Lenkų", "T1": "Prašome naudoti AUKŠTYN IR ŽEMYN mygtukus, kad išsirinktumėte savo kalbą. Po to spauskite OK mygtuką.", @@ -342,6 +368,7 @@ LANG_TEXT = { "fr_FR": "Franska", "fi_FI": "Finnska", "pt_PT": "Portúgalska", + "fy_x-FY": "Frisian", "it_IT": "Ítalska", "no_NO": "Norska", "nl_NL": "Hollenska", @@ -359,15 +386,17 @@ LANG_TEXT = { "tr_TR": "Tyrkneska", "de_DE": "Þýska", "ar_AE": "Arabíska", + "uk_UA": "Ukrainian", "sv_SE": "Sænskt", "pl_PL": "Pólska", - "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", + "T1": "Vinsamlega notið UP og NIÐUR takka til að velja tungumál. Ýttu svo á OK til að nota.", "T2": "Val tungumáls", }, "it_IT": { "fr_FR": "Francese", "fi_FI": "Finlandese", "pt_PT": "Portoghese", + "fy_x-FY": "Frisian", "it_IT": "Italiano", "no_NO": "Norvegese", "nl_NL": "Olandese", @@ -385,6 +414,7 @@ LANG_TEXT = { "tr_TR": "Turco", "de_DE": "Tedesco", "ar_AE": "Arabo", + "uk_UA": "Ucraino", "sv_SE": "Svedese", "pl_PL": "Polacco", "T1": "Selezionare la propria lingua utilizzando i tasti Sù/Giù. Premere OK per confermare.", @@ -394,6 +424,7 @@ LANG_TEXT = { "fr_FR": "Fransk", "fi_FI": "Finsk", "pt_PT": "Portugisisk", + "fy_x-FY": "Frisian", "it_IT": "Italiensk", "no_NO": "Norsk", "nl_NL": "Nederlandsk", @@ -411,6 +442,7 @@ LANG_TEXT = { "tr_TR": "Tyrkisk", "de_DE": "Tysk", "ar_AE": "Arabisk", + "uk_UA": "Ukrainian", "sv_SE": "Svensk", "pl_PL": "Polsk", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -420,6 +452,7 @@ LANG_TEXT = { "fr_FR": "Francuski", "fi_FI": "Fiński", "pt_PT": "Portugalski", + "fy_x-FY": "Frisian", "it_IT": "Włoski", "no_NO": "Norweski", "nl_NL": "Holenderski", @@ -437,6 +470,7 @@ LANG_TEXT = { "tr_TR": "Turecki", "de_DE": "Niemiecki", "ar_AE": "Arabski", + "uk_UA": "Ukrainian", "sv_SE": "Szwedzki", "pl_PL": "Polski", "T1": "W celu wyboru języka użyj klawiszy GÓRA i DÓŁ. Nastepnie nacisnij przycisk OK.", @@ -446,6 +480,7 @@ LANG_TEXT = { "fr_FR": "Francês", "fi_FI": "Finlandês", "pt_PT": "Português", + "fy_x-FY": "Frisian", "it_IT": "Italiano", "no_NO": "Norueguês", "nl_NL": "Holandês", @@ -463,6 +498,7 @@ LANG_TEXT = { "tr_TR": "Turco", "de_DE": "Alemão", "ar_AE": "Arabe", + "uk_UA": "Ukrainian", "sv_SE": "Sueco", "pl_PL": "Polaco", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -472,6 +508,7 @@ LANG_TEXT = { "fr_FR": "Французский", "fi_FI": "Окончание", "pt_PT": "Portuguese", + "fy_x-FY": "Frisian", "it_IT": "Итальянский", "no_NO": "Норвежский", "nl_NL": "Нидерландский", @@ -489,6 +526,7 @@ LANG_TEXT = { "tr_TR": "Турецкий", "de_DE": "Немецкий", "ar_AE": "Арабский", + "uk_UA": "Ukrainian", "sv_SE": "Шведский", "pl_PL": "Polish", "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", @@ -498,6 +536,7 @@ LANG_TEXT = { "fr_FR": "Francés", "fi_FI": "Finlandés", "pt_PT": "Portugués", + "fy_x-FY": "Frisian", "it_IT": "Italiano", "no_NO": "Noruego", "nl_NL": "Alemán", @@ -515,6 +554,7 @@ LANG_TEXT = { "tr_TR": "Turco", "de_DE": "Alemán", "ar_AE": "Arábigo", + "uk_UA": "Ukrainian", "sv_SE": "Sueco", "pl_PL": "Polaco", "T1": "Use las teclas ARRIBA y ABAJO para seleccionar su idioma. Después, pulse el botón OK.", @@ -524,6 +564,7 @@ LANG_TEXT = { "fr_FR": "Franska", "fi_FI": "Finska", "pt_PT": "Portugisiska", + "fy_x-FY": "Frisian", "it_IT": "Italienska", "no_NO": "Norska", "nl_NL": "Holländska", @@ -541,6 +582,7 @@ LANG_TEXT = { "tr_TR": "Turkiska", "de_DE": "Tyska", "ar_AE": "Arabiska", + "uk_UA": "Ukrainian", "sv_SE": "Svenska", "pl_PL": "Polska", "T1": "Vänligen använd UPP och NER pil för att välja språk. Efter val tryck på OK knappen.", @@ -548,28 +590,86 @@ LANG_TEXT = { }, "tr_TR": { "fr_FR": "Fransızca", - "fi_FI": "Bitiş", - "pt_PT": "Portuguese", - "it_IT": "İtalya", - "no_NO": "Norveç", - "nl_NL": "Almanca", + "fi_FI": "Fince", + "pt_PT": "Portekizce", + "fy_x-FY": "Frisian", + "it_IT": "İtalyanca", + "no_NO": "Norveççe", + "nl_NL": "Flemenkçe", "el_GR": "Greek", - "hu_HU": "Hungarian", - "lt_LT": "Lithuanian", - "hr_HR": "Croatian", + "hu_HU": "Macarca", + "lt_LT": "Litvanyaca", + "hr_HR": "Hırvatça", "en_EN": "İngilizce", "es_ES": "İspanyolca", - "ca_AD": "Catalan", - "ru_RU": "Russian", - "is_IS": "izlanda", - "da_DK": "Çanak", - "cs_CZ": "Czech", - "tr_TR": "Turkish", - "de_DE": "Alman", + "ca_AD": "Katalanca", + "ru_RU": "Rusça", + "is_IS": "İzlandaca", + "da_DK": "Danca", + "cs_CZ": "Çekçe", + "tr_TR": "Türkçe", + "de_DE": "Almanca", "ar_AE": "Arapça", - "sv_SE": "İsveç", + "uk_UA": "Ukraynaca", + "sv_SE": "İsveççe", "pl_PL": "Polish", - "T1": "Please use the UP and DOWN keys to select your language. Afterwards press the OK button.", - "T2": "Lisan Seçimi", + "T1": "Dil seçiminizi, yapmak için YUKARI ve AŞAĞI tuşlarını, onaylamak için OK tuşunu kullanın.", + "T2": "Dil seçimi", +}, +"uk_UA": { + "fr_FR": "Французька", + "fi_FI": "Фінська", + "pt_PT": "Португальська", + "fy_x-FY": "Frisian", + "it_IT": "Італійська", + "no_NO": "Норвежська", + "nl_NL": "Данська", + "el_GR": "Грецька", + "hu_HU": "Угорська", + "lt_LT": "Литовська", + "hr_HR": "Хорватьска", + "en_EN": "Англійська", + "es_ES": "Іспанська", + "ca_AD": "Каталонська", + "ru_RU": "Російська", + "is_IS": "Ісландська", + "da_DK": "Данська", + "cs_CZ": "Чешська", + "tr_TR": "Турецька", + "de_DE": "Німецька", + "ar_AE": "Арабський", + "uk_UA": "Ukrainian", + "sv_SE": "Шведська", + "pl_PL": "Польська", + "T1": "Використовуйте кнопки ВВЕРХ і ВНИЗ, щоб вибрати Вашу мову. Після вибору натисніть OK.", + "T2": "Вибір мови", +}, +"fy_x-FY": { + "fr_FR": "Frans", + "fi_FI": "Finsk", + "pt_PT": "Portugeesk", + "fy_x-FY": "Frisian", + "it_IT": "Italiaansk", + "no_NO": "Noarsk", + "nl_NL": "Nederlansk", + "el_GR": "Gryks", + "hu_HU": "Hongaarsk", + "lt_LT": "Lithuaniansk", + "hr_HR": "Kroatysk", + "en_EN": "Engelsk", + "es_ES": "Spaans", + "ca_AD": "Catalânsk", + "ru_RU": "Russysk", + "is_IS": "Iislansk", + "da_DK": "Deensk", + "cs_CZ": "Tsjechysk", + "tr_TR": "Turks", + "de_DE": "Dúts", + "ar_AE": "Arabysk", + "uk_UA": "Ukrainian", + "sv_SE": "Zweeds", + "pl_PL": "Poolsk", + "T1": "Brúk de op en del toets om jo taal te kiezen. Dernei druk op OK", + "T2": "Taal Kieze", }, } diff --git a/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py b/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py index a63562c8..69f935e4 100644 --- a/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py +++ b/lib/python/Plugins/DemoPlugins/TestPlugin/plugin.py @@ -51,7 +51,7 @@ class Test(Screen): def mycallback(self, answer): print "answer:", answer if answer: - raise "test-crash" + raise Exception("test-crash") self.close() def keyLeft(self): diff --git a/lib/python/Plugins/Extensions/CutListEditor/plugin.py b/lib/python/Plugins/Extensions/CutListEditor/plugin.py index 0d2454e4..1ef15a53 100644 --- a/lib/python/Plugins/Extensions/CutListEditor/plugin.py +++ b/lib/python/Plugins/Extensions/CutListEditor/plugin.py @@ -12,10 +12,12 @@ from Components.GUIComponent import GUIComponent from enigma import eListboxPythonMultiContent, eListbox, gFont, iPlayableService, RT_HALIGN_RIGHT from Screens.FixedMenu import FixedMenu from Screens.HelpMenu import HelpableScreen +from ServiceReference import ServiceReference +from Components.Sources.List import List + import bisect def CutListEntry(where, what): - res = [ (where, what) ] w = where / 90 ms = w % 1000 s = (w / 1000) % 60 @@ -23,16 +25,17 @@ def CutListEntry(where, what): h = w / 3600000 if what == 0: type = "IN" + type_col = 0x004000 elif what == 1: type = "OUT" + type_col = 0x400000 elif what == 2: type = "MARK" + type_col = 0x000040 elif what == 3: type = "LAST" - res.append(MultiContentEntryText(size=(400, 20), text = "%dh:%02dm:%02ds:%03d" % (h, m, s, ms))) - res.append(MultiContentEntryText(pos=(400,0), size=(130, 20), text = type, flags = RT_HALIGN_RIGHT)) - - return res + type_col = 0x000000 + return ((where, what), "%dh:%02dm:%02ds:%03d" % (h, m, s, ms), type, type_col) class CutListContextMenu(FixedMenu): RET_STARTCUT = 0 @@ -42,6 +45,7 @@ class CutListContextMenu(FixedMenu): RET_DELETEMARK = 4 RET_REMOVEBEFORE = 5 RET_REMOVEAFTER = 6 + RET_GRABFRAME = 7 SHOW_STARTCUT = 0 SHOW_ENDCUT = 1 @@ -75,6 +79,7 @@ class CutListContextMenu(FixedMenu): else: menu.append((_("remove this mark"), self.removeMark)) + menu.append((("grab this frame as bitmap"), self.grabFrame)) FixedMenu.__init__(self, session, _("Cut"), menu) self.skinName = "Menu" @@ -99,50 +104,8 @@ class CutListContextMenu(FixedMenu): def removeAfter(self): self.close(self.RET_REMOVEAFTER) - -class CutList(GUIComponent): - def __init__(self, list): - GUIComponent.__init__(self) - self.l = eListboxPythonMultiContent() - self.setList(list) - self.l.setFont(0, gFont("Regular", 20)) - self.onSelectionChanged = [ ] - - def getCurrent(self): - return self.l.getCurrentSelection() - - def getCurrentIndex(self): - return self.l.getCurrentSelectionIndex() - - GUI_WIDGET = eListbox - - def postWidgetCreate(self, instance): - instance.setContent(self.l) - instance.setItemHeight(30) - instance.selectionChanged.get().append(self.selectionChanged) - - def preWidgetRemove(self, instance): - instance.setContent(None) - instance.selectionChanged.get().remove(self.selectionChanged) - - def selectionChanged(self): - for x in self.onSelectionChanged: - x() - - def invalidateEntry(self, index): - self.l.invalidateEntry(index) - - def setIndex(self, index, data): - self.list[index] = data - self.invalidateEntry(index) - - def setList(self, list): - self.list = list - self.l.setList(self.list) - - def setSelection(self, index): - if self.instance is not None: - self.instance.moveSelectionTo(index) + def grabFrame(self): + self.close(self.RET_GRABFRAME) class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, HelpableScreen): skin = """ @@ -161,7 +124,17 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He </widget> <eLabel position="62,98" size="179,274" backgroundColor="#505555" /> <eLabel position="64,100" size="175,270" backgroundColor="#000000" /> - <widget name="Cutlist" position="64,100" zPosition="1" size="175,270" scrollbarMode="showOnDemand" transparent="1" /> + <widget source="cutlist" position="64,100" zPosition="1" size="175,270" scrollbarMode="showOnDemand" transparent="1" render="Listbox" > + <convert type="TemplatedMultiContent"> + {"template": [ + MultiContentEntryText(size=(125, 20), text = 1, backcolor = MultiContentTemplateColor(3)), + MultiContentEntryText(pos=(125,0), size=(50, 20), text = 2, flags = RT_HALIGN_RIGHT, backcolor = MultiContentTemplateColor(3)) + ], + "fonts": [gFont("Regular", 18)], + "itemHeight": 20 + } + </convert> + </widget> <widget name="Timeline" position="50,485" size="615,20" backgroundColor="#505555" pointer="skin_default/position_arrow.png:3,5" foregroundColor="black" /> <ePixmap pixmap="skin_default/icons/mp_buttons.png" position="305,515" size="109,13" alphatest="on" /> </screen>""" @@ -186,8 +159,8 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He self.downloadCuesheet() self["Timeline"] = ServicePositionGauge(self.session.nav) - self["Cutlist"] = CutList(self.getCutlist()) - self["Cutlist"].onSelectionChanged.append(self.selectionChanged) + self["cutlist"] = List(self.getCutlist()) + self["cutlist"].onSelectionChanged.append(self.selectionChanged) self["Video"] = VideoWindow(decoder = 0) @@ -229,20 +202,20 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He def setType(self, index, type): if len(self.cut_list): self.cut_list[index] = (self.cut_list[index][0], type) - self["Cutlist"].setIndex(index, CutListEntry(*self.cut_list[index])) + self["cutlist"].modifyEntry(index, CutListEntry(*self.cut_list[index])) def setIn(self): - m = self["Cutlist"].getCurrentIndex() + m = self["cutlist"].getIndex() self.setType(m, 0) self.uploadCuesheet() def setOut(self): - m = self["Cutlist"].getCurrentIndex() + m = self["cutlist"].getIndex() self.setType(m, 1) self.uploadCuesheet() def setMark(self): - m = self["Cutlist"].getCurrentIndex() + m = self["cutlist"].getIndex() self.setType(m, 2) self.uploadCuesheet() @@ -250,7 +223,7 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He self.toggleMark(onlyadd=True, tolerance=90000) # do not allow two marks in <1s def __removeMark(self): - m = self["Cutlist"].getCurrent() + m = self["cutlist"].getCurrent() m = m and m[0] if m is not None: self.removeMark(m) @@ -265,7 +238,7 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He return r def selectionChanged(self): - where = self["Cutlist"].getCurrent() + where = self["cutlist"].getCurrent() if where is None: print "no selection" return @@ -282,11 +255,11 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He # get the first changed entry, and select it new_list = self.getCutlist() - self["Cutlist"].setList(new_list) + self["cutlist"].list = new_list for i in range(min(len(new_list), len(self.last_cuts))): if new_list[i] != self.last_cuts[i]: - self["Cutlist"].setSelection(i) + self["cutlist"].setIndex(i) break self.last_cuts = new_list @@ -390,6 +363,8 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He # add 'out' point bisect.insort(self.cut_list, (self.context_position, 1)) self.uploadCuesheet() + elif result == CutListContextMenu.RET_GRABFRAME: + self.grabFrame() # we modify the "play" behavior a bit: # if we press pause while being in slowmotion, we will pause (and not play) @@ -399,6 +374,14 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He else: self.pauseService() + def grabFrame(self): + path = self.session.nav.getCurrentlyPlayingServiceReference().getPath() + from Components.Console import Console + grabConsole = Console() + cmd = 'grab -vblpr%d "%s"' % (180, path.rsplit('.',1)[0] + ".png") + grabConsole.ePopen(cmd) + self.playpauseService() + def main(session, service, **kwargs): session.open(CutListEditor, service) diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py b/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py index 112a221e..b0b8197a 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py @@ -1,18 +1,10 @@ from Tools.Directories import fileExists -from Components.config import config, ConfigSubsection, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence +from Components.config import config, ConfigSubsection, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence, ConfigSubList class ConfigColor(ConfigSequence): def __init__(self): ConfigSequence.__init__(self, seperator = "#", limits = [(0,255),(0,255),(0,255)]) -class ConfigPixelvals(ConfigSequence): - def __init__(self): - ConfigSequence.__init__(self, seperator = ",", limits = [(0,200),(0,200),(0,200)]) - -class ConfigPixelvals(ConfigSequence): - def __init__(self): - ConfigSequence.__init__(self, seperator = ",", limits = [(0,200),(0,200),(0,200)]) - class ConfigFilename(ConfigText): def __init__(self): ConfigText.__init__(self, default = "", fixed_size = True, visible_width = False) @@ -35,19 +27,11 @@ class DVDProject: 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"))]) - self.settings.menubg = ConfigFilename() - self.settings.menuaudio = ConfigFilename() - self.settings.titleformat = ConfigText(fixed_size = False, visible_width = 40) - self.settings.subtitleformat = ConfigText(fixed_size = False, visible_width = 40) - self.settings.color_headline = ConfigColor() - self.settings.color_highlight = ConfigColor() - self.settings.color_button = ConfigColor() - self.settings.font_face = ConfigFilename() - self.settings.font_size = ConfigPixelvals() - self.settings.space = ConfigPixelvals() + self.settings.dataformat = ConfigSelection(choices = [("iso9660_1", ("ISO9660 Level 1")), ("iso9660_4", ("ISO9660 version 2")), ("udf", ("UDF"))]) + self.settings.menutemplate = ConfigFilename() self.settings.vmgm = ConfigFilename() - self.filekeys = ["vmgm", "menubg", "menuaudio", "font_face", "isopath"] + self.filekeys = ["vmgm", "isopath", "menutemplate"] + self.menutemplate = MenuTemplate() def addService(self, service): import DVDTitle @@ -65,12 +49,30 @@ class DVDProject: list.append('\t<settings ') for key, val in self.settings.dict().iteritems(): list.append( key + '="' + str(val.getValue()) + '" ' ) - list.append(' />\n') + list.append('/>\n') list.append('\t<titles>\n') for title in self.titles: - list.append('\t\t<path>') + list.append('\t\t<title>\n') + list.append('\t\t\t<path>') list.append(stringToXML(title.source.getPath())) list.append('</path>\n') + list.append('\t\t\t<properties ') + audiotracks = [] + for key, val in title.properties.dict().iteritems(): + if type(val) is ConfigSubList: + audiotracks.append('\t\t\t<audiotracks>\n') + for audiotrack in val: + audiotracks.append('\t\t\t\t<audiotrack ') + for subkey, subval in audiotrack.dict().iteritems(): + audiotracks.append( subkey + '="' + str(subval.getValue()) + '" ' ) + audiotracks.append(' />\n') + audiotracks.append('\t\t\t</audiotracks>\n') + else: + list.append( key + '="' + str(val.getValue()) + '" ' ) + list.append('/>\n') + for line in audiotracks: + list.append(line) + list.append('\t\t</title>\n') list.append('\t</titles>\n') list.append('</DreamDVDBurnerProject>\n') @@ -89,6 +91,13 @@ class DVDProject: return False return filename + def load(self, filename): + ret = self.loadProject(filename) + if ret: + ret = self.menutemplate.loadTemplate(self.settings.menutemplate.getValue()) + self.error += self.menutemplate.error + return ret + def loadProject(self, filename): import xml.dom.minidom try: @@ -105,9 +114,9 @@ class DVDProject: if project.nodeType == xml.dom.minidom.Element.nodeType: if project.tagName == 'settings': i = 0 - if project.attributes.length < 11: + if project.attributes.length < len(self.settings.dict()): self.error = "project attributes missing" - raise AttributeError + raise AttributeError while i < project.attributes.length: item = project.attributes.item(i) key = item.name.encode("utf-8") @@ -131,3 +140,44 @@ class DVDProject: self.error += (" in project '%s'") % (filename) return False return True + +class MenuTemplate(DVDProject): + def __init__(self): + self.settings = ConfigSubsection() + self.settings.titleformat = ConfigText(fixed_size = False, visible_width = 40) + self.settings.subtitleformat = ConfigText(fixed_size = False, visible_width = 40) + self.settings.menubg = ConfigFilename() + self.settings.menuaudio = ConfigFilename() + self.settings.dimensions = ConfigSequence(seperator = ',', default = [576,720], limits = [(352,720),(480,576)]) + self.settings.rows = ConfigInteger(default = 4, limits = (1, 10)) + self.settings.cols = ConfigInteger(default = 1, limits = (1, 4)) + self.settings.color_headline = ConfigColor() + self.settings.color_headline = ConfigColor() + self.settings.color_highlight = ConfigColor() + self.settings.color_button = ConfigColor() + self.settings.fontface_headline = ConfigFilename() + self.settings.fontface_title = ConfigFilename() + self.settings.fontface_subtitle = ConfigFilename() + self.settings.fontsize_headline = ConfigInteger(default = 46, limits = (0, 199)) + self.settings.fontsize_title = ConfigInteger(default = 24, limits = (0, 199)) + self.settings.fontsize_subtitle = ConfigInteger(default = 14, limits = (0, 199)) + self.settings.margin_top = ConfigInteger(default = 120, limits = (0, 500)) + self.settings.margin_bottom = ConfigInteger(default = 40, limits = (0, 500)) + self.settings.margin_left = ConfigInteger(default = 56, limits = (0, 500)) + self.settings.margin_right = ConfigInteger(default = 56, limits = (0, 500)) + self.settings.space_rows = ConfigInteger(default = 32, limits = (0, 500)) + self.settings.space_cols = ConfigInteger(default = 24, limits = (0, 500)) + self.settings.prev_page_text = ConfigText(default = "<<<", fixed_size = False) + self.settings.next_page_text = ConfigText(default = ">>>", fixed_size = False) + self.settings.offset_headline = ConfigSequence(seperator = ',', default = [0,0], limits = [(-1,500),(-1,500)]) + self.settings.offset_title = ConfigSequence(seperator = ',', default = [0,0], limits = [(-1,500),(-1,500)]) + self.settings.offset_subtitle = ConfigSequence(seperator = ',', default = [20,0], limits = [(-1,500),(-1,500)]) + self.settings.offset_thumb = ConfigSequence(seperator = ',', default = [40,0], limits = [(-1,500),(-1,500)]) + self.settings.thumb_size = ConfigSequence(seperator = ',', default = [200,158], limits = [(0,576),(-1,720)]) + self.settings.thumb_border = ConfigInteger(default = 2, limits = (0, 20)) + self.filekeys = ["menubg", "menuaudio", "fontface_headline", "fontface_title", "fontface_subtitle"] + + def loadTemplate(self, filename): + ret = DVDProject.loadProject(self, filename) + DVDProject.error = self.error + return ret diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py b/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py index b1c627aa..660005e6 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py @@ -51,11 +51,11 @@ class DVDTitle: 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)) + s = project.menutemplate.settings + self.properties.menutitle.setValue(self.formatDVDmenuText(s.titleformat.getValue(), track)) + self.properties.menusubtitle.setValue(self.formatDVDmenuText(s.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) @@ -76,7 +76,7 @@ class DVDTitle: 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) @@ -90,7 +90,7 @@ class DVDTitle: else: template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "") return template - + def produceFinalCuesheet(self): CUT_TYPE_IN = 0 CUT_TYPE_OUT = 1 diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py index 836c9fbd..ce16259e 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py @@ -50,7 +50,7 @@ class DVDToolbox(Screen): "green": self.update, "yellow": self.format, #"blue": self.eject, - "cancel": self.close, + "cancel": self.exit, "pageUp": self.pageUp, "pageDown": self.pageDown }) @@ -63,7 +63,7 @@ class DVDToolbox(Screen): def pageDown(self): self["details"].pageDown() - def update(self, dev="", media_state=""): + def update(self, dev="", action=""): self["space_label"].text = _("Please wait... Loading list...") self["info"].text = "" self["details"].setText("") @@ -89,7 +89,7 @@ class DVDToolbox(Screen): for line in mediuminfo.splitlines(): if line.find("Mounted Media:") > -1: mediatype = line.rsplit(',',1)[1][1:] - if mediatype.find("RW") > 0: + if mediatype.find("RW") > 0 or mediatype.find("RAM") > 0: self.formattable = True else: self.formattable = False @@ -186,7 +186,7 @@ class DVDformatTask(Task): if line.startswith("- media is already formatted"): self.error = self.ERROR_ALREADYFORMATTED self.retryargs = [ "-force" ] - if line.startswith("- media is not blank"): + if line.startswith("- media is not blank") or line.startswith(" -format=full to perform full (lengthy) reformat;"): self.error = self.ERROR_ALREADYFORMATTED self.retryargs = [ "-blank" ] if line.startswith(":-( mounted media doesn't appear to be"): diff --git a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml new file mode 100644 index 00000000..2c35e531 --- /dev/null +++ b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" ?> +<DreamDVDBurnProject> + <settings + name="Dreambox DVD record" + authormode="menu_linked" + menutemplate="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/Thumbs menu clouds.ddvdm.xml" + titlesetmode="multi" + vmgm="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/vmgmdream.mpg" + output="dvd" + isopath="/media/hdd/movie/" + dataformat="iso9660_4" + /> + <titles> </titles> +</DreamDVDBurnProject> diff --git a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml deleted file mode 100644 index 7d8de8ce..00000000 --- a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<DreamDVDBurnerProject> - <settings - name="Dreambox DVD record" - authormode="menu_linked" - titlesetmode="multi" - titleformat="$i. $t" - 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" - color_button="[8, 0, 0]" - color_highlight="[0, 192, 192]" - color_headline="[0, 0, 128]" - font_face="/usr/share/fonts/nmsbd.ttf" - font_size="[46, 24, 14]" - space="[120, 32, 56]" - output="dvd" - isopath="/media/hdd/movie/" - dataformat="iso9660_4" - /> - <titles> </titles> -</DreamDVDBurnerProject> diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 89ca90fd..d0c9d3c6 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -165,7 +165,7 @@ class DemuxTask(Task): def cleanup(self, failed): if failed: import os - for file in self.generated_files.itervalues(): + for file in self.generated_files: os.remove(file) class MplexTaskPostcondition(Condition): @@ -220,7 +220,7 @@ class RemoveESFiles(Task): def prepare(self): self.args += ["-f"] - self.args += self.demux_task.generated_files.values() + self.args += self.demux_task.generated_files self.args += [self.demux_task.cutfile] class DVDAuthorTask(Task): @@ -368,6 +368,9 @@ class CheckDiskspaceTask(Task): self.global_preconditions.append(DiskspacePrecondition(diskSpaceNeeded)) self.weighting = 5 + def abort(self): + self.finish(aborted = True) + def run(self, callback): failed_preconditions = self.checkPreconditions(True) + self.checkPreconditions(False) if len(failed_preconditions): @@ -452,13 +455,13 @@ class ImagePrepareTask(Task): try: from ImageFont import truetype from Image import open as Image_open - s = self.job.project.settings + s = self.job.project.menutemplate.settings + (width, height) = s.dimensions.getValue() self.Menus.im_bg_orig = Image_open(s.menubg.getValue()) - if self.Menus.im_bg_orig.size != (self.Menus.imgwidth, self.Menus.imgheight): - self.Menus.im_bg_orig = self.Menus.im_bg_orig.resize((720, 576)) - self.Menus.fontsizes = s.font_size.getValue() - fontface = s.font_face.getValue() - self.Menus.fonts = [truetype(fontface, self.Menus.fontsizes[0]), truetype(fontface, self.Menus.fontsizes[1]), truetype(fontface, self.Menus.fontsizes[2])] + if self.Menus.im_bg_orig.size != (width, height): + self.Menus.im_bg_orig = self.Menus.im_bg_orig.resize((width, height)) + self.Menus.fontsizes = [s.fontsize_headline.getValue(), s.fontsize_title.getValue(), s.fontsize_subtitle.getValue()] + self.Menus.fonts = [(truetype(s.fontface_headline.getValue(), self.Menus.fontsizes[0])), (truetype(s.fontface_title.getValue(), self.Menus.fontsizes[1])),(truetype(s.fontface_subtitle.getValue(), self.Menus.fontsizes[2]))] Task.processFinished(self, 0) except: Task.processFinished(self, 1) @@ -477,98 +480,158 @@ class MenuImageTask(Task): def run(self, callback): self.callback = callback - try: - import ImageDraw, Image, os - s = self.job.project.settings - fonts = self.Menus.fonts - im_bg = self.Menus.im_bg_orig.copy() - im_high = Image.new("P", (self.Menus.imgwidth, self.Menus.imgheight), 0) - im_high.putpalette(self.Menus.spu_palette) - draw_bg = ImageDraw.Draw(im_bg) - draw_high = ImageDraw.Draw(im_high) - if self.menu_count == 1: - headline = s.name.getValue().decode("utf-8") - textsize = draw_bg.textsize(headline, font=fonts[0]) - if textsize[0] > self.Menus.imgwidth: - offset = (0 , 20) - else: - offset = (((self.Menus.imgwidth-textsize[0]) / 2) , 20) - draw_bg.text(offset, headline, fill=self.Menus.color_headline, font=fonts[0]) - spuxml = """<?xml version="1.0" encoding="utf-8"?> - <subpictures> - <stream> - <spu - highlight="%s" - transparent="%02x%02x%02x" - start="00:00:00.00" - force="yes" >""" % (self.highlightpngfilename, self.Menus.spu_palette[0], self.Menus.spu_palette[1], self.Menus.spu_palette[2]) - s_top, s_rows, s_left = s.space.getValue() - rowheight = (self.Menus.fontsizes[1]+self.Menus.fontsizes[2]+s_rows) - menu_start_title = (self.menu_count-1)*self.job.titles_per_menu + 1 - menu_end_title = (self.menu_count)*self.job.titles_per_menu + 1 - nr_titles = len(self.job.project.titles) - if menu_end_title > nr_titles: - menu_end_title = nr_titles+1 - menu_i = 0 - for title_no in range( menu_start_title , menu_end_title ): - menu_i += 1 - 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 = 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: - bottom = self.Menus.imgheight - spuxml += """ - <button name="button%s" x0="%d" x1="%d" y0="%d" y1="%d"/>""" % (str(title_no).zfill(2),s_left,self.Menus.imgwidth,top,bottom ) - if self.menu_count < self.job.nr_menus: - next_page_text = ">>>" - textsize = draw_bg.textsize(next_page_text, font=fonts[1]) - offset = ( self.Menus.imgwidth-textsize[0]-2*s_left, s_top + ( self.job.titles_per_menu * rowheight ) ) - draw_bg.text(offset, next_page_text, fill=self.Menus.color_button, font=fonts[1]) - draw_high.text(offset, next_page_text, fill=1, font=fonts[1]) - spuxml += """ - <button name="button_next" x0="%d" x1="%d" y0="%d" y1="%d"/>""" % (offset[0],offset[0]+textsize[0],offset[1],offset[1]+textsize[1]) - if self.menu_count > 1: - prev_page_text = "<<<" - textsize = draw_bg.textsize(prev_page_text, font=fonts[1]) - offset = ( 2*s_left, s_top + ( self.job.titles_per_menu * rowheight ) ) - draw_bg.text(offset, prev_page_text, fill=self.Menus.color_button, font=fonts[1]) - draw_high.text(offset, prev_page_text, fill=1, font=fonts[1]) - spuxml += """ - <button name="button_prev" x0="%d" x1="%d" y0="%d" y1="%d"/>""" % (offset[0],offset[0]+textsize[0],offset[1],offset[1]+textsize[1]) - del draw_bg - del draw_high - fd=open(self.menubgpngfilename,"w") - im_bg.save(fd,"PNG") - fd.close() - fd=open(self.highlightpngfilename,"w") - im_high.save(fd,"PNG") - fd.close() + #try: + import ImageDraw, Image, os + s = self.job.project.menutemplate.settings + s_top = s.margin_top.getValue() + s_bottom = s.margin_bottom.getValue() + s_left = s.margin_left.getValue() + s_right = s.margin_right.getValue() + s_rows = s.space_rows.getValue() + s_cols = s.space_cols.getValue() + nr_cols = s.cols.getValue() + nr_rows = s.rows.getValue() + thumb_size = s.thumb_size.getValue() + if thumb_size[0]: + from Image import open as Image_open + (s_width, s_height) = s.dimensions.getValue() + fonts = self.Menus.fonts + im_bg = self.Menus.im_bg_orig.copy() + im_high = Image.new("P", (s_width, s_height), 0) + im_high.putpalette(self.Menus.spu_palette) + draw_bg = ImageDraw.Draw(im_bg) + draw_high = ImageDraw.Draw(im_high) + if self.menu_count == 1: + headlineText = self.job.project.settings.name.getValue().decode("utf-8") + headlinePos = self.getPosition(s.offset_headline.getValue(), 0, 0, s_width, s_top, draw_bg.textsize(headlineText, font=fonts[0])) + draw_bg.text(headlinePos, headlineText, fill=self.Menus.color_headline, font=fonts[0]) + spuxml = """<?xml version="1.0" encoding="utf-8"?> + <subpictures> + <stream> + <spu + highlight="%s" + transparent="%02x%02x%02x" + start="00:00:00.00" + force="yes" >""" % (self.highlightpngfilename, self.Menus.spu_palette[0], self.Menus.spu_palette[1], self.Menus.spu_palette[2]) + #rowheight = (self.Menus.fontsizes[1]+self.Menus.fontsizes[2]+thumb_size[1]+s_rows) + menu_start_title = (self.menu_count-1)*self.job.titles_per_menu + 1 + menu_end_title = (self.menu_count)*self.job.titles_per_menu + 1 + nr_titles = len(self.job.project.titles) + if menu_end_title > nr_titles: + menu_end_title = nr_titles+1 + col = 1 + row = 1 + for title_no in range( menu_start_title , menu_end_title ): + title = self.job.project.titles[title_no-1] + col_width = ( s_width - s_left - s_right ) / nr_cols + row_height = ( s_height - s_top - s_bottom ) / nr_rows + left = s_left + ( (col-1) * col_width ) + s_cols/2 + right = left + col_width - s_cols + top = s_top + ( (row-1) * row_height) + s_rows/2 + bottom = top + row_height - s_rows + width = right - left + height = bottom - top + + if bottom > s_height: + bottom = s_height + #draw_bg.rectangle((left, top, right, bottom), outline=(255,0,0)) + im_cell_bg = Image.new("RGBA", (width, height),(0,0,0,0)) + draw_cell_bg = ImageDraw.Draw(im_cell_bg) + im_cell_high = Image.new("P", (width, height), 0) + im_cell_high.putpalette(self.Menus.spu_palette) + draw_cell_high = ImageDraw.Draw(im_cell_high) + + if thumb_size[0]: + thumbPos = self.getPosition(s.offset_thumb.getValue(), 0, 0, width, height, thumb_size) + box = (thumbPos[0], thumbPos[1], thumbPos[0]+thumb_size[0], thumbPos[1]+thumb_size[1]) + try: + thumbIm = Image_open(title.inputfile.rsplit('.',1)[0] + ".png") + im_cell_bg.paste(thumbIm,thumbPos) + except: + draw_cell_bg.rectangle(box, fill=(64,127,127,127)) + border = s.thumb_border.getValue() + if border: + draw_cell_high.rectangle(box, fill=1) + draw_cell_high.rectangle((box[0]+border, box[1]+border, box[2]-border, box[3]-border), fill=0) + + titleText = title.formatDVDmenuText(s.titleformat.getValue(), title_no).decode("utf-8") + titlePos = self.getPosition(s.offset_title.getValue(), 0, 0, width, height, draw_bg.textsize(titleText, font=fonts[1])) + + draw_cell_bg.text(titlePos, titleText, fill=self.Menus.color_button, font=fonts[1]) + draw_cell_high.text(titlePos, titleText, fill=1, font=self.Menus.fonts[1]) + + subtitleText = title.formatDVDmenuText(s.subtitleformat.getValue(), title_no).decode("utf-8") + subtitlePos = self.getPosition(s.offset_subtitle.getValue(), 0, 0, width, height, draw_cell_bg.textsize(subtitleText, font=fonts[2])) + draw_cell_bg.text(subtitlePos, subtitleText, fill=self.Menus.color_button, font=fonts[2]) + + del draw_cell_bg + del draw_cell_high + im_bg.paste(im_cell_bg,(left, top, right, bottom), mask=im_cell_bg) + im_high.paste(im_cell_high,(left, top, right, bottom)) + spuxml += """ - </spu> - </stream> - </subpictures>""" - - f = open(self.spuxmlfilename, "w") - f.write(spuxml) - f.close() - Task.processFinished(self, 0) - except: - Task.processFinished(self, 1) + <button name="button%s" x0="%d" x1="%d" y0="%d" y1="%d"/>""" % (str(title_no).zfill(2),left,right,top,bottom ) + if col < nr_cols: + col += 1 + else: + col = 1 + row += 1 + + top = s_height - s_bottom - s_rows/2 + if self.menu_count < self.job.nr_menus: + next_page_text = s.next_page_text.getValue().decode("utf-8") + textsize = draw_bg.textsize(next_page_text, font=fonts[1]) + pos = ( s_width-textsize[0]-s_right, top ) + draw_bg.text(pos, next_page_text, fill=self.Menus.color_button, font=fonts[1]) + draw_high.text(pos, next_page_text, fill=1, font=fonts[1]) + spuxml += """ + <button name="button_next" x0="%d" x1="%d" y0="%d" y1="%d"/>""" % (pos[0],pos[0]+textsize[0],pos[1],pos[1]+textsize[1]) + if self.menu_count > 1: + prev_page_text = s.prev_page_text.getValue().decode("utf-8") + textsize = draw_bg.textsize(prev_page_text, font=fonts[1]) + pos = ( (s_left+s_cols/2), top ) + draw_bg.text(pos, prev_page_text, fill=self.Menus.color_button, font=fonts[1]) + draw_high.text(pos, prev_page_text, fill=1, font=fonts[1]) + spuxml += """ + <button name="button_prev" x0="%d" x1="%d" y0="%d" y1="%d"/>""" % (pos[0],pos[0]+textsize[0],pos[1],pos[1]+textsize[1]) + del draw_bg + del draw_high + fd=open(self.menubgpngfilename,"w") + im_bg.save(fd,"PNG") + fd.close() + fd=open(self.highlightpngfilename,"w") + im_high.save(fd,"PNG") + fd.close() + spuxml += """ + </spu> + </stream> + </subpictures>""" + + f = open(self.spuxmlfilename, "w") + f.write(spuxml) + f.close() + Task.processFinished(self, 0) + #except: + #Task.processFinished(self, 1) + + def getPosition(self, offset, left, top, right, bottom, size): + pos = [left, top] + if offset[0] != -1: + pos[0] += offset[0] + else: + pos[0] += ( (right-left) - size[0] ) / 2 + if offset[1] != -1: + pos[1] += offset[1] + else: + pos[1] += ( (bottom-top) - size[1] ) / 2 + return tuple(pos) class Menus: def __init__(self, job): self.job = job job.Menus = self - - s = self.job.project.settings - self.imgwidth = 720 - self.imgheight = 576 + s = self.job.project.menutemplate.settings self.color_headline = tuple(s.color_headline.getValue()) self.color_button = tuple(s.color_button.getValue()) @@ -577,10 +640,9 @@ class Menus: ImagePrepareTask(job) nr_titles = len(job.project.titles) - if nr_titles < 6: - job.titles_per_menu = 5 - else: - job.titles_per_menu = 4 + + job.titles_per_menu = s.cols.getValue()*s.rows.getValue() + job.nr_menus = ((nr_titles+job.titles_per_menu-1)/job.titles_per_menu) #a new menu_count every 4 titles (1,2,3,4->1 ; 5,6,7,8->2 etc.) @@ -791,7 +853,7 @@ class DVDJob(Job): 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 b77383cf..7407263d 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py +++ b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py @@ -26,7 +26,10 @@ class FileBrowser(Screen, HelpableScreen): currDir = "/" if self.scope == "project": currDir = self.getDir() - pattern = "(?i)^.*\.(ddvdp\.xml)" + pattern = "(?i)^.*\.(ddvdp\.xml)" + elif self.scope == "menutemplate": + currDir = self.getDir() + pattern = "(?i)^.*\.(ddvdm\.xml)" if self.scope == "menubg": currDir = self.getDir(settings.menubg) pattern = "(?i)^.*\.(jpeg|jpg|jpe|png|bmp)" @@ -101,7 +104,7 @@ class ProjectSettings(Screen,ConfigListScreen): self["key_yellow"] = StaticText(_("Load")) self["key_blue"] = StaticText(_("Save")) - 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") + 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) self.settings = project.settings @@ -137,16 +140,17 @@ class ProjectSettings(Screen,ConfigListScreen): if output == "iso": self.list.append(getConfigListEntry(_("ISO path"), self.settings.isopath)) if authormode.startswith("menu"): - self.list.append(getConfigListEntry(_("Menu")+' '+_("background image"), self.settings.menubg)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("Title"), self.settings.titleformat)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("Subtitles"), self.settings.subtitleformat)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("headline")+' '+_("color"), self.settings.color_headline)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("text")+' '+_("color"), self.settings.color_button)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("highlighted button")+' '+_("color"), self.settings.color_highlight)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("font face"), self.settings.font_face)) - self.list.append(getConfigListEntry(_("Font size")+' ('+_("headline")+', '+_("Title")+', '+_("Subtitles")+')', self.settings.font_size)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("spaces (top, between rows, left)"), self.settings.space)) - self.list.append(getConfigListEntry(_("Menu")+' '+_("Audio"), self.settings.menuaudio)) + self.list.append(getConfigListEntry(_("Menu")+' '+_("template file"), self.settings.menutemplate)) + self.list.append(getConfigListEntry(_("Menu")+' '+_("Title"), self.project.menutemplate.settings.titleformat)) + self.list.append(getConfigListEntry(_("Menu")+' '+_("Subtitles"), self.project.menutemplate.settings.subtitleformat)) + self.list.append(getConfigListEntry(_("Menu")+' '+_("background image"), self.project.menutemplate.settings.menubg)) + #self.list.append(getConfigListEntry(_("Menu")+' '+_("headline")+' '+_("color"), self.settings.color_headline)) + #self.list.append(getConfigListEntry(_("Menu")+' '+_("text")+' '+_("color"), self.settings.color_button)) + #self.list.append(getConfigListEntry(_("Menu")+' '+_("highlighted button")+' '+_("color"), self.settings.color_highlight)) + #self.list.append(getConfigListEntry(_("Menu")+' '+_("font face"), self.settings.font_face)) + #self.list.append(getConfigListEntry(_("Font size")+' ('+_("headline")+', '+_("Title")+', '+_("Subtitles")+')', self.settings.font_size)) + #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(_("Titleset mode"), self.settings.titlesetmode)) if self.settings.titlesetmode.getValue() == "single" or authormode == "just_linked": @@ -198,8 +202,16 @@ class ProjectSettings(Screen,ConfigListScreen): self.session.open(MessageBox,text,type = MessageBox.TYPE_ERROR) def FileBrowserClosed(self, path, scope): + if scope == "menutemplate": + if not self.project.menutemplate.loadTemplate(path): + self.session.open(MessageBox,self.project.error,MessageBox.TYPE_ERROR) + else: + print "[ProjectSettings] menu template loaded" + if scope in self.project.filekeys: self.settings.dict()[scope].setValue(path) elif scope == "project": if not self.project.loadProject(path): self.session.open(MessageBox,self.project.error,MessageBox.TYPE_ERROR) + else: + self.initConfigList() diff --git a/lib/python/Plugins/Extensions/DVDBurn/Text menu boat.ddvdm.xml b/lib/python/Plugins/Extensions/DVDBurn/Text menu boat.ddvdm.xml new file mode 100644 index 00000000..0de7f4b6 --- /dev/null +++ b/lib/python/Plugins/Extensions/DVDBurn/Text menu boat.ddvdm.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" ?> +<DreamDVDBurnMenu> + <settings + titleformat="$i. $t" + subtitleformat="$D.$M.$Y, $T $C, $d" + menubg="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/dreamdvd_boat.jpg" + menuaudio="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/silence.mp2" + dimensions="(720, 576)" + rows="5" + cols="1" + color_button="[8, 0, 0]" + color_highlight="[0, 192, 192]" + color_headline="[0, 0, 128]" + fontface_headline="/usr/share/fonts/nmsbd.ttf" + fontface_title="/usr/share/fonts/nmsbd.ttf" + fontface_subtitle="/usr/share/fonts/nmsbd.ttf" + fontsize_headline="46" + fontsize_title="24" + fontsize_subtitle="14" + margin_left="56" + margin_right="56" + margin_top="100" + margin_bottom="70" + space_rows="30" + space_cols="40" + offset_headline="(-1, 40)" + offset_title="(0, 0)" + offset_subtitle="(0, 32)" + offset_thumb="(0, 0)" + thumb_size="(0, 0)" + thumb_border="0" + prev_page_text="«««" + next_page_text="»»»" + /> +</DreamDVDBurnMenu> diff --git a/lib/python/Plugins/Extensions/DVDBurn/Thumbs menu clouds.ddvdm.xml b/lib/python/Plugins/Extensions/DVDBurn/Thumbs menu clouds.ddvdm.xml new file mode 100644 index 00000000..c00c3fee --- /dev/null +++ b/lib/python/Plugins/Extensions/DVDBurn/Thumbs menu clouds.ddvdm.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8" ?> +<DreamDVDBurnMenu> + <settings + titleformat="$t" + subtitleformat="$d" + menubg="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/dreamdvd_clouds.jpg" + menuaudio="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/silence.mp2" + dimensions="(720, 576)" + rows="2" + cols="2" + color_button="[8, 0, 0]" + color_highlight="[128, 0, 0]" + color_headline="[128, 0, 0]" + fontface_headline="/usr/share/fonts/nmsbd.ttf" + fontface_title="/usr/share/fonts/nmsbd.ttf" + fontface_subtitle="/usr/share/fonts/nmsbd.ttf" + fontsize_headline="46" + fontsize_title="18" + fontsize_subtitle="12" + margin_left="48" + margin_right="48" + margin_top="100" + margin_bottom="48" + space_rows="24" + space_cols="24" + offset_headline="(-1, 40)" + offset_title="(-1, 144)" + offset_subtitle="(-1, 164)" + offset_thumb="(-1, 0)" + thumb_size="(180, 144)" + thumb_border="2" + prev_page_text="«««" + next_page_text="»»»" + /> +</DreamDVDBurnMenu> diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py b/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py index 210a3d58..61152e8a 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py @@ -1,6 +1,7 @@ from Plugins.Extensions.CutListEditor.plugin import CutListEditor from Components.ServiceEventTracker import ServiceEventTracker from enigma import iPlayableService, iServiceInformation +from Tools.Directories import fileExists class TitleCutter(CutListEditor): def __init__(self, session, t): @@ -46,7 +47,12 @@ class TitleCutter(CutListEditor): self.t.properties.aspect.setValue(aspect) self.t.VideoType = service.info().getInfo(iServiceInformation.sVideoType) + def checkAndGrabThumb(self): + if not fileExists(self.t.inputfile.rsplit('.',1)[0] + ".png"): + CutListEditor.grabFrame(self) + def exit(self): + self.checkAndGrabThumb() self.session.nav.stopService() self.close(self.cut_list[:]) @@ -56,4 +62,5 @@ class CutlistReader(TitleCutter): def getPMTInfo(self): TitleCutter.getPMTInfo(self) + TitleCutter.checkAndGrabThumb(self) self.close(self.cut_list[:]) diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py index 345af877..749f80eb 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py @@ -74,9 +74,22 @@ class TitleList(Screen, HelpableScreen): self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)]) self.updateTitleList() - + + def checkBackgroundJobs(self): + for job in job_manager.getPendingJobs(): + print "type(job):", type(job) + print "Process.DVDJob:", Process.DVDJob + if type(job) == Process.DVDJob: + self.backgroundJob = job + return + self.backgroundJob = None + def showMenu(self): menu = [] + self.checkBackgroundJobs() + if self.backgroundJob: + j = self.backgroundJob + menu.append(("%s: %s (%d%%)" % (j.getStatustext(), j.name, int(100*j.progress/float(j.end))), self.showBackgroundJob)) if self.project.settings.output.getValue() == "dvd": menu.append((_("Burn DVD"), self.burnProject)) elif self.project.settings.output.getValue() == "iso": @@ -97,6 +110,11 @@ class TitleList(Screen, HelpableScreen): if choice: choice[1]() + def showBackgroundJob(self): + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, self.backgroundJob) + self.backgroundJob = None + def titleProperties(self): if self.getCurrentTitle(): self.session.openWithCallback(self.updateTitleList, TitleProperties.TitleProperties, self, self.project, self["titles"].getIndex()) @@ -172,8 +190,8 @@ class TitleList(Screen, HelpableScreen): self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":" def loadTemplate(self): - filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml" - if self.project.loadProject(filename): + filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVD.ddvdp.xml" + if self.project.load(filename): self["error_label"].hide() return True else: @@ -212,12 +230,12 @@ 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.properties.menutitle.getValue()) ] + a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 5, 500, 25, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue()) ] res.append(a) totalsize += title.estimatedDiskspace self["titles"].list = res self.updateSize(totalsize) - + def updateSize(self, totalsize): size = int((totalsize/1024)/1024) max_SL = 4370 diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py index d5ba6c16..63ae6c1f 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py @@ -8,10 +8,12 @@ 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 Components.Pixmap import Pixmap +from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, ePicLoad 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 +from Components.AVSwitch import AVSwitch import DVDTitle class TitleProperties(Screen,ConfigListScreen): @@ -23,9 +25,9 @@ class TitleProperties(Screen,ConfigListScreen): <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" /> + <widget source="serviceinfo" render="Label" position="10,46" size="350,144" font="Regular;18" /> + <widget name="thumbnail" position="370,46" size="180,144" alphatest="on" /> + <widget name="config" position="10,206" size="540,228" scrollbarMode="showOnDemand" /> </screen>""" def __init__(self, session, parent, project, title_idx): @@ -37,9 +39,12 @@ class TitleProperties(Screen,ConfigListScreen): 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["thumbnail"] = Pixmap() + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.paintThumbPixmapCB) + self.properties = project.titles[title_idx].properties ConfigListScreen.__init__(self, []) self.properties.crop = DVDTitle.ConfigFixedText("crop") @@ -47,8 +52,6 @@ class TitleProperties(Screen,ConfigListScreen): self.properties.aspect.addNotifier(self.initConfigList) for audiotrack in self.properties.audiotracks: audiotrack.active.addNotifier(self.initConfigList) - - self.initConfigList() self["setupActions"] = ActionMap(["SetupActions", "ColorActions"], { @@ -58,6 +61,8 @@ class TitleProperties(Screen,ConfigListScreen): "cancel": self.cancel, "ok": self.ok, }, -2) + + self.onShown.append(self.update) def initConfigList(self, element=None): try: @@ -79,18 +84,15 @@ class TitleProperties(Screen,ConfigListScreen): 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 + infotext = "DVB " + _("Title") + ': ' + title.DVBname + "\n" + _("Description") + ': ' + title.DVBdescr + "\n" + _("Channel") + ': ' + title.DVBchannel + '\n' + _("Begin time") + title.formatDVDmenuText(": $D.$M.$Y, $T\n", self.title_idx+1) chaptermarks = title.getChapterMarks(template="$h:$m:$s") chapters_count = len(chaptermarks) if chapters_count >= 1: - infotext += ', ' + str(chapters_count+1) + ' ' + _("chapters") + ' (' - infotext += ' / '.join(chaptermarks) + ')' + infotext += '\n' + str(chapters_count+1) + ' ' + _("chapters") + ': ' + infotext += ' / '.join(chaptermarks) self["serviceinfo"].setText(infotext) self["config"].setList(self.list) except AttributeError: @@ -98,7 +100,22 @@ class TitleProperties(Screen,ConfigListScreen): def editTitle(self): self.parent.editTitle() + + def update(self): + print "[onShown]" self.initConfigList() + self.loadThumb() + + def loadThumb(self): + thumbfile = self.project.titles[self.title_idx].inputfile.rsplit('.',1)[0] + ".png" + sc = AVSwitch().getFramebufferScale() + self.picload.setPara((self["thumbnail"].instance.size().width(), self["thumbnail"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000")) + self.picload.startDecode(thumbfile) + + def paintThumbPixmapCB(self, picInfo=None): + ptr = self.picload.getData() + if ptr != None: + self["thumbnail"].instance.setPixmap(ptr.__deref__()) def changedConfigList(self): self.initConfigList() diff --git a/lib/python/Plugins/Extensions/DVDBurn/dreamdvd_clouds.jpg b/lib/python/Plugins/Extensions/DVDBurn/dreamdvd_clouds.jpg Binary files differnew file mode 100644 index 00000000..aacf25d0 --- /dev/null +++ b/lib/python/Plugins/Extensions/DVDBurn/dreamdvd_clouds.jpg diff --git a/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png b/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png Binary files differindex 7e7adead..7e7adead 100755..100644 --- a/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png +++ b/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png diff --git a/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml b/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml index 2a872c21..7b7f2054 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml +++ b/lib/python/Plugins/Extensions/DVDPlayer/keymap.xml @@ -11,7 +11,7 @@ <key id="KEY_AUDIO" mapto="dvdAudioMenu" flags="m" /> <key id="KEY_RADIO" mapto="nextAudioTrack" flags="m" /> <key id="KEY_TEXT" mapto="nextSubtitleTrack" flags="m" /> - <key id="KEY_VIDEO" mapto="seekBeginning" flags="l" /> + <key id="KEY_VIDEO" mapto="nextAngle" flags="m" /> </device> <device name="dreambox advanced remote control (native)"> <key id="KEY_PREVIOUS" mapto="prevChapter" flags="m" /> @@ -21,6 +21,7 @@ <key id="KEY_RADIO" mapto="dvdAudioMenu" flags="l" /> <key id="KEY_RADIO" mapto="nextAudioTrack" flags="m" /> <key id="KEY_TEXT" mapto="nextSubtitleTrack" flags="m" /> + <key id="KEY_VIDEO" mapto="nextAngle" flags="m" /> </device> <!--device name="dreambox ir keyboard"> <key id="KEY_PAUSE" mapto="pause" flags="m" /> diff --git a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py index cb5f0e0d..421a2b4e 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/DVDPlayer/plugin.py @@ -1,5 +1,5 @@ from os import path as os_path, remove as os_remove, listdir as os_listdir, system -from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys +from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys, getDesktop from Screens.Screen import Screen from Screens.MessageBox import MessageBox from Screens.ChoiceBox import ChoiceBox @@ -7,6 +7,7 @@ from Screens.HelpMenu import HelpableScreen from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap from Components.Label import Label +from Components.Pixmap import Pixmap from Components.FileList import FileList from Components.MenuList import MenuList from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase @@ -109,10 +110,11 @@ class DVDSummary(Screen): self["Title"].setText(title) class DVDOverlay(Screen): - skin = """<screen name="DVDOverlay" position="0,0" size="720,576" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />""" def __init__(self, session, args = None): + desktop_size = getDesktop(0).size() + DVDOverlay.skin = """<screen name="DVDOverlay" position="0,0" size="%d,%d" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />""" %(desktop_size.width(), desktop_size.height()) Screen.__init__(self, session) - + class ChapterZap(Screen): skin = """ <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" > @@ -182,14 +184,17 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP <!-- Chapter info --> <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" /> <!-- Audio track info --> - <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/> - <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" /> + <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,60" zPosition="1" size="26,16" alphatest="on"/> + <widget name="audioLabel" position="570,60" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" /> <!-- Subtitle track info --> - <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" > + <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,83" zPosition="1" size="26,16" alphatest="on" > <convert type="ServiceInfo">HasTelext</convert> <convert type="ConditionalShowHide" /> </widget> - <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" /> + <widget name="subtitleLabel" position="570,83" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" /> + <!-- Angle info --> + <widget name="anglePix" pixmap="skin_default/icons/icon_view.png" position="540,106" size="26,16" alphatest="on" /> + <widget name="angleLabel" position="570,106" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" /> <!-- Elapsed time --> <widget source="session.CurrentService" render="Label" position="205,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" > <convert type="ServicePosition">Position,ShowHours</convert> @@ -251,9 +256,13 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP self.session.nav.stopService() self["audioLabel"] = Label("n/a") self["subtitleLabel"] = Label("") + self["angleLabel"] = Label("") self["chapterLabel"] = Label("") + self["anglePix"] = Pixmap() + self["anglePix"].hide() self.last_audioTuple = None self.last_subtitleTuple = None + self.last_angleTuple = None self.totalChapters = 0 self.currentChapter = 0 self.totalTitles = 0 @@ -273,7 +282,8 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP iPlayableService.evUser+8: self.__chapterUpdated, iPlayableService.evUser+9: self.__titleUpdated, iPlayableService.evUser+11: self.__menuOpened, - iPlayableService.evUser+12: self.__menuClosed + iPlayableService.evUser+12: self.__menuClosed, + iPlayableService.evUser+13: self.__osdAngleInfoAvail }) self["DVDPlayerDirectionActions"] = ActionMap(["DirectionActions"], @@ -316,6 +326,7 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")), "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")), "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")), + "nextAngle": (self.nextAngle, _("switch to the next angle")), "seekBeginning": self.seekBeginning, }, -2) @@ -352,7 +363,7 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP if file.mimetype == "video/x-dvd": self.dvd_device = devicepath print "physical dvd found:", self.dvd_device - self.physicalDVD = True + self.physicalDVD = True self.dvd_filelist = dvd_filelist self.onFirstExecBegin.append(self.showFileBrowser) @@ -387,9 +398,6 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP def serviceStarted(self): #override InfoBarShowHide function self.dvdScreen.show() - subs = self.getServiceInterface("subtitle") - if subs: - subs.enableSubtitles(self.dvdScreen.instance, None) def doEofInternal(self, playing): if self.in_menu: @@ -469,6 +477,22 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP if subtitleTuple != self.last_subtitleTuple and not self.in_menu: self.doShow() self.last_subtitleTuple = subtitleTuple + + def __osdAngleInfoAvail(self): + info = self.getServiceInterface("info") + angleTuple = info and info.getInfoObject(iServiceInformation.sUser+8) + print "AngleInfoAvail ", repr(angleTuple) + if angleTuple: + angleString = "" + if angleTuple[1] > 1: + angleString = "%d / %d" % (angleTuple[0],angleTuple[1]) + self["anglePix"].show() + else: + self["anglePix"].hide() + self["angleLabel"].setText(angleString) + if angleTuple != self.last_angleTuple and not self.in_menu: + self.doShow() + self.last_angleTuple = angleTuple def __chapterUpdated(self): info = self.getServiceInterface("info") @@ -489,9 +513,9 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP self.doShow() def askLeavePlayer(self): - choices = [(_("Continue playing"), "play"), (_("Exit"), "exit")] + choices = [(_("Exit"), "exit"), (_("Continue playing"), "play")] if not self.physicalDVD: - choices.insert(1,(_("Return to file browser"), "browser")) + choices.insert(1,(_("Return to file browser"), "browser")) self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices) def sendKey(self, key): @@ -523,6 +547,9 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP def enterDVDMenu(self): self.sendKey(iServiceKeys.keyUser+7) + + def nextAngle(self): + self.sendKey(iServiceKeys.keyUser+8) def seekBeginning(self): if self.service: @@ -588,6 +615,9 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP self.service = self.session.nav.getCurrentService() print "self.service", self.service print "cur_dlg", self.session.current_dialog + subs = self.getServiceInterface("subtitle") + if subs: + subs.enableSubtitles(self.dvdScreen.instance, None) def exitCB(self, answer): if answer is not None: diff --git a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp index 1add04ab..c2590af5 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp +++ b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp @@ -87,30 +87,48 @@ DEFINE_REF(eServiceDVD); eServiceDVD::eServiceDVD(const char *filename): m_filename(filename), m_ddvdconfig(ddvd_create()), - m_pixmap(new gPixmap(eSize(720, 576), 32)), m_subtitle_widget(0), m_state(stIdle), m_current_trick(0), m_pump(eApp, 1) { + int aspect = DDVD_16_9; + int policy = DDVD_PAN_SCAN; + + char tmp[255]; + ssize_t rd; + m_sn = eSocketNotifier::create(eApp, ddvd_get_messagepipe_fd(m_ddvdconfig), eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup); - std::string aspect; eDebug("SERVICEDVD construct!"); // create handle ddvd_set_dvd_path(m_ddvdconfig, filename); ddvd_set_ac3thru(m_ddvdconfig, 0); ddvd_set_language(m_ddvdconfig, "de"); - if (ePythonConfigQuery::getConfigValue("config.av.aspect", aspect) != 0) - aspect = "16_9"; - if (aspect == "4_3_letterbox") - ddvd_set_video(m_ddvdconfig, DDVD_4_3_LETTERBOX, DDVD_PAL); - else if (aspect == "4_3_panscan") - ddvd_set_video(m_ddvdconfig, DDVD_4_3_PAN_SCAN, DDVD_PAL); - else - ddvd_set_video(m_ddvdconfig, DDVD_16_9, DDVD_PAL); + int fd = open("/proc/stb/video/aspect", O_RDONLY); + if (fd > -1) + { + rd = read(fd, tmp, 255); + if (rd > 2 && !strncmp(tmp, "4:3", 3)) + aspect = DDVD_4_3; + else if (rd > 4 && !strncmp(tmp, "16:10", 5)) + aspect = DDVD_16_10; + close(fd); + } + + fd = open("/proc/stb/video/policy", O_RDONLY); + if (fd > -1) + { + rd = read(fd, tmp, 255); + if (rd > 6 && !strncmp(tmp, "bestfit", 7)) + policy = DDVD_JUSTSCALE; + else if (rd > 8 && !strncmp(tmp, "letterbox", 9)) + policy = DDVD_LETTERBOX; + close(fd); + } + + ddvd_set_video(m_ddvdconfig, aspect, policy, DDVD_PAL /*unused*/); - ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, 720, 576, 4, 720*4); CONNECT(m_sn->activated, eServiceDVD::gotMessage); CONNECT(m_pump.recv_msg, eServiceDVD::gotThreadMessage); strcpy(m_ddvd_titlestring,""); @@ -158,8 +176,11 @@ void eServiceDVD::gotMessage(int /*what*/) } case DDVD_SCREEN_UPDATE: eDebug("DVD_SCREEN_UPDATE!"); - if (m_subtitle_widget) - m_subtitle_widget->setPixmap(m_pixmap, eRect(0, 0, 720, 576)); + if (m_subtitle_widget) { + int x1,x2,y1,y2; + ddvd_get_last_blit_area(m_ddvdconfig, &x1, &x2, &y1, &y2); + m_subtitle_widget->setPixmap(m_pixmap, eRect(x1, y1, (x2-x1)+1, (y2-y1)+1)); + } break; case DDVD_SHOWOSD_STATE_PLAY: { @@ -213,6 +234,14 @@ void eServiceDVD::gotMessage(int /*what*/) eDebug("DVD_SOF_REACHED!"); m_event(this, evSOF); break; + case DDVD_SHOWOSD_ANGLE: + { + int current, num; + ddvd_get_angle_info(m_ddvdconfig, ¤t, &num); + eDebug("DVD_ANGLE_INFO: %d / %d", current, num); + m_event(this, evUser+13); + break; + } case DDVD_SHOWOSD_TIME: { static struct ddvd_time last_info; @@ -259,6 +288,7 @@ eServiceDVD::~eServiceDVD() kill(); saveCuesheet(); ddvd_close(m_ddvdconfig); + disableSubtitles(0); } RESULT eServiceDVD::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection) @@ -272,7 +302,6 @@ RESULT eServiceDVD::start() assert(m_state == stIdle); m_state = stRunning; eDebug("eServiceDVD starting"); - run(); // m_event(this, evStart); return 0; } @@ -437,6 +466,7 @@ int eServiceDVD::getInfo(int w) } case sUser+6: case sUser+7: + case sUser+8: return resIsPyObject; default: return resNA; @@ -506,6 +536,16 @@ PyObject *eServiceDVD::getInfoObject(int w) } return tuple; } + case sUser+8: + { + ePyObject tuple = PyTuple_New(2); + int current, num; + ddvd_get_angle_info(m_ddvdconfig, ¤t, &num); + PyTuple_SetItem(tuple, 0, PyInt_FromLong(current)); + PyTuple_SetItem(tuple, 1, PyInt_FromLong(num)); + + return tuple; + } default: eDebug("unhandled getInfoObject(%d)", w); } @@ -514,13 +554,23 @@ PyObject *eServiceDVD::getInfoObject(int w) RESULT eServiceDVD::enableSubtitles(eWidget *parent, SWIG_PYOBJECT(ePyObject) /*entry*/) { - if (m_subtitle_widget) - delete m_subtitle_widget; + delete m_subtitle_widget; + m_subtitle_widget = new eSubtitleWidget(parent); m_subtitle_widget->resize(parent->size()); - m_subtitle_widget->setPixmap(m_pixmap, eRect(0, 0, 720, 576)); + + eSize size = parent->size(); + + if (!m_pixmap) + { + m_pixmap = new gPixmap(size, 32); + ddvd_set_lfb(m_ddvdconfig, (unsigned char *)m_pixmap->surface->data, size.width(), size.height(), 4, size.width()*4); + run(); // start the thread + } + m_subtitle_widget->setZPosition(-1); m_subtitle_widget->show(); + return 0; } @@ -655,6 +705,9 @@ RESULT eServiceDVD::keyPressed(int key) case iServiceKeys::keyUser+7: ddvd_send_key(m_ddvdconfig, DDVD_KEY_MENU); break; + case iServiceKeys::keyUser+8: + ddvd_send_key(m_ddvdconfig, DDVD_KEY_ANGLE); + break; default: return -1; } diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py b/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py index 1af90f13..b22c4b80 100644 --- a/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py +++ b/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py @@ -15,8 +15,9 @@ from Screens.TimeDateInput import TimeDateInput from Screens.TimerEntry import TimerEntry from Screens.EpgSelection import EPGSelection from Screens.TimerEdit import TimerSanityConflict +from Screens.MessageBox import MessageBox from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE -from RecordTimer import RecordTimerEntry, parseEvent +from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT from ServiceReference import ServiceReference from Tools.LoadPixmap import LoadPixmap from enigma import eEPGCache, eListbox, gFont, eListboxPythonMultiContent, \ @@ -41,6 +42,10 @@ class EPGList(HTMLComponent, GUIComponent): self.l.setSelectableFunc(self.isSelectable) self.epgcache = eEPGCache.getInstance() self.clock_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock.png')) + self.clock_add_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_add.png')) + self.clock_pre_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_pre.png')) + self.clock_post_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_post.png')) + self.clock_prepost_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_prepost.png')) self.time_base = None self.time_epoch = time_epoch self.list = None @@ -81,10 +86,10 @@ class EPGList(HTMLComponent, GUIComponent): return (event_list and len(event_list) and True) or False def setEpoch(self, epoch): - if self.cur_event is not None and self.cur_service is not None: - self.offs = 0 - self.time_epoch = epoch - self.fillMultiEPG(None) # refill +# if self.cur_event is not None and self.cur_service is not None: + self.offs = 0 + self.time_epoch = epoch + self.fillMultiEPG(None) # refill def getEventFromId(self, service, eventid): event = None @@ -92,14 +97,31 @@ class EPGList(HTMLComponent, GUIComponent): event = self.epgcache.lookupEventId(service.ref, eventid) return event + def moveToService(self,serviceref): + if serviceref is not None: + for x in range(len(self.list)): + if self.list[x][0] == serviceref.toString(): + self.instance.moveSelectionTo(x) + break + + def getIndexFromService(self, serviceref): + if serviceref is not None: + for x in range(len(self.list)): + if self.list[x][0] == serviceref.toString(): + return x + + def setCurrentIndex(self, index): + if self.instance is not None: + self.instance.moveSelectionTo(index) + def getCurrent(self): - if self.cur_service is None or self.cur_event is None: + if self.cur_service is None: return ( None, None ) old_service = self.cur_service #(service, service_name, events) events = self.cur_service[2] refstr = self.cur_service[0] - if not events or not len(events): - return ( None, None ) + if self.cur_event is None or not events or not len(events): + return ( None, ServiceReference(refstr) ) event = events[self.cur_event] #(event_id, event_title, begin_time, duration) eventid = event[0] service = ServiceReference(refstr) @@ -155,11 +177,12 @@ class EPGList(HTMLComponent, GUIComponent): def selectionChanged(self): for x in self.onSelChanged: if x is not None: - try: - x() - except: # FIXME!!! - print "FIXME in EPGList.selectionChanged" - pass + x() +# try: +# x() +# except: # FIXME!!! +# print "FIXME in EPGList.selectionChanged" +# pass GUI_WIDGET = eListbox @@ -204,7 +227,13 @@ class EPGList(HTMLComponent, GUIComponent): def buildEntry(self, service, service_name, events): r1=self.service_rect r2=self.event_rect - res = [ None, MultiContentEntryText(pos = (r1.left(),r1.top()), size = (r1.width(), r1.height()), font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_CENTER, text = service_name, color = self.foreColorService, backcolor = self.backColorService) ] + res = [ None, MultiContentEntryText( + pos = (r1.left(),r1.top()), + size = (r1.width(), r1.height()), + font = 0, flags = RT_HALIGN_LEFT | RT_VALIGN_CENTER, + text = service_name, + color = self.foreColorService, + backcolor = self.backColorService) ] if events: start = self.time_base+self.offs*self.time_epoch*60 @@ -220,11 +249,19 @@ class EPGList(HTMLComponent, GUIComponent): borderColor = self.borderColor for ev in events: #(event_id, event_title, begin_time, duration) - rec=ev[2] and self.timer.isInTimer(ev[0], ev[2], ev[3], service) > ((ev[3]/10)*8) + rec=ev[2] and self.timer.isInTimer(ev[0], ev[2], ev[3], service) xpos, ewidth = self.calcEntryPosAndWidthHelper(ev[2], ev[3], start, end, width) - res.append(MultiContentEntryText(pos = (left+xpos, top), size = (ewidth, height), font = 1, flags = RT_HALIGN_CENTER | RT_VALIGN_CENTER | RT_WRAP, text = ev[1], color = foreColor, color_sel = foreColorSelected, backcolor = backColor, backcolor_sel = backColorSelected, border_width = 1, border_color = borderColor)) + res.append(MultiContentEntryText( + pos = (left+xpos, top), size = (ewidth, height), + font = 1, flags = RT_HALIGN_CENTER | RT_VALIGN_CENTER | RT_WRAP, + text = ev[1], color = foreColor, color_sel = foreColorSelected, + backcolor = backColor, backcolor_sel = backColorSelected, border_width = 1, border_color = borderColor)) if rec and ewidth > 23: - res.append(MultiContentEntryPixmapAlphaTest(pos = (left+xpos+ewidth-22, top+height-22), size = (21, 21), png = self.clock_pixmap, backcolor = backColor, backcolor_sel = backColorSelected)) + res.append(MultiContentEntryPixmapAlphaTest( + pos = (left+xpos+ewidth-22, top+height-22), size = (21, 21), + png = self.getClockPixmap(service, ev[2], ev[3], ev[0]), + backcolor = backColor, + backcolor_sel = backColorSelected)) return res def selEntry(self, dir, visible=True): @@ -278,8 +315,13 @@ class EPGList(HTMLComponent, GUIComponent): self.time_base = int(stime) test = [ (service.ref.toString(), 0, self.time_base, self.time_epoch) for service in services ] test.insert(0, 'XRnITBD') +# print "BEFORE:" +# for x in test: +# print x epg_data = self.queryEPG(test) - +# print "EPG:" +# for x in epg_data: +# print x self.list = [ ] tmp_list = None service = "" @@ -310,6 +352,30 @@ class EPGList(HTMLComponent, GUIComponent): def resetOffset(self): self.offs = 0 + + def getClockPixmap(self, refstr, beginTime, duration, eventId): + pre_clock = 1 + post_clock = 2 + clock_type = 0 + endTime = beginTime + duration + for x in self.timer.timer_list: + if x.service_ref.ref.toString() == refstr: + if x.eit == eventId: + return self.clock_pixmap + beg = x.begin + end = x.end + if beginTime > beg and beginTime < end and endTime > end: + clock_type |= pre_clock + elif beginTime < beg and endTime > beg and endTime < end: + clock_type |= post_clock + if clock_type == 0: + return self.clock_add_pixmap + elif clock_type == pre_clock: + return self.clock_pre_pixmap + elif clock_type == post_clock: + return self.clock_post_pixmap + else: + return self.clock_prepost_pixmap class TimelineText(HTMLComponent, GUIComponent): def __init__(self): @@ -337,6 +403,12 @@ config.misc.graph_mepg_prev_time=ConfigClock(default = time()) config.misc.graph_mepg_prev_time_period=ConfigInteger(default=120, limits=(60,300)) class GraphMultiEPG(Screen): + EMPTY = 0 + ADD_TIMER = 1 + REMOVE_TIMER = 2 + + ZAP = 1 + def __init__(self, session, services, zapFunc=None, bouquetChangeCB=None): Screen.__init__(self, session) self.bouquetChangeCB = bouquetChangeCB @@ -345,7 +417,9 @@ class GraphMultiEPG(Screen): self.ask_time = now - tmp self.closeRecursive = False self["key_red"] = Button("") - self["key_green"] = Button(_("Add timer")) + self["key_green"] = Button("") + self.key_green_choice = self.EMPTY + self.key_red_choice = self.EMPTY self["timeline_text"] = TimelineText() self["Event"] = Event() self.time_lines = [ ] @@ -469,6 +543,7 @@ class GraphMultiEPG(Screen): #just used in multipeg def onCreate(self): self["list"].fillMultiEPG(self.services, self.ask_time) + self["list"].moveToService(self.session.nav.getCurrentlyPlayingServiceReference()) self.moveTimeLines() def eventViewCallback(self, setEvent, setService, val): @@ -486,22 +561,37 @@ class GraphMultiEPG(Screen): setEvent(cur[0]) def zapTo(self): - if self.zapFunc and self["key_red"].getText() == "Zap": + if self.zapFunc and self.key_red_choice == self.ZAP: self.closeRecursive = True ref = self["list"].getCurrent()[1] - self.zapFunc(ref.ref) + if ref: + self.zapFunc(ref.ref) def eventSelected(self): self.infoKeyPressed() + def removeTimer(self, timer): + timer.afterEvent = AFTEREVENT.NONE + self.session.nav.RecordTimer.removeEntry(timer) + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + def timerAdd(self): cur = self["list"].getCurrent() event = cur[0] serviceref = cur[1] if event is None: return - newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event)) - self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry) + eventid = event.getEventId() + refstr = serviceref.ref.toString() + for timer in self.session.nav.RecordTimer.timer_list: + if timer.eit == eventid and timer.service_ref.ref.toString() == refstr: + cb_func = lambda ret : not ret or self.removeTimer(timer) + self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName()) + break + else: + newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event)) + self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry) def finishedAdd(self, answer): print "finished add" @@ -509,32 +599,71 @@ class GraphMultiEPG(Screen): entry = answer[1] simulTimerList = self.session.nav.RecordTimer.record(entry) if simulTimerList is not None: - if (len(simulTimerList) == 2) and (simulTimerList[1].dontSave) and (simulTimerList[1].autoincrease): - simulTimerList[1].end = entry.begin - 30 - self.session.nav.RecordTimer.timeChanged(simulTimerList[1]) - self.session.nav.RecordTimer.record(entry) - else: + for x in simulTimerList: + if x.setAutoincreaseEnd(entry): + self.session.nav.RecordTimer.timeChanged(x) + simulTimerList = self.session.nav.RecordTimer.record(entry) + if simulTimerList is not None: self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList) + self["key_green"].setText(_("Remove timer")) + self.key_green_choice = self.REMOVE_TIMER else: - print "Timeredit aborted" + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + print "Timeredit aborted" def finishSanityCorrection(self, answer): self.finishedAdd(answer) def onSelectionChanged(self): - evt = self["list"].getCurrent() - self["Event"].newEvent(evt and evt[0]) - if evt and evt[0]: - evt = evt[0] - now = time() - start = evt.getBeginTime() - end = start + evt.getDuration() - if now >= start and now <= end: - self["key_red"].setText("Zap") - else: + cur = self["list"].getCurrent() + if cur is None: + if self.key_green_choice != self.EMPTY: + self["key_green"].setText("") + self.key_green_choice = self.EMPTY + if self.key_red_choice != self.EMPTY: self["key_red"].setText("") - + self.key_red_choice = self.EMPTY + return + + event = cur[0] + self["Event"].newEvent(event) + + if cur[1] is None or cur[1].getServiceName() == "": + if self.key_green_choice != self.EMPTY: + self["key_green"].setText("") + self.key_green_choice = self.EMPTY + if self.key_red_choice != self.EMPTY: + self["key_red"].setText("") + self.key_red_choice = self.EMPTY + return + elif self.key_red_choice != self.ZAP: + self["key_red"].setText("Zap") + self.key_red_choice = self.ZAP + + if not event: + if self.key_green_choice != self.EMPTY: + self["key_green"].setText("") + self.key_green_choice = self.EMPTY + return + + serviceref = cur[1] + eventid = event.getEventId() + refstr = serviceref.ref.toString() + isRecordEvent = False + for timer in self.session.nav.RecordTimer.timer_list: + if timer.eit == eventid and timer.service_ref.ref.toString() == refstr: + isRecordEvent = True + break + if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER: + self["key_green"].setText(_("Remove timer")) + self.key_green_choice = self.REMOVE_TIMER + elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER: + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + def moveTimeLines(self, force=False): + self.updateTimelineTimer.start((60-(int(time())%60))*1000) #keep syncronised l = self["list"] event_rect = l.getEventRect() time_epoch = l.getTimeEpoch() @@ -542,6 +671,7 @@ class GraphMultiEPG(Screen): if event_rect is None or time_epoch is None or time_base is None: return time_steps = time_epoch > 180 and 60 or 30 + num_lines = time_epoch/time_steps incWidth=event_rect.width()/num_lines pos=event_rect.left() @@ -569,8 +699,7 @@ class GraphMultiEPG(Screen): now=time() timeline_now = self["timeline_now"] if now >= time_base and now < (time_base + time_epoch * 60): - bla = (event_rect.width() * 1000) / time_epoch - xpos = ((now/60) - (time_base/60)) * bla / 1000 + xpos = int((((now - time_base) * event_rect.width()) / (time_epoch * 60))-(timeline_now.instance.size().width()/2)) old_pos = timeline_now.position new_pos = (xpos+event_rect.left(), old_pos[1]) if old_pos != new_pos: @@ -578,3 +707,6 @@ class GraphMultiEPG(Screen): timeline_now.visible = True else: timeline_now.visible = False + # here no l.l.invalidate() is needed when the zPosition in the skin is correct! + + diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py b/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py index 21d1bfe8..adb7015d 100644 --- a/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py +++ b/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py @@ -69,6 +69,7 @@ def changeBouquetCB(direction, epg): bouquet = bouquetSel.getCurrent() services = getBouquetServices(bouquet) if len(services): + global epg_bouquet epg_bouquet = bouquet epg.setServices(services) @@ -93,4 +94,5 @@ 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_EVENTINFO, fnc=main) ] + return [ PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EVENTINFO, fnc=main), + PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main) ] diff --git a/lib/python/Plugins/Extensions/Makefile.am b/lib/python/Plugins/Extensions/Makefile.am index 6b5d9735..9f3737aa 100644 --- a/lib/python/Plugins/Extensions/Makefile.am +++ b/lib/python/Plugins/Extensions/Makefile.am @@ -1,2 +1 @@ SUBDIRS = TuxboxPlugins FileManager CutListEditor PicturePlayer MediaScanner MediaPlayer IpkgInstaller GraphMultiEPG SocketMMI DVDPlayer DVDBurn -# SimpleRSS is still not finished diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index 0d5305d7..3e023841 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -1,6 +1,6 @@ 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, loadPic +from enigma import iPlayableService, eTimer, eServiceCenter, iServiceInformation, ePicLoad from ServiceReference import ServiceReference from Screens.Screen import Screen from Screens.HelpMenu import HelpableScreen @@ -35,18 +35,59 @@ class MyPlayList(PlayList): self.oldCurrPlaying = -1 class MediaPixmap(Pixmap): + def __init__(self): + Pixmap.__init__(self) + self.coverArtFileName = "" + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.paintCoverArtPixmapCB) + self.coverFileNames = ["folder.png", "folder.jpg"] + def applySkin(self, desktop, screen): - self.default_pixmap = None + from Tools.LoadPixmap import LoadPixmap + noCoverFile = None if self.skinAttributes is not None: for (attrib, value) in self.skinAttributes: if attrib == "pixmap": - self.default_pixmap = value + noCoverFile = value 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"] + if noCoverFile is None: + noCoverFile = resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/no_coverArt.png") + self.noCoverPixmap = LoadPixmap(noCoverFile) return Pixmap.applySkin(self, desktop, screen) + def onShow(self): + Pixmap.onShow(self) + sc = AVSwitch().getFramebufferScale() + #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB) + self.picload.setPara((self.instance.size().width(), self.instance.size().height(), sc[0], sc[1], False, 1, "#00000000")) + + def paintCoverArtPixmapCB(self, picInfo=None): + ptr = self.picload.getData() + if ptr != None: + self.instance.setPixmap(ptr.__deref__()) + + def updateCoverArt(self, path): + while not path.endswith("/"): + path = path[:-1] + new_coverArtFileName = None + for filename in self.coverFileNames: + if fileExists(path + filename): + new_coverArtFileName = path + filename + if self.coverArtFileName != new_coverArtFileName: + self.coverArtFileName = new_coverArtFileName + if new_coverArtFileName: + self.picload.startDecode(self.coverArtFileName) + else: + self.showDefaultCover() + + def showDefaultCover(self): + self.instance.setPixmap(self.noCoverPixmap) + + def embeddedCoverArt(self): + print "[embeddedCoverArt] found" + self.coverArtFileName = "/tmp/.id3coverart" + self.picload.startDecode(self.coverArtFileName) + class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoBarCueSheetSupport, InfoBarNotifications, InfoBarSubtitleSupport, HelpableScreen): ALLOW_SUSPEND = True ENABLE_RESUME_SUPPORT = True @@ -70,11 +111,10 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB # 'None' is magic to start at the list of mountpoints 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 = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|mkv|mp4|m4a|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() - #self.playlist = PlayList() self.is_closing = False self.delname = "" self["playlist"] = self.playlist @@ -83,15 +123,15 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self["currenttext"] = Label("") - self["artisttext"] = Label(_("Artist:")) + self["artisttext"] = Label(_("Artist")+':') self["artist"] = Label("") - self["titletext"] = Label(_("Title:")) + self["titletext"] = Label(_("Title")+':') self["title"] = Label("") - self["albumtext"] = Label(_("Album:")) + self["albumtext"] = Label(_("Album")+':') self["album"] = Label("") - self["yeartext"] = Label(_("Year:")) + self["yeartext"] = Label(_("Year")+':') self["year"] = Label("") - self["genretext"] = Label(_("Genre:")) + self["genretext"] = Label(_("Genre")+':') self["genre"] = Label("") self["coverArt"] = MediaPixmap() self["repeat"] = MultiPixmap() @@ -169,8 +209,6 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.leftKeyTimer.callback.append(self.leftTimerFire) self.currList = "filelist" - - self.coverArtFileName = "" self.isAudioCD = False self.AudioCD_albuminfo = {} self.cdAudioTrackFiles = [] @@ -187,7 +225,8 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB { iPlayableService.evUpdatedInfo: self.__evUpdatedInfo, iPlayableService.evUser+11: self.__evDecodeError, - iPlayableService.evUser+12: self.__evPluginError + iPlayableService.evUser+12: self.__evPluginError, + iPlayableService.evUser+13: self["coverArt"].embeddedCoverArt }) def doNothing(self): @@ -206,6 +245,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB config.mediaplayer.defaultDir.setValue(self.filelist.getCurrentDirectory()) config.mediaplayer.defaultDir.save() hotplugNotifier.remove(self.hotplugCB) + del self["coverArt"].picload self.close() def checkSkipShowHideLock(self): @@ -285,19 +325,6 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB if self[name].getText() != info: self[name].setText(info) - def updateCoverArtPixmap(self, path): - while not path.endswith("/"): - path = path[:-1] - 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 self.leftKeyTimer.start(1000) @@ -456,17 +483,20 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB else: menu.append((_("add files to playlist"), "copyfiles")) menu.append((_("switch to playlist"), "playlist")) - menu.append((_("delete file"), "deletefile")) + if config.usage.setup_level.index >= 1: # intermediate+ + menu.append((_("delete file"), "deletefile")) else: menu.append((_("switch to filelist"), "filelist")) - menu.append((_("shuffle playlist"), "shuffle")) - menu.append((_("Delete entry"), "deleteentry")) menu.append((_("clear playlist"), "clear")) + menu.append((_("Delete entry"), "deleteentry")) + if config.usage.setup_level.index >= 1: # intermediate+ + menu.append((_("shuffle playlist"), "shuffle")) menu.append((_("hide player"), "hide")); - menu.append((_("save playlist"), "saveplaylist")); menu.append((_("load playlist"), "loadplaylist")); - menu.append((_("delete saved playlist"), "deleteplaylist")); - menu.append((_("Edit settings"), "settings")) + if config.usage.setup_level.index >= 1: # intermediate+ + menu.append((_("save playlist"), "saveplaylist")); + menu.append((_("delete saved playlist"), "deleteplaylist")); + menu.append((_("Edit settings"), "settings")) self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu) def menuCallback(self, choice): @@ -629,12 +659,16 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def copyDirectory(self, directory, recursive = True): print "copyDirectory", directory - filelist = FileList(directory, useServiceRef = True, isTop = True) + if directory == '/': + print "refusing to operate on /" + return + filelist = FileList(directory, useServiceRef = True, showMountpoints = False, isTop = True) for x in filelist.getFileList(): if x[0][1] == True: #isDir if recursive: - self.copyDirectory(x[0][0]) + if x[0][0] != directory: + self.copyDirectory(x[0][0]) elif filelist.getServiceRef() and filelist.getServiceRef().type == 4097: self.playlist.addFile(x[0][0]) self.playlist.updateList() @@ -775,6 +809,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def playEntry(self): if len(self.playlist.getServiceRefList()): + audio_extensions = (".mp2", ".mp3", ".wav", ".ogg", "flac", "m4a") needsInfoUpdate = False currref = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()] if self.session.nav.getCurrentlyPlayingServiceReference() is None or currref != self.session.nav.getCurrentlyPlayingServiceReference(): @@ -790,7 +825,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB ext = text[-4:].lower() # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead - if ext not in [".mp2", ".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD: + if ext not in audio_extensions and not self.isAudioCD: self.hide() else: needsInfoUpdate = True @@ -817,7 +852,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB currref = self.playlist.getServiceRefList()[idx] text = currref.getPath() ext = text[-4:].lower() - if ext not in [".mp2", ".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD: + if ext not in audio_extensions and not self.isAudioCD: self.hide() else: needsInfoUpdate = True @@ -825,11 +860,9 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.unPauseService() if needsInfoUpdate == True: path = self.playlist.getServiceRefList()[self.playlist.getCurrentIndex()].getPath() - self.updateCoverArtPixmap(path) + self["coverArt"].updateCoverArt(path) else: - pngname = self["coverArt"].default_pixmap - self.coverArtFileName = pngname - self["coverArt"].instance.setPixmapFromFile(self.coverArtFileName) + self["coverArt"].showDefaultCover() self.readTitleInformation() def updatedSeekState(self): @@ -863,17 +896,22 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB 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) + if dev == harddiskmanager.getCD(): + if media_state == "1": + 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) + else: + self.cdAudioTrackFiles = [] + if self.isAudioCD: + self.clear_playlist() class MediaPlayerLCDScreen(Screen): skin = """ diff --git a/lib/python/Plugins/Extensions/MediaPlayer/settings.py b/lib/python/Plugins/Extensions/MediaPlayer/settings.py index c6d274bd..416ab2ee 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/settings.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/settings.py @@ -3,30 +3,10 @@ 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.config import config, getConfigListEntry, ConfigSubsection, configfile, ConfigText, ConfigYesNo, ConfigDirectory 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) diff --git a/lib/python/Plugins/Extensions/MediaScanner/plugin.py b/lib/python/Plugins/Extensions/MediaScanner/plugin.py index 7d57ce0b..88b917ee 100644 --- a/lib/python/Plugins/Extensions/MediaScanner/plugin.py +++ b/lib/python/Plugins/Extensions/MediaScanner/plugin.py @@ -17,6 +17,7 @@ def mountpoint_choosen(option): from Screens.ChoiceBox import ChoiceBox + print "scanning", option (description, mountpoint, session) = option res = scanDevice(mountpoint) diff --git a/lib/python/Plugins/Extensions/PicturePlayer/plugin.py b/lib/python/Plugins/Extensions/PicturePlayer/plugin.py index ea906f0d..05adb633 100644 --- a/lib/python/Plugins/Extensions/PicturePlayer/plugin.py +++ b/lib/python/Plugins/Extensions/PicturePlayer/plugin.py @@ -1,384 +1,151 @@ -from enigma import eTimer, loadPic, getExif +from enigma import ePicLoad, eTimer, getDesktop + from Screens.Screen import Screen -from Screens.ServiceInfo import ServiceInfoList, ServiceInfoListEntry -from Components.ActionMap import ActionMap, NumberActionMap +from Tools.Directories import resolveFilename, pathExists, fileExists, SCOPE_MEDIA +from Plugins.Plugin import PluginDescriptor + from Components.Pixmap import Pixmap, MovingPixmap +from Components.ActionMap import ActionMap, NumberActionMap from Components.Label import Label - -from Components.ConfigList import ConfigList -from Components.config import * - -from Tools.Directories import resolveFilename, fileExists, pathExists, createDir, SCOPE_MEDIA +from Components.Button import Button from Components.FileList import FileList from Components.AVSwitch import AVSwitch +from Components.Sources.List import List +from Components.ConfigList import ConfigList -from Plugins.Plugin import PluginDescriptor +from Components.config import config, ConfigSubsection, ConfigInteger, ConfigSelection, ConfigText, ConfigEnableDisable, KEY_LEFT, KEY_RIGHT, KEY_0, getConfigListEntry + +def getScale(): + return AVSwitch().getFramebufferScale() config.pic = ConfigSubsection() -config.pic.slidetime = ConfigInteger(default=10, limits=(5, 60)) -config.pic.resize = ConfigSelection(default="0", choices = [("0", _("simple")), ("1", _("better"))]) +config.pic.framesize = ConfigInteger(default=30, limits=(5, 99)) +config.pic.slidetime = ConfigInteger(default=10, limits=(10, 60)) +config.pic.resize = ConfigSelection(default="1", choices = [("0", _("simple")), ("1", _("better"))]) config.pic.cache = ConfigEnableDisable(default=True) config.pic.lastDir = ConfigText(default=resolveFilename(SCOPE_MEDIA)) -config.pic.rotate = ConfigSelection(default="0", choices = [("0", _("none")), ("1", _("manual")), ("2", _("by Exif"))]) - -def getAspect(): - val = AVSwitch().getAspectRatioSetting() - return val/2 +config.pic.infoline = ConfigEnableDisable(default=True) +config.pic.loop = ConfigEnableDisable(default=True) +config.pic.bgcolor = ConfigSelection(default="#00000000", choices = [("#00000000", _("black")),("#009eb9ff", _("blue")),("#00ff5a51", _("red")), ("#00ffe875", _("yellow")), ("#0038FF48", _("green"))]) +config.pic.textcolor = ConfigSelection(default="#0038FF48", choices = [("#00000000", _("black")),("#009eb9ff", _("blue")),("#00ff5a51", _("red")), ("#00ffe875", _("yellow")), ("#0038FF48", _("green"))]) -#------------------------------------------------------------------------------------------ +class picshow(Screen): + def __init__(self, session): + self.skin = """<screen position="80,80" size="560,440" title="PicturePlayer" > + <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" alphatest="on" /> + <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" alphatest="on" /> + <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" alphatest="on" /> + <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" alphatest="on" /> + <widget name="key_red" position="0,0" size="140,40" font="Regular;20" backgroundColor="#9f1313" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> + <widget name="key_green" position="140,0" size="140,40" font="Regular;20" backgroundColor="#1f771f" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> + <widget name="key_yellow" position="280,0" size="140,40" font="Regular;20" backgroundColor="#a08500" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> + <widget name="key_blue" position="420,0" size="140,40" font="Regular;20" backgroundColor="#18188b" zPosition="2" transparent="1" shadowColor="black" shadowOffset="-1,-1" /> + <widget name="label" position="5,55" size="350,140" font="Regular;19" /> + <widget name="thn" position="360,40" size="180,160" alphatest="on" /> + <widget name="filelist" position="5,205" zPosition="2" size="550,230" scrollbarMode="showOnDemand" /> + </screen>""" -class ThumbView(Screen): - skin = """ - <screen position="0,0" size="720,576" flags="wfNoBorder" title="ThumbView" > - <eLabel position="0,0" zPosition="0" size="720,576" backgroundColor="black" /> - <widget name="frame" position="50,63" size="190,200" pixmap="pic_frame.png" zPosition="1" alphatest="on" /> - <widget name="label0" position="55,240" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" /> - <widget name="label1" position="270,240" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" /> - <widget name="label2" position="485,240" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" /> - <widget name="label3" position="55,465" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" /> - <widget name="label4" position="270,465" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" /> - <widget name="label5" position="485,465" size="180,20" font="Regular;13" halign="center" zPosition="2" transparent="1" /> - <widget name="thumb0" position="55,68" size="180,160" zPosition="2" transparent="1" /> - <widget name="thumb1" position="270,68" size="180,160" zPosition="2" transparent="1" /> - <widget name="thumb2" position="485,68" size="180,160" zPosition="2" transparent="1" /> - <widget name="thumb3" position="55,293" size="180,160" zPosition="2" transparent="1" /> - <widget name="thumb4" position="270,293" size="180,160" zPosition="2" transparent="1" /> - <widget name="thumb5" position="485,293" size="180,160" zPosition="2" transparent="1" /> - </screen>""" - - def __init__(self, session, filelist, name, path): - self.skin = ThumbView.skin Screen.__init__(self, session) - self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "MovieSelectionActions"], + self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions"], { - "cancel": self.Exit, - "ok": self.KeyOk, - "showEventInfo": self.StartExif, - "right": self.key_right, - "left": self.key_left, - "up": self.key_up, - "down": self.key_down + "cancel": self.KeyExit, + "red": self.KeyRed, + "yellow": self.KeyYellow, + "blue": self.KeyBlue, + "ok": self.KeyOk }, -1) - - for x in range(6): - self["label"+str(x)] = Label() - self["thumb"+str(x)] = Pixmap() - self["frame"] = MovingPixmap() - - self.aspect = getAspect() - self.path = path - self.filelist = filelist - self.currPage = -1 - self.index = 0 - self.old_index = 0 - self.thumblist = [] - self.thumbindex = 0 - self.list = [] - self.poslist = [[50,63],[265,63],[480,63],[50,288],[265,288],[480,288]] - - count=0 - pos=0 - for x in self.filelist: - if x[0][1] == False: - self.list.append((x[0][0], self.path + x[0][0], count/6, pos, "(" + str(count+1) + ") ")) - pos += 1 - if pos == 6: - pos = 0 - if x[0][0] == name: - self.index = count - count += 1 - self.maxentry = len(self.list)-1 - - if self.maxentry < 0: - self["label0"].setText(_("no Picture found")) - - self.ThumbTimer = eTimer() - self.ThumbTimer.callback.append(self.showThumb) - self.fillPage() - - def key_left(self): - self.index -= 1 - if self.index < 0: - self.index = self.maxentry - self.fillPage() - - def key_right(self): - self.index += 1 - if self.index > self.maxentry: - self.index = 0 - self.fillPage() - - def key_up(self): - self.index -= 3 - if self.index < 0: - self.index = 0 - self.fillPage() - - def key_down(self): - self.index += 3 - if self.index > self.maxentry: - self.index = self.maxentry - self.fillPage() - - def fillPage(self): - if self.maxentry < 0: - return + self["key_red"] = Button(_("Thumbnails")) + self["key_green"] = Button() + self["key_yellow"] = Button(_("Exif")) + self["key_blue"] = Button(_("Setup")) + self["label"] = Label() + self["thn"] = Pixmap() - self["frame"].moveTo(self.poslist[self.list[self.index][3]][0], self.poslist[self.list[self.index][3]][1], 1) - self["frame"].startMoving() - - if self.list[self.index][2] != self.currPage: - self.currPage = self.list[self.index][2] - textlist = ["","","","","",""] - self.thumblist = ["","","","","",""] - - for x in self.list: - if x[2] == self.currPage: - textlist[x[3]] = x[4] + x[0] - self.thumblist[x[3]] = x[0] - - for x in range(6): - self["label"+str(x)].setText(textlist[x]) - self["thumb"+str(x)].hide() - - self.ThumbTimer.start(500, True) - - def showThumb(self): - if self.thumblist[self.thumbindex] != "": - cachefile = "" - if config.pic.cache.value: - cachedir = self.path + ".Thumbnails/" - cachefile = cachedir + self.thumblist[self.thumbindex] + str(180) + str(160) + str(self.aspect) - if not pathExists(cachedir): - 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, 1) - if ptr != None: - self["thumb"+str(self.thumbindex)].show() - self["thumb"+str(self.thumbindex)].instance.setPixmap(ptr) - - self.thumbindex += 1 - if self.thumbindex < 6: - self.ThumbTimer.start(500, True) - else: - self.thumbindex = 0 - else: - self.thumbindex = 0 - - def StartExif(self): - if self.maxentry < 0: - return - - self.session.open(ExifView, self.list[self.index][1], self.list[self.index][0]) - - def KeyOk(self): - if self.maxentry < 0: - return - - self.old_index = self.index - self.session.openWithCallback(self.returnView ,PicView, self.filelist, self.list[self.index][0], self.path) - - def returnView(self, val=0): - self.index = val - if self.old_index != self.index: - self.fillPage() - - def Exit(self): - self.close(self.index) - -#------------------------------------------------------------------------------------------ - -class PicView(Screen): - skin = """ - <screen position="0,0" size="720,576" flags="wfNoBorder" title="PicturePlayer" > - <eLabel position="0,0" zPosition="0" size="720,576" backgroundColor="black" /> - <widget name="picture" position="80,50" size="560,450" zPosition="1" transparent="1" /> - <widget name="point" position="80,515" size="14,14" zPosition="1" pixmap="skin_default/icons/record.png" alphatest="on" /> - <widget name="file" position="150,510" size="350,30" font="Regular;20" halign="center" zPosition="1" transparent="1" /> - <ePixmap position="500,515" size="36,20" pixmap="skin_default/buttons/key_info.png" zPosition="1" alphatest="on" /> - <ePixmap position="550,515" size="20,20" pixmap="skin_default/icons/ico_mp_rewind.png" zPosition="1" alphatest="on" /> - <widget name="play" position="575,515" size="20,20" pixmap="skin_default/icons/ico_mp_play.png" zPosition="1" alphatest="on" /> - <widget name="pause" position="600,515" size="20,20" pixmap="skin_default/icons/ico_mp_pause.png" zPosition="1" alphatest="on" /> - <ePixmap position="625,515" size="20,20" pixmap="skin_default/icons/ico_mp_forward.png" zPosition="1" alphatest="on" /> - </screen>""" - - def __init__(self, session, filelist, name, path): - self.skin = PicView.skin - Screen.__init__(self, session) - - self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "MovieSelectionActions"], - { - "cancel": self.Exit, - "showEventInfo": self.StartExif, - "green": self.Play, - "yellow": self.Pause, - "blue": self.nextPic, - "red": self.prevPic - }, -1) - - self.aspect = getAspect() - self.blinking = False - self.autoShow = True - self.slideOn = False - self.pauseOn = False - self.index = 0 - self.old = 0 - self.list = [] - - count=0 - for x in filelist: - if x[0][1] == False: - self.list.append((x[0][0], path + x[0][0], 0)) - if x[0][0] == name: - self.index = count - count += 1 - self.maxentry = len(self.list)-1 + currDir = config.pic.lastDir.value + if not pathExists(currDir): + currDir = "/" - self["file"] = Label(_("please wait, loading picture...")) - self["picture"] = Pixmap() - self["point"] = Pixmap() - self["play"] = Pixmap() - self["pause"] = Pixmap() + self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)") + self["filelist"] = self.filelist + self["filelist"].onSelectionChanged.append(self.selectionChanged) - self.decodeTimer = eTimer() - self.decodeTimer.callback.append(self.decodePic) - self.decodeTimer.start(300, True) + self.ThumbTimer = eTimer() + self.ThumbTimer.callback.append(self.showThumb) - self.slideTimer = eTimer() - self.slideTimer.callback.append(self.slidePic) - - - def Pause(self): - if self.slideOn: - if self.pauseOn: - self.pauseOn=False - self["pause"].show() - else: - self.pauseOn=True - self["play"].show() - self.slideValue = 0 - - def Play(self): - if self.pauseOn == False: - if self.slideOn: - self.slideOn=False - self["play"].show() - else: - self.slideOn=True - self.slideTimer.start(1000, True) - - self.slideValue = int(config.pic.slidetime.value) + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.showPic) - def slidePic(self): - if self.slideOn == True and self.pauseOn == False: - self.blinkingWidget("play") - self.slideValue -= 1 - if self.slideValue <= 0: - self.slideValue = int(config.pic.slidetime.value) - self.nextPic() - - self.slideTimer.start(1000, True) + self.onLayoutFinish.append(self.setConf) - if self.pauseOn: - self.blinkingWidget("pause") - self.slideTimer.start(1000, True) + def showPic(self, picInfo=""): + ptr = self.picload.getData() + if ptr != None: + self["thn"].instance.setPixmap(ptr.__deref__()) + self["thn"].show() - def decodePic(self): - self.currPic = loadPic(self.list[self.index][1], 560, 450, self.aspect, int(config.pic.resize.value), int(config.pic.rotate.value),1) - self["point"].hide() - if self.autoShow: - self.showPic() - self.autoShow = False + text = picInfo.split('\n',1) + self["label"].setText(text[1]) + self["label"].show() - def showPic(self): - if self.currPic != None: - self.old = self.index - self["file"].setText(self.list[self.old][0] + " (" + str(self.old+1) + "/" + str(self.maxentry+1) + ")") - self["picture"].instance.setPixmap(self.currPic) + def showThumb(self): + if not self.filelist.canDescent(): + if self.filelist.getCurrentDirectory() and self.filelist.getFilename(): + if self.picload.getThumbnail(self.filelist.getCurrentDirectory() + self.filelist.getFilename()) == 1: + self.ThumbTimer.start(500, True) - self.next() - self["point"].show() - self.decodeTimer.start(300, True) - - def nextPic(self): - self.showPic() - - def prevPic(self): - self.index = self.old - self.prev() - self.autoShow = True - self["point"].show() - self.decodeTimer.start(300, True) + def selectionChanged(self): + if not self.filelist.canDescent(): + self.ThumbTimer.start(500, True) + else: + self["label"].hide() + self["thn"].hide() - def next(self): - self.index += 1 - if self.index > self.maxentry: - self.index = 0 + def KeyRed(self): + #if not self.filelist.canDescent(): + self.session.openWithCallback(self.callbackView, Pic_Thumb, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory()) + + def KeyYellow(self): + if not self.filelist.canDescent(): + self.session.open(Pic_Exif, self.picload.getInfo(self.filelist.getCurrentDirectory() + self.filelist.getFilename())) + + def KeyBlue(self): + self.session.openWithCallback(self.setConf ,Pic_Setup) - def prev(self): - self.index -= 1 - if self.index < 0: - self.index = self.maxentry - - def blinkingWidget(self, name): - if self.blinking: - self.blinking=False - self[name].show() + def KeyOk(self): + if self.filelist.canDescent(): + self.filelist.descent() else: - self.blinking=True - self[name].hide() + self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist.getFileList(), self.filelist.getSelectionIndex(), self.filelist.getCurrentDirectory()) - def StartExif(self): - if self.pauseOn == False: - self.Pause() - self.session.openWithCallback(self.StopExif ,ExifView, self.list[self.old][1], self.list[self.old][0]) + def setConf(self): + sc = getScale() + #0=Width 1=Height 2=Aspect 3=use_cache 4=resize_type 5=Background(#AARRGGBB) + self.picload.setPara((self["thn"].instance.size().width(), self["thn"].instance.size().height(), sc[0], sc[1], config.pic.cache.value, int(config.pic.resize.value), "#00000000")) - def StopExif(self): - if self.pauseOn: - self.Pause() - - def Exit(self): - self.close(self.old) + def callbackView(self, val=0): + if val > 0: + self.filelist.moveToIndex(val) -#------------------------------------------------------------------------------------------ + def KeyExit(self): + del self.picload -class ExifView(Screen): - skin = """ - <screen position="80,130" size="560,320" title="Exif-Data" > - <widget name="exiflist" position="5,5" size="550,310" selectionDisabled="1" /> - </screen>""" - - def __init__(self, session, fullname, name): - self.skin = ExifView.skin - Screen.__init__(self, session) + if self.filelist.getCurrentDirectory() is None: + config.pic.lastDir.value = "/" + else: + config.pic.lastDir.value = self.filelist.getCurrentDirectory() - self["actions"] = ActionMap(["OkCancelActions"], - { - "cancel": self.close - }, -1) - - dlist = ["Name:", "EXIF-Version:", "Camera-Make:", "Camera-Model:", "Date/Time:", "User Comments:", "Width / Height:", "Orientation:", "Metering Mode:", "Exposure Program:", "Light Source:", "Flash used:", "CompressedBitsPerPixel:", "ISO Speed Rating:", "X-Resolution:", "Y-Resolution:", "Resolution Unit:", "Brightness:", "Exposure Time:", "Exposure Bias:", "Distance:", "CCD-Width:", "ApertureFNumber:"] - tlist = [ ] - self["exiflist"] = ServiceInfoList(tlist) - tlist.append(ServiceInfoListEntry(dlist[0], name)) - count=1 - for x in getExif(fullname): - tlist.append(ServiceInfoListEntry(dlist[count], x)) - count += 1 + config.pic.save() + self.close() #------------------------------------------------------------------------------------------ -class PicSetup(Screen): - skin = """ - <screen position="160,220" size="400,120" title="Settings" > - <widget name="liste" position="10,10" size="380,100" /> - </screen>""" - +class Pic_Setup(Screen): def __init__(self, session): - self.skin = PicSetup.skin + self.skin = """<screen position="120,180" size="480,210" title="Settings" > + <widget name="liste" position="5,5" size="470,200" /> + </screen>""" Screen.__init__(self, session) self["actions"] = NumberActionMap(["SetupActions"], @@ -398,12 +165,16 @@ class PicSetup(Screen): "9": self.keyNumber }, -1) - self.list = [] - self["liste"] = ConfigList(self.list) - self.list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime)) - self.list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize)) - self.list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache)) - #self.list.append(getConfigListEntry(_("Rotate Picture"), config.pic.rotate)) + list = [] + self["liste"] = ConfigList(list) + list.append(getConfigListEntry(_("Slideshow Interval (sec.)"), config.pic.slidetime)) + list.append(getConfigListEntry(_("Scaling Mode"), config.pic.resize)) + list.append(getConfigListEntry(_("Cache Thumbnails"), config.pic.cache)) + list.append(getConfigListEntry(_("show Infoline"), config.pic.infoline)) + list.append(getConfigListEntry(_("Frame size in full view"), config.pic.framesize)) + list.append(getConfigListEntry(_("slide picture in loop"), config.pic.loop)) + list.append(getConfigListEntry(_("backgroundcolor"), config.pic.bgcolor)) + list.append(getConfigListEntry(_("textcolor"), config.pic.textcolor)) def keyLeft(self): self["liste"].handleKey(KEY_LEFT) @@ -414,126 +185,390 @@ class PicSetup(Screen): def keyNumber(self, number): self["liste"].handleKey(KEY_0 + number) +#--------------------------------------------------------------------------- + +class Pic_Exif(Screen): + def __init__(self, session, exiflist): + self.skin = """<screen position="80,120" size="560,360" title="Info" > + <widget source="menu" render="Listbox" position="0,0" size="560,360" scrollbarMode="showOnDemand" selectionDisabled="1" > + <convert type="TemplatedMultiContent"> + {"template": [ MultiContentEntryText(pos = (5, 5), size = (250, 30), flags = RT_HALIGN_LEFT, text = 0), MultiContentEntryText(pos = (260, 5), size = (290, 30), flags = RT_HALIGN_LEFT, text = 1)], "fonts": [gFont("Regular", 20)], "itemHeight": 30 } + </convert> + </widget> + </screen>""" + Screen.__init__(self, session) -#------------------------------------------------------------------------------------------ + self["actions"] = ActionMap(["OkCancelActions"], + { + "cancel": self.close + }, -1) + + exifdesc = [_("filename")+':', "EXIF-Version:", "Make:", "Camera:", "Date/Time:", "Width / Height:", "Flash used:", "Orientation:", "User Comments:", "Metering Mode:", "Exposure Program:", "Light Source:", "CompressedBitsPerPixel:", "ISO Speed Rating:", "X-Resolution:", "Y-Resolution:", "Resolution Unit:", "Brightness:", "Exposure Time:", "Exposure Bias:", "Distance:", "CCD-Width:", "ApertureFNumber:"] + list = [] -class picmain(Screen): - skin = """ - <screen position="160,90" size="400,390" title="PicturePlayer" > - <ePixmap position="10,40" size="36,20" pixmap="skin_default/buttons/key_menu.png" transparent="1" alphatest="on" /> - <ePixmap position="10,70" size="36,20" pixmap="skin_default/buttons/key_info.png" transparent="1" alphatest="on" /> - <ePixmap position="12,100" size="36,20" pixmap="skin_default/buttons/key_red.png" transparent="1" alphatest="on" /> - <eLabel text="Settings" position="60,40" size="120,25" font="Regular;20" transparent="1" /> - <eLabel text="Exif-Data" position="60,70" size="120,25" font="Regular;20" transparent="1" /> - <eLabel text="Thumbnails" position="60,100" size="120,25" font="Regular;20" transparent="1" /> - <widget name="thumbnail" position="200,5" size="180,160" alphatest="on" /> - <widget name="filelist" position="5,170" zPosition="2" size="390,210" scrollbarMode="showOnDemand" /> - </screen>""" - - def __init__(self, session): - self.skin = picmain.skin + for x in range(len(exiflist)): + if x>0: + list.append((exifdesc[x], exiflist[x])) + else: + name = exiflist[x].split('/')[-1] + list.append((exifdesc[x], name)) + self["menu"] = List(list) + +#---------------------------------------------------------------------------------------- + +T_INDEX = 0 +T_FRAME_POS = 1 +T_PAGE = 2 +T_NAME = 3 +T_FULL = 4 + +class Pic_Thumb(Screen): + def __init__(self, session, piclist, lastindex, path): + + self.textcolor = config.pic.textcolor.value + self.color = config.pic.bgcolor.value + textsize = 20 + self.spaceX = 35 + self.picX = 190 + self.spaceY = 30 + self.picY = 200 + + size_w = getDesktop(0).size().width() + size_h = getDesktop(0).size().height() + self.thumbsX = size_w / (self.spaceX + self.picX) # thumbnails in X + self.thumbsY = size_h / (self.spaceY + self.picY) # thumbnails in Y + self.thumbsC = self.thumbsX * self.thumbsY # all thumbnails + + self.positionlist = [] + skincontent = "" + + posX = -1 + for x in range(self.thumbsC): + posY = x / self.thumbsX + posX += 1 + if posX >= self.thumbsX: + posX = 0 + + absX = self.spaceX + (posX*(self.spaceX + self.picX)) + absY = self.spaceY + (posY*(self.spaceY + self.picY)) + self.positionlist.append((absX, absY)) + skincontent += "<widget name=\"label" + str(x) + "\" position=\"" + str(absX+5) + "," + str(absY+self.picY-textsize) + "\" size=\"" + str(self.picX - 10) + "," + str(textsize) + "\" font=\"Regular;14\" zPosition=\"2\" transparent=\"1\" noWrap=\"1\" foregroundColor=\"" + self.textcolor + "\" />" + + skincontent += "<widget name=\"thumb" + str(x) + "\" position=\"" + str(absX+5)+ "," + str(absY+5) + "\" size=\"" + str(self.picX -10) + "," + str(self.picY - (textsize*2)) + "\" zPosition=\"2\" transparent=\"1\" alphatest=\"on\" />" + + + # Screen, backgroundlabel and MovingPixmap + self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \ + <eLabel position=\"0,0\" zPosition=\"0\" size=\""+ str(size_w) + "," + str(size_h) + "\" backgroundColor=\"" + self.color + "\" /><widget name=\"frame\" position=\"35,30\" size=\"190,200\" pixmap=\"pic_frame.png\" zPosition=\"1\" alphatest=\"on\" />" + skincontent + "</screen>" + Screen.__init__(self, session) - - self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ColorActions", "MovieSelectionActions"], + + self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"], { - "ok": self.KeyOk, "cancel": self.Exit, - "right": self.rightDown, - "left": self.leftUp, - "up": self.up, - "down": self.down, + "ok": self.KeyOk, + "left": self.key_left, + "right": self.key_right, + "up": self.key_up, + "down": self.key_down, "showEventInfo": self.StartExif, - "contextMenu": self.Settings, - "red": self.StartThumb }, -1) - self.aspect = getAspect() - currDir = config.pic.lastDir.value - if not pathExists(currDir): - currDir = "/" + self["frame"] = MovingPixmap() + for x in range(self.thumbsC): + self["label"+str(x)] = Label() + self["thumb"+str(x)] = Pixmap() + + self.Thumbnaillist = [] + self.filelist = [] + self.currPage = -1 + self.dirlistcount = 0 + self.path = path - self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(jpeg|jpg|jpe|png|bmp|gif)") - self["filelist"] = self.filelist - self["thumbnail"] = Pixmap() + index = 0 + framePos = 0 + Page = 0 + for x in piclist: + if x[0][1] == False: + self.filelist.append((index, framePos, Page, x[0][0], path + x[0][0])) + index += 1 + framePos += 1 + if framePos > (self.thumbsC -1): + framePos = 0 + Page += 1 + else: + self.dirlistcount += 1 + + self.maxentry = len(self.filelist)-1 + self.index = lastindex - self.dirlistcount + if self.index < 0: + self.index = 0 + + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.showPic) + + self.onLayoutFinish.append(self.setPicloadConf) self.ThumbTimer = eTimer() - self.ThumbTimer.callback.append(self.showThumb) - self.ThumbTimer.start(500, True) + self.ThumbTimer.callback.append(self.showPic) + + def setPicloadConf(self): + sc = getScale() + self.picload.setPara([self["thumb0"].instance.size().width(), self["thumb0"].instance.size().height(), sc[0], sc[1], config.pic.cache.value, int(config.pic.resize.value), self.color]) + self.paintFrame() + + def paintFrame(self): + #print "index=" + str(self.index) + if self.maxentry < self.index or self.index < 0: + return + + pos = self.positionlist[self.filelist[self.index][T_FRAME_POS]] + self["frame"].moveTo( pos[0], pos[1], 1) + self["frame"].startMoving() - def up(self): - self["filelist"].up() - self.ThumbTimer.start(1500, True) + if self.currPage != self.filelist[self.index][T_PAGE]: + self.currPage = self.filelist[self.index][T_PAGE] + self.newPage() + + def newPage(self): + self.Thumbnaillist = [] + #clear Labels and Thumbnail + for x in range(self.thumbsC): + self["label"+str(x)].setText("") + self["thumb"+str(x)].hide() + #paint Labels and fill Thumbnail-List + for x in self.filelist: + if x[T_PAGE] == self.currPage: + self["label"+str(x[T_FRAME_POS])].setText("(" + str(x[T_INDEX]+1) + ") " + x[T_NAME]) + self.Thumbnaillist.append([0, x[T_FRAME_POS], x[T_FULL]]) + + #paint Thumbnail start + self.showPic() - def down(self): - self["filelist"].down() - self.ThumbTimer.start(1500, True) + def showPic(self, picInfo=""): + for x in range(len(self.Thumbnaillist)): + if self.Thumbnaillist[x][0] == 0: + if self.picload.getThumbnail(self.Thumbnaillist[x][2]) == 1: #zu tun probier noch mal + self.ThumbTimer.start(500, True) + else: + self.Thumbnaillist[x][0] = 1 + break + elif self.Thumbnaillist[x][0] == 1: + self.Thumbnaillist[x][0] = 2 + ptr = self.picload.getData() + if ptr != None: + self["thumb" + str(self.Thumbnaillist[x][1])].instance.setPixmap(ptr.__deref__()) + self["thumb" + str(self.Thumbnaillist[x][1])].show() + + def key_left(self): + self.index -= 1 + if self.index < 0: + self.index = self.maxentry + self.paintFrame() - def leftUp(self): - self["filelist"].pageUp() - self.ThumbTimer.start(1500, True) + def key_right(self): + self.index += 1 + if self.index > self.maxentry: + self.index = 0 + self.paintFrame() - def rightDown(self): - self["filelist"].pageDown() - self.ThumbTimer.start(1500, True) + def key_up(self): + self.index -= self.thumbsX + if self.index < 0: + self.index =self.maxentry + self.paintFrame() + + def key_down(self): + self.index += self.thumbsX + if self.index > self.maxentry: + self.index = 0 + self.paintFrame() - def showThumb(self): - if not self.filelist.canDescent(): - cachefile = "" - if config.pic.cache.value: - cachedir = self.filelist.getCurrentDirectory() + ".Thumbnails/" - cachefile = cachedir + self.filelist.getFilename() + str(180) + str(160) + str(self.aspect) - if not pathExists(cachedir): - 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, 1) - if ptr != None: - self["thumbnail"].show() - self["thumbnail"].instance.setPixmap(ptr) - else: - self["thumbnail"].hide() + def StartExif(self): + if self.maxentry < 0: + return + self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.index][T_FULL])) def KeyOk(self): - if self.filelist.canDescent(): - self.filelist.descent() - else: - self.session.openWithCallback(self.returnVal, PicView, self.filelist.getFileList(), self.filelist.getFilename(), self.filelist.getCurrentDirectory()) - - def StartThumb(self): - self.session.openWithCallback(self.returnVal, ThumbView, self.filelist.getFileList(), self.filelist.getFilename(), self.filelist.getCurrentDirectory()) + if self.maxentry < 0: + return + self.old_index = self.index + self.session.openWithCallback(self.callbackView, Pic_Full_View, self.filelist, self.index, self.path) - def returnVal(self, val=0): - if val > 0: - for x in self.filelist.getFileList(): - if x[0][1] == True: - val += 1 - self.filelist.moveToIndex(val) + def callbackView(self, val=0): + self.index = val + if self.old_index != self.index: + self.paintFrame() + def Exit(self): + del self.picload + self.close(self.index + self.dirlistcount) - def StartExif(self): - if not self.filelist.canDescent(): - self.session.open(ExifView, self.filelist.getCurrentDirectory() + self.filelist.getFilename(), self.filelist.getFilename()) +#--------------------------------------------------------------------------- + +class Pic_Full_View(Screen): + def __init__(self, session, filelist, index, path): + + self.textcolor = config.pic.textcolor.value + self.bgcolor = config.pic.bgcolor.value + space = config.pic.framesize.value + size_w = getDesktop(0).size().width() + size_h = getDesktop(0).size().height() + + self.skin = "<screen position=\"0,0\" size=\"" + str(size_w) + "," + str(size_h) + "\" flags=\"wfNoBorder\" > \ + <eLabel position=\"0,0\" zPosition=\"0\" size=\""+ str(size_w) + "," + str(size_h) + "\" backgroundColor=\""+ self.bgcolor +"\" /><widget name=\"pic\" position=\"" + str(space) + "," + str(space) + "\" size=\"" + str(size_w-(space*2)) + "," + str(size_h-(space*2)) + "\" zPosition=\"1\" alphatest=\"on\" /> \ + <widget name=\"point\" position=\""+ str(space+5) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/record.png\" alphatest=\"on\" /> \ + <widget name=\"play_icon\" position=\""+ str(space+25) + "," + str(space+2) + "\" size=\"20,20\" zPosition=\"2\" pixmap=\"skin_default/icons/ico_mp_play.png\" alphatest=\"on\" /> \ + <widget name=\"file\" position=\""+ str(space+45) + "," + str(space) + "\" size=\""+ str(size_w-(space*2)-50) + ",25\" font=\"Regular;20\" halign=\"left\" foregroundColor=\"" + self.textcolor + "\" zPosition=\"2\" noWrap=\"1\" transparent=\"1\" /></screen>" + + Screen.__init__(self, session) + + self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"], + { + "cancel": self.Exit, + "green": self.PlayPause, + "yellow": self.PlayPause, + "blue": self.nextPic, + "red": self.prevPic, + "left": self.prevPic, + "right": self.nextPic, + "showEventInfo": self.StartExif, + }, -1) + + self["point"] = Pixmap() + self["pic"] = Pixmap() + self["play_icon"] = Pixmap() + self["file"] = Label(_("please wait, loading picture...")) + + self.old_index = 0 + self.filelist = [] + self.lastindex = index + self.currPic = [] + self.shownow = True + self.dirlistcount = 0 + + for x in filelist: + if len(filelist[0]) == 3: #orig. filelist + if x[0][1] == False: + self.filelist.append(path + x[0][0]) + else: + self.dirlistcount += 1 + elif len(filelist[0]) == 2: #scanlist + if x[0][1] == False: + self.filelist.append(x[0][0]) + else: + self.dirlistcount += 1 + else: # thumbnaillist + self.filelist.append(x[T_FULL]) + + self.maxentry = len(self.filelist)-1 + self.index = index - self.dirlistcount + if self.index < 0: + self.index = 0 + + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.finish_decode) + + self.slideTimer = eTimer() + self.slideTimer.callback.append(self.slidePic) - def Settings(self): - self.session.open(PicSetup) + if self.maxentry >= 0: + self.onLayoutFinish.append(self.setPicloadConf) + + def setPicloadConf(self): + sc = getScale() + self.picload.setPara([self["pic"].instance.size().width(), self["pic"].instance.size().height(), sc[0], sc[1], 0, int(config.pic.resize.value), self.bgcolor]) + + self["play_icon"].hide() + if config.pic.infoline.value == False: + self["file"].hide() + self.start_decode() + + def ShowPicture(self): + if self.shownow and len(self.currPic): + self.shownow = False + self["file"].setText(self.currPic[0]) + self.lastindex = self.currPic[1] + self["pic"].instance.setPixmap(self.currPic[2].__deref__()) + self.currPic = [] + + self.next() + self.start_decode() - def Exit(self): - if self.filelist.getCurrentDirectory() is None: - config.pic.lastDir.value = "/" + def finish_decode(self, picInfo=""): + self["point"].hide() + ptr = self.picload.getData() + if ptr != None: + text = "" + try: + text = picInfo.split('\n',1) + text = "(" + str(self.index+1) + "/" + str(self.maxentry+1) + ") " + text[0].split('/')[-1] + except: + pass + self.currPic = [] + self.currPic.append(text) + self.currPic.append(self.index) + self.currPic.append(ptr) + self.ShowPicture() + + def start_decode(self): + self.picload.startDecode(self.filelist[self.index]) + self["point"].show() + + def next(self): + self.index += 1 + if self.index > self.maxentry: + self.index = 0 + + def prev(self): + self.index -= 1 + if self.index < 0: + self.index = self.maxentry + + def slidePic(self): + print "slide to next Picture index=" + str(self.lastindex) + if config.pic.loop.value==False and self.lastindex == self.maxentry: + self.PlayPause() + self.shownow = True + self.ShowPicture() + + def PlayPause(self): + if self.slideTimer.isActive(): + self.slideTimer.stop() + self["play_icon"].hide() else: - config.pic.lastDir.value = self.filelist.getCurrentDirectory() + self.slideTimer.start(config.pic.slidetime.value*1000) + self["play_icon"].show() + self.nextPic() - config.pic.save() - self.close() + def prevPic(self): + self.currPic = [] + self.index = self.lastindex + self.prev() + self.start_decode() + self.shownow = True + + def nextPic(self): + self.shownow = True + self.ShowPicture() + + def StartExif(self): + if self.maxentry < 0: + return + self.session.open(Pic_Exif, self.picload.getInfo(self.filelist[self.lastindex])) + + def Exit(self): + del self.picload + self.close(self.lastindex + self.dirlistcount) #------------------------------------------------------------------------------------------ def main(session, **kwargs): - session.open(picmain) + session.open(picshow) def filescan_open(list, session, **kwargs): # Recreate List as expected by PicView filelist = [((file.path, False), None) for file in list] - session.open(PicView, filelist, "", "") + session.open(Pic_Full_View, filelist, 0, file.path) def filescan(**kwargs): from Components.Scanner import Scanner, ScanPath @@ -557,5 +592,5 @@ def filescan(**kwargs): def Plugins(**kwargs): return \ - [PluginDescriptor(name="PicturePlayer", description="Picture Viewer (BMP, PNG, JPG, GIF)", icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main), - PluginDescriptor(name="PicturePlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)] + [PluginDescriptor(name=_("PicturePlayer"), description=_("fileformats (BMP, PNG, JPG, GIF)"), icon="pictureplayer.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main), + PluginDescriptor(name=_("PicturePlayer"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)] diff --git a/lib/python/Plugins/SystemPlugins/DiseqcTester/Makefile.am b/lib/python/Plugins/SystemPlugins/DiseqcTester/Makefile.am new file mode 100644 index 00000000..cd72696a --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/DiseqcTester/Makefile.am @@ -0,0 +1,5 @@ +installdir = $(LIBDIR)/enigma2/python/Plugins/SystemPlugins/DiseqcTester + +install_PYTHON = \ + __init__.py \ + plugin.py
\ No newline at end of file diff --git a/lib/python/Plugins/SystemPlugins/DiseqcTester/__init__.py b/lib/python/Plugins/SystemPlugins/DiseqcTester/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/DiseqcTester/__init__.py diff --git a/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py b/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py new file mode 100644 index 00000000..07861954 --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/DiseqcTester/plugin.py @@ -0,0 +1,642 @@ +from Screens.Satconfig import NimSelection +from Screens.Screen import Screen +from Screens.TextBox import TextBox +from Screens.MessageBox import MessageBox + +from Plugins.Plugin import PluginDescriptor + +from Components.ActionMap import ActionMap, NumberActionMap +from Components.NimManager import nimmanager +from Components.ResourceManager import resourcemanager +from Components.Sources.FrontendStatus import FrontendStatus +from Components.TuneTest import TuneTest +from Components.Sources.List import List +from Components.Sources.Progress import Progress +from Components.Sources.StaticText import StaticText +from Components.ConfigList import ConfigListScreen +from Components.config import getConfigListEntry, ConfigSelection, ConfigYesNo +from Components.Harddisk import harddiskmanager + +import random + +# always use: +# setResultType(type) +# setResultParameter(parameter) +# getTextualResult() +class ResultParser: + def __init__(self): + pass + + TYPE_BYORBPOS = 0 + TYPE_BYINDEX = 1 + TYPE_ALL = 2 + def setResultType(self, type): + self.type = type + + def setResultParameter(self, parameter): + if self.type == self.TYPE_BYORBPOS: + self.orbpos = parameter + elif self.type == self.TYPE_BYINDEX: + self.index = parameter + + def getTextualResultForIndex(self, index, logfulltransponders = False): + text = "" + text += "%s:\n" % self.getTextualIndexRepresentation(index) + + failed, successful = self.results[index]["failed"], self.results[index]["successful"] + countfailed = len(failed) + countsuccessful = len(successful) + countall = countfailed + countsuccessful + percentfailed = round(countfailed / float(countall + 0.0001) * 100) + percentsuccessful = round(countsuccessful / float(countall + 0.0001) * 100) + text += "Tested %d transponders\n%d (%d %%) transponders succeeded\n%d (%d %%) transponders failed\n" % (countall, countsuccessful, percentsuccessful, countfailed, percentfailed) + reasons = {} + if countfailed > 0: + for transponder in failed: + reasons[transponder[2]] = reasons.get(transponder[2], []) + reasons[transponder[2]].append(transponder) + if transponder[2] == "pids_failed": + print transponder[2], "-", transponder[3] + + text += "The %d unsuccessful tuning attempts failed for the following reasons:\n" % countfailed + + for reason in reasons.keys(): + text += "%s: %d transponders failed\n" % (reason, len(reasons[reason])) + + for reason in reasons.keys(): + text += "\n" + text += "%s previous planes:\n" % reason + for transponder in reasons[reason]: + if transponder[1] is not None: + text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1])) + else: + text += "No transponder tuned" + text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0])) + text += "\n" + if logfulltransponders: + text += str(transponder[1]) + text += " ==> " + text += str(transponder[0]) + text += "\n" + if countsuccessful > 0: + text += "\n" + text += "Successfully tuned transponders' previous planes:\n" + for transponder in successful: + if transponder[1] is not None: + text += self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[1])) + else: + text += "No transponder tuned" + text += " ==> " + self.getTextualIndexRepresentation(self.getIndexForTransponder(transponder[0])) + text += "\n" + return text + + def getTextualResult(self): + text = "" + if self.type == self.TYPE_BYINDEX: + text += self.getTextualResultForIndex(self.index) + elif self.type == self.TYPE_BYORBPOS: + for index in self.results.keys(): + if index[2] == self.orbpos: + text += self.getTextualResultForIndex(index) + text += "\n-----------------------------------------------------\n" + elif self.type == self.TYPE_ALL: + orderedResults = {} + for index in self.results.keys(): + orbpos = index[2] + orderedResults[orbpos] = orderedResults.get(orbpos, []) + orderedResults[orbpos].append(index) + ordered_orbpos = orderedResults.keys() + ordered_orbpos.sort() + for orbpos in ordered_orbpos: + text += "\n*****************************************\n" + text += "Orbital position %s:" % str(orbpos) + text += "\n*****************************************\n" + for index in orderedResults[orbpos]: + text += self.getTextualResultForIndex(index, logfulltransponders = True) + text += "\n-----------------------------------------------------\n" + + + return text + +class DiseqcTester(Screen, TuneTest, ResultParser): + skin = """ + <screen position="90,100" size="520,400" title="DiSEqC Tester" > + <!--ePixmap pixmap="skin_default/icons/dish_scan.png" position="5,25" zPosition="0" size="119,110" transparent="1" alphatest="on" /> + <widget source="Frontend" render="Label" position="190,10" zPosition="2" size="260,20" font="Regular;19" halign="center" valign="center" transparent="1"> + <convert type="FrontendInfo">SNRdB</convert> + </widget> + <eLabel name="snr" text="SNR:" position="120,35" size="60,22" font="Regular;21" halign="right" transparent="1" /> + <widget source="Frontend" render="Progress" position="190,35" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc"> + <convert type="FrontendInfo">SNR</convert> + </widget> + <widget source="Frontend" render="Label" position="460,35" size="60,22" font="Regular;21"> + <convert type="FrontendInfo">SNR</convert> + </widget> + <eLabel name="agc" text="AGC:" position="120,60" size="60,22" font="Regular;21" halign="right" transparent="1" /> + <widget source="Frontend" render="Progress" position="190,60" size="260,20" pixmap="skin_default/bar_snr.png" borderWidth="2" borderColor="#cccccc"> + <convert type="FrontendInfo">AGC</convert> + </widget> + <widget source="Frontend" render="Label" position="460,60" size="60,22" font="Regular;21"> + <convert type="FrontendInfo">AGC</convert> + </widget> + <eLabel name="ber" text="BER:" position="120,85" size="60,22" font="Regular;21" halign="right" transparent="1" /> + <widget source="Frontend" render="Progress" position="190,85" size="260,20" pixmap="skin_default/bar_ber.png" borderWidth="2" borderColor="#cccccc"> + <convert type="FrontendInfo">BER</convert> + </widget> + <widget source="Frontend" render="Label" position="460,85" size="60,22" font="Regular;21"> + <convert type="FrontendInfo">BER</convert> + </widget> + <eLabel name="lock" text="Lock:" position="120,115" size="60,22" font="Regular;21" halign="right" /> + <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_on.png" position="190,110" zPosition="1" size="38,31" alphatest="on"> + <convert type="FrontendInfo">LOCK</convert> + <convert type="ConditionalShowHide" /> + </widget> + <widget source="Frontend" render="Pixmap" pixmap="skin_default/icons/lock_off.png" position="190,110" zPosition="1" size="38,31" alphatest="on"> + <convert type="FrontendInfo">LOCK</convert> + <convert type="ConditionalShowHide">Invert</convert> + </widget--> + <widget source="progress_list" render="Listbox" position="0,0" size="510,150" scrollbarMode="showOnDemand"> + <convert type="TemplatedMultiContent"> + {"template": [ + MultiContentEntryText(pos = (10, 0), size = (330, 25), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the index name, + MultiContentEntryText(pos = (330, 0), size = (150, 25), flags = RT_HALIGN_RIGHT, text = 2) # index 2 is the status, + ], + "fonts": [gFont("Regular", 20)], + "itemHeight": 25 + } + </convert> + </widget> + <eLabel name="overall_progress" text="Overall progress:" position="20,162" size="480,22" font="Regular;21" halign="center" transparent="1" /> + <widget source="overall_progress" render="Progress" position="20,192" size="480,20" borderWidth="2" backgroundColor="#254f7497" /> + <eLabel name="overall_progress" text="Progress:" position="20,222" size="480,22" font="Regular;21" halign="center" transparent="1" /> + <widget source="sub_progress" render="Progress" position="20,252" size="480,20" borderWidth="2" backgroundColor="#254f7497" /> + + <eLabel name="" text="Failed:" position="20,282" size="140,22" font="Regular;21" halign="left" transparent="1" /> + <widget source="failed_counter" render="Label" position="160,282" size="100,20" font="Regular;21" /> + + <eLabel name="" text="Succeeded:" position="20,312" size="140,22" font="Regular;21" halign="left" transparent="1" /> + <widget source="succeeded_counter" render="Label" position="160,312" size="100,20" font="Regular;21" /> + + <eLabel name="" text="With errors:" position="20,342" size="140,22" font="Regular;21" halign="left" transparent="1" /> + <widget source="witherrors_counter" render="Label" position="160,342" size="100,20" font="Regular;21" /> + + <eLabel name="" text="Not tested:" position="20,372" size="140,22" font="Regular;21" halign="left" transparent="1" /> + <widget source="untestable_counter" render="Label" position="160,372" size="100,20" font="Regular;21" /> + + <widget source="CmdText" render="Label" position="300,282" size="180,200" font="Regular;21" /> + </screen>""" + + TEST_TYPE_QUICK = 0 + TEST_TYPE_RANDOM = 1 + TEST_TYPE_COMPLETE = 2 + def __init__(self, session, feid, test_type = TEST_TYPE_QUICK, loopsfailed = 3, loopssuccessful = 1, log = False): + Screen.__init__(self, session) + self.feid = feid + self.test_type = test_type + self.loopsfailed = loopsfailed + self.loopssuccessful = loopssuccessful + self.log = log + + self["actions"] = NumberActionMap(["SetupActions"], + { + "ok": self.select, + "cancel": self.keyCancel, + }, -2) + + TuneTest.__init__(self, feid, stopOnSuccess = self.loopssuccessful, stopOnError = self.loopsfailed) + #self["Frontend"] = FrontendStatus(frontend_source = lambda : self.frontend, update_interval = 100) + self["overall_progress"] = Progress() + self["sub_progress"] = Progress() + + self["failed_counter"] = StaticText("0") + self["succeeded_counter"] = StaticText("0") + self["witherrors_counter"] = StaticText("0") + self["untestable_counter"] = StaticText("0") + + self.list = [] + self["progress_list"] = List(self.list) + self["progress_list"].onSelectionChanged.append(self.selectionChanged) + + self["CmdText"] = StaticText(_("Please wait while scanning is in progress...")) + + self.indexlist = {} + self.readTransponderList() + + self.running = False + + self.results = {} + self.resultsstatus = {} + + self.onLayoutFinish.append(self.go) + + def getProgressListComponent(self, index, status): + return (index, self.getTextualIndexRepresentation(index), status) + + def clearProgressList(self): + self.list = [] + self["progress_list"].list = self.list + + def addProgressListItem(self, index): + if index in self.indexlist: + for entry in self.list: + if entry[0] == index: + self.changeProgressListStatus(index, "working") + return + self.list.append(self.getProgressListComponent(index, _("working"))) + self["progress_list"].list = self.list + self["progress_list"].setIndex(len(self.list) - 1) + + def changeProgressListStatus(self, index, status): + self.newlist = [] + count = 0 + indexpos = 0 + for entry in self.list: + if entry[0] == index: + self.newlist.append(self.getProgressListComponent(index, status)) + indexpos = count + else: + self.newlist.append(entry) + count += 1 + self.list = self.newlist + self["progress_list"].list = self.list + self["progress_list"].setIndex(indexpos) + + def readTransponderList(self): + for sat in nimmanager.getSatListForNim(self.feid): + for transponder in nimmanager.getTransponders(sat[0]): + #print transponder + mytransponder = (transponder[1] / 1000, transponder[2] / 1000, transponder[3], transponder[4], transponder[5], sat[0], None, None, transponder[10], transponder[11]) + self.analyseTransponder(mytransponder) + + def getIndexForTransponder(self, transponder): + + if transponder[0] < 11700: + band = 1 # low + else: + band = 0 # high + + polarisation = transponder[2] + + sat = transponder[5] + + index = (band, polarisation, sat) + return index + + # sort the transponder into self.transponderlist + def analyseTransponder(self, transponder): + index = self.getIndexForTransponder(transponder) + if index not in self.indexlist: + self.indexlist[index] = [] + self.indexlist[index].append(transponder) + #print "self.indexlist:", self.indexlist + + # returns a string for the user representing a human readable output for index + def getTextualIndexRepresentation(self, index): + print "getTextualIndexRepresentation:", index + text = "" + + text += nimmanager.getSatDescription(index[2]) + ", " + + if index[0] == 1: + text += "Low Band, " + else: + text += "High Band, " + + if index[1] == 0: + text += "H" + else: + text += "V" + return text + + def fillTransponderList(self): + self.clearTransponder() + print "----------- fillTransponderList" + print "index:", self.currentlyTestedIndex + keys = self.indexlist.keys() + if self.getContinueScanning(): + print "index:", self.getTextualIndexRepresentation(self.currentlyTestedIndex) + for transponder in self.indexlist[self.currentlyTestedIndex]: + self.addTransponder(transponder) + print "transponderList:", self.transponderlist + return True + else: + return False + + def progressCallback(self, progress): + if progress[0] != self["sub_progress"].getRange(): + self["sub_progress"].setRange(progress[0]) + self["sub_progress"].setValue(progress[1]) + + # logic for scanning order of transponders + # on go getFirstIndex is called + def getFirstIndex(self): + # TODO use other function to scan more randomly + if self.test_type == self.TEST_TYPE_QUICK: + self.myindex = 0 + keys = self.indexlist.keys() + keys.sort(key = lambda a: a[2]) # sort by orbpos + self["overall_progress"].setRange(len(keys)) + self["overall_progress"].setValue(self.myindex) + return keys[0] + elif self.test_type == self.TEST_TYPE_RANDOM: + self.randomkeys = self.indexlist.keys() + random.shuffle(self.randomkeys) + self.myindex = 0 + self["overall_progress"].setRange(len(self.randomkeys)) + self["overall_progress"].setValue(self.myindex) + return self.randomkeys[0] + elif self.test_type == self.TEST_TYPE_COMPLETE: + keys = self.indexlist.keys() + print "keys:", keys + successorindex = {} + for index in keys: + successorindex[index] = [] + for otherindex in keys: + if otherindex != index: + successorindex[index].append(otherindex) + random.shuffle(successorindex[index]) + self.keylist = [] + stop = False + currindex = None + while not stop: + if currindex is None or len(successorindex[currindex]) == 0: + oldindex = currindex + for index in successorindex.keys(): + if len(successorindex[index]) > 0: + currindex = index + self.keylist.append(currindex) + break + if currindex == oldindex: + stop = True + else: + currindex = successorindex[currindex].pop() + self.keylist.append(currindex) + print "self.keylist:", self.keylist + self.myindex = 0 + self["overall_progress"].setRange(len(self.keylist)) + self["overall_progress"].setValue(self.myindex) + return self.keylist[0] + + + # after each index is finished, getNextIndex is called to get the next index to scan + def getNextIndex(self): + # TODO use other function to scan more randomly + if self.test_type == self.TEST_TYPE_QUICK: + self.myindex += 1 + keys = self.indexlist.keys() + keys.sort(key = lambda a: a[2]) # sort by orbpos + + self["overall_progress"].setValue(self.myindex) + if self.myindex < len(keys): + return keys[self.myindex] + else: + return None + elif self.test_type == self.TEST_TYPE_RANDOM: + self.myindex += 1 + keys = self.randomkeys + + self["overall_progress"].setValue(self.myindex) + if self.myindex < len(keys): + return keys[self.myindex] + else: + return None + elif self.test_type == self.TEST_TYPE_COMPLETE: + self.myindex += 1 + keys = self.keylist + + self["overall_progress"].setValue(self.myindex) + if self.myindex < len(keys): + return keys[self.myindex] + else: + return None + + # after each index is finished and the next index is returned by getNextIndex + # the algorithm checks, if we should continue scanning + def getContinueScanning(self): + if self.test_type == self.TEST_TYPE_QUICK or self.test_type == self.TEST_TYPE_RANDOM: + return (self.myindex < len(self.indexlist.keys())) + elif self.test_type == self.TEST_TYPE_COMPLETE: + return (self.myindex < len(self.keylist)) + + def addResult(self, index, status, failedTune, successfullyTune): + self.results[index] = self.results.get(index, {"failed": [], "successful": [], "status": None, "internalstatus": None}) + self.resultsstatus[status] = self.resultsstatus.get(status, []) + + oldstatus = self.results[index]["internalstatus"] + if oldstatus is None: + self.results[index]["status"] = status + elif oldstatus == "successful": + if status == "failed": + self.results[index]["status"] = "with_errors" + elif status == "successful": + self.results[index]["status"] = oldstatus + elif status == "with_errors": + self.results[index]["status"] = "with_errors" + elif status == "not_tested": + self.results[index]["status"] = oldstatus + elif oldstatus == "failed": + if status == "failed": + self.results[index]["status"] = oldstatus + elif status == "successful": + self.results[index]["status"] = "with_errors" + elif status == "with_errors": + self.results[index]["status"] = "with_errors" + elif status == "not_tested": + self.results[index]["status"] = oldstatus + elif oldstatus == "with_errors": + if status == "failed": + self.results[index]["status"] = oldstatus + elif status == "successful": + self.results[index]["status"] = oldstatus + elif status == "with_errors": + self.results[index]["status"] = oldstatus + elif status == "not_tested": + self.results[index]["status"] = oldstatus + elif oldstatus == "not_tested": + self.results[index]["status"] = status + + if self.results[index]["status"] != "working": + self.results[index]["internalstatus"] = self.results[index]["status"] + self.results[index]["failed"] = failedTune + self.results[index]["failed"] + self.results[index]["successful"] = successfullyTune + self.results[index]["successful"] + + self.resultsstatus[status].append(index) + + def finishedChecking(self): + print "finishedChecking" + TuneTest.finishedChecking(self) + + if not self.results.has_key(self.currentlyTestedIndex): + self.results[self.currentlyTestedIndex] = {"failed": [], "successful": [], "status": None, "internalstatus": None} + + if len(self.failedTune) > 0 and len(self.successfullyTune) > 0: + self.changeProgressListStatus(self.currentlyTestedIndex, "with errors") + self["witherrors_counter"].setText(str(int(self["witherrors_counter"].getText()) + 1)) + self.addResult(self.currentlyTestedIndex, "with_errors", self.failedTune, self.successfullyTune) + elif len(self.failedTune) == 0 and len(self.successfullyTune) == 0: + self.changeProgressListStatus(self.currentlyTestedIndex, "not tested") + self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1)) + self.addResult(self.currentlyTestedIndex, "untestable", self.failedTune, self.successfullyTune) + elif len(self.failedTune) > 0: + self.changeProgressListStatus(self.currentlyTestedIndex, "failed") + #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune))) + self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + 1)) + self.addResult(self.currentlyTestedIndex, "failed", self.failedTune, self.successfullyTune) + else: + self.changeProgressListStatus(self.currentlyTestedIndex, "successful") + #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune))) + self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + 1)) + self.addResult(self.currentlyTestedIndex, "successful", self.failedTune, self.successfullyTune) + + + #self["failed_counter"].setText(str(int(self["failed_counter"].getText()) + len(self.failedTune))) + #self["succeeded_counter"].setText(str(int(self["succeeded_counter"].getText()) + len(self.successfullyTune))) + #if len(self.failedTune) == 0 and len(self.successfullyTune) == 0: + #self["untestable_counter"].setText(str(int(self["untestable_counter"].getText()) + 1)) + + self.currentlyTestedIndex = self.getNextIndex() + self.addProgressListItem(self.currentlyTestedIndex) + + if self.fillTransponderList(): + self.run(checkPIDs = True) + else: + self.running = False + self["progress_list"].setIndex(0) + print "results:", self.results + print "resultsstatus:", self.resultsstatus + if self.log: + file = open("/media/hdd/diseqctester.log", "w") + self.setResultType(ResultParser.TYPE_ALL) + file.write(self.getTextualResult()) + file.close() + self.session.open(MessageBox, text=_("The results have been written to %s.") % "/media/hdd/diseqctester.log", type = MessageBox.TYPE_INFO) + + def go(self): + self.running = True + self["failed_counter"].setText("0") + self["succeeded_counter"].setText("0") + self["untestable_counter"].setText("0") + self.currentlyTestedIndex = self.getFirstIndex() + + self.clearProgressList() + self.addProgressListItem(self.currentlyTestedIndex) + + if self.fillTransponderList(): + self.run(True) + + def keyCancel(self): + self.close() + + def select(self): + print "selectedIndex:", self["progress_list"].getCurrent()[0] + if not self.running: + index = self["progress_list"].getCurrent()[0] + #self.setResultType(ResultParser.TYPE_BYORBPOS) + #self.setResultParameter(index[2]) + self.setResultType(ResultParser.TYPE_BYINDEX) + self.setResultParameter(index) + #self.setResultType(ResultParser.TYPE_ALL) + self.session.open(TextBox, self.getTextualResult()) + + def selectionChanged(self): + print "selection changed" + if len(self.list) > 0 and not self.running: + self["CmdText"].setText(_("Press OK to get further details for %s") % str(self["progress_list"].getCurrent()[1])) + +class DiseqcTesterTestTypeSelection(Screen, ConfigListScreen): + skin = """<screen position="80,95" size="560,412" title="DiSEqC Tester Test Settings"> + <widget name="config" position="10,10" size="540,402" scrollbarMode="showOnDemand" /> + </screen> + """ + def __init__(self, session, feid): + Screen.__init__(self, session) + self.feid = feid + + self.list = [] + ConfigListScreen.__init__(self, self.list) + + self["actions"] = ActionMap(["SetupActions"], + { + "cancel": self.keyCancel + }, -2) + + self.createSetup() + + def createSetup(self): + self.testtype = ConfigSelection(choices={"quick": _("Quick"), "random": _("Random"), "complete": _("Complete")}, default = "quick") + self.testtypeEntry = getConfigListEntry(_("Test Type"), self.testtype) + self.list.append(self.testtypeEntry) + + self.loopsfailed = ConfigSelection(choices={"-1": "Every known", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8"}, default = "3") + self.loopsfailedEntry = getConfigListEntry(_("Stop testing plane after # failed transponders"), self.loopsfailed) + self.list.append(self.loopsfailedEntry) + + self.loopssuccessful = ConfigSelection(choices={"-1": "Every known", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8"}, default = "1") + self.loopssuccessfulEntry = getConfigListEntry(_("Stop testing plane after # successful transponders"), self.loopssuccessful) + self.list.append(self.loopssuccessfulEntry) + + self.log = ConfigYesNo(False) + if harddiskmanager.HDDCount() > 0: + self.logEntry = getConfigListEntry(_("Log results to harddisk"), self.log) + self.list.append(self.logEntry) + + self["config"].list = self.list + self["config"].l.setList(self.list) + + def keyOK(self): + print self.testtype.getValue() + testtype = DiseqcTester.TEST_TYPE_QUICK + if self.testtype.getValue() == "quick": + testtype = DiseqcTester.TEST_TYPE_QUICK + elif self.testtype.getValue() == "random": + testtype = DiseqcTester.TEST_TYPE_RANDOM + elif self.testtype.getValue() == "complete": + testtype = DiseqcTester.TEST_TYPE_COMPLETE + self.session.open(DiseqcTester, feid = self.feid, test_type = testtype, loopsfailed = int(self.loopsfailed.value), loopssuccessful = int(self.loopssuccessful.value), log = self.log.value) + + def keyCancel(self): + self.close() + +class DiseqcTesterNimSelection(NimSelection): + skin = """ + <screen position="160,123" size="400,330" title="Choose Tuner"> + <widget source="nimlist" render="Listbox" position="0,0" size="380,300" scrollbarMode="showOnDemand"> + <convert type="TemplatedMultiContent"> + {"template": [ + MultiContentEntryText(pos = (10, 5), size = (360, 30), flags = RT_HALIGN_LEFT, text = 1), # index 1 is the nim name, + MultiContentEntryText(pos = (50, 30), size = (320, 30), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is a description of the nim settings, + ], + "fonts": [gFont("Regular", 20), gFont("Regular", 15)], + "itemHeight": 70 + } + </convert> + </widget> + </screen>""" + + def __init__(self, session, args = None): + NimSelection.__init__(self, session) + + def setResultClass(self): + #self.resultclass = DiseqcTester + self.resultclass = DiseqcTesterTestTypeSelection + + def showNim(self, nim): + nimConfig = nimmanager.getNimConfig(nim.slot) + if nim.isCompatible("DVB-S"): + if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends", "nothing"]: + return False + if nimConfig.configMode.value == "simple": + if nimConfig.diseqcMode.value == "positioner": + return True + return True + return False + +def DiseqcTesterMain(session, **kwargs): + session.open(DiseqcTesterNimSelection) + +def autostart(reason, **kwargs): + resourcemanager.addResource("DiseqcTester", DiseqcTesterMain) + +def Plugins(**kwargs): + return [ PluginDescriptor(name="DiSEqC Tester", description=_("Test DiSEqC settings"), where = PluginDescriptor.WHERE_PLUGINMENU, fnc=DiseqcTesterMain), + PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart)] diff --git a/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py b/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py index 97ddf4a1..b19007c9 100644 --- a/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py +++ b/lib/python/Plugins/SystemPlugins/Hotplug/plugin.py @@ -3,17 +3,9 @@ from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor from Components.Harddisk import harddiskmanager -DEVICEDB = \ - { "/devices/pci0000:00/0000:00:14.2/usb1/1-1/1-1:1.0/host0/target0:0:0/0:0:0:0": "CF Slot", - "/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") - def connectionMade(self): self.received = "" @@ -40,20 +32,19 @@ class Hotplug(Protocol): dev = device.split('/')[-1] if action is not None and action == "add": - print "Medium found in", self.getUserfriendlyDeviceName(dev) - harddiskmanager.addHotplugPartition(dev, self.getUserfriendlyDeviceName(physdevpath)) + harddiskmanager.addHotplugPartition(dev, physdevpath) elif action is not None and action == "remove": harddiskmanager.removeHotplugPartition(dev) elif media_state is not None: if media_state == '1': harddiskmanager.removeHotplugPartition(dev) - harddiskmanager.addHotplugPartition(dev, self.getUserfriendlyDeviceName(physdevpath)) + harddiskmanager.addHotplugPartition(dev, physdevpath) elif media_state == '0': harddiskmanager.removeHotplugPartition(dev) for callback in hotplugNotifier: try: - callback(dev, media_state) + callback(dev, action or media_state) except AttributeError: hotplugNotifier.remove(callback) diff --git a/lib/python/Plugins/SystemPlugins/Makefile.am b/lib/python/Plugins/SystemPlugins/Makefile.am index 36b4bde5..4491eafc 100644 --- a/lib/python/Plugins/SystemPlugins/Makefile.am +++ b/lib/python/Plugins/SystemPlugins/Makefile.am @@ -1 +1 @@ -SUBDIRS = SoftwareUpdate FrontprocessorUpgrade PositionerSetup ConfigurationBackup Satfinder SkinSelector SatelliteEquipmentControl Videomode VideoTune Hotplug DefaultServicesScanner NFIFlash +SUBDIRS = SoftwareUpdate FrontprocessorUpgrade PositionerSetup ConfigurationBackup Satfinder SkinSelector SatelliteEquipmentControl Videomode VideoTune Hotplug DefaultServicesScanner NFIFlash DiseqcTester diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py b/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py index c2046af7..c91c8588 100644 --- a/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py +++ b/lib/python/Plugins/SystemPlugins/NFIFlash/downloader.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from Components.MenuList import MenuList from Screens.Screen import Screen from Screens.MessageBox import MessageBox @@ -18,6 +19,7 @@ import urllib from twisted.web import client from twisted.internet import reactor, defer from twisted.python import failure +from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier class UserRequestedCancel(Exception): pass @@ -119,10 +121,10 @@ class NFIDownload(Screen): <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" zPosition="0" size="140,40" transparent="1" alphatest="on" /> <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" zPosition="0" size="140,40" transparent="1" alphatest="on" /> <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" zPosition="0" size="140,40" transparent="1" alphatest="on" /> - <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" /> - <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" /> - <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#a08500" transparent="1" /> - <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#18188b" transparent="1" /> + <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#9f1313" transparent="1" /> + <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" /> + <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#a08500" transparent="1" /> + <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;19" valign="center" halign="center" backgroundColor="#18188b" transparent="1" /> <widget source="label_top" render="Label" position="10,44" size="240,20" font="Regular;16" /> <widget name="feedlist" position="10,66" size="250,222" scrollbarMode="showOnDemand" /> @@ -169,6 +171,7 @@ class NFIDownload(Screen): self.box = HardwareInfo().get_device_name() self.feed_base = "http://www.dreamboxupdate.com/opendreambox/1.5/%s/images/" % self.box self.nfi_filter = "" # "release" # only show NFIs containing this string, or all if "" + self.wizard_mode = False self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "EPGSelectActions"], { @@ -205,7 +208,7 @@ class NFIDownload(Screen): self["key_yellow"].text = (_("Change dir.")) else: self["key_yellow"].text = (_("Select image")) - self["key_blue"].text = (_("Fix USB stick")) + self["key_blue"].text = (_("USB stick wizard")) def switchList(self,to_where=None): if self.download or not self["feedlist"].isValid(): @@ -335,7 +338,7 @@ class NFIDownload(Screen): self.download = self.nfo_download self.downloading(True) client.getPage(nfourl).addCallback(self.nfo_finished).addErrback(self.nfo_failed) - self["statusbar"].text = _("Downloading image description...") + self["statusbar"].text = ("Downloading image description...") def nfo_failed(self, failure_instance): print "[nfo_failed] " + str(failure_instance) @@ -399,8 +402,8 @@ class NFIDownload(Screen): print "couldn't save nfo file " + self.nfofilename pos = self.nfo.find("MD5:") - if pos > 0 and len(self.nfo) >= pos+5+32: - self["statusbar"].text = _("Please wait for md5 signature verification...") + if pos > 0 and len(self.nfo) >= pos+5+32: + self["statusbar"].text = ("Please wait for md5 signature verification...") cmd = "md5sum -c -" md5 = self.nfo[pos+5:pos+5+32] + " " + self.nfilocal print cmd, md5 @@ -415,6 +418,8 @@ class NFIDownload(Screen): else: self["statusbar"].text = "Download completed." self.downloading(False) + if self.wizard_mode: + self.configBackup() def md5ready(self, retval): self.download_container.sendEOF() @@ -423,9 +428,12 @@ class NFIDownload(Screen): print "[md5finished]: " + str(retval) self.download_container.appClosed.remove(self.md5finished) if retval==0: - self["statusbar"].text = _(".NFI file passed md5sum signature check. You can safely flash this image!") - self.switchList(self.LIST_SOURCE) self.downloading(False) + if self.wizard_mode: + self.configBackup() + else: + self["statusbar"].text = _(".NFI file passed md5sum signature check. You can safely flash this image!") + self.switchList(self.LIST_SOURCE) else: self.session.openWithCallback(self.nfi_remove, MessageBox, (_("The md5sum validation failed, the file may be downloaded incompletely or be corrupted!") + "\n" + _("Remove the broken .NFI file?")), MessageBox.TYPE_YESNO) @@ -489,33 +497,22 @@ class NFIDownload(Screen): def umount_finished(self, retval): self.container.appClosed.remove(self.umount_finished) - self.session.openWithCallback(self.dmesg_clear, MessageBox, _("To make sure you intend to do this, please remove the target USB stick now and stick it back in upon prompt. Press OK when you have taken the stick out."), MessageBox.TYPE_INFO) - - def dmesg_clear(self, answer): self.container.appClosed.append(self.dmesg_cleared) self.taskstring = "" self.cmd = "dmesg -c" print "executing " + self.cmd self.container.execute(self.cmd) - def dmesg_cleared(self, retval): + def dmesg_cleared(self, answer): self.container.appClosed.remove(self.dmesg_cleared) - self.session.openWithCallback(self.stick_back_in, MessageBox, (_("Now please insert the USB stick (minimum size is 64 MB) that you want to format and use as .NFI image flasher. Press OK after you've put the stick back in.")), MessageBox.TYPE_INFO) - - def stick_back_in(self, answer): - self["statusbar"].text = _("Waiting for USB stick to settle...") - self.delayTimer = eTimer() - self.delayTimer.callback.append(self.waiting_for_stick) - self.delayCount = -1 - self.delayTimer.start(1000) - - def waiting_for_stick(self): - self.delayCount += 1 - self["job_progressbar"].range = 6 - self["job_progressbar"].value = self.delayCount - self["job_progresslabel"].text = "-%d s" % (6-self.delayCount) - if self.delayCount > 5: - self.delayTimer.stop() + self.msgbox = self.session.open(MessageBox, _("Please disconnect all USB devices from your Dreambox and (re-)attach the target USB stick (minimum size is 64 MB) now!"), MessageBox.TYPE_INFO) + hotplugNotifier.append(self.hotplugCB) + + def hotplugCB(self, dev, action): + print "[hotplugCB]", dev, action + if dev.startswith("sd") and action == "add": + self.msgbox.close() + hotplugNotifier.remove(self.hotplugCB) self.container.appClosed.append(self.dmesg_scanned) self.taskstring = "" self.cmd = "dmesg" @@ -539,8 +536,8 @@ class NFIDownload(Screen): self.session.openWithCallback(self.fdisk_query, MessageBox, (_("The following device was found:\n\n%s\n\nDo you want to write the USB flasher to this stick?") % self.devicetext), MessageBox.TYPE_YESNO) def fdisk_query(self, answer): - if answer == True: - self["statusbar"].text = _("Partitioning USB stick...") + if answer == True and self.stickdevice: + self["statusbar"].text = ("Partitioning USB stick...") self["job_progressbar"].range = 1000 self["job_progressbar"].value = 100 self["job_progresslabel"].text = "5.00%" @@ -562,7 +559,7 @@ class NFIDownload(Screen): self.tar_finished(0) self["job_progressbar"].value = 700 else: - self["statusbar"].text = _("Decompressing USB stick flasher boot image...") + self["statusbar"].text = ("Decompressing USB stick flasher boot image...") self.taskstring = "" self.container.appClosed.append(self.tar_finished) self.container.setCWD("/tmp") @@ -588,7 +585,7 @@ class NFIDownload(Screen): self.container.appClosed.remove(self.tar_finished) if retval == 0: self.imagefilename = "/tmp/nfiflash_" + self.box + ".img" - self["statusbar"].text = _("Copying USB flasher boot image to stick...") + self["statusbar"].text = ("Copying USB flasher boot image to stick...") self.taskstring = "" self.container.appClosed.append(self.dd_finished) self.cmd = "dd if=%s of=%s" % (self.imagefilename,self.stickdevice+"/part1") @@ -607,7 +604,7 @@ class NFIDownload(Screen): if retval == 0: self["job_progressbar"].value = 950 self["job_progresslabel"].text = "95.00%" - self["statusbar"].text = _("Remounting stick partition...") + self["statusbar"].text = ("Remounting stick partition...") self.taskstring = "" self.container.appClosed.append(self.mount_finished) self.cmd = "mount %s /mnt/usb -o rw,sync" % (self.stickdevice+"/part1") @@ -622,11 +619,12 @@ class NFIDownload(Screen): if retval == 0: self["job_progressbar"].value = 1000 self["job_progresslabel"].text = "100.00%" - self["statusbar"].text = _(".NFI Flasher bootable USB stick successfully created.") - self.session.openWithCallback(self.remove_img, MessageBox, _("The .NFI Image flasher USB stick is now ready to use. Please download an .NFI image file from the feed server and save it on the stick. Then reboot and hold the 'Down' key on the front panel to boot the .NFI flasher from the stick!"), MessageBox.TYPE_INFO) + self["statusbar"].text = (".NFI Flasher bootable USB stick successfully created.") + self.session.openWithCallback(self.flasherFinishedCB, MessageBox, _("The USB stick is now bootable. Do you want to download the latest image from the feed server and save it on the stick?"), type = MessageBox.TYPE_YESNO) self["destlist"].changeDir("/mnt/usb") else: - self.session.openWithCallback(self.remove_img, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR) + self.session.openWithCallback(self.flasherFinishedCB, MessageBox, (self.cmd + " " + _("failed") + ":\n" + str(self.taskstring)), MessageBox.TYPE_ERROR) + self.remove_img(True) def remove_img(self, answer): if fileExists("/tmp/nfiflasher_image.tar.bz2"): @@ -636,6 +634,43 @@ class NFIDownload(Screen): self.downloading(False) self.switchList(self.LIST_SOURCE) + def flasherFinishedCB(self, answer): + if answer == True: + self.wizard_mode = True + self["feedlist"].moveSelection(0) + self["path_bottom"].text = str(self["destlist"].getCurrentDirectory()) + self.nfo_download() + self.nfi_download() + + def configBackup(self): + self.session.openWithCallback(self.runBackup, MessageBox, _("The wizard can backup your current settings. Do you want to do a backup now?")) + + def runBackup(self, result=None): + from Tools.Directories import createDir, isMount, pathExists + from time import localtime + from datetime import date + from Screens.Console import Console + if result: + if isMount("/mnt/usb/"): + if (pathExists("/mnt/usb/backup") == False): + createDir("/mnt/usb/backup", True) + d = localtime() + dt = date(d.tm_year, d.tm_mon, d.tm_mday) + self.backup_file = "backup/" + str(dt) + "_settings_backup.tar.gz" + self.session.open(Console, title = "Backup running", cmdlist = ["tar -czvf " + "/mnt/usb/" + self.backup_file + " /etc/enigma2/ /etc/network/interfaces /etc/wpa_supplicant.conf"], finishedCallback = self.backup_finished, closeOnSuccess = True) + else: + self.backup_file = None + self.backup_finished(skipped=True) + + def backup_finished(self, skipped=False): + if not skipped: + wizardfd = open("/mnt/usb/wizard.nfo", "w") + if wizardfd: + wizardfd.write("image: "+self["feedlist"].getNFIname()+'\n') + wizardfd.write("configuration: "+self.backup_file+'\n') + wizardfd.close() + self.session.open(MessageBox, _("To update your Dreambox firmware, please follow these steps:\n1) Turn off your box with the rear power switch and plug in the bootable USB stick.\n2) Turn mains back on and hold the DOWN button on the front panel pressed for 10 seconds.\n3) Wait for bootup and follow instructions of the wizard."), type = MessageBox.TYPE_INFO) + def closeCB(self): if self.download: self.download.stop() @@ -659,8 +694,8 @@ def filescan(**kwargs): Scanner(mimetypes = ["application/x-dream-image"], paths_to_scan = [ - ScanPath(path = "", with_subdirs = False), + ScanPath(path = "", with_subdirs = False), ], name = "NFI", - description = (_("Download .NFI-Files for USB-Flasher")+"..."), + description = (_("Download .NFI-Files for USB-Flasher")+"..."), openfnc = filescan_open, ) diff --git a/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py b/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py index 6a982c58..860efc02 100644 --- a/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py +++ b/lib/python/Plugins/SystemPlugins/NFIFlash/flasher.py @@ -17,7 +17,7 @@ import re class writeNAND(Task): def __init__(self,job,param,box): - Task.__init__(self,job, _("Writing image file to NAND Flash")) + Task.__init__(self,job, ("Writing image file to NAND Flash")) self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/mywritenand") if box == "dm7025": self.end = 256 @@ -26,7 +26,7 @@ class writeNAND(Task): if box == "dm8000": self.setTool("/usr/lib/enigma2/python/Plugins/SystemPlugins/NFIFlash/dm8000_writenand") self.args += param - self.weighting = 1 + self.weighting = 1 def processOutput(self, data): print "[writeNand] " + data @@ -174,8 +174,8 @@ class NFIFlash(Screen): print sign if sign.find("NFI1" + self.box + "\0") == 0: if self.md5sum != "": - self["statusbar"].text = _("Please wait for md5 signature verification...") - self.session.summary.setText(_("Please wait for md5 signature verification...")) + self["statusbar"].text = ("Please wait for md5 signature verification...") + self.session.summary.setText(("Please wait for md5 signature verification...")) self.container = eConsoleAppContainer() self.container.setCWD(self["filelist"].getCurrentDirectory()) self.container.appClosed.append(self.md5finished) @@ -252,7 +252,7 @@ class NFIFlash(Screen): def reboot(self): if self.job.status == self.job.FINISHED: - self["statusbar"].text = _("rebooting...") + self["statusbar"].text = ("rebooting...") TryQuitMainloop(self.session,2) def createSummary(self): diff --git a/lib/python/Plugins/SystemPlugins/PositionerSetup/plugin.py b/lib/python/Plugins/SystemPlugins/PositionerSetup/plugin.py index d67a97cb..6d2ddce3 100644 --- a/lib/python/Plugins/SystemPlugins/PositionerSetup/plugin.py +++ b/lib/python/Plugins/SystemPlugins/PositionerSetup/plugin.py @@ -14,6 +14,8 @@ from Components.ActionMap import ActionMap from Components.NimManager import nimmanager from Components.MenuList import MenuList from Components.config import ConfigSatlist, ConfigNothing, ConfigSelection, ConfigSubsection, KEY_LEFT, KEY_RIGHT, getConfigListEntry +from Components.TuneTest import Tuner +from Tools.Transponder import ConvertToHumanReadable from time import sleep @@ -26,22 +28,20 @@ class PositionerSetup(Screen): <widget name="green" position="140,155" size="140,80" backgroundColor="green" halign="center" valign="center" font="Regular;21" /> <widget name="yellow" position="280,155" size="140,80" backgroundColor="yellow" halign="center" valign="center" font="Regular;21" /> <widget name="blue" position="420,155" size="140,80" backgroundColor="blue" halign="center" valign="center" font="Regular;21" /> - - <widget name="snr" text="SNR:" position="0,245" size="60,22" font="Regular;21" /> - <widget name="agc" text="AGC:" position="0,270" size="60,22" font="Regular;21" /> - <widget name="ber" text="BER:" position="0,295" size="60,22" font="Regular;21" /> - <widget name="lock" text="Lock:" position="0,320" size="60,22" font="Regular;21" /> - <widget name="snr_percentage" position="220,245" size="60,22" font="Regular;21" /> - <widget name="agc_percentage" position="220,270" size="60,22" font="Regular;21" /> + + <widget name="snr_db" position="60,245" size="150,22" halign="center" valign="center" font="Regular;21" /> + <eLabel text="SNR:" position="0,270" size="60,22" font="Regular;21" /> + <eLabel text="BER:" position="0,295" size="60,22" font="Regular;21" /> + <eLabel text="Lock:" position="0,320" size="60,22" font="Regular;21" /> + <widget name="snr_percentage" position="220,270" size="60,22" font="Regular;21" /> <widget name="ber_value" position="220,295" size="60,22" font="Regular;21" /> <widget name="lock_state" position="60,320" size="150,22" font="Regular;21" /> - <widget name="snr_bar" position="60,245" size="150,22" /> - <widget name="agc_bar" position="60,270" size="150,22" /> + <widget name="snr_bar" position="60,270" size="150,22" /> <widget name="ber_bar" position="60,295" size="150,22" /> - <widget name="frequency" text="Frequency:" position="300,245" size="120,22" font="Regular;21" /> - <widget name="symbolrate" text="Symbolrate:" position="300,270" size="120,22" font="Regular;21" /> - <widget name="fec" text="FEC:" position="300,295" size="120,22" font="Regular;21" /> + <eLabel text="Frequency:" position="300,245" size="120,22" font="Regular;21" /> + <eLabel text="Symbolrate:" position="300,270" size="120,22" font="Regular;21" /> + <eLabel text="FEC:" position="300,295" size="120,22" font="Regular;21" /> <widget name="frequency_value" position="420,245" size="120,22" font="Regular;21" /> <widget name="symbolrate_value" position="420,270" size="120,22" font="Regular;21" /> <widget name="fec_value" position="420,295" size="120,22" font="Regular;21" /> @@ -51,23 +51,46 @@ class PositionerSetup(Screen): Screen.__init__(self, session) self.feid = feid self.oldref = None - + + cur = { } if not self.openFrontend(): self.oldref = session.nav.getCurrentlyPlayingServiceReference() + service = session.nav.getCurrentService() + feInfo = service and service.frontendInfo() + if feInfo: + cur = feInfo.getTransponderData(True) + del feInfo + del service session.nav.stopService() # try to disable foreground service if not self.openFrontend(): if session.pipshown: # try to disable pip + service = self.session.pip.pipservice + feInfo = service and service.frontendInfo() + if feInfo: + cur = feInfo.getTransponderData() + del feInfo + del service session.pipshown = False del session.pip if not self.openFrontend(): self.frontend = None # in normal case this should not happen - + self.frontendStatus = { } - self.diseqc = Diseqc(self.frontend) self.tuner = Tuner(self.frontend) - self.tuner.tune((0,0,0,0,0,0)) - + + tp = ( cur.get("frequency", 0) / 1000, + cur.get("symbol_rate", 0) / 1000, + cur.get("polarization", eDVBFrontendParametersSatellite.Polarisation_Horizontal), + cur.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto), + cur.get("inversion", eDVBFrontendParametersSatellite.Inversion_Unknown), + cur.get("orbital_position", 0), + cur.get("system", eDVBFrontendParametersSatellite.System_DVB_S), + cur.get("modulation", eDVBFrontendParametersSatellite.Modulation_QPSK), + cur.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35), + cur.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown)) + + self.tuner.tune(tp) self.createConfig() self.isMoving = False @@ -81,27 +104,18 @@ class PositionerSetup(Screen): self["yellow"] = self.yellow self.blue = Label("") self["blue"] = self.blue - + self.list = [] self["list"] = ConfigList(self.list) self.createSetup() - - self["snr"] = Label() - self["agc"] = Label() - self["ber"] = Label() - self["lock"] = Label() + + self["snr_db"] = TunerInfo(TunerInfo.SNR_DB, statusDict = self.frontendStatus) self["snr_percentage"] = TunerInfo(TunerInfo.SNR_PERCENTAGE, statusDict = self.frontendStatus) - self["agc_percentage"] = TunerInfo(TunerInfo.AGC_PERCENTAGE, statusDict = self.frontendStatus) self["ber_value"] = TunerInfo(TunerInfo.BER_VALUE, statusDict = self.frontendStatus) self["snr_bar"] = TunerInfo(TunerInfo.SNR_BAR, statusDict = self.frontendStatus) - self["agc_bar"] = TunerInfo(TunerInfo.AGC_BAR, statusDict = self.frontendStatus) self["ber_bar"] = TunerInfo(TunerInfo.BER_BAR, statusDict = self.frontendStatus) self["lock_state"] = TunerInfo(TunerInfo.LOCK_STATE, statusDict = self.frontendStatus) - self["frequency"] = Label() - self["symbolrate"] = Label() - self["fec"] = Label() - self["frequency_value"] = Label("") self["symbolrate_value"] = Label("") self["fec_value"] = Label("") @@ -260,7 +274,12 @@ class PositionerSetup(Screen): elif entry == "limits": self.diseqccommand("limitOff") elif entry == "tune": - self.session.openWithCallback(self.tune, TunerScreen, self.feid) + fe_data = { } + self.frontend.getFrontendData(fe_data) + self.frontend.getTransponderData(fe_data, True) + feparm = self.tuner.lastparm.getDVBS() + fe_data["orbital_position"] = feparm.orbital_position + self.session.openWithCallback(self.tune, TunerScreen, self.feid, fe_data) elif entry == "goto0": print "move to position 0" self.diseqccommand("moveTo", 0) @@ -283,6 +302,7 @@ class PositionerSetup(Screen): elif entry == "storage": print "store at position", int(self.positioner_storage.value) self.diseqccommand("store", int(self.positioner_storage.value)) + elif entry == "limits": self.diseqccommand("limitWest") @@ -329,14 +349,13 @@ class PositionerSetup(Screen): def updateStatus(self): if self.frontend: self.frontend.getFrontendStatus(self.frontendStatus) + self["snr_db"].update() self["snr_percentage"].update() - self["agc_percentage"].update() self["ber_value"].update() self["snr_bar"].update() - self["agc_bar"].update() self["ber_bar"].update() self["lock_state"].update() - transponderdata = self.tuner.getTransponderData() + transponderdata = ConvertToHumanReadable(self.tuner.getTransponderData()) self["frequency_value"].setText(str(transponderdata.get("frequency"))) self["symbolrate_value"].setText(str(transponderdata.get("symbol_rate"))) self["fec_value"].setText(str(transponderdata.get("fec_inner"))) @@ -387,37 +406,6 @@ class Diseqc: sleep(0.05) self.frontend.sendDiseqc(cmd) # send 2nd time -class Tuner: - def __init__(self, frontend): - self.frontend = frontend - - def tune(self, transponder): - print "tuning to transponder with data", transponder - parm = eDVBFrontendParametersSatellite() - parm.frequency = transponder[0] * 1000 - parm.symbol_rate = transponder[1] * 1000 - parm.polarisation = transponder[2] - parm.fec = transponder[3] - parm.inversion = transponder[4] - parm.orbital_position = transponder[5] - parm.system = 0 # FIXMEE !! HARDCODED DVB-S (add support for DVB-S2) - parm.modulation = 1 # FIXMEE !! HARDCODED QPSK - feparm = eDVBFrontendParameters() - feparm.setDVBS(parm, True) - self.lastparm = feparm - if self.frontend: - self.frontend.tune(feparm) - - def retune(self): - if self.frontend: - self.frontend.tune(self.lastparm) - - def getTransponderData(self): - ret = { } - if self.frontend: - self.frontend.getTransponderData(ret, True) - return ret - tuning = None class TunerScreen(ScanSetup): @@ -427,8 +415,9 @@ class TunerScreen(ScanSetup): <widget name="introduction" position="20,360" size="350,30" font="Regular;23" /> </screen>""" - def __init__(self, session, feid): + def __init__(self, session, feid, fe_data): self.feid = feid + self.fe_data = fe_data ScanSetup.__init__(self, session) self["introduction"].setText("") @@ -440,21 +429,35 @@ class TunerScreen(ScanSetup): self.list.append(self.typeOfTuningEntry) self.satEntry = getConfigListEntry(_('Satellite'), tuning.sat) self.list.append(self.satEntry) + nim = nimmanager.nim_slots[self.feid] + self.systemEntry = None + if tuning.type.value == "manual_transponder": + if nim.isCompatible("DVB-S2"): + self.systemEntry = getConfigListEntry(_('System'), self.scan_sat.system) + self.list.append(self.systemEntry) + else: + # downgrade to dvb-s, in case a -s2 config was active + self.scan_sat.system.value = eDVBFrontendParametersSatellite.System_DVB_S self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency)) self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion)) self.list.append(getConfigListEntry(_('Symbol Rate'), self.scan_sat.symbolrate)) self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization)) - self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec)) + if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S: + self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec)) + elif self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2: + self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec_s2)) + self.modulationEntry = getConfigListEntry(_('Modulation'), self.scan_sat.modulation) + self.list.append(self.modulationEntry) + self.list.append(getConfigListEntry(_('Rolloff'), self.scan_sat.rolloff)) + self.list.append(getConfigListEntry(_('Pilot'), self.scan_sat.pilot)) elif tuning.type.value == "predefined_transponder": self.list.append(getConfigListEntry(_("Transponder"), tuning.transponder)) self["config"].list = self.list self["config"].l.setList(self.list) def newConfig(self): - if self["config"].getCurrent() == self.typeOfTuningEntry: - self.createSetup() - elif self["config"].getCurrent() == self.satEntry: + if self["config"].getCurrent() in (self.typeOfTuningEntry, self.satEntry, self.systemEntry): self.createSetup() def createConfig(self, foo): @@ -468,8 +471,14 @@ class TunerScreen(ScanSetup): tuning.sat = ConfigSatlist(list=nimmanager.getRotorSatListForNim(self.feid)) tuning.sat.addNotifier(self.tuningSatChanged) self.updateTransponders() - TunerScreenConfigCreated = True - ScanSetup.createConfig(self, None) + orb_pos = self.fe_data.get("orbital_position", None) + if orb_pos is not None: + for x in nimmanager.getRotorSatListForNim(self.feid): + opos = str(orb_pos) + if x[0] == orb_pos and tuning.sat.value != opos: + tuning.sat.value = opos + del self.fe_data["orbital_position"] + ScanSetup.createConfig(self, self.fe_data) def tuningSatChanged(self, *parm): self.updateTransponders() @@ -491,46 +500,55 @@ class TunerScreen(ScanSetup): else: pol = "??" if x[4] == 0: - fec = "FEC_AUTO" + fec = "FEC Auto" elif x[4] == 1: - fec = "FEC_1_2" + fec = "FEC 1/2" elif x[4] == 2: - fec = "FEC_2_3" + fec = "FEC 2/3" elif x[4] == 3: - fec = "FEC_3_4" + fec = "FEC 3/4" elif x[4] == 4: - fec = "FEC_5_6" + fec = "FEC 5/6" elif x[4] == 5: - fec = "FEC_7_8" + fec = "FEC 7/8" elif x[4] == 6: - fec = "FEC_8_9" + fec = "FEC 8/9" elif x[4] == 7: - fec = "FEC_3_5" + fec = "FEC 3/5" elif x[4] == 8: - fec = "FEC_4_5" + fec = "FEC 4/5" elif x[4] == 9: - fec = "FEC_9_10" + fec = "FEC 9/10" elif x[4] == 15: - fec = "FEC_None" + fec = "FEC None" else: - fec = "FEC_Unknown" + fec = "FEC Unknown" tps.append(str(x[1]) + "," + str(x[2]) + "," + pol + "," + fec) tuning.transponder = ConfigSelection(choices=tps) def keyGo(self): - returnvalue = (0, 0, 0, 0, 0, 0) + returnvalue = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) satpos = int(tuning.sat.value) if tuning.type.value == "manual_transponder": + if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2: + fec = self.scan_sat.fec_s2.value + else: + fec = self.scan_sat.fec.value returnvalue = ( self.scan_sat.frequency.value, self.scan_sat.symbolrate.value, - self.scan_sat.polarization.index, - self.scan_sat.fec.index, - self.scan_sat.inversion.index, - satpos) + self.scan_sat.polarization.value, + fec, + self.scan_sat.inversion.value, + satpos, + self.scan_sat.system.value, + self.scan_sat.modulation.value, + self.scan_sat.rolloff.value, + self.scan_sat.pilot.value) elif tuning.type.value == "predefined_transponder": transponder = nimmanager.getTransponders(satpos)[tuning.transponder.index] - returnvalue = (int(transponder[1] / 1000), int(transponder[2] / 1000), transponder[3], transponder[4], 2, satpos) + returnvalue = (transponder[1] / 1000, transponder[2] / 1000, + transponder[3], transponder[4], 2, satpos, transponder[5], transponder[6], transponder[8], transponder[9]) self.close(returnvalue) def keyCancel(self): @@ -538,8 +556,8 @@ class TunerScreen(ScanSetup): class RotorNimSelection(Screen): skin = """ - <screen position="140,165" size="400,100" title="select Slot"> - <widget name="nimlist" position="20,10" size="360,75" /> + <screen position="140,165" size="400,130" title="select Slot"> + <widget name="nimlist" position="20,10" size="360,100" /> </screen>""" def __init__(self, session): diff --git a/lib/python/Plugins/SystemPlugins/Satfinder/plugin.py b/lib/python/Plugins/SystemPlugins/Satfinder/plugin.py index 74568855..8e148812 100644 --- a/lib/python/Plugins/SystemPlugins/Satfinder/plugin.py +++ b/lib/python/Plugins/SystemPlugins/Satfinder/plugin.py @@ -12,73 +12,9 @@ from Components.ActionMap import ActionMap from Components.NimManager import nimmanager, getConfigSatlist from Components.MenuList import MenuList from Components.config import ConfigSelection, getConfigListEntry - -class Tuner: - def __init__(self, frontend): - self.frontend = frontend - - def tune(self, transponder): - if self.frontend: - print "tuning to transponder with data", transponder - parm = eDVBFrontendParametersSatellite() - parm.frequency = transponder[0] * 1000 - parm.symbol_rate = transponder[1] * 1000 - parm.polarisation = transponder[2] - parm.fec = transponder[3] - parm.inversion = transponder[4] - parm.orbital_position = transponder[5] - parm.system = 0 # FIXMEE !! HARDCODED DVB-S (add support for DVB-S2) - parm.modulation = 1 # FIXMEE !! HARDCODED QPSK - feparm = eDVBFrontendParameters() - feparm.setDVBS(parm) - self.lastparm = feparm - self.frontend.tune(feparm) - - def retune(self): - if self.frontend: - self.frontend.tune(self.lastparm) +from Components.TuneTest import Tuner class Satfinder(ScanSetup): - skin = """ - <screen position="90,100" size="520,400" title="Tune"> - <widget name="config" position="20,10" size="460,210" scrollbarMode="showOnDemand" /> - <widget name="introduction" position="20,360" zPosition="-10" size="350,30" font="Regular;23" /> - <eLabel text="dB:" position="23,230" size="60,22" font="Regular;21" /> - <eLabel text="SNR:" position="23,255" size="60,22" font="Regular;21" /> - <eLabel text="AGC:" position="23,280" size="60,22" font="Regular;21" /> - <eLabel text="BER:" position="23,305" size="60,22" font="Regular;21" /> - <eLabel text="Lock:" position="23,330" size="60,22" font="Regular;21" /> - <widget source="Frontend" render="Label" position="295,230" size="60,22" font="Regular;21" > - <convert type="FrontendInfo">SNRdB</convert> - </widget> - <widget source="Frontend" render="Label" position="295,255" size="60,22" font="Regular;21" > - <convert type="FrontendInfo">SNR</convert> - </widget> - <widget source="Frontend" render="Label" position="295,280" size="60,22" font="Regular;21" > - <convert type="FrontendInfo">AGC</convert> - </widget> - <widget source="Frontend" render="Label" position="295,305" size="60,22" font="Regular;21" > - <convert type="FrontendInfo">BER</convert> - </widget> - <widget source="Frontend" render="Progress" position="85,257" size="200,22" > - <convert type="FrontendInfo">SNR</convert> - </widget> - <widget source="Frontend" render="Progress" position="85,282" size="200,22" > - <convert type="FrontendInfo">AGC</convert> - </widget> - <widget source="Frontend" render="Progress" position="85,307" size="200,22" > - <convert type="FrontendInfo">BER</convert> - </widget> - <widget source="Frontend" render="Pixmap" pixmap="skin_default/buttons/key_green.png" position="295,330" zPosition="4" size="28,20" alphatest="on" > - <convert type="FrontendInfo">LOCK</convert> - <convert type="ConditionalShowHide" /> - </widget> - <widget source="Frontend" render="Pixmap" pixmap="skin_default/buttons/key_red.png" position="295,330" zPosition="4" size="28,20" alphatest="on" > - <convert type="FrontendInfo">LOCK</convert> - <convert type="ConditionalShowHide">Invert</convert> - </widget> - </screen>""" - def openFrontend(self): res_mgr = eDVBResourceManager.getInstance() if res_mgr: @@ -125,25 +61,44 @@ class Satfinder(ScanSetup): self.satEntry = None self.list = [] + self.typeOfTuningEntry = getConfigListEntry(_('Tune'), self.tuning_type) self.list.append(self.typeOfTuningEntry) self.satEntry = getConfigListEntry(_('Satellite'), self.tuning_sat) self.list.append(self.satEntry) + + nim = nimmanager.nim_slots[self.feid] + + self.systemEntry = None if self.tuning_type.value == "manual_transponder": + if nim.isCompatible("DVB-S2"): + self.systemEntry = getConfigListEntry(_('System'), self.scan_sat.system) + self.list.append(self.systemEntry) + else: + # downgrade to dvb-s, in case a -s2 config was active + self.scan_sat.system.value = eDVBFrontendParametersSatellite.System_DVB_S self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency)) self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion)) self.list.append(getConfigListEntry(_('Symbol Rate'), self.scan_sat.symbolrate)) self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization)) - self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec)) + if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S: + self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec)) + elif self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2: + self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec_s2)) + self.modulationEntry = getConfigListEntry(_('Modulation'), self.scan_sat.modulation) + self.list.append(self.modulationEntry) + self.list.append(getConfigListEntry(_('Rolloff'), self.scan_sat.rolloff)) + self.list.append(getConfigListEntry(_('Pilot'), self.scan_sat.pilot)) elif self.tuning_transponder and self.tuning_type.value == "predefined_transponder": self.list.append(getConfigListEntry(_("Transponder"), self.tuning_transponder)) self["config"].list = self.list self["config"].l.setList(self.list) def newConfig(self): - if self["config"].getCurrent() == self.typeOfTuningEntry: + cur = self["config"].getCurrent() + if cur in (self.typeOfTuningEntry, self.systemEntry): self.createSetup() - elif self["config"].getCurrent() == self.satEntry: + elif cur == self.satEntry: self.updateSats() self.createSetup() @@ -152,20 +107,33 @@ class Satfinder(ScanSetup): self.retune(config_element) def retune(self, configElement): - returnvalue = (0, 0, 0, 0, 0, 0, 0) - satpos = self.tuning_sat.orbital_position - - if satpos is not None: - if self.tuning_type.value == "manual_transponder": - returnvalue = (self.scan_sat.frequency.value, self.scan_sat.symbolrate.value, self.scan_sat.polarization.index, self.scan_sat.fec.index, self.scan_sat.inversion.index, satpos) + returnvalue = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + satpos = int(self.tuning_sat.value) + if self.tuning_type.value == "manual_transponder": + if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2: + fec = self.scan_sat.fec_s2.value + else: + fec = self.scan_sat.fec.value + returnvalue = ( + self.scan_sat.frequency.value, + self.scan_sat.symbolrate.value, + self.scan_sat.polarization.value, + fec, + self.scan_sat.inversion.value, + satpos, + self.scan_sat.system.value, + self.scan_sat.modulation.value, + self.scan_sat.rolloff.value, + self.scan_sat.pilot.value) + self.tune(returnvalue) + elif self.tuning_type.value == "predefined_transponder": + tps = nimmanager.getTransponders(satpos) + l = len(tps) + if l > self.tuning_transponder.index: + transponder = tps[self.tuning_transponder.index] + returnvalue = (transponder[1] / 1000, transponder[2] / 1000, + transponder[3], transponder[4], 2, satpos, transponder[5], transponder[6], transponder[8], transponder[9]) self.tune(returnvalue) - elif self.tuning_type.value == "predefined_transponder": - tps = nimmanager.getTransponders(satpos) - l = len(tps) - if l > self.tuning_transponder.index: - transponder = nimmanager.getTransponders(satpos)[self.tuning_transponder.index] - returnvalue = (int(transponder[1] / 1000), int(transponder[2] / 1000), transponder[3], transponder[4], 2, satpos) - self.tune(returnvalue) def createConfig(self, foo): self.tuning_transponder = None @@ -174,14 +142,13 @@ class Satfinder(ScanSetup): ScanSetup.createConfig(self, None) self.updateSats() - - self.tuning_type.addNotifier(self.retune, initial_call = False) - self.tuning_sat.addNotifier(self.sat_changed, initial_call = False) - self.scan_sat.frequency.addNotifier(self.retune, initial_call = False) - self.scan_sat.inversion.addNotifier(self.retune, initial_call = False) - self.scan_sat.symbolrate.addNotifier(self.retune, initial_call = False) - self.scan_sat.polarization.addNotifier(self.retune, initial_call = False) - self.scan_sat.fec.addNotifier(self.retune, initial_call = False) + + for x in (self.tuning_type, self.tuning_sat, self.scan_sat.frequency, + self.scan_sat.inversion, self.scan_sat.symbolrate, + self.scan_sat.polarization, self.scan_sat.fec, self.scan_sat.pilot, + self.scan_sat.fec_s2, self.scan_sat.fec, self.scan_sat.modulation, + self.scan_sat.rolloff, self.scan_sat.system): + x.addNotifier(self.retune, initial_call = False) def updateSats(self): orb_pos = self.tuning_sat.orbital_position @@ -201,29 +168,29 @@ class Satfinder(ScanSetup): else: pol = "??" if x[4] == 0: - fec = "FEC_AUTO" + fec = "FEC Auto" elif x[4] == 1: - fec = "FEC_1_2" + fec = "FEC 1/2" elif x[4] == 2: - fec = "FEC_2_3" + fec = "FEC 2/3" elif x[4] == 3: - fec = "FEC_3_4" + fec = "FEC 3/4" elif x[4] == 4: - fec = "FEC_5_6" + fec = "FEC 5/6" elif x[4] == 5: - fec = "FEC_7_8" + fec = "FEC 7/8" elif x[4] == 6: - fec = "FEC_8_9" + fec = "FEC 8/9" elif x[4] == 7: - fec = "FEC_3_5" + fec = "FEC 3/5" elif x[4] == 8: - fec = "FEC_4_5" + fec = "FEC 4/5" elif x[4] == 9: - fec = "FEC_9_10" + fec = "FEC 9/10" elif x[4] == 15: - fec = "FEC_None" + fec = "FEC None" else: - fec = "FEC_Unknown" + fec = "FEC Unknown" e = str(x[1]) + "," + str(x[2]) + "," + pol + "," + fec if default is None: default = e @@ -256,8 +223,8 @@ class Satfinder(ScanSetup): class SatNimSelection(Screen): skin = """ - <screen position="140,165" size="400,100" title="select Slot"> - <widget name="nimlist" position="20,10" size="360,75" /> + <screen position="140,165" size="400,130" title="select Slot"> + <widget name="nimlist" position="20,10" size="360,100" /> </screen>""" def __init__(self, session): @@ -281,7 +248,13 @@ class SatNimSelection(Screen): self.session.open(Satfinder, selection) def SatfinderMain(session, **kwargs): - nimList = nimmanager.getNimListOfType("DVB-S") + nims = nimmanager.getNimListOfType("DVB-S") + + nimList = [] + for x in nims: + if not nimmanager.getNimConfig(x).configMode.value in ("loopthrough", "satposdepends", "nothing"): + nimList.append(x) + if len(nimList) == 0: session.open(MessageBox, _("No satellite frontend found!!"), MessageBox.TYPE_ERROR) else: diff --git a/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py b/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py index 2422475e..6a85c4da 100644 --- a/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py +++ b/lib/python/Plugins/SystemPlugins/Videomode/VideoHardware.py @@ -59,10 +59,37 @@ class VideoHardware: widescreen_modes = set(["720p", "1080i"]) + def getOutputAspect(self): + ret = (16,9) + port = config.av.videoport.value + if port not in config.av.videomode: + print "current port not available in getOutputAspect!!! force 16:9" + else: + mode = config.av.videomode[port].value + force_widescreen = self.isWidescreenMode(port, mode) + is_widescreen = force_widescreen or config.av.aspect.value in ["16_9", "16_10"] + is_auto = config.av.aspect.value == "auto" + if is_widescreen: + if force_widescreen: + pass + else: + aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value] + if aspect == "16:10": + ret = (16,10) + elif is_auto: + try: + aspect_str = open("/proc/stb/vmpeg/0/aspect", "r").read() + if aspect_str == "1": # 4:3 + ret = (4,3) + except IOError: + pass + else: # 4:3 + ret = (4,3) + return ret + def __init__(self): self.last_modes_preferred = [ ] self.on_hotplug = CList() - self.standby = False self.current_mode = None self.current_port = None @@ -79,7 +106,7 @@ class VideoHardware: config.av.aspectratio.notifiers = [ ] config.av.tvsystem.notifiers = [ ] config.av.wss.notifiers = [ ] - AVSwitch.setInput = self.AVSwitchSetInput + AVSwitch.getOutputAspect = self.getOutputAspect config.av.aspect.addNotifier(self.updateAspect) config.av.wss.addNotifier(self.updateAspect) @@ -91,12 +118,6 @@ class VideoHardware: # self.timer.callback.append(self.readPreferredModes) # self.timer.start(1000) - config.av.colorformat.addNotifier(self.updateFastblank) - - def AVSwitchSetInput(self, mode): - self.standby = mode == "SCART" - self.updateStandby() - def readAvailableModes(self): try: modes = open("/proc/stb/video/videomode_choices").read()[:-1] @@ -264,6 +285,7 @@ class VideoHardware: is_widescreen = force_widescreen or config.av.aspect.value in ["16_9", "16_10"] is_auto = config.av.aspect.value == "auto" + policy2 = "policy" # use main policy if is_widescreen: if force_widescreen: @@ -271,6 +293,7 @@ class VideoHardware: else: aspect = {"16_9": "16:9", "16_10": "16:10"}[config.av.aspect.value] policy = {"pillarbox": "panscan", "panscan": "letterbox", "nonlinear": "nonlinear", "scale": "bestfit"}[config.av.policy_43.value] + policy2 = {"letterbox": "letterbox", "panscan": "panscan", "scale": "bestfit"}[config.av.policy_169.value] elif is_auto: aspect = "any" policy = "bestfit" @@ -283,46 +306,14 @@ class VideoHardware: else: wss = "auto" - print "-> setting aspect, policy, wss", aspect, policy, wss + print "-> setting aspect, policy, policy2, wss", aspect, policy, policy2, wss open("/proc/stb/video/aspect", "w").write(aspect) open("/proc/stb/video/policy", "w").write(policy) open("/proc/stb/denc/0/wss", "w").write(wss) - self.updateSlowblank() - self.updateFastblank() - - def updateSlowblank(self): - if self.standby: - from Components.SystemInfo import SystemInfo - if SystemInfo["ScartSwitch"]: - input = "scart" - sb = "vcr" - else: - input = "off" - sb = "0" - else: - input = "encoder" - sb = "auto" - - open("/proc/stb/avs/0/sb", "w").write(sb) - open("/proc/stb/avs/0/input", "w").write(input) - - def updateStandby(self): - self.updateSlowblank() - self.updateFastblank() - - def updateFastblank(self, *args): - if self.standby: - from Components.SystemInfo import SystemInfo - if SystemInfo["ScartSwitch"]: - fb = "vcr" - else: - fb = "low" - else: - if self.current_port == "Scart" and config.av.colorformat.value == "rgb": - fb = "high" - else: - fb = "low" - open("/proc/stb/avs/0/fb", "w").write(fb) + try: + open("/proc/stb/video/policy2", "w").write(policy2) + except IOError: + pass config.av.edid_override = ConfigYesNo(default = False) video_hw = VideoHardware() diff --git a/lib/python/Plugins/SystemPlugins/Videomode/plugin.py b/lib/python/Plugins/SystemPlugins/Videomode/plugin.py index ab7aad72..30bdf796 100644 --- a/lib/python/Plugins/SystemPlugins/Videomode/plugin.py +++ b/lib/python/Plugins/SystemPlugins/Videomode/plugin.py @@ -78,6 +78,7 @@ class VideoSetup(Screen, ConfigListScreen): if force_wide or config.av.aspect.value in ["16_9", "16_10"]: self.list.append(getConfigListEntry(_("Display 4:3 content as"), config.av.policy_43)) + self.list.append(getConfigListEntry(_("Display >16:9 content as"), config.av.policy_169)) elif config.av.aspect.value == "4_3": self.list.append(getConfigListEntry(_("Display 16:9 content as"), config.av.policy_169)) diff --git a/lib/python/Plugins/newplugin.py b/lib/python/Plugins/newplugin.py new file mode 100644 index 00000000..48bb28ea --- /dev/null +++ b/lib/python/Plugins/newplugin.py @@ -0,0 +1,146 @@ +#!/usr/bin/python + +import os + +os.system("clear") +internalname = raw_input("Internal plugin name (no whitespaces, plugin directory): ") +name = raw_input("Visible plugin name: ") +print + +os.system("clear") +dirlist = [] +count = 0 +print "Plugin categories:" +for dir in os.listdir("."): + if os.path.isdir(dir): + count += 1 + dirlist.append(dir) + print count, dir + +category = raw_input("Select plugin category: ") +category = dirlist[int(category) - 1] + +def add_where_extensionsmenu(name, fnc): + description = raw_input("Plugin description: ") + return 'PluginDescriptor(name = "%s", description = _("%s"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc = %s)' % (name, description, fnc) + +def add_where_pluginmenu(name, fnc): + description = raw_input("Plugin description: ") + icon = raw_input("Icon (default: 'plugin.png': ") + if icon == "": + icon = "plugin.png" + return 'PluginDescriptor(name = "%s", description = _("%s"), icon = "%s", where = PluginDescriptor.WHERE_PLUGINMENU, fnc = %s)' % (name, description, icon, fnc) + +wherelist = [] +wherelist.append(("WHERE_EXTENSIONSMENU", add_where_extensionsmenu)) +wherelist.append(("WHERE_PLUGINMENU", add_where_pluginmenu)) + +targetlist = [] + +stop = False + +while not stop: + os.system("clear") + print "selected targets:" + for where in targetlist: + print where[0] + + print + print "available targets:" + count = 0 + for where in wherelist: + count += 1 + print count, where[0] + print "x break" + + target = raw_input("Select WHERE-target: ") + if target == "x": + stop = True + else: + if wherelist[int(target) - 1] not in targetlist: + targetlist.append(wherelist[int(target) - 1]) + else: + targetlist.remove(wherelist[int(target) - 1]) + + +pluginpath = category + "/" + internalname +os.mkdir(pluginpath) + +makefile = open(category + "/Makefile.am", "r") +lines = makefile.readlines() +lines = ''.join(lines) +lines = lines.strip() +lines += " " + internalname +makefile.close() + +makefile = open(category + "/Makefile.am", "w") +makefile.write(lines) +makefile.close() + +lines = [] +print "open" +configure = open("../../../configure.ac", "r") +while True: + line = configure.readline() + if not line: + break + lines.append(line) + if line.strip() == "lib/python/Plugins/" + category + "/Makefile": + lines.append("lib/python/Plugins/" + pluginpath + "/Makefile\n") +configure.close() +print "close" + +configure = open("../../../configure.ac", "w") +configure.writelines(lines) +configure.close() + +file = open(pluginpath + "/plugin.py", "w") + +importlist = [] +for where in targetlist: + importlist.append(where[0]) + +file.write("""from Screens.Screen import Screen +from Plugins.Plugin import PluginDescriptor, %s +""" % ', '.join(importlist)) + +mainlist = [] +for count in range(len(targetlist)): + if count == 0: + mainlist.append("main") + else: + mainlist.append("main" + str(count)) + +for main in mainlist: + file.write(""" +def %s(session, **kwargs): + pass +""" % main) + +descriptorlist = [] +for count in range(len(targetlist)): + os.system("clear") + where = targetlist[count] + print "Options for target %s" % where[0] + descriptorlist.append(where[1](name, mainlist[count])) + +if len(descriptorlist) == 1: + descriptorlist = descriptorlist[0] +else: + descriptorlist = "[" + ', '.join(descriptorlist) + "]" + +file.write(""" +def Plugins(**kwargs): + return %s + """ % descriptorlist) + +file.close() + +makefile = open(pluginpath + "/Makefile.am", "w") +makefile.write("""installdir = $(LIBDIR)/enigma2/python/Plugins/%s/%s + +install_PYTHON = \\ + __init__.py \\ + plugin.py +""" % (category, internalname)) +makefile.close() diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index b203b24e..ebfbe812 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -76,7 +76,7 @@ def append_when_current_valid(current, menu, args, level = 0): class ChannelContextMenu(Screen): def __init__(self, session, csel): Screen.__init__(self, session) - #raise "we need a better summary screen here" + #raise Exception("we need a better summary screen here") self.csel = csel self.bsel = None diff --git a/lib/python/Screens/Console.py b/lib/python/Screens/Console.py index b57f2400..c6b156cf 100644 --- a/lib/python/Screens/Console.py +++ b/lib/python/Screens/Console.py @@ -55,6 +55,7 @@ class Console(Screen): str = self["text"].getText() str += _("Execution finished!!"); self["text"].setText(str) + self["text"].lastPage() if self.finishedCallback is not None: self.finishedCallback() if not retval and self.closeOnSuccess: @@ -67,4 +68,4 @@ class Console(Screen): self.container.dataAvail.remove(self.dataAvail) def dataAvail(self, str): - self["text"].setText(self["text"].getText() + str) + self["text"].setText(self["text"].getText() + str)
\ No newline at end of file diff --git a/lib/python/Screens/EpgSelection.py b/lib/python/Screens/EpgSelection.py index 6740bfb6..e7388fc2 100644 --- a/lib/python/Screens/EpgSelection.py +++ b/lib/python/Screens/EpgSelection.py @@ -5,11 +5,13 @@ from Components.Pixmap import Pixmap from Components.Label import Label from Components.EpgList import EPGList, EPG_TYPE_SINGLE, EPG_TYPE_SIMILAR, EPG_TYPE_MULTI from Components.ActionMap import ActionMap +from Components.TimerSanityCheck import TimerSanityCheck from Screens.TimerEdit import TimerSanityConflict from Screens.EventView import EventViewSimple +from Screens.MessageBox import MessageBox from TimeDateInput import TimeDateInput from enigma import eServiceReference -from RecordTimer import RecordTimerEntry, parseEvent +from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT from TimerEntry import TimerEntry from ServiceReference import ServiceReference from time import localtime, time @@ -17,6 +19,12 @@ from time import localtime, time mepg_config_initialized = False class EPGSelection(Screen): + EMPTY = 0 + ADD_TIMER = 1 + REMOVE_TIMER = 2 + + ZAP = 1 + def __init__(self, session, service, zapFunc=None, eventid=None, bouquetChangeCB=None): Screen.__init__(self, session) self.bouquetChangeCB = bouquetChangeCB @@ -58,6 +66,8 @@ class EPGSelection(Screen): self.zapFunc = zapFunc self["key_green"] = Button(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + self.key_red_choice = self.EMPTY self["list"] = EPGList(type = self.type, selChangedCB = self.onSelectionChanged, timer = self.session.nav.RecordTimer) self["actions"] = ActionMap(["EPGSelectActions", "OkCancelActions"], @@ -125,6 +135,7 @@ class EPGSelection(Screen): l.recalcEntrySize() if self.type == EPG_TYPE_MULTI: l.fillMultiEPG(self.services, self.ask_time) + l.moveToService(self.session.nav.getCurrentlyPlayingServiceReference()) elif self.type == EPG_TYPE_SINGLE: l.fillSingleEPG(self.currentService) else: @@ -145,7 +156,7 @@ class EPGSelection(Screen): setEvent(cur[0]) def zapTo(self): # just used in multiepg - if self.zapFunc and self["key_red"].getText() == "Zap": + if self.zapFunc and self.key_red_choice == self.ZAP: lst = self["list"] count = lst.getCurrentChangeCount() if count == 0: @@ -179,14 +190,28 @@ class EPGSelection(Screen): if self.type == EPG_TYPE_MULTI: self["list"].updateMultiEPG(1) + def removeTimer(self, timer): + timer.afterEvent = AFTEREVENT.NONE + self.session.nav.RecordTimer.removeEntry(timer) + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + def timerAdd(self): cur = self["list"].getCurrent() event = cur[0] serviceref = cur[1] if event is None: return - newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event)) - self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry) + eventid = event.getEventId() + refstr = serviceref.ref.toString() + for timer in self.session.nav.RecordTimer.timer_list: + if timer.eit == eventid and timer.service_ref.ref.toString() == refstr: + cb_func = lambda ret : not ret or self.removeTimer(timer) + self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName()) + break + else: + newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event)) + self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry) def finishedAdd(self, answer): print "finished add" @@ -194,14 +219,18 @@ class EPGSelection(Screen): entry = answer[1] simulTimerList = self.session.nav.RecordTimer.record(entry) if simulTimerList is not None: - if (len(simulTimerList) == 2) and (simulTimerList[1].dontSave) and (simulTimerList[1].autoincrease): - simulTimerList[1].end = entry.begin - 30 - self.session.nav.RecordTimer.timeChanged(simulTimerList[1]) - self.session.nav.RecordTimer.record(entry) - else: + for x in simulTimerList: + if x.setAutoincreaseEnd(entry): + self.session.nav.RecordTimer.timeChanged(x) + simulTimerList = self.session.nav.RecordTimer.record(entry) + if simulTimerList is not None: self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList) + self["key_green"].setText(_("Remove timer")) + self.key_green_choice = self.REMOVE_TIMER else: - print "Timeredit aborted" + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + print "Timeredit aborted" def finishSanityCorrection(self, answer): self.finishedAdd(answer) @@ -211,7 +240,7 @@ class EPGSelection(Screen): def moveDown(self): self["list"].moveDown() - + def applyButtonState(self, state): if state == 0: self["now_button"].hide() @@ -226,13 +255,11 @@ class EPGSelection(Screen): self["key_red"].setText("") else: if state == 1: - self["key_red"].setText("Zap") self["now_button_sel"].show() self["now_button"].hide() else: self["now_button"].show() self["now_button_sel"].hide() - self["key_red"].setText("") if state == 2: self["next_button_sel"].show() @@ -249,6 +276,16 @@ class EPGSelection(Screen): self["more_button_sel"].hide() def onSelectionChanged(self): + cur = self["list"].getCurrent() + if cur is None: + if self.key_green_choice != self.EMPTY: + self["key_green"].setText("") + self.key_green_choice = self.EMPTY + if self.key_red_choice != self.EMPTY: + self["key_red"].setText("") + self.key_red_choice = self.EMPTY + return + event = cur[0] if self.type == EPG_TYPE_MULTI: count = self["list"].getCurrentChangeCount() if self.ask_time != -1: @@ -260,8 +297,7 @@ class EPGSelection(Screen): else: self.applyButtonState(1) days = [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ] - datastr = "" - event = self["list"].getCurrent()[0] + datestr = "" if event is not None: now = time() beg = event.getBeginTime() @@ -272,3 +308,36 @@ class EPGSelection(Screen): else: datestr = '%s %d.%d.'%(_("Today"), begTime[2], begTime[1]) self["date"].setText(datestr) + + if cur[1] is None or cur[1].getServiceName() == "": + if self.key_green_choice != self.EMPTY: + self["key_green"].setText("") + self.key_green_choice = self.EMPTY + if self.key_red_choice != self.EMPTY: + self["key_red"].setText("") + self.key_red_choice = self.EMPTY + return + elif self.key_red_choice != self.ZAP and self.type == EPG_TYPE_MULTI: + self["key_red"].setText("Zap") + self.key_red_choice = self.ZAP + + if event is None: + if self.key_green_choice != self.EMPTY: + self["key_green"].setText("") + self.key_green_choice = self.EMPTY + return + + serviceref = cur[1] + eventid = event.getEventId() + refstr = serviceref.ref.toString() + isRecordEvent = False + for timer in self.session.nav.RecordTimer.timer_list: + if timer.eit == eventid and timer.service_ref.ref.toString() == refstr: + isRecordEvent = True + break + if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER: + self["key_green"].setText(_("Remove timer")) + self.key_green_choice = self.REMOVE_TIMER + elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER: + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER diff --git a/lib/python/Screens/EventView.py b/lib/python/Screens/EventView.py index 5d50d9bc..6aed1e11 100644 --- a/lib/python/Screens/EventView.py +++ b/lib/python/Screens/EventView.py @@ -1,17 +1,21 @@ from Screen import Screen from Screens.TimerEdit import TimerSanityConflict +from Screens.MessageBox import MessageBox from Components.ActionMap import ActionMap from Components.Button import Button from Components.Label import Label from Components.ScrollLabel import ScrollLabel from Components.TimerList import TimerList from enigma import eEPGCache, eTimer, eServiceReference -from RecordTimer import RecordTimerEntry, parseEvent +from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT from TimerEntry import TimerEntry from time import localtime from Components.config import config class EventViewBase: + ADD_TIMER = 0 + REMOVE_TIMER = 1 + def __init__(self, Event, Ref, callback=None, similarEPGCB=None): self.similarEPGCB = similarEPGCB self.cbFunc = callback @@ -28,6 +32,7 @@ class EventViewBase: self.SimilarBroadcastTimer.callback.append(self.getSimilarEvents) else: self.SimilarBroadcastTimer = None + self.key_green_choice = self.ADD_TIMER if self.isRecording: self["key_green"] = Button("") else: @@ -59,8 +64,25 @@ class EventViewBase: if self.cbFunc is not None: self.cbFunc(self.setEvent, self.setService, +1) + def removeTimer(self, timer): + timer.afterEvent = AFTEREVENT.NONE + self.session.nav.RecordTimer.removeEntry(timer) + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + def timerAdd(self): - if not self.isRecording: + event = self.event + serviceref = self.currentService + if event is None: + return + eventid = event.getEventId() + refstr = serviceref.ref.toString() + for timer in self.session.nav.RecordTimer.timer_list: + if timer.eit == eventid and timer.service_ref.ref.toString() == refstr: + cb_func = lambda ret : not ret or self.removeTimer(timer) + self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName()) + break + else: newEntry = RecordTimerEntry(self.currentService, checkOldTimers = True, *parseEvent(self.event)) self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry) @@ -70,13 +92,17 @@ class EventViewBase: entry = answer[1] simulTimerList = self.session.nav.RecordTimer.record(entry) if simulTimerList is not None: - if (len(simulTimerList) == 2) and (simulTimerList[1].dontSave) and (simulTimerList[1].autoincrease): - simulTimerList[1].end = entry.begin - 30 - self.session.nav.RecordTimer.timeChanged(simulTimerList[1]) - self.session.nav.RecordTimer.record(entry) - else: + for x in simulTimerList: + if x.setAutoincreaseEnd(entry): + self.session.nav.RecordTimer.timeChanged(x) + simulTimerList = self.session.nav.RecordTimer.record(entry) + if simulTimerList is not None: self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList) + self["key_green"].setText(_("Remove timer")) + self.key_green_choice = self.REMOVE_TIMER else: + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER print "Timeredit aborted" def finishSanityCorrection(self, answer): @@ -123,6 +149,22 @@ class EventViewBase: if self.SimilarBroadcastTimer is not None: self.SimilarBroadcastTimer.start(400,True) + serviceref = self.currentService + eventid = self.event.getEventId() + refstr = serviceref.ref.toString() + isRecordEvent = False + for timer in self.session.nav.RecordTimer.timer_list: + if timer.eit == eventid and timer.service_ref.ref.toString() == refstr: + isRecordEvent = True + break + if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER: + self["key_green"].setText(_("Remove timer")) + self.key_green_choice = self.REMOVE_TIMER + elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER: + self["key_green"].setText(_("Add timer")) + self.key_green_choice = self.ADD_TIMER + + def pageUp(self): self["epg_description"].pageUp() diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 409018de..89a6b8e3 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -29,7 +29,7 @@ from Screens.TimeDateInput import TimeDateInput from ServiceReference import ServiceReference from Tools import Notifications -from Tools.Directories import SCOPE_HDD, resolveFilename, pathExists +from Tools.Directories import SCOPE_HDD, resolveFilename, fileExists from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \ iPlayableService, eServiceReference, eEPGCache @@ -348,14 +348,14 @@ class InfoBarMenu: def mainMenu(self): print "loading mainmenu XML..." - menu = mdom.childNodes[0] - assert menu.tagName == "menu", "root element in menu must be 'menu'!" + menu = mdom.getroot() + assert menu.tag == "menu", "root element in menu must be 'menu'!" self.session.infobar = self # so we can access the currently active infobar from screens opened from within the mainmenu # at the moment used from the SubserviceSelection - self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu, menu.childNodes) + self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu) def mainMenuClosed(self, *val): self.session.infobar = None @@ -403,7 +403,7 @@ class InfoBarEPG: self.eventView = None self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions", { - "showEventView": (self.openEventView, _("show EPG...")), + "showEventInfo": (self.openEventView, _("show EPG...")), "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")), "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible, }) @@ -1033,7 +1033,13 @@ class InfoBarPVRState: def __playStateChanged(self, state): playstateString = state[3] self.pvrStateDialog["state"].setText(playstateString) - self._mayShow() + + # if we return into "PLAY" state, ensure that the dialog gets hidden if there will be no infobar displayed + if not config.usage.show_infobar_on_skip.value and self.seekstate == self.SEEK_STATE_PLAY: + self.pvrStateDialog.hide() + else: + self._mayShow() + class InfoBarTimeshiftState(InfoBarPVRState): def __init__(self): @@ -1321,7 +1327,6 @@ class InfoBarJobman: self.session.openWithCallback(self.JobViewCB, JobView, job) def JobViewCB(self, in_background): - from Screens.TaskView import JobView job_manager.in_background = in_background # depends on InfoBarExtensions @@ -1437,8 +1442,8 @@ class InfoBarInstantRecord: except: pass - begin = time() - end = time() + 3600 * 24 * 365 * 1 # 1 year + begin = int(time()) + end = begin + 3600 # dummy name = "instant record" description = "" eventid = None @@ -1459,19 +1464,28 @@ class InfoBarInstantRecord: recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = config.movielist.last_videodir.value) recording.dontSave = True - recording.autoincrease = True - - simulTimerList = self.session.nav.RecordTimer.record(recording) - if simulTimerList is not None: - print "timer conflict detected!" - if (len(simulTimerList) > 1): - print "tsc_list > 1" - recording.end = simulTimerList[1].begin - 30 + + if event is None or limitEvent == False: + recording.autoincrease = True + if recording.setAutoincreaseEnd(): self.session.nav.RecordTimer.record(recording) - print "new endtime applied" - else: - print "conflict with only one timer? ! ?" - self.recording.append(recording) + self.recording.append(recording) + else: + simulTimerList = self.session.nav.RecordTimer.record(recording) + if simulTimerList is not None: # conflict with other recording + name = simulTimerList[1].name + name_date = name + strftime(" %c", localtime(simulTimerList[1].begin)) + print "[TIMER] conflicts with", name_date + recording.autoincrease = True # start with max available length, then increment + if recording.setAutoincreaseEnd(): + self.session.nav.RecordTimer.record(recording) + self.recording.append(recording) + self.session.open(MessageBox, _("Record time limited due to conflicting timer %s") % name_date, MessageBox.TYPE_INFO) + else: + self.session.open(MessageBox, _("Couldn't record due to conflicting timer %s") % name, MessageBox.TYPE_INFO) + recording.autoincrease = False + else: + self.recording.append(recording) def isInstantRecordRunning(self): print "self.recording:", self.recording @@ -1544,12 +1558,12 @@ class InfoBarInstantRecord: print "stopping recording after", int(value), "minutes." if int(value) != 0: self.recording[self.selectedEntry].autoincrease = False - self.recording[self.selectedEntry].end = time() + 60 * int(value) + self.recording[self.selectedEntry].end = int(time()) + 60 * int(value) self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry]) def instantRecord(self): dir = config.movielist.last_videodir.value - if not pathExists(dir): + if not fileExists(dir, 'w'): dir = resolveFilename(SCOPE_HDD) try: stat = os_stat(dir) @@ -1561,21 +1575,21 @@ class InfoBarInstantRecord: if self.isInstantRecordRunning(): self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \ title=_("A recording is currently running.\nWhat do you want to do?"), \ - list=[(_("stop recording"), "stop"), \ - (_("change recording (duration)"), "changeduration"), \ - (_("change recording (endtime)"), "changeendtime"), \ - (_("add recording (indefinitely)"), "indefinitely"), \ - (_("add recording (stop after current event)"), "event"), \ + list=[(_("add recording (stop after current event)"), "event"), \ (_("add recording (enter recording duration)"), "manualduration"), \ (_("add recording (enter recording endtime)"), "manualendtime"), \ + (_("add recording (indefinitely)"), "indefinitely"), \ + (_("change recording (duration)"), "changeduration"), \ + (_("change recording (endtime)"), "changeendtime"), \ + (_("stop recording"), "stop"), \ (_("do nothing"), "no")]) else: self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \ title=_("Start recording?"), \ - list=[(_("add recording (indefinitely)"), "indefinitely"), \ - (_("add recording (stop after current event)"), "event"), \ + list=[(_("add recording (stop after current event)"), "event"), \ (_("add recording (enter recording duration)"), "manualduration"), \ (_("add recording (enter recording endtime)"), "manualendtime"), \ + (_("add recording (indefinitely)"), "indefinitely"), \ (_("don't record"), "no")]) from Tools.ISO639 import LanguageCodes diff --git a/lib/python/Screens/Makefile.am b/lib/python/Screens/Makefile.am index a3cf70bb..cde2d6c3 100755 --- a/lib/python/Screens/Makefile.am +++ b/lib/python/Screens/Makefile.am @@ -13,5 +13,6 @@ 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 VirtualKeyBoard.py + SessionGlobals.py LocationBox.py WizardLanguage.py TaskView.py Rc.py VirtualKeyBoard.py \ + TextBox.py diff --git a/lib/python/Screens/Menu.py b/lib/python/Screens/Menu.py index 92039b42..93f23dfb 100644 --- a/lib/python/Screens/Menu.py +++ b/lib/python/Screens/Menu.py @@ -9,12 +9,10 @@ from Components.SystemInfo import SystemInfo from Tools.Directories import resolveFilename, SCOPE_SKIN -import xml.dom.minidom +import xml.etree.cElementTree from Screens.Setup import Setup, getSetupTitle -from Tools import XMLTools - # <item text="TV-Mode">self.setModeTV()</item> # <item text="Radio-Mode">self.setModeRadio()</item> # <item text="File-Mode">self.setModeFile()</item> @@ -22,9 +20,7 @@ from Tools import XMLTools # read the menu -menufile = file(resolveFilename(SCOPE_SKIN, 'menu.xml'), 'r') -mdom = xml.dom.minidom.parseString(menufile.read()) -menufile.close() +mdom = xml.etree.cElementTree.parse(resolveFilename(SCOPE_SKIN, 'menu.xml')) class boundFunction: def __init__(self, fnc, *args): @@ -103,17 +99,17 @@ class Menu(Screen): self.session.openWithCallback(self.menuClosed, Setup, dialog) def addMenu(self, destList, node): - requires = node.getAttribute("requires") + requires = node.get("requires") if requires and not SystemInfo.get(requires, False): return - MenuTitle = _(node.getAttribute("text").encode("UTF-8") or "??") - entryID = node.getAttribute("entryID") or "undefined" - weight = node.getAttribute("weight") or 50 - x = node.getAttribute("flushConfigOnClose") + MenuTitle = _(node.get("text", "??").encode("UTF-8")) + entryID = node.get("entryID", "undefined") + weight = node.get("weight", 50) + x = node.get("flushConfigOnClose") if x: - a = boundFunction(self.session.openWithCallback, self.menuClosedWithConfigFlush, Menu, node, node.childNodes) + a = boundFunction(self.session.openWithCallback, self.menuClosedWithConfigFlush, Menu, node) else: - a = boundFunction(self.session.openWithCallback, self.menuClosed, Menu, node, node.childNodes) + a = boundFunction(self.session.openWithCallback, self.menuClosed, Menu, node) #TODO add check if !empty(node.childNodes) destList.append((MenuTitle, a, entryID, weight)) @@ -126,18 +122,16 @@ class Menu(Screen): self.close(True) def addItem(self, destList, node): - requires = node.getAttribute("requires") + requires = node.get("requires") if requires and not SystemInfo.get(requires, False): return - item_text = node.getAttribute("text").encode("UTF-8") - entryID = node.getAttribute("entryID") or "undefined" - weight = node.getAttribute("weight") or 50 - for x in node.childNodes: - if x.nodeType != xml.dom.minidom.Element.nodeType: - continue - elif x.tagName == 'screen': - module = x.getAttribute("module") or None - screen = x.getAttribute("screen") or None + item_text = node.get("text", "").encode("UTF-8") + entryID = node.get("entryID", "undefined") + weight = node.get("weight", 50) + for x in node: + if x.tag == 'screen': + module = x.get("module") + screen = x.get("screen") if screen is None: screen = module @@ -150,16 +144,16 @@ class Menu(Screen): # check for arguments. they will be appended to the # openDialog call - args = XMLTools.mergeText(x.childNodes) + args = x.text or "" screen += ", " + args destList.append((_(item_text or "??"), boundFunction(self.runScreen, (module, screen)), entryID, weight)) return - elif x.tagName == 'code': - destList.append((_(item_text or "??"), boundFunction(self.execText, XMLTools.mergeText(x.childNodes)), entryID, weight)) + elif x.tag == 'code': + destList.append((_(item_text or "??"), boundFunction(self.execText, x.text), entryID, weight)) return - elif x.tagName == 'setup': - id = x.getAttribute("id") + elif x.tag == 'setup': + id = x.get("id") if item_text == "": item_text = _(getSetupTitle(id)) + "..." else: @@ -169,26 +163,23 @@ class Menu(Screen): destList.append((item_text, self.nothing, entryID, weight)) - def __init__(self, session, parent, childNode): + def __init__(self, session, parent): Screen.__init__(self, session) list = [] menuID = None - for x in childNode: #walk through the actual nodelist - if x.nodeType != xml.dom.minidom.Element.nodeType: - continue - elif x.tagName == 'item': - item_level = int(x.getAttribute("level") or "0") - + for x in parent: #walk through the actual nodelist + if x.tag == 'item': + item_level = int(x.get("level", 0)) if item_level <= config.usage.setup_level.index: self.addItem(list, x) count += 1 - elif x.tagName == 'menu': + elif x.tag == 'menu': self.addMenu(list, x) count += 1 - elif x.tagName == "id": - menuID = x.getAttribute("val") + elif x.tag == "id": + menuID = x.get("val") count = 0 if menuID is not None: @@ -237,10 +228,10 @@ class Menu(Screen): "9": self.keyNumberGlobal }) - a = parent.getAttribute("title").encode("UTF-8") or None + a = parent.get("title", "").encode("UTF-8") or None a = a and _(a) if a is None: - a = _(parent.getAttribute("text").encode("UTF-8")) + a = _(parent.get("text", "").encode("UTF-8")) self["title"] = StaticText(a) self.menu_title = a diff --git a/lib/python/Screens/Satconfig.py b/lib/python/Screens/Satconfig.py index 6489f28f..da6fcc12 100644 --- a/lib/python/Screens/Satconfig.py +++ b/lib/python/Screens/Satconfig.py @@ -87,6 +87,10 @@ class NimSetup(Screen, ConfigListScreen): self.uncommittedDiseqcCommand = None self.cableScanType = None self.have_advanced = False + self.advancedUnicable = None + self.advancedType = None + self.advancedManufacturer = None + self.advancedSCR = None if self.nim.isCompatible("DVB-S"): self.configMode = getConfigListEntry(_("Configuration Mode"), self.nimConfig.configMode) @@ -190,6 +194,7 @@ class NimSetup(Screen, ConfigListScreen): checkList = (self.configMode, self.diseqcModeEntry, self.advancedSatsEntry, \ self.advancedLnbsEntry, self.advancedDiseqcMode, self.advancedUsalsEntry, \ self.advancedLof, self.advancedPowerMeasurement, self.turningSpeed, \ + self.advancedType, self.advancedSCR, self.advancedManufacturer, self.advancedUnicable, \ self.uncommittedDiseqcCommand, self.cableScanType) for x in checkList: if self["config"].getCurrent() == x: @@ -216,19 +221,57 @@ class NimSetup(Screen, ConfigListScreen): if isinstance(currLnb, ConfigNothing): currLnb = None - self.list.append(getConfigListEntry(_("Voltage mode"), Sat.voltage)) - self.list.append(getConfigListEntry(_("Tone mode"), Sat.tonemode)) - if currLnb and currLnb.diseqcMode.value == "1_2": - if lnbnum < 33: - self.advancedUsalsEntry = getConfigListEntry(_("Use usals for this sat"), Sat.usals) - self.list.append(self.advancedUsalsEntry) - if not Sat.usals.value: - self.list.append(getConfigListEntry(_("Stored position"), Sat.rotorposition)) - # LNBs self.advancedLnbsEntry = getConfigListEntry(_("LNB"), Sat.lnb) self.list.append(self.advancedLnbsEntry) + if currLnb: + self.list.append(getConfigListEntry(_("Priority"), currLnb.prio)) + self.advancedLof = getConfigListEntry(_("LOF"), currLnb.lof) + self.list.append(self.advancedLof) + if currLnb.lof.value == "user_defined": + self.list.append(getConfigListEntry(_("LOF/L"), currLnb.lofl)) + self.list.append(getConfigListEntry(_("LOF/H"), currLnb.lofh)) + self.list.append(getConfigListEntry(_("Threshold"), currLnb.threshold)) +# self.list.append(getConfigListEntry(_("12V Output"), currLnb.output_12v)) + + if currLnb.lof.value == "unicable": + self.advancedUnicable = getConfigListEntry("Unicable "+_("Configuration Mode"), currLnb.unicable) + self.list.append(self.advancedUnicable) + if currLnb.unicable.value == "unicable_user": + self.advancedSCR = getConfigListEntry(_("Channel"), currLnb.satcruser) + self.list.append(self.advancedSCR) + self.list.append(getConfigListEntry(_("Frequency"), currLnb.satcrvcouser[currLnb.satcruser.index])) + self.list.append(getConfigListEntry(_("LOF/L"), currLnb.lofl)) + self.list.append(getConfigListEntry(_("LOF/H"), currLnb.lofh)) + self.list.append(getConfigListEntry(_("Threshold"), currLnb.threshold)) + elif currLnb.unicable.value == "unicable_matrix": + manufacturer_name = currLnb.unicableMatrixManufacturer.value + manufacturer = currLnb.unicableMatrix[manufacturer_name] + product_name = manufacturer.product.value + self.advancedManufacturer = getConfigListEntry(_("Manufacturer"), currLnb.unicableMatrixManufacturer) + self.advancedType = getConfigListEntry(_("Type"), manufacturer.product) + self.advancedSCR = getConfigListEntry(_("Channel"), manufacturer.scr[product_name]) + self.list.append(self.advancedManufacturer) + self.list.append(self.advancedType) + self.list.append(self.advancedSCR) + self.list.append(getConfigListEntry(_("Frequency"), manufacturer.vco[product_name][manufacturer.scr[product_name].index])) + elif currLnb.unicable.value == "unicable_lnb": + manufacturer_name = currLnb.unicableLnbManufacturer.value + manufacturer = currLnb.unicableLnb[manufacturer_name] + product_name = manufacturer.product.value + self.advancedManufacturer = getConfigListEntry(_("Manufacturer"), currLnb.unicableLnbManufacturer) + self.advancedType = getConfigListEntry(_("Type"), manufacturer.product) + self.advancedSCR = getConfigListEntry(_("Channel"), manufacturer.scr[product_name]) + self.list.append(self.advancedManufacturer) + self.list.append(self.advancedType) + self.list.append(self.advancedSCR) + self.list.append(getConfigListEntry(_("Frequency"), manufacturer.vco[product_name][manufacturer.scr[product_name].index])) + else: #kein Unicable + self.list.append(getConfigListEntry(_("Voltage mode"), Sat.voltage)) + self.list.append(getConfigListEntry(_("Increased voltage"), currLnb.increased_voltage)) + self.list.append(getConfigListEntry(_("Tone mode"), Sat.tonemode)) + if lnbnum < 33: self.advancedDiseqcMode = getConfigListEntry(_("DiSEqC mode"), currLnb.diseqcMode) self.list.append(self.advancedDiseqcMode) @@ -275,14 +318,12 @@ class NimSetup(Screen, ConfigListScreen): if currLnb.powerMeasurement.value: currLnb.powerMeasurement.value = False currLnb.powerMeasurement.save() - self.advancedLof = getConfigListEntry(_("LOF"), currLnb.lof) - self.list.append(self.advancedLof) - if currLnb.lof.value == "user_defined": - self.list.append(getConfigListEntry(_("LOF/L"), currLnb.lofl)) - self.list.append(getConfigListEntry(_("LOF/H"), currLnb.lofh)) - self.list.append(getConfigListEntry(_("Threshold"), currLnb.threshold)) -# self.list.append(getConfigListEntry(_("12V Output"), currLnb.output_12v)) - self.list.append(getConfigListEntry(_("Increased voltage"), currLnb.increased_voltage)) + self.advancedUsalsEntry = getConfigListEntry(_("Use usals for this sat"), Sat.usals) + self.list.append(self.advancedUsalsEntry) + if not Sat.usals.value: + self.list.append(getConfigListEntry(_("Stored position"), Sat.rotorposition)) + + def fillAdvancedList(self): self.list = [ ] @@ -383,18 +424,26 @@ class NimSelection(Screen): self.list = [None] * nimmanager.getSlotCount() self["nimlist"] = List(self.list) self.updateList() + + self.setResultClass() self["actions"] = ActionMap(["OkCancelActions"], { "ok": self.okbuttonClick , "cancel": self.close }, -2) + + def setResultClass(self): + self.resultclass = NimSetup def okbuttonClick(self): nim = self["nimlist"].getCurrent() nim = nim and nim[3] if nim is not None and not nim.empty: - self.session.openWithCallback(self.updateList, NimSetup, nim.slot) + self.session.openWithCallback(self.updateList, self.resultclass, nim.slot) + + def showNim(self, nim): + return True def updateList(self): self.list = [ ] @@ -402,42 +451,44 @@ class NimSelection(Screen): slotid = x.slot nimConfig = nimmanager.getNimConfig(x.slot) text = nimConfig.configMode.value - if x.isCompatible("DVB-S"): - if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends"]: - text = { "loopthrough": _("loopthrough to"), - "equal": _("equal to"), - "satposdepends": _("second cable of motorized LNB") } [nimConfig.configMode.value] - text += " " + _("Tuner") + " " + ["A", "B", "C", "D"][int(nimConfig.connectedTo.value)] - elif nimConfig.configMode.value == "nothing": - 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") + ": " - 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"]: - if nimConfig.diseqcB.orbital_position != 3601: - text += "," + nimmanager.getSatName(int(nimConfig.diseqcB.value)) - if nimConfig.diseqcMode.value == "diseqc_a_b_c_d": - 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": - text += _("USALS") - elif nimConfig.positionerMode.value == "manual": - text += _("manual") - else: - text = _("simple") - elif nimConfig.configMode.value == "advanced": - text = _("advanced") - elif x.isCompatible("DVB-T") or x.isCompatible("DVB-C"): - if nimConfig.configMode.value == "nothing": - text = _("nothing connected") - elif nimConfig.configMode.value == "enabled": - text = _("enabled") - - self.list.append((slotid, x.friendly_full_description, text, x)) + if self.showNim(x): + if x.isCompatible("DVB-S"): + if nimConfig.configMode.value in ["loopthrough", "equal", "satposdepends"]: + text = { "loopthrough": _("loopthrough to"), + "equal": _("equal to"), + "satposdepends": _("second cable of motorized LNB") } [nimConfig.configMode.value] + text += " " + _("Tuner") + " " + ["A", "B", "C", "D"][int(nimConfig.connectedTo.value)] + elif nimConfig.configMode.value == "nothing": + 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") + ": " + 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"]: + if nimConfig.diseqcB.orbital_position != 3601: + text += "," + nimmanager.getSatName(int(nimConfig.diseqcB.value)) + if nimConfig.diseqcMode.value == "diseqc_a_b_c_d": + 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": + text += _("USALS") + elif nimConfig.positionerMode.value == "manual": + text += _("manual") + else: + text = _("simple") + elif nimConfig.configMode.value == "advanced": + text = _("advanced") + elif x.isCompatible("DVB-T") or x.isCompatible("DVB-C"): + if nimConfig.configMode.value == "nothing": + text = _("nothing connected") + elif nimConfig.configMode.value == "enabled": + text = _("enabled") + + self.list.append((slotid, x.friendly_full_description, text, x)) + self["nimlist"].setList(self.list) self["nimlist"].updateList(self.list)
\ No newline at end of file diff --git a/lib/python/Screens/ScanSetup.py b/lib/python/Screens/ScanSetup.py index 608dcb2d..7089074a 100644 --- a/lib/python/Screens/ScanSetup.py +++ b/lib/python/Screens/ScanSetup.py @@ -17,64 +17,17 @@ def buildTerTransponder(frequency, inversion=2, bandwidth = 3, fechigh = 6, feclow = 6, modulation = 2, transmission = 2, guard = 4, hierarchy = 4): - # print "freq", frequency, "inv", inversion, "bw", bandwidth, "fech", fechigh, "fecl", feclow, "mod", modulation, "tm", transmission, "guard", guard, "hierarchy", hierarchy - - # WARNING: normally, enums are working directly. - # Don't copy this (very bad)!! Instead either fix swig (good) or - # move this into a central place. - Bw8MHz = 0 - Bw7MHz = 1 - Bw6MHz = 2 - #Bw5MHz = 3 #not implemented for e1 compatibilty - BwAuto = 3 - - f1_2 = 0 - f2_3 = 1 - f3_4 = 2 - f5_6 = 3 - f7_8 = 4 - fAuto = 5 - - TM2k = 0 - TM8k = 1 - #TM4k = 2 #not implemented for e1 compatibilty - TMAuto = 2 - - GI_1_32 = 0 - GI_1_16 = 1 - GI_1_8 = 2 - GI_1_4 = 3 - GI_Auto = 4 - - HNone = 0 - H1 = 1 - H2 = 2 - H4 = 3 - HAuto = 4 - - QPSK = 0 - QAM16 = 1 - QAM64 = 2 - Auto = 3 - - Off = 0 - On = 1 - Unknown = 2 - parm = eDVBFrontendParametersTerrestrial() - parm.frequency = frequency - - parm.inversion = [Off, On, Unknown][inversion] - parm.bandwidth = [Bw8MHz, Bw7MHz, Bw6MHz, BwAuto][bandwidth] # Bw5MHz unsupported - parm.code_rate_HP = [f1_2, f2_3, f3_4, f5_6, f7_8, fAuto][fechigh] - parm.code_rate_LP = [f1_2, f2_3, f3_4, f5_6, f7_8, fAuto][feclow] - parm.modulation = [QPSK, QAM16, QAM64, Auto][modulation] - parm.transmission_mode = [TM2k, TM8k, TMAuto][transmission] # TM4k unsupported - parm.guard_interval = [GI_1_32, GI_1_16, GI_1_8, GI_1_4, GI_Auto][guard] - parm.hierarchy = [HNone, H1, H2, H4, HAuto][hierarchy] - + parm.inversion = inversion + parm.bandwidth = bandwidth + parm.code_rate_HP = fechigh + parm.code_rate_LP = feclow + parm.modulation = modulation + parm.transmission_mode = transmission + parm.guard_interval = guard + parm.hierarchy = hierarchy return parm def getInitialTransponderList(tlist, pos): @@ -103,7 +56,7 @@ def getInitialCableTransponderList(tlist, nim): parm.symbol_rate = x[2] parm.modulation = x[3] parm.fec_inner = x[4] - parm.inversion = 2 # AUTO + parm.inversion = parm.Inversion_Unknown #print "frequency:", x[1] #print "symbol_rate:", x[2] #print "modulation:", x[3] @@ -178,10 +131,22 @@ class CableTransponderSearchSupport: if len(data): if data[0] == 'OK': print str - qam = { "QAM16" : 1, "QAM32" : 2, "QAM64" : 3, "QAM128" : 4, "QAM256" : 5 } - inv = { "INVERSION_OFF" : 0, "INVERSION_ON" : 1 } - fec = { "FEC_AUTO" : 0, "FEC_1_2" : 1, "FEC_2_3" : 2, "FEC_3_4" : 3, "FEC_5_6": 4, "FEC_7_8" : 5, "FEC_8_9" : 6, "FEC_NONE" : 15 } parm = eDVBFrontendParametersCable() + qam = { "QAM16" : parm.Modulation_QAM16, + "QAM32" : parm.Modulation_QAM32, + "QAM64" : parm.Modulation_QAM64, + "QAM128" : parm.Modulation_QAM128, + "QAM256" : parm.Modulation_QAM256 } + inv = { "INVERSION_OFF" : parm.Inversion_Off, + "INVERSION_ON" : parm.Inversion_On } + fec = { "FEC_AUTO" : parm.FEC_Auto, + "FEC_1_2" : parm.FEC_1_2, + "FEC_2_3" : parm.FEC_2_3, + "FEC_3_4" : parm.FEC_3_4, + "FEC_5_6": parm.FEC_5_6, + "FEC_7_8" : parm.FEC_7_8, + "FEC_8_9" : parm.FEC_8_9, + "FEC_NONE" : parm.FEC_None } parm.frequency = int(data[1]) parm.symbol_rate = int(data[2]) parm.fec_inner = fec[data[3]] @@ -381,15 +346,15 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.list.append(self.systemEntry) else: # downgrade to dvb-s, in case a -s2 config was active - self.scan_sat.system.value = "dvb-s" + self.scan_sat.system.value = eDVBFrontendParametersSatellite.System_DVB_S self.list.append(getConfigListEntry(_('Satellite'), self.scan_satselection[index_to_scan])) self.list.append(getConfigListEntry(_('Frequency'), self.scan_sat.frequency)) self.list.append(getConfigListEntry(_('Inversion'), self.scan_sat.inversion)) self.list.append(getConfigListEntry(_('Symbol Rate'), self.scan_sat.symbolrate)) self.list.append(getConfigListEntry(_("Polarity"), self.scan_sat.polarization)) - if self.scan_sat.system.value == "dvb-s": + if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S: self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec)) - elif self.scan_sat.system.value == "dvb-s2": + elif self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S2: self.list.append(getConfigListEntry(_("FEC"), self.scan_sat.fec_s2)) self.modulationEntry = getConfigListEntry(_('Modulation'), self.scan_sat.modulation) self.list.append(self.modulationEntry) @@ -447,7 +412,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): if cur == self.typeOfScanEntry or \ cur == self.tunerEntry or \ cur == self.systemEntry or \ - (self.modulationEntry and self.systemEntry[1].value == "dvb-s2" and cur == self.modulationEntry): + (self.modulationEntry and self.systemEntry[1].value == eDVBFrontendParametersSatellite.System_DVB_S2 and cur == self.modulationEntry): self.createSetup() def createConfig(self, frontendData): @@ -481,34 +446,65 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): #("Transmission Mode", frontendData["transmission_mode"], TYPE_TEXT), #("Guard Interval", frontendData["guard_interval"], TYPE_TEXT), #("Hierarchy Inform.", frontendData["hierarchy_information"], TYPE_TEXT), - defaultSat = { "orbpos": 192, "system": "dvb-s", "frequency": 11836, "inversion": "auto", "symbolrate": 27500, "polarization": "horizontal", "fec": "auto", "fec_s2": "9_10", "modulation": "qpsk" } - defaultCab = {"frequency": 466, "inversion": "auto", "modulation": "64qam", "fec": "auto", "symbolrate": 6900} + defaultSat = { + "orbpos": 192, + "system": eDVBFrontendParametersSatellite.System_DVB_S, + "frequency": 11836, + "inversion": eDVBFrontendParametersSatellite.Inversion_Unknown, + "symbolrate": 27500, + "polarization": eDVBFrontendParametersSatellite.Polarisation_Horizontal, + "fec": eDVBFrontendParametersSatellite.FEC_Auto, + "fec_s2": eDVBFrontendParametersSatellite.FEC_9_10, + "modulation": eDVBFrontendParametersSatellite.Modulation_QPSK } + defaultCab = { + "frequency": 466, + "inversion": eDVBFrontendParametersCable.Inversion_Unknown, + "modulation": eDVBFrontendParametersCable.Modulation_QAM64, + "fec": eDVBFrontendParametersCable.FEC_Auto, + "symbolrate": 6900 } + defaultTer = { + "frequency" : 466000, + "inversion" : eDVBFrontendParametersTerrestrial.Inversion_Unknown, + "bandwidth" : eDVBFrontendParametersTerrestrial.Bandwidth_7MHz, + "fechigh" : eDVBFrontendParametersTerrestrial.FEC_Auto, + "feclow" : eDVBFrontendParametersTerrestrial.FEC_Auto, + "modulation" : eDVBFrontendParametersTerrestrial.Modulation_Auto, + "transmission_mode" : eDVBFrontendParametersTerrestrial.TransmissionMode_Auto, + "guard_interval" : eDVBFrontendParametersTerrestrial.GuardInterval_Auto, + "hierarchy": eDVBFrontendParametersTerrestrial.Hierarchy_Auto } + if frontendData is not None: ttype = frontendData.get("tuner_type", "UNKNOWN") if ttype == "DVB-S": - defaultSat["system"] = {"DVB-S": "dvb-s", "DVB-S2": "dvb-s2"}[frontendData.get("system", "DVB-S")] - defaultSat["frequency"] = int(frontendData.get("frequency", 0) / 1000) - defaultSat["inversion"] = {"INVERSION_OFF": "off", "INVERSION_ON": "on", "INVERSION_AUTO": "auto"}[frontendData.get("inversion", "INVERSION_AUTO")] - defaultSat["symbolrate"] = int(frontendData.get("symbol_rate", 0) / 1000) - defaultSat["polarization"] = {"HORIZONTAL": "horizontal", "VERTICAL": "vertical", "CIRCULAR_LEFT": "circular_left", "CIRCULAR_RIGHT": "circular_right", "UNKNOWN": None}[frontendData.get("polarization", "HORIZONTAL")] - - if frontendData.get("system", "DVB-S") == "DVB-S2": - defaultSat["fec_s2"] = {"FEC_1_2": "1_2", "FEC_2_3": "2_3", "FEC_3_4": "3_4", "FEC_4_5": "4_5", "FEC_5_6": "5_6", "FEC_7_8": "7_8", "FEC_8_9": "8_9", "FEC_9_10": "9_10"} \ - [frontendData.get("fec_inner", "FEC_AUTO")] - defaultSat["rolloff"] = {"ROLLOFF_0_35" : "0_35", "ROLLOFF_0_25" : "0_25", "ROLLOFF_0_20" : "0_20"}[frontendData.get("rolloff", "ROLLOFF_0_35")] - defaultSat["pilot"] = {"PILOT_ON" : "on", "PILOT_OFF" : "off", "PILOT_AUTO" : "auto"}[frontendData.get("pilot", "PILOT_AUTO")] + defaultSat["system"] = frontendData.get("system", eDVBFrontendParametersSatellite.System_DVB_S) + defaultSat["frequency"] = frontendData.get("frequency", 0) / 1000 + defaultSat["inversion"] = frontendData.get("inversion", eDVBFrontendParametersSatellite.Inversion_Unknown) + defaultSat["symbolrate"] = frontendData.get("symbol_rate", 0) / 1000 + defaultSat["polarization"] = frontendData.get("polarization", eDVBFrontendParametersSatellite.Polarisation_Horizontal) + if defaultSat["system"] == eDVBFrontendParametersSatellite.System_DVB_S2: + defaultSat["fec_s2"] = frontendData.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto) + defaultSat["rolloff"] = frontendData.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35) + defaultSat["pilot"] = frontendData.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown) else: - defaultSat["fec"] = {"FEC_AUTO": "auto", "FEC_1_2": "1_2", "FEC_2_3": "2_3", "FEC_3_4": "3_4", "FEC_5_6": "5_6", "FEC_7_8": "7_8", "FEC_NONE": "none"} \ - [frontendData.get("fec_inner", "FEC_AUTO")] - - defaultSat["modulation"] = {"QPSK": "qpsk", "8PSK": "8psk"}[frontendData.get("modulation", "QPSK")] + defaultSat["fec"] = frontendData.get("fec_inner", eDVBFrontendParametersSatellite.FEC_Auto) + defaultSat["modulation"] = frontendData.get("modulation", eDVBFrontendParametersSatellite.Modulation_QPSK) defaultSat["orbpos"] = frontendData.get("orbital_position", 0) elif ttype == "DVB-C": - defaultCab["frequency"] = int(frontendData.get("frequency", 0) / 1000) - defaultCab["symbolrate"] = int(frontendData.get("symbol_rate", 0) / 1000) - defaultCab["inversion"] = {"INVERSION_OFF": "off", "INVERSION_ON": "on", "INVERSION_AUTO": "auto"}[frontendData.get("inversion", "INVERSION_AUTO")] - defaultCab["fec"] = {"FEC_AUTO": "auto", "FEC_1_2": "1_2", "FEC_2_3": "2_3", "FEC_3_4": "3_4", "FEC_5_6": "5_6", "FEC_7_8": "7_8", "FEC_8_9": "8_9", "FEC_NONE": "none"}[frontendData.get("fec_inner", "FEC_AUTO")] - defaultCab["modulation"] = {"QAM_AUTO": "auto", "QAM_16": "16qam", "QAM_32": "32qam", "QAM_64": "64qam", "QAM_128": "128qam", "QAM_256": "256qam"}[frontendData.get("modulation", "QAM_16")] + defaultCab["frequency"] = frontendData.get("frequency", 0) / 1000 + defaultCab["symbolrate"] = frontendData.get("symbol_rate", 0) / 1000 + defaultCab["inversion"] = frontendData.get("inversion", eDVBFrontendParametersCable.Inversion_Unknown) + defaultCab["fec"] = frontendData.get("fec_inner", eDVBFrontendParametersCable.FEC_Auto) + defaultCab["modulation"] = frontendData.get("modulation", eDVBFrontendParametersCable.Modulation_QAM16) + elif ttype == "DVB-T": + defaultTer["frequency"] = frontendData.get("frequency", 0) + defaultTer["inversion"] = frontendData.get("inversion", eDVBFrontendParametersTerrestrial.Inversion_Unknown) + defaultTer["bandwidth"] = frontendData.get("bandwidth", eDVBFrontendParametersTerrestrial.Bandwidth_7MHz) + defaultTer["fechigh"] = frontendData.get("code_rate_hp", eDVBFrontendParametersTerrestrial.FEC_Auto) + defaultTer["feclow"] = frontendData.get("code_rate_lp", eDVBFrontendParametersTerrestrial.FEC_Auto) + defaultTer["modulation"] = frontendData.get("constellation", eDVBFrontendParametersTerrestrial.Modulation_Auto) + defaultTer["transmission_mode"] = frontendData.get("transmission_mode", eDVBFrontendParametersTerrestrial.TransmissionMode_Auto) + defaultTer["guard_interval"] = frontendData.get("guard_interval", eDVBFrontendParametersTerrestrial.GuardInterval_Auto) + defaultTer["hierarchy"] = frontendData.get("hierarchy_information", eDVBFrontendParametersTerrestrial.Hierarchy_Auto) self.scan_sat = ConfigSubsection() self.scan_cab = ConfigSubsection() @@ -524,7 +520,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): nim_list = [] # collect all nims which are *not* set to "nothing" for n in nimmanager.nim_slots: - if n.config_mode != "nothing": + if not n.config_mode in ("loopthrough", "satposdepends", "nothing"): nim_list.append((str(n.slot), n.friendly_full_description)) self.scan_nims = ConfigSelection(choices = nim_list) @@ -538,36 +534,120 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.scan_ber.enabled = False # sat - self.scan_sat.system = ConfigSelection(default = defaultSat["system"], choices = [("dvb-s", _("DVB-S")), ("dvb-s2", _("DVB-S2"))]) + self.scan_sat.system = ConfigSelection(default = defaultSat["system"], choices = [ + (eDVBFrontendParametersSatellite.System_DVB_S, _("DVB-S")), + (eDVBFrontendParametersSatellite.System_DVB_S2, _("DVB-S2"))]) self.scan_sat.frequency = ConfigInteger(default = defaultSat["frequency"], limits = (1, 99999)) - self.scan_sat.inversion = ConfigSelection(default = defaultSat["inversion"], choices = [("off", _("off")), ("on", _("on")), ("auto", _("Auto"))]) + self.scan_sat.inversion = ConfigSelection(default = defaultSat["inversion"], choices = [ + (eDVBFrontendParametersSatellite.Inversion_Off, _("off")), + (eDVBFrontendParametersSatellite.Inversion_On, _("on")), + (eDVBFrontendParametersSatellite.Inversion_Unknown, _("Auto"))]) self.scan_sat.symbolrate = ConfigInteger(default = defaultSat["symbolrate"], limits = (1, 99999)) - self.scan_sat.polarization = ConfigSelection(default = defaultSat["polarization"], choices = [("horizontal", _("horizontal")), ("vertical", _("vertical")), ("circular_left", _("circular left")), ("circular_right", _("circular right"))]) - self.scan_sat.fec = ConfigSelection(default = defaultSat["fec"], choices = [("auto", _("Auto")), ("1_2", "1/2"), ("2_3", "2/3"), ("3_4", "3/4"), ("5_6", "5/6"), ("7_8", "7/8"), ("none", _("None"))]) - self.scan_sat.fec_s2 = ConfigSelection(default = defaultSat["fec_s2"], choices = [("1_2", "1/2"), ("2_3", "2/3"), ("3_4", "3/4"), ("3_5", "3/5"), ("4_5", "4/5"), ("5_6", "5/6"), ("7_8", "7/8"), ("8_9", "8/9"), ("9_10", "9/10")]) - self.scan_sat.modulation = ConfigSelection(default = defaultSat["modulation"], choices = [("qpsk", "QPSK"), ("8psk", "8PSK")]) - self.scan_sat.rolloff = ConfigSelection(default = defaultSat.get("rolloff", "0_35"), choices = [("0_35", "0.35"), ("0_25", "0.25"), ("0_20", "0.20")]) - self.scan_sat.pilot = ConfigSelection(default = defaultSat.get("pilot", "auto"), choices = [("off", _("off")), ("on", _("on")), ("auto", _("Auto"))]) + self.scan_sat.polarization = ConfigSelection(default = defaultSat["polarization"], choices = [ + (eDVBFrontendParametersSatellite.Polarisation_Horizontal, _("horizontal")), + (eDVBFrontendParametersSatellite.Polarisation_Vertical, _("vertical")), + (eDVBFrontendParametersSatellite.Polarisation_CircularLeft, _("circular left")), + (eDVBFrontendParametersSatellite.Polarisation_CircularRight, _("circular right"))]) + self.scan_sat.fec = ConfigSelection(default = defaultSat["fec"], choices = [ + (eDVBFrontendParametersSatellite.FEC_Auto, _("Auto")), + (eDVBFrontendParametersSatellite.FEC_1_2, "1/2"), + (eDVBFrontendParametersSatellite.FEC_2_3, "2/3"), + (eDVBFrontendParametersSatellite.FEC_3_4, "3/4"), + (eDVBFrontendParametersSatellite.FEC_5_6, "5/6"), + (eDVBFrontendParametersSatellite.FEC_7_8, "7/8"), + (eDVBFrontendParametersSatellite.FEC_None, _("None"))]) + self.scan_sat.fec_s2 = ConfigSelection(default = defaultSat["fec_s2"], choices = [ + (eDVBFrontendParametersSatellite.FEC_1_2, "1/2"), + (eDVBFrontendParametersSatellite.FEC_2_3, "2/3"), + (eDVBFrontendParametersSatellite.FEC_3_4, "3/4"), + (eDVBFrontendParametersSatellite.FEC_3_5, "3/5"), + (eDVBFrontendParametersSatellite.FEC_4_5, "4/5"), + (eDVBFrontendParametersSatellite.FEC_5_6, "5/6"), + (eDVBFrontendParametersSatellite.FEC_7_8, "7/8"), + (eDVBFrontendParametersSatellite.FEC_8_9, "8/9"), + (eDVBFrontendParametersSatellite.FEC_9_10, "9/10")]) + self.scan_sat.modulation = ConfigSelection(default = defaultSat["modulation"], choices = [ + (eDVBFrontendParametersSatellite.Modulation_QPSK, "QPSK"), + (eDVBFrontendParametersSatellite.Modulation_8PSK, "8PSK")]) + self.scan_sat.rolloff = ConfigSelection(default = defaultSat.get("rolloff", eDVBFrontendParametersSatellite.RollOff_alpha_0_35), choices = [ + (eDVBFrontendParametersSatellite.RollOff_alpha_0_35, "0.35"), + (eDVBFrontendParametersSatellite.RollOff_alpha_0_25, "0.25"), + (eDVBFrontendParametersSatellite.RollOff_alpha_0_20, "0.20")]) + self.scan_sat.pilot = ConfigSelection(default = defaultSat.get("pilot", eDVBFrontendParametersSatellite.Pilot_Unknown), choices = [ + (eDVBFrontendParametersSatellite.Pilot_Off, _("off")), + (eDVBFrontendParametersSatellite.Pilot_On, _("on")), + (eDVBFrontendParametersSatellite.Pilot_Unknown, _("Auto"))]) # cable self.scan_cab.frequency = ConfigInteger(default = defaultCab["frequency"], limits = (50, 999)) - self.scan_cab.inversion = ConfigSelection(default = defaultCab["inversion"], choices = [("off", _("off")), ("on", _("on")), ("auto", _("Auto"))]) - self.scan_cab.modulation = ConfigSelection(default = defaultCab["modulation"], choices = [("16qam", "16-QAM"), ("32qam", "32-QAM"), ("64qam", "64-QAM"), ("128qam", "128-QAM"), ("256qam", "256-QAM")]) - self.scan_cab.fec = ConfigSelection(default = defaultCab["fec"], choices = [("auto", _("Auto")), ("1_2", "1/2"), ("2_3", "2/3"), ("3_4", "3/4"), ("5_6", "5/6"), ("7_8", "7/8"), ("8_9", "8/9"), ("none", _("None"))]) + self.scan_cab.inversion = ConfigSelection(default = defaultCab["inversion"], choices = [ + (eDVBFrontendParametersCable.Inversion_Off, _("off")), + (eDVBFrontendParametersCable.Inversion_On, _("on")), + (eDVBFrontendParametersCable.Inversion_Unknown, _("Auto"))]) + self.scan_cab.modulation = ConfigSelection(default = defaultCab["modulation"], choices = [ + (eDVBFrontendParametersCable.Modulation_QAM16, "16-QAM"), + (eDVBFrontendParametersCable.Modulation_QAM32, "32-QAM"), + (eDVBFrontendParametersCable.Modulation_QAM64, "64-QAM"), + (eDVBFrontendParametersCable.Modulation_QAM128, "128-QAM"), + (eDVBFrontendParametersCable.Modulation_QAM256, "256-QAM")]) + self.scan_cab.fec = ConfigSelection(default = defaultCab["fec"], choices = [ + (eDVBFrontendParametersCable.FEC_Auto, _("Auto")), + (eDVBFrontendParametersCable.FEC_1_2, "1/2"), + (eDVBFrontendParametersCable.FEC_2_3, "2/3"), + (eDVBFrontendParametersCable.FEC_3_4, "3/4"), + (eDVBFrontendParametersCable.FEC_5_6, "5/6"), + (eDVBFrontendParametersCable.FEC_7_8, "7/8"), + (eDVBFrontendParametersCable.FEC_8_9, "8/9"), + (eDVBFrontendParametersCable.FEC_None, _("None"))]) self.scan_cab.symbolrate = ConfigInteger(default = defaultCab["symbolrate"], limits = (1, 99999)) # terrestial self.scan_ter.frequency = ConfigInteger(default = 466000, limits = (50000, 999000)) - self.scan_ter.inversion = ConfigSelection(default = "auto", choices = [("off", _("off")), ("on", _("on")), ("auto", _("Auto"))]) + self.scan_ter.inversion = ConfigSelection(default = defaultTer["inversion"], choices = [ + (eDVBFrontendParametersTerrestrial.Inversion_Off, _("off")), + (eDVBFrontendParametersTerrestrial.Inversion_On, _("on")), + (eDVBFrontendParametersTerrestrial.Inversion_Unknown, _("Auto"))]) # WORKAROUND: we can't use BW-auto - self.scan_ter.bandwidth = ConfigSelection(default = "8MHz", choices = [("8MHz", "8MHz"), ("7MHz", "7MHz"), ("6MHz", "6MHz")]) - #, ("auto", _("Auto")))) - self.scan_ter.fechigh = ConfigSelection(default = "auto", choices = [("1_2", "1/2"), ("2_3", "2/3"), ("3_4", "3/4"), ("5_6", "5/6"), ("7_8", "7/8"), ("auto", _("Auto"))]) - self.scan_ter.feclow = ConfigSelection(default = "auto", choices = [("1_2", "1/2"), ("2_3", "2/3"), ("3_4", "3/4"), ("5_6", "5/6"), ("7_8", "7/8"), ("auto", _("Auto"))]) - self.scan_ter.modulation = ConfigSelection(default = "auto", choices = [("qpsk", "QPSK"), ("qam16", "QAM16"), ("qam64", "QAM64"), ("auto", _("Auto"))]) - self.scan_ter.transmission = ConfigSelection(default = "auto", choices = [("2k", "2K"), ("8k", "8K"), ("auto", _("Auto"))]) - self.scan_ter.guard = ConfigSelection(default = "auto", choices = [("1_32", "1/32"), ("1_16", "1/16"), ("1_8", "1/8"), ("1_4", "1/4"), ("auto", _("Auto"))]) - self.scan_ter.hierarchy = ConfigSelection(default = "auto", choices = [("none", _("None")), ("1", "1"), ("2", "2"), ("4", "4"), ("auto", _("Auto"))]) + self.scan_ter.bandwidth = ConfigSelection(default = defaultTer["bandwidth"], choices = [ + (eDVBFrontendParametersTerrestrial.Bandwidth_8MHz, "8MHz"), + (eDVBFrontendParametersTerrestrial.Bandwidth_7MHz, "7MHz"), + (eDVBFrontendParametersTerrestrial.Bandwidth_6MHz, "6MHz")]) + #, (eDVBFrontendParametersTerrestrial.Bandwidth_Auto, _("Auto")))) + self.scan_ter.fechigh = ConfigSelection(default = defaultTer["fechigh"], choices = [ + (eDVBFrontendParametersTerrestrial.FEC_1_2, "1/2"), + (eDVBFrontendParametersTerrestrial.FEC_2_3, "2/3"), + (eDVBFrontendParametersTerrestrial.FEC_3_4, "3/4"), + (eDVBFrontendParametersTerrestrial.FEC_5_6, "5/6"), + (eDVBFrontendParametersTerrestrial.FEC_7_8, "7/8"), + (eDVBFrontendParametersTerrestrial.FEC_Auto, _("Auto"))]) + self.scan_ter.feclow = ConfigSelection(default = defaultTer["feclow"], choices = [ + (eDVBFrontendParametersTerrestrial.FEC_1_2, "1/2"), + (eDVBFrontendParametersTerrestrial.FEC_2_3, "2/3"), + (eDVBFrontendParametersTerrestrial.FEC_3_4, "3/4"), + (eDVBFrontendParametersTerrestrial.FEC_5_6, "5/6"), + (eDVBFrontendParametersTerrestrial.FEC_7_8, "7/8"), + (eDVBFrontendParametersTerrestrial.FEC_Auto, _("Auto"))]) + self.scan_ter.modulation = ConfigSelection(default = defaultTer["modulation"], choices = [ + (eDVBFrontendParametersTerrestrial.Modulation_QPSK, "QPSK"), + (eDVBFrontendParametersTerrestrial.Modulation_QAM16, "QAM16"), + (eDVBFrontendParametersTerrestrial.Modulation_QAM64, "QAM64"), + (eDVBFrontendParametersTerrestrial.Modulation_Auto, _("Auto"))]) + self.scan_ter.transmission = ConfigSelection(default = defaultTer["transmission_mode"], choices = [ + (eDVBFrontendParametersTerrestrial.TransmissionMode_2k, "2K"), + (eDVBFrontendParametersTerrestrial.TransmissionMode_8k, "8K"), + (eDVBFrontendParametersTerrestrial.TransmissionMode_Auto, _("Auto"))]) + self.scan_ter.guard = ConfigSelection(default = defaultTer["guard_interval"], choices = [ + (eDVBFrontendParametersTerrestrial.GuardInterval_1_32, "1/32"), + (eDVBFrontendParametersTerrestrial.GuardInterval_1_16, "1/16"), + (eDVBFrontendParametersTerrestrial.GuardInterval_1_8, "1/8"), + (eDVBFrontendParametersTerrestrial.GuardInterval_1_4, "1/4"), + (eDVBFrontendParametersTerrestrial.GuardInterval_Auto, _("Auto"))]) + self.scan_ter.hierarchy = ConfigSelection(default = defaultTer["hierarchy"], choices = [ + (eDVBFrontendParametersTerrestrial.Hierarchy_None, _("None")), + (eDVBFrontendParametersTerrestrial.Hierarchy_1, "1"), + (eDVBFrontendParametersTerrestrial.Hierarchy_2, "2"), + (eDVBFrontendParametersTerrestrial.Hierarchy_4, "4"), + (eDVBFrontendParametersTerrestrial.Hierarchy_Auto, _("Auto"))]) self.scan_scansat = {} for sat in nimmanager.satList: @@ -577,7 +657,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): self.scan_satselection = [] for slot in nimmanager.nim_slots: if slot.isCompatible("DVB-S"): - self.scan_satselection.append(getConfigSatlist(int(defaultSat["orbpos"]), self.satList[slot.slot])) + self.scan_satselection.append(getConfigSatlist(defaultSat["orbpos"], self.satList[slot.slot])) else: self.scan_satselection.append(None) @@ -594,36 +674,20 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): def updateStatus(self): print "updatestatus" - fecmap = { "auto": 0, - "1_2": 1, - "2_3": 2, - "3_4": 3, - "5_6": 4, - "7_8": 5, - "8_9": 6, - "3_5": 7, - "4_5": 8, - "9_10": 9, - "none": 15 - } - def addSatTransponder(self, tlist, frequency, symbol_rate, polarisation, fec, inversion, orbital_position, system, modulation, rolloff, pilot): - print "Add Sat: frequ: " + str(frequency) + " symbol: " + str(symbol_rate) + " pol: " + str(polarisation) + " fec: " + str(self.fecmap[fec]) + " inversion: " + str(inversion) + " modulation: " + str(modulation) + " system: " + str(system) + " rolloff" + str(rolloff) + " pilot" + str(pilot) + print "Add Sat: frequ: " + str(frequency) + " symbol: " + str(symbol_rate) + " pol: " + str(polarisation) + " fec: " + str(fec) + " inversion: " + str(inversion) + " modulation: " + str(modulation) + " system: " + str(system) + " rolloff" + str(rolloff) + " pilot" + str(pilot) print "orbpos: " + str(orbital_position) parm = eDVBFrontendParametersSatellite() - if modulation == 1: - parm.modulation = 2 # eDVBFrontendParametersSatellite.Modulation.8PSK - else: - parm.modulation = 1 # eDVBFrontendParametersSatellite.Modulation.QPSK + parm.modulation = modulation parm.system = system parm.frequency = frequency * 1000 parm.symbol_rate = symbol_rate * 1000 parm.polarisation = polarisation - parm.fec = self.fecmap[fec] + parm.fec = fec parm.inversion = inversion - parm.orbital_position = int(orbital_position) - parm.rolloff = int(rolloff) - parm.pilot = int(pilot) + parm.orbital_position = orbital_position + parm.rolloff = rolloff + parm.pilot = pilot tlist.append(parm) def addCabTransponder(self, tlist, frequency, symbol_rate, modulation, fec, inversion): @@ -632,7 +696,7 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): parm.frequency = frequency * 1000 parm.symbol_rate = symbol_rate * 1000 parm.modulation = modulation - parm.fec = self.fecmap[fec] + parm.fec = fec parm.inversion = inversion tlist.append(parm) @@ -665,21 +729,21 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): # however, the satList itself could be empty. in that case, "index" is 0 (for "None"). if len(nimsats): orbpos = nimsats[selsatidx][0] - if self.scan_sat.system.value == "dvb-s": + if self.scan_sat.system.value == eDVBFrontendParametersSatellite.System_DVB_S: fec = self.scan_sat.fec.value else: fec = self.scan_sat.fec_s2.value print "add sat transponder" self.addSatTransponder(tlist, self.scan_sat.frequency.value, self.scan_sat.symbolrate.value, - self.scan_sat.polarization.index, + self.scan_sat.polarization.value, fec, - self.scan_sat.inversion.index, + self.scan_sat.inversion.value, orbpos, - self.scan_sat.system.index, - self.scan_sat.modulation.index, - self.scan_sat.rolloff.index, - self.scan_sat.pilot.index) + self.scan_sat.system.value, + self.scan_sat.modulation.value, + self.scan_sat.rolloff.value, + self.scan_sat.pilot.value) removeAll = False elif self.scan_type.value == "single_satellite": sat = self.satList[index_to_scan][self.scan_satselection[index_to_scan].index] @@ -693,12 +757,11 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): elif nim.isCompatible("DVB-C"): if self.scan_typecable.value == "single_transponder": - fec = self.scan_cab.fec.value self.addCabTransponder(tlist, self.scan_cab.frequency.value, self.scan_cab.symbolrate.value, - self.scan_cab.modulation.index + 1, - fec, - self.scan_cab.inversion.index) + self.scan_cab.modulation.value, + self.scan_cab.fec.value, + self.scan_cab.inversion.value) removeAll = False elif self.scan_typecable.value == "complete": if config.Nims[index_to_scan].cable.scan_type.value == "provider": @@ -710,14 +773,14 @@ class ScanSetup(ConfigListScreen, Screen, CableTransponderSearchSupport): if self.scan_typeterrestrial.value == "single_transponder": self.addTerTransponder(tlist, self.scan_ter.frequency.value * 1000, - inversion = self.scan_ter.inversion.index, - bandwidth = self.scan_ter.bandwidth.index, - fechigh = self.scan_ter.fechigh.index, - feclow = self.scan_ter.feclow.index, - modulation = self.scan_ter.modulation.index, - transmission = self.scan_ter.transmission.index, - guard = self.scan_ter.guard.index, - hierarchy = self.scan_ter.hierarchy.index) + inversion = self.scan_ter.inversion.value, + bandwidth = self.scan_ter.bandwidth.value, + fechigh = self.scan_ter.fechigh.value, + feclow = self.scan_ter.feclow.value, + modulation = self.scan_ter.modulation.value, + transmission = self.scan_ter.transmission.value, + guard = self.scan_ter.guard.value, + hierarchy = self.scan_ter.hierarchy.value) removeAll = False elif self.scan_typeterrestrial.value == "complete": getInitialTerrestrialTransponderList(tlist, nimmanager.getTerrestrialDescription(index_to_scan)) diff --git a/lib/python/Screens/ServiceInfo.py b/lib/python/Screens/ServiceInfo.py index 4606f883..e07b3208 100644 --- a/lib/python/Screens/ServiceInfo.py +++ b/lib/python/Screens/ServiceInfo.py @@ -5,6 +5,7 @@ from Components.ActionMap import ActionMap from Components.Label import Label from ServiceReference import ServiceReference from enigma import eListboxPythonMultiContent, eListbox, gFont, iServiceInformation, eServiceCenter +from Tools.Transponder import ConvertToHumanReadable RT_HALIGN_LEFT = 0 @@ -131,27 +132,28 @@ class ServiceInfo(Screen): self.fillList(Labels) else: if self.transponder_info: - conv = { "type" : _("Transponder Type"), + tp_info = ConvertToHumanReadable(self.transponder_info) + conv = { "tuner_type" : _("Transponder Type"), "system" : _("System"), "modulation" : _("Modulation"), - "orbital position" : _("Orbital Position"), + "orbital_position" : _("Orbital Position"), "frequency" : _("Frequency"), - "symbolrate" : _("Symbolrate"), + "symbol_rate" : _("Symbolrate"), "bandwidth" : _("Bandwidth"), "polarization" : _("Polarization"), "inversion" : _("Inversion"), "pilot" : _("Pilot"), - "roll off" : _("Rolloff"), - "fec inner" : _("FEC"), - "code rate lp" : _("Coderate LP"), - "code rate hp" : _("Coderate HP"), + "rolloff" : _("Rolloff"), + "fec_inner" : _("FEC"), + "code_rate_lp" : _("Coderate LP"), + "code_rate_hp" : _("Coderate HP"), "constellation" : _("Constellation"), - "transmission mode": _("Transmission Mode"), - "guard interval" : _("Guard Interval"), - "hierarchy" : _("Hierarchy Information") } + "transmission_mode": _("Transmission Mode"), + "guard_interval" : _("Guard Interval"), + "hierarchy_information": _("Hierarchy Information") } Labels = [ ] - for i in self.transponder_info.keys(): - Labels.append( (conv[i], self.transponder_info[i], TYPE_TEXT) ) + for i in tp_info.keys(): + Labels.append( (conv[i], tp_info[i], TYPE_VALUE_DEC) ) self.fillList(Labels) def pids(self): @@ -180,9 +182,10 @@ class ServiceInfo(Screen): if self.type == TYPE_SERVICE_INFO: self.showFrontendData(False) - def getFEData(self, frontendData): - if frontendData and len(frontendData): - if frontendData["tuner_type"] == "DVB-S": + def getFEData(self, frontendDataOrg): + if frontendDataOrg and len(frontendDataOrg): + frontendData = ConvertToHumanReadable(frontendDataOrg) + if frontendDataOrg["tuner_type"] == "DVB-S": return (("NIM", ['A', 'B', 'C', 'D'][frontendData["tuner_number"]], TYPE_TEXT), ("Type", frontendData["system"], TYPE_TEXT), ("Modulation", frontendData["modulation"], TYPE_TEXT), @@ -194,7 +197,7 @@ class ServiceInfo(Screen): ("FEC inner", frontendData["fec_inner"], TYPE_TEXT), ("Pilot", frontendData.get("pilot", None), TYPE_TEXT), ("Rolloff", frontendData.get("rolloff", None), TYPE_TEXT)) - elif frontendData["tuner_type"] == "DVB-C": + elif frontendDataOrg["tuner_type"] == "DVB-C": return (("NIM", ['A', 'B', 'C', 'D'][frontendData["tuner_number"]], TYPE_TEXT), ("Type", frontendData["tuner_type"], TYPE_TEXT), ("Frequency", frontendData["frequency"], TYPE_VALUE_DEC), @@ -202,7 +205,7 @@ class ServiceInfo(Screen): ("Modulation", frontendData["modulation"], TYPE_TEXT), ("Inversion", frontendData["inversion"], TYPE_TEXT), ("FEC inner", frontendData["fec_inner"], TYPE_TEXT)) - elif frontendData["tuner_type"] == "DVB-T": + elif frontendDataOrg["tuner_type"] == "DVB-T": return (("NIM", ['A', 'B', 'C', 'D'][frontendData["tuner_number"]], TYPE_TEXT), ("Type", frontendData["tuner_type"], TYPE_TEXT), ("Frequency", frontendData["frequency"], TYPE_VALUE_DEC), diff --git a/lib/python/Screens/Setup.py b/lib/python/Screens/Setup.py index 3ff0b76e..1d035b8a 100644 --- a/lib/python/Screens/Setup.py +++ b/lib/python/Screens/Setup.py @@ -6,8 +6,7 @@ from Components.ConfigList import ConfigListScreen from Components.Label import Label from Components.Pixmap import Pixmap -import xml.dom.minidom -from Tools import XMLTools +import xml.etree.cElementTree # FIXME: use resolveFile! # read the setupmenu @@ -17,9 +16,16 @@ try: except: # if not found in the current path, we use the global datadir-path setupfile = file('/usr/share/enigma2/setup.xml', 'r') -setupdom = xml.dom.minidom.parseString(setupfile.read()) +setupdom = xml.etree.cElementTree.parse(setupfile) setupfile.close() +class SetupError(Exception): + def __init__(self, message): + self.message = message + + def __str__(self): + return self.message + class SetupSummary(Screen): skin = """ <screen position="6,0" size="120,64"> @@ -63,16 +69,12 @@ class Setup(ConfigListScreen, Screen): self["config"].setList(list) def refill(self, list): - xmldata = setupdom.childNodes[0] - entries = xmldata.childNodes - for x in entries: #walk through the actual nodelist - if x.nodeType != xml.dom.minidom.Element.nodeType: + xmldata = setupdom.getroot() + for x in xmldata.findall("setup"): + if x.get("key") != self.setup: continue - elif x.tagName == 'setup': - if x.getAttribute("key") != self.setup: - continue - self.addItems(list, x.childNodes); - self.setup_title = x.getAttribute("title").encode("UTF-8") + self.addItems(list, x); + self.setup_title = x.get("title", "").encode("UTF-8") def __init__(self, session, setup): Screen.__init__(self, session) @@ -118,12 +120,10 @@ class Setup(ConfigListScreen, Screen): def createSummary(self): return SetupSummary - def addItems(self, list, childNode): - for x in childNode: - if x.nodeType != xml.dom.minidom.Element.nodeType: - continue - elif x.tagName == 'item': - item_level = int(x.getAttribute("level") or "0") + def addItems(self, list, parentNode): + for x in parentNode: + if x.tag == 'item': + item_level = int(x.get("level", 0)) if not self.levelChanged in config.usage.setup_level.notifiers: config.usage.setup_level.notifiers.append(self.levelChanged) @@ -132,12 +132,12 @@ class Setup(ConfigListScreen, Screen): if item_level > config.usage.setup_level.index: continue - requires = x.getAttribute("requires") + requires = x.get("requires") if requires and not SystemInfo.get(requires, False): continue; - item_text = _(x.getAttribute("text").encode("UTF-8") or "??") - b = eval(XMLTools.mergeText(x.childNodes)); + item_text = _(x.get("text", "??").encode("UTF-8")) + b = eval(x.text or ""); if b == "": continue #add to configlist @@ -148,8 +148,8 @@ class Setup(ConfigListScreen, Screen): list.append( (item_text, item) ) def getSetupTitle(id): - xmldata = setupdom.childNodes[0].childNodes - for x in XMLTools.elementsWithTag(xmldata, "setup"): - if x.getAttribute("key") == id: - return x.getAttribute("title").encode("UTF-8") - raise "unknown setup id '%s'!" % repr(id) + xmldata = setupdom.getroot() + for x in xmldata.findall("setup"): + if x.get("key") == id: + return x.get("title", "").encode("UTF-8") + raise SetupError("unknown setup id '%s'!" % repr(id)) diff --git a/lib/python/Screens/Standby.py b/lib/python/Screens/Standby.py index 4c3a1720..d09f28af 100644 --- a/lib/python/Screens/Standby.py +++ b/lib/python/Screens/Standby.py @@ -2,6 +2,7 @@ from Screen import Screen from Components.ActionMap import ActionMap from Components.config import config from Components.AVSwitch import AVSwitch +from Components.SystemInfo import SystemInfo from enigma import eDVBVolumecontrol inStandby = None @@ -49,7 +50,10 @@ class Standby(Screen): #stop actual played dvb-service self.session.nav.stopService() #set input to vcr scart - self.avswitch.setInput("SCART") + if SystemInfo["ScartSwitch"]: + self.avswitch.setInput("SCART") + else: + self.avswitch.setInput("AUX") #set lcd brightness to standby value config.lcd.standby.apply() self.onShow.append(self.__onShow) diff --git a/lib/python/Screens/TextBox.py b/lib/python/Screens/TextBox.py new file mode 100644 index 00000000..44b8a3cf --- /dev/null +++ b/lib/python/Screens/TextBox.py @@ -0,0 +1,26 @@ +from Screens.Screen import Screen + +from Components.ActionMap import ActionMap +from Components.Sources.StaticText import StaticText +from Components.ScrollLabel import ScrollLabel + +class TextBox(Screen): + def __init__(self, session, text = ""): + Screen.__init__(self, session) + + self.text = text + self["text"] = ScrollLabel(self.text) + + self["actions"] = ActionMap(["OkCancelActions", "DirectionActions"], + { + "cancel": self.cancel, + "ok": self.ok, + "up": self["text"].pageUp, + "down": self["text"].pageDown, + }, -1) + + def ok(self): + self.close() + + def cancel(self): + self.close() diff --git a/lib/python/Screens/TimerEdit.py b/lib/python/Screens/TimerEdit.py index aae345db..bb2d3c76 100644 --- a/lib/python/Screens/TimerEdit.py +++ b/lib/python/Screens/TimerEdit.py @@ -199,9 +199,11 @@ class TimerEditList(Screen): self.updateState() def removeTimerQuestion(self): - if not self["timerlist"].getCurrent(): + cur = self["timerlist"].getCurrent() + if not cur: return - self.session.openWithCallback(self.removeTimer, MessageBox, _("Really delete this timer?")) + + self.session.openWithCallback(self.removeTimer, MessageBox, _("Do you really want to delete %s?") % (cur.name)) def removeTimer(self, result): if not result: @@ -212,18 +214,6 @@ class TimerEditList(Screen): timer = cur timer.afterEvent = AFTEREVENT.NONE self.session.nav.RecordTimer.removeEntry(timer) - if not timer.dontSave: - for timer in self.session.nav.RecordTimer.timer_list: - if timer.dontSave and timer.autoincrease: - timer.end = timer.begin + (3600 * 24 * 356 * 1) - self.session.nav.RecordTimer.timeChanged(timer) - timersanitycheck = TimerSanityCheck(self.session.nav.RecordTimer.timer_list,timer) - if not timersanitycheck.check(): - tsc_list = timersanitycheck.getSimulTimerList() - if len(tsc_list) > 1: - timer.end = tsc_list[1].begin - 30 - self.session.nav.RecordTimer.timeChanged(timer) - self.refill() self.updateState() @@ -259,6 +249,7 @@ class TimerEditList(Screen): def addTimer(self, timer): self.session.openWithCallback(self.finishedAdd, TimerEntry, timer) + def finishedEdit(self, answer): print "finished edit" @@ -267,19 +258,25 @@ class TimerEditList(Screen): print "Edited timer" entry = answer[1] timersanitycheck = TimerSanityCheck(self.session.nav.RecordTimer.timer_list, entry) + success = False if not timersanitycheck.check(): simulTimerList = timersanitycheck.getSimulTimerList() - if (len(simulTimerList) == 2) and (simulTimerList[1].dontSave) and (simulTimerList[1].autoincrease): - simulTimerList[1].end = entry.begin - 30 - self.session.nav.RecordTimer.timeChanged(simulTimerList[1]) - self.session.nav.RecordTimer.timeChanged(entry) - else: - print "Sanity check failed" - self.session.openWithCallback(self.finishedEdit, TimerSanityConflict, timersanitycheck.getSimulTimerList()) + if simulTimerList is not None: + for x in simulTimerList: + if x.setAutoincreaseEnd(entry): + self.session.nav.RecordTimer.timeChanged(x) + if not timersanitycheck.check(): + simulTimerList = timersanitycheck.getSimulTimerList() + if simulTimerList is not None: + self.session.openWithCallback(self.finishedEdit, TimerSanityConflict, timersanitycheck.getSimulTimerList()) + else: + success = True else: + succsess = True + if success: print "Sanity check passed" - if not timersanitycheck.doubleCheck(): - self.session.nav.RecordTimer.timeChanged(entry) + self.session.nav.RecordTimer.timeChanged(entry) + self.fillTimerList() self.updateState() else: @@ -291,11 +288,11 @@ class TimerEditList(Screen): entry = answer[1] simulTimerList = self.session.nav.RecordTimer.record(entry) if simulTimerList is not None: - if (len(simulTimerList) == 2) and (simulTimerList[1].dontSave) and (simulTimerList[1].autoincrease): - simulTimerList[1].end = entry.begin - 30 - self.session.nav.RecordTimer.timeChanged(simulTimerList[1]) - self.session.nav.RecordTimer.record(entry) - else: + for x in simulTimerList: + if x.setAutoincreaseEnd(entry): + self.session.nav.RecordTimer.timeChanged(x) + simulTimerList = self.session.nav.RecordTimer.record(entry) + if simulTimerList is not None: self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList) self.fillTimerList() self.updateState() @@ -333,6 +330,8 @@ class TimerSanityConflict(Screen): self.list.append((_("Conflicting timer") + " " + str(count), x)) self.list2.append((timer[count], False)) count += 1 + if count == 1: + self.list.append((_("Channel not in services list"))) self["list"] = MenuList(self.list) self["timer2"] = TimerList(self.list2) @@ -409,7 +408,7 @@ class TimerSanityConflict(Screen): self["actions"].actions.update({"green":self.toggleTimer1}) self["key_green"].setText(_("Enable")) self.key_green_choice = self.ENABLE - elif self.timer[0].isRunning() and not timer[0].repeated and self.key_green_choice != self.EMPTY: + elif self.timer[0].isRunning() and not self.timer[0].repeated and self.key_green_choice != self.EMPTY: self.removeAction("green") self["key_green"].setText(" ") self.key_green_choice = self.EMPTY @@ -429,7 +428,7 @@ class TimerSanityConflict(Screen): self["actions"].actions.update({"blue":self.toggleTimer2}) self["key_blue"].setText(_("Enable")) self.key_blue_choice = self.ENABLE - elif self.timer[x].isRunning() and not timer[x].repeated and self.key_blue_choice != self.EMPTY: + elif self.timer[x].isRunning() and not self.timer[x].repeated and 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 1774061d..0544eff1 100644 --- a/lib/python/Screens/TimerEntry.py +++ b/lib/python/Screens/TimerEntry.py @@ -32,11 +32,15 @@ class TimerEntry(Screen, ConfigListScreen): self.createConfig() - self["actions"] = NumberActionMap(["SetupActions"], + self["actions"] = NumberActionMap(["SetupActions", "GlobalActions", "PiPSetupActions"], { "ok": self.keySelect, "save": self.keyGo, "cancel": self.keyCancel, + "volumeUp": self.incrementStart, + "volumeDown": self.decrementStart, + "size+": self.incrementEnd, + "size-": self.decrementEnd }, -2) self.list = [] @@ -46,7 +50,12 @@ class TimerEntry(Screen, ConfigListScreen): def createConfig(self): justplay = self.timer.justplay - afterevent = { AFTEREVENT.NONE: "nothing", AFTEREVENT.DEEPSTANDBY: "deepstandby", AFTEREVENT.STANDBY: "standby"}[self.timer.afterEvent] + afterevent = { + AFTEREVENT.NONE: "nothing", + AFTEREVENT.DEEPSTANDBY: "deepstandby", + AFTEREVENT.STANDBY: "standby", + AFTEREVENT.AUTO: "auto" + }[self.timer.afterEvent] weekday_table = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] @@ -84,7 +93,7 @@ class TimerEntry(Screen, ConfigListScreen): day[weekday] = 1 self.timerentry_justplay = ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[justplay]) - self.timerentry_afterevent = ConfigSelection(choices = [("nothing", _("do nothing")), ("standby", _("go to standby")), ("deepstandby", _("go to deep standby"))], default = afterevent) + self.timerentry_afterevent = ConfigSelection(choices = [("nothing", _("do nothing")), ("standby", _("go to standby")), ("deepstandby", _("go to deep standby")), ("auto", _("auto"))], default = afterevent) 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) @@ -155,9 +164,14 @@ class TimerEntry(Screen, ConfigListScreen): self.entryDate = getConfigListEntry(_("Date"), self.timerentry_date) if self.timerentry_type.value == "once": self.list.append(self.entryDate) - self.list.append(getConfigListEntry(_("StartTime"), self.timerentry_starttime)) + + self.entryStartTime = getConfigListEntry(_("StartTime"), self.timerentry_starttime) + self.list.append(self.entryStartTime) if self.timerentry_justplay.value != "zap": - self.list.append(getConfigListEntry(_("EndTime"), self.timerentry_endtime)) + self.entryEndTime = getConfigListEntry(_("EndTime"), self.timerentry_endtime) + self.list.append(self.entryEndTime) + else: + self.entryEndTime = None self.channelEntry = getConfigListEntry(_("Channel"), self.timerentry_service) self.list.append(self.channelEntry) @@ -250,7 +264,12 @@ class TimerEntry(Screen, ConfigListScreen): self.timer.description = self.timerentry_description.value self.timer.justplay = self.timerentry_justplay.value == "zap" self.timer.resetRepeated() - self.timer.afterEvent = {"nothing": AFTEREVENT.NONE, "deepstandby": AFTEREVENT.DEEPSTANDBY, "standby": AFTEREVENT.STANDBY}[self.timerentry_afterevent.value] + self.timer.afterEvent = { + "nothing": AFTEREVENT.NONE, + "deepstandby": AFTEREVENT.DEEPSTANDBY, + "standby": AFTEREVENT.STANDBY, + "auto": AFTEREVENT.AUTO + }[self.timerentry_afterevent.value] self.timer.service_ref = self.timerentry_service_ref self.timer.tags = self.timerentry_tags @@ -309,6 +328,24 @@ class TimerEntry(Screen, ConfigListScreen): self.saveTimer() self.close((True, self.timer)) + def incrementStart(self): + self.timerentry_starttime.increment() + self["config"].invalidate(self.entryStartTime) + + def decrementStart(self): + self.timerentry_starttime.decrement() + self["config"].invalidate(self.entryStartTime) + + def incrementEnd(self): + if self.entryEndTime is not None: + self.timerentry_endtime.increment() + self["config"].invalidate(self.entryEndTime) + + def decrementEnd(self): + if self.entryEndTime is not None: + self.timerentry_endtime.decrement() + self["config"].invalidate(self.entryEndTime) + def subserviceSelected(self, service): if not service is None: self.timer.service_ref = ServiceReference(service[1]) diff --git a/lib/python/Screens/Wizard.py b/lib/python/Screens/Wizard.py index 23d6253a..feba8ac2 100644..100755 --- a/lib/python/Screens/Wizard.py +++ b/lib/python/Screens/Wizard.py @@ -3,7 +3,8 @@ from Screen import Screen import string from Screens.HelpMenu import HelpableScreen -from Components.config import config, KEY_LEFT, KEY_RIGHT, KEY_DELETE, KEY_BACKSPACE +from Components.config import config, KEY_LEFT, KEY_RIGHT, KEY_HOME, KEY_END, KEY_0, KEY_DELETE, KEY_BACKSPACE, KEY_OK, KEY_TOGGLEOW, KEY_ASCII, KEY_TIMEOUT, KEY_NUMBERS + from Components.Label import Label from Components.Slider import Slider from Components.ActionMap import NumberActionMap @@ -215,8 +216,9 @@ class Wizard(Screen): self.disableKeys = False - self["actions"] = NumberActionMap(["WizardActions", "NumberActions", "ColorActions", "SetupActions"], + self["actions"] = NumberActionMap(["WizardActions", "NumberActions", "ColorActions", "SetupActions", "InputAsciiActions"], { + "gotAsciiCode": self.keyGotAscii, "ok": self.ok, "back": self.back, "left": self.left, @@ -368,6 +370,10 @@ class Wizard(Screen): def keyNumberGlobal(self, number): if (self.wizard[self.currStep]["config"]["screen"] != None): self.configInstance.keyNumberGlobal(number) + + def keyGotAscii(self): + if (self.wizard[self.currStep]["config"]["screen"] != None): + self["config"].handleKey(KEY_ASCII) def left(self): self.resetCounter() diff --git a/lib/python/Tools/Directories.py b/lib/python/Tools/Directories.py index 2b60924c..0d238b30 100644 --- a/lib/python/Tools/Directories.py +++ b/lib/python/Tools/Directories.py @@ -126,6 +126,9 @@ def resolveFilename(scope, base = "", path_prefix = None): def pathExists(path): return os_path.exists(path) +def isMount(path): + return os_path.ismount(path) + def createDir(path, makeParents = False): try: if makeParents: diff --git a/lib/python/Tools/LoadPixmap.py b/lib/python/Tools/LoadPixmap.py index 53e04e54..fff414ad 100644 --- a/lib/python/Tools/LoadPixmap.py +++ b/lib/python/Tools/LoadPixmap.py @@ -14,7 +14,7 @@ def LoadPixmap(path, desktop = None, cached = False): alpha = loadPNG(path + "a.png") ptr = loadJPG(path + "rgb.jpg", alpha) else: - raise "neither .png nor .jpg, please fix file extension" + raise Exception("neither .png nor .jpg, please fix file extension") if ptr and desktop: desktop.makeCompatiblePixmap(ptr) diff --git a/lib/python/Tools/Makefile.am b/lib/python/Tools/Makefile.am index 609f3bab..5617cb66 100644 --- a/lib/python/Tools/Makefile.am +++ b/lib/python/Tools/Makefile.am @@ -4,4 +4,4 @@ install_PYTHON = \ FuzzyDate.py XMLTools.py Directories.py NumericalTextInput.py \ KeyBindings.py BoundFunction.py ISO639.py Notifications.py __init__.py \ RedirectOutput.py DreamboxHardware.py Import.py Event.py CList.py \ - LoadPixmap.py Profile.py HardwareInfo.py + LoadPixmap.py Profile.py HardwareInfo.py Transponder.py diff --git a/lib/python/Tools/NumericalTextInput.py b/lib/python/Tools/NumericalTextInput.py index 5954c9c3..c5576405 100644 --- a/lib/python/Tools/NumericalTextInput.py +++ b/lib/python/Tools/NumericalTextInput.py @@ -1,44 +1,65 @@ -# -*- coding: iso-8859-1 -*- +# -*- coding: utf-8 -*- from enigma import eTimer from Components.Language import language class NumericalTextInput: - def __init__(self, nextFunc=None, handleTimeout = True): + def __init__(self, nextFunc=None, handleTimeout = True, search = False): self.mapping = [] self.lang = language.getLanguage() self.useableChars=None self.nextFunction=nextFunc - + + if handleTimeout: + self.timer = eTimer() + self.timer.callback.append(self.timeout) + else: + self.timer = None + self.lastKey = -1 + self.pos = -1 + + if search: + self.mapping.append (u"%_0") # 0 + self.mapping.append (u" 1") # 1 + self.mapping.append (u"abc2") # 2 + self.mapping.append (u"def3") # 3 + self.mapping.append (u"ghi4") # 4 + self.mapping.append (u"jkl5") # 5 + self.mapping.append (u"mno6") # 6 + self.mapping.append (u"pqrs7") # 7 + self.mapping.append (u"tuv8") # 8 + self.mapping.append (u"wxyz9") # 9 + return + if self.lang == 'de_DE': self.mapping.append (u".,?'+\"0-()@/:_$!") # 0 self.mapping.append (u" 1") # 1 - self.mapping.append (u"abc2ABC") # 2 + self.mapping.append (u"aäbc2AÄBC") # 2 self.mapping.append (u"def3DEF") # 3 self.mapping.append (u"ghi4GHI") # 4 self.mapping.append (u"jkl5JKL") # 5 - self.mapping.append (u"mno6MNO") # 6 - self.mapping.append (u"pqrs7PQRS") # 7 - self.mapping.append (u"tuv8TUV") # 8 + self.mapping.append (u"mnoö6MNOÖ") # 6 + self.mapping.append (u"pqrsß7PQRSß") # 7 + self.mapping.append (u"tuüv8TUÜV") # 8 self.mapping.append (u"wxyz9WXYZ") # 9 elif self.lang == 'es_ES': self.mapping.append (u".,?'+\"0-()@/:_$!") # 0 self.mapping.append (u" 1") # 1 - self.mapping.append (u"abc2ABC") # 2 - self.mapping.append (u"def3DEF") # 3 - self.mapping.append (u"ghi4GHI") # 4 + self.mapping.append (u"abcáà2ABCÁÀ") # 2 + self.mapping.append (u"deéèf3DEFÉÈ") # 3 + self.mapping.append (u"ghiíì4GHIÍÌ") # 4 self.mapping.append (u"jkl5JKL") # 5 - self.mapping.append (u"mno6MNO") # 6 + self.mapping.append (u"mnñoóò6MNÑOÓÒ") # 6 self.mapping.append (u"pqrs7PQRS") # 7 - self.mapping.append (u"tuv8TUV") # 8 + self.mapping.append (u"tuvúù8TUVÚÙ") # 8 self.mapping.append (u"wxyz9WXYZ") # 9 if self.lang in ['sv_SE', 'fi_FI']: self.mapping.append (u".,?'+\"0-()@/:_$!") # 0 self.mapping.append (u" 1") # 1 - self.mapping.append (u"abc2ABC") # 2 - self.mapping.append (u"def3DEF") # 3 + self.mapping.append (u"abcåä2ABCÅÄ") # 2 + self.mapping.append (u"defé3DEFÉ") # 3 self.mapping.append (u"ghi4GHI") # 4 self.mapping.append (u"jkl5JKL") # 5 - self.mapping.append (u"mno6MNO") # 6 + self.mapping.append (u"mnoö6MNOÖ") # 6 self.mapping.append (u"pqrs7PQRS") # 7 self.mapping.append (u"tuv8TUV") # 8 self.mapping.append (u"wxyz9WXYZ") # 9 @@ -54,14 +75,6 @@ class NumericalTextInput: self.mapping.append (u"tuv8TUV") # 8 self.mapping.append (u"wxyz9WXYZ") # 9 - if handleTimeout: - self.timer = eTimer() - self.timer.callback.append(self.timeout) - else: - self.timer = None - self.lastKey = -1 - self.pos = -1 - def setUseableChars(self, useable): self.useableChars = useable diff --git a/lib/python/Tools/Transponder.py b/lib/python/Tools/Transponder.py new file mode 100644 index 00000000..f37603c5 --- /dev/null +++ b/lib/python/Tools/Transponder.py @@ -0,0 +1,117 @@ +from enigma import eDVBFrontendParametersSatellite, eDVBFrontendParametersCable, eDVBFrontendParametersTerrestrial + +def ConvertToHumanReadable(tp): + ret = { } + type = tp.get("tuner_type", "None") + if type == "DVB-S": + ret["tuner_type"] = _("Satellite") + ret["inversion"] = { + eDVBFrontendParametersSatellite.Inversion_Unknown : _("Auto"), + eDVBFrontendParametersSatellite.Inversion_On : _("On"), + eDVBFrontendParametersSatellite.Inversion_Off : _("Off")}[tp["inversion"]] + ret["fec_inner"] = { + eDVBFrontendParametersSatellite.FEC_None : _("None"), + eDVBFrontendParametersSatellite.FEC_Auto : _("Auto"), + eDVBFrontendParametersSatellite.FEC_1_2 : "1/2", + eDVBFrontendParametersSatellite.FEC_2_3 : "2/3", + eDVBFrontendParametersSatellite.FEC_3_4 : "3/4", + eDVBFrontendParametersSatellite.FEC_5_6 : "5/6", + eDVBFrontendParametersSatellite.FEC_7_8 : "7/8", + eDVBFrontendParametersSatellite.FEC_3_5 : "3/5", + eDVBFrontendParametersSatellite.FEC_4_5 : "4/5", + eDVBFrontendParametersSatellite.FEC_8_9 : "8/9", + eDVBFrontendParametersSatellite.FEC_9_10 : "9/10"}[tp["fec_inner"]] + ret["modulation"] = { + eDVBFrontendParametersSatellite.Modulation_Auto : _("Auto"), + eDVBFrontendParametersSatellite.Modulation_QPSK : "QPSK", + eDVBFrontendParametersSatellite.Modulation_QAM16 : "QAM16", + eDVBFrontendParametersSatellite.Modulation_8PSK : "8PSK"}[tp["modulation"]] + ret["polarization"] = { + eDVBFrontendParametersSatellite.Polarisation_Horizontal : _("Horizontal"), + eDVBFrontendParametersSatellite.Polarisation_Vertical : _("Vertical"), + eDVBFrontendParametersSatellite.Polarisation_CircularLeft : _("Circular left"), + eDVBFrontendParametersSatellite.Polarisation_CircularRight : _("Circular right")}[tp["polarization"]] + ret["system"] = { + eDVBFrontendParametersSatellite.System_DVB_S : "DVB-S", + eDVBFrontendParametersSatellite.System_DVB_S2 : "DVB-S2"}[tp["system"]] + if ret["system"] == "DVB-S2": + ret["rolloff"] = { + eDVBFrontendParametersSatellite.RollOff_alpha_0_35 : "0.35", + eDVBFrontendParametersSatellite.RollOff_alpha_0_25 : "0.25", + eDVBFrontendParametersSatellite.RollOff_alpha_0_20 : "0.20"}[tp["rolloff"]] + ret["pilot"] = { + eDVBFrontendParametersSatellite.Pilot_Unknown : _("Auto"), + eDVBFrontendParametersSatellite.Pilot_On : _("On"), + eDVBFrontendParametersSatellite.Pilot_Off : _("Off")}[tp["pilot"]] + elif type == "DVB-C": + ret["tuner_type"] = _("Cable") + ret["modulation"] = { + eDVBFrontendParametersCable.Modulation_Auto: _("Auto"), + eDVBFrontendParametersCable.Modulation_QAM16 : "QAM16", + eDVBFrontendParametersCable.Modulation_QAM32 : "QAM32", + eDVBFrontendParametersCable.Modulation_QAM64 : "QAM64", + eDVBFrontendParametersCable.Modulation_QAM128 : "QAM128", + eDVBFrontendParametersCable.Modulation_QAM256 : "QAM256"}[tp["modulation"]] + ret["inversion"] = { + eDVBFrontendParametersCable.Inversion_Unknown : _("Auto"), + eDVBFrontendParametersCable.Inversion_On : _("On"), + eDVBFrontendParametersCable.Inversion_Off : _("Off")}[tp["inversion"]] + ret["fec_inner"] = { + eDVBFrontendParametersCable.FEC_None : _("None"), + eDVBFrontendParametersCable.FEC_Auto : _("Auto"), + eDVBFrontendParametersCable.FEC_1_2 : "1/2", + eDVBFrontendParametersCable.FEC_2_3 : "2/3", + eDVBFrontendParametersCable.FEC_3_4 : "3/4", + eDVBFrontendParametersCable.FEC_5_6 : "5/6", + eDVBFrontendParametersCable.FEC_7_8 : "7/8", + eDVBFrontendParametersCable.FEC_8_9 : "8/9"}[tp["fec_inner"]] + elif type == "DVB-T": + ret["tuner_type"] = _("Terrestrial") + ret["bandwidth"] = { + eDVBFrontendParametersTerrestrial.Bandwidth_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.Bandwidth_8MHz : "8 MHz", + eDVBFrontendParametersTerrestrial.Bandwidth_7MHz : "7 MHz", + eDVBFrontendParametersTerrestrial.Bandwidth_6MHz : "6 MHz"}[tp["bandwidth"]] + ret["code_rate_lp"] = { + eDVBFrontendParametersTerrestrial.FEC_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.FEC_1_2 : "1/2", + eDVBFrontendParametersTerrestrial.FEC_2_3 : "2/3", + eDVBFrontendParametersTerrestrial.FEC_3_4 : "3/4", + eDVBFrontendParametersTerrestrial.FEC_5_6 : "5/6", + eDVBFrontendParametersTerrestrial.FEC_7_8 : "7/8"}[tp["code_rate_lp"]] + ret["code_rate_hp"] = { + eDVBFrontendParametersTerrestrial.FEC_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.FEC_1_2 : "1/2", + eDVBFrontendParametersTerrestrial.FEC_2_3 : "2/3", + eDVBFrontendParametersTerrestrial.FEC_3_4 : "3/4", + eDVBFrontendParametersTerrestrial.FEC_5_6 : "5/6", + eDVBFrontendParametersTerrestrial.FEC_7_8 : "7/8"}[tp["code_rate_hp"]] + ret["constellation"] = { + eDVBFrontendParametersTerrestrial.Modulation_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.Modulation_QPSK : "QPSK", + eDVBFrontendParametersTerrestrial.Modulation_QAM16 : "QAM16", + eDVBFrontendParametersTerrestrial.Modulation_QAM64 : "QAM64"}[tp["constellation"]] + ret["transmission_mode"] = { + eDVBFrontendParametersTerrestrial.TransmissionMode_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.TransmissionMode_2k : "2k", + eDVBFrontendParametersTerrestrial.TransmissionMode_8k : "8k"}[tp["transmission_mode"]] + ret["guard_interval"] = { + eDVBFrontendParametersTerrestrial.GuardInterval_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.GuardInterval_1_32 : "1/32", + eDVBFrontendParametersTerrestrial.GuardInterval_1_16 : "1/16", + eDVBFrontendParametersTerrestrial.GuardInterval_1_8 : "1/8", + eDVBFrontendParametersTerrestrial.GuardInterval_1_4 : "1/4"}[tp["guard_interval"]] + ret["hierarchy_information"] = { + eDVBFrontendParametersTerrestrial.Hierarchy_Auto : _("Auto"), + eDVBFrontendParametersTerrestrial.Hierarchy_None : _("None"), + eDVBFrontendParametersTerrestrial.Hierarchy_1 : "1", + eDVBFrontendParametersTerrestrial.Hierarchy_2 : "2", + eDVBFrontendParametersTerrestrial.Hierarchy_4 : "4"}[tp["hierarchy_information"]] + ret["inversion"] = { + eDVBFrontendParametersTerrestrial.Inversion_Unknown : _("Auto"), + eDVBFrontendParametersTerrestrial.Inversion_On : _("On"), + eDVBFrontendParametersTerrestrial.Inversion_Off : _("Off")}[tp["inversion"]] + for x in tp.keys(): + if not ret.has_key(x): + ret[x] = tp[x] + return ret diff --git a/lib/python/enigma_python.i b/lib/python/enigma_python.i index 7de05d2b..bdf1b144 100644 --- a/lib/python/enigma_python.i +++ b/lib/python/enigma_python.i @@ -141,6 +141,7 @@ typedef long time_t; %include <lib/service/service.h> // TODO: embed these... +%immutable ePicLoad::PictureData; %immutable eButton::selected; %immutable eInput::changed; %immutable eComponentScan::statusChanged; @@ -287,7 +288,7 @@ PyObject *getBestPlayableServiceReference(const eServiceReference &bouquet_ref, PyObject *getBestPlayableServiceReference(const eServiceReference &bouquet_ref, const eServiceReference &ignore, bool simulate=false) { eStaticServiceDVBBouquetInformation info; - if (info.isPlayable(bouquet_ref, ignore)) + if (info.isPlayable(bouquet_ref, ignore, simulate)) return New_eServiceReference(info.getPlayableService()); Py_INCREF(Py_None); return Py_None; diff --git a/lib/python/python.cpp b/lib/python/python.cpp index 50b66103..c5faeed4 100644 --- a/lib/python/python.cpp +++ b/lib/python/python.cpp @@ -5,7 +5,7 @@ extern "C" void init_enigma(); extern "C" void eBaseInit(void); extern "C" void eConsoleInit(void); -extern void bsodFatal(); +extern void bsodFatal(const char *component); #define SKIP_PART2 #include <lib/python/python.h> @@ -44,7 +44,7 @@ ePyObject::operator PyObject*() if (m_file) eDebug("last modified in file %s line %d from %d to %d", m_file, m_line, m_from, m_to); - bsodFatal(); + bsodFatal("enigma2, refcnt"); } return 0; } @@ -57,7 +57,7 @@ void ePyObject::incref(const char *file, int line) if (m_file) eDebug("last modified in file %s line %d from %d to %d", m_file, m_line, m_from, m_to); - bsodFatal(); + bsodFatal("enigma2, refcnt"); } if (m_erased || m_ob->ob_refcnt <= 0) { @@ -66,7 +66,7 @@ void ePyObject::incref(const char *file, int line) if (m_file) eDebug("last modified in file %s line %d from %d to %d", m_file, m_line, m_from, m_to); - bsodFatal(); + bsodFatal("enigma2, refcnt"); } if (m_ob->ob_refcnt == 0x7FFFFFFF) { @@ -75,7 +75,7 @@ void ePyObject::incref(const char *file, int line) if (m_file) eDebug("last modified in file %s line %d from %d to %d", m_file, m_line, m_from, m_to); - bsodFatal(); + bsodFatal("enigma2, refcnt"); } m_file = file; m_line = line; @@ -92,7 +92,7 @@ void ePyObject::decref(const char *file, int line) if (m_file) eDebug("last modified in file %s line %d from %d to %d", m_file, m_line, m_from, m_to); - bsodFatal(); + bsodFatal("enigma2, refcnt"); } if (m_erased || m_ob->ob_refcnt <= 0) { @@ -101,7 +101,7 @@ void ePyObject::decref(const char *file, int line) if (m_file) eDebug("last modified in file %s line %d from %d to %d", m_file, m_line, m_from, m_to); - bsodFatal(); + bsodFatal("enigma2, refcnt"); } m_file = file; m_line = line; @@ -207,7 +207,7 @@ int ePython::call(ePyObject pFunc, ePyObject pArgs) eDebug("(PyObject_CallObject(%s,%s) failed)", PyString_AS_STRING(FuncStr), PyString_AS_STRING(ArgStr)); Py_DECREF(FuncStr); Py_DECREF(ArgStr); - bsodFatal(); + bsodFatal(0); } } return res; diff --git a/lib/python/python.h b/lib/python/python.h index f56d49bb..52ec6c1e 100644 --- a/lib/python/python.h +++ b/lib/python/python.h @@ -24,6 +24,7 @@ public: #ifdef PYTHON_REFCOUNT_DEBUG inline ePyObject(PyObject *ob, const char *file, int line); #endif + inline ePyObject(PyVarObject *ob); inline ePyObject(PyDictObject *ob); inline ePyObject(PyTupleObject *ob); inline ePyObject(PyListObject *ob); @@ -32,11 +33,13 @@ public: operator bool() { return !!m_ob; } ePyObject &operator=(const ePyObject &); ePyObject &operator=(PyObject *); + ePyObject &operator=(PyVarObject *ob) { return operator=((PyObject*)ob); } ePyObject &operator=(PyDictObject *ob) { return operator=((PyObject*)ob); } ePyObject &operator=(PyTupleObject *ob) { return operator=((PyObject*)ob); } ePyObject &operator=(PyListObject *ob) { return operator=((PyObject*)ob); } ePyObject &operator=(PyStringObject *ob) { return operator=((PyObject*)ob); } operator PyObject*(); + operator PyVarObject*() { return (PyVarObject*)operator PyVarObject*(); } operator PyTupleObject*() { return (PyTupleObject*)operator PyObject*(); } operator PyListObject*() { return (PyListObject*)operator PyObject*(); } operator PyStringObject*() { return (PyStringObject*)operator PyObject*(); } @@ -84,6 +87,14 @@ inline ePyObject::ePyObject(PyObject *ob, const char* file, int line) } #endif +inline ePyObject::ePyObject(PyVarObject *ob) + :m_ob((PyObject*)ob) +#ifdef PYTHON_REFCOUNT_DEBUG + ,m_file(0), m_line(0), m_from(0), m_to(0), m_erased(false) +#endif +{ +} + inline ePyObject::ePyObject(PyDictObject *ob) :m_ob((PyObject*)ob) #ifdef PYTHON_REFCOUNT_DEBUG |
