Project

General

Profile

Setup and Layout of an XML Skin
 

1.1  General Directory Structure
1.2  Theme Files
1.3  globals.xml
1.4  setup.xml and skin specific OSD setup menu
1.5  Skin and XML File Structure
1.6  SVG Templates

 


1.1 General Directory Structure

All the files associated with a skin are contained in subdirectories within a single skin root directory. The skins root directory should be named using your skins name. The skins root directory and subdirectories should be laid out in the following structure:

(* see README for more information about configuring the <skinpath>)

<skinpath>
+---<skinname>
    |
    |--- globals.xml
    |
    |--- setup.xml
    |
    |--- themes
    |    |--- default
    |    |    |--- theme.xml
    |    |    |--- icons
    |    |    |--- menuicons
    |    |    |    |--- customicons
    |    |    |    |--- pluginicons
    |    |    |    |--- standardicons
    |    |    |--- skinparts
    |    |--- logos
    |    |
    |    |--- theme2
    |         |--- theme.xml
    |         |--- icons
    |         |--- ...
    |
    |--- xmlfiles
    |
    |--- icons
    |
    |--- menuicons
    |    |--- customicons
    |    |--- pluginicons
    |    |--- standardicons
    |
    |--- skinparts
    |
    |--- svgtemplates
         |--- icons
         |--- menuicons
         |    |--- customicons
         |    |--- pluginicons
         |    |--- standardicons
         |--- skinparts

The skins root folder must contain "globals.xml". Each theme may use an optional "theme.xml" to complete or override settings in "globals.xml". Further explanations are available in chapter 1.3 regarding this.

If used, "setup.xml" should be located in skins root folder. In "setup.xml" you can define settings/variables which are then accessible via the OSD. They may be changed directly from the OSD without requiring any manual editing of any XML file. The skin can then be written in a way that changes its behavior based on these settings/variables. See chapter 1.4 for more information.

The "xmlfiles" Folder contains all necessary XML files to display the skin itself. These XML files are used by all themes.

Each skin must contain a "default" theme directory in the skins "themes" directory (/<skinpath>/<skinname>/themes/default/). Additional themes are stored in their own directories within the "themes" directory. For example, /<skinpath>/<skinname>/themes/<mytheme1>, /<skinpath>/<skinname>/themes/<mytheme2>, etc.

The following folders may be located in the skins root directory (/<skinpath>/<skinname>/), within a skins theme folder (/<skinpath>/<skinname>/themes/<themename>/), or both. Image files located in the skins root directory are shared/available to all skin themes, while image files located within a theme folder are available to that theme only. Image files within theme folders are given priority. If an image file is used by the theme but missing from the themes folder, Skindesigner will look for the image file in the shared folders as a fallback. Icons must be in SVG or PNG format.

  • menuicons/ parent folder for all menu icons. these icons must be named exactly as their english VDR menu entries are
  • menuicons/customicons/ icons paired with custom menu entries
  • menuicons/pluginicons/ icons paired with plugins
  • menuicons/standardicons/ icons for standard VDR menu items (Schedules, Channels, Timers, Recordings, etc)
  • icons/ all icons that are outside the scope of menuicons
  • skinparts/ graphics used for skin elements, such as foregrounds and backgrounds

The svgtemplates folder located in the root folder of the skin stores so called "SVG Templates". This SVG Templates are used by all themes of a skin, the images represented by the SVG Templates are colored automatically with colors defined in the themes. See chapter 1.6 for a detailed explanation how to use this SVG Templates.

Each theme may have its own set of logos in an optional /<skinpath>/<skinname>/themes/<themename>/logos/ folder. If this folder doesn't exist, Skindesigner will use the common logo folder, set using the "-l" plugin parameter (see README for details), as a fallback.

 


1.2 Theme Files

If your skin only has one theme (default), no dedicated theme file is required. If your skin has multiple themes, each theme must have a "<skinname>-<themename>.theme" file placed in VDRs theme directory. The contents of these files only needs to be:

