Home

enigma2 skins

Fundi

Usuario Destacado
Loco por OpenSPA
Fan de OpenSPA
19 Mar 2007
11.803
596
0
enigma2 skins
=============

A skin file is an XML file. Better read the existing skin file as an
example.

colors
======

you can define alias names for different colors. the "value" is given as
#aarrggbb, or just #rrggbb.

windowstyle
===========
here you can configure the "window style", i.e. the bord around windows.

screens
=======

these are the different widgets for the screens. they can also be embedded
in the screens itself.

pixmap paths
============
there is no lookup order, but exactly one place to search for pixmaps.
You can either:
- specify a full pathname (PLEASE, don't!), with a leading slash.
- specify a relative pathname, without leading slash.
The file will be searched for under the default skin image directory.
use this to refer to pixmaps which are included in the default
distribution, i.e. no skin specific stuff but for example the
number bitmaps etc.
- relative to the skin's directory (with a leading "~/").
~ in this case can be seen as the skin's "home directory", that's the
place where the skin.xml is.
use this if you are building a skin.

A NOTE ABOUT PNGs
=================

Enigma can user either a 32bit argb or an 8bit pseudocolor output. In any
case, enigma uses 8bit PNGs for skins.

Though it would be easy to support 32bit pngs as well, it questionable if
this would be a great idea.

a.) the quality improvement is realative

you can use another palette for each png. that gives you unique 256 colors
for each skin element. Unless you have very big PNGs, you shouldn't be able
to notive the difference between 32bit and 8bit.

b.) 32bit skins wouldn't be compatible to 8bit displays

we still want to use enigma on hardware which is too slow for using a 32bit
output (after all, framebuffers can be very slow). Turning a 32bit bitmap
into an 8bit one is not ease and involves a lot of computations.

It would end up that you need to specify an 8bit and a 32bit version. Is
that really what you want?

c.) 32bit PNGs don't compress well

PNG is a lossless format. 32bit bitmap data is very hard to compress
lossless.

We could use JPG, but jpgs don't offer a transparency channel, as far as i
know.


So, how to make your PNGs to look good?

It's simple. Edit them as 32bit ARGB (photoshop, gimp should be able to do
this fine!). Be sure that if you want alphatest, transparency really has an
alpha value of 0 / 255 (i.e. the extreme).

When you're finished, use "pngquant 256 <filename>" to process your PNGs to
be compatible with enigma.

note:
=====

if you're having less than 16 colors in your png file, pngquant generates a
16color (4bit) PNG, which is not really what we want. Either add more colors
(evil workaround), fix enigma (good idea!) or patch pngquant to
always create 8bit pngs.

transparency:
=============

First, do not mix up transparency with alpha. I agree, both terms refer to
the same thing, but in our case, it's more complicated. As long as we don't
run on accelerated graphic, we need to differentiate between these two.

Alpha, in our context, is the ratio between the video and the OSD. Alpha = 0
means that OSD is completely visible, and no video, whereas Alpha = 1 (or
0xFF, if you express it so) means that there is only video.

Transparency, on the other hand, is OSD-only. When you have a background,
say a color, and you want to blit a picture on it, you can mix the
background with the picture. (*) This allows pixmap with a non-rectangular
shape.

Because of speed reasons, we don't support real alpha blending when not
running with acceleration. Instead, we use alpha testing. This means that a
special color is "transparent", whereas all other colors are not. This
colors *HAS TO BE AT INDEX 0*. As you can't count on automatic palette
merging (it's disabled when the target is 32bit, so you you're not
restricted to 8bit in total, only 8bit per pixmap), you have to tell your
gfx program to put the transparent color at index 0. This is what's normally
done, but in case transparency doesn't work correctly, you might want to
check this.


(*) Note, that, technically, if we start with a alpha=1 background (i.e.
only video), and alphablend on this, we generalized the problem enough that
we can handle both cases the same. But currently, we have to differentiate
between them, as we can't always alphablend simply for performance reasons.

lcd:
====

Right now, most lcd-skins ("summary screens") are implemented right in the
python screens. However, you can override them with regular skinfiles.

There is some confusion about the actual size of the LCD. For now, assume it
to be 132x64 pixel, but think of the fact that some (most?) hardware can
only display either 128 (dreambox) or 120 (dbox2, dm8000) pixels
horizontally.

Right now some pixels will be cropped, currently at the right side. This
will be (hopefully) fixed soon, so that the used pixels are always in the
center.

So, bottom line:

Design LCD skins for 132x64, with no important items (text etc.) at the
outermost 6 pixels on each side. In doubt, leave them white.

LCD colorspace:
===============

current LCDs are not able to display grayscale graphics. For this, there
will be a 1bit quantization. However, skins should be designed for 8bit
grayscale (and still look good in 1bit!), because some next-generation
display might be able to display some shades of gray - likely not 256, but
maybe 16 or so.
 

Fundi

