blink frontpanel led when record is running
[enigma2.git] / skin.py
diff --git a/skin.py b/skin.py
index cb433269a584459d0c8d1a5ad719ca32211bd9ef..21ec62ae4cefbc733315480b117e3e64b7b96321 100644 (file)
--- a/skin.py
+++ b/skin.py
@@ -1,15 +1,19 @@
+from Tools.Profile import profile, profile_final
+
+profile("LOAD:minidom")
 import xml.dom.minidom
-from xml.dom import EMPTY_NAMESPACE
 from os import path
 
+profile("LOAD:enigma_skin")
 from enigma import eSize, ePoint, gFont, eWindow, eLabel, ePixmap, eWindowStyleManager, \
-       loadPNG, addFont, gRGB, eWindowStyleSkinned
+       addFont, gRGB, eWindowStyleSkinned
 
 from Components.config import ConfigSubsection, ConfigText, config
-from Components.Element import Element
 from Components.Converter.Converter import Converter
+from Components.Sources.Source import Source, ObsoleteSource
 from Tools.Directories import resolveFilename, SCOPE_SKIN, SCOPE_SKIN_IMAGE, SCOPE_FONTS
 from Tools.Import import my_import
+from Tools.LoadPixmap import LoadPixmap
 
 from Tools.XMLTools import elementsWithTag, mergeText
 
@@ -52,13 +56,18 @@ def loadSkin(name):
 config.skin = ConfigSubsection()
 config.skin.primary_skin = ConfigText(default = "skin.xml")
 
+profile("LoadSkin")
 try:
        loadSkin(config.skin.primary_skin.value)
 except (SkinError, IOError, AssertionError), err:
        print "SKIN ERROR:", err
        print "defaulting to standard skin..."
+       config.skin.primary_skin.value = 'skin.xml'
        loadSkin('skin.xml')
+
+profile("LoadSkinDefault")
 loadSkin('skin_default.xml')
+profile("LoadSkinDefaultDone")
 
 def parsePosition(str):
        x, y = str.split(',')
@@ -77,7 +86,7 @@ def parseColor(str):
                try:
                        return colorNames[str]
                except:
-                       raise ("color '%s' must be #aarrggbb or valid named color" % (str))
+                       raise SkinError("color '%s' must be #aarrggbb or valid named color" % (str))
        return gRGB(int(str[1:], 0x10))
 
 def collectAttributes(skinAttributes, node, skin_path_prefix=None, ignore=[]):
@@ -90,16 +99,16 @@ def collectAttributes(skinAttributes, node, skin_path_prefix=None, ignore=[]):
                # TODO: localization? as in e1?
                value = a.value.encode("utf-8")
                
-               if attrib in ["pixmap", "pointer", "seek_pointer"]:
+               if attrib in ["pixmap", "pointer", "seek_pointer", "backgroundPixmap", "selectionPixmap"]:
                        value = resolveFilename(SCOPE_SKIN_IMAGE, value, path_prefix=skin_path_prefix)
                
                if attrib not in ignore:
                        skinAttributes.append((attrib, value))
 
-def loadPixmap(path):
-       ptr = loadPNG(path)
+def loadPixmap(path, desktop):
+       ptr = LoadPixmap(path, desktop)
        if ptr is None:
-               raise "pixmap file %s not found!" % (path)
+               raise SkinError("pixmap file %s not found!" % (path))
        return ptr
 
 def applySingleAttribute(guiObject, desktop, attrib, value):
@@ -117,15 +126,20 @@ def applySingleAttribute(guiObject, desktop, attrib, value):
                        guiObject.setFont(parseFont(value))
                elif attrib == 'zPosition':
                        guiObject.setZPosition(int(value))