Description = <name you want displayed in VDRs menu>

 


1.3 globals.xml

The "globals.xml" file should contain all global definitions for the skin. Themes may optionally use a "theme.xml", located in /<skinpath>/<skinname>/themes/<themename>/, to add further definitions available only to that theme. The file structure for "globals.xml" and "theme.xml" is identical. If a definition of the same name is present in both "globals.xml" and "theme.xml", the definition in "theme.xml" takes priority.

The different definitions and variables are in detail:

<globals>
    <colors>
        <color name="clrRed">FFFF0000</color>
        ...
    </colors>
    ...

Define in this area all the colors used in the skin. The attribute "name" is mandatory so that the color can be used with this name in the skin. The color definition is an ARGB value with the first two digits describing the transparency. FF is completely opaque, 00 is fully transparent.

    ...
    <variables>
        <var type="int" name="border">5</var>
        <var type="int" name="fadetime">500</var>
        <var type="double" name="pi">3.14</var>
        <var type="string" name="constant">some constant string</var>
    </variables>
    ...

Variables can be used everywhere in the skin. Variables of type "int" or "double" are intended to be used for calculation in numeric attributes, "string" variables have to be used in the "text" attribute of the <drawtext> and <drawtextbox> functions.

    ...
    <translations>
        <token name="tr(activetimers)">
            <trans lang="en_EN">Active Timers</trans>
            <trans lang="de_DE">Aktive Timer</trans>
        </token>
        ....
    </translations>
    ...

Inside the <translations> tag you can define all texts which should be displayed in different languages. Just define your needed tokens and languages. If an language is not available, english is used as default.

    ...
    <fonts>
        <font name="light">VDROpen Sans Light:Light</font>
        <font name="semibold">VDROpen Sans Semibold:Semibold</font>
        ...
    </fonts>
</globals>

Finally inside the <font> tag all fonts which are used in the skin can be defined. The font definition has to be the exact name of the font as known by VDR. For a list of fonts VDR currently knows on your system, you can use the command "svdrpsend plug skindesigner LSTF" which prints a list of all fonts in your system log.

The three fonts vdrOsd, vdrFix and vdrSml can be used always. These are the fonts defined in the VDR OSD menu for Osd Font, Fixed Font and monospaced Font.

All the described variables can be used in the different attributes of the various functions to draw on the OSD which are described later by referencing them with the "name" attribute. Keep in mind that whenever you use one of these values, the name has to be embedded in curly braces. For example, displaying text with the <drawtext> function, using the vdrOsd font, you would write something like this:

<drawtext x=".." y=".." font="{vdrOsd}" color="{clrRed}" text="{tr(activetimers)}" ... />

This is a general concept in skindesigner that "tokens" (description see later) are always used in this way.

 


1.4 setup.xml and skin specific OSD setup menu

The "setup.xml" file is structured in the following way:

<setup>
    <menu>
        <parameter type="int" name="intvar" min="5" max="20" displaytext="I am an integer variable with default value 10" helptext="I am the helptext for this parameter">10</parameter>
        <parameter type="bool" name="boolvar" displaytext="{tr(boolvartext)}" helptext="{tr(helpboolvar)}">1</parameter>
        <parameter type="separator" displaytext="{tr(separatortext)}"/>
        <parameter type="string" name="stringvar" displaytext="I am a string parameter with three options" options="option1,option2,option3">2</parameter>
        ...
        <submenu name="submenu1" displaytext="{tr(submenu1text)}">
            <parameter type="bool" name="subboolvar" displaytext="{tr(subboolvartext)}">0</parameter>
            ...
            <submenu name="subsubmenu1" ...>
                ...
            </submenu>
        </submenu>
        <submenu name="submenu1" displaytext="{tr(submenu1text)}">
            ...
        </submenu>
    </menu>

    <translations>
        <token name="tr(boolvartext)">
            <trans lang="en_EN">Display xxxxx?</trans>
            <trans lang="de_DE">xxxxx anzeigen?</trans>
        </token>
        <token name="tr(helpboolvar)">
            <trans lang="en_EN">Detailed help for boolvar...</trans>
            <trans lang="de_DE">Ausführliche Hilfe für diese boolsche Variable...</trans>
        </token>
        <token name="tr(submenu1text)">
            <trans lang="en_EN">I am a submenu</trans>
            <trans lang="de_DE">Ich bin ein Untermenü</trans>
        </token>
        <token name="tr(option1)">
            <trans lang="en_EN">Option 1</trans>
            <trans lang="de_DE">Auswahlmöglichkeit 1</trans>
        </token>
        ...
    </translations>
