diff options
| author | Felix Domke <tmbinc@elitedvb.net> | 2009-02-11 12:52:48 +0100 |
|---|---|---|
| committer | Felix Domke <tmbinc@elitedvb.net> | 2009-02-11 12:52:48 +0100 |
| commit | bbfcb7ea1f040d030277e2b6f2efa9ea0967bf2b (patch) | |
| tree | c5945c791698c14723e989449e6b4bfcc275c05d /lib/python/Plugins | |
| parent | 4f7990ff2a55874b9eb65e3c9cd47dacb9f76deb (diff) | |
| parent | 5e6f814d005a01caa437a532e61f4b338617ff67 (diff) | |
| download | enigma2-bbfcb7ea1f040d030277e2b6f2efa9ea0967bf2b.tar.gz enigma2-bbfcb7ea1f040d030277e2b6f2efa9ea0967bf2b.zip | |
Merge branch 'master' of /home/tmbinc/enigma2-git into tmbinc/FixTimingBugs
Conflicts:
lib/dvb/decoder.cpp
Diffstat (limited to 'lib/python/Plugins')
38 files changed, 2418 insertions, 1135 deletions
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() |
