diff options
author | lordjaxom <lordjaxom> | 2004-06-25 17:54:38 +0000 |
---|---|---|
committer | lordjaxom <lordjaxom> | 2004-06-25 17:54:38 +0000 |
commit | f2a4ea2dc8c0d915e0f2af6f4ec1a228e1e94453 (patch) | |
tree | e071f932913f57fa464a7e3cdd5cf774c3a629e5 | |
parent | de602ae6486b181ec081749a510cfcf15c71c817 (diff) | |
download | vdr-plugin-text2skin-f2a4ea2dc8c0d915e0f2af6f4ec1a228e1e94453.tar.gz vdr-plugin-text2skin-f2a4ea2dc8c0d915e0f2af6f4ec1a228e1e94453.tar.bz2 |
- on devices capable of full-color OSD, bpp's have no meaning anymorev0.0.7
(but will still work like usual). On such devices, a full-screen 8-bit
OSD will be used
- new display-item "PresentTextDescription" displays combined
ShortText/Description
- displaying replay symbols only if information is actually available
- exchanged x, y, width, height with x1, y1, x2, y2 coordinates
(skin version is now 0.0.3)
- coordinates may be negative to respect dynamic OSD settings
(negative coordinates give pixels from the right or bottom edge)
- added base parameter to Skin item to be able to use full screen in absolute
mode
- added a script to convert 0.0.2 skins to 0.0.3
- added parsing quoted texts (path="Bla.jpg" etc. will work correctly now)
- fixed translator to escape the dollar sign
- fixed display of scrollbar (REALLY!)
- fixed linkage of libMagick++
-rw-r--r-- | HISTORY | 20 | ||||
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | README.de | 10 | ||||
-rw-r--r-- | common.c | 41 | ||||
-rw-r--r-- | common.h | 19 | ||||
-rw-r--r-- | contrib/items.doc | 22 | ||||
-rwxr-xr-x | contrib/list_items.pl | 40 | ||||
-rwxr-xr-x | contrib/skin_to_003.pl | 23 | ||||
-rwxr-xr-x | contrib/transform.pl | 54 | ||||
-rw-r--r-- | data.c | 39 | ||||
-rw-r--r-- | data.h | 23 | ||||
-rw-r--r-- | display.c | 6 | ||||
-rw-r--r-- | i18n.c | 7 | ||||
-rw-r--r-- | i18n.h | 4 | ||||
-rw-r--r-- | loader.c | 6 | ||||
-rw-r--r-- | render.c | 234 | ||||
-rw-r--r-- | render.h | 11 | ||||
-rw-r--r-- | text2skin.c | 6 |
19 files changed, 427 insertions, 155 deletions
@@ -1,6 +1,26 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2004-06-25: Version 0.0.7 + +- on devices capable of full-color OSD, bpp's have no meaning anymore + (but will still work like usual). On such devices, a full-screen 8-bit + OSD will be used +- new display-item "PresentTextDescription" displays combined + ShortText/Description +- displaying replay symbols only if information is actually available +- exchanged x, y, width, height with x1, y1, x2, y2 coordinates + (skin version is now 0.0.3) +- coordinates may be negative to respect dynamic OSD settings + (negative coordinates give pixels from the right or bottom edge) +- added base parameter to Skin item to be able to use full screen in absolute + mode +- added a script to convert 0.0.2 skins to 0.0.3 +- added parsing quoted texts (path="Bla.jpg" etc. will work correctly now) +- fixed translator to escape the dollar sign +- fixed display of scrollbar (REALLY!) +- fixed linkage of libMagick++ + 2004-06-18: Version 0.0.6 - reimplemented image cache (fixes segfaults and speeds up image loading) @@ -9,7 +9,7 @@ HAVE_IMAGEMAGICK=1 # DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING # ------------------------------------------------------------- # -# $Id: Makefile,v 1.12 2004/06/18 16:08:11 lordjaxom Exp $ +# $Id: Makefile,v 1.14 2004/06/24 18:37:30 lordjaxom Exp $ # # The official name of this plugin. @@ -34,10 +34,6 @@ VDRDIR = ../../.. LIBDIR = ../../lib TMPDIR = /tmp -### Allow user defined options to overwrite defaults: - --include $(VDRDIR)/Make.config - ### The version number of VDR (taken from VDR's "config.h"): VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g') @@ -49,6 +45,8 @@ PACKAGE = vdr-$(ARCHIVE) ### Includes and Defines (add further entries here): +-include $(VDRDIR)/Make.config + ifdef HAVE_IMLIB2 DEFINES += -DHAVE_IMLIB2 LIBS += -lImlib2 @@ -56,7 +54,8 @@ endif ifdef HAVE_IMAGEMAGICK DEFINES += -DHAVE_IMAGEMAGICK - LIBS += -lMagick -lMagick++ +# LIBS += -lMagick -lMagick++ + LIBS += $(shell Magick++-config --ldflags --libs) endif ifdef DEBUG @@ -67,6 +66,10 @@ INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' +### Allow user defined options to overwrite defaults: + +-include $(VDRDIR)/Make.config + ### The object files (add further files here): OBJS = $(PLUGIN).o loader.o data.o display.o render.o common.o bitmap.o \ @@ -85,7 +85,7 @@ folder. Inside that "plugins" folder, create a subfolder called "text2skin". Inside "text2skin", create one folder for each skin. These skin-folders must have the 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: +carrying the same name, but ending in ".skin". Example (the Skin is called myskin): /video0/plugins/text2skin/ @@ -87,11 +87,13 @@ Innerhalb dieses "plugins" Ordners erstellen Sie einen Ordner namens "text2skin". In "text2skin" erstellen Sie einen weiteren Ordner pro Skin. Diese Skin-Ordner müssen den gleichen Namen tragen wie die Skins in ihnen. Jedes Skin muss mindestens eine Datei enthalten, die denselben Namen trägt, aber mit -der Endung ".skin". Beispiel: +der Endung ".skin". -/video0/plugins/text2skin/demo/demo.skin -/video0/plugins/text2skin/skin2/skin2.skin -... +Beispiel (das Skin heisst myskin): +/video0/plugins/text2skin/ +/video0/plugins/text2skin/myskin/ +/video0/plugins/text2skin/msykin/msykin.skin +/video0/plugins/text2skin/myskin/channeldisplay.png Die anderen Dateien in dem Skin-Ordner sind weitere Beschreibungsdateien (für Farben und Übersetzungen) sowie Bilder, Logos und Symbole. @@ -1,5 +1,5 @@ /* - * $Id: common.c,v 1.10 2004/06/16 18:46:50 lordjaxom Exp $ + * $Id: common.c,v 1.12 2004/06/25 17:51:34 lordjaxom Exp $ */ #include "data.h" @@ -29,10 +29,13 @@ const string DisplayNames[__DISPLAY_COUNT__] = "MessageStatus", "MessageInfo", "MessageWarning", "MessageError", "MenuTitle", "MenuRed", "MenuGreen", "MenuYellow", "MenuBlue", "MenuText", "MenuRecording", "MenuScrollUp", "MenuScrollDown", "MenuItems", - "MenuCurrent", "MenuGroups", "ReplayMode" }; + "MenuCurrent", "MenuGroups", "ReplayMode", "PresentTextDescription" }; const string ReplayNames[__REPLAY_COUNT__] = { "", "normal", "mp3", "mplayer", "dvd", "vcd" }; + +const string BaseNames[__BASE_COUNT__] = + { "rel", "abs" }; const char *SkinPath(void) { return cPlugin::ConfigDirectory(PLUGIN_NAME_I18N); @@ -123,8 +126,13 @@ bool ParseVar(const char *Text, const char *Name, string &Value){ --ptr1; ptr1 += strlen(str); if ((ptr2 = strchr(ptr1, ',')) || (ptr2 = strchr(ptr1, ';'))) { + int pos; Value = ptr1; Value.erase(ptr2 - ptr1); + if (Value[0] == '"') + SkipQuotes(Value); + while ((pos = Value.find('$')) != -1) + Value.replace(pos, 1, "{*}"); res = true; } } @@ -166,3 +174,32 @@ bool ParseVar(const char *Text, const char *Name, const cFont **Value) { return false; } +bool ParseVar(const char *Text, const char *Name, eBaseCoordinate *Value) { + string value; + if (ParseVar(Text, Name, value)) { + int i; + for (i = 0; i < __BASE_COUNT__; ++i) { + if (BaseNames[i] == value) { + *Value = (eBaseCoordinate)i; + return true; + } + if (i == __BASE_COUNT__) + esyslog("ERROR: text2skin: unknown coordinate base %s", value.c_str()); + } + } + return false; +} + +void SkipQuotes(string &Value) { + char quote = Value[0]; + int i; + Value.erase(0, 1); + for (i = 0; i < (int)Value.length() && Value[i] != quote; ++i) { + if (Value[i] == '\\') + Value.erase(i, 1); + } + if (Value[i] == quote) + Value.erase(i, 1); + else + esyslog("ERROR: text2skin: missing closing %c", quote); +} @@ -1,5 +1,5 @@ /* - * $Id: common.h,v 1.10 2004/06/16 18:46:50 lordjaxom Exp $ + * $Id: common.h,v 1.12 2004/06/25 17:51:34 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_COMMON_H @@ -16,8 +16,12 @@ using std::map; #ifdef DEBUG # define Dprintf(x...) fprintf(stderr, x); +# define Dbench(x) time_t bench_##x = time_ms(); +# define Ddiff(x) time_ms() - bench_##x #else # define Dprintf(x...) +# define Dbench(x) +# define Ddiff(x) #endif // sections and items known by skin files @@ -117,6 +121,7 @@ enum eSkinDisplay { displayMenuCurrent, // exc: text (TODO: logo?) displayMenuGroups, // exc: text (TODO: logo?) displayReplayMode, // exc: text, logo + displayPresentTextDescription, // exc: text __DISPLAY_COUNT__ }; @@ -129,21 +134,30 @@ enum eReplayMode { replayVCD, __REPLAY_COUNT__ }; + +enum eBaseCoordinate { + baseRelative, + baseAbsolute, + __BASE_COUNT__ +}; extern const string SectionNames[__SECTION_COUNT__]; extern const string ItemNames[__ITEM_COUNT__]; extern const string DisplayNames[__DISPLAY_COUNT__]; extern const string ReplayNames[__REPLAY_COUNT__]; +extern const string BaseNames[__BASE_COUNT__]; // geometrical structures struct POINT { int x, y; + POINT(int _x = 0, int _y = 0) { x = _x; y = _y; } POINT &operator+=(const POINT &pt) { x += pt.x; y += pt.y; return *this; } }; struct SIZE { int w, h; + SIZE(int _w = 0, int _h = 0) { w = _w; h = _h; } }; // class forwards @@ -164,5 +178,8 @@ 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, eTextAlignment *Value); +bool ParseVar(const char *Text, const char *Name, eBaseCoordinate *Value); + +void SkipQuotes(string &Value); #endif // VDR_TEXT2SKIN_COMMON_H diff --git a/contrib/items.doc b/contrib/items.doc index 716f4a2..518eb30 100644 --- a/contrib/items.doc +++ b/contrib/items.doc @@ -24,6 +24,14 @@ This is the documentation to the Text2Skin file-format (version 0.0.2). How To create text-based skins ------------------------------ +If you are using an output driver capable of displaying a full-screen 256 color +OSD (i.e. an upgraded DVB-card, or plugins like SoftDevice), the plugin will +detect this and make use of the full-screen area. If you intend to write a skin +that will only work on such a device, you can skip the section concerning +backgrounds. However, if you plan to make the skin usable on a usual DVB-card, +even if you don't use one yourself, you should read the following sections +carefully. + 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 @@ -89,6 +97,8 @@ Item=Skin,name=Test,version=0.0.2; # 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 +# APPENDIX: Bpp is useless ff the plugin detects a fullscreen-capable Output +# device. In that case, this item just draws the background image 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) @@ -113,6 +123,15 @@ END_EN Wie man textbasierte Skins erstellt ----------------------------------- +Wenn Sie einen Ausgabetreiber nutzen, der fähig ist, ein 256-Farben Vollbild +als OSD darzustellen (z.B. eine aufgerüstete DVB-Karte oder Plugins wie +SoftDevice), wird das Plugin dies erkennen und die volle Bildfläche nutzen. +Wenn Sie beabsichtigen, ein Skin zu schreiben, welches nur auf solchen Geräten +funktionieren soll, können Sie die folgenden Sektionen, die die Backgrounds +betreffen überspringen. Wenn Sie jedoch planen Ihr Skin auch auf normalen +DVB-Karten nutzbar zu machen, auch wenn Sie selbst eine solche nicht nutzen, +sollten Sie die folgenden Abschnitte aufmerksam lesen. + 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 @@ -182,6 +201,9 @@ Item=Skin,name=Test,version=0.0.2; # 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 +# ERGÄNZUNG: Wenn das Plugin eine Fullscreen fähige Ausgabeschnittstelle +# erkennt, ist bpp bedeutungslos, und der Background wird nur fürs Bild +# gebraucht 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) diff --git a/contrib/list_items.pl b/contrib/list_items.pl index ad0fde9..a47803f 100755 --- a/contrib/list_items.pl +++ b/contrib/list_items.pl @@ -160,12 +160,40 @@ while (defined($_ = <DAT>)) { 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"; + if ($what eq "pos1") { + printo i18n("Parameter:"), 15; + print "x1\n"; + printo i18n("Description:"), 15; + print "\n"; + printo i18n("Default:"), 15; + print "\n\n"; + printo i18n("Parameter:"), 15; + print "y1\n"; + printo i18n("Description:"), 15; + print "\n"; + printo i18n("Default:"), 15; + print "\n\n"; + } elsif ($what eq "pos2") { + printo i18n("Parameter:"), 15; + print "x2\n"; + printo i18n("Description:"), 15; + print "\n"; + printo i18n("Default:"), 15; + print "\n\n"; + printo i18n("Parameter:"), 15; + print "y2\n"; + printo i18n("Description:"), 15; + print "\n"; + printo i18n("Default:"), 15; + print "\n\n"; + } else { + printo i18n("Parameter:"), 15; + print "$what\n"; + printo i18n("Description:"), 15; + print "\n"; + printo i18n("Default:"), 15; + print "\n\n"; + } }; } } diff --git a/contrib/skin_to_003.pl b/contrib/skin_to_003.pl new file mode 100755 index 0000000..0f4f88c --- /dev/null +++ b/contrib/skin_to_003.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl + +while (defined($_ = <>)) { + $x = 0; $y = 0; + $w = 0; $h = 0; + + s/version=0.0.2/version=0.0.3,base=rel/; + + /,x=(\d+)[,;]/ and $x = $1; + /,y=(\d+)[,;]/ and $y = $1; + /,width=(\d+)[,;]/ and $w = $1; + /,height=(\d+)[,;]/ and $h = $1; + + $x2 = $x + $w - 1; + $y2 = $y + $h - 1; + + s/,x=$x/,x1=$x/; + s/,y=$y/,y1=$y/; + s/,width=$w/,x2=$x2/; + s/,height=$h/,y2=$y2/; + + print $_; +} diff --git a/contrib/transform.pl b/contrib/transform.pl new file mode 100755 index 0000000..db41183 --- /dev/null +++ b/contrib/transform.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl + +if (@ARGV != 2) { + die "Usage: $0 <in> <out>"; +} + +open DAT, "<$ARGV[0]" or die $!; +open OUT, ">$ARGV[1]" or die $!; + +$| = 1; + +system("stty -icanon eol \001"); + +while (defined($_ = <DAT>)) { + /\[(\w+)\]/ and print "\nNew Section: $1\n\n"; + /^Item=(\w+),/ and do { + $i = $1; + /,x1=(\d+)[,;]/ and do { + $x1 = $1; + print "Item $i, x1 (left)? ([l]/r) > "; + read STDIN, $c, 1; + print "\n"; + $nx1 = $x1 - 624; + s/,x1=$x1/,x1=$nx1/ if $c eq 'r'; + }; + /,y1=(\d+)[,;]/ and do { + $y1 = $1; + print "Item $i, y1 (top)? ([l]/r) > "; + read STDIN, $c, 1; + print "\n"; + $ny1 = $y1 - 486; + s/,y1=$y1/,y1=$ny1/ if $c eq 'r'; + }; + /,x2=(\d+)[,;]/ and do { + $x2 = $1; + print "Item $i, x2 (right)? ([l]/r) > "; + read STDIN, $c, 1; + print "\n"; + $nx2 = $x2 - 624; + s/,x2=$x2/,x2=$nx2/ if $c eq 'r'; + }; + /,y2=(\d+)[,;]/ and do { + $y2 = $1; + print "Item $i, y2 (bottom)? ([l]/r) > "; + read STDIN, $c, 1; + print "\n"; + $ny2 = $y2 - 486; + s/,y2=$y2/,y2=$ny2/ if $c eq 'r'; + }; + }; + print OUT $_; +} + +system("stty icanon eol ^@"); @@ -1,22 +1,20 @@ /* - * $Id: data.c,v 1.19 2004/06/16 18:46:50 lordjaxom Exp $ + * $Id: data.c,v 1.20 2004/06/22 16:48:03 lordjaxom Exp $ */ #include "data.h" #include "common.h" +#include "render.h" cText2SkinItem::cText2SkinItem(void) { mItem = itemUnknown; mDisplay = displayAlways; - mPos.x = 0; - mPos.y = 0; - mSize.w = 0; - mSize.h = 0; mBpp = 4; mArc = 0; mAlpha = 0; mFont = cFont::GetFont(fontOsd); mAlign = taDefault; + mBase = baseRelative; } cText2SkinItem::~cText2SkinItem() { @@ -28,24 +26,27 @@ bool cText2SkinItem::Parse(const char *Text) { bool res = false; // check if this is an item - if (ParseVar(ptr, "Item", &mItem)) { - if (mItem == itemSkin && (!ParseVar(ptr, "name", mName) || !ParseVar(ptr, "version", mVersion))) + if (ParseVar(ptr, "Item", &mItem) && mItem != itemUnknown) { + ParseItem(ptr); + + if (mItem == itemSkin && (mName == "" || mVersion == "")) esyslog("ERROR: text2skin: Item=Skin is missing the name and/or version parameter(s)"); - else if (mItem != itemUnknown) { - ParseItem(ptr); + else res = true; - } } else esyslog("ERROR: text2skin: unknown item in skin"); return res; } bool cText2SkinItem::ParseItem(const char *Text) { + ParseVar(Text, "name", mName); + ParseVar(Text, "version", mVersion); + ParseVar(Text, "base", &mBase); ParseVar(Text, "display", &mDisplay); - ParseVar(Text, "x", &mPos.x); - ParseVar(Text, "y", &mPos.y); - ParseVar(Text, "width", &mSize.w); - ParseVar(Text, "height", &mSize.h); + ParseVar(Text, "x1", &mPos1.x); + ParseVar(Text, "y1", &mPos1.y); + ParseVar(Text, "x2", &mPos2.x); + ParseVar(Text, "y2", &mPos2.y); ParseVar(Text, "bpp", &mBpp); ParseVar(Text, "arc", &mArc); ParseVar(Text, "alpha", &mAlpha); @@ -61,6 +62,16 @@ bool cText2SkinItem::ParseItem(const char *Text) { return true; } +const POINT cText2SkinItem::Pos(void) const { + return cText2SkinRender::Transform(mPos1); +} + +const SIZE cText2SkinItem::Size(void) const { + POINT p1 = cText2SkinRender::Transform(mPos1); + POINT p2 = cText2SkinRender::Transform(mPos2); + return SIZE(p2.x - p1.x + 1, p2.y - p1.y + 1); +} + // --- cText2SkinData --------------------------------------------------------- cText2SkinData::cText2SkinData(const char *Skin): cText2SkinFile(Skin) { @@ -1,5 +1,5 @@ /* - * $Id: data.h,v 1.16 2004/06/12 18:00:05 lordjaxom Exp $ + * $Id: data.h,v 1.17 2004/06/22 16:48:03 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_DATA_H @@ -12,13 +12,11 @@ #include <vdr/config.h> class cText2SkinItem { - friend class cText2SkinRender; - private: eSkinItem mItem; eSkinDisplay mDisplay; - POINT mPos; - SIZE mSize; + POINT mPos1; + POINT mPos2; int mBpp; int mArc; int mAlpha; @@ -33,6 +31,7 @@ private: string mType; string mFormat; eTextAlignment mAlign; + eBaseCoordinate mBase; protected: bool ParseItem(const char *Text); @@ -43,10 +42,16 @@ public: bool Parse(const char *Text); + // writeables + POINT &Pos1(void) { return mPos1; } + POINT &Pos2(void) { return mPos2; } + + // readables eSkinItem Item(void) const { return mItem; } eSkinDisplay Display(void) const { return mDisplay; } - const POINT &Pos(void) const { return mPos; } - const SIZE &Size(void) const { return mSize; } + eBaseCoordinate Base(void) const { return mBase; } + const POINT &Pos1(void) const { return mPos1; } + const POINT &Pos2(void) const { return mPos2; } int Bpp(void) const { return mBpp; } int Arc(void) const { return mArc; } int Alpha(void) const { return mAlpha; } @@ -61,6 +66,10 @@ public: const string &Type(void) const { return mType; } const string &Format(void) const { return mFormat; } eTextAlignment Align(void) const { return mAlign; } + + // auto-conversion + const POINT Pos(void) const; + const SIZE Size(void) const; }; class cText2SkinData: public cText2SkinFile { @@ -1,5 +1,5 @@ /* - * $Id: display.c,v 1.17 2004/06/16 18:46:50 lordjaxom Exp $ + * $Id: display.c,v 1.18 2004/06/24 18:37:30 lordjaxom Exp $ */ #include "render.h" @@ -109,8 +109,10 @@ void cText2SkinDisplayReplay::SetTitle(const char *Title) { } void cText2SkinDisplayReplay::SetMode(bool Play, bool Forward, int Speed) { + Dprintf("speed: Play = %s, Forward = %s, Speed = %d\n", Play ? "true" : "false", Forward ? "true" : "false", Speed); mRender->Lock(); - if (mRender->mReplayPlay != Play || mRender->mReplayForward != Forward || mRender->mReplaySpeed != Speed) { + if (mRender->mReplayInfo == false || mRender->mReplayPlay != Play || mRender->mReplayForward != Forward || mRender->mReplaySpeed != Speed) { + mRender->mReplayInfo = true; mRender->mReplayPlay = Play; mRender->mReplayForward = Forward; mRender->mReplaySpeed = Speed; @@ -1,5 +1,5 @@ /* - * $Id: i18n.c,v 1.8 2004/06/18 16:08:11 lordjaxom Exp $ + * $Id: i18n.c,v 1.9 2004/06/22 16:48:03 lordjaxom Exp $ */ #include "i18n.h" @@ -146,8 +146,3 @@ bool cText2SkinI18n::Load(const string &Filename) { } return false; } - -string cText2SkinI18n::Translate(const string &Text) { - string s = I18nTranslate(Text.c_str(), mIdentity.c_str()); - return s != "" ? s : Text; -} @@ -1,5 +1,5 @@ /* - * $Id: i18n.h,v 1.2 2004/06/07 18:23:11 lordjaxom Exp $ + * $Id: i18n.h,v 1.3 2004/06/22 16:48:03 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_I18N_H @@ -25,7 +25,7 @@ public: virtual ~cText2SkinI18n(); virtual bool Load(const string &Filename); - string Translate(const string &Text); + string Translate(const string &Text) { return I18nTranslate(Text.c_str(), mIdentity.c_str()); } }; #endif // VDR_TEXT2SKIN_I18N_H @@ -1,5 +1,5 @@ /* - * $Id: loader.c,v 1.11 2004/06/16 18:46:50 lordjaxom Exp $ + * $Id: loader.c,v 1.12 2004/06/22 16:48:03 lordjaxom Exp $ */ #include "loader.h" @@ -53,10 +53,10 @@ void cText2SkinLoader::Load(const char *Skin) { new cText2SkinLoader(data, translations, theme, Skin, skin->Name()); return; } else - esyslog("ERROR: text2skin: Skin %s is version %s, expecting %s", Skin, skin->Version().c_str(), cText2SkinPlugin::ThemeVersion()); + esyslog("ERROR: text2skin: Skin is version %s, expecting %s", skin->Version().c_str(), cText2SkinPlugin::ThemeVersion()); return; } else - esyslog("ERROR: text2skin: Item=Skin is missing in Skin %s", Skin); + esyslog("ERROR: text2skin: Item=Skin is missing in Skin"); } delete data; } else @@ -1,5 +1,5 @@ /* - * $Id: render.c,v 1.33 2004/06/18 16:41:08 lordjaxom Exp $ + * $Id: render.c,v 1.36 2004/06/25 17:51:34 lordjaxom Exp $ */ #include "render.h" @@ -12,6 +12,8 @@ #include <vdr/epg.h> #include <vdr/menu.h> +cText2SkinRender *cText2SkinRender::mRender = NULL; + cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Section) { tArea areas[MAXOSDAREAS]; int numAreas = 0; @@ -22,13 +24,14 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio mI18n = Loader->I18n(); mTheme = Loader->Theme(); mSection = Section; - mOsd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop); + mOsd = NULL; mScroller = NULL; mChannel = NULL; mChannelNumber = 0; mVolumeCurrent = -1; mVolumeTotal = -1; mVolumeMute = false; + mReplayInfo = false; mReplayPlay = false; mReplayForward = false; mReplaySpeed = 0; @@ -47,26 +50,60 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio mMenuScrollPage = false; mActive = false; mUpdateIn = 0; + mBase = baseRelative; - cText2SkinData::tIterator it = mData->First(mSection); - for (; it != mData->Last(mSection); ++it) { - if ((*it)->Item() == itemBackground) { - if (numAreas < MAXOSDAREAS) { - areas[numAreas].x1 = (*it)->Pos().x; - areas[numAreas].y1 = (*it)->Pos().y; - areas[numAreas].x2 = (*it)->Pos().x + (*it)->Size().w - 1; - areas[numAreas].y2 = (*it)->Pos().y + (*it)->Size().h - 1; - areas[numAreas].bpp = (*it)->Bpp(); - ++numAreas; - } else - esyslog("ERROR: text2skin: too many background areas\n"); + mRender = this; + + cText2SkinItem *item = mData->Get(sectionSkin, itemSkin); + switch (mBase = item->Base()) { + case baseRelative: + mOsd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop); + mBaseSize = SIZE(Setup.OSDWidth, Setup.OSDHeight); + break; + case baseAbsolute: + mOsd = cOsdProvider::NewOsd(0, 0); + mBaseSize = SIZE(720, 576); //XXX + break; + default: + break; + } + + Dprintf("base: %d\n", item->Base()); + + eOsdError res = oeOk; + areas[0].x1 = 0; + areas[0].y1 = 0; + areas[0].x2 = mBaseSize.w - 1; + areas[0].y2 = mBaseSize.h - 1; + areas[0].bpp = 8; + Dprintf("trying big area %d:%d:%d:%d\n", areas[0].x1, areas[0].y1, areas[0].x2, areas[0].y2, areas[0].bpp); + if ((res = mOsd->CanHandleAreas(areas, 1)) == oeOk) { + mOsd->SetAreas(areas, 1); + mOsd->DrawRectangle(areas[0].x1, areas[0].y1, areas[0].x2, areas[0].y2, areas[0].bpp); + } else { + Dprintf("failed, chunking\n"); + cText2SkinData::tIterator it = mData->First(mSection); + for (; it != mData->Last(mSection); ++it) { + if ((*it)->Item() == itemBackground) { + if (numAreas < MAXOSDAREAS) { + POINT p = (*it)->Pos(); + SIZE s = (*it)->Size(); + areas[numAreas].x1 = p.x; + areas[numAreas].y1 = p.y; + areas[numAreas].x2 = p.x + s.w - 1; + areas[numAreas].y2 = p.y + s.h - 1; + areas[numAreas].bpp = (*it)->Bpp(); + ++numAreas; + } else + esyslog("ERROR: text2skin: too many background areas\n"); + } } + + if ((res = mOsd->CanHandleAreas(areas, numAreas)) == oeOk) + mOsd->SetAreas(areas, numAreas); } - eOsdError res; - if ((res = mOsd->CanHandleAreas(areas, numAreas)) == oeOk) - mOsd->SetAreas(areas, numAreas); - else { + if (res != oeOk) { const char *emsg = NULL; switch (res) { case oeTooManyAreas: @@ -100,6 +137,7 @@ cText2SkinRender::~cText2SkinRender() { delete mScroller; delete mOsd; cText2SkinBitmap::ResetCache(); + mRender = NULL; } void cText2SkinRender::Action(void) { @@ -118,6 +156,8 @@ void cText2SkinRender::Action(void) { } void cText2SkinRender::Update(void) { + Dbench(update); + if (mScroller && !mMenuScroll) mOsd->SaveRegion(mScroller->Left(), mScroller->Top(), mScroller->Left() + mScroller->Width() - 1, mScroller->Top() + mScroller->Height() - 1); @@ -154,6 +194,7 @@ void cText2SkinRender::Update(void) { case displayPresentTitle: case displayPresentShortText: case displayPresentDescription: + case displayPresentTextDescription: DisplayPresentText(*it); break; case displayFollowingStartTime: @@ -239,7 +280,10 @@ void cText2SkinRender::Update(void) { break; } } + Dbench(flush); mOsd->Flush(); + Dprintf("flush only took %d ms\n", Ddiff(flush)); + Dprintf("complete flush took %d ms\n", Ddiff(update)); } void cText2SkinRender::DrawBackground(const POINT &Pos, const SIZE &Size, const tColor *Bg, const tColor *Fg, int Alpha, const string &Path) { @@ -247,7 +291,6 @@ void cText2SkinRender::DrawBackground(const POINT &Pos, const SIZE &Size, const if (Path != "") { char *p; asprintf(&p, "%s/%s/%s", SkinPath(), mData->Skin().c_str(), Path.c_str()); - Dprintf("Trying to load image: %s\n", p); if ((bmp = cText2SkinBitmap::Load(p, Alpha)) != NULL) { if (Bg) bmp->SetColor(0, *Bg); if (Fg) bmp->SetColor(1, *Fg); @@ -296,41 +339,35 @@ void cText2SkinRender::DrawProgressbar(const POINT &Pos, const SIZE &Size, int C if (Current > Total) Current = Total; if (Size.w > Size.h) { - SIZE size = { Size.w * Current / Total, Size.h }; - DrawRectangle(Pos, size, Fg); + DrawRectangle(Pos, SIZE(Size.w * Current / Total, Size.h), Fg); if (Marks) { - bool Start = true; + bool start = true; for (const cMark *m = Marks->First(); m; m = Marks->Next(m)) { - POINT p1 = { Pos.x + m->position * Size.w / Total, Pos.y }; - if (Start) { + POINT pt(Pos.x + m->position * Size.w / Total, Pos.y); + if (start) { const cMark *m2 = Marks->Next(m); tColor col = clrRed; - POINT p2 = { p1.x, Pos.y + Size.h / 3 }; - SIZE s = { ((m2 ? m2->position : Total) - m->position) * Size.w / Total, Size.h / 3 }; - DrawRectangle(p2, s, &col); + DrawRectangle(POINT(pt.x, Pos.y + Size.h / 3), SIZE(((m2 ? m2->position : Total) - m->position) * Size.w / Total, Size.h / 3), &col); } - DrawMark(p1, Size, Start, m->position == Current, false); - Start = !Start; + DrawMark(pt, Size, start, m->position == Current, false); + start = !start; } } } else { - SIZE size = { Size.w, Size.h * Current / Total }; - DrawRectangle(Pos, size, Fg); + DrawRectangle(Pos, SIZE(Size.w, Size.h * Current / Total), Fg); if (Marks) { - bool Start = true; + bool start = true; for (const cMark *m = Marks->First(); m; m = Marks->Next(m)) { - POINT p1 = { Pos.x, Pos.y + m->position * Size.h / Total }; - if (Start) { + POINT pt(Pos.x, Pos.y + m->position * Size.h / Total); + if (start) { const cMark *m2 = Marks->Next(m); tColor col = clrRed; - POINT p2 = { Pos.x + Size.w / 3, p1.y }; - SIZE s = { Size.w / 3, ((m2 ? m2->position : Total) - m->position) * Size.h / Total }; - DrawRectangle(p2, s, &col); + DrawRectangle(POINT(Pos.x + Size.w / 3, pt.y), SIZE(Size.w / 3, ((m2 ? m2->position : Total) - m->position) * Size.h / Total), &col); } - DrawMark(p1, Size, Start, m->position == Current, true); - Start = !Start; + DrawMark(pt, Size, start, m->position == Current, true); + start = !start; } } } @@ -339,26 +376,20 @@ void cText2SkinRender::DrawProgressbar(const POINT &Pos, const SIZE &Size, int C void cText2SkinRender::DrawMark(const POINT &Pos, const SIZE &Size, bool Start, bool Current, bool Horizontal) { tColor mark = clrBlack; tColor current = clrRed; - POINT p1 = { Pos.x, Pos.y }; + POINT p1 = Pos; if (Horizontal) { - SIZE s1 = { Size.w, 1 }; - DrawRectangle(p1, s1, &mark); + DrawRectangle(p1, SIZE(Size.w, 1), &mark); const int d = Size.w / (Current ? 3 : 9); for (int i = 0; i < d; i++) { int h = Start ? i : Size.w - 1 - i; - POINT p2 = { Pos.x + h, Pos.y - d + i }; - SIZE s2 = { 1, (d - i) * 2 }; - DrawRectangle(p2, s2, Current ? ¤t : &mark); + DrawRectangle(POINT(Pos.x + h, Pos.y - d + i), SIZE(1, (d - i) * 2), Current ? ¤t : &mark); } } else { - SIZE s1 = { 1, Size.h }; - DrawRectangle(p1, s1, &mark); + DrawRectangle(p1, SIZE(1, Size.h), &mark); const int d = Size.h / (Current ? 3 : 9); for (int i = 0; i < d; i++) { int h = Start ? i : Size.h - 1 - i; - POINT p2 = { Pos.x - d + i, Pos.y + h }; - SIZE s2 = { (d - i) * 2, 1 }; - DrawRectangle(p2, s2, Current ? ¤t : &mark); + DrawRectangle(POINT(Pos.x - d + i, Pos.y + h), SIZE((d - i) * 2, 1), Current ? ¤t : &mark); } } } @@ -379,13 +410,13 @@ void cText2SkinRender::DrawScrollbar(const POINT &Pos, const SIZE &Size, int Off POINT sp = Pos; SIZE ss = Size; sp.y += Size.h * Offset / Total; - ss.h = Size.h * Shown / Total; + ss.h = Size.h * Shown / Total + 1; DrawRectangle(sp, ss, Fg); } else { POINT sp = Pos; SIZE ss = Size; sp.x += Size.w * Offset / Total; - ss.w = Size.w * Shown / Total; + ss.w = Size.w * Shown / Total + 1; DrawRectangle(sp, ss, Fg); } } @@ -588,22 +619,27 @@ void cText2SkinRender::DisplayPresentText(cText2SkinItem *Item) { } if (event) { - const char *text = NULL; + string text; switch (Item->Display()) { case displayPresentTitle: - text = event->Title(); + text = event->Title() ? event->Title() : ""; break; case displayPresentShortText: - text = event->ShortText(); + text = event->ShortText() ? event->ShortText() : ""; break; case displayPresentDescription: - text = event->Description(); + text = event->Description() ? event->Description() : ""; break; + case displayPresentTextDescription: + if (event->ShortText()) + text += (string)event->ShortText() + "\n\n"; + if (event->Description()) + text += event->Description(); default: break; } - if (text) { + if (text != "") { ItemData data; data.text = text; DisplayItem(Item, &data); @@ -775,30 +811,32 @@ void cText2SkinRender::DisplayReplayPrompt(cText2SkinItem *Item) { } void cText2SkinRender::DisplayReplaySymbol(cText2SkinItem *Item) { - ItemData data; - switch (Item->Display()) { - case displayPlay: - data.path = (mReplaySpeed == -1 && mReplayPlay) ? Item->Path() : Item->AltPath(); - break; - case displayPause: - data.path = (mReplaySpeed == -1 && !mReplayPlay) ? Item->Path() : Item->AltPath(); - break; - case displayFastFwd: - data.path = (mReplaySpeed != -1 && mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath(); - break; - case displayFastRew: - data.path = (mReplaySpeed != -1 && mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath(); - break; - case displaySlowFwd: - data.path = (mReplaySpeed != -1 && !mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath(); - break; - case displaySlowRew: - data.path = (mReplaySpeed != -1 && !mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath(); - break; - default: - break; + if (mReplayInfo) { + ItemData data; + switch (Item->Display()) { + case displayPlay: + data.path = (mReplaySpeed == -1 && mReplayPlay) ? Item->Path() : Item->AltPath(); + break; + case displayPause: + data.path = (mReplaySpeed == -1 && !mReplayPlay) ? Item->Path() : Item->AltPath(); + break; + case displayFastFwd: + data.path = (mReplaySpeed != -1 && mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath(); + break; + case displayFastRew: + data.path = (mReplaySpeed != -1 && mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath(); + break; + case displaySlowFwd: + data.path = (mReplaySpeed != -1 && !mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath(); + break; + case displaySlowRew: + data.path = (mReplaySpeed != -1 && !mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath(); + break; + default: + break; + } + DisplayItem(Item, &data); } - DisplayItem(Item, &data); } void cText2SkinRender::DisplayReplayMode(cText2SkinItem *Item) { @@ -896,7 +934,7 @@ void cText2SkinRender::DisplayMenuItems(cText2SkinItem *Item) { cText2SkinItem *item = mData->Get(sectionMenu, itemMenuItem); if (item && area) { - POINT pos = area->Pos(); + POINT pos = area->Pos1(); int max = area->Size().h / item->Size().h; for (int i = 0; i < min((int)mMenuItems.size(), max); ++i) { @@ -919,19 +957,15 @@ void cText2SkinRender::DisplayMenuItems(cText2SkinItem *Item) { POINT itempos = pos; itempos.y += i * item->Size().h; - itempos += Item->Pos(); + itempos += Item->Pos1(); if (Item->Item() == itemText) { // draw tabs for (int t = 0; t < cSkinDisplayMenu::MaxTabs; ++t) { if (mMenuItems[i].tabs[t] != "") { ItemData data; cText2SkinItem cur = *Item; - cur.mPos = itempos; - cur.mPos.x += mMenuTabs[t]; - cur.mSize.w -= mMenuTabs[t]; - /*if (t == cSkinDisplayMenu::MaxTabs || !mMenuTabs[t + 1]) - cur.mSize.w -= mMenuTabs[t]; - else - cur.mSize.w = mMenuTabs[t + 1] - mMenuTabs[t];*/ + cur.Pos1() = itempos; + cur.Pos1().x += mMenuTabs[t]; + cur.Pos2() += itempos; data.text = mMenuItems[i].tabs[t]; DisplayItem(&cur, &data); } @@ -941,7 +975,8 @@ void cText2SkinRender::DisplayMenuItems(cText2SkinItem *Item) { } else { ItemData data; cText2SkinItem cur = *Item; - cur.mPos = itempos; + cur.Pos1() = itempos; + cur.Pos2() += itempos; DisplayItem(&cur, &data); } } @@ -953,15 +988,14 @@ string cText2SkinRender::ItemText(cText2SkinItem *Item) { } string cText2SkinRender::ItemText(cText2SkinItem *Item, const string &Content) { - string s; if (Item->Text() != "") { - s = mI18n ? mI18n->Translate(Item->Text()) : Item->Text(); + string s = mI18n ? mI18n->Translate(Item->Text()) : Item->Text(); int pos; - while ((pos = s.find('$')) != -1) - s.replace(pos, 1, Content); - } else - s = Content; - return s; + while ((pos = s.find("{*}")) != -1) + s.replace(pos, 3, Content); + return s; + } + return Content; } tColor *cText2SkinRender::ItemFg(cText2SkinItem *Item) { @@ -993,3 +1027,9 @@ int cText2SkinRender::GetEditableWidth(MenuItem Item, bool Current) { item = mData->Get(sectionMenu, itemMenuItem); return item->Size().w - mMenuTabs[1]; } + +POINT cText2SkinRender::Transform(const POINT &Pos) { + SIZE base = mRender->mBaseSize; + return POINT(Pos.x < 0 ? base.w + Pos.x : Pos.x, Pos.y < 0 ? base.h + Pos.y : Pos.y); +} + @@ -1,5 +1,5 @@ /* - * $Id: render.h,v 1.22 2004/06/16 18:46:50 lordjaxom Exp $ + * $Id: render.h,v 1.24 2004/06/24 18:37:30 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_RENDER_H @@ -26,6 +26,8 @@ class cText2SkinRender: public cThread { friend class cText2SkinDisplayMenu; private: + static cText2SkinRender *mRender; + cText2SkinData *mData; cText2SkinI18n *mI18n; cText2SkinTheme *mTheme; @@ -56,6 +58,7 @@ private: // replay display string mReplayTitle; + bool mReplayInfo; bool mReplayPlay; bool mReplayForward; int mReplaySpeed; @@ -98,6 +101,10 @@ private: cCondVar mDoUpdate; cMutex mMutex; int mUpdateIn; + + // coordinate transformation + eBaseCoordinate mBase; + SIZE mBaseSize; protected: // Update thread @@ -157,6 +164,8 @@ public: cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Section); virtual ~cText2SkinRender(); + static POINT Transform(const POINT &Pos); + void Flush(void) { Lock(); mDoUpdate.Broadcast(); Unlock(); } }; diff --git a/text2skin.c b/text2skin.c index 6822797..5db7ff1 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.21 2004/06/18 16:08:11 lordjaxom Exp $ + * $Id: text2skin.c,v 1.23 2004/06/25 17:51:34 lordjaxom Exp $ */ #include "text2skin.h" @@ -11,8 +11,8 @@ #include "i18n.h" #include "loader.h" -const char *cText2SkinPlugin::VERSION = "0.0.6"; -const char *cText2SkinPlugin::THEMEVERSION = "0.0.2"; +const char *cText2SkinPlugin::VERSION = "0.0.7"; +const char *cText2SkinPlugin::THEMEVERSION = "0.0.3"; const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins"; cText2SkinPlugin::cText2SkinPlugin(void) { |