</setup>

Inside the <menu> tag <parameter> and <submenu> tags with an arbitrary depth are allowed. Each defined parameter is shown in the appropriate skin setup (sub) menu which is located inside the skindesigner plugin setup menu. Submenus have to carry the attributes "name" and "displaytext". "name" is just for internal purposes to identify the submenu, "displaytext" is used as the text to show in the menu and can be a translation token. Additionally the optional "helptext" attribute can be defined (can also be a translation token). If a help text is defined, this text can be displayed with the green button in a separate text page.

Parameters can be of type int, bool, string or separator. For int variables a minimum (default 0) and a maximum (default 1000) can be configured, so that in the OSD setup menu the range is limited accordingly. "displaytext" is used as setup parameter description in the setup menu itself. Analog to the translations in globals.xml for each parameters displaytext a translation can be defined. The value of the parameter tag is the default value for the parameter. For string parameters the attribute "options" has to be defined as a comma separated string. The first option has index 0. Here the value of the parameter tag is the default index value for the parameter. For the values in the options field also translations can be defined. The translations are just just for displaying the different options in the setup menu. Separators can be used to structure the setup menus in a more userfriendly way. Separators are not selectable in the menus.

In the skin xml files int and bool parameters can be used identically as integer variables in globals.xml. If for instance a int parameter with the name "fadetime" is defined in setup.xml, you can use this variable as {fadetime} token everywhere in the skin. Values of string parameters are provided as string tokens with the selected option as value and additionally as int token with the index as value. The int token is named as the appropriate string token with an preposed "index". So if a string parameter is named "menuorientation" with the options "horizontal" and "vertical", the string token {menuorientation} and the int token {indexmenuorientation} are available.

After closing the skindesigner setup menu completely, the currenty active skin gets newly loaded and cached so that changes of parameters are immediately in use.

 


1.5 Skin and XML File Structure

A VDR Skin contains of six different views:

  • displaychannel: display during channel switching
  • displaymenu: the VDR menu
  • displayreplay: display during playing a recording
  • displaymessages: display if VDR needs to tell you something
  • displayaudiotracks: display for selecting audio tracks of a channel
  • displayvolume: display for selecting volume

For each of this six views an appropriate XML file has to exist, for instance "displaychannel.xml", which is responsible for displaying the view. Each of these XML Files starts in the same way, here the beginning of displaychannel.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE displaychannel SYSTEM "../../dtd/displaychannel.dtd">
<displaychannel x="0" y="0" width="100%" height="100%" fadetime="300">
...
</displaychannel>

The first two lines ensure, that the document is a well formed XML document and fulfills the rules defined in the document type definition "../../dtd/displaychannel.dtd". The DTD which is also used by the two included skins is already delivered by skindesigner and should be placed correnctly during plugin installation.

Each skindesigner XML document has to be "well formed", otherwise the XML parser will not accept the document. The syntax rules are in short:

  • XML documents must have a root element
  • XML elements must have a closing tag
  • XML elements without value have to be closed with />
  • XML tags are case sensitive
  • XML elements must be properly nested
  • XML attribute values must be quoted

Whenever the VDR default skin LCARS appears instead of the choosen skindesigner skin, then most probably there are errors in your XML documents. Check the VDR log, there skindesigner tells you what is exactly wrong with your XML files.

