diff options
-rw-r--r-- | HISTORY | 16 | ||||
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | README | 19 | ||||
-rw-r--r-- | bitmap.c | 79 | ||||
-rw-r--r-- | bitmap.h | 12 | ||||
-rw-r--r-- | cache.h | 11 | ||||
-rw-r--r-- | common.c | 9 | ||||
-rw-r--r-- | common.h | 11 | ||||
-rw-r--r-- | contrib/items.doc | 620 | ||||
-rwxr-xr-x | contrib/list_items.pl | 173 | ||||
-rw-r--r-- | data.c | 29 | ||||
-rw-r--r-- | deprecated/SKINS (renamed from SKINS) | 0 | ||||
-rw-r--r-- | deprecated/SKINS.de (renamed from SKINS.de) | 0 | ||||
-rw-r--r-- | display.c | 4 | ||||
-rw-r--r-- | i18n.c | 14 | ||||
-rw-r--r-- | loader.c | 3 | ||||
-rw-r--r-- | render.c | 57 | ||||
-rw-r--r-- | render.h | 9 | ||||
-rw-r--r-- | text2skin.c | 4 | ||||
-rw-r--r-- | theme.c | 6 |
20 files changed, 989 insertions, 99 deletions
@@ -1,6 +1,22 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2004-06-16: Version 0.0.5 + +- fixed disappearing Scrolltext when Message was displayed +- fixed display-items "MenuScrollUp" and "MenuScrollDown" which didn't display + any other items than "Symbol" +- fixed the above for all replay- and channel-symbols + (for all display-items that can be symbols there must be path, altpath or + both to tell the plugin if that item is to be drawn if the symbol is on, + off or in both cases) +- fixed various memory leaks and missing destructions (valgrind rox) +- fixed the image loaders to respect the alpha value and palette properly + (this hopefully also fixes the phenomenon that images "get lost" after some + time) +- added display-item "Scrollbar" +- SKINS and SKINS.de are now generated during the make + 2004-06-13: Version 0.0.4 - added parameter alpha for images @@ -9,7 +9,7 @@ HAVE_IMAGEMAGICK=1 # DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING # ------------------------------------------------------------- # -# $Id: Makefile,v 1.10 2004/06/12 18:00:05 lordjaxom Exp $ +# $Id: Makefile,v 1.11 2004/06/16 18:46:50 lordjaxom Exp $ # # The official name of this plugin. @@ -90,10 +90,16 @@ $(DEPFILE): Makefile all: libvdr-$(PLUGIN).so -libvdr-$(PLUGIN).so: $(OBJS) +libvdr-$(PLUGIN).so: $(OBJS) SKINS SKINS.de $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -o $@ @cp $@ $(LIBDIR)/$@.$(VDRVERSION) +SKINS: contrib/items.doc + @contrib/list_items.pl >$@ + +SKINS.de: contrib/items.doc + @contrib/list_items.pl de >$@ + dist: clean @-rm -rf $(TMPDIR)/$(ARCHIVE) @mkdir $(TMPDIR)/$(ARCHIVE) @@ -103,4 +109,4 @@ dist: clean @echo Distribution package created as $(PACKAGE).tgz clean: - @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ + @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ SKINS SKINS.de @@ -53,7 +53,9 @@ Installation: Install text2skin like any other plugin. In this example I assume that you have changed to the folder where the VDR sourcecode is located, and that it is -version 0.0.1 of the plugin you wish to install. +version 0.0.1 of the plugin you wish to install. During the build process, +there will be generated two files called SKINS and SKINS.de, the skin format +documentation. root@linux # cd PLUGINS/src root@linux # wget http://www.magoa.net/linux/contrib/vdr-text2skin-0.0.1.tgz @@ -63,6 +65,13 @@ root@linux # cd ../.. root@linux # make plugins root@linux # ./vdr -P text2skin +If you are using VDR 1.3.10, your have to apply a patch to the sources of VDR. +This patch will hopefully be included in VDR 1.3.11. + +root@linux # patch -p1 < PLUGINS/src/text2skin/patches/vdr-1.3.10-scroller.diff +root@linux # make vdr +root@linux # ./vdr -P text2skin + If you are using VDR 1.3.9, you also have to apply a patch to the sources. This patch will be included in VDR 1.3.10. @@ -85,9 +94,11 @@ Inside that "plugins" folder, create a subfolder called "text2skin". Inside same names as the skins residing in them. Each skin must at least have a file carrying the same name, but ending in ".skin". Example: -/video0/plugins/text2skin/demo/demo.skin -/video0/plugins/text2skin/skin2/skin2.skin -... +Example (the Skin is called myskin): +/video0/plugins/text2skin/ +/video0/plugins/text2skin/myskin/ +/video0/plugins/text2skin/msykin/msykin.skin +/video0/plugins/text2skin/myskin/channeldisplay.png The other files inside the skin-folder are additional description files (for Themeing and Translation), images, logos and symbols. @@ -1,5 +1,5 @@ /* - * $Id: bitmap.c,v 1.15 2004/06/12 19:16:11 lordjaxom Exp $ + * $Id: bitmap.c,v 1.16 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "bitmap.h" @@ -11,9 +11,7 @@ #endif #ifdef HAVE_IMAGEMAGICK #include <Magick++.h> -using Magick::Image; -using Magick::PixelPacket; -using Magick::Exception; +using namespace Magick; #endif template<> @@ -22,6 +20,7 @@ void cImageCache::Delete(string &key, cText2SkinBitmap *&value) { } cImageCache cText2SkinBitmap::mCache(Text2SkinSetup.MaxCacheFill); +bool cText2SkinBitmap::mFirstTime = true; cText2SkinBitmap::cText2SkinBitmap(void) { mCurrent = 0; @@ -31,6 +30,7 @@ cText2SkinBitmap::cText2SkinBitmap(void) { cText2SkinBitmap::~cText2SkinBitmap() { for (int i = 0; i < (int)mBitmaps.size(); ++i) delete mBitmaps[i]; + mBitmaps.clear(); } cBitmap &cText2SkinBitmap::Get(int &UpdateIn) { @@ -60,10 +60,25 @@ cBitmap &cText2SkinBitmap::Get(int &UpdateIn) { return *mBitmaps[mCurrent]; } +void cText2SkinBitmap::SetAlpha(int Alpha) { + if (Alpha > 0) { + vector<cBitmap*>::iterator it = mBitmaps.begin(); + for (; it != mBitmaps.end(); ++it) { + int count; + if ((*it)->Colors(count)) { + for (int i = 0; i < count; ++i) { + int alpha = (((*it)->Color(i) & 0xFF000000) >> 24) * Alpha / 255; + (*it)->SetColor(i, ((*it)->Color(i) & 0x00FFFFFF) | (alpha << 24)); + } + } + } + } +} + cText2SkinBitmap *cText2SkinBitmap::Load(const char *Filename, int Alpha) { - if (mCache.Contains(Filename)) { + if (mCache.Contains(Filename)) return mCache[Filename]; - } else { + else { cText2SkinBitmap *bmp = new cText2SkinBitmap; int len = strlen(Filename); bool result = false; @@ -84,8 +99,11 @@ cText2SkinBitmap *cText2SkinBitmap::Load(const char *Filename, int Alpha) { } else esyslog("ERROR: text2skin: filename %s too short to identify format", Filename); - if (result) + if (result) { + bmp->SetAlpha(Alpha); return (mCache[Filename] = bmp); + } else + delete bmp; } return false; } @@ -93,11 +111,6 @@ cText2SkinBitmap *cText2SkinBitmap::Load(const char *Filename, int Alpha) { bool cText2SkinBitmap::LoadXpm(const char *Filename, int Alpha) { cBitmap *bmp = new cBitmap(1,1,1); if (bmp->LoadXpm(Filename)) { - int count; - if (Alpha && bmp->Colors(count)) { - for (int i = 0; i < count; ++i) - bmp->SetColor(i, (bmp->Color(i) & 0x00FFFFFF) | (Alpha << 24)); - } mBitmaps.push_back(bmp); return true; } @@ -121,13 +134,7 @@ bool cText2SkinBitmap::LoadImlib(const char *Filename, int Alpha) { for (int y = 0; y < bmp->Height(); ++y) { for (int x = 0; x < bmp->Width(); ++x) { tColor col = (data[pos + 3] << 24) | (data[pos + 2] << 16) | (data[pos + 1] << 8) | data[pos + 0]; - if (Alpha) - col = (col & 0x00FFFFFF) | (Alpha << 24); - int res = bmp->Index(col); - if (pal > 0 && res == 0) - ;//esyslog("ERROR: text2skin: Too many colors used in palette"); - else - bmp->SetIndex(x, y, res); + bmp->DrawPixel(x, y, col); pos += 4; } } @@ -140,6 +147,9 @@ bool cText2SkinBitmap::LoadImlib(const char *Filename, int Alpha) { #ifdef HAVE_IMAGEMAGICK bool cText2SkinBitmap::LoadMagick(const char *Filename, int Alpha) { + if (mFirstTime) + InitializeMagick("text2skin"); + vector<Image> images; cBitmap *bmp = NULL; try { @@ -154,16 +164,33 @@ bool cText2SkinBitmap::LoadMagick(const char *Filename, int Alpha) { for (it = images.begin(); it != images.end(); ++it) { w = (*it).columns(); h = (*it).rows(); - bmp = new cBitmap(w, h, 8); + if ((*it).depth() > 8) { + esyslog("ERROR: text2skin: More than 8bpp images are not supported"); + return false; + } + bmp = new cBitmap(w, h, (*it).depth()); - const PixelPacket *ptr = (*it).getConstPixels(0, 0, w, h); + if ((*it).classType() == PseudoClass) { + int total = (*it).totalColors(); + for (int ic = 0; ic < (int)total; ++ic) { + Color c = (*it).colorMap(ic); + tColor col = (~(c.alphaQuantum() * 255 / MaxRGB) << 24) | ((c.redQuantum() * 255 / MaxRGB) << 16) | ((c.greenQuantum() * 255 / MaxRGB) << 8) | (c.blueQuantum() * 255 / MaxRGB); + bmp->SetColor(ic, col); + } + } + + const PixelPacket *pix = (*it).getConstPixels(0, 0, w, h); + const IndexPacket *idx = (*it).getConstIndexes(); for (int iy = 0; iy < h; ++iy) { for (int ix = 0; ix < w; ++ix) { - tColor col = (((~ptr->opacity & 0xFF00) << 16) | ((ptr->red & 0xFF00) << 8) | (ptr->green & 0xFF00) | ((ptr->blue & 0xFF00) >> 8)); - if (Alpha) - col = (col & 0x00FFFFFF) | (Alpha << 24); - bmp->DrawPixel(ix, iy, col); - ++ptr; + if ((*it).classType() == PseudoClass) { + bmp->SetIndex(ix, iy, *idx); + ++idx; + } else { + tColor col = (~(pix->opacity * 255 / MaxRGB) << 24) | ((pix->red * 255 / MaxRGB) << 16) | ((pix->green * 255 / MaxRGB) << 8) | (pix->blue * 255 / MaxRGB); + bmp->DrawPixel(ix, iy, col); + ++pix; + } } } mBitmaps.push_back(bmp); @@ -1,5 +1,5 @@ /* - * $Id: bitmap.h,v 1.10 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: bitmap.h,v 1.11 2004/06/16 18:46:50 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_BITMAP_H @@ -15,11 +15,12 @@ typedef cText2SkinCache<string,cText2SkinBitmap*> cImageCache; class cText2SkinBitmap { private: static cImageCache mCache; + static bool mFirstTime; - vector<cBitmap*> mBitmaps; - int mCurrent; - time_t mDelay; - time_t mLastGet; + vector<cBitmap*> mBitmaps; + int mCurrent; + time_t mDelay; + time_t mLastGet; // disallow direct construction cText2SkinBitmap(void); @@ -32,6 +33,7 @@ public: cBitmap &Get(int &UpdateIn); void SetColor(int Index, tColor Color) { mBitmaps[mCurrent]->SetColor(Index, Color); } + void SetAlpha(int Alpha); bool LoadXpm(const char *Filename, int Alpha); #ifdef HAVE_IMLIB2 @@ -1,5 +1,5 @@ /* - * $Id: cache.h,v 1.3 2004/06/08 20:45:52 lordjaxom Exp $ + * $Id: cache.h,v 1.4 2004/06/16 18:46:50 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_CACHE_HPP @@ -69,10 +69,6 @@ inline void cText2SkinCache<K,D>::Delete(Item *item) { } template<class K,class D> -inline void cText2SkinCache<K,D>::Delete(K &key, D &Data) { -} - -template<class K,class D> inline void cText2SkinCache<K,D>::Update(Item *item) { item->_lastUsed = time_ms(); if (item->_next != NULL || item->_prev != NULL) @@ -111,6 +107,11 @@ cText2SkinCache<K,D>::~cText2SkinCache() { } template<class K,class D> +void cText2SkinCache<K,D>::Delete(K &key, D &Data) { + abort(); +} + +template<class K,class D> void cText2SkinCache<K,D>::Flush(void) { Item *cur = _first; while (cur) { @@ -1,5 +1,5 @@ /* - * $Id: common.c,v 1.9 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: common.c,v 1.10 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "data.h" @@ -12,7 +12,8 @@ const string SectionNames[__SECTION_COUNT__] = const string ItemNames[__ITEM_COUNT__] = { "Unknown", "Skin", "Background", "Text", "Scrolltext", "Image", "Rectangle", - "Ellipse", "Slope", "Progress", "Logo", "Symbol", "MenuArea", "MenuItem" }; + "Ellipse", "Slope", "Progress", "Logo", "Symbol", "MenuArea", "MenuItem", + "Scrollbar" }; const string DisplayNames[__DISPLAY_COUNT__] = { "Always", "DateTimeF", "DateTime", "Date", "Time", "ChannelNumberName", @@ -131,10 +132,10 @@ bool ParseVar(const char *Text, const char *Name, string &Value){ return res; } -bool ParseVar(const char *Text, const char *Name, tColor **Value) { +bool ParseVar(const char *Text, const char *Name, tColor *Value) { string value; if (ParseVar(Text, Name, value) && value[0] == '#') { - *Value = new tColor(strtoul(value.c_str() + 1, NULL, 16)); + *Value = (tColor)strtoul(value.c_str() + 1, NULL, 16); return true; } return false; @@ -1,5 +1,5 @@ /* - * $Id: common.h,v 1.9 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: common.h,v 1.10 2004/06/16 18:46:50 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_COMMON_H @@ -49,6 +49,7 @@ enum eSkinItem { itemSymbol, itemMenuArea, itemMenuItem, + itemScrollbar, __ITEM_COUNT__ }; @@ -74,9 +75,9 @@ enum eSkinDisplay { displayPresentTitle, // exc: text displayPresentShortText, // exc: text displayPresentDescription, // exc: text - displayFollowingStartTime, // exc: text, progress - displayFollowingEndTime, // exc: text, progress - displayFollowingDuration, // exc: text, progress + displayFollowingStartTime, // exc: text + displayFollowingEndTime, // exc: text + displayFollowingDuration, // exc: text displayFollowingTitle, // exc: text displayFollowingShortText, // exc: text displayTeletext, // exc: symbol @@ -161,7 +162,7 @@ bool ParseVar(const char *Text, const char *Name, eSkinDisplay *Value); bool ParseVar(const char *Text, const char *Name, int *Value); bool ParseVar(const char *Text, const char *Name, const cFont **Value); bool ParseVar(const char *Text, const char *Name, string &Value); -bool ParseVar(const char *Text, const char *Name, tColor **Value); +bool ParseVar(const char *Text, const char *Name, tColor *Value); bool ParseVar(const char *Text, const char *Name, eTextAlignment *Value); #endif // VDR_TEXT2SKIN_COMMON_H diff --git a/contrib/items.doc b/contrib/items.doc new file mode 100644 index 0000000..716f4a2 --- /dev/null +++ b/contrib/items.doc @@ -0,0 +1,620 @@ +%LANGS = ("en" => 0, "de" => 1); + +%TRANS = ( + "Known Sections" => [ "Bekannte Sektionen" ], + "Known drawable Items" => [ "Bekannte Zeichnungs-Items" ], + "Known Display-Items" => [ "Bekannte Anzeige-Items" ], + "Known Parameters" => [ "Bekannte Parameter" ], + + "Section:" => [ "Sektion:" ], + "Description:" => [ "Beschreibung:" ], + "Item:" => [ "Item:" ], + "Parameters:" => [ "Parameter:" ], + "Display:" => [ "Anzeige:" ], + "Parameter:" => [ "Parameter:" ], + "Default:" => [ "Standard:" ], + "Substitutes:" => [ "Ersetzt:" ], +); + + +@INTRO = ( <<END_EN + +This is the documentation to the Text2Skin file-format (version 0.0.2). + +How To create text-based skins +------------------------------ + +It is important that you understand the limitations of the OSD memory. If there +are too many objects with too many colors defined, VDR will throw an error and +some areas will not be displayed. For other output devices this limitations may +not apply, so if you are planning to design a skin for another output device, +feel free to use more colors, but remember that VDR can handle a maximum of 256 +areas per object. + +An object is defined to be a specific area with a specific palette and color +depth. Those objects will be referred to as 'backgrounds' later on. Calculate +the dimensions of them wisely, since overlapping areas or oversized areas will +lead to an error. Also, the width and height of each area has to be a multiple +of four when using a DVB-Card. + + +Creation of an image +-------------------- + +I used gimp to create some test images displaying things on screen, although +I don't know much about image processing :-). To give an advice, I will point +out how I created those test images. + +I've used a template for a menu provided by a community member, tiled it into +sections fully covered by the image. That made three images in this case. Then +I added a little bit of transparency to the image covering the middle part. I've +resized the image so that it's width and height were multiples of four. Now I've +added 50% transparency to the top layer of the image. Then I've reduced the +colordepth of the image (Image->Mode->Indexed) to 14 colors (of course the +image may not be too extensive, but 14 colors can give some nice gradients). +That leaves two colors for text and progress bar in the same display. Reduce +the number of colors according to the background depth and additional +decoration you intend to use. I saved the results to a png file and placed the +result into the skin. + +If you intend to use xpm's, be aware that VDR doesn't know about named colors, +so some images GIMP creates will not be read on-the-fly, because GIMP may use +some named colors, but VDR only recognizes "None". + + +The Description File Format +--------------------------- + +It is a simple configuration file, consisting of Sections and items. +Commentary lines can be added when they are lead in by a '#'. Blank lines will +be ignored. A section is placed in '[]' brackets. All other lines specify +drawable items and are lead in by the phrase "Item=<...>" followed by one or +more parameters (separated by commas). The line must end with a semicolon. + +It is quite important that you understand the relation between the Item and +it's display parameter. The display parameter doesn't only specify WHAT to +display, it also specifies IF it is displayed. For example a rectangle with +display=PresentVPSTime will only be drawn if there is a present VPS time given. +A text with display=PresentVPSTime behaves the same, but the text is +substituted by the actual VPS time string. If the text-parameter contains a +dollar-sign, like in display=PresentVPSTime,text=VPS: $, the VPS time will be +substituted in place of the dollar-sign. + +Example (sorry for the long lines): + +# Description of the skin file +Item=Skin,name=Test,version=0.0.2; +[Channel] +# This is the full channel display +# Background area to draw on (a background MUST be specified to make items +# drawn on it actually visible!!!), with background picture. Bpp=4 equals 16 +# colors +Item=Background,path=channeltop.xpm,x=42,y=350,width=540,height=32,bpp=4; +# A second area below the first one, again with 16 colors (make 32 colors +# alltogether) +Item=Background,path=channel.png,x=48,y=382,width=528,height=84,bpp=4; +# A textual item displaying the channel numer and name (if present) +# The color is a symbolic name that will be filled in the .colors-file +Item=Text,display=ChannelNumberName,x=50,y=355,width=250,height=28,fg=ChNumNameFG,font=Sml; +# A textual item displaying the current date and time +Item=Text,display=PresentDateTime,x=52,y=387,width=150,height=28,fg=DateTimeFG,font=Osd; +[Volume] +# This is the volume display +# Again, we specify an area to be able to draw items on it +Item=Background,x=10,y=10,width=20,height=200,bpp=4; +# A progressbar displaying the current volume. +Item=Progress,display=VolumeCurrent,x=10,y=10,width=20,height=200,bg=VolumeBG,fg=VolumeFG; + + +END_EN + +, <<END_DE + +Wie man textbasierte Skins erstellt +----------------------------------- + +Es ist wichtig, dass sie die Limitierungen des OSD Speichers verstehen. Wenn +zuviele Objekte mit zuvielen Farben definiert werden, dann wird VDR einen +Fehler ins Log schreiben und einige Bereiche werden nicht angezeigt werden. Bei +anderen Ausgabegeräten mag es sein, dass diese Limitierungen nicht zutreffen, +wenn Sie also ein Skin für ein anderes Gerät schreiben möchten, benutzen Sie +ruhig ein paar mehr Farben, aber denken Sie daran, dass VDR generell maximal +256 Farben pro Objekt verwalten kann. + +Ein Objekt ist als ein bestimmter Bereich definiert, der eine bestimmte +Farbpalette und Farbtiefe verwendet. Diese Objekte werden im Verlauf dieses +Dokuments "Backgrounds" genannt. Berechnen sie die Dimensionen dieser Bereiche +weise, denn überlappende oder übergroße Backgrounds führen zu einem Fehler. +Zusätzlich muss die Breite und Höhe jedes Backgrounds durch vier teilbar sein, +wenn eine DVB-Karte verwendet wird. + + +Die Erstellung eines Bildes +--------------------------- + +Ich habe mit gimp einige Beispielbilder erstellt, die Dinge auf dem Bildschirm +anzeigen, obwohl ich mit Grafik eigentlich recht wenig am Hut habe. Um einige +Hinweise zu geben, werde ich erklären wie ich diese Bilder erzeugt habe. + +Ich habe eine Vorlage für ein Kanaldisplay von einem Community-Mitglied +erhalten, dieses in drei Bereiche zerlegt, die jeweils komplett vom Hintergrund +gefüllt wurden. Nun habe ich das Bild so vergrößert, dass Breite und Höhe durch +vier teilbar sind. Um im mittleren Bereich etwas Transparenz zu erzeugen, habe +ich die Deckkraft der Bildebene auf 50% reduziert. Anschliessend habe ich alle +Bilder auf 14 Farben reduziert (Bild->Modus->Indiziert) (natürlich darf das +Bild nicht zu aufwändig sein, aber mit 14 Farben bekommt man schon schöne +Übergänge hin. Dann bleiben zwei Farben für Text und Symbole übrig, und das +ganze passt in einen 16-farb (4-bit) Background. Reduzieren sie die Azahl der +Farben entsprechend, wenn Sie beabsichtigen, mehr Vordergrundobjekte zu +zeichnen. Das Ergebnis habe ich als PNG gespeichert und in das Skin kopiert. + +Wenn sie beabsichtigen, xpm's zu nutzen, achten sie darauf dass VDR keine +benannten Farben beherrscht, es könnte also sein dass Bilder die gimp erzeugt +nicht sofort nutzbar sind. Die einzige benannte Farbe, die VDR beherrscht, ist +"None". + + +Das Format der Beschreibungsdatei +--------------------------------- + +Die Datei ist eine einfache Konfigurationsdatei, die aus Sektionen und Objekten +besteht. Kommentarzeilen können mit einem '#' eingeleitet werden. Leerzeilen +werden ignoriert. Eine Sektion ist von eckigen '[]' Klammern eingeschlossen. +Ein Objekt beginnt mit dem Text "Item=", gefolgt von der Art des Objekts. +Dahinter folgen Parameter für das Objekt, mit Komma getrennt. Die Zeile wird +durch ein Semikolon ';' abgeschlossen. + +Es ist sehr wichtig, dass sie den Zusammenhang zwischen Item und seinem +display-Parameter verstehen. Der display-Parameter gibt nicht nur an WAS +angezeigt wird, sondern auch OB es angezeigt wird. Ein Rechteck mit +display=PresentVPSTime wird nur angezeigt, wenn eine aktuelle VPS-Zeit gegeben +ist. Ein Text-Item mit display=PresentVPSTime verhält sich genauso, aber der +anzuzeigende Text durch die tatsächliche VPS-Zeit ersetzt. Wenn Text ein +Dollarzeichen enthält, wie in display=PresentVPSTime,text=VPS: $, dann wird +die VPS-Zeit an der Stelle des Dollarzeichens eingesetzt. + +Beispiel: + +# Description of the skin file +Item=Skin,name=Test,version=0.0.2; +[Channel] +# Dies ist die grosse Kanalanzeige +# Hintergrundbereich wo wir drauf zeichnen (so etwas MUSS angegeben werden, +# damit Objekte die darauf gezeichnet werden überhaupt sichtbar werden), mit +# Bild. Bpp=4 entspricht 16 Farben +Item=Background,path=channeltop.xpm,x=42,y=350,width=540,height=32,bpp=4; +# Ein zweiter Bereich unter dem ersten, wieder mit 16 Farben (macht 32 Farben +# insgesamt) +Item=Background,path=channel.png,x=48,y=382,width=528,height=84,bpp=4; +# Ein Text-Objekt welches die Kanalnummer und den -namen anzeigt (wenn +# vorhanden) +Item=Text,display=ChannelNumberName,x=50,y=355,width=250,height=28,fg=ChNumNameFG,font=Sml; +# Ein Text-Objekt welches das aktuelle Datum und die Zeit anzeigt. +Item=Text,display=PresentDateTime,x=52,y=387,width=150,height=28,fg=DateTimeFG,font=Osd; +[Volume] +# Dies ist die Lautstärkeanzeige +# Und wieder ein Bereich in dem wir Objekte zeichnen können (diesmal ohne Bild) +# Wird keine BG-Farbe angegeben, so wird transparent (unsichtbar) benutzt. +Item=Background,x=10,y=10,width=20,height=200,bpp=4; +# Eine Fortschrittsleiste welche die aktuelle Lautstärke anzeigt. +Item=Progress,display=VolumeCurrent,x=10,y=10,width=20,height=200,bg=VolumeBG,fg=VolumeFG; + + +END_DE + +); + +%SECTIONS = ( + "ChannelSmall" => [ + "The channel display. It displays the current programme and number only, ". + "together with some decoration. [UNUSED]", + + "Die Kanalanzeige, die nur den aktuellen Kanalnamen und die -nummer mit ". + "etwas Dekoration anzeigt. [UNGENUTZT]" + ], + + "Channel" => [ + "The channel display. It displays the current programme and number, ". + "together with the currently running programme and possibly a ". + "timebar, channel logo and some symbols.", + + "Die Kanalanzeige. Sie zeigt aktuellen Kanalnamen und -nummer, ". + "gemeinsam mit dem aktuellen Programm und möglicherweise eine ". + "Zeitleiste und ein Kanallogo (noch nicht implementiert)." + ], + + "Volume" => [ + "The volume display. It displays the volumebar and possibly a mute ". + "symbol, along with decorative items.", + + "Die Lautstärkeanzeige. Zeigt die Lautstärkeleiste und ". + "möglicherweise ein Mute-Symbol und etwas Dekoration." + ], + + "ReplayMode" => [ + "The replay modes display. Will be shown if only the replay mode ". + "symbol(s) shall be shown. This display can't contain a progress-bar.", + + "Die Wiedergabeanzeige. Wird angezeigt wenn nur der ". + "Wiedergabemodus gezeigt werden soll. Diese Anzeige kann keine ". + "Wiedergabeleiste enthalten." + ], + + "Replay" => [ + "The full replay display. It shows the title, time and length of an ". + "ongoing replay, together with a Progressbar and maybe even a replay logo", + + "" + ], + + "Message" => [ + "This display will be used only if there is no other display open, and ". + "VDR wants to display a message. Therefore this display shouldn't show ". + "much more than that message.", + + "" + ], + + "Menu" => [ + "The full menu. This is the all-round display used when showing a list of ". + "items or when showing something in detail (EPG-summary for example).", + + "" + ], +); + +%ITEMS = ( + "Background" => [ + "This adds a background area for the specific display. This area ". + "will be used to draw anything else, so you have to define a ". + "background for everything that will be drawn later on. You can ". + "define a background image for that area here, too. That picture ". + "has to be the same width and height as the area. If you don't use ". + "a background image, the area will be initialized with the bg color ". + "(default transparent). If an image is present, the background color will ". + "replace the color 0 in the image's palette, and the foreground ". + "color will replace color 1.", + + "" + ], + + "Text" => [ + "Draws plain text into the given area, using the given foreground ". + "color. Text has no background, only the pixels containing the foreground ". + "color will be drawn. If no width or height are given, the ". + "limits are the background areas. If you want to align the text, you need ". + "to specify at least the width. If this item is specified with an ". + "appropriate display parameter, and text is not given or contains a ". + "dollar sign, it will be substituted by the content given by the display ". + "parameter.", + + "" + ], + + "Scrolltext" => [ + "Draws a line-wrapped, scrollable text-area into the area, using the ". + "given foreground color. Behaves like Text otherwise. This item makes ". + "most sense for display=MenuText, display=PresentDescription and ". + "display=MenuRecording, since those are the only one's supporting ". + "the actual scrolling mechanism (inside the menu).", + + "" + ], + + "Image" => [ + "Draws the image from the parameter path into the area, substituting ". + "foreground and background colors like in Item=Background", + + "" + ], + + "Rectangle" => [ + "Draws a rectangle filled with the foreground color into the area.", + + "" + ], + + "Ellipse" => [ + "Draws an ellipse (or part of it) filled with the foreground color into ". + "the area. The parameter arc, if given, specifies which part of the ". + "ellipse will be drawn.", + + "" + ], + + "Slope" => [ + "Draws a slope (some kind of wave) (or part of it) filled with the ". + "foreground color into the area. The parameter arc, if give, specifies ". + "how the slope is formed.", + + "" + ], + + "Progress" => [ + "Draws a progress bar into the display. The \"shown\" fraction of the ". + "relevant display-parameter is drawn using the foreground color, while ". + "the \"rest\" fraction is drawn using the background color (if given). ". + "This item makes sense for display=PresentDuration, VolumeCurrent and ". + "ReplayTime", + + "" + ], + + "Logo" => [ + "Draws an image displaying some kind of logo into the area. The image ". + "file is given by the path- and type-parameters, together with the result ". + "from the corresponding display-parameter. This item makes sense for ". + "display=ChannelName (where the channel name is the filename), for ". + "display=ReplayMode (where the filename can be one of \"normal\", ". + "\"dvd\", \"vcd\", \"mp3\" and \"mplayer\" (more to come hopefully) ". + "and for display=Language (where the language code is [WILL BE] the ". + "filename. Behaves like Item=Image otherwise", + + "" + ], + + "Symbol" => [ + "Draws an On/Off-symbol into the area. The On-image is given by the path-". + "parameter, the Off-image with the altpath-parameter. Otherwise like ". + "Item=Image", + + "" + ], + + "MenuArea" => [ + "Specifies the area that is considered to be the central menu area ". + "(where the list of menu items is drawn). Note that this will not display ". + "anything yet, you have to give additional Text items to actually draw ". + "the list", + + "" + ], + + "MenuItem" => [ + "Specifies the area occupied by one item of the list which is displayed ". + "in the central menu area. The number of items that can be displayed is ". + "determined by the height of MenuArea and the height of this item. Note ". + "that this will not display anything yet, you have to give additional ". + "Text items to actually draw the list. Also note that the x- and y-". + "parameters (if given) are relative to the top-left corner of the ". + "MenuArea.", + + "" + ], + + "Scrollbar" => [ + "Draws a real scrollbar into the display. The \"seen\" and \"rest\" ". + "fractions are drawn using the background color, while the bar indicating ". + "the \"shown\" fraction and the current position, is drawn using the ". + "foreground color. This item makes sense for display=MenuText, ". + "PresentDescription and MenuRecording", + + "" + ], +); + +%ITEMPARAMS = ( + "Background" => "x, y, width, height, bpp, path, bg, fg", + "Text" => "display, x, y, width, height, fg, font, align", + "Scrolltext" => "display, x, y, width, height, fg, font", + "Image" => "display, x, y, width, height, bg, fg, path", + "Rectangle" => "display, x, y, width, height, fg", + "Ellipse" => "display, x, y, width, height, fg, arc", + "Slope" => "display, x, y, width, height, fg, arc", + "Progress" => "display, x, y, width, height, bg, fg", + "Logo" => "display, x, y, width, height, bg, fg, path, type", + "Symbol" => "display, x, y, width, height, bg, fg, path, altpath", + "MenuArea" => "x, y, width, height", + "MenuItem" => "x, y, width, height", + "Scrollbar" => "display, x, y, width, height, bg, fg", +); + +%DISPLAYS = ( + "DateTimeF" => [ + "The current date and time, formatted according to the format-parameter. ". + "To learn how the string can be formatted, please see man strftime.", + + "" + ], + + "DateTime" => [ + "The current date and time, pre-formatted like \"dd.mm. HH:MM\".", + + "" + ], + + "Date" => [ + "The current date, pre-formatted like \"dd.mm.\".", + + "" + ], + + "Time" => [ + "The current time, pre-formatted like \"HH:MM\".", + + "" + ], + + "ChannelNumberName" => [ + "A string containing the current channel number and name, where the ". + "channel number can be followed by a minus (while entering a channel) ". + "or where the channel name can be a channel group separator", + + "" + ], + + "ChannelNumber" => [ + "A string containing the current channel number, where the ". + "channel number can be followed by a minus (while entering a channel).", + + "" + ], + "ChannelName" => [ + "A string containing the current channel name, where the ". + "channel name can be a channel group separator. This also substitutes the ". + "channel logo (if present).", + + "" + ], + + "Language" => [ + "This substitutes a language logo, which will someday show the flag of ". + "the language currently in programme. Today only \"Audio 1\", \"Audio 2\" ". + "and \"Digital Audio\" are possible.", + + "" + ], + + "PresentDateTimeF" => [ + "The start date and time of the present event (in the channel display or ". + "while viewing EPG-details in the menu), formatted according to the ". + "format-parameter. ". + "To learn how the string can be formatted, please see man strftime.", + + "" + ], + + "PresentStartTime" => [ + "The start time of the present event (in the channel display or ". + "while viewing EPG-details in the menu), formatted like \"HH:MM\"", + + "" + ], + + "PresentDate" => [ + "The start date of the present event (in the channel display or ". + "while viewing EPG-details in the menu), formatted like \"dd.mm.\"", + + "" + ], + + "PresentVPSTime" => [ + "The VPS start time of the present event (in the channel display or ". + "while viewing EPG-details in the menu), formatted like \"HH:MM\", ". + "if present and different from the normal start time.", + + "" + ], + + "PresentEndTime" => [ + "The end time of the present event (in the channel display or ". + "while viewing EPG-details in the menu), formatted like \"HH:MM\"", + + "" + ], + + "PresentDuration" => [ + "The duration time of the present event (in the channel display or ". + "while viewing EPG-details in the menu), formatted like \"HH:MM\". This ". + "also substitutes the progress bar (timebar).", + + "" + ], + + "PresentVPS" => [ + "Substitutes a symbol, which shows whether the channel broadcasting ". + "the present event is a VPS-channel", + + "" + ], + + "PresentRunning" => [ + "Substitutes a symbol, which shows whether the present event is running.", + + "" + ], + + "PresentTimer" => [ + "Substitutes a symbol, which shows whether the present event is scheduled ". + "for recording.", + + "" + ], + + "PresentTitle" => [ + "The title of the currently displayed event.", + + "" + ], + + "PresentShortText" => [ + "The short text (or episode name) of the currently displayed event.", + + "" + ], + + "PresentDescription" => [ + "The long description of the currently displayed event. Makes most sense ". + "when used when displaying an EPG-detail in the menu, inside a Scrolltext.", + + "" + ], + + "FollowingStartTime" => [ + "The start time of the following event (in the channel display only), ". + "formatted like \"HH:MM\"", + + "" + ], + + "FollowingEndTime" => [ + "The end time of the following event (in the channel display only), ". + "formatted like \"HH:MM\"", + + "" + ], + + "FollowingDuration" => [ + "The duration time of the following event (in the channel display only), ". + "formatted like \"HH:MM\".", + + "" + ], + + "FollowingTitle" => [ + "The title of the following event.", + + "" + ], + + "FollowingShortText" => [ + "The short text (or episode name) of the following event.", + + "" + ], +); + +%DISPLAYPARAMS = ( + "DateTimeF" => "format", + "PresentDateTimeF" => "format" +); + +%DISPLAYSUBST = ( + "DateTimeF" => "text", + "DateTime" => "text", + "Date" => "text", + "Time" => "text", + "ChannelNumberName" => "text", + "ChannelNumber" => "text", + "ChannelName" => "text, path", + "Language" => "path", + "PresentDateTimeF" => "text", + "PresentStartTime" => "text", + "PresentDate" => "text", + "PresentVPSTime" => "text", + "PresentEndTime" => "text", + "PresentDuration" => "text, progress", + "PresentVPS" => "path", + "PresentRunning" => "path", + "PresentTimer" => "path", + "PresentTitle" => "text", + "PresentShortText" => "text", + "PresentDescription" => "text", + "FollowingStartTime" => "text", + "FollowingEndTime" => "text", + "FollowingDuration" => "text, progress", + "FollowingTitle" => "text", + "FollowingShortText" => "text", +); + +return 1; diff --git a/contrib/list_items.pl b/contrib/list_items.pl new file mode 100755 index 0000000..ad0fde9 --- /dev/null +++ b/contrib/list_items.pl @@ -0,0 +1,173 @@ +#!/usr/bin/perl + +$ITEMFILE="common.h"; +$PARMFILE="data.h"; + +sub printo { + my $text = shift; + my $len = shift; + print sprintf("%.*s", $len, $text); + if (length($text) < $len) { + print " " x ($len - length($text)); + } +} + +sub printa { + my $text = shift; + my $len = shift; + + my @words = split(/\s+/, $text); + my $offset = $len; + while (@words) { + $word = shift(@words); + if ($offset + length($word) + 1 >= 80) { + print "\n"; + print " " x $len; + $offset = $len; + } + print "$word "; + $offset += length($word) + 1; + } +} + +sub i18n { + my $text = shift; + if ($lang != 0) { + return $TRANS{$text}->[$lang - 1]; + } + return $text; +} + +require 'contrib/items.doc'; + +$lang = "en"; +if (defined($ARGV[0])) { + $lang = $ARGV[0]; +} +$lang = $LANGS{$lang}; + +print $INTRO[$lang]; + +$where = 0; +$until = ""; + +open DAT, "<$ITEMFILE" or die "Couldn't open $ITEMFILE: $!"; +while (defined($_ = <DAT>)) { + chomp; + + /^enum\s+eSkinSection/ and do { + $where = 1; + $until = "__SECTION_COUNT__"; + print i18n("Known Sections")."\n"; + print "-" x length(i18n("Known Sections")); + print "\n\n"; + next; + }; + + /^enum\s+eSkinItem/ and do { + $where = 2; + $until = "__ITEM_COUNT__"; + print i18n("Known drawable Items")."\n"; + print "-" x length(i18n("Known drawable Items")); + print "\n\n"; + next; + }; + + /^enum\s+eSkinDisplay/ and do { + $where = 3; + $until = "__DISPLAY_COUNT__"; + print i18n("Known Display-Items")."\n"; + print "-" x length(i18n("Known Display-Items")); + print "\n\n"; + next; + }; + + (length($until) && /$until/) and do { + $where = 0; + $until = ""; + print "\n"; + next; + }; + + if ($where == 1) { + next if /sectionSkin/; + /section([\w]+)/ and do { + $what = $1; + printo i18n("Section:"), 15; + print "[$what]\n"; + printo i18n("Description:"), 15; + printa $SECTIONS{$what}->[$lang], 15; + print "\n\n"; + }; + } + + if ($where == 2) { + next if /itemUnknown/; + next if /itemSkin/; + /item([\w]+)/ and do { + $what = $1; + printo i18n("Item:"), 15; + print "Item=$what\n"; + printo i18n("Description:"), 15; + printa $ITEMS{$what}->[$lang], 15; + print "\n"; + printo i18n("Parameters:"), 15; + printa $ITEMPARAMS{$what}, 15; + print "\n\n"; + }; + } + + if ($where == 3) { + next if /displayAlways/; + /display([\w]+)/ and do { + $what = $1; + printo i18n("Display:"), 15; + print "display=$what\n"; + printo i18n("Description:"), 15; + printa $DISPLAYS{$what}->[$lang], 15; + print "\n"; + printo i18n("Parameters:"), 15; + printa $DISPLAYPARAMS{$what}, 15; + print "\n"; + printo i18n("Substitutes:"), 15; + printa $DISPLAYSUBST{$what}, 15; + print "\n\n"; + }; + } +} +close DAT; + +open DAT, "<$PARMFILE" or die "Couldn't open $PARMFILE: $!"; +while (defined($_ = <DAT>)) { + chomp; + + /eSkinItem\s+mItem;/ and do { + $where = 1; + $until = "protected:"; + print i18n("Known Parameters")."\n"; + print "-" x length(i18n("Known Parameters")); + print "\n\n"; + next; + }; + + (length($until) && /$until/) and do { + $where = 0; + $until = ""; + next; + }; + + if ($where == 1) { + next if /mItem;\s*$/; + /m([\w]+);\s*$/ and do { + $what = lc($1); + printo i18n("Parameter:"), 15; + print "$what\n"; + printo i18n("Description:"), 15; + print "\n"; + printo i18n("Default:"), 15; + print "\n\n"; + }; + } +} +close DAT; + @@ -1,5 +1,5 @@ /* - * $Id: data.c,v 1.18 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: data.c,v 1.19 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "data.h" @@ -23,27 +23,21 @@ cText2SkinItem::~cText2SkinItem() { } bool cText2SkinItem::Parse(const char *Text) { - char *text = strdup(Text); - char *ptr = text; + const char *text = Text; + const char *ptr = text; + bool res = false; // check if this is an item if (ParseVar(ptr, "Item", &mItem)) { - if (mItem == itemSkin) { // the Skin item - if (!ParseVar(ptr, "name", mName) || !ParseVar(ptr, "version", mVersion)){ - esyslog("ERROR: text2skin: Item=Skin is missing the name and/or version parameter(s)"); - return false; - } - } - - if (mItem != itemUnknown) { + if (mItem == itemSkin && (!ParseVar(ptr, "name", mName) || !ParseVar(ptr, "version", mVersion))) + esyslog("ERROR: text2skin: Item=Skin is missing the name and/or version parameter(s)"); + else if (mItem != itemUnknown) { ParseItem(ptr); - return true; + res = true; } } else esyslog("ERROR: text2skin: unknown item in skin"); - - // fall through - return false; + return res; } bool cText2SkinItem::ParseItem(const char *Text) { @@ -74,6 +68,11 @@ cText2SkinData::cText2SkinData(const char *Skin): cText2SkinFile(Skin) { } cText2SkinData::~cText2SkinData() { + for (int i = 0; i < __SECTION_COUNT__; ++i) { + for (int j = 0; j < (int)mSections[i].size(); ++j) + delete mSections[i][j]; + mSections[i].clear(); + } } bool cText2SkinData::Parse(const char *Text) { diff --git a/SKINS.de b/deprecated/SKINS.de index 2e1cc8e..2e1cc8e 100644 --- a/SKINS.de +++ b/deprecated/SKINS.de @@ -1,5 +1,5 @@ /* - * $Id: display.c,v 1.16 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: display.c,v 1.17 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "render.h" @@ -300,8 +300,8 @@ void cText2SkinDisplayMenu::SetItem(const char *Text, int Index, bool Current, b if (!Tab(i + 1)) break; } - SetEditableWidth(mRender->GetEditableWidth(item, Current)); mRender->Lock(); + SetEditableWidth(mRender->GetEditableWidth(item, Current)); if ((int)mRender->mMenuItems.size() <= Index) { mRender->mMenuItems.push_back(item); mDirty = true; @@ -1,5 +1,5 @@ /* - * $Id: i18n.c,v 1.6 2004/06/12 21:16:18 lordjaxom Exp $ + * $Id: i18n.c,v 1.7 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "i18n.h" @@ -54,6 +54,11 @@ cText2SkinI18n::cText2SkinI18n(const char *Skin): cText2SkinFile(Skin) { } cText2SkinI18n::~cText2SkinI18n() { + for (int i = 0; mPhrases[i][0]; ++i) { + for (int j = 0; j < I18nNumLanguages; ++j) + free((void*)mPhrases[i][j]); + } + free(mPhrases); } bool cText2SkinI18n::Parse(const char *Text) { @@ -66,17 +71,18 @@ bool cText2SkinI18n::Parse(const char *Text) { memset(&p, 0, sizeof(tI18nPhrase)); Text += 17; - for (i = 0; i < I18nNumLanguages; ++i) { char *langs = strdup(I18nLanguageCode(i)); char *ptr = langs, *ep; string text; - p[i] = ""; + p[i] = strdup(""); do { if ((ep = strchr(ptr, ',')) != NULL) *ep = '\0'; - if (ParseVar(Text, ptr, text)) + if (ParseVar(Text, ptr, text)) { + free((void*)p[i]); p[i] = strdup(text.c_str()); + } ptr = ep + 1; } while (ep != NULL); free(langs); @@ -1,5 +1,5 @@ /* - * $Id: loader.c,v 1.10 2004/06/11 15:01:58 lordjaxom Exp $ + * $Id: loader.c,v 1.11 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "loader.h" @@ -74,7 +74,6 @@ cText2SkinLoader::~cText2SkinLoader() { delete mData; delete mI18n; delete mTheme; - // mDescription is part of mData } cSkinDisplayChannel *cText2SkinLoader::DisplayChannel(bool WithInfo) { @@ -1,5 +1,5 @@ /* - * $Id: render.c,v 1.30 2004/06/13 18:19:18 lordjaxom Exp $ + * $Id: render.c,v 1.31 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "render.h" @@ -48,8 +48,6 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio mActive = false; mUpdateIn = 0; - cText2SkinBitmap::FlushCache(); - cText2SkinData::tIterator it = mData->First(mSection); for (; it != mData->Last(mSection); ++it) { if ((*it)->Item() == itemBackground) { @@ -90,26 +88,25 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio } esyslog("ERROR: text2skin: OSD provider can't handle skin: %s\n", emsg); } - Start(); } cText2SkinRender::~cText2SkinRender() { if (mActive) { mActive = false; - TriggerUpdate(); + Flush(); Cancel(3); } delete mScroller; delete mOsd; + cText2SkinBitmap::FlushCache(); } void cText2SkinRender::Action(void) { mActive = true; Lock(); while (mActive) { - bool res = true; - if (mUpdateIn) res = mDoUpdate.TimedWait(mMutex, mUpdateIn); + if (mUpdateIn) mDoUpdate.TimedWait(mMutex, mUpdateIn); else mDoUpdate.Wait(mMutex); if (!mActive) break; // fall out if thread to be stopped @@ -121,6 +118,9 @@ void cText2SkinRender::Action(void) { } void cText2SkinRender::Update(void) { + if (mScroller && !mMenuScroll) + mOsd->SaveRegion(mScroller->Left(), mScroller->Top(), mScroller->Left() + mScroller->Width() - 1, mScroller->Top() + mScroller->Height() - 1); + cText2SkinData::tIterator it = mData->First(mSection); for (; it != mData->Last(mSection); ++it) { switch ((*it)->Display()) { @@ -362,12 +362,30 @@ void cText2SkinRender::DrawMark(const POINT &Pos, const SIZE &Size, bool Start, } } -void cText2SkinRender::DrawScrollText(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align) { +void cText2SkinRender::DrawScrolltext(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align) { if (mScroller == NULL) mScroller = new cTextScroller(mOsd, Pos.x, Pos.y, Size.w, Size.h, Text.c_str(), Font, Fg ? *Fg : 0, clrTransparent); else if (mMenuScroll) { mScroller->Scroll(mMenuScrollUp, mMenuScrollPage); mMenuScroll = false; + } else + mOsd->RestoreRegion(); +} + +void cText2SkinRender::DrawScrollbar(const POINT &Pos, const SIZE &Size, int Offset, int Shown, int Total, const tColor *Bg, const tColor *Fg) { + DrawRectangle(Pos, Size, Bg); + if (Size.h > Size.w) { + POINT sp = Pos; + SIZE ss = Size; + sp.y += Size.h * Offset / Total; + ss.h -= Size.h * (Shown - 2) / Total; + DrawRectangle(sp, ss, Fg); + } else { + POINT sp = Pos; + SIZE ss = Size; + sp.x += Size.w * Offset / Total; + ss.w -= Size.w * (Shown - 2) / Total; + DrawRectangle(sp, ss, Fg); } } @@ -382,14 +400,15 @@ void cText2SkinRender::DisplayItem(cText2SkinItem *Item, const ItemData *Data) { DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, Data->text), Item->Font(), Item->Align()); break; case itemScrolltext: - DrawScrollText(Item->Pos(), Item->Size(), ItemFg(Item), Data->text, Item->Font(), Item->Align()); + DrawScrolltext(Item->Pos(), Item->Size(), ItemFg(Item), Data->text, Item->Font(), Item->Align()); break; case itemImage: DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Alpha(), Item->Path()); break; case itemLogo: case itemSymbol: - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Alpha(), Data->path); + if (Data->path != "") + DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Alpha(), Data->path); break; case itemRectangle: DrawRectangle(Item->Pos(), Item->Size(), ItemFg(Item)); @@ -403,6 +422,8 @@ void cText2SkinRender::DisplayItem(cText2SkinItem *Item, const ItemData *Data) { case itemProgress: DrawProgressbar(Item->Pos(), Item->Size(), Data->current, Data->total, ItemBg(Item), ItemFg(Item), Data->marks); break; + case itemScrollbar: + DrawScrollbar(Item->Pos(), Item->Size(), Data->current, Data->shown, Data->total, ItemBg(Item), ItemFg(Item)); default: break; } @@ -710,11 +731,10 @@ void cText2SkinRender::DisplayVolume(cText2SkinItem *Item) { } void cText2SkinRender::DisplayMuteIcon(cText2SkinItem *Item) { - if (mVolumeMute) { - ItemData data; - data.path = Item->Path(); + ItemData data; + data.path = mVolumeMute ? Item->Path() : Item->AltPath(); + if (data.path != "") DisplayItem(Item, &data); - } } void cText2SkinRender::DisplayReplayTime(cText2SkinItem *Item) { @@ -841,8 +861,15 @@ void cText2SkinRender::DisplayMenuText(cText2SkinItem *Item) { default: break; } - if (data.text != "") + if (data.text != "") { + // HACK: make sure the scroller exists! + if (mScroller) { + data.current = mScroller->Offset(); + data.shown = mScroller->Shown(); + data.total = mScroller->Total(); + } DisplayItem(Item, &data); + } } void cText2SkinRender::DisplayMenuScrollIcon(cText2SkinItem *Item) { @@ -1,5 +1,5 @@ /* - * $Id: render.h,v 1.21 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: render.h,v 1.22 2004/06/16 18:46:50 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_RENDER_H @@ -37,6 +37,7 @@ private: string text; string path; int current; + int shown; int total; const cMarks *marks; ItemData(void) { marks = NULL; } @@ -113,7 +114,8 @@ protected: void DrawSlope(const POINT &Pos, const SIZE &Size, const tColor *Fg, int Arc); void DrawProgressbar(const POINT &Pos, const SIZE &Size, int Current, int Total, const tColor *Fg, const tColor *Bg, const cMarks *Marks = NULL); void DrawMark(const POINT &Pos, const SIZE &Size, bool Start, bool Current, bool Horizontal); - void DrawScrollText(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align); + void DrawScrolltext(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align); + void DrawScrollbar(const POINT &Pos, const SIZE &Size, int Offset, int Shown, int Total, const tColor *Bg, const tColor *Fg); // displays a full item void DisplayItem(cText2SkinItem *Item, const ItemData *Data = NULL); @@ -149,14 +151,13 @@ protected: tColor *ItemFg(cText2SkinItem *Item); tColor *ItemBg(cText2SkinItem *Item); int GetEditableWidth(MenuItem Item, bool Current); - void TriggerUpdate(void) { mDoUpdate.Broadcast(); } void Update(void); public: cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Section); virtual ~cText2SkinRender(); - void Flush(void) { TriggerUpdate(); } + void Flush(void) { Lock(); mDoUpdate.Broadcast(); Unlock(); } }; #endif // VDR_TEXT2SKIN_RENDER_H diff --git a/text2skin.c b/text2skin.c index 8ded7a4..c974236 100644 --- a/text2skin.c +++ b/text2skin.c @@ -3,7 +3,7 @@ * * See the README file for copyright information and how to reach the author. * - * $Id: text2skin.c,v 1.19 2004/06/13 18:20:17 lordjaxom Exp $ + * $Id: text2skin.c,v 1.20 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "text2skin.h" @@ -11,7 +11,7 @@ #include "i18n.h" #include "loader.h" -const char *cText2SkinPlugin::VERSION = "0.0.4"; +const char *cText2SkinPlugin::VERSION = "0.0.5"; const char *cText2SkinPlugin::THEMEVERSION = "0.0.2"; const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins"; @@ -1,5 +1,5 @@ /* - * $Id: theme.c,v 1.1 2004/06/02 20:43:05 lordjaxom Exp $ + * $Id: theme.c,v 1.2 2004/06/16 18:46:50 lordjaxom Exp $ */ #include "theme.h" #include <vdr/osd.h> @@ -17,9 +17,9 @@ bool cText2SkinTheme::Parse(const char *Text) { if (strncmp(Text, "Item=Color,", 11) == 0) { Text += 11; string name; - tColor *value; + tColor value; if (ParseVar(Text, "name", name) && ParseVar(Text, "default", &value)) { - mMap[name] = mTheme.AddColor(name.c_str(), *value); + mMap[name] = mTheme.AddColor(name.c_str(), value); result = true; } else esyslog("ERROR: text2skin: Parameters name and default must be present\n"); |