summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY16
-rw-r--r--Makefile12
-rw-r--r--README19
-rw-r--r--bitmap.c79
-rw-r--r--bitmap.h12
-rw-r--r--cache.h11
-rw-r--r--common.c9
-rw-r--r--common.h11
-rw-r--r--contrib/items.doc620
-rwxr-xr-xcontrib/list_items.pl173
-rw-r--r--data.c29
-rw-r--r--deprecated/SKINS (renamed from SKINS)0
-rw-r--r--deprecated/SKINS.de (renamed from SKINS.de)0
-rw-r--r--display.c4
-rw-r--r--i18n.c14
-rw-r--r--loader.c3
-rw-r--r--render.c57
-rw-r--r--render.h9
-rw-r--r--text2skin.c4
-rw-r--r--theme.c6
20 files changed, 989 insertions, 99 deletions
diff --git a/HISTORY b/HISTORY
index 243fedb..c4c1520 100644
--- a/HISTORY
+++ b/HISTORY
@@ -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
diff --git a/Makefile b/Makefile
index ddf7267..3d35506 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/README b/README
index 16c11f3..1faba7d 100644
--- a/README
+++ b/README
@@ -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.
diff --git a/bitmap.c b/bitmap.c
index 9e7c02b..3aa91a5 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -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);
diff --git a/bitmap.h b/bitmap.h
index ac0f0e4..44a3e1b 100644
--- a/bitmap.h
+++ b/bitmap.h
@@ -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
diff --git a/cache.h b/cache.h
index 11b7d79..1fd0811 100644
--- a/cache.h
+++ b/cache.h
@@ -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) {
diff --git a/common.c b/common.c
index 4643b9f..5ec7970 100644
--- a/common.c
+++ b/common.c
@@ -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;
diff --git a/common.h b/common.h
index 64163d9..c1a0436 100644
--- a/common.h
+++ b/common.h
@@ -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;
+
diff --git a/data.c b/data.c
index 8e44dae..a801fb4 100644
--- a/data.c
+++ b/data.c
@@ -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 b/deprecated/SKINS
index da5ea09..da5ea09 100644
--- a/SKINS
+++ b/deprecated/SKINS
diff --git a/SKINS.de b/deprecated/SKINS.de
index 2e1cc8e..2e1cc8e 100644
--- a/SKINS.de
+++ b/deprecated/SKINS.de
diff --git a/display.c b/display.c
index 50f042d..43a6786 100644
--- a/display.c
+++ b/display.c
@@ -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;
diff --git a/i18n.c b/i18n.c
index 4493b3b..affc848 100644
--- a/i18n.c
+++ b/i18n.c
@@ -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);
diff --git a/loader.c b/loader.c
index d2218da..3bbb5ec 100644
--- a/loader.c
+++ b/loader.c
@@ -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) {
diff --git a/render.c b/render.c
index 03ad7eb..e778dfc 100644
--- a/render.c
+++ b/render.c
@@ -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) {
diff --git a/render.h b/render.h
index 2433dbf..b47db56 100644
--- a/render.h
+++ b/render.h
@@ -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";
diff --git a/theme.c b/theme.c
index c76166d..706a15d 100644
--- a/theme.c
+++ b/theme.c
@@ -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");