-               elif attrib == "pixmap":
-                       ptr = loadPixmap(value) # this should already have been filename-resolved.
-                       desktop.makeCompatiblePixmap(ptr)
-                       guiObject.setPixmap(ptr)
+               elif attrib in ["pixmap", "backgroundPixmap", "selectionPixmap"]:
+                       ptr = loadPixmap(value, desktop) # this should already have been filename-resolved.
+                       if attrib == "pixmap":
+                               guiObject.setPixmap(ptr)
+                       elif attrib == "backgroundPixmap":
+                               guiObject.setBackgroundPicture(ptr)
+                       elif attrib == "selectionPixmap":
+                               guiObject.setSelectionPicture(ptr)
                        # guiObject.setPixmapFromFile(value)
                elif attrib == "alphatest": # used by ePixmap
                        guiObject.setAlphatest(
-                               { "on": True,
-                                 "off": False
+                               { "on": 1,
+                                 "off": 0,
+                                 "blend": 2,
                                }[value])
                elif attrib == "orientation": # used by eSlider
                        try:
@@ -164,8 +178,12 @@ def applySingleAttribute(guiObject, desktop, attrib, value):
                                        print "illegal flag %s!" % f
                elif attrib == "backgroundColor":
                        guiObject.setBackgroundColor(parseColor(value))
+               elif attrib == "backgroundColorSelected":
+                       guiObject.setBackgroundColorSelected(parseColor(value))
                elif attrib == "foregroundColor":
                        guiObject.setForegroundColor(parseColor(value))
+               elif attrib == "foregroundColorSelected":
+                       guiObject.setForegroundColorSelected(parseColor(value))
                elif attrib == "shadowColor":
                        guiObject.setShadowColor(parseColor(value))
                elif attrib == "selectionDisabled":
@@ -187,15 +205,14 @@ def applySingleAttribute(guiObject, desktop, attrib, value):
                elif attrib == "pointer" or attrib == "seek_pointer":
                        (name, pos) = value.split(':')
                        pos = parsePosition(pos)
-                       ptr = loadPixmap(name)
-                       desktop.makeCompatiblePixmap(ptr)
+                       ptr = loadPixmap(name, desktop)
                        guiObject.setPointer({"pointer": 0, "seek_pointer": 1}[attrib], ptr, pos)
                elif attrib == 'shadowOffset':
                        guiObject.setShadowOffset(parsePosition(value))
                elif attrib == 'noWrap':
                        guiObject.setNoWrap(1)
                else:
-                       raise "unsupported attribute " + attrib + "=" + value
+                       raise SkinError("unsupported attribute " + attrib + "=" + value)
        except int:
 # AttributeError:
                print "widget %s (%s) doesn't support attribute %s!" % ("", guiObject.__class__.__name__, attrib)
@@ -209,7 +226,23 @@ def loadSingleSkinData(desktop, dom_skin, path_prefix):
        
        skin = dom_skin.childNodes[0]
        assert skin.tagName == "skin", "root element in skin must be 'skin'!"
-       
+
+       for c in elementsWithTag(skin.childNodes, "output"):
+               id = int(c.getAttribute("id") or "0")
+               if id == 0: # framebuffer
+                       for res in elementsWithTag(c.childNodes, "resolution"):
+                               xres = int(res.getAttribute("xres" or "720"))
+                               yres = int(res.getAttribute("yres" or "576"))
+                               bpp = int(res.getAttribute("bpp" or "32"))
+
+                               from enigma import gFBDC
+                               i = gFBDC.getInstance()
+                               i.setResolution(xres, yres)
+
+                               if bpp != 32:
+                                       # load palette (not yet implemented)
+                                       pass
+
        for c in elementsWithTag(skin.childNodes, "colors"):
                for color in elementsWithTag(c.childNodes, "color"):
                        name = str(color.getAttribute("name"))
@@ -249,10 +282,7 @@ def loadSingleSkinData(desktop, dom_skin, path_prefix):
                                bpName = str(pixmap.getAttribute("pos"))
                                filename = str(pixmap.getAttribute("filename"))
                                
-                               png = loadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, filename, path_prefix=path_prefix))
-                               
-                               # adapt palette
-                               desktop.makeCompatiblePixmap(png)
+                               png = loadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, filename, path_prefix=path_prefix), desktop)
                                style.setPixmap(eWindowStyleSkinned.__dict__[bsName], eWindowStyleSkinned.__dict__[bpName], png)
 
                for color in elementsWithTag(windowstyle.childNodes, "color"):
@@ -282,18 +312,28 @@ def lookupScreen(name):
                                return x, path
        return None, None
 
-def readSkin(screen, skin, name, desktop):
-       
-       myscreen, path = lookupScreen(name)
-       
+def readSkin(screen, skin, names, desktop):
+       if not isinstance(names, list):
+               names = [names]
+
+       name = "<embedded-in-'%s'>" % screen.__class__.__name__
+
+       # try all skins, first existing one have priority
+       for n in names:
+               myscreen, path = lookupScreen(n)
+               if myscreen is not None:
+                       # use this name for debug output
+                       name = n
+                       break
+
        # otherwise try embedded skin
        myscreen = myscreen or getattr(screen, "parsedSkin", None)
-       
+
        # try uncompiled embedded skin
        if myscreen is None and getattr(screen, "skin", None):
                myscreen = screen.parsedSkin = xml.dom.minidom.parseString(screen.skin).childNodes[0]
-       
-       assert myscreen is not None, "no skin for screen '" + name + "' found!"
+
+       assert myscreen is not None, "no skin for screen '" + repr(names) + "' found!"
 
        screen.skinAttributes = [ ]
        
@@ -334,7 +374,37 @@ def readSkin(screen, skin, name, desktop):
                        collectAttributes(attributes, widget, skin_path_prefix, ignore=['name'])
                elif wsource:
                        # get corresponding source
-                       source = screen.get(wsource)
+
+                       while True: # until we found a non-obsolete source
+
+                               # parse our current "wsource", which might specifiy a "related screen" before the dot,
+                               # for example to reference a parent, global or session-global screen.
+                               scr = screen
+
+                               # resolve all path components
+                               path = wsource.split('.')
+                               while len(path) > 1:
+                                       scr = screen.getRelatedScreen(path[0])
+                                       if scr is None:
+                                               print wsource
+                                               print name
+                                               raise SkinError("specified related screen '" + wsource + "' was not found in screen '" + name + "'!")
+                                       path = path[1:]
+
+                               # resolve the source.
+                               source = scr.get(path[0])
+                               if isinstance(source, ObsoleteSource):
+                                       # however, if we found an "obsolete source", issue warning, and resolve the real source.
+                                       print "WARNING: SKIN '%s' USES OBSOLETE SOURCE '%s', USE '%s' INSTEAD!" % (name, wsource, source.new_source)
+                                       print "OBSOLETE SOURCE WILL BE REMOVED %s, PLEASE UPDATE!" % (source.removal_date)
+                                       if source.description:
+                                               print source.description
+
+                                       wsource = source.new_source
+                               else:
+                                       # otherwise, use that source.
+                                       break
+
                        if source is None:
                                raise SkinError("source '" + wsource + "' was not found in screen '" + name + "'!")
                        
@@ -360,7 +430,7 @@ def readSkin(screen, skin, name, desktop):
                                        c = converter_class(parms)
                                        c.connect(source)
                                else:
-                                       print "reused conveter!"
+                                       print "reused converter!"
        
                                source = c