Usuario Destacado
Loco por OpenSPA
Fan de OpenSPA
19 Mar 2007
11.803
596
0
Skins are now converted to use a "source"/"covert"/"render"-mechanism.

A "source" is a data-source. For example, the infobar has a source called
"CurrentService", which is the currently displayed service, i.e. the channel
the user is watching at the moment.

Now, a "current service" has a lot of properties, like
- Service Name
- service number
- flags like "are subservices available?"
- playback position, length, ...

Say you want to display the "service name" on screen. Only "renderers" can
paint on the screen. The most basic renderer is the "Label"-Renderer, which
can display a text. The "service name" is a text, so we use the
"Label"-renderer. We also know that "CurrentService" is our source.

But the renderer can only display texts, not "services". It needs something
to turn a "service" into a "text", i.e. something which extracts the service
name out of a service.

That's where "converters" come into action. If we want to extract the
servicename from a service, we need the "ServiceName"-converter. The
"ServiceName"-converter can not only extract the service *name*, but also
the provider name (another property of a service), so we have to specify
what we want.

So our skin data could look like:

<widget source="CurrentService" render="Label" position="69,25"
size="427,26" font="Regular;22" backgroundColor="#101258" >
<convert type="ServiceName">Name</convert>
</widget>

The "call chain" consists of

"CurrentService" -> "ServiceName(NAME)" -> "Label"


The are the following source types:

Clock - the current time
EventInfo - the current now&next events
MenuList - a menu
CurrentService - the currently playing service
FrontendStatus - frontend status, like BER, Signal Strength etc.
Boolean - a usually fixed boolean value, for example "is record possible?"

Actually used sources are defined in a "Screen". That is, a Screen offers
sources, which you can use inside your skin.

The "Infobar", for example, offers the following sources:

Event_Now
Event_Next
CurrentService
RecordingPossible
TimeshiftPossible
ExtensionsAvailable
Clock

Then there are the following "Converters":

ClockToText - turns a 'Clock' source into a text
Parameters:
"WithSeconds": "hh:mm:ss"
"InMinutes" : "mm min"
"Date" : "Wednesday, 07 June, 2006"
"Default" : "hh:mm"
EventName - extracts the event name
Parameters:
"Description": Extracts the description of the event
"ExtendedDescription": Extracts the extended description of the event
"Name": extracts the name of the event
EventTime - extracts the event time
Parameters:
"EndTime": extracts the end time of the event
"Remaining": extracts the remaining time of the event
"StartTime": extracts the start time of the event
"Duration": extracts the duration of the event
"Progress": extracts the progress of the event
RemainingToText - turns a "remaining"-time into text ("xxx m", or "+xx m")
It automatically uses the event length when the remaining time is invalid
StringList - turns a menulist into a list usable for a "Listbox"-renderer
FrontendInfo - extracts specific information out of a frontend
Parameters:
BER
SNR
AGC
LOCK

You can either use a "Progress" or "Label" renderer, or, with Lock or
BER, you can use a ConditionalShowHide to show a "warning symbol" when
BER is >0.

ServiceInfo - extracts info out of a service
Parameters:
HasTeletext
IsMultichannel
IsCrypted
IsWidescreen
SubservicesAvailable
ConditionalShowHide - conditionally show/hide a widgets based on the
source's boolean output
Optional parameter: "Invert" - inverts the sense, i.e. show when boolean
value is false
ServicePosition - extracts the current service play position out of a
service
Parameters:
"Length"
"Position"
"Remaining"
"Gauge"
ServiceName
Parameters:
"Name"
"Provider"

Then there are the following renderers:
Label
Progress
Listbox
Pixmap
PositionGauge
FixedLabel

You can also put multiple converters in a row. Each one will pick up the
output of the last coverter.

Of course you can only connect items which are compatible. Right now you
have to look at the examples :)

Some more examples:

"SUBSERVICES AVAILABLE DISPLAY"
===============================

<widget source="CurrentService" render="Pixmap" pixmap="button_green.png" position="320,132" size="27,12" >
<convert type="ServiceInfo">SubservicesAvailable</convert>
<convert type="ConditionalShowHide" />
</widget>

will display a pixmap whenever the "CurrentService" has
"SubservicesAvailable".

"CURRENT SERVICE POSITION IN A POSITION GAUGE"
==============================================

<widget source="CurrentService" render="PositionGauge" position="247,60" size="225,20" zPosition="2" pointer="position_pointer.png:3,5" >
<convert type="ServicePosition">Gauge</convert>
</widget>

The "ServicePosition" is extracted from the CurrentService, and the
PositionGauge picks that information up and displays it on screen.

"START TIME OF CURRENT EVENT"
=============================

<widget source="Event_Now" render="Label" position="210,68" size="60,22" font="Regular;20" backgroundColor="dark">
<convert type="EventTime">StartTime</convert>
<convert type="ClockToText">Default</convert>
</widget>
The StartTime is extracted from the Event_Now (current event), and converted
into text with the standard (hh:mm) style, then displayed with the
"Label"-renderer.