diff options
-rw-r--r-- | HISTORY | 12 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | bitmap.c | 93 | ||||
-rw-r--r-- | bitmap.h | 13 | ||||
-rw-r--r-- | cache.h | 3 | ||||
-rw-r--r-- | common.c | 66 | ||||
-rw-r--r-- | common.h | 121 | ||||
-rwxr-xr-x | contrib/skin_to_002.pl | 102 | ||||
-rw-r--r-- | data.c | 57 | ||||
-rw-r--r-- | data.h | 103 | ||||
-rw-r--r-- | i18n.c | 28 | ||||
-rw-r--r-- | loader.c | 13 | ||||
-rw-r--r-- | render.c | 988 | ||||
-rw-r--r-- | render.h | 62 | ||||
-rw-r--r-- | text2skin.c | 6 | ||||
-rw-r--r-- | text2skin.h | 8 |
16 files changed, 1045 insertions, 634 deletions
@@ -1,6 +1,18 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2004-06-11: Version 0.0.3 + +- fixed VPSTime which was displayed on channels that didn't even have VPS +- fixed Symbols in channel display when viewing a group +- fixed text translation if no translation is present +- fixed compile error with gcc 3.4 (thanks to Gregoire Favre for reporting this) +- restructured Skin (now the official Skin version is 0.0.2) + it is now possible to control visibility of all items +- added a script to convert 0.0.1 themes to 0.0.2 +- added support for animated logos (mng or gif files) ONLY IMAGEMAGICK!!! +- added finnish language translations (thanks to Rolf Ahrenberg) + 2004-06-07: Version 0.0.2 - fixed Timebar which sometimes displayed something beyond 100% @@ -3,13 +3,13 @@ # Text2Skin if you use Imlib2! (That's why I actually implemented ImageMagick) HAVE_IMAGEMAGICK=1 -# HAVE_IMLIB2=1 +#HAVE_IMLIB2=1 # DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING # ------------------------------------------------------------- # -# $Id: Makefile,v 1.8 2004/06/07 18:23:11 lordjaxom Exp $ +# $Id: Makefile,v 1.9 2004/06/08 20:45:52 lordjaxom Exp $ # # The official name of this plugin. @@ -1,5 +1,5 @@ /* - * $Id: bitmap.c,v 1.11 2004/06/05 16:52:44 lordjaxom Exp $ + * $Id: bitmap.c,v 1.13 2004/06/11 15:01:58 lordjaxom Exp $ */ #include "bitmap.h" @@ -10,6 +10,9 @@ #endif #ifdef HAVE_IMAGEMAGICK #include <Magick++.h> +using Magick::Image; +using Magick::PixelPacket; +using Magick::Exception; #endif template<> @@ -19,10 +22,37 @@ void cImageCache::Delete(string &key, cText2SkinBitmap *&value) { cImageCache cText2SkinBitmap::mCache(10); -cText2SkinBitmap::cText2SkinBitmap(void): cBitmap(1, 1, 1) { +cText2SkinBitmap::cText2SkinBitmap(void)/*: cBitmap(1, 1, 1)*/ { + mCurrent = 0; + mLastGet = 0; } cText2SkinBitmap::~cText2SkinBitmap() { + for (int i = 0; i < (int)mBitmaps.size(); ++i) + delete mBitmaps[i]; +} + +cBitmap &cText2SkinBitmap::Get(int &UpdateIn) { + if (mBitmaps.size() == 1) + return *mBitmaps[0]; + + time_t upd, cur = time_ms(); + int diff; + if (mLastGet == 0) { + mLastGet = cur; + upd = mDelay; + } else if ((diff = cur - mLastGet) >= mDelay) { + mCurrent = (mCurrent + 1) % mBitmaps.size(); + mLastGet = cur; + upd = mDelay; + } else { + upd = mDelay - diff; + } + + if (UpdateIn == 0 || UpdateIn > upd) + UpdateIn = upd; + + return *mBitmaps[mCurrent]; } cText2SkinBitmap *cText2SkinBitmap::Load(const char *Filename) { @@ -55,57 +85,78 @@ cText2SkinBitmap *cText2SkinBitmap::Load(const char *Filename) { return false; } +bool cText2SkinBitmap::LoadXpm(const char *Filename) { + cBitmap *bmp = new cBitmap(1,1,1); + if (bmp->LoadXpm(Filename)) { + mBitmaps.push_back(bmp); + return true; + } + delete bmp; + return false; +} + #ifdef HAVE_IMLIB2 bool cText2SkinBitmap::LoadImlib(const char *Filename) { Imlib_Image image; + cBitmap *bmp = NULL; image = imlib_load_image(Filename); if (!image) return false; Imlib_Context ctx = imlib_context_new(); imlib_context_push(ctx); imlib_context_set_image(image); - SetSize(imlib_image_get_width(), imlib_image_get_height()); - SetBpp(8); + bmp = new cBitmap(imlib_image_get_width(), imlib_image_get_height(), 8); uint8_t *data = (uint8_t*)imlib_image_get_data_for_reading_only(); int pal = 0, pos = 0; - for (int y = 0; y < Height(); ++y) { - for (int x = 0; x < Width(); ++x) { + 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]; - int res = Index(col); + int res = bmp->Index(col); if (pal > 0 && res == 0) ;//esyslog("ERROR: text2skin: Too many colors used in palette"); else - SetIndex(x, y, res); + bmp->SetIndex(x, y, res); pos += 4; } } imlib_free_image(); imlib_context_free(ctx); + mBitmaps.push_back(bmp); return true; } #endif #ifdef HAVE_IMAGEMAGICK bool cText2SkinBitmap::LoadMagick(const char *Filename) { - Magick::Image image; + vector<Image> images; + cBitmap *bmp = NULL; try { int w, h; - image.read(Filename); - w = image.columns(); - h = image.rows(); - SetSize(w, h); - SetBpp(8); + vector<Image>::iterator it; + readImages(&images, Filename); + if (images.size() == 0) { + esyslog("ERROR: text2skin: Couldn't load %s", Filename); + return false; + } + mDelay = images[0].animationDelay(); + for (it = images.begin(); it != images.end(); ++it) { + w = (*it).columns(); + h = (*it).rows(); + bmp = new cBitmap(w, h, 8); - const Magick::PixelPacket *ptr = image.getConstPixels(0, 0, w, h); - 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)); - DrawPixel(ix, iy, col); - ++ptr; + const PixelPacket *ptr = (*it).getConstPixels(0, 0, w, h); + 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)); + bmp->DrawPixel(ix, iy, col); + ++ptr; + } } + mBitmaps.push_back(bmp); } - } catch (Magick::Exception &e) { + } catch (Exception &e) { esyslog("ERROR: text2skin: Couldn't load %s: %s", Filename, e.what()); + delete bmp; return false; } return true; @@ -1,5 +1,5 @@ /* - * $Id: bitmap.h,v 1.8 2004/06/07 18:23:11 lordjaxom Exp $ + * $Id: bitmap.h,v 1.9 2004/06/08 20:45:52 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_BITMAP_H @@ -12,10 +12,15 @@ class cText2SkinBitmap; typedef cText2SkinCache<string,cText2SkinBitmap*> cImageCache; -class cText2SkinBitmap: public cBitmap { +class cText2SkinBitmap { private: static cImageCache mCache; + vector<cBitmap*> mBitmaps; + int mCurrent; + time_t mDelay; + time_t mLastGet; + // disallow direct construction cText2SkinBitmap(void); @@ -25,6 +30,10 @@ public: virtual ~cText2SkinBitmap(); + cBitmap &Get(int &UpdateIn); + void SetColor(int Index, tColor Color) { mBitmaps[mCurrent]->SetColor(Index, Color); } + + bool LoadXpm(const char *Filename); #ifdef HAVE_IMLIB2 bool LoadImlib(const char *Filename); #endif @@ -1,11 +1,12 @@ /* - * $Id: cache.h,v 1.2 2004/06/07 18:23:11 lordjaxom Exp $ + * $Id: cache.h,v 1.3 2004/06/08 20:45:52 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_CACHE_HPP #define VDR_TEXT2SKIN_CACHE_HPP #include "common.h" +#include <vdr/tools.h> // template class generic cache @@ -1,11 +1,35 @@ /* - * $Id: common.c,v 1.7 2004/06/05 16:52:44 lordjaxom Exp $ + * $Id: common.c,v 1.8 2004/06/11 15:01:58 lordjaxom Exp $ */ #include "data.h" #include "common.h" #include <vdr/plugin.h> +const string SectionNames[__SECTION_COUNT__] = + { "Skin", "ChannelSmall", "Channel", "Volume", "ReplayMode", "Replay", + "Message", "Menu" }; + +const string ItemNames[__ITEM_COUNT__] = + { "Unknown", "Skin", "Background", "Text", "Scrolltext", "Image", "Rectangle", + "Ellipse", "Slope", "Progress", "Logo", "Symbol", "MenuArea", "MenuItem" }; + +const string DisplayNames[__DISPLAY_COUNT__] = + { "Always", "DateTimeF", "DateTime", "Date", "Time", "ChannelNumberName", + "ChannelNumber", "ChannelName", "Language", "PresentDateTimeF", + "PresentStartTime", "PresentDate", "PresentVPSTime", "PresentEndTime", + "PresentDuration", "PresentVPS", "PresentRunning", "PresentTimer", + "PresentTitle", "PresentShortText", "PresentDescription", + "FollowingStartTime", "FollowingEndTime", "FollowingDuration", + "FollowingTitle", "FollowingShortText", "Teletext", "Audio", "Dolby", + "Encrypted", "Recording", "Radio", "VolumeCurrent", "VolumeTotal", "Mute", + "ReplayTime", "ReplayDuration", "ReplayTitle", "ReplayPrompt", "Play", + "Pause", "FastFwd", "FastRew", "SlowFwd", "SlowRew", "Message", + "MessageStatus", "MessageInfo", "MessageWarning", "MessageError", + "MenuTitle", "MenuRed", "MenuGreen", "MenuYellow", "MenuBlue", "MenuText", + "MenuRecording", "MenuScrollUp", "MenuScrollDown", "MenuItems", + "MenuCurrent", "MenuGroups" }; + const char *SkinPath(void) { return cPlugin::ConfigDirectory(PLUGIN_NAME_I18N); } @@ -44,6 +68,38 @@ string ItemText(cText2SkinItem *Item, const string &Content) { return s; } +bool ParseVar(const char *Text, const char *Name, eSkinItem *Value) { + string value; + if (ParseVar(Text, Name, value)) { + int i; + for (i = 0; i < __ITEM_COUNT__; ++i) { + if (ItemNames[i] == value) { + *Value = (eSkinItem)i; + return true; + } + if (i == __ITEM_COUNT__) + esyslog("ERROR: text2skin: unknown item %s", value.c_str()); + } + } + return false; +} + +bool ParseVar(const char *Text, const char *Name, eSkinDisplay *Value) { + string value; + if (ParseVar(Text, Name, value)) { + int i; + for (i = 0; i < __DISPLAY_COUNT__; ++i) { + if (DisplayNames[i] == value) { + *Value = (eSkinDisplay)i; + return true; + } + if (i == __DISPLAY_COUNT__) + esyslog("ERROR: text2skin: unknown display parameter %s", value.c_str()); + } + } + return false; +} + bool ParseVar(const char *Text, const char *Name, int *Value) { string value; if (ParseVar(Text, Name, value)) { @@ -54,11 +110,13 @@ bool ParseVar(const char *Text, const char *Name, int *Value) { } bool ParseVar(const char *Text, const char *Name, string &Value){ - char *ptr1, *ptr2; + const char *ptr1, *ptr2; char *str; bool res = false; - asprintf(&str, "%s=", Name); - if ((ptr1 = strstr(Text, str))) { + asprintf(&str, ",%s=", Name); + if ((ptr1 = strstr(Text, str)) || (strncmp(ptr1 = Text, str + 1, strlen(str) - 1) == 0)) { + if (ptr1 == Text) + --ptr1; ptr1 += strlen(str); if ((ptr2 = strchr(ptr1, ',')) || (ptr2 = strchr(ptr1, ';'))) { Value = ptr1; @@ -1,5 +1,5 @@ /* - * $Id: common.h,v 1.7 2004/06/05 16:52:44 lordjaxom Exp $ + * $Id: common.h,v 1.8 2004/06/11 15:01:58 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_COMMON_H @@ -20,13 +20,132 @@ using std::map; # define Dprintf(x...) #endif +// sections and items known by skin files + +enum eSkinSection { + sectionSkin, + sectionChannelSmall, + sectionChannel, + sectionVolume, + sectionReplayMode, + sectionReplay, + sectionMessage, + sectionMenu, + __SECTION_COUNT__ +}; + +enum eSkinItem { + itemUnknown, + itemSkin, // item identifying the Skin itself + itemBackground, + itemText, + itemScrolltext, + itemImage, + itemRectangle, + itemEllipse, + itemSlope, + itemProgress, + itemLogo, + itemSymbol, + itemMenuArea, + itemMenuItem, + __ITEM_COUNT__ +}; + +enum eSkinDisplay { + displayAlways, + displayDateTimeF, // exc: text + displayDateTime, // exc: text + displayDate, // exc: text + displayTime, // exc: text + displayChannelNumberName, // exc: text + displayChannelNumber, // exc: text + displayChannelName, // exc: text, logo + displayLanguage, // exc: text, logo + displayPresentDateTimeF, // exc: text + displayPresentStartTime, // exc: text + displayPresentDate, // exc: text + displayPresentVPSTime, // exc: text + displayPresentEndTime, // exc: text + displayPresentDuration, // exc: text, progress + displayPresentVPS, // exc: symbol + displayPresentRunning, // exc: symbol + displayPresentTimer, // exc: symbol + displayPresentTitle, // exc: text + displayPresentShortText, // exc: text + displayPresentDescription, // exc: text + displayFollowingStartTime, // exc: text, progress + displayFollowingEndTime, // exc: text, progress + displayFollowingDuration, // exc: text, progress + displayFollowingTitle, // exc: text + displayFollowingShortText, // exc: text + displayTeletext, // exc: symbol + displayAudio, // exc: symbol + displayDolby, // exc: symbol + displayEncrypted, // exc: symbol + displayRecording, // exc: symbol + displayRadio, // exc: symbol + displayVolumeCurrent, // exc: text, progress + displayVolumeTotal, // exc: text, progress + displayMute, // exc: symbol + displayReplayTime, // exc: text, progress + displayReplayDuration, // exc: text + displayReplayTitle, // exc: text + displayReplayPrompt, // exc: text + displayPlay, // exc: symbol + displayPause, // exc: symbol + displayFastFwd, // exc: symbol + displayFastRew, // exc: symbol + displaySlowFwd, // exc: symbol + displaySlowRew, // exc: symbol + displayMessage, // exc: text + displayMessageStatus, // exc: text + displayMessageInfo, // exc: text + displayMessageWarning, // exc: text + displayMessageError, // exc: text + displayMenuTitle, // exc: text (TODO: logo?) + displayMenuRed, // exc: text + displayMenuGreen, // exc: text + displayMenuYellow, // exc: text + displayMenuBlue, // exc: text + displayMenuText, // exc: text + displayMenuRecording, // exc: text + displayMenuScrollUp, // exc: symbol + displayMenuScrollDown, // exc: symbol + displayMenuItems, + displayMenuCurrent, + displayMenuGroups, + __DISPLAY_COUNT__ +}; + +extern const string SectionNames[__SECTION_COUNT__]; +extern const string ItemNames[__ITEM_COUNT__]; +extern const string DisplayNames[__DISPLAY_COUNT__]; + +// geometrical structures + +struct POINT { + int x, y; + POINT &operator+=(const POINT &pt) { x += pt.x; y += pt.y; return *this; } +}; + +struct SIZE { + int w, h; +}; + +// class forwards + class cChannel; class cText2SkinItem; +// helper functions + const char *SkinPath(void); const char *ChannelNumber(const cChannel *Channel, int Number); const char *ChannelName(const cChannel *Channel, int Number); +bool ParseVar(const char *Text, const char *Name, eSkinItem *Value); +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); diff --git a/contrib/skin_to_002.pl b/contrib/skin_to_002.pl new file mode 100755 index 0000000..8c94765 --- /dev/null +++ b/contrib/skin_to_002.pl @@ -0,0 +1,102 @@ +#!/usr/bin/perl + +while (defined($_ = <STDIN>)) { + /^Item=Skin/ && do { + s/version=0\.0\.1/version=0.0.2/; + }; + /^Item=MenuItem/ && do { + chomp $_; + s/;$//; + %params = map { split(/=/); } split(/,/); + print STDOUT sprintf("Item=MenuItem,width=%d,height=%d;\n", $params{width}+0, $params{height}+0); + $_ = "Item=Text,display=MenuGroups"; + $_ .= ",x=$params{x}" if defined($params{x}); + $_ .= ",y=$params{y}" if defined($params{y}); + $_ .= sprintf(",width=%d,height=%d", $params{width}+0, $params{height}+0); + $_ .= ",fg=$params{fg}" if defined($params{fg}); + $_ .= ",font=$params{font}" if defined($params{font}); + $_ .= ";\n"; + print STDOUT $_; + s/display=MenuGroups/display=MenuItems/g; + }; + /^Item=MenuCurrent/ && do { + chomp $_; + s/;$//; + %params = map { split(/=/); } split(/,/); + if (defined($params{bg})) { + $l = "Item=Rectangle,display=MenuCurrent"; + $l .= ",x=$params{x}" if defined($params{x}); + $l .= ",y=$params{x}" if defined($params{y}); + $l .= sprintf(",width=%d,height=%d", $params{width}+0, $params{height}+0); + $l .= ",fg=$params{bg}"; + $l .= ";\n"; + print STDOUT $l; + } + $_ = "Item=Text,display=MenuCurrent"; + $_ .= ",x=$params{x}" if defined($params{x}); + $_ .= ",y=$params{y}" if defined($params{y}); + $_ .= sprintf(",width=%d,height=%d", $params{width}+0, $params{height}+0); + $_ .= ",fg=$params{fg}" if defined($params{fg}); + $_ .= ",font=$params{font}" if defined($params{font}); + $_ .= ";\n"; + }; + s/^Item=DateTimeF,/Item=Text,display=DateTimeF,/; + s/^Item=DateTime,/Item=Text,display=DateTime,/; + s/^Item=Date,/Item=Text,display=Date,/; + s/^Item=Time,/Item=Text,display=Time,/; + s/^Item=ChannelNumberName,/Item=Text,display=ChannelNumberName,/; + s/^Item=ChannelNumber,/Item=Text,display=ChannelNumber,/; + s/^Item=ChannelName,/Item=Text,display=ChannelName,/; + s/^Item=ChannelLogo,/Item=Logo,display=ChannelName,/; + s/^Item=SymbolTeletext,/Item=Symbol,display=Teletext,/; + s/^Item=SymbolRadio,/Item=Symbol,display=Radio,/; + s/^Item=SymbolAudio,/Item=Symbol,display=Audio,/; + s/^Item=SymbolDolby,/Item=Symbol,display=Dolby,/; + s/^Item=SymbolEncrypted,/Item=Symbol,display=Encrypted,/; + s/^Item=SymbolRecording,/Item=Symbol,display=Recording,/; + s/^Item=Language,/Item=Logo,display=Language,/; + s/^Item=PresentTime,/Item=Text,display=PresentStartTime,/; + s/^Item=Timebar,/Item=Progress,display=PresentDuration,/; + s/^Item=PresentTitle,/Item=Text,display=PresentTitle,/; + s/^Item=PresentShortText,/Item=Text,display=PresentShortText,/; + s/^Item=FollowingTime,/Item=Text,display=FollowingStartTime,/; + s/^Item=FollowingTitle,/Item=Text,display=FollowingTitle,/; + s/^Item=FollowingShortText,/Item=Text,display=FollowingShortText,/; + s/^Item=MessageStatus,/Item=Text,display=MessageStatus,/; + s/^Item=MessageInfo,/Item=Text,display=MessageInfo,/; + s/^Item=MessageWarning,/Item=Text,display=MessageWarning,/; + s/^Item=MessageError,/Item=Text,display=MessageError,/; + s/^Item=Mute,/Item=Symbol,display=Mute,/; + s/^Item=Volumebar,/Item=Progress,display=VolumeCurrent,/; + s/^Item=SymbolPlay,/Item=Symbol,display=Play,/; + s/^Item=SymbolPause,/Item=Symbol,display=Pause,/; + s/^Item=SymbolFastFwd,/Item=Symbol,display=FastFwd,/; + s/^Item=SymbolFastRew,/Item=Symbol,display=FastRew,/; + s/^Item=SymbolSlowFwd,/Item=Symbol,display=SlowFwd,/; + s/^Item=SymbolSlowRew,/Item=Symbol,display=SlowRew,/; + s/^Item=ReplayTitle,/Item=Text,display=ReplayTitle,/; + s/^Item=ReplayJump,/Item=Text,display=ReplayPrompt,/; + s/^Item=Replaybar,/Item=Progress,display=ReplayTime,/; + s/^Item=ReplayCurrent,/Item=Text,display=ReplayTime,/; + s/^Item=ReplayTotal,/Item=Text,display=ReplayDuration,/; + s/^Item=MenuTitle,/Item=Text,display=MenuTitle,/; + s/^Item=MenuText,/Item=Scrolltext,display=MenuText,/; + s/^Item=MenuRed,/Item=Text,display=MenuRed,/; + s/^Item=MenuGreen,/Item=Text,display=MenuGreen,/; + s/^Item=MenuYellow,/Item=Text,display=MenuYellow,/; + s/^Item=MenuBlue,/Item=Text,display=MenuBlue,/; + s/^Item=MenuEventDateTimeF,/Item=Text,display=PresentDateTimeF,/; + s/^Item=MenuEventDate,/Item=Text,display=PresentDate,/; + s/^Item=MenuEventEndTime,/Item=Text,display=PresentEndTime,/; + s/^Item=MenuEventTitle,/Item=Text,display=PresentTitle,/; + s/^Item=MenuEventVPSTime,/Item=Text,display=PresentVPSTime,/; + s/^Item=MenuEventShortText,/Item=Text,display=PresentShortText,/; + s/^Item=MenuEventDescription,/Item=Scrolltext,display=PresentDescription,/; + s/^Item=SymbolEventRunning,/Item=Symbol,display=PresentRunning,/; + s/^Item=SymbolEventVPS,/Item=Symbol,display=PresentVPS,/; + s/^Item=SymbolEventTimer,/Item=Symbol,display=PresentTimer,/; + s/^Item=SymbolScrollUp,/Item=Symbol,display=MenuScrollUp,/; + s/^Item=SymbolScrollDown,/Item=Symbol,display=MenuScrollDown,/; + s/^Item=MenuRecording,/Item=Scrolltext,display=MenuRecording,/; + print STDOUT $_; +} @@ -1,36 +1,15 @@ /* - * $Id: data.c,v 1.16 2004/06/07 19:08:42 lordjaxom Exp $ + * $Id: data.c,v 1.17 2004/06/11 15:01:58 lordjaxom Exp $ */ #include "data.h" #include "common.h" -const string cText2SkinData::SectionNames[__SECTION_COUNT__] = - { "Skin", "ChannelSmall", "Channel", "Volume", "ReplayMode", "Replay", - "Message", "Menu" }; - -const string cText2SkinData::ItemNames[__ITEM_COUNT__] = - { "Unknown", "Skin", "Background", "Text", "Image", "Rectangle", "Ellipse", - "Slope", "DateTime", "Date", "Time", "ChannelLogo", "ChannelNumberName", - "ChannelNumber", "ChannelName", "Language", "Timebar", "PresentTime", - "PresentTitle", "PresentShortText", "FollowingTime", "FollowingTitle", - "FollowingShortText", "SymbolTeletext", "SymbolAudio", "SymbolDolby", - "SymbolEncrypted", "SymbolRecording", "SymbolRadio", "Volumebar", "Mute", - "Replaybar", "ReplayTitle", "ReplayCurrent", "ReplayTotal", "ReplayJump", - "SymbolPlay", "SymbolPause", "SymbolFastFwd", "SymbolFastRew", - "SymbolSlowFwd", "SymbolSlowRew", "MessageStatus", "MessageInfo", - "MessageWarning", "MessageError", "MenuArea", "MenuItem", "MenuCurrent", - "MenuTitle", "MenuRed", "MenuGreen", "MenuYellow", "MenuBlue", "MenuText", - "SymbolScrollUp", "SymbolScrollDown", "MenuEventTitle", - "MenuEventShortText", "MenuEventDescription", "MenuEventTime", - "SymbolEventRunning", "SymbolEventTimer", "SymbolEventVPS", - "MenuRecording", "MenuEventEndTime", "MenuEventVPSTime", "MenuEventDate", - "MenuEventDateTimeF", "DateTimeF" }; - cText2SkinItem::cText2SkinItem(void) { mItem = itemUnknown; - mPos.x = -1; - mPos.y = -1; + mDisplay = displayAlways; + mPos.x = 0; + mPos.y = 0; mSize.w = 0; mSize.h = 0; mBpp = 4; @@ -47,39 +26,27 @@ bool cText2SkinItem::Parse(const char *Text) { char *ptr = text; // check if this is an item - string item; - if (ParseVar(ptr, "Item", item)) { - if (item == "Skin") { // the Skin item - if (ParseVar(ptr, "name", mName) && ParseVar(ptr, "version", mVersion)) - mItem = itemSkin; - else - esyslog("ERROR: text2skin: Skin doesn't contain Item=Skin keyphrase"); - } else { - int i; - // valid items begin at index two - for (i = 2; i < __ITEM_COUNT__; ++i) { - if (cText2SkinData::ItemNames[i] == item) { - mItem = (eSkinItem)i; - break; - } + 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 (i == __ITEM_COUNT__) - esyslog("ERROR: text2skin: %s is not a valid theme item\n", item.c_str()); } if (mItem != itemUnknown) { - if (mItem != itemSkin) - ParseItem(ptr); + ParseItem(ptr); return true; } } else - esyslog("ERROR: text2skin: Missing Item= in Skin"); + esyslog("ERROR: text2skin: unknown item in skin"); // fall through return false; } bool cText2SkinItem::ParseItem(const char *Text) { + ParseVar(Text, "display", &mDisplay); ParseVar(Text, "x", &mPos.x); ParseVar(Text, "y", &mPos.y); ParseVar(Text, "width", &mSize.w); @@ -1,5 +1,5 @@ /* - * $Id: data.h,v 1.14 2004/06/07 19:08:42 lordjaxom Exp $ + * $Id: data.h,v 1.15 2004/06/11 15:01:58 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_DATA_H @@ -11,107 +11,12 @@ #include <vdr/osd.h> #include <vdr/config.h> -// sections and items known by skin files - -enum eSkinSection { - sectionSkin, - sectionChannelSmall, - sectionChannel, - sectionVolume, - sectionReplayMode, - sectionReplay, - sectionMessage, - sectionMenu, - __SECTION_COUNT__ -}; - -enum eSkinItem { - itemUnknown, - itemSkin, // item identifying the Skin itself - itemBackground, - itemText, - itemImage, - itemRectangle, - itemEllipse, - itemSlope, - itemDateTime, - itemDate, - itemTime, - itemChannelLogo, - itemChannelNumberName, - itemChannelNumber, - itemChannelName, - itemLanguage, - itemTimebar, - itemPresentTime, - itemPresentTitle, - itemPresentShortText, - itemFollowingTime, - itemFollowingTitle, - itemFollowingShortText, - itemSymbolTeletext, - itemSymbolAudio, - itemSymbolDolby, - itemSymbolEncrypted, - itemSymbolRecording, - itemSymbolRadio, - itemVolumebar, - itemMute, - itemReplaybar, - itemReplayTitle, - itemReplayCurrent, - itemReplayTotal, - itemReplayJump, - itemSymbolPlay, - itemSymbolPause, - itemSymbolFastFwd, - itemSymbolFastRew, - itemSymbolSlowFwd, - itemSymbolSlowRew, - itemMessageStatus, - itemMessageInfo, - itemMessageWarning, - itemMessageError, - itemMenuArea, - itemMenuItem, - itemMenuCurrent, - itemMenuTitle, - itemMenuRed, - itemMenuGreen, - itemMenuYellow, - itemMenuBlue, - itemMenuText, - itemSymbolScrollUp, - itemSymbolScrollDown, - itemMenuEventTitle, - itemMenuEventShortText, - itemMenuEventDescription, - itemMenuEventTime, - itemSymbolEventRunning, - itemSymbolEventTimer, - itemSymbolEventVPS, - itemMenuRecording, - itemMenuEventEndTime, - itemMenuEventVPSTime, - itemMenuEventDate, - itemMenuEventDateTimeF, - itemDateTimeF, - __ITEM_COUNT__ -}; - -struct POINT { - int x, y; -}; - -struct SIZE { - int w, h; -}; - class cText2SkinItem { friend class cText2SkinRender; private: eSkinItem mItem; + eSkinDisplay mDisplay; POINT mPos; SIZE mSize; int mBpp; @@ -138,6 +43,7 @@ public: bool Parse(const char *Text); 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; } int Bpp(void) const { return mBpp; } @@ -160,9 +66,6 @@ public: typedef vector<cText2SkinItem*> tSection; typedef tSection::iterator tIterator; - static const string SectionNames[__SECTION_COUNT__]; - static const string ItemNames[__ITEM_COUNT__]; - private: eSkinSection mCurrentSection; tSection mSections[__SECTION_COUNT__]; @@ -1,10 +1,29 @@ /* - * $Id: i18n.c,v 1.3 2004/06/07 18:23:11 lordjaxom Exp $ + * $Id: i18n.c,v 1.5 2004/06/08 20:45:52 lordjaxom Exp $ */ #include "i18n.h" const tI18nPhrase Phrases[] = { + { "Loader for text-based skins", + "", + "", + "", + "", + "", + "", + "", + "Helposti muokattavat ulkoasut", + "", + "", + "", + "", + "", + "", + "", + "", + "" + }, { "Flush image cache", "Bildspeicher leeren", "", @@ -13,7 +32,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "Tyhjennä kuvat välimuistista", "", "", "", @@ -32,7 +51,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "Tyhjennetään välimuistia...", "", "", "", @@ -104,5 +123,6 @@ bool cText2SkinI18n::Load(const string &Filename) { } string cText2SkinI18n::Translate(const string &Text) { - return I18nTranslate(Text.c_str(), mIdentity.c_str()); + string s = I18nTranslate(Text.c_str(), mIdentity.c_str()); + return s != "" ? s : Text; } @@ -1,5 +1,5 @@ /* - * $Id: loader.c,v 1.9 2004/06/07 18:23:11 lordjaxom Exp $ + * $Id: loader.c,v 1.10 2004/06/11 15:01:58 lordjaxom Exp $ */ #include "loader.h" @@ -7,6 +7,7 @@ #include "i18n.h" #include "theme.h" #include "display.h" +#include "text2skin.h" #include <vdr/plugin.h> #include <sys/types.h> #include <dirent.h> @@ -48,14 +49,18 @@ void cText2SkinLoader::Load(const char *Skin) { if (data->Load(skinfile)) { cText2SkinItem *skin = data->Get(sectionSkin, itemSkin); if (skin) { - new cText2SkinLoader(data, translations, theme, Skin, skin->Name()); + if (skin->Version() == cText2SkinPlugin::ThemeVersion()) { + 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()); return; } else - esyslog("ERROR: Item=Skin is missing in Skin\n"); + esyslog("ERROR: text2skin: Item=Skin is missing in Skin %s", Skin); } delete data; } else - esyslog("ERROR: text2skin: %s/%s is not a valid skin directory\n", SkinPath(), Skin); + esyslog("ERROR: text2skin: %s/%s is not a valid skin directory", SkinPath(), Skin); } cText2SkinLoader::cText2SkinLoader(cText2SkinData *Data, cText2SkinI18n *I18n, cText2SkinTheme *Theme, const string &Skin, const string &Description): cSkin(Skin.c_str(), Theme->Theme()) { @@ -1,5 +1,5 @@ /* - * $Id: render.c,v 1.22 2004/06/07 19:08:42 lordjaxom Exp $ + * $Id: render.c,v 1.26 2004/06/11 15:02:57 lordjaxom Exp $ */ #include "render.h" @@ -15,7 +15,7 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio tArea areas[MAXOSDAREAS]; int numAreas = 0; - SetDescription("Text2Skin: %s display update", cText2SkinData::SectionNames[Section].c_str()); + SetDescription("Text2Skin: %s display update", SectionNames[Section].c_str()); mData = Loader->Data(); mI18n = Loader->I18n(); @@ -25,8 +25,8 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio mScroller = NULL; mChannel = NULL; mChannelNumber = 0; - mVolumeCurrent = 0; - mVolumeTotal = 0; + mVolumeCurrent = -1; + mVolumeTotal = -1; mVolumeMute = false; mReplayPlay = false; mReplayForward = false; @@ -45,6 +45,7 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio mMenuScrollUp = false; mMenuScrollPage = false; mActive = false; + mUpdateIn = 0; cText2SkinData::tIterator it = mData->First(mSection); for (; it != mData->Last(mSection); ++it) { @@ -87,15 +88,13 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio esyslog("ERROR: text2skin: OSD provider can't handle skin: %s\n", emsg); } - //Start(); + Start(); } cText2SkinRender::~cText2SkinRender() { if (mActive) { - mMutex.Lock(); mActive = false; - mDoUpdate.Broadcast(); - mMutex.Unlock(); + TriggerUpdate(); Cancel(3); } delete mScroller; @@ -106,119 +105,130 @@ void cText2SkinRender::Action(void) { mActive = true; Lock(); while (mActive) { - mDoUpdate.Wait(mMutex); + bool res = true; + if (mUpdateIn) res = mDoUpdate.TimedWait(mMutex, mUpdateIn); + else mDoUpdate.Wait(mMutex); + + if (!mActive) break; // fall out if thread to be stopped + + mUpdateIn = 0; // has to be re-set within Update(); + Update(); } Unlock(); } -void cText2SkinRender::Flush(void) { +void cText2SkinRender::Update(void) { cText2SkinData::tIterator it = mData->First(mSection); for (; it != mData->Last(mSection); ++it) { - cText2SkinItem *item = (*it); - switch (item->Item()) { - case itemBackground: - DisplayBackground(item); break; - case itemChannelLogo: - DisplayChannelLogo(item); break; - case itemLanguage: - DisplayLanguage(item); break; - case itemText: - DisplayText(item); break; - case itemImage: - DisplayImage(item); break; - case itemDateTime: - case itemDate: - case itemTime: - case itemDateTimeF: - DisplayDateTime(item); break; - case itemChannelNumberName: - DisplayChannelNumberName(item); break; - case itemChannelNumber: - DisplayChannelNumber(item); break; - case itemChannelName: - DisplayChannelName(item); break; - case itemRectangle: - DisplayRectangle(item); break; - case itemEllipse: - DisplayEllipse(item); break; - case itemSlope: - DisplaySlope(item); break; - case itemTimebar: - DisplayTimebar(item); break; - case itemPresentTime: - DisplayPresentTime(item); break; - case itemPresentTitle: - DisplayPresentTitle(item); break; - case itemPresentShortText: - DisplayPresentShortText(item); break; - case itemFollowingTime: - DisplayFollowingTime(item); break; - case itemFollowingTitle: - DisplayFollowingTitle(item); break; - case itemFollowingShortText: - DisplayFollowingShortText(item); break; - case itemSymbolTeletext: - case itemSymbolAudio: - case itemSymbolDolby: - case itemSymbolEncrypted: - case itemSymbolRecording: - case itemSymbolRadio: - case itemSymbolPlay: - case itemSymbolPause: - case itemSymbolFastFwd: - case itemSymbolFastRew: - case itemSymbolSlowFwd: - case itemSymbolSlowRew: - case itemSymbolScrollUp: - case itemSymbolScrollDown: - case itemSymbolEventRunning: - case itemSymbolEventTimer: - case itemSymbolEventVPS: - DisplaySymbol(item); break; - case itemVolumebar: - DisplayVolumebar(item); break; - case itemMute: - DisplayMute(item); break; - case itemReplaybar: - DisplayReplaybar(item); break; - case itemReplayTitle: - DisplayReplayTitle(item); break; - case itemReplayCurrent: - DisplayReplayCurrent(item); break; - case itemReplayTotal: - DisplayReplayTotal(item); break; - case itemReplayJump: - DisplayReplayJump(item); break; - case itemMessageInfo: - case itemMessageStatus: - case itemMessageWarning: - case itemMessageError: - DisplayMessage(item); break; - case itemMenuItem: - DisplayMenuItems(item); break; - case itemMenuTitle: - DisplayMenuTitle(item); break; - case itemMenuRed: - case itemMenuGreen: - case itemMenuYellow: - case itemMenuBlue: - DisplayMenuColorbutton(item); break; - case itemMenuText: - DisplayMenuText(item); break; - case itemMenuEventTitle: - DisplayMenuEventTitle(item); break; - case itemMenuEventShortText: - DisplayMenuEventShortText(item); break; - case itemMenuEventDescription: - DisplayMenuEventDescription(item); break; - case itemMenuEventTime: - case itemMenuEventEndTime: - case itemMenuEventVPSTime: - case itemMenuEventDate: - case itemMenuEventDateTimeF: - DisplayMenuEventTime(item); break; - case itemMenuRecording: - DisplayMenuRecording(item); break; + switch ((*it)->Display()) { + case displayAlways: + DisplayItem(*it); + break; + case displayDateTimeF: + case displayDateTime: + case displayDate: + case displayTime: + DisplayDateTime(*it); + break; + case displayChannelNumberName: + case displayChannelNumber: + case displayChannelName: + DisplayChannelNumberName(*it); + break; + case displayPresentDateTimeF: + case displayPresentStartTime: + case displayPresentDate: + case displayPresentVPSTime: + case displayPresentEndTime: + case displayPresentDuration: + DisplayPresentTime(*it); + break; + case displayPresentVPS: + case displayPresentRunning: + case displayPresentTimer: + DisplayPresentIcon(*it); + break; + case displayPresentTitle: + case displayPresentShortText: + case displayPresentDescription: + DisplayPresentText(*it); + break; + case displayFollowingStartTime: + case displayFollowingEndTime: + case displayFollowingDuration: + DisplayFollowingTime(*it); + break; + case displayFollowingTitle: + DisplayFollowingTitle(*it); + break; + case displayFollowingShortText: + DisplayFollowingShortText(*it); + break; + case displayLanguage: + DisplayLanguage(*it); + break; + case displayTeletext: + case displayAudio: + case displayDolby: + case displayEncrypted: + case displayRecording: + case displayRadio: + DisplayChannelIcon(*it); + break; + case displayVolumeCurrent: + case displayVolumeTotal: + DisplayVolume(*it); + break; + case displayMute: + DisplayMuteIcon(*it); + break; + case displayReplayTime: + case displayReplayDuration: + DisplayReplayTime(*it); + break; + case displayReplayTitle: + DisplayReplayTitle(*it); + break; + case displayReplayPrompt: + DisplayReplayPrompt(*it); + break; + case displayPlay: + case displayPause: + case displayFastFwd: + case displayFastRew: + case displaySlowFwd: + case displaySlowRew: + DisplayReplaySymbol(*it); + break; + case displayMessage: + case displayMessageStatus: + case displayMessageInfo: + case displayMessageWarning: + case displayMessageError: + DisplayMessage(*it); + break; + case displayMenuTitle: + DisplayMenuTitle(*it); + break; + case displayMenuRed: + case displayMenuGreen: + case displayMenuYellow: + case displayMenuBlue: + DisplayMenuButton(*it); + break; + case displayMenuText: + case displayMenuRecording: + DisplayMenuText(*it); + break; + case displayMenuScrollUp: + case displayMenuScrollDown: + DisplayMenuScrollIcon(*it); + break; + case displayMenuItems: + case displayMenuCurrent: + case displayMenuGroups: + DisplayMenuItems(*it); + break; default: break; } @@ -239,7 +249,7 @@ void cText2SkinRender::DrawBackground(const POINT &Pos, const SIZE &Size, const } if (bmp) - mOsd->DrawBitmap(Pos.x, Pos.y, *bmp); + mOsd->DrawBitmap(Pos.x, Pos.y, bmp->Get(mUpdateIn)); else mOsd->DrawRectangle(Pos.x, Pos.y, Pos.x + Size.w - 1, Pos.y + Size.h - 1, Bg ? *Bg : 0); } @@ -252,7 +262,7 @@ void cText2SkinRender::DrawImage(const POINT &Pos, const SIZE &Size, const tColo if ((bmp = cText2SkinBitmap::Load(p)) != NULL) { if (Bg) bmp->SetColor(0, *Bg); if (Fg) bmp->SetColor(1, *Fg); - mOsd->DrawBitmap(Pos.x, Pos.y, *bmp); + mOsd->DrawBitmap(Pos.x, Pos.y, bmp->Get(mUpdateIn)); } free(p); } @@ -355,382 +365,532 @@ void cText2SkinRender::DrawScrollText(const POINT &Pos, const SIZE &Size, const } } -void cText2SkinRender::DisplayBackground(cText2SkinItem *Item) { - DrawBackground(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Path()); -} - -void cText2SkinRender::DisplayChannelLogo(cText2SkinItem *Item) { - if (Item->Type() != "" && mChannel) { - string path = Item->Path() + "/" + ChannelName(mChannel, mChannelNumber) + "." + Item->Type(); - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), path); +void cText2SkinRender::DisplayItem(cText2SkinItem *Item, const ItemData *Data) { + static ItemData dummyData; + if (Data == NULL) Data = &dummyData; + switch (Item->Item()) { + case itemBackground: + DrawBackground(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Path()); + break; + case itemText: + 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()); + break; + case itemImage: + DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Path()); + break; + case itemLogo: + case itemSymbol: + DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Data->path); + break; + case itemRectangle: + DrawRectangle(Item->Pos(), Item->Size(), ItemFg(Item)); + break; + case itemEllipse: + DrawEllipse(Item->Pos(), Item->Size(), ItemFg(Item), Item->Arc()); + break; + case itemSlope: + DrawSlope(Item->Pos(), Item->Size(), ItemFg(Item), Item->Arc()); + break; + case itemProgress: + DrawProgressbar(Item->Pos(), Item->Size(), Data->current, Data->total, ItemBg(Item), ItemFg(Item), Data->marks); + break; + default: + break; } } -void cText2SkinRender::DisplayLanguage(cText2SkinItem *Item) { - int current; - const char **tracks = cDevice::PrimaryDevice()->GetAudioTracks(¤t); - if (Item->Path() != "" && Item->Type() != "" && tracks) { - Dprintf("Languages: "); - int i = 0; - while (tracks[i]) { - Dprintf("%s%s, ", tracks[i], i == current ? " (current)" : ""); - ++i; - } - Dprintf("\n"); - if (current < i) { - string path = Item->Path() + "/" + tracks[current] + "." + Item->Type(); - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), path); - } +void cText2SkinRender::DisplayDateTime(cText2SkinItem *Item) { + ItemData data; + char text[1000]; + time_t t = time(NULL); + struct tm tm_r, *tm; + *text = '\0'; + tm = localtime_r(&t, &tm_r); + + switch (Item->Display()) { + case displayDateTimeF: + strftime(text, 1000, Item->Format().c_str(), tm); + break; + case displayDateTime: + strftime(text, 1000, "%a %e.%m. %H:%M", tm); + break; + case displayDate: + strftime(text, 1000, "%e.%m.", tm); + break; + case displayTime: + strftime(text, 1000, "%H:%M", tm); + break; + default: + break; } -} -void cText2SkinRender::DisplayText(cText2SkinItem *Item) { - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item), Item->Font(), Item->Align()); + data.text = text; + DisplayItem(Item, &data); } -void cText2SkinRender::DisplayImage(cText2SkinItem *Item) { - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Path()); +void cText2SkinRender::DisplayChannelNumberName(cText2SkinItem *Item) { + if (mChannel || mChannelNumber) { + ItemData data; + data.path = Item->Path() + "/" + ChannelName(mChannel, mChannelNumber) + "." + Item->Type(); + switch (Item->Display()) { + case displayChannelNumberName: + data.text = ChannelString(mChannel, mChannelNumber); + break; + case displayChannelNumber: + data.text = ChannelNumber(mChannel, mChannelNumber); + break; + case displayChannelName: + data.text = ChannelName(mChannel, mChannelNumber); + break; + default: + break; + } + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayDateTime(cText2SkinItem *Item) { - char *text = NULL; - time_t t; - t = time(NULL); - switch (Item->Item()) { - case itemDateTime: - text = strdup(DayDateTime(t)); break; - case itemDate: - text = strdup(DayDateTime(t) + 4); text[5] = '\0'; break; - case itemTime: - text = strdup(DayDateTime(t) + 13); text[5] = '\0'; break; - case itemDateTimeF: - { - struct tm tm_r, *tm; - tm = localtime_r(&t, &tm_r); - text = MALLOC(char, 1000); - strftime(text, 1000, Item->Format().c_str(), tm); - } +void cText2SkinRender::DisplayPresentTime(cText2SkinItem *Item) { + const cEvent *event = NULL; + switch (mSection) { + case sectionChannel: + case sectionChannelSmall: + event = mChannelPresent; + break; + case sectionMenu: + event = mMenuEvent; break; default: break; } - if (text) { - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, text), Item->Font(), Item->Align()); - free(text); - } -} -void cText2SkinRender::DisplayChannelNumberName(cText2SkinItem *Item) { - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, ChannelString(mChannel, mChannelNumber)), Item->Font(), Item->Align()); + if (event && event->StartTime()) { + ItemData data; + char text[1000]; + const char *f = "%H:%M"; + time_t t = 0, n = time(NULL); + struct tm tm_r, *tm; + *text = '\0'; + data.path = Item->Path(); + + switch (Item->Display()) { + case displayPresentDateTimeF: + f = Item->Format().c_str(); + t = event->StartTime(); + break; + case displayPresentStartTime: + t = event->StartTime(); + break; + case displayPresentDate: + f = "%e.%m."; + t = event->StartTime(); + break; + case displayPresentVPSTime: + t = event->Vps(); + break; + case displayPresentEndTime: + t = event->EndTime(); + break; + case displayPresentDuration: + t = event->Duration(); + break; + default: + break; + } + + if (t) { + tm = localtime_r(&t, &tm_r); + strftime(text, 1000, f, tm); + data.text = text; + data.total = event->Duration(); + data.current = n - event->StartTime(); + DisplayItem(Item, &data); + } + } } -void cText2SkinRender::DisplayChannelNumber(cText2SkinItem *Item) { - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, ChannelNumber(mChannel, mChannelNumber)), Item->Font(), Item->Align()); -} +void cText2SkinRender::DisplayPresentIcon(cText2SkinItem *Item) { + const cEvent *event = NULL; + switch (mSection) { + case sectionChannel: + case sectionChannelSmall: + event = mChannelPresent; + break; + case sectionMenu: + event = mMenuEvent; + break; + default: + break; + } -void cText2SkinRender::DisplayChannelName(cText2SkinItem *Item) { - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, ChannelName(mChannel, mChannelNumber)), Item->Font(), Item->Align()); + if (event) { + ItemData data; + switch (Item->Display()) { + case displayPresentVPS: + data.path = event->Vps() && event->Vps() != event->StartTime() ? Item->Path() : Item->AltPath(); + break; + case displayPresentRunning: + data.path = event->IsRunning() ? Item->Path() : Item->AltPath(); + break; + case displayPresentTimer: + data.path = event->HasTimer() ? Item->Path() : Item->AltPath(); + break; + default: + break; + } + if (data.path != "") + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayRectangle(cText2SkinItem *Item) { - DrawRectangle(Item->Pos(), Item->Size(), ItemFg(Item)); - -} +void cText2SkinRender::DisplayPresentText(cText2SkinItem *Item) { + const cEvent *event = NULL; + switch (mSection) { + case sectionChannel: + case sectionChannelSmall: + event = mChannelPresent; + break; + case sectionMenu: + event = mMenuEvent; + break; + default: + break; + } + + if (event) { + const char *text = NULL; + switch (Item->Display()) { + case displayPresentTitle: + text = event->Title(); + break; + case displayPresentShortText: + text = event->ShortText(); + break; + case displayPresentDescription: + text = event->Description(); + break; + default: + break; + } -void cText2SkinRender::DisplayEllipse(cText2SkinItem *Item) { - DrawEllipse(Item->Pos(), Item->Size(), ItemFg(Item), Item->Arc()); + if (text) { + ItemData data; + data.text = text; + DisplayItem(Item, &data); + } + } } -void cText2SkinRender::DisplaySlope(cText2SkinItem *Item) { - DrawSlope(Item->Pos(), Item->Size(), ItemFg(Item), Item->Arc()); -} +void cText2SkinRender::DisplayFollowingTime(cText2SkinItem *Item) { + if (mChannelFollowing && mChannelFollowing->StartTime()) { + ItemData data; + char text[1000]; + time_t t = 0, n = time(NULL); + struct tm tm_r, *tm; + *text = '\0'; + + switch (Item->Display()) { + case displayFollowingStartTime: + t = mChannelFollowing->StartTime(); + break; + case displayFollowingEndTime: + t = mChannelFollowing->EndTime(); + break; + case displayFollowingDuration: + t = mChannelFollowing->Duration(); + break; + default: + break; + } -void cText2SkinRender::DisplayTimebar(cText2SkinItem *Item) { - time_t now = time(NULL); - if (mChannelPresent && mChannelPresent->StartTime() && mChannelPresent->Duration() && now > mChannelPresent->StartTime()) { - int total = mChannelPresent->Duration(); - int current = now - mChannelPresent->StartTime(); - DrawProgressbar(Item->Pos(), Item->Size(), current, total, ItemBg(Item), ItemFg(Item)); + tm = localtime_r(&t, &tm_r); + strftime(text, 1000, "%H:%M", tm); + data.text = text; + data.total = mChannelFollowing->Duration(); + data.current = n - mChannelFollowing->StartTime(); + DisplayItem(Item, &data); } } -void cText2SkinRender::DisplayPresentTime(cText2SkinItem *Item) { - if (mChannelPresent) { - const char *text = DayDateTime(mChannelPresent->StartTime()); - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, text + 10), Item->Font(), Item->Align()); +void cText2SkinRender::DisplayFollowingTitle(cText2SkinItem *Item) { + if (mChannelFollowing && mChannelFollowing->Title()) { + ItemData data; + data.text = mChannelFollowing->Title(); + DisplayItem(Item, &data); } } -void cText2SkinRender::DisplayPresentTitle(cText2SkinItem *Item) { - if (mChannelPresent && mChannelPresent->Title()) - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mChannelPresent->Title()), Item->Font(), Item->Align()); +void cText2SkinRender::DisplayFollowingShortText(cText2SkinItem *Item) { + if (mChannelFollowing && mChannelFollowing->ShortText()) { + ItemData data; + data.text = mChannelFollowing->ShortText(); + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayPresentShortText(cText2SkinItem *Item) { - if (mChannelPresent && mChannelPresent->ShortText()) - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mChannelPresent->ShortText()), Item->Font(), Item->Align()); -} +void cText2SkinRender::DisplayLanguage(cText2SkinItem *Item) { + int current; + const char **tracks = cDevice::PrimaryDevice()->GetAudioTracks(¤t); + if (tracks) { + Dprintf("Languages: "); + int i; + for (i = 0; tracks[i] != NULL; ++i) + Dprintf("%s%s, ", tracks[i], i == current ? " (current)" : ""); + Dprintf("\n"); -void cText2SkinRender::DisplayFollowingTime(cText2SkinItem *Item) { - if (mChannelFollowing) { - const char *text = DayDateTime(mChannelFollowing->StartTime()); - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, text + 10), Item->Font(), Item->Align()); + if (current < i) { + ItemData data; + data.text = tracks[current]; + data.path = Item->Path() + "/" + tracks[current] + "." + Item->Type(); + DisplayItem(Item, &data); + } } } -void cText2SkinRender::DisplayFollowingTitle(cText2SkinItem *Item) { - if (mChannelFollowing && mChannelFollowing->Title()) - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mChannelFollowing->Title()), Item->Font(), Item->Align()); -} - -void cText2SkinRender::DisplayFollowingShortText(cText2SkinItem *Item) { - if (mChannelFollowing && mChannelFollowing->ShortText()) - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mChannelFollowing->ShortText()), Item->Font(), Item->Align()); -} - -void cText2SkinRender::DisplaySymbol(cText2SkinItem *Item) { - string image; - if (mSection == sectionChannel && mChannel) { - switch (Item->Item()) { - case itemSymbolTeletext: - image = mChannel->Tpid() ? Item->Path() : Item->AltPath(); break; - case itemSymbolAudio: - image = mChannel->Apid2() ? Item->Path() : Item->AltPath(); break; - case itemSymbolDolby: - image = mChannel->Dpid1() ? Item->Path() : Item->AltPath(); break; - case itemSymbolEncrypted: - image = mChannel->Ca() ? Item->Path() : Item->AltPath(); break; - case itemSymbolRadio: - image = (mChannel->Vpid() == 0 || mChannel->Vpid() == 1 || mChannel->Vpid() == 0x1FFF) ? Item->Path() : Item->AltPath(); break; - case itemSymbolRecording: - image = cRecordControls::Active() ? Item->Path() : Item->AltPath(); break; - default: +void cText2SkinRender::DisplayChannelIcon(cText2SkinItem *Item) { + if (mChannel && !mChannel->GroupSep()) { + ItemData data; + switch (Item->Display()) { + case displayTeletext: + data.path = mChannel->Tpid() ? Item->Path() : Item->AltPath(); + break; + case displayAudio: + data.path = mChannel->Apid2() ? Item->Path() : Item->AltPath(); + break; + case displayDolby: + data.path = mChannel->Dpid1() ? Item->Path() : Item->AltPath(); + break; + case displayEncrypted: + data.path = mChannel->Ca() ? Item->Path() : Item->AltPath(); + break; + case displayRadio: + data.path = mChannel->Vpid() == 0 || mChannel->Vpid() == 1 || mChannel->Vpid() == 0x1FFF ? Item->Path() : Item->AltPath(); + break; + case displayRecording: + data.path = cRecordControls::Active() ? Item->Path() : Item->AltPath(); break; - } - } else if (mSection == sectionReplay || mSection == sectionReplayMode) { - switch (Item->Item()) { - case itemSymbolPlay: - image = (mReplaySpeed == -1 && mReplayPlay) ? Item->Path() : Item->AltPath(); break; - case itemSymbolPause: - image = (mReplaySpeed == -1 && !mReplayPlay) ? Item->Path() : Item->AltPath(); break; - case itemSymbolFastFwd: - image = (mReplaySpeed != -1 && mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath(); break; - case itemSymbolFastRew: - image = (mReplaySpeed != -1 && mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath(); break; - case itemSymbolSlowFwd: - image = (mReplaySpeed != -1 && !mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath(); break; - case itemSymbolSlowRew: - image = (mReplaySpeed != -1 && !mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath(); break; default: break; } - } else if (mSection == sectionMenu) { - if (mScroller) { - switch (Item->Item()) { - case itemSymbolScrollUp: - image = mScroller->CanScrollUp() ? Item->Path() : Item->AltPath(); break; - case itemSymbolScrollDown: - image = mScroller->CanScrollDown() ? Item->Path() : Item->AltPath(); break; - default: - break; - } - } - if (mMenuEvent) { - switch (Item->Item()) { - case itemSymbolEventRunning: - image = mMenuEvent->IsRunning() ? Item->Path() : Item->AltPath(); break; - case itemSymbolEventTimer: - image = mMenuEvent->HasTimer() ? Item->Path() : Item->AltPath(); break; - case itemSymbolEventVPS: - image = mMenuEvent->Vps() > 0 ? Item->Path() : Item->AltPath(); break; - default: - break; - } - } + if (data.path != "") + DisplayItem(Item, &data); } - if (image != "") - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), image); } -void cText2SkinRender::DisplayVolumebar(cText2SkinItem *Item) { - if (mVolumeTotal && mVolumeCurrent <= mVolumeTotal) { - int total = mVolumeTotal; - int current = mVolumeCurrent; - DrawProgressbar(Item->Pos(), Item->Size(), current, total, ItemBg(Item), ItemFg(Item)); +void cText2SkinRender::DisplayVolume(cText2SkinItem *Item) { + if (mVolumeTotal && mVolumeCurrent <= mVolumeTotal && !mVolumeMute) { + ItemData data; + char *text = NULL; + data.total = mVolumeTotal; + data.current = mVolumeCurrent; + switch (Item->Display()) { + case displayVolumeCurrent: + asprintf(&text, "%d", mVolumeCurrent); + break; + case displayVolumeTotal: + asprintf(&text, "%d", mVolumeTotal); + break; + default: + break; + } + if (text) { + data.text = text; + free(text); + } + DisplayItem(Item, &data); } } -void cText2SkinRender::DisplayMute(cText2SkinItem *Item) { +void cText2SkinRender::DisplayMuteIcon(cText2SkinItem *Item) { if (mVolumeMute) { - if (Item->Path() != "") - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->Path()); - if (Item->Text() != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), Item->Text(), Item->Font(), Item->Align()); - } else if (Item->Path() != "") - DrawImage(Item->Pos(), Item->Size(), ItemBg(Item), ItemFg(Item), Item->AltPath()); + ItemData data; + data.path = Item->Path(); + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayReplaybar(cText2SkinItem *Item) { +void cText2SkinRender::DisplayReplayTime(cText2SkinItem *Item) { if (mReplayTotal && mReplayCurrent <= mReplayTotal) { - int total = mReplayTotal; - int current = mReplayCurrent; - DrawProgressbar(Item->Pos(), Item->Size(), current, total, ItemBg(Item), ItemFg(Item), mReplayMarks); + ItemData data; + data.total = mReplayTotal; + data.current = mReplayCurrent; + data.marks = mReplayMarks; + switch (Item->Display()) { + case displayReplayTime: + data.text = mReplayCurrentText; + break; + case displayReplayDuration: + data.text = mReplayTotalText; + break; + default: + break; + } + DisplayItem(Item, &data); } } void cText2SkinRender::DisplayReplayTitle(cText2SkinItem *Item) { - if (mReplayTitle != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mReplayTitle), Item->Font(), Item->Align()); + if (mReplayTitle != "") { + ItemData data; + data.text = mReplayTitle; + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayReplayCurrent(cText2SkinItem *Item) { - if (mReplayCurrentText != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mReplayCurrentText), Item->Font(), Item->Align()); -} - -void cText2SkinRender::DisplayReplayTotal(cText2SkinItem *Item) { - if (mReplayTotalText != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mReplayTotalText), Item->Font(), Item->Align()); -} - -void cText2SkinRender::DisplayReplayJump(cText2SkinItem *Item) { - if (mReplayJump != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mReplayJump), Item->Font(), Item->Align()); +void cText2SkinRender::DisplayReplayPrompt(cText2SkinItem *Item) { + if (mReplayJump != "") { + ItemData data; + data.text = mReplayJump; + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayMessage(cText2SkinItem *Item) { - string text; - switch (Item->Item()) { - case itemMessageStatus: - if (mMessageType == mtStatus) text = mMessageText; break; - case itemMessageInfo: - if (mMessageType == mtInfo) text = mMessageText; break; - case itemMessageWarning: - if (mMessageType == mtWarning) text = mMessageText; break; - case itemMessageError: - if (mMessageType == mtError) text = mMessageText; break; +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 (text != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, text), Item->Font(), Item->Align()); + DisplayItem(Item, &data); } -void cText2SkinRender::DisplayMenuItems(cText2SkinItem *Item) { - cText2SkinItem *area = mData->Get(sectionMenu, itemMenuArea); - cText2SkinItem *current = mData->Get(sectionMenu, itemMenuCurrent); - int xoffs = area->Pos().x; - int yoffs = area->Pos().y; - - if (Item->Pos().x != -1) - xoffs += Item->Pos().x; - if (Item->Pos().y != -1) - yoffs += Item->Pos().y; - - int index = 0; - while (yoffs < area->Pos().y + area->Size().h && index < (int)mMenuItems.size()) { - cText2SkinItem *item = (index == mMenuCurrent) ? current : Item; - POINT pt = { xoffs, yoffs }; - SIZE size = item->Size(); - if (item->Pos().x != -1) - pt.x += item->Pos().x; - if (item->Pos().y != -1) - pt.y += item->Pos().y; - if (ItemBg(item)) - DrawRectangle(pt, size, ItemBg(item)); - - for (int i = 0; i < cSkinDisplayMenu::MaxTabs; ++i) { - if (mMenuItems[index].tabs[i] != "") { - POINT pt2 = { pt.x + mMenuTabs[i], pt.y }; - SIZE sz = { size.w - mMenuTabs[i], size.h }; - DrawText(pt2, sz, ItemFg(item), mMenuItems[index].tabs[i], item->Font(), item->Align()); - } - if (!mMenuTabs[i + 1]) - break; - } - - yoffs += Item->Size().h; - ++index; +void cText2SkinRender::DisplayMessage(cText2SkinItem *Item) { + if (mMessageText != "" && (Item->Display() == displayMessage || (Item->Display() - displayMessageStatus) == mMessageType)) { + ItemData data; + data.text = mMessageText; + DisplayItem(Item, &data); } } void cText2SkinRender::DisplayMenuTitle(cText2SkinItem *Item) { - if (mMenuTitle != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mMenuTitle), Item->Font(), Item->Align()); + if (mMenuTitle != "") { + ItemData data; + data.text = mMenuTitle; + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayMenuColorbutton(cText2SkinItem *Item) { - string text; - switch (Item->Item()) { - case itemMenuRed: - text = mMenuRed; break; - case itemMenuGreen: - text = mMenuGreen; break; - case itemMenuYellow: - text = mMenuYellow; break; - case itemMenuBlue: - text = mMenuBlue; break; - default: break; +void cText2SkinRender::DisplayMenuButton(cText2SkinItem *Item) { + ItemData data; + switch (Item->Display()) { + case displayMenuRed: + data.text = mMenuRed; + break; + case displayMenuGreen: + data.text = mMenuGreen; + break; + case displayMenuYellow: + data.text = mMenuYellow; + break; + case displayMenuBlue: + data.text = mMenuBlue; + break; + default: + break; } - if (text != "") - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, text), Item->Font(), Item->Align()); + if (data.text != "") + DisplayItem(Item, &data); } void cText2SkinRender::DisplayMenuText(cText2SkinItem *Item) { - if (mMenuText != "") - DrawScrollText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mMenuText), Item->Font(), Item->Align()); -} + ItemData data; -void cText2SkinRender::DisplayMenuEventTitle(cText2SkinItem *Item) { - if (mMenuEvent && mMenuEvent->Title()) - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mMenuEvent->Title()), Item->Font(), Item->Align()); -} - -void cText2SkinRender::DisplayMenuEventShortText(cText2SkinItem *Item) { - if (mMenuEvent && mMenuEvent->ShortText()) - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mMenuEvent->ShortText()), Item->Font(), Item->Align()); -} - -void cText2SkinRender::DisplayMenuEventDescription(cText2SkinItem *Item) { - if (mMenuEvent && mMenuEvent->Description()) - DrawScrollText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mMenuEvent->Description()), Item->Font(), Item->Align()); + switch (Item->Display()) { + case displayMenuText: + data.text = mMenuText; + break; + case displayMenuRecording: + if (mMenuRecording && mMenuRecording->Summary()) + data.text = mMenuRecording->Summary(); + break; + default: + break; + } + if (data.text != "") + DisplayItem(Item, &data); } -void cText2SkinRender::DisplayMenuEventTime(cText2SkinItem *Item) { - if (mMenuEvent) { - char *text = NULL; - Dprintf("DATE: %s\n", DayDateTime(mMenuEvent->StartTime())); - switch (Item->Item()) { - case itemMenuEventTime: - text = strdup(DayDateTime(mMenuEvent->StartTime()) + 10); break; - case itemMenuEventEndTime: - text = strdup(DayDateTime(mMenuEvent->EndTime()) + 10); break; - case itemMenuEventVPSTime: - text = mMenuEvent->Vps() != mMenuEvent->StartTime() ? strdup(DayDateTime(mMenuEvent->Vps()) + 10) : NULL; break; - case itemMenuEventDate: - text = strdup(DayDateTime(mMenuEvent->StartTime()) + 4); text[5] = '\0'; break; - case itemMenuEventDateTimeF: - { - time_t t = mMenuEvent->StartTime(); - struct tm tm_r, *tm; - tm = localtime_r(&t, &tm_r); - text = MALLOC(char, 1000); - strftime(text, 1000, Item->Format().c_str(), tm); - } +void cText2SkinRender::DisplayMenuScrollIcon(cText2SkinItem *Item) { + if (mScroller) { + ItemData data; + switch (Item->Display()) { + case displayMenuScrollUp: + data.path = mScroller->CanScrollUp() ? Item->Path() : Item->AltPath(); + break; + case displayMenuScrollDown: + data.path = mScroller->CanScrollDown() ? Item->Path() : Item->AltPath(); break; default: break; } - if (text) { - DrawText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, text), Item->Font(), Item->Align()); - free(text); - } - } + if (data.path != "") + DisplayItem(Item, &data); + } } -void cText2SkinRender::DisplayMenuRecording(cText2SkinItem *Item) { - if (mMenuRecording) - DrawScrollText(Item->Pos(), Item->Size(), ItemFg(Item), ItemText(Item, mMenuRecording->Summary()), Item->Font(), Item->Align()); +void cText2SkinRender::DisplayMenuItems(cText2SkinItem *Item) { + cText2SkinItem *area = mData->Get(sectionMenu, itemMenuArea); + cText2SkinItem *item = mData->Get(sectionMenu, itemMenuItem); + + if (item && area) { + POINT pos = area->Pos(); + + int max = area->Size().h / item->Size().h; + for (int i = 0; i < min((int)mMenuItems.size(), max); ++i) { + switch (Item->Display()) { + case displayMenuItems: + if (i == mMenuCurrent || !mMenuItems[i].sel) + continue; + break; + case displayMenuCurrent: + if (i != mMenuCurrent) + continue; + break; + case displayMenuGroups: + if (mMenuItems[i].sel) + continue; + break; + default: + break; + } + + POINT itempos = pos; + itempos.y += i * item->Size().h; + itempos += Item->Pos(); + for (int t = 0; t < cSkinDisplayMenu::MaxTabs; ++t) { + if (mMenuItems[i].tabs[t] != "") { + POINT abspos = { itempos.x + mMenuTabs[t], itempos.y }; + ItemData data; + cText2SkinItem cur = *Item; + cur.mPos = abspos; + data.text = mMenuItems[i].tabs[t]; + DisplayItem(&cur, &data); + } + if (!mMenuTabs[t + 1]) + break; + } + } + } } string cText2SkinRender::ItemText(cText2SkinItem *Item) { @@ -774,10 +934,12 @@ tColor *cText2SkinRender::ItemBg(cText2SkinItem *Item) { } int cText2SkinRender::GetEditableWidth(MenuItem Item, bool Current) { - cText2SkinItem *current; + /*cText2SkinItem *current; if (Current) current = mData->Get(sectionMenu, itemMenuCurrent); else current = mData->Get(sectionMenu, itemMenuItem); return current->Size().w - mMenuTabs[1]; + */ + return 0; } @@ -1,5 +1,5 @@ /* - * $Id: render.h,v 1.17 2004/06/07 19:08:42 lordjaxom Exp $ + * $Id: render.h,v 1.20 2004/06/11 15:01:58 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_RENDER_H @@ -33,6 +33,15 @@ private: cOsd *mOsd; cTextScroller *mScroller; + struct ItemData { + string text; + string path; + int current; + int total; + const cMarks *marks; + ItemData(void) { marks = NULL; } + }; + // channel display const cChannel *mChannel; int mChannelNumber; @@ -87,6 +96,7 @@ private: bool mActive; cCondVar mDoUpdate; cMutex mMutex; + int mUpdateIn; protected: // Update thread @@ -105,44 +115,32 @@ protected: 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); + // displays a full item + void DisplayItem(cText2SkinItem *Item, const ItemData *Data = NULL); + // High-level operations - void DisplayBackground(cText2SkinItem *Item); - void DisplayChannelLogo(cText2SkinItem *Item); - void DisplayLanguage(cText2SkinItem *Item); - void DisplayText(cText2SkinItem *Item); - void DisplayImage(cText2SkinItem *Item); - void DisplayDateTime(cText2SkinItem *Item); - void DisplayChannelNumberName(cText2SkinItem *Item); - void DisplayChannelNumber(cText2SkinItem *Item); - void DisplayChannelName(cText2SkinItem *Item); - void DisplayRectangle(cText2SkinItem *Item); - void DisplayEllipse(cText2SkinItem *Item); - void DisplaySlope(cText2SkinItem *Item); - void DisplayTimebar(cText2SkinItem *Item); + void DisplayDateTime(cText2SkinItem *Item); + void DisplayChannelNumberName(cText2SkinItem *Item); void DisplayPresentTime(cText2SkinItem *Item); - void DisplayPresentTitle(cText2SkinItem *Item); - void DisplayPresentShortText(cText2SkinItem *Item); + void DisplayPresentIcon(cText2SkinItem *Item); + void DisplayPresentText(cText2SkinItem *Item); void DisplayFollowingTime(cText2SkinItem *Item); void DisplayFollowingTitle(cText2SkinItem *Item); void DisplayFollowingShortText(cText2SkinItem *Item); - void DisplaySymbol(cText2SkinItem *Item); - void DisplayVolumebar(cText2SkinItem *Item); - void DisplayMute(cText2SkinItem *Item); - void DisplayReplaybar(cText2SkinItem *Item); + void DisplayLanguage(cText2SkinItem *Item); + void DisplayChannelIcon(cText2SkinItem *Item); + void DisplayVolume(cText2SkinItem *Item); + void DisplayMuteIcon(cText2SkinItem *Item); + void DisplayReplayTime(cText2SkinItem *Item); void DisplayReplayTitle(cText2SkinItem *Item); - void DisplayReplayCurrent(cText2SkinItem *Item); - void DisplayReplayTotal(cText2SkinItem *Item); - void DisplayReplayJump(cText2SkinItem *Item); + void DisplayReplayPrompt(cText2SkinItem *Item); + void DisplayReplaySymbol(cText2SkinItem *Item); void DisplayMessage(cText2SkinItem *Item); - void DisplayMenuItems(cText2SkinItem *Item); void DisplayMenuTitle(cText2SkinItem *Item); - void DisplayMenuColorbutton(cText2SkinItem *Item); + void DisplayMenuButton(cText2SkinItem *Item); void DisplayMenuText(cText2SkinItem *Item); - void DisplayMenuEventTitle(cText2SkinItem *Item); - void DisplayMenuEventShortText(cText2SkinItem *Item); - void DisplayMenuEventDescription(cText2SkinItem *Item); - void DisplayMenuEventTime(cText2SkinItem *Item); - void DisplayMenuRecording(cText2SkinItem *Item); + void DisplayMenuScrollIcon(cText2SkinItem *Item); + void DisplayMenuItems(cText2SkinItem *Item); // Helpers string ItemText(cText2SkinItem *Item); @@ -150,12 +148,14 @@ 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); + void Flush(void) { TriggerUpdate(); } }; #endif // VDR_TEXT2SKIN_RENDER_H diff --git a/text2skin.c b/text2skin.c index efd236a..fecbe52 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.13 2004/06/07 19:08:42 lordjaxom Exp $ + * $Id: text2skin.c,v 1.15 2004/06/11 15:02:57 lordjaxom Exp $ */ #include "text2skin.h" @@ -11,8 +11,8 @@ #include "i18n.h" #include "loader.h" -const char *cText2SkinPlugin::VERSION = "0.0.2"; -const char *cText2SkinPlugin::THEMEVERSION = "0.0.1"; +const char *cText2SkinPlugin::VERSION = "0.0.3"; +const char *cText2SkinPlugin::THEMEVERSION = "0.0.2"; const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins"; cText2SkinPlugin::cText2SkinPlugin(void) diff --git a/text2skin.h b/text2skin.h index a42faf1..8699c65 100644 --- a/text2skin.h +++ b/text2skin.h @@ -1,5 +1,5 @@ /* - * $Id: text2skin.h,v 1.2 2004/06/05 16:53:14 lordjaxom Exp $ + * $Id: text2skin.h,v 1.4 2004/06/11 15:01:58 lordjaxom Exp $ */ #ifndef VDR_TEXT2SKIN_H @@ -13,12 +13,14 @@ private: static const char *VERSION; static const char *THEMEVERSION; static const char *DESCRIPTION; + public: + static const char *ThemeVersion(void) { return THEMEVERSION; } + cText2SkinPlugin(void); virtual ~cText2SkinPlugin(); virtual const char *Version(void) { return VERSION; } - virtual const char *ThemeVersion(void) { return THEMEVERSION; } - virtual const char *Description(void) { return DESCRIPTION; } + virtual const char *Description(void) { return tr(DESCRIPTION); } virtual bool Start(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); |