From 5d99df7b7760c4a2b497c737a15b609008f6d56d Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 16 May 2004 10:35:36 +0200 Subject: Implemented 'skins' and 'themes' --- PLUGINS.html | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 188 insertions(+), 27 deletions(-) (limited to 'PLUGINS.html') diff --git a/PLUGINS.html b/PLUGINS.html index d13ca4ab..a2cfe9b3 100644 --- a/PLUGINS.html +++ b/PLUGINS.html @@ -9,17 +9,20 @@
Version 1.3

-Copyright © 2003 Klaus Schmidinger
+Copyright © 2004 Klaus Schmidinger
kls@cadsoft.de
www.cadsoft.de/vdr

-
  +
  Important modifications introduced in version 1.2.6 are marked like this.
-
  +
  Important modifications introduced in version 1.3.0 are marked like this.
+
  +Important modifications introduced in version 1.3.7 are marked like this. +

VDR provides an easy to use plugin interface that allows additional functionality to be added to the program by implementing a dynamically loadable library file. @@ -67,10 +70,14 @@ structures and allows it to hook itself into specific areas to perform special a

  • Status monitor
  • Players
  • Receivers -
      +
     
  • Filters
  • The On Screen Display +
      +
  • Skins +
  • Themes +
  • Devices
  • Dolby Digital
  • Remote Control @@ -1207,7 +1214,7 @@ Mode). If the cReceiver isn't needed any more, it may simply be deleted and will automatically detach itself from the cDevice. -
      +
     

    Filters

    A Fistful of Datas

    @@ -1253,35 +1260,166 @@ and will automatically detach itself from the cDevice. See VDR/eit.c or VDR/pat.c to learn how to process filter data.

    +
     

    The On Screen Display

    -
    Express yourself

    +

    Window to the world

    -Most of the time a plugin should be able to access the OSD through the -standard mechanisms also used by VDR itself. However, these set up the OSD in -a manner of textual rows and columns, and automatically set the various -windows and color depths. -

    If a plugin needs to have total control over the OSD, it can call the static function

     #include <vdr/osd.h>
     
    -cOsdBase *MyOsd = cOsd::OpenRaw(x, y);
    +cOsd *MyOsd = cOsdProvider::NewOsd(x, y);
     

    where x and y are the coordinates of the upper left corner -of the OSD area on the screen. Such a "raw" OSD doesn't display anything +of the OSD area on the screen. Such an OSD doesn't display anything yet, so you need to at least call the function

    -MyOsd->Create(...);
    +tArea Area = { 0, 0, 100, 100, 4 };
    +MyOsd->SetAreas(Area, 1);
     

    -to define an actual OSD drawing area (see VDR/osdbase.h for the declarations -of these functions, and VDR/osd.c to see how VDR opens the OSD and sets up +to define an actual OSD drawing area (see VDR/osd.h for the declarations +of these functions, and VDR/skinsttng.c to see how VDR opens the OSD and sets up its windows and color depths). +

    +Theoretically the OSD supports a full screen drawing area, with 32 bit color +depth. However, the actual OSD device in use may not be able to provide the +full area or color depth, maybe because of lack of OSD memory or other restrictions. +A plugin that uses the OSD should therefore test whether the OSD is able to +provide the requested functionality, and should offer alternate color depths +to allow a less powerfull OSD implementation to still work reasonably. +Since it is often not really necessary to have hundreds or thousands of colors +all over the OSD area, a plugin can divide the total drawing area into several +sub-areas with different color depths and separate color palettes, as in + +

    +tArea Area = { 0, 0, 99, 99, 4 };
    +if (osd->CanHandleAreas(Area, 1) == oeOk)
    +   osd->SetAreas(Area, 1);
    +else {
    +   tArea Areas[] = { { 0,  0, 99, 19, 2 },
    +                     { 0, 20, 99, 79, 2 },
    +                     { 0, 80, 99, 99, 4 }
    +                   };
    +   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
    +   }
    +

    + +In this example an OSD with 100 by 100 pixel and 4 bit color depth shall +be opened, so at first a single area with the full required resolution +is set up and CanHandleAreas() is called with it. If the result indicates +that the OSD will be able to handle this drawing area, a call to SetAreas() +actually sets it. If a single area with that resolution can't be handled, +a second attempt is made in which the total drawing area is divided into +three horizontal stripes, two of which use only 2 bit color depth (because +the objects drawn in there can be displayed with 4 colors) while the third +one still requests 4 bit color depth. +

    +Note that a plugin should always at first request a single drawing area +with the full required resolution. Only if this fails shall it use alternate +areas. Drawing areas are always rectangular and may not overlap (but do not need +to be adjacent). + +


    Skins

    + +
    The emperor's new clothes

    + +The way VDR displays its menus to the user is implemented through skins. +A particular skin provides several functions that return objects to be used +for displaying a specific part of the OSD, like a menu, the channel display +or the volume bar. +

    +By default VDR offers the Classic and the ST:TNG Panels skins, +which can be selected through Setup/OSD/Skin. A plugin can implement an +arbitrary skin of its own by doing something similar to what's done in +VDR/skinclassic.c. +

    +The first step in implementing a new skin is to derive a class from cSkin +that provides the handling objects necessary to do the actual work: + +

    +#include "skins.h"
    +
    +class cMySkin : public cSkin {
    +public:
    +  cMySkin(void);
    +  virtual const char *Description(void);
    +  virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
    +  virtual cSkinDisplayMenu *DisplayMenu(void);
    +  virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
    +  virtual cSkinDisplayVolume *DisplayVolume(void);
    +  virtual cSkinDisplayMessage *DisplayMessage(void);
    +  };
    +

    + +See the comments in VDR/skins.h for details. VDR/skinclassic.[hc] +can be used as an example for how to implement all the necessary classes and +functions to compose a complete skin. See also the chapter about themes +if you want to make the colors used by your skin configurable. +

    +To add your new skin to the list of skins available to the user in Setup/OSD/Skin, +all you need to do is create a new object of your skin class, as in + +

    +new cMySkin;
    +

    + +in the Start() function of your plugin. +Do not delete this object, it will be automatically deleted when the program ends. + +


    Themes

    + +
    Eye of the beholder...

    + +A theme is a collection of colors that can be used by a skin. +Since every skin most likely has its own idea about what parts of it can be +themed, and different skins may have completely different numbers of +"themeable" parts, a particular theme can only be used with the skin it was designed +for. A particular skin, however, can have any number of themes. Which theme +will be actually used can be defined in Setup/OSD/Theme. +

    +In order to make a skin "themeable" is shall create an object of type cTheme, as in + +

    +static cTheme Theme;
    +

    + +The next step is to define the colors that shall be provided by this theme, as in + +

    +THEME_CLR(Theme, clrTitle,        0xFFBC8024);
    +THEME_CLR(Theme, clrButtonRedFg,  clrWhite);
    +THEME_CLR(Theme, clrButtonRedBg,  clrRed);
    +

    + +THEME_CLR() is a helper macro that adds the given color name +and its default color value to the theme. +

    +Any color names can be used, but they should always start with clr... and +if a given color has a foreground and a background value, the two names shall be +distinguished by appending ...Fg and ...Bg, respectively. +

    +Color values can be either 32 bit hexadecimal numbers in the form 0xAARRGGBB +(where the individual bytes represent Alpha (transparency), Red, Green +and Blue component, respectively), or one of the predefined color names from +VDR/osd.h. +

    +In the actual drawing code of a skin, the color names defined with the THEME_CLR() +macros can be used to fetch the actual color values from the theme, as in + +

    +osd->DrawText(x, y, s, Theme.Color(clrButtonRedFg), Theme.Color(clrButtonRedBg), font);
    +

    + +By default this will use the colors that have been defined in the respective +THEME_CLR() line, but may be overwritten through user supplied theme +files (see man vdr(5) for information about the format of a theme file). +


    Devices

    @@ -1297,7 +1435,7 @@ into a VDR system; or an analog TV receiver card, which does the MPEG encoding "on the fly" - assuming your machine is fast enough), or just a software program that takes an MPEG data stream and displays it, for instance, on an existing graphics adapter.

    -To implement an additional device, a plugin must derive a class from cDevice: +To implement an additional device, a plugin must derive a class from cDevice:

     #include <vdr/device.h>
    @@ -1374,7 +1512,7 @@ The functions to implement replaying capabilites are
     virtual bool HasDecoder(void) const;
     virtual bool CanReplay(void) const;
     virtual bool SetPlayMode(ePlayMode PlayMode);
    -
      +
      virtual int64_t GetSTC(void);
    virtual void TrickSpeed(int Speed); @@ -1396,7 +1534,7 @@ virtual void SetVideoFormat(bool VideoFormat16_9); virtual void SetVolumeDevice(int Volume);

    -
      +
     

    Section Filtering

    @@ -1426,23 +1564,46 @@ handle section data.

    On Screen Display

    +
      If your device provides On Screen Display (OSD) capabilities (which every device -that is supposed to be used as a primary device should do), it can implement -the function +that is supposed to be used as a primary device should do), it shall implement +an "OSD provider" class, derived from cOsdProvider, which, when its CreateOsd() +function is called, returns an object derived from cOsd, which can be used to +access the device's OSD: + +

    +class cMyOsdProvider : public cOsdProvider {
    +public:
    +  cMyOsdProvider(void);
    +  virtual cOsd *CreateOsd(int Left, int Top);
    +  };
    +

    + +In its MakePrimaryDevice() function the device shall create an object +of this class, as in

    -virtual cOsdBase *NewOsd(int x, int y);
    +void cMyDevice::MakePrimaryDevice(bool On)
    +{
    +  new cMyOsdProvider;
    +}
     

    -which must return a newly created object of a derived cOsdBase class that -implements the functions necessary to display OSD information on your device. -The caller of this function will delete the object as soon as it is no longer -needed. +The OSD provider object is allocated on the heap and shall not be deleted +(it will be deleted automatically in case a different device sets up an OSD +provider, or when the program ends). + +Note that an OSD implementation need not be physically linked to the device +in any way. All it needs to make sure is that the OSD will be visible to the +user - whether this goes through OSD facilities of the physical device (like +a "full featured" DVB card) or through a graphics adapter that overlays its +output with the video signal, doesn't matter. +

    Initializing new devices

    -A derived cDevice class shall implement a static function +A derived cDevice class shall implement a static function in which it determines whether the necessary hardware to run this sort of device is actually present in this machine (or whatever other prerequisites might be important), and then creates as many device objects as necessary. -- cgit v1.2.3