The root node ("view tag") of the XML document has always to be named as the document itself. The attributes of this root node define the general behaviour of the view and the position of the OSD. In detail the followig attributes are allowed in the view tag:

  • x (mandatory): x position of the OSD
  • y (mandatory): y position of the OSD
  • width (mandatory): width of the OSD
  • height (mandatory): height of OSD
  • fadetime (optional): fade in and fade out time for view in ms, default: 0
    shifttime (optional): shifting duration in milliseconds
  • shiftx, shifty (optional): shifting start point. All areas in the view start at this point and shift to their final position defined in the area element itself (x, y attribute). (mandatory, alternatively use shifttype)
  • shifttype (optional): possible values: top, bottom, left, right. If this attribute is set, the view shifts in from the correspondingly OSD border. (mandatory, alternatively use shiftx and shifty)
  • shiftmode (optional):: possible values: linear, slowed. If shiftmode is set to "linear", shifting is done with a constant speed. With "slowed" shifting is slightly slowed down at the end.
  • scaletvx (optional): x position of scaled tv window, default: 0
  • scaletvy (optional): y position of scaled tv window, default: 0
  • scaletvwidth (optional): width of the scaled tv window, default: osdwidth
  • scaletvheight (optional): height of the scaled tv window, default: osdheight

Each of the positioning attributes can include an absolute or a relative value in proportion to the full OSD size. With that it is possible to create skins which automatically fit to different screen resolutions. Here an exemplarily "displaychannel" tag:

<displaychannel x="5%" y="75%" width="90%" height="20%" fadetime="300">
...
</displaychannel>

Here the display during channel switching is placed only in the lower area of the screen width a height of 20% of the total screen and with a 5% border around. Keep in mind that this defined area is the "reference area" for all further elements in this XML document. That means, it is not possible to draw any content outside the area defined in the view tag.

If in VDRs OSD Menu a border is configured (OSD Left, Top, Width and Height settings), these values are also respectively considered in the calculation of the OSD size.

Five of the six needed XML files are structured in this way. Ony the structure of the file "displaymenu.xml" is a little bit more complex. Since the VDR menu has several categories and subcomponents which have to be handled differentely, the head of displaymenu.xml looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE displaymenu SYSTEM "../../dtd/displaymenu.dtd" [
<!ENTITY displaymenudefault SYSTEM "displaymenudefault.xml">
<!ENTITY displaymenumain SYSTEM "displaymenumain.xml">
<!ENTITY displaymenusetup SYSTEM "displaymenusetup.xml">
<!ENTITY displaymenuschedules SYSTEM "displaymenuschedules.xml">
<!ENTITY displaymenutimers SYSTEM "displaymenutimers.xml">
<!ENTITY displaymenuchannels SYSTEM "displaymenuchannels.xml">
<!ENTITY displaymenurecordings SYSTEM "displaymenurecordings.xml">
<!ENTITY displaymenudetailepg SYSTEM "displaymenudetailepg.xml">
<!ENTITY displaymenudetailrecording SYSTEM "displaymenudetailrecording.xml">
<!ENTITY displaymenudetailtext SYSTEM "displaymenudetailtext.xml">
]>

<displaymenu x="3%" y="5%" width="94%" height="90%" fadetime="0">

    ...

    &displaymenudefault;
    &displaymenumain;
    &displaymenusetup;
    &displaymenuschedules;
    &displaymenutimers;
    &displaymenuchannels;
    &displaymenurecordings;
    &displaymenudetailepg;
    &displaymenudetailrecording;
    &displaymenudetailtext;
</displaymenu>

Here in the header of the XML file additionally xml entities are defined, so that for every different menu category or subcomponent a dedicated XML file can be included. This is done with an "&" before the entity name inside the XML document. In the included XML documents the first child node of the root tag <displaymenu> defines again the used area for the subcomponent. Here an example for the main menu:

