Contents
We need graphical artists
If you are good with graphics, layouts and stuff, please: we need you to improve Freevo skins and maybe design new ones. If you want to help, read this document and join the developers list. It you don't want to work on the skins, but have other ideas, you can send mockups and likes to the development lists too. If we like it we may implement it.
Why should I read this? I like the current skin.
Freevo supports folder based skins and has an extra xml file for menus with a background image you can use for DVD/VCD/CD, movie submenus and folders containing recordings of different episodes of one tv show. If you like that, keep reading or skip to the examples.
Selecting a different skin
You can change skins from within Freevo. Just press d (DISPLAY in your remote) in the main menu. You should get a list of the available skins. Select the one you like and press ENTER (SELECT in your remote).
This skin will not be loaded during the next run. If you want some skin as your default, change your local_conf.py and search for the GUI_XML_FILE (SKIN_XML_FILE for Freevo 1.5.x). You should change the value to the skin name you want.
Example:
SKIN_XML_FILE = 'noia'
or
GUI_XML_FILE = 'noia'
Writing your own skin
Turn on skin debugging
Freevo now has skin debugging mode to make writing and adjusting skins much easier. In your local_conf.py add the following:
DEBUG_SKIN = True
When you next start freevo all the skin labels will be displayed allowing you to easily identify the code to the corresponding skin areas.
About the skins
In Freevo, two things can be called skins:
skin backend: which render things on the screen. For now, there is only one backend in Freevo, but you can write one if it doesn't act like you want. This backend handles a set of XML files and images to compound what we call a skin (see next point). We will not cover backend coding in this document, since the backend is flexible enough. Maybe it's just a matter of changing it, not implementing another. But if you really want to, join the developers mail list. Skin backends are located in src/skins. The backend we use now is called main and it's in src/skins/main.
skin configuration: this one is specific for each backend. It can handle colors, layouts, menus, etc. This document will only cover this type of "skin". Skins are made from XML files and images.
The files are in share/skins/<backend> (or /usr/share/freevo/skins in a default installation). They all have the .fxd extension. We will cover the skins for the main backend, so you should look in share/skins/main. The skins can inherit from each other so that information is not repeated over and over again.
The blue.fxd skin contain all needed information for a skin. All other skins inherit from this one.
Note: the extension .fxd is use for all xml files used by Freevo, so you may see files ended in .fxd that has nothing to do with the skin.
Skin structure
Tip: While you read this document, open some skins in a XML editor with syntax highlight (ie: kate, vi, emacs, ...) then try to match what we say with that document. blue.fxd is the base skin, almost every other skin inherit from it. info.fxd is a more elaborated skin, with different menu styles, information for items and more. barbieri_blue.fxd is my personal skin (Gustavo), it was made to demonstrate as many as possible skin capabilities.
A skin xml contains different elements to make it possible to change the look very easy. First, the skin defines a geometry and maybe inherits from another skin. The skins provided with Freevo uses 800x600. If you use a different resolution, all positions and sizes will be scaled to fit the screen.
IMPORTANT NOTE: one element can point to another referring to its label attribute.
First, we begin the XML document, specify the XML version (and if you want, specify the encoding, the default one is utf-8) and open the root tag:
<?xml version="1.0" ?> <freevo>
This is needed for all Freevo XML files. Remember that .fxd files can contain other kinds of information. We need to make it clear to Freevo that we're creating a skin. For this, we use the following tag:
<skin geometry="800x600">
This says we started to specify a skin document. The 'screen'-tag accepts the following attributes:
geometry="<width>x<height>" -- the skin's geometry
fontscale="<float_number>" -- font sizes will be multiplied by this factor
include="<some_file>" -- include this file (must be other skin, of course)
Using an Icon Set
Now we want to define which icon theme we use with this skin:
<iconset theme="AquaFusion" />
All icon themes are located in share/icons/themes/.
Setting Skins Variables
We can also set skin variables using the FXD. For example:
<setvar name="box_under_icon" val="0" />
This sets the box_under_icon value to zero, disabling this feature.
Current variables are:
box_under_icon, when enabled, says the box under items should be also under icons, in text menus (more about this feature later on).
anamorphic, when enabled, scales foreground images to 75% of their original width. When a theme with this set is displayed on a 16:9 anamorphic display, images will be displayed at the correct aspect ratio.
Before you go any further, you should be familiar with the following tags and their functions:
Colors
You may define <color> tags so you don't need to remember values, it's easier to keep it consistent. It's easy to learn: <font label="<label>" value="<color>" />. label is how other elements will refer to this <color>, value is the color in 0xAARRGGBB (ARGB mode, in hexa), 0xRRGGBB (RGB mode, also in hexa, as used in HTML).
Example:
<color label="list bg" value="0xa0333333" />
Images
As simple as <color>, used to avoid typing and keep it consistent. Here's an example:
<image label="background" filename="barbieri/bg.png" />
This tag as child of other element can have other attributes. For example, in <listing> it can have width, height, x and y and label value is used internally by listing to match some pre-defined names, used by the skin backend.
It can also be a child of layout's <background> tag. There you can refer to a previously declared <image> and specify the geometry.
Rectangles
Rectangles are used to draw a rectangular shape. Rectangles have a bgcolor (background color) that is used to fill the rectangle. The color is used as border color. size specifies the border size (0 disable the border). width, height, x and y specify the geometry and position. radius specifies the border radius, used to create rounded boxes.
<rectangle bgcolor="selection bg" color="selection border" size="0" x="0" y="0" width="20" height="20" radius="10" />
Fonts
You need to define a <font> tag to instantiate a font. This font then can be used everywhere in the skin. Its attributes are:
label="<label>": other elements will refer to this font by this label.
name="<name>": the font name, you don't need the extension if it's ttf. The font must be in share/fonts!
size="<size>": font size.
color="<color>": color in 0xAARRGGBB (ARGB mode, in hexa) or in 0xRRGGBB (RGB mode, also in hexa, as used in HTML). The color can also be some color label, specified with <color>.
And it can also have one child tag, <shadow>, which specify the font shadow. It has the x and y attributes, that say how many pixels far the shadow will be, the color and visible="<yes|no>".
Another example:
<font label="info title" name="impact" size="24" color="0xD59215"> <shadow x="1" y="1" color="0x734F0B" visible="yes"/> </font>
Setting Main Menu Items
Then, let's define the main menu:
<main> <item label="tv" name="TV" icon="tv.png" /> <item label="video" name="Movies" icon="movies.png" /> <item label="audio" name="Music" icon="mp3.png" /> <item label="image" name="Images" icon="images.png" /> <item label="games" name="Games" icon="package_games.png" /> <item label="shutdown" name="Shutdown" icon="shutdown.png" /> </main>
The <main> tag handles main menu item's settings. The <item> accept the following attributes:
label="<item's name>" -- the item's name.
name="<some label to this item>" -- it's what you will see in Freevo. You may change this attribute to get nice names, like "Watch a movie" or even translate it if you're foreigner like me ("Veja um Filme", in Brazilian Portuguese).
icon="<icon file>" -- the icon for this item, relative to iconset theme. Leave in blank if you don't want icons.
outicon="<icon file>" -- the icon to be used when this item is not selected. If not specified, defaults to icon above. You can use this to simulate effects like icon zooming (see note below), colorizing, etc..
image="<image file>" -- if instead of an icon you want an image associated with this file, specify this, relative to share/images. See info.fxd.
Note: Icons will be scaled according to the line height, so based on the font size. If you want to simulate zoom effect in icons, you shouldn't give icons from different sizes in icon and outicon, but instead get icon from the same size (canvas) with the contents resized. For example, check share/icons/themes/tuxntosh/mainmenu/54x54/music.png and share/icons/themes/tuxntosh/mainmenu/54x54/out_music.png
Other configurations for main menu, like position, alignment and others are handled like other menus, with <menu type="main"> and <menuset>, except that the main menu can only have one <style>.
Defining your Menus
Now you can define what kind of menus do you want to have using the <menu> tag. Possible types are "all" (delete all other menus from the skin you inherit from), "video", "audio", "image", "games", "tv" and "default" (everything which is not defined). Each menu defines what menuset you want to use for this type using the <style> tag.
blue.fxd only defines "default, but info.fxd for examples defines more different menusets for different types.
Each menu defines a list of styles to use. You can toggle through the styles by pressing d (DISPLAY in your RC) in the menu. For instance, info.fxd has different styles (menusets), so you can, for example, browse your CD's viewing their covers.
Here's an excerpt from info.fxd:
<menu type="audio"> <style image="audio menu with info" text="text with info style"/> <style text="text with info style"/> </menu>
This tells that the Audio Menus will have 2 styles. The first style will be the default and it say it will show listings in image mode with possible a text fallback (for example, when you're browsing through music you may see CD covers, but if you're inside a CD, all items will have the same cover, so there's no sense in viewing the cover, so we fallback to the text menu). The second style is a text view. Both image and text points to <menusets>.
If an image view is defined, you will see a bi-dimensional menu with images (covers if movies/music) and possible the name under it.
If a text view is defined, you will see a one-dimensional menu with item names and possible an icon representing the item's type or some mark to allow you to identify that. For now, if some item doesn't have an icon associated and it's a directory, you will get [ and ] around the name. If it's a playlist, you get PL: before it.
If you define text and image, the menu will use image and when all covers are the same (like a directory containing all mp3 files of a cd) the skin will switch to text view. In style, you don't really define the look, you point to a menuset with the label attribute.
Menu Sets
Now, you must define all menusets your menu needs. As explained above, each <style> reference to a <menuset> with image and text attributes.
A <menuset> can inherit other menuset using the inherits="<other menuset label>". It also has some areas, here called layouts:
screen: the background and some items related, like rectangles.
title: can be menu's title or selected item.
subtitle: same as title.
listing: where the menu will show its items.
info: information about the selected item.
view: some kind of visualization for the selected item. Can be a bigger cover or something else. Maybe in future we can get movie and tv preview in this place.
Each area may point to a layout. If you're inheriting other menuset, you don't need to set this. Areas may also have their position and geometry, defined as x, y, width and height. You can disable an area by setting visible="no".
<listing> can also have <image> inside them, so you can position your navigation arrows. These images have pre-defined labels: uparrow and downarrow. They're displayed just when needed.
Here's an excerpt from barbieri_blue.fxd:
<menuset label="audio iconified with info big"> <screen layout="audio screen" x="0" y="0" width="800" height="600" /> <title layout="audio title" x="10" y="80" width="623" height="70" /> <subtitle visible="no" /> <listing layout="audio list" x="346" y="151" width="416" height="439"> <image label="uparrow" x="760" y="171" width="32" height="32" filename="up.png"/> <image label="downarrow" x="760" y="538" width="32" height="32" filename="down.png"/> </listing> <view layout="audio view" x="10" y="171" width="250" height="250" /> <info layout="audio info" x="10" y="441" width="336" height="150" /> </menuset>
Layouts
A layout must have a label attribute, so other elements can refer to it. It also may have some children tags:
<background>: contains images and rectangles.
<content>: defines how the content should look like.
Layouts used by <screen> doesn't need the content tag, just the background one. <title>, <subtitle>, <listing>, <view> and <info>, the other way, just need the <content>.
<content> is the most important element in Freevo skin. It values and children tags depends on who use it, so pay attention! .
It's attributes are:
type="<type>":
If used by <listing> can be: text if it will be used in text listings, image for image listings without names under it, image+text for image listings with names under
If used by <title> or <subtitle> can be menu to get the menu title or short item to get the selected item name.
If used by <screen>, <info> or <view> it's ignored.
x="<x>": horizontal position relative to the position defined in the calling area, so if in you used <screen x="20" .../> and then use <content x="5" ... />, the contents will show in absolute position 25.
y="<y>": vertical position, also relative.
width="<width>": the width. Can be MAX+<value> or MAX-<value>, where MAX will be replaced by the width of the calling area. This is useful when you want to define some spacement from other things. For example, you can use x="10" and width="MAX-20" to get 10 pixels spacement in horizontal direction.
height="<height>": the width. Can be MAX+<value> or MAX-<value>, same properties as width.
align="<left|right|center>": horizontal alignment. Can be left, right or center.
valign="<top|bottom|center>": vertical alignment. Can be top, bottom or center.
spacing="<spacing>": spacing between items.
The <listing>, <view> and <info> area may contain <item> tags inside content to define different looks for the different types of menu items.
Listing Layouts
For <listing>, the <item> tags may have the type attribute set to:
audio: settings for Audio items.
video: settings for Video items.
image: settings for Image items.
game: settings for Video Game items.
playlist: settings for Playlists items.
dir: settings for directories.
dvd: settings for DVD items.
vcd: settings for VCD items.
audiocd: settings for Audio CD items.
empty_cdrom: settings for Empty CD-Roms items.
default: used when one of the above was not specified.
These define the settings for non-selected items, for the selected you should use the selected variant, just have the type to be one of the described above + selected, ie: audio selected, except from default which become just selected.
Note that if you use different layouts for different menus, you don't need to specify items you know will be not there. For example, you have a <menuset> used only by audio menu. The <layout> of its <listing> doesn't need to define 'game' menus, you just need to define audio related types (dvd, empty_cdrom, audiocd, dir, playlist). But if you will use the same menuset for all menus, you may define all the types.
You can define a rectangle for the listing items (the selection bar). If you like, you could also define a rectangle for the non selected items with a different background, or no selection bar for the selected item and even a transparent background for some kind of items. If you want this selection bar to be also under the icon in text views, you can define the skin variable box_under_icon (take a look in the Setting Skins Variables section).
As example, here is a <layout> to be used by <listing> for text view:
<layout label="default list"> <content type="text" spacing="2" align="right" valign="center"> <!-- Define default item. ALWAYS --> <item type="default" font="item" /> <item type="selected" font="selected"> <rectangle bgcolor="selection bg" color="selection border" size="1" x="-10" y="-3" width="max+20" height="max+6" radius="10"/> </item> <item type="audio" font="audio item" icon="mimetypes/out_audio.png"/> <item type="audio selected" font="audio selected" icon="mimetypes/audio.png" /> </content> </layout>
This will display Audio items without a selection box, but with icon at the right side (because we defined content alignment as "right", and with different icons for selected and non selected items (pay attention to the filenames). All other items will show with a selection box under it, it's defined by <rectangle> tag.
This box will have a "selection border" color 1px border, that begins 10px before the item's limit and ends 10px after the limit in the horizontal direction, the horizontal limit is the one specified by the area (ie <listing>) with x and width in the <menuset>. It also start 3px before and end 3px after the item's limit in the vertical direction, the vertical item's limit is given by the item's height, if in a text menu, it's the font height, if in a image menu, it's the image height, if in a image+text menu, it's the sum of both. The box will have round corners with 10px radius.
This relative box geometry can be confusing, but it's just first impression... Better you try some tests and see the results.
Now, look at another <listing> example, this time for image+text view:
<layout label="video list"> <content type="image+text" spacing="-17" align="center" valign="center"> <item type="default" width="108" height="150" font="item small" align="center" valign="center"/> <item type="selected" width="128" height="177" font="selected small" align="center" valign="center"> <rectangle bgcolor="list selection bg" color="list selection fg" size="1" x="-10" y="max-font_h-10" width="max+20" height="font_h+20" radius="20"/> </item> <item type="video" width="108" height="150" font="video item small" align="center" valign="center"/> <item type="video selected" width="128" height="177" font="video selected small" align="center" valign="center"> <rectangle bgcolor="list selection bg" color="list selection fg" size="1" x="-10" y="max-font_h-10" width="max+20" height="font_h+20" radius="20"/> </item> </content> </layout>
It's almost the same, except some settings:
Now you may define <item> width and height. That will be used as image geometry. You also can have different sizes for selected and non-selected items, causing the zoom effect for selected items.
Because of this, you may need some negative spacing, because the item's geometry will be: width = max( selected item width, non-selected item width ) and height = max( selected item height, non-selected item height ). So if you have selected item 20px larger than the non-selected, you may get 40px spacing between items! So using spacing="-17" will reduce it to 23px.
The rectangle attributes may use another meta value aside from MAX, this value is font_h, this is the font height. With that you can have things like the selection box to appear just under the text (as in this example), under the whole image+text or just under the image.
Info Layouts
Info layouts define what info and how these info will show up in the screen. The <item> type attribute is something like those for <listing>, except that you don't have the selected variant. Again, if you will use this layout from a menuset used by just some kind of items, you don't need to define all types, like in the following example, which is used only by audio menu's in barbieri_blue.fxd.
You need to know some formatting tags before looking at the example. They're:
<newline />: used to go next line.
<goto_pos x="<x>" y="<y>" mode="<absolute|relative>" />: Go to the given position. If you specify relative as mode, then it's relative to the "pen" position (where the last char was draw). If you specify absolute, then you will go to the position inside the layout area, which is defined in the <info> are in menuset, that is it's absolute in the layout context, but not absolute in the screen context.
<if expression="<some expression>"> <!-- some tags --> </if>: This can be used to hide parts if some kind of data is not available. The expression is a logic expression that uses information attribute names as values and can have the logic operators or, and and not. These attribute names depends on what kind of information that item type provides to you. For example, audio have title, track, artist, album and year. Also, you can have len(<info name>) <some comparison>, (ie: len(playlist) >= 1 ) this is useful for playlists, so you can check how many items are in that.
<text font="<font>" width="<width>" height="<height>" mode="<hard|soft>" align="<horizontal alignment>" valign="<vertical alignment>">some text</text>: This says what font to use and other properties of the text to be shown. Every text outside <text> will NOT be displayed!. The attributes are:
mode: soft if you want the line to be broke at words or hard if you want to break at chars.
Tip: for small text/area, better to use hard or you will end with just ellipses (used when the text is truncated).
expression: it's the information name, as explained above in <if>. The result of the expression will be displayed and the tag contents data will be discarded.
font: the font to use.
height: can be the meta value line_height, to fit one line; max to fit the whole text or until reach the bottom of the layout limit or the smallest between both.
width: some value in pixels. This can be used with <goto_pos> to simulate a tabular environment.
So, here goes the example:
<layout label="audio info"> <content x="0" y="0"> <item type="audio"> <if expression="title"> <if expression="track"> <text height="line_height" align="left" font="info title" mode="hard" expression="track" /> <text font="info title"> - </text> </if> <text height="line_height" align="left" font="info title" mode="hard" expression="title" /> <newline /> </if> <if expression="artist"> <text height="line_height" width="75" align="right" font="info label" mode="hard">Artist:</text> <goto_pos x="10" mode="relative" /> <text height="line_height" align="left" font="info value" mode="hard" expression="artist" /> <newline /> </if> <if expression="album"> <text height="line_height" width="75" align="right" font="info label" mode="hard">Album:</text> <goto_pos x="10" mode="relative" /> <text height="line_height" align="left" font="info value" mode="hard" expression="album" /> <if expression="year"> <text font="info value"> (</text> <text height="line_height" align="left" font="info value" mode="hard" expression="year" /> <text font="info value">)</text> </if> <newline /> </if> </item> <item type="dir"> <if expression="name"> <text height="line_height" align="right" font="info title" mode="hard" expression="name" /> <newline /> </if> <if expression="dir"> <text height="line_height" align="left" font="info value" mode="hard" expression="dir" /> <newline /> </if> </item> <item type="playlist"> <if expression="len(playlist)>1"> <text font="info value" expression="len(playlist)"/> <text font="info value"> musics in this playlist.</text> <newline/> </if> <if expression="len(playlist)==1"> <text font="info value">Just one music in this playlist.</text> <newline/> </if> <if expression="len(playlist)==0"> <text font="info value">This playlist is empty!</text> <newline/> </if> </item> </content> </layout>
Defining TV settings
TV is just like other menus, the <tv> tag behaves just like <menu>in which you select different <menuset> using the <style> tag. (See Menu Sets section).
As in TV Guide you can move horizontally, you may also define <image> tags with label="leftarrow" and label="rightarrow", just you do for uparrow and downarrow in other <listing>.
Example:
<tv> <style text="tv menu"/> <style text="tv menu more info"/> </tv> <menuset label="tv menu"> <screen layout="tv screen" x="0" y="0" width="800" height="600"/> <info layout="tv info" x="10" y="70" width="780" height="140"/> <title visible="no"/> <listing layout="tv listing" x="10" y="220" width="750" height="370"> <image x="765" y="220" width="32" height="32" label="uparrow" filename="up.png"/> <image x="765" y="max-32" width="32" height="32" label="downarrow" filename="down.png"/> <image width="16" height="16" label="leftarrow" filename="left.png"/> <image width="16" height="16" label="rightarrow" filename="right.png"/> </listing> </menuset> <menuset label="tv menu more info" inherits="tv menu"> <listing height="150"/> <info layout="tv info" y="250" height="340"/> </menuset>
Defining Player settings
Player is just like <menuset>:
<player> <screen layout="player screen" x="0" y="0" width="800" height="600"/> <view layout="player view" x="430" y="230" width="420" height="360"/> <info layout="player info" x="-50" y="80" width="600" height="300"/> <title visible="no"/> </player>
Examples
OK, here some nice cool small examples:
Different background image
You may have a file called skin.fxd in the freevo config directory. In this file you could write:
<?xml version="1.0" ?> <freevo> <skin> <image label="background" filename="my-background"/> </skin> </freevo>
and now you have a different background image for the menu. You could also put this in a folder.fxd and Freevo would use the new background in this folder only. So if you're Star Wars big fan, your Star Wars movie collection can have a different background!
Changing skins
More? OK, maybe you like info.fxd. But you also like the 3rd view skin (detailed info) in the video menu. But you only want that in the folder with all your fxd files pointing to your DVDs. Just create a folder.fxd, inherit from info.fxd, force the skin to 3rd view and set the background to some you want:
<?xml version="1.0" ?> <freevo> <folder> <setvar name="force_skin_layout" val="2"/> <!-- this select the 3rd view (detailed info) --> </folder> <skin include="blue2" geometry="800x600"> <image label="background" filename="myfavorite_bg.jpg" /> <!-- should be a file called myfavorite_bg.jpg in share/images/ --> </skin> </freevo>
Background images for DVDs or tv show folder
Now something different: you want a background image for a folder or as DVD menu. You don't need a title area, no view or info area, there is this background image. OK, just inherit from the image.fxd (a skin specially designed for this purpose) and redefine the listing area position and the colors (look at share/skins/main/image.fxd for more details). E.g.: I have a nice orange background for my Charlie's Angels DVD. I also have a fxd file for this DVD. I just added skin information to that file:
<?xml version="1.0" ?> <freevo> <copyright> The information in this file are from the Internet Movie Database (IMDb). Please visit http://www.imdb.com for more information. </copyright> <disc-set title="Charlie's Angels"> <cover-img>charlies_angels.jpg</cover-img> <!-- ... the rest of your FXD, probably you may get this with the Search IMDb plugin --> </disc-set> <skin include="image" geometry="800x600"> <menuset label="bgimage style"> <listing x="10" y="100" width="300" height="340"/> </menuset> <image label="background" filename="charlies_angels_bg.jpg"/> <color label="selected" value="0xffff00"/> <color label="item" value="0x000000"/> <color label="selection bar" value="0xa0000000"/> </skin> </freevo>
CD-ROM support
Don't put a folder.fxd file on a cd. The format may change.
You always should use the movie fxd file to do that and put this file in some dir accessible by freevo, ie the defined in DIR_MOVIES or MOVIE_DATA_DIR. If you put in MOVIE_DATA_DIR, then when you insert your CD, it will show the information automatically. If you put in DIR_MOVIES it will do the same as MOVIE_DATA_DIR and will show the movie in the dir, even if the disc is not there. When you press ENTER (SELECT in your RC), Freevo will ask you for the Disc.
Write a new skin, including new Python code
If you don't like the current skin at all, you can write your own skin in python and you have all the freedom you want in designing the look of freevo. Please take a look at skin.py to get the needed callbacks your skin needs.
OSD Skins
OSD Skins are used to change the look and feel of some of the dialog boxes displayed in the Freevo frontend and also the play state or the EPG information displayed when viewing a movie or watching TV. To enable the use of OSD skins when viewing a movie or watching TV you need to be running Freevo under X11, have installed the kaa.display package (currently only available from the subversion repository) and using Freevo 1.8.4 (or the latest svn version).
Selecting an OSD Skins
To select the OSD skin to use simple add:
DIALOG_SKIN_XML_FILE='<your chosen skin name>'
to your local_conf.py file. By default the base skin is selected.
Creating/Editing an OSD Skin
Creating a OSD Skin is similiar to writing a menu skin for Freevo, but slightly simpler due to the use of the OSD Designer (see OsdDesigner for more details).