<menumain x="0" y="0" width="50%" height="50%" fadetime="0" scaletvx="50%" scaletvy="50%" scaletvwidth="50%" scaeltvheight="50%">
...
</menumain>

That means, that the main menu uses only the upper right quarter of the area defined by <displaymenu>, the tv picture is scaled to the lower right quarter. All the values for x, y, width and height are relatively to the parent node. This is a general concept in skindesigner that sizes of areas are always defined relatively to the size and position of the parent node.

The different subcomponents in displaymenu are used in the following cases:

  • displaymenudefault: the default VDR list menu used in all standard list menus
  • displaymenumain: the VDR main menu
  • displaymenusetup: the VDR setup menu
  • displaymenuschedules: the VDR "Schedules" category with "what's on", "what's on now" and "what's on next" lists
  • displaymenutimers: the VDR "Timers" list
  • displaymenuchannels: the VDR "Channels" list
  • displaymenurecordings: the VDR "Recordings" menu
  • displaymenudetailepg: detailed view for EPG entries
  • displaymenudetailrecording: detailed view for recordings
  • displaymenudetailtext: detailed view for pure text

displaymenudefault has to be used mandatorily. If one or more of the other submenus are not included in displaymenu, displaymenudefault is used instead for displaying this submenu.

For a complete skin all the described XML files have to be created. As a starting point a skeleton which includes all the needed files with all necessary basic definitions is provided in the plugin sources in the "skinskeleton" folder.

 


1.6 SVG Templates

Often in skins the color of (background)images or icons is dependend of the used theme. One possibility to achieve this is to use differently colored images / icons for each theme. That means that for every new theme the images have to be copied and redeyed again manually for this new theme. An alternative and more convenient way is to use SVG templates. Initially the effort is slightly higher because the SVG templates have to be created also manually one time, but after this is done, a new theme can be generated just by adapting the colors in the accoring theme.xml file.

So what is a SVG template? SVG Images in general are stored with a specific XML syntax. When you create a SVG image (for instance with Inkscape) and open the stored image with an editor, you'll see how SVG images are "described" using XML. An colored circle for instance is described in the following way:

<circle style="opacity:1;fill:#ff0000;fill-opacity:0.8;..." ... />

In this example the circle is filled with red (fill:#ff0000, color in RGB) with a opacity of 80%. If you now want to generate a SVG Template so that this circle is colored differently for each theme, you just have to define a dedicated color in your theme.xml file and replace the color and opacity settings in the original SVG file with specific tokens. Assuming that the defined color in the theme.xml file is called "clrIcon", you have to use the two tokens {sdcol(clrIcon)} and {sdopac(clrIcon)} in the SVG image:

<circle style="opacity:1;fill:#{sdcol(clrIcon)};fill-opacity:{sdopac(clrIcon)};..." ... />

If clrIcon is defined as CCFF0000 for a theme (as ARGB value as usual in theme files), you'll get the identical image as in the example above (the "Alpha" value "CC" is just the representation of 80% in hex notation). You do not have to care about the conversion from ARGB to the color and opacity values a SVG images expects. This is done automatically by skindesigner.

So the recommended way to create SVG Templates is first to create an image "normally" with Inkscape (or any other vector based graphics software) using some "default" colors. After that the image has to be edited with a text editor and every color intended to be "themable" has to be replaced by appropriate tokens as described above. These SVG templates have then to be stored in the "svgtemplates" folder in the skin root folder (see chapter 1.1).

SVG templates can be used for any icon or skinpart used in a skin. If an image is not available in the usual directories (themes image directories and common image directories) an additional search for this image is peformed in the "svgtemplates" folder. Inside this folder, the images have to be placed in the identical subfolder structure as in the main skin directory. If the image (respectively the template) is found there, automatically all color tokens are replaced with the colors defined in the theme.xml file and the image is displayed using colors suitable for the currently selected theme. For sure these generated images are also cached internally in memory, so using SVG templates has no performance impact.