summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY25
-rw-r--r--Makefile43
-rw-r--r--README107
-rw-r--r--bitmap.c25
-rw-r--r--bitmap.h15
-rw-r--r--common.h5
-rw-r--r--config.c163
-rw-r--r--config.h110
-rw-r--r--enigma.c1655
-rw-r--r--enigma.h21
-rw-r--r--font.c220
-rw-r--r--font.h50
-rw-r--r--i18n.c1344
-rw-r--r--i18n.h5
-rw-r--r--logo.c44
-rw-r--r--logo.h35
-rw-r--r--setup.c546
-rw-r--r--setup.h111
-rw-r--r--skinenigmang.c419
-rw-r--r--status.c4
-rw-r--r--status.h4
-rw-r--r--texteffects.c447
-rw-r--r--texteffects.h148
-rw-r--r--themes/EnigmaNG-AppleGreen.theme7
-rw-r--r--themes/EnigmaNG-Blue.theme47
-rw-r--r--themes/EnigmaNG-Blue2.theme47
-rw-r--r--themes/EnigmaNG-Blue3.theme47
-rw-r--r--themes/EnigmaNG-Coolblue.theme69
-rw-r--r--themes/EnigmaNG-DarkBlue.theme7
-rw-r--r--themes/EnigmaNG-MoBuntu.theme48
-rw-r--r--themes/EnigmaNG-WineRed.theme7
-rw-r--r--themes/EnigmaNG-WomenLike.theme7
-rw-r--r--themes/EnigmaNG-YellowSun.theme7
-rw-r--r--themes/EnigmaNG-default.theme7
-rw-r--r--tools.c116
-rw-r--r--tools.h17
36 files changed, 4848 insertions, 1131 deletions
diff --git a/HISTORY b/HISTORY
index 8f8b8d7..949ecbe 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,31 @@
VDR Skin 'EnigmaNG' Revision History
------------------------------------------
+2007-06-11: Version 0.0.5rc
+- Fixed possible crash in recording's details.
+- Added MoBuntu theme (Submitted by Morone @vdr-portal.de).
+- Added Blue, Blue2, Blue3 and Coolblue theme (Submitted by Uwe @vdr-portal.de).
+- Added support for TrueTypeFonts (based on graphtft and text2skin plugins).
+- Added support for new epgsearch tags.
+- Updated French translation. (Submitted by pat @vdr-portal.de)
+- Changed size calculation for scrollbars.
+- Add setup options to individually set the fonts to use. See README for details.
+- Set used colors for every area in menu OSD when using multiple areas.
+- Reworked multiple areas mode in menu OSD.
+- Do not disable logos/symbols/flags if 4bpp single area is configured in setup.
+- Replaced setup options "One area (if possible)" and "Bpp in single area" by option "Try 8bpp single areas".
+- Unified appearance of error/info/status messages in all OSDs.
+- Added setup option to selectively enable scrolling text.
+- Added setup option to selectively enable logos in the different OSDs.
+- Added text effects (e.g. scrolling and blinking) for selected text.
+- Removed clrMenuHighlight, clrMessageBorder, clrMenuItemCurrentFg, clrMenuEventTitle, clrMenuEventShortText, clrMenuScrollbarTotal and clrMenuScrollbarShown in themes.
+- Fixed height of title/subtitle box in EPG & recording details.
+- Recognize mediamanager plugin in mainmenu logos.
+- Don't cut info line in EPG & recording details at logo area's left edge.
+- Updated Russian translation (Submitted by neptunvasja @vdr-portal.de).
+- Added Dutch translation (Submitted by dorpsgek @vdr-portal.de).
+- Various bugfixes and graphical changes.
+
2007-04-02: Version 0.0.4
- Changed text color in themes for green and yellow buttons.
- Fixed false colors problem after theme changes.
diff --git a/Makefile b/Makefile
index 8ffe1f1..b8df874 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for a Video Disk Recorder plugin
#
-# $Id: Makefile,v 1.8 2007/03/28 10:01:33 amair Exp $
+# $Id: Makefile,v 1.14 2007/06/11 06:57:47 amair Exp $
# If you are using the epgsearch plugin and want to see the number of
# timer conflicts in the main menu's info area.
@@ -23,6 +23,23 @@
# plugin will be used because it has no compile time requirements.
SKINENIGMA_USE_PLUGIN_MAILBOX = 1
+# EXPERIMENTAL!!! NOT YET OFFICIALY SUPPORTED!!!
+#
+# USE AT OWN RISC!!!
+#SKINENIGMA_USE_PLUGIN_AVARDS = 1
+
+# Disable any code that is used for scrolling or blinking text.
+# NOTE: this is only useful if you want to save some bytes because you
+# can disable them in the setup too.
+#DISABLE_ANIMATED_TEXT = 1
+
+# Set the descriptions for fonts you've patched in VDR. These fonts then
+# can be selected in EnigmaNG setup.
+#SKINENIGMA_FONTS = "\"Test Font\", \"Test2 Font\""
+
+# If you have installed FreeType2 and want to use TrueTypeFonts.
+#HAVE_FREETYPE = 1
+
# Strip debug symbols? Set eg. to /bin/true if not
#STRIP = strip
STRIP = /bin/true
@@ -83,20 +100,42 @@ ifdef SKINENIGMA_USE_PLUGIN_MAILBOX
DEFINES += -DUSE_PLUGIN_MAILBOX
endif
+ifdef SKINENIGMA_USE_PLUGIN_AVARDS
+DEFINES += -DUSE_PLUGIN_AVARDS
+endif
+
ifdef HAVE_IMAGEMAGICK
DEFINES += -DHAVE_IMAGEMAGICK
endif
DEFINES += -DRECORDING_COVER='"Cover-Enigma"'
+ifdef SKINENIGMA_DISABLE_ANIMATED_TEXT
+DEFINES += -DDISABLE_ANIMATED_TEXT
+endif
+
+DEFINES += -DSKINENIGMA_FONTS=$(SKINENIGMA_FONTS)
+
### The object files (add further files here):
-OBJS = $(PLUGIN).o enigma.o config.o logo.o i18n.o tools.o status.o
+OBJS = $(PLUGIN).o enigma.o config.o logo.o i18n.o tools.o status.o texteffects.o setup.o
ifdef HAVE_IMAGEMAGICK
OBJS += bitmap.o
LIBS += -lMagick++
endif
+ifdef HAVE_FREETYPE
+ ifneq ($(shell which freetype-config),)
+ INCLUDES += $(shell freetype-config --cflags)
+ LIBS += $(shell freetype-config --libs)
+ else
+ INCLUDES += -I/usr/include/freetype -I/usr/local/include/freetype
+ LIBS += -lfreetype
+ endif
+ DEFINES += -DHAVE_FREETYPE
+ OBJS += font.o
+endif
+
### Implicit rules:
%.o: %.c
diff --git a/README b/README
index 0572f4c..4000912 100644
--- a/README
+++ b/README
@@ -46,6 +46,18 @@ If you use the mailbox plugin this will include support for it.
NOTE: this can also be defined if you don't know if the mailbox
plugin will be used because it has no compile time requirements.
+SKINENIGMA_DISABLE_ANIMATED_TEXT = 1
+Disable any code that is used for scrolling or blinking text.
+NOTE: this is only useful if you want to save some bytes because you
+can disable them in the setup too.
+
+SKINENIGMA_FONTS =
+Set the descriptions for fonts you've patched in VDR. These fonts then
+can be selected in EnigmaNG setup.
+
+HAVE_FREETYPE = 1
+If you have installed FreeType2 and want to use TrueTypeFonts.
+
Patches
-------
@@ -91,12 +103,15 @@ some things before:
Options
-------
- -l path, --logodir=path
- Path to the logos (Default: <vdrconfdir>/skinenigmang).
+ -f path, --fonts=path
+ Path to the TrueTypeFonts (*.ttf) (Default: <logodir>/fonts).
-i path, --epgimages=path
Path to the epgimages (Default: <logodir>/epgimages).
+ -l path, --logodir=path
+ Path to the logos (Default: <vdrconfdir>/plugins/skinenigmang).
+
Usage
-----
@@ -107,7 +122,8 @@ In VDR go to the OSD settings menu and select the skin "EnigmaNG"
Setup Options
-------------
-- One area (if possible)
+* General
+- Try 8bpp single area
If you don't want to use a single 8bpp area for the OSD you can disable
it here. If this option is enabled this will not ensure that a single
area is used, but EnigmaNG will try to use it. If your output deviice
@@ -120,11 +136,6 @@ Setup Options
NOTE: after commit the settings you have to fully close and re-open the OSD
to make the change affect.
-- Bpp in single area (4/8)
- The number of bpp (bit per pixel) to use for the single area.
- 4bpp means upto 16 colors, 8bpp means upto 256 colors.
- NOTE: if this is set to 4bpp this will disable all symbols/logos/images/flags.
-
- Show info area in main menu
This info area is shown in the main menu and it will show the current/next
timers and the number of timer conflicts (if SKINENIGMA_HAVE_EPGSEARCH has
@@ -170,15 +181,16 @@ Setup Options
* Logos & Symbols
-- Show symbols (never/always/not in menu/only in menu)
+- Show symbols
Here you can enable or disable the large symbols shown in top right corner
of the main menu, the recordings info and the event info and the "background"
symbol of the mode symbol when replaying recordings.
- Possible options:
- never - don't show them anywhere
- always - show them everywhere
- not in menu - don't show them in the main menu or recording/even info
- only in menu - only show them in the main menu or recording/even info
+
+- Show symbols in menu
+- Show symbols in replay
+- Show symbols in messages
+- Show symbols in audio
+ If "Show Symbols" is set to "yes" you can enable or disable symbols for each OSD.
- Show symbols in lists
This replaces "T", "t", "V"... in the EPG views symbols.
@@ -230,7 +242,70 @@ Setup Options
- Channel logo cache size
The number of logos/symbols to keep in the cache.
-* EPGSearch (NOTE: only visible if epgsearch support is compiled in)
+* Animated Text
+ NOTE: only visible if SKINENIGMA_DISABLE_ANIMATED_TEXT is not set
+
+- Enable
+ This option enables scrolling of long lines and blinking of some text.
+
+- Scroll OSD title
+ Scroll title of OSDs?
+
+- Scroll info area
+ Scroll a timer's title in the main menu's info area?
+
+- Scroll active list items
+ Scroll long columns of the active line in the menu?
+
+- Scroll other items
+ Scroll items in other areas?
+ At the moment these areas cover the title and subtitle in the EPGs and
+ recordings details and the message in the message OSD.
+
+- Scoll behaviour (to the left/left and right)
+ Text can either scroll from the left to right and then start again at the
+ left or it can scroll from the left to the right and then back from the
+ right to the left (ping pong).
+
+- Scroll delay (ms) (50 - 1000)
+ The number of milliseconds to wait before the scrolling text is moved.
+
+- Scroll pause (ms) (500 - 2000)
+ The number of milliseconds to wait at the left or right side of the text
+ before scrolling again.
+
+- Blink pause (ms) (500 - 2000)
+ The number of milliseconds to wait for blinking text.
+
+* Fonts
+ If you've set the VDR OSD option "Use small font" to "skin dependent" then
+ you can set your prefered fonts for various areas. If you've patched additional
+ fonts into VDR you need to set the SKINENIGMA_FONTS define (see above) to see
+ them in the list of available fonts.
+
+- OSD title
+- Messages
+- Date
+- Help keys
+- Channelinfo: title
+- Channelinfo: subtitle
+- Channelinfo: language
+- List items
+- Info area: timers title
+- Info area: timers text
+- Info area: warning title
+- Info area: warning text
+- Details: title
+- Details: subtitle
+- Details: date
+- Details: text
+- Replay: times
+ Set the font for the named area.
+ If you have set HAVE_FREETYPE you can set the TrueTypeFont to use by pressing
+ the blue key.
+
+* EPGSearch
+ NOTE: only visible if epgsearch support is compiled in
- Number of Reruns (0 - 10)
The number of reruns to show in an event's info.
@@ -300,4 +375,6 @@ Credits
- skiller2k1 @vdr-portal.de for Comedy Central logo.
http://www.vdr-portal.de/board/thread.php?postid=567887#post567887
+- uwe @vdr-portal.de for themes (Blue, Blue2, Blue3 and CoolBlue).
+ http://www.vdr-portal.de/board/thread.php?postid=615540#post615540
// vim:et:sw=2:ts=2:
diff --git a/bitmap.c b/bitmap.c
index 59bf98b..4ca52b4 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -1,15 +1,20 @@
#ifdef HAVE_IMAGEMAGICK
+
+#include "common.h"
#include "bitmap.h"
#include "config.h"
-#include <vdr/themes.h>
-
+#ifndef X_DISPLAY_MISSING
#define X_DISPLAY_MISSING
+#endif
+
+#undef debug
#include <Magick++.h>
using namespace Magick;
#include <vector>
-using namespace std;
+
+#include <vdr/themes.h>
cOSDImageBitmap::cOSDImageBitmap()
{}
@@ -18,12 +23,12 @@ cOSDImageBitmap::cOSDImageBitmap()
cOSDImageBitmap::~cOSDImageBitmap()
{}
-bool cOSDImageBitmap::LoadImage(const char *fileNameP, int w, int h, int colors, cBitmap &bmp)
+bool cOSDImageBitmap::DrawImage(const char *fileNameP, int x, int y, int w, int h, int colors, cBitmap *bmp)
{
- return LoadMagick(fileNameP, w, h, colors, bmp);
+ return DrawMagick(fileNameP, x, y, w, h, colors, bmp);
}
-bool cOSDImageBitmap::LoadMagick(const char *Filename, int width, int height, int colors, cBitmap &bmp)
+bool cOSDImageBitmap::DrawMagick(const char *Filename, int x, int y, int width, int height, int colors, cBitmap *bmp)
{
Image image;
try {
@@ -52,8 +57,10 @@ bool cOSDImageBitmap::LoadMagick(const char *Filename, int width, int height, in
image.quantizeColors(colors);
image.quantize();
}
- bmp.SetSize(w, h);
- bmp.SetBpp(colors <= 16 ? 4 : 8);
+
+ // center image
+ x += ((width - w) / 2);
+ y += ((height - h) / 2);
const PixelPacket *pix = image.getConstPixels(0, 0, w, h);
for (int iy = 0; iy < h; ++iy) {
@@ -62,7 +69,7 @@ bool cOSDImageBitmap::LoadMagick(const char *Filename, int width, int height, in
| ((pix->red * 255 / MaxRGB) << 16)
| ((pix->green * 255 / MaxRGB) << 8)
| (pix->blue * 255 / MaxRGB);
- bmp.DrawPixel(ix, iy, col);
+ bmp->DrawPixel(x + ix, y + iy, col);
++pix;
}
}
diff --git a/bitmap.h b/bitmap.h
index 5692b9d..507d7f7 100644
--- a/bitmap.h
+++ b/bitmap.h
@@ -1,20 +1,29 @@
+/*
+ * bitmap.h: 'EnigmaNG' skin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
#ifdef HAVE_IMAGEMAGICK
#ifndef _OSDIMAGE_BITMAP_H_
#define _OSDIMAGE_BITMAP_H_
+#include "common.h"
#include <vdr/osd.h>
-#include <vdr/skins.h>
class cOSDImageBitmap {
public:
cOSDImageBitmap();
~cOSDImageBitmap();
- bool LoadImage(const char *fileNameP, int w, int h, int colors, cBitmap &bmp);
+ bool DrawImage(const char *fileNameP, int x, int y, int w, int h, int colors, cBitmap *bmp);
private:
- bool LoadMagick(const char *Filename, int height, int width, int colors, cBitmap &bmp);
+ bool DrawMagick(const char *Filename, int x, int y, int height, int width, int colors, cBitmap *bmp);
};
#endif
#endif //HAVE_IMAGEMAGICK
+
+// vim:et:sw=2:ts=2:
diff --git a/common.h b/common.h
index 0d23e78..03a21ae 100644
--- a/common.h
+++ b/common.h
@@ -1,5 +1,5 @@
/*
- * common.h: The 'EnigmaNG' VDR skin
+ * common.h: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -9,7 +9,7 @@
#define __SKINENIGMA_COMMON_H
#include <string>
-#include <vdr/tools.h>
+#include <stdio.h>
#ifdef DEBUG
#define debug(x...) printf("EnigmaNG: " x);
@@ -20,3 +20,4 @@
#endif
#endif // __SKINENIGMA_COMMON_H
+// vim:et:sw=2:ts=2:
diff --git a/config.c b/config.c
index ef1ab4f..e666668 100644
--- a/config.c
+++ b/config.c
@@ -5,9 +5,17 @@
*
*/
-#include <stdlib.h>
#include "common.h"
#include "config.h"
+#include "tools.h"
+
+#ifdef USE_PLUGIN_AVARDS
+#include "../avards/avards_services.h"
+#endif
+
+#include <stdlib.h>
+#include <vdr/font.h>
+#include <vdr/plugin.h>
#ifdef HAVE_IMAGEMAGICK
const char *imageExtensionTexts[NUM_IMAGEEXTENSIONTEXTS] = { "xpm", "jpg", "png" };
@@ -15,16 +23,64 @@ const char *imageExtensionTexts[NUM_IMAGEEXTENSIONTEXTS] = { "xpm", "jpg", "png"
cEnigmaConfig EnigmaConfig;
+#ifdef HAVE_FREETYPE
+cGraphtftFont FontCache;
+#endif
+
+FontConfig allFontConfig[FONT_NUMFONTS] =
+{
+ { FONT_OSDTITLE, "FontOsdTitle", "FontOsdTitleName" },
+ { FONT_MESSAGE, "FontMessage", "FontMessageName" },
+ { FONT_DATE, "FontDate", "FontDateName" },
+ { FONT_HELPKEYS, "FontHelpKeys", "FontHelpKeysName" },
+ { FONT_CITITLE, "FontCiTitle", "FontCiTitleName" },
+ { FONT_CISUBTITLE, "FontCiSubtitle", "FontCiSubtitleName" },
+ { FONT_CILANGUAGE, "FontCiLanguage", "FontCiLanguageName" },
+ { FONT_LISTITEM, "FontListItem", "FontListItemName" },
+ { FONT_INFOTIMERHEADLINE, "FontInfoTimerHeadline", "FontInfoTimerHeadlineName" },
+ { FONT_INFOTIMERTEXT, "FontInfoTimerText", "FontInfoTimerTextName" },
+ { FONT_INFOWARNHEADLINE, "FontInfoWarnHeadline", "FontInfoWarnHeadlineName" },
+ { FONT_INFOWARNTEXT, "FontInfoWarnText", "FontInfoWarnTextName" },
+ { FONT_DETAILSTITLE, "FontDetailsTitle", "FontDetailsTitleName" },
+ { FONT_DETAILSSUBTITLE, "FontDetailsSubtitle", "FontDetailsSubtitleName" },
+ { FONT_DETAILSDATE, "FontDetailsDate", "FontDetailsDateName" },
+ { FONT_DETAILSTEXT, "FontDetailsText", "FontDetailsTextName" },
+ { FONT_REPLAYTIMES, "FontReplayTimes", "FontReplayTimesName" },
+ { FONT_FIXED, "FontFixed", "FontFixed" }
+};
+
cEnigmaConfig::cEnigmaConfig() : showAuxInfo(1), showLogo(1), showVps(1), showSymbols(1),
+ showSymbolsMenu(1), showSymbolsReplay(1), showSymbolsMsgs(1), showSymbolsAudio(1),
showListSymbols(1), showProgressbar(1), cacheSize(50),
useChannelId(0), showInfo(1), showRemaining(0), showMarker(1),
singleArea(1), singleArea8Bpp(1), showFlags(1), numReruns(5),
useSubtitleRerun(1), showTimerConflicts(1), showRecSize(2),
- showImages(1), resizeImages(0), showMailIcon(0),
- imageWidth(120), imageHeight(120), imageExtension(0), fullTitleWidth(0)
+ showImages(0), resizeImages(0), showMailIcon(0),
+ imageWidth(120), imageHeight(80), imageExtension(0), fullTitleWidth(0),
+ useTextEffects(0), scrollDelay(50), scrollPause(1500), scrollMode(0),
+ blinkPause(1000), scrollInfo(1), scrollListItem(1), scrollOther(1), scrollTitle(1),
+ dynOsd(0)
{
memset(logoDir, 0, sizeof(logoDir));
memset(strImagesDir, 0, sizeof(strImagesDir));
+#ifdef HAVE_FREETYPE
+ memset(strFontsDir, 0, sizeof(strFontsDir));
+#endif
+
+ for (int id = 0; id < FONT_NUMFONTS; id++) {
+ switch (id) {
+ case FONT_CISUBTITLE:
+ case FONT_CILANGUAGE:
+ case FONT_DETAILSSUBTITLE:
+ allFonts[id].VdrId = fontSml + 1;
+ break;
+ default:
+ allFonts[id].VdrId = fontOsd + 2;
+ }
+ memset(allFonts[id].Name, 0, sizeof(allFonts[id].Name));
+ allFonts[id].Width = 100;
+ allFonts[id].Size = 26;
+ }
}
cEnigmaConfig::~cEnigmaConfig()
@@ -33,8 +89,7 @@ cEnigmaConfig::~cEnigmaConfig()
void cEnigmaConfig::SetLogoDir(const char *logodirP)
{
- if (logodirP)
- {
+ if (logodirP) {
debug("cEnigmaConfig::SetLogoDir(%s)\n", logodirP);
strncpy(logoDir, logodirP, sizeof(logoDir));
}
@@ -42,19 +97,105 @@ void cEnigmaConfig::SetLogoDir(const char *logodirP)
void cEnigmaConfig::SetImagesDir(const char *dir)
{
- if (dir)
- {
- debug("cEnigmaConfig::SetImagesDir(%s)\n", dir);
+ if (dir) {
+ debug("cEnigmaConfig::SetImagesDir(%s)\n", dir);
strncpy(strImagesDir, dir, sizeof(strImagesDir));
- }
+ }
}
const char *cEnigmaConfig::GetImageExtension(void)
{
#ifdef HAVE_IMAGEMAGICK
- return (0 <= imageExtension && imageExtension < NUM_IMAGEEXTENSIONTEXTS) ? imageExtensionTexts[imageExtension] : imageExtensionTexts[0];
+ return (0 <= imageExtension && imageExtension < NUM_IMAGEEXTENSIONTEXTS) ? imageExtensionTexts[imageExtension] : imageExtensionTexts[0];
+#else
+ return "xpm";
+#endif
+}
+
+#ifdef HAVE_FREETYPE
+void cEnigmaConfig::SetFontsDir(const char *dir)
+{
+ if (dir) {
+ debug("cEnigmaConfig::SetFontsDir(%s)\n", dir);
+ strncpy(strFontsDir, dir, sizeof(strFontsDir));
+ }
+}
+#endif
+
+const cFont *cEnigmaConfig::GetFont(int id)
+{
+ const cFont *res = NULL;
+ if (allFonts[id].VdrId == FONT_TRUETYPE) {
+#ifdef HAVE_FREETYPE
+ char *cachename;
+ asprintf(&cachename, "%s_%d_%d_%d", allFonts[id].Name, allFonts[id].Size, allFonts[id].Width, Setup.OSDLanguage);
+ if (FontCache.Load(string(strFontsDir) + "/" + string(allFonts[id].Name), cachename, allFonts[id].Size, Setup.OSDLanguage, allFonts[id].Width)) {
+ res = FontCache.GetFont(cachename);
+ } else {
+ error("ERROR: EnigmaNG: Couldn't load font %s:%d", allFonts[id].Name, allFonts[id].Size);
+ }
+ free(cachename);
#else
- return "xpm";
+ error("ERROR: EnigmaNG: Font engine not enabled at compile time!");
#endif
+ } else if (allFonts[id].VdrId > FONT_TRUETYPE) {
+ res = cFont::GetFont((eDvbFont)(allFonts[id].VdrId - 1));
+ } else {
+ res = cFont::GetFont((eDvbFont)allFonts[id].VdrId);
+ }
+ if (res)
+ return res;
+ else
+ return cFont::GetFont(fontOsd);
}
+void cEnigmaConfig::SetFont(int id, const char *font)
+{
+ if (id >= 0 && id < FONT_NUMFONTS && font) {
+ char *tmp = strrchr(font, ':');
+ if (tmp) {
+ strncpy(allFonts[id].Name, font, min((int)sizeof(allFonts[id].Name), tmp - font));
+ allFonts[id].Size = atoi(tmp + 1);
+ tmp = strchr(tmp + 1, ',');
+ if (tmp) {
+ allFonts[id].Width = atoi(tmp + 1);
+ }
+ } else {
+ strncpy(allFonts[id].Name, font, sizeof(allFonts[id].Name));
+ }
+ }
+}
+
+void cEnigmaConfig::SetFont(int id, int vdrId)
+{
+ if (id >= 0 && id < FONT_NUMFONTS && vdrId >= 0) {
+ allFonts[id].VdrId = vdrId;
+ }
+}
+
+void cEnigmaConfig::GetOsdSize(struct EnigmaOsdSize *size)
+{
+ if (size == NULL)
+ return;
+
+ size->y = Setup.OSDTop;
+ size->x = Setup.OSDLeft;
+ size->w = Setup.OSDWidth;
+ size->h = Setup.OSDHeight;
+
+#ifdef USE_PLUGIN_AVARDS
+ if (dynOsd) {
+ cPlugin *p = cPluginManager::GetPlugin("avards");
+ if (p) {
+ avards_MaxOSDsize_v1_0 OSDsize;
+ if (p->Service(AVARDS_MAXOSDSIZE_SERVICE_STRING_ID, &OSDsize)) {
+ size->y = OSDsize.top;
+ size->x = OSDsize.left;
+ size->w = OSDsize.width;
+ size->h = OSDsize.height;
+ }
+ }
+ }
+#endif
+}
+// vim:et:sw=2:ts=2:
diff --git a/config.h b/config.h
index bce7357..de51ce5 100644
--- a/config.h
+++ b/config.h
@@ -8,6 +8,8 @@
#ifndef __SKINENIGMA_CONFIG_H
#define __SKINENIGMA_CONFIG_H
+#include "common.h"
+
#ifdef HAVE_IMAGEMAGICK
#define NUM_IMAGEEXTENSIONTEXTS 3
extern const char *imageExtensionTexts[NUM_IMAGEEXTENSIONTEXTS];
@@ -15,23 +17,94 @@ extern const char *imageExtensionTexts[NUM_IMAGEEXTENSIONTEXTS];
#define NUM_IMAGEEXTENSIONTEXTS 0
#endif
+#ifdef HAVE_FREETYPE
+# include "font.h"
+#endif
+
+#include <vdr/skins.h>
+
+struct EnigmaOsdSize
+{
+ int x;
+ int y;
+ int w;
+ int h;
+};
+
+#define FONT_TRUETYPE 0
+
+enum
+{
+ FONT_OSDTITLE,
+ FONT_MESSAGE,
+ FONT_DATE,
+ FONT_HELPKEYS,
+ FONT_CITITLE,
+ FONT_CISUBTITLE,
+ FONT_CILANGUAGE,
+ FONT_LISTITEM,
+ FONT_INFOTIMERHEADLINE,
+ FONT_INFOTIMERTEXT,
+ FONT_INFOWARNHEADLINE,
+ FONT_INFOWARNTEXT,
+ FONT_DETAILSTITLE,
+ FONT_DETAILSSUBTITLE,
+ FONT_DETAILSDATE,
+ FONT_DETAILSTEXT,
+ FONT_REPLAYTIMES,
+ FONT_FIXED,
+ FONT_NUMFONTS
+};
+
+struct FontInfo
+{
+ int VdrId;
+ char Name[255];
+ int Width;
+ int Size;
+};
+
+struct FontConfig
+{
+ int Id;
+ char *KeyId;
+ char *KeyName;
+};
+
+extern FontConfig allFontConfig[FONT_NUMFONTS];
+
struct cEnigmaConfig
{
private:
char logoDir[255];
- char strImagesDir[255];
+ char strImagesDir[255];
+#ifdef HAVE_FREETYPE
+ char strFontsDir[255];
+#endif
public:
cEnigmaConfig();
~cEnigmaConfig();
void SetLogoDir(const char *logodirP);
char *GetLogoDir(void) { return logoDir; }
- void SetImagesDir(const char *dir);
- char *GetImagesDir(void) {return strImagesDir; }
- const char *GetImageExtension(void);
+ void SetImagesDir(const char *dir);
+ char *GetImagesDir(void) { return strImagesDir; }
+#ifdef HAVE_FREETYPE
+ void SetFontsDir(const char *dir);
+ char *GetFontsDir(void) { return strFontsDir; }
+#endif
+ const char *GetImageExtension(void);
+ const cFont *GetFont(int id);
+ void SetFont(int id, const char *font);
+ void SetFont(int id, int vdrId);
+ void GetOsdSize(struct EnigmaOsdSize *size);
int showAuxInfo;
int showLogo;
int showVps;
int showSymbols;
+ int showSymbolsMenu;
+ int showSymbolsReplay;
+ int showSymbolsMsgs;
+ int showSymbolsAudio;
int showListSymbols;
int showProgressbar;
int cacheSize;
@@ -45,16 +118,29 @@ public:
int numReruns;
int useSubtitleRerun;
int showTimerConflicts;
- int showRecSize;
- int showImages;
- int resizeImages;
- int showMailIcon;
- int imageWidth;
- int imageHeight;
- int imageExtension;
- int fullTitleWidth;
+ int showRecSize;
+ int showImages;
+ int resizeImages;
+ int showMailIcon;
+ int imageWidth;
+ int imageHeight;
+ int imageExtension;
+ int fullTitleWidth;
+ int useTextEffects;
+ int scrollDelay;
+ int scrollPause;
+ int scrollMode;
+ int blinkPause;
+ int scrollInfo;
+ int scrollListItem;
+ int scrollOther;
+ int scrollTitle;
+ int dynOsd;
+ FontInfo allFonts[FONT_NUMFONTS];
};
extern cEnigmaConfig EnigmaConfig;
#endif // __SKINENIGMA_CONFIG_H
+
+// vim:et:sw=2:ts=2:
diff --git a/enigma.c b/enigma.c
index e2a6622..93beb0d 100644
--- a/enigma.c
+++ b/enigma.c
@@ -1,27 +1,24 @@
/*
- * enigma.c: The 'EnigmaNG' VDR skin
+ * enigma.c: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
+#include "common.h"
+#include "config.h"
+#include "enigma.h"
+#include "logo.h"
+#include "i18n.h"
+#include "status.h"
+#include "texteffects.h"
+
#include <math.h>
#include <ctype.h>
#include <sstream>
#include <iomanip>
#include <locale.h>
-#ifndef __STL_CONFIG_H
-#define __STL_CONFIG_H
-#endif
-
-#include "common.h"
-#include "tools.h"
-#include "config.h"
-#include "logo.h"
-#include "i18n.h"
-#include "enigma.h"
-#include "status.h"
#include <vdr/device.h>
#include <vdr/timers.h>
#include <vdr/menu.h>
@@ -34,7 +31,11 @@
#include "../epgsearch/services.h"
#endif
-using namespace std;
+#ifdef USE_PLUGIN_AVARDS
+#include "../avards/avards_services.h"
+#endif
+
+#include "tools.h"
#define MAX_AUDIO_BITMAPS 3
#define MAX_SPEED_BITMAPS 10
@@ -167,7 +168,6 @@ THEME_CLR(Theme, clrButtonYellowBg, 0xE5C4C400);
THEME_CLR(Theme, clrButtonBlueFg, 0xFFFFFFFF);
THEME_CLR(Theme, clrButtonBlueBg, 0xE50000C4);
// Messages
-THEME_CLR(Theme, clrMessageBorder, 0xE5FF0000);
THEME_CLR(Theme, clrMessageStatusFg, 0xFF000000);
THEME_CLR(Theme, clrMessageStatusBg, 0xE5D7FFD1);
THEME_CLR(Theme, clrMessageInfoFg, 0xFF000000);
@@ -180,16 +180,8 @@ THEME_CLR(Theme, clrMessageErrorBg, 0xE5FFD1D1);
THEME_CLR(Theme, clrVolumeBar, 0xFF33CC33);
THEME_CLR(Theme, clrVolumeBarMute, 0xFFFF0000);
// Menu list items
-THEME_CLR(Theme, clrMenuItemCurrentFg, 0xFF000000);
-THEME_CLR(Theme, clrMenuHighlight, 0xE5B2BBD6);
THEME_CLR(Theme, clrMenuItemSelectableFg, 0xFF000000);
THEME_CLR(Theme, clrMenuItemNotSelectableFg, 0xE54158BC);
-// title/subtitle
-THEME_CLR(Theme, clrMenuEventTitle, 0xFF000000);
-THEME_CLR(Theme, clrMenuEventShortText, 0xFF1D2F7D);
-// Scrollbar
-THEME_CLR(Theme, clrMenuScrollbarTotal, 0xE5B2BBD6);
-THEME_CLR(Theme, clrMenuScrollbarShown, 0xFF000000);
// Replay OSD
THEME_CLR(Theme, clrReplayCurrent, 0xFF1D2F7D);
THEME_CLR(Theme, clrReplayTotal, 0xFF1D2F7D);
@@ -206,7 +198,6 @@ THEME_CLR(Theme, clrReplayProgressCurrent, 0xFFFF0000);
#define Gap 4
#define BigGap 8
#define Roundness 10
-#define MessageHeight (2 * SmallGap + cFont::GetFont(fontOsd)->Height() + 2 * SmallGap)
#define TitleDecoGap SmallGap
#define TitleDecoGap2 SmallGap
@@ -218,14 +209,29 @@ THEME_CLR(Theme, clrReplayProgressCurrent, 0xFFFF0000);
#define MarkerGap 6
#define ListProgressBarGap Gap
#define ListProgressBarBorder TinyGap
+#define ScrollbarHeight 20
+#define ScrollbarWidth 16
+
// --- cSkinEnigmaDisplayChannel --------------------------------------------
-class cSkinEnigmaDisplayChannel:public cSkinDisplayChannel {
+class cSkinEnigmaDisplayChannel : public cSkinDisplayChannel, public cSkinEnigmaOsd {
private:
cOsd *osd;
bool fShowLogo;
- time_t lastTime;
+ char *strLastDate;
+#ifndef DISABLE_ANIMATED_TEXT
+ bool fScrollTitle;
+ bool fLocked;
+ int idTitle;
+#endif
+
+ const cFont *pFontOsdTitle;
+ const cFont *pFontDate;
+ const cFont *pFontTitle;
+ const cFont *pFontSubtitle;
+ const cFont *pFontLanguage;
+ const cFont *pFontMessage;
int xLogoLeft, xLogoRight, yLogoTop, yLogoBottom, xLogoDecoLeft, xLogoDecoRight, xLogoPos, yLogoPos;
int xTitleLeft, xTitleRight, yTitleTop, yTitleBottom, yTitleDecoTop, yTitleDecoBottom;
@@ -233,10 +239,7 @@ private:
int xEventNextLeft, xEventNextRight, yEventNextTop, yEventNextBottom;
int xBottomLeft, xBottomRight, yBottomTop, yBottomBottom;
int xMessageLeft, xMessageRight, yMessageTop, yMessageBottom;
- int xFirstSymbol;
-
- int lineHeightSml;
- int lineHeightOsd;
+ int xFirstSymbol, xDateLeft;
bool HasChannelTimerRecording(const cChannel *Channel);
void DrawAreas(void);
@@ -251,18 +254,33 @@ public:
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
+ virtual void DrawTitle(const char *Title);
};
cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo)
{
- fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && EnigmaConfig.showLogo;
- xFirstSymbol = 0;
- lastTime = 0;
+ debug("cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(%d)\n", WithInfo);
- lineHeightSml = cFont::GetFont(fontSml)->Height();
- lineHeightOsd = cFont::GetFont(fontOsd)->Height();
+ struct EnigmaOsdSize OsdSize;
+ EnigmaConfig.GetOsdSize(&OsdSize);
+
+ pFontOsdTitle = EnigmaConfig.GetFont(FONT_OSDTITLE);
+ pFontDate = EnigmaConfig.GetFont(FONT_DATE);
+ pFontTitle = EnigmaConfig.GetFont(FONT_CITITLE);
+ pFontSubtitle = EnigmaConfig.GetFont(FONT_CISUBTITLE);
+ pFontLanguage = EnigmaConfig.GetFont(FONT_CILANGUAGE);
+ pFontMessage = EnigmaConfig.GetFont(FONT_MESSAGE);
+
+ fShowLogo = EnigmaConfig.showLogo;
+ xFirstSymbol = 0;
+ strLastDate = NULL;
+#ifndef DISABLE_ANIMATED_TEXT
+ fScrollTitle = EnigmaConfig.useTextEffects && EnigmaConfig.scrollTitle;
+ idTitle = -1;
+#endif
- int LogoSize = max(lineHeightSml * 2 + lineHeightOsd * 2 + SmallGap, ChannelLogoHeight);
+ int MessageHeight = 2 * SmallGap + pFontMessage->Height() + 2 * SmallGap;
+ int LogoSize = max(pFontTitle->Height() * 2 + pFontSubtitle->Height() * 2 + SmallGap, ChannelLogoHeight);
LogoSize += (LogoSize % 2 ? 1 : 0);
// title bar & logo area
xLogoLeft = 0;
@@ -270,9 +288,9 @@ cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo)
xLogoDecoLeft = xLogoRight + LogoDecoGap;
xLogoDecoRight = xLogoDecoLeft + LogoDecoWidth;
xTitleLeft = (fShowLogo && !EnigmaConfig.fullTitleWidth ? xLogoDecoRight + LogoDecoGap2 : xLogoLeft);
- xTitleRight = xTitleLeft + ((Setup.OSDWidth - xTitleLeft) & ~0x07); // width must be multiple of 8
+ xTitleRight = xTitleLeft + ((OsdSize.w - xTitleLeft) & ~0x07); // width must be multiple of 8
yTitleTop = 0;
- yTitleBottom = yTitleTop + lineHeightOsd;
+ yTitleBottom = yTitleTop + max(pFontOsdTitle->Height(), pFontDate->Height());
yTitleDecoTop = yTitleBottom + TitleDecoGap;
yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight;
yLogoTop = yTitleDecoBottom + TitleDecoGap2;
@@ -283,31 +301,37 @@ cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo)
xEventNowLeft = (fShowLogo ? xLogoDecoRight + LogoDecoGap2 : xTitleLeft);
xEventNowRight = xTitleRight;
yEventNowTop = yLogoTop;
- yEventNowBottom = yEventNowTop + lineHeightOsd + lineHeightSml;
+ yEventNowBottom = yEventNowTop + pFontTitle->Height() + pFontSubtitle->Height();
// next event area
xEventNextLeft = xEventNowLeft;
xEventNextRight = xEventNowRight;
yEventNextTop = yEventNowBottom + SmallGap;
- yEventNextBottom = yEventNextTop + lineHeightOsd + lineHeightSml;
+ yEventNextBottom = yEventNextTop + pFontTitle->Height() + pFontSubtitle->Height();
// progress bar area
xBottomLeft = xTitleLeft;
xBottomRight = xTitleRight;
yBottomTop = yEventNextBottom + SmallGap;
- yBottomBottom = yBottomTop + lineHeightOsd;
+ yBottomBottom = yBottomTop + pFontDate->Height();
// message area
xMessageLeft = xEventNowLeft;
xMessageRight = xTitleRight;
- yMessageTop = yLogoTop + (LogoSize - 2 * SmallGap - lineHeightSml - 2 * SmallGap) / 2;
+ yMessageTop = yLogoTop + (LogoSize - MessageHeight) / 2;
yMessageBottom = yMessageTop + MessageHeight;
+ // date area
+ cString date = DayDateTime();
+ int w = pFontDate->Width(date);
+ xDateLeft = xTitleRight - Roundness - w - SmallGap;
// create osd
- osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : (Setup.OSDHeight - yBottomBottom)) );
- tArea Areas[] = { {0, 0, xBottomRight - 1, yBottomBottom - 1, fShowLogo ? 8 : 4} };
- if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ osd = cOsdProvider::NewOsd(OsdSize.x, OsdSize.y + (Setup.ChannelInfoPos ? 0 : (OsdSize.h - yBottomBottom)) );
+ tArea Areas[] = { {0, 0, xBottomRight - 1, yBottomBottom - 1, fShowLogo || EnigmaConfig.showFlags ? 8 : 4} };
+ if ((Areas[0].bpp < 8 || EnigmaConfig.singleArea8Bpp) && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ debug("cSkinEnigmaDisplayChannel: using %dbpp single area\n", Areas[0].bpp);
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
// clear all
osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent);
} else {
+ debug("cSkinEnigmaDisplayChannel: using multiple areas\n");
if (fShowLogo) {
tArea Areas[] = { {xLogoLeft, yLogoTop, xLogoDecoRight - 1, yLogoBottom - 1, 4},
{xTitleLeft, yTitleTop, xTitleRight - 1, yTitleDecoBottom - 1, 2},
@@ -341,10 +365,27 @@ cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo)
}
}
}
+
+#ifndef DISABLE_ANIMATED_TEXT
+ fLocked = false;
+ if (fScrollTitle) {
+ TE_START(osd);
+ fLocked = true;
+ }
+#endif
}
cSkinEnigmaDisplayChannel::~cSkinEnigmaDisplayChannel()
{
+ debug("cSkinEnigmaDisplayChannel::~cSkinEnigmaDisplayChannel()\n");
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle) {
+ if (!fLocked) TE_LOCK;
+ TE_STOP;
+ }
+#endif
+ free(strLastDate);
delete osd;
}
@@ -391,24 +432,43 @@ void cSkinEnigmaDisplayChannel::DrawGroupInfo(const cChannel *Channel, int Numbe
{
DrawAreas();
- const cFont *font = cFont::GetFont(fontOsd);
- int xName = (fShowLogo && EnigmaConfig.fullTitleWidth ? xEventNowLeft : xTitleLeft + Roundness + font->Width("0000-") + Gap);
- // draw channel group name
- osd->DrawText(xName + 3, yTitleTop + 3, GetChannelName(Channel),
- Theme.Color(clrTitleShadow), clrTransparent, font,
- xTitleRight - Roundness - xName - 3, lineHeightOsd - 3);
- osd->DrawText(xName, yTitleTop, GetChannelName(Channel),
- Theme.Color(clrTitleFg), clrTransparent, font,
- xTitleRight - Roundness - xName, lineHeightOsd);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle) {
+ int xName = (fShowLogo && EnigmaConfig.fullTitleWidth ? xEventNowLeft : xTitleLeft + Roundness + pFontOsdTitle->Width("0000-") + Gap);
+ idTitle = TE_TITLE(osd, idTitle, GetChannelName(Channel), pFontOsdTitle, xDateLeft - SmallGap - xName, this);
+ } else
+#endif
+ DrawTitle(GetChannelName(Channel));
+}
+
+void cSkinEnigmaDisplayChannel::DrawTitle(const char *Title)
+{
+ //Must be TE_LOCKed by caller
+
+ int xName = (fShowLogo && EnigmaConfig.fullTitleWidth ? xEventNowLeft : xTitleLeft + Roundness + pFontOsdTitle->Width("0000-") + Gap);
+ // draw titlebar
+ osd->DrawRectangle(xName, yTitleTop, xDateLeft - SmallGap - 1, yTitleBottom - 1,
+ Theme.Color(clrTitleBg));
+ osd->DrawRectangle(xName, yTitleDecoTop, xDateLeft - SmallGap - 1,
+ yTitleDecoBottom - 1, Theme.Color(clrTitleBg));
+ if (Title) {
+ int y = yTitleTop + (yTitleBottom - yTitleTop - pFontOsdTitle->Height()) / 2;
+ // draw channel group name
+ osd->DrawText(xName + 3, y + 3, Title,
+ Theme.Color(clrTitleShadow), clrTransparent, pFontOsdTitle,
+ xDateLeft - SmallGap - xName - 3, yTitleBottom - y - 3);
+ osd->DrawText(xName, y, Title,
+ Theme.Color(clrTitleFg), clrTransparent, pFontOsdTitle,
+ xDateLeft - SmallGap - xName - 3, yTitleBottom - y);
+ }
}
void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Number)
{
DrawAreas();
- const cFont *font = cFont::GetFont(fontOsd);
int xNumber = xTitleLeft + Roundness;
- int xName = xNumber + font->Width("0000-") + Gap;
+ int xName = xNumber + pFontOsdTitle->Width("0000-") + Gap;
if (fShowLogo && EnigmaConfig.fullTitleWidth) {
xNumber = xTitleLeft + Roundness;
xName = xEventNowLeft;
@@ -416,19 +476,21 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num
// draw channel number
osd->DrawText(xNumber + 3, yTitleTop + 3, GetChannelNumber(Channel, Number),
- Theme.Color(clrTitleShadow), clrTransparent, font,
+ Theme.Color(clrTitleShadow), clrTransparent, pFontOsdTitle,
xName - xNumber - Gap - 3, yTitleBottom - yTitleTop - 3, taCenter);
osd->DrawText(xNumber, yTitleTop, GetChannelNumber(Channel, Number),
- Theme.Color(clrTitleFg), clrTransparent, font,
+ Theme.Color(clrTitleFg), clrTransparent, pFontOsdTitle,
xName - xNumber - Gap, yTitleBottom - yTitleTop, taCenter);
+
// draw channel name
- osd->DrawText(xName + 3, yTitleTop + 3, GetChannelName(Channel),
- Theme.Color(clrTitleShadow), clrTransparent, font,
- xTitleRight - Roundness - xName - 3,
- yTitleBottom - yTitleTop - 3);
- osd->DrawText(xName, yTitleTop, GetChannelName(Channel),
- Theme.Color(clrTitleFg), clrTransparent, font,
- xTitleRight - Roundness - xName, yTitleBottom - yTitleTop);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle) {
+ int xName = (fShowLogo && EnigmaConfig.fullTitleWidth ? xEventNowLeft : xTitleLeft + Roundness + pFontOsdTitle->Width("0000-") + Gap);
+ idTitle = TE_TITLE(osd, idTitle, GetChannelName(Channel), pFontOsdTitle, xDateLeft - SmallGap - xName, this);
+ } else
+#endif
+ DrawTitle(GetChannelName(Channel));
+
// draw symbols
// right edge of logo
int xs = xBottomRight - Roundness;
@@ -454,7 +516,7 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num
}
bool fFlagFound = false;
- if ((!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && EnigmaConfig.showFlags && !isempty(Channel->Alang(0))) {
+ if (EnigmaConfig.showFlags && !isempty(Channel->Alang(0))) {
char *strFile = NULL;
asprintf(&strFile, "flags/%s", Channel->Alang(0));
if (EnigmaLogoCache.LoadSymbol(strFile)) {
@@ -465,11 +527,10 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num
free(strFile);
}
if (!fFlagFound) {
- const cFont *fontSmall = cFont::GetFont(fontSml);
- xs -= fontSmall->Width(Channel->Alang(0));
+ xs -= pFontLanguage->Width(Channel->Alang(0));
osd->DrawText(xs, yBottomTop + SmallGap , Channel->Alang(0),
- Theme.Color(clrSymbolActive), Theme.Color(clrBottomBg), fontSmall,
- fontSmall->Width(Channel->Alang(0)), yBottomBottom - SmallGap);
+ Theme.Color(clrSymbolActive), Theme.Color(clrBottomBg), pFontLanguage,
+ pFontLanguage->Width(Channel->Alang(0)), yBottomBottom - SmallGap);
}
// draw audio symbol according to current audio channel
int AudioMode = cDevice::PrimaryDevice()->GetAudioChannel();
@@ -526,6 +587,21 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num
}
}
#endif
+
+#ifdef USE_PLUGIN_AVARDS
+ cPlugin *AvardsPlugin = cPluginManager::GetPlugin("avards");
+ if (AvardsPlugin) {
+ avards_CurrentWssMode_v1_0 avardsData;
+ if (AvardsPlugin->Service("avards-CurrentWSSMode-v1.0", &avardsData)) {
+ if (avardsData.ModeString) { //TODO: icons?
+ xs -= (pFontLanguage->Width(avardsData.ModeString) + SmallGap);
+ osd->DrawText(xs, yBottomTop + SmallGap , avardsData.ModeString,
+ Theme.Color(clrSymbolActive), Theme.Color(clrBottomBg), pFontLanguage,
+ pFontLanguage->Width(avardsData.ModeString), yBottomBottom - SmallGap);
+ }
+ }
+ }
+#endif
xFirstSymbol = xs - Gap;
}
@@ -559,8 +635,16 @@ cString cSkinEnigmaDisplayChannel::GetChannelNumber(const cChannel *Channel, int
void cSkinEnigmaDisplayChannel::SetChannel(const cChannel *Channel, int Number)
{
+ debug("cSkinEnigmaDisplayChannel::SetChannel()\n");
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle && !fLocked)
+ TE_LOCK;
+#endif
+
xFirstSymbol = 0;
- lastTime = 0;
+ free(strLastDate);
+ strLastDate = NULL;
if (Channel) {
// clear all
@@ -584,16 +668,27 @@ void cSkinEnigmaDisplayChannel::SetChannel(const cChannel *Channel, int Number)
else
DrawChannelInfo(Channel, Number);
}
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle && !fLocked)
+ TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayChannel::SetEvents(const cEvent *Present,
const cEvent *Following)
{
- const cFont *lFontOsd = cFont::GetFont(fontOsd);
- const cFont *lFontSml = cFont::GetFont(fontSml);
+ debug("cSkinEnigmaDisplayChannel::SetEvents() %d %d\n", fScrollTitle, fLocked);
int xTimeLeft = xEventNowLeft + Gap;
- int xTimeWidth = lFontOsd->Width("00:00");
+ int xTimeWidth = pFontTitle->Width("00:00");
+ int lineHeightTitle = pFontTitle->Height();
+ int lineHeightSubtitle = pFontSubtitle->Height();
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle && !fLocked)
+ TE_LOCK;
+#endif
// check epg datas
const cEvent *e = Present; // Current event
@@ -620,46 +715,46 @@ void cSkinEnigmaDisplayChannel::SetEvents(const cEvent *Present,
}
}
- int xDurationLeft = xEventNowRight - Gap - max(lFontOsd->Width(sLen), lFontOsd->Width(sNow));
+ int xDurationLeft = xEventNowRight - Gap - max(pFontTitle->Width(sLen), pFontSubtitle->Width(sNow));
int xDurationWidth = xEventNowRight - Gap - xDurationLeft;
int xTextLeft = xTimeLeft + xTimeWidth + BigGap;
int xTextWidth = xDurationLeft - xTextLeft - BigGap;
// draw start time
osd->DrawText(xTimeLeft, yEventNowTop, e->GetTimeString(),
- Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground),
- lFontOsd, xTimeWidth, lineHeightOsd);
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground),
+ pFontTitle, xTimeWidth);
// draw title
osd->DrawText(xTextLeft, yEventNowTop, e->Title(),
- Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground),
- lFontOsd, xTextWidth, lineHeightOsd);
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground),
+ pFontTitle, xTextWidth);
// draw duration
osd->DrawText(xDurationLeft, yEventNowTop, sLen,
- Theme.Color(clrMenuEventTitle), Theme.Color(clrBackground),
- lFontOsd, xDurationWidth, lineHeightOsd, taRight);
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground),
+ pFontTitle, xDurationWidth, lineHeightTitle, taRight);
if (e->HasTimer()) {
if (e->IsRunning())
osd->DrawBitmap(xTimeLeft + (xTimeWidth - bmRecording.Width()) / 2,
- yEventNowTop + lineHeightOsd, bmRecording,
+ yEventNowTop + lineHeightTitle, bmRecording,
Theme.Color(clrSymbolRecActive),
Theme.Color(clrBackground));
else
osd->DrawBitmap(xTimeLeft + (xTimeWidth - bmTimer.Width()) / 2,
- yEventNowTop + lineHeightOsd, bmTimer,
+ yEventNowTop + lineHeightTitle, bmTimer,
Theme.Color(clrSymbolTimerActive),
Theme.Color(clrBackground));
}
// draw shorttext
- osd->DrawText(xTextLeft, yEventNowTop + lineHeightOsd, e->ShortText(),
- Theme.Color(clrMenuEventShortText),
- Theme.Color(clrBackground), lFontSml, xTextWidth, lineHeightSml);
+ osd->DrawText(xTextLeft, yEventNowTop + lineHeightTitle, e->ShortText(),
+ Theme.Color(clrMenuItemNotSelectableFg),
+ Theme.Color(clrBackground), pFontSubtitle, xTextWidth);
// draw duration
if ((now < total) && ((now / 60) > 0)) {
- osd->DrawText(xDurationLeft, yEventNowTop + lineHeightOsd, sNow,
- Theme.Color(clrMenuEventShortText),
- Theme.Color(clrBackground), lFontSml, xDurationWidth,
- lineHeightSml, taRight);
+ osd->DrawText(xDurationLeft, yEventNowTop + lineHeightTitle, sNow,
+ Theme.Color(clrMenuItemNotSelectableFg),
+ Theme.Color(clrBackground), pFontSubtitle, xDurationWidth,
+ lineHeightSubtitle, taRight);
}
// draw timebar
int xBarLeft = xBottomLeft + Roundness;
@@ -681,36 +776,48 @@ void cSkinEnigmaDisplayChannel::SetEvents(const cEvent *Present,
char sLen[6];
snprintf(sLen, sizeof(sLen), "%d'", e->Duration() / 60);
- int xDurationLeft = xEventNowRight - Gap - lFontOsd->Width(sLen);
+ int xDurationLeft = xEventNowRight - Gap - pFontTitle->Width(sLen);
int xDurationWidth = xEventNowRight - Gap - xDurationLeft;
int xTextLeft = xTimeLeft + xTimeWidth + BigGap;
int xTextWidth = xDurationLeft - xTextLeft - BigGap;
// draw start time
osd->DrawText(xTimeLeft, yEventNextTop, e->GetTimeString(),
- Theme.Color(clrMenuEventTitle), Theme.Color(clrAltBackground),
- lFontOsd, xTimeWidth, lineHeightOsd);
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontTitle, xTimeWidth);
// draw title
osd->DrawText(xTextLeft, yEventNextTop, e->Title(),
- Theme.Color(clrMenuEventTitle), Theme.Color(clrAltBackground),
- lFontOsd, xTextWidth, lineHeightOsd);
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontTitle, xTextWidth);
// draw duration
osd->DrawText(xDurationLeft, yEventNextTop, sLen,
- Theme.Color(clrMenuEventTitle), Theme.Color(clrAltBackground),
- lFontOsd, xDurationWidth, lineHeightOsd, taRight);
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontTitle, xDurationWidth, lineHeightTitle, taRight);
if (e->HasTimer())
osd->DrawBitmap(xTimeLeft + (xTimeWidth - bmTimer.Width()) / 2,
- yEventNextTop + lineHeightOsd, bmTimer,
+ yEventNextTop + lineHeightTitle, bmTimer,
Theme.Color(clrSymbolTimerActive), Theme.Color(clrAltBackground));
// draw shorttext
- osd->DrawText(xTextLeft, yEventNextTop + lineHeightOsd, e->ShortText(),
- Theme.Color(clrMenuEventShortText),
- Theme.Color(clrAltBackground), lFontSml, xTextWidth, lineHeightSml);
+ osd->DrawText(xTextLeft, yEventNextTop + lineHeightTitle, e->ShortText(),
+ Theme.Color(clrMenuItemNotSelectableFg),
+ Theme.Color(clrAltBackground), pFontSubtitle, xTextWidth);
}
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle && !fLocked)
+ TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayChannel::SetMessage(eMessageType Type, const char *Text)
{
+ debug("cSkinEnigmaDisplayChannel::SetMessage()\n");
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle && !fLocked)
+ TE_LOCK;
+#endif
+
// check if message
if (Text) {
// save osd region
@@ -720,48 +827,85 @@ void cSkinEnigmaDisplayChannel::SetMessage(eMessageType Type, const char *Text)
yMessageBottom - 1, clrTransparent);
osd->DrawRectangle(xMessageLeft, yMessageTop + SmallGap, xMessageRight - 1,
yMessageBottom - SmallGap - 1,
- Theme.Color(clrMessageBorder));
- osd->DrawText(xMessageLeft + Gap, yMessageTop + 2 * SmallGap, Text,
+ Theme.Color(clrButtonRedBg));
+ osd->DrawText(xMessageLeft, yMessageTop + 2 * SmallGap, Text,
Theme.Color(clrMessageStatusFg + 2 * Type),
Theme.Color(clrMessageStatusBg + 2 * Type),
- cFont::GetFont(fontOsd),
- xMessageRight - Gap - xMessageLeft - Gap - 1,
+ pFontMessage,
+ xMessageRight - xMessageLeft,
yMessageBottom - 2 * SmallGap - yMessageTop - 2 * SmallGap,
taCenter);
} else {
// restore saved osd region
osd->RestoreRegion();
}
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle && !fLocked)
+ TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayChannel::Flush(void)
{
- time_t now = time(NULL);
- if (now != lastTime) {
- lastTime = now;
+// debug("cSkinEnigmaDisplayChannel::Flush()\n");
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked && fScrollTitle)
+ TE_LOCK;
+#endif
+
+ cString date = DayDateTime();
+ if ((strLastDate == NULL) || strcmp(strLastDate, (const char*)date) != 0) {
+ free(strLastDate);
+ strLastDate = strdup((const char*)date);
// update date string
- cString date = DayDateTime();
- const cFont *font = cFont::GetFont(fontOsd);
- int w = font->Width(date);
- osd->DrawText(xTitleRight - Roundness - w, yTitleTop, date,
+ int w = pFontDate->Width(date);
+ osd->DrawText(xDateLeft, yTitleTop, date,
Theme.Color(clrTitleFg), Theme.Color(clrTitleBg),
- font, w, yTitleBottom - yTitleTop, taCenter);
+ pFontDate, w, yTitleBottom - yTitleTop, taCenter);
}
osd->Flush();
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle) {
+ TE_UNLOCK;
+ if (fLocked) {
+ fLocked = false;
+ TE_WAKEUP;
+ }
+ }
+#endif
}
// --- cSkinEnigmaDisplayMenu -----------------------------------------------
-class cSkinEnigmaDisplayMenu:public cSkinDisplayMenu {
+class cSkinEnigmaDisplayMenu : public cSkinDisplayMenu, cSkinEnigmaOsd {
private:
cOsd *osd;
+ const cFont *pFontList;
+ const cFont *pFontDate;
+ const cFont *pFontOsdTitle;
+ const cFont *pFontDetailsTitle;
+ const cFont *pFontDetailsSubtitle;
+ const cFont *pFontDetailsDate;
+ const cFont *pFontDetailsText;
+ const cFont *pFontHelpKeys;
+ const cFont *pFontInfoWarnHeadline;
+ const cFont *pFontInfoWarnText;
+ const cFont *pFontInfoTimerHeadline;
+ const cFont *pFontInfoTimerText;
+ const cFont *pFontMessage;
+ const cFont *pFontFixed;
char *strTitle;
char *strLastDate;
char *strTheme;
bool isMainMenu;
bool fShowLogo;
+ bool fShowLogoDefault;
bool fShowInfo;
+ bool fSetupAreasDone;
int xBodyLeft, xBodyRight, yBodyTop, yBodyBottom;
int xTitleLeft, xTitleRight, yTitleTop, yTitleBottom, yTitleDecoTop, yTitleDecoBottom;
@@ -771,17 +915,33 @@ private:
int xLogoLeft, xLogoRight, yLogoTop, yLogoBottom;
int xInfoLeft, xInfoRight, yInfoTop, yInfoBottom;
- int lineHeightOsd;
- int lineHeightSml;
+ int lineHeight;
+ int xItemLeft;
+ int xItemRight;
+ int yItemTop;
+
int nMessagesShown;
int nNumImageColors;
+#ifndef DISABLE_ANIMATED_TEXT
+ int nOldIndex;
+ int idListItem[MaxTabs];
+ int idTitle;
+ bool fLocked;
+ bool fScrollTitle;
+ bool fScrollInfo;
+ bool fScrollListItem;
+ bool fScrollOther;
+#endif
+
void SetScrollbar(void);
void SetupAreas(void);
- void DrawTitle(const char *Title);
+ void SetColors(void);
int DrawFlag(int x, int y, const tComponent *p);
const char *GetPluginMainMenuName(const char *plugin);
int ReadSizeVdr(const char *strPath);
+ bool HasTabbedText(const char *s, int Tab);
+
public:
cSkinEnigmaDisplayMenu();
virtual ~cSkinEnigmaDisplayMenu();
@@ -798,48 +958,77 @@ public:
virtual int GetTextAreaWidth(void) const;
virtual const cFont *GetTextAreaFont(bool FixedFont) const;
virtual void Flush(void);
+ virtual void DrawTitle(const char *Title);
};
cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void)
{
+ struct EnigmaOsdSize OsdSize;
+ EnigmaConfig.GetOsdSize(&OsdSize);
+
+ fSetupAreasDone = false;
setlocale(LC_TIME, tr("en_US"));
osd = NULL;
+ pFontList = EnigmaConfig.GetFont(FONT_LISTITEM);
+ pFontDate = EnigmaConfig.GetFont(FONT_DATE);
+ pFontOsdTitle = EnigmaConfig.GetFont(FONT_OSDTITLE);
+ pFontDetailsTitle = EnigmaConfig.GetFont(FONT_DETAILSTITLE);
+ pFontDetailsSubtitle = EnigmaConfig.GetFont(FONT_DETAILSSUBTITLE);
+ pFontDetailsDate = EnigmaConfig.GetFont(FONT_DETAILSDATE);
+ pFontDetailsText = EnigmaConfig.GetFont(FONT_DETAILSTEXT);
+ pFontHelpKeys = EnigmaConfig.GetFont(FONT_HELPKEYS);
+ pFontInfoWarnHeadline = EnigmaConfig.GetFont(FONT_INFOWARNHEADLINE);
+ pFontInfoWarnText = EnigmaConfig.GetFont(FONT_INFOWARNTEXT);
+ pFontInfoTimerHeadline = EnigmaConfig.GetFont(FONT_INFOTIMERHEADLINE);
+ pFontInfoTimerText = EnigmaConfig.GetFont(FONT_INFOTIMERTEXT);
+ pFontMessage = EnigmaConfig.GetFont(FONT_MESSAGE);
+ pFontFixed = EnigmaConfig.GetFont(FONT_FIXED);
+
strTitle = NULL;
strLastDate = NULL;
strTheme = strdup(Theme.Name());
- isMainMenu = true;
-#ifdef SKINENIGMA_NO_MENULOGO
+ isMainMenu = false;
fShowLogo = false;
+#ifdef SKINENIGMA_NO_MENULOGO
+ fShowLogoDefault = false;
#else
- fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3);
+ fShowLogoDefault = EnigmaConfig.showSymbols && (EnigmaConfig.showSymbolsMenu || EnigmaConfig.showImages);
#endif
- fShowInfo = EnigmaConfig.showInfo;
+ fShowInfo = false;
nMessagesShown = 0;
nNumImageColors = 2;
+#ifndef DISABLE_ANIMATED_TEXT
+ for (int i = 0; i < MaxTabs; i++)
+ idListItem[i] = -1;
+ nOldIndex = -1;
+ idTitle = -1;
+ fScrollTitle = EnigmaConfig.useTextEffects && EnigmaConfig.scrollTitle;
+ fScrollInfo = EnigmaConfig.useTextEffects && EnigmaConfig.scrollInfo;
+ fScrollListItem = EnigmaConfig.useTextEffects && EnigmaConfig.scrollListItem;
+ fScrollOther = EnigmaConfig.useTextEffects && EnigmaConfig.scrollOther;
+#endif
- lineHeightSml = cFont::GetFont(fontSml)->Height();
- lineHeightOsd = cFont::GetFont(fontOsd)->Height();
-
- int LogoHeight = max(lineHeightOsd + TitleDeco + lineHeightOsd + lineHeightSml,
- max(3 * lineHeightOsd,
- EnigmaConfig.showImages ? max(EnigmaConfig.imageHeight, IconHeight) : IconHeight
+ int LogoHeight = max(max(pFontOsdTitle->Height(), pFontDate->Height()) + TitleDeco + pFontDetailsTitle->Height() + Gap + pFontDetailsSubtitle->Height(),
+ max(3 * pFontDate->Height(),
+ (EnigmaConfig.showImages ? max(EnigmaConfig.imageHeight, IconHeight) : IconHeight)
)
);
int LogoWidth = EnigmaConfig.showImages ? max(IconWidth, EnigmaConfig.imageWidth) : IconWidth;
int RightColWidth = (144 + LogoWidth) & ~0x07; // must be multiple of 8
+ int MessageHeight = 2 * SmallGap + pFontMessage->Height() + 2 * SmallGap;
// title bar
xTitleLeft = 0;
- xTitleRight = Setup.OSDWidth - RightColWidth;
+ xTitleRight = OsdSize.w - RightColWidth;
yTitleTop = 0;
- yTitleBottom = lineHeightOsd;
+ yTitleBottom = max(pFontOsdTitle->Height(), pFontDate->Height());
yTitleDecoTop = yTitleBottom + TitleDecoGap;
yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight;
// help buttons
xButtonsLeft = xTitleLeft;
- xButtonsRight = Setup.OSDWidth;
- yButtonsTop = Setup.OSDHeight - lineHeightOsd;
- yButtonsBottom = Setup.OSDHeight;
+ xButtonsRight = OsdSize.w;
+ yButtonsTop = OsdSize.h - pFontHelpKeys->Height();
+ yButtonsBottom = OsdSize.h;
// content area with items
xBodyLeft = xTitleLeft;
xBodyRight = xTitleRight;
@@ -847,46 +1036,43 @@ cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void)
yBodyBottom = yButtonsTop - SmallGap;
// message area
xMessageLeft = xBodyLeft;
- xMessageRight = Setup.OSDWidth;
+ xMessageRight = OsdSize.w;
yMessageBottom = yButtonsTop - SmallGap;
yMessageTop = yMessageBottom - MessageHeight + SmallGap; // No extra SmallGap at bottom as there's already the Gap above the buttons
// logo box
- xLogoLeft = Setup.OSDWidth - LogoWidth;
- xLogoRight = Setup.OSDWidth;
+ xLogoLeft = OsdSize.w - LogoWidth;
+ xLogoRight = OsdSize.w;
yLogoTop = yTitleTop;
yLogoBottom = yLogoTop + LogoHeight + SmallGap;
// info box
- xInfoLeft = Setup.OSDWidth - RightColWidth;
- xInfoRight = Setup.OSDWidth;
+ xInfoLeft = OsdSize.w - RightColWidth;
+ xInfoRight = OsdSize.w;
yInfoTop = yLogoBottom;
yInfoBottom = yBodyBottom;
// date box
xDateLeft = xTitleRight;
- xDateRight = Setup.OSDWidth;
+ xDateRight = OsdSize.w;
yDateTop = yTitleTop;
yDateBottom = yLogoBottom;
// create osd
- osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
+ osd = cOsdProvider::NewOsd(OsdSize.x, OsdSize.y);
- tArea Areas[] = { {xTitleLeft, yTitleTop, xMessageRight - 1, yButtonsBottom - 1, EnigmaConfig.singleArea8Bpp ? 8 : 4} };
- if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ tArea Areas[] = { {xTitleLeft, yTitleTop, xMessageRight - 1, yButtonsBottom - 1, 8} };
+ if (EnigmaConfig.singleArea8Bpp && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ debug("cSkinEnigmaDisplayMenu: using %dbpp single area\n", Areas[0].bpp);
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
- nNumImageColors = (EnigmaConfig.singleArea8Bpp ? 230 : 2); //TODO: find correct number of colors
+ nNumImageColors = 230; //TODO: find correct number of colors
} else {
+ debug("cSkinEnigmaDisplayMenu: using multiple areas\n");
tArea Areas[] = { {xTitleLeft, yTitleTop, xTitleRight - 1, yTitleDecoBottom - 1, 2}, //title area
- {xBodyLeft, yBodyTop, xBodyRight - 1, yLogoBottom - 1, 2}, //body area (beside date/logo area)
-#ifdef SKINENIGMA_NO_MENULOGO
- {xDateLeft, yDateTop, xDateRight - 1, yBodyTop - 1, 2}, //date
- {xDateLeft, yBodyTop, xDateRight - 1, yDateBottom - 1, 2}, //date/body
-#else
- {xDateLeft, yDateTop, xDateRight - 1, yInfoTop - 1, 4}, //date/logo area
-#endif
- {xBodyLeft, yInfoTop, xInfoRight - 1, yInfoTop + lineHeightOsd - 1, 4}, //area for symbols in event/recording info
- {xBodyLeft, yInfoTop + lineHeightOsd, xInfoRight - 1, yMessageTop - 1, 2}, //body area (below date/logo area)
- {xMessageLeft, yMessageTop, xMessageRight - 1, yButtonsBottom - 1, 4} //message/buttons area
+ {xBodyLeft, yBodyTop, xBodyRight - 1, yInfoTop + pFontDetailsDate->Height() - 1, 2}, //body area (beside date/logo/symbols area)
+ {xDateLeft, yDateTop, xLogoRight - 1, yInfoTop - 1, 4}, //date/logo area
+ {xBodyRight, yInfoTop, xInfoRight - 1, yInfoTop + pFontDetailsDate->Height() - 1, 4}, //area for symbols in event/recording info
+ {xBodyLeft, yInfoTop + pFontDetailsDate->Height(), xInfoRight - 1, yMessageTop - 1, 2}, // body/info area (below symbols area)
+ {xMessageLeft, yMessageTop, xButtonsRight - 1, yButtonsBottom - 1, 4} //buttons/message area
};
-
+
eOsdError rc = osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea));
if (rc == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
@@ -901,28 +1087,170 @@ cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void)
nNumImageColors = 13; // "16 available colors" - "clrTransparent" - "clrLogoBg" - "clrMenuTxtFg"
}
- // clear all
- osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent);
+ lineHeight = pFontList->Height();
+ xItemLeft = xBodyLeft + (EnigmaConfig.showMarker ? lineHeight : SmallGap);
+ xItemRight = (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - (EnigmaConfig.showMarker ? lineHeight : SmallGap);
+ int numItems = (yBodyBottom - yBodyTop) / lineHeight;
+ yItemTop = yBodyTop + (yBodyBottom - yBodyTop - numItems * lineHeight) / 2;
- SetupAreas();
+#ifndef DISABLE_ANIMATED_TEXT
+ fLocked = false;
+ if (fScrollTitle || fScrollInfo || fScrollListItem || fScrollOther) {
+ TE_START(osd);
+ fLocked = true;
+ }
+#endif
+}
+
+void cSkinEnigmaDisplayMenu::SetColors(void)
+{
+ debug("cSkinEnigmaDisplayMenu::SetColors\n");
+
+ if (osd->GetBitmap(1) == NULL) { //single area
+ cBitmap *bitmap = osd->GetBitmap(0);
+ if (bitmap) {
+ bitmap->Reset();
+ bitmap->SetColor( 0, clrTransparent);
+ bitmap->SetColor( 1, Theme.Color(clrTitleBg));
+ bitmap->SetColor( 2, Theme.Color(clrTitleFg));
+ bitmap->SetColor( 3, Theme.Color(clrTitleShadow));
+ bitmap->SetColor( 4, Theme.Color(clrLogoBg));
+ bitmap->SetColor( 5, Theme.Color(clrBackground));
+ bitmap->SetColor( 6, Theme.Color(clrAltBackground));
+ bitmap->SetColor( 7, Theme.Color(clrMenuTxtFg));
+ bitmap->SetColor( 8, Theme.Color(clrBottomBg));
+ bitmap->SetColor( 9, Theme.Color(clrButtonRedBg));
+ bitmap->SetColor(10, Theme.Color(clrButtonRedFg));
+ bitmap->SetColor(11, Theme.Color(clrButtonGreenBg));
+ bitmap->SetColor(12, Theme.Color(clrButtonGreenFg));
+ bitmap->SetColor(13, Theme.Color(clrButtonYellowBg));
+ bitmap->SetColor(14, Theme.Color(clrButtonYellowFg));
+ bitmap->SetColor(15, Theme.Color(clrButtonBlueBg));
+ bitmap->SetColor(16, Theme.Color(clrButtonBlueFg));
+ }
+ return;
+ }
+
+ cBitmap *bitmap = osd->GetBitmap(0);
+ if (bitmap) { //title area
+ bitmap->Reset();
+ bitmap->SetColor(0, clrTransparent);
+ bitmap->SetColor(1, Theme.Color(clrTitleBg));
+ bitmap->SetColor(2, Theme.Color(clrTitleFg));
+ bitmap->SetColor(3, Theme.Color(clrTitleShadow));
+ }
+ bitmap = osd->GetBitmap(1);
+ if (bitmap) { //body area (beside date/logo/ area)
+ bitmap->Reset();
+ bitmap->SetColor(0, Theme.Color(clrBackground));
+ bitmap->SetColor(1, Theme.Color(clrAltBackground));
+ bitmap->SetColor(2, Theme.Color(clrMenuItemSelectableFg));
+ bitmap->SetColor(3, Theme.Color(clrMenuItemNotSelectableFg));
+ }
+ bitmap = osd->GetBitmap(2);
+ if (bitmap) { //date/logo area
+ bitmap->Reset();
+ if (fShowLogo) {
+ bitmap->SetColor(0, clrTransparent);
+ bitmap->SetColor(1, Theme.Color(clrLogoBg));
+ bitmap->SetColor(2, Theme.Color(clrMenuTxtFg));
+ } else {
+ bitmap->SetColor(0, Theme.Color(clrBackground));
+ bitmap->SetColor(1, Theme.Color(clrAltBackground));
+ bitmap->SetColor(2, Theme.Color(clrMenuItemSelectableFg));
+ bitmap->SetColor(3, Theme.Color(clrMenuItemNotSelectableFg));
+ bitmap->SetColor(4, clrTransparent);
+ bitmap->SetColor(5, Theme.Color(clrLogoBg));
+ bitmap->SetColor(6, Theme.Color(clrMenuTxtFg));
+ }
+ }
+ bitmap = osd->GetBitmap(3);
+ if (bitmap) { //area for symbols in event/recording info
+ bitmap->Reset();
+ bitmap->SetColor(0, Theme.Color(clrBackground));
+ bitmap->SetColor(1, Theme.Color(clrAltBackground));
+ bitmap->SetColor(2, Theme.Color(clrMenuItemSelectableFg));
+ bitmap->SetColor(3, Theme.Color(clrMenuItemNotSelectableFg));
+ }
+ bitmap = osd->GetBitmap(4);
+ if (bitmap) { //body/info area (below symbols area)
+ bitmap->Reset();
+ bitmap->SetColor(0, Theme.Color(clrBackground));
+ bitmap->SetColor(1, Theme.Color(clrAltBackground));
+ bitmap->SetColor(2, Theme.Color(clrMenuItemSelectableFg));
+ bitmap->SetColor(3, Theme.Color(clrMenuItemNotSelectableFg));
+ }
+ bitmap = osd->GetBitmap(5);
+ if (bitmap) { //buttons/message area
+ bitmap->Reset();
+ bitmap->SetColor( 0, Theme.Color(clrBackground));
+ bitmap->SetColor( 1, Theme.Color(clrAltBackground));
+ bitmap->SetColor( 2, Theme.Color(clrMenuItemSelectableFg));
+ bitmap->SetColor( 3, Theme.Color(clrMenuItemNotSelectableFg));
+ bitmap->SetColor( 4, Theme.Color(clrBottomBg));
+ bitmap->SetColor( 5, Theme.Color(clrButtonRedBg));
+ bitmap->SetColor( 6, Theme.Color(clrButtonRedFg));
+ bitmap->SetColor( 7, Theme.Color(clrButtonGreenBg));
+ bitmap->SetColor( 8, Theme.Color(clrButtonGreenFg));
+ bitmap->SetColor( 9, Theme.Color(clrButtonYellowBg));
+ bitmap->SetColor(10, Theme.Color(clrButtonYellowFg));
+ bitmap->SetColor(11, Theme.Color(clrButtonBlueBg));
+ bitmap->SetColor(12, Theme.Color(clrButtonBlueFg));
+ bitmap->SetColor(13, clrTransparent);
+ // color 14 reserved for "clrMessageStatusFg + 2 * Type"
+ // color 15 reserved for "clrMessageStatusBg + 2 * Type"
+ }
}
void cSkinEnigmaDisplayMenu::SetupAreas(void)
{
+ //Must be TE_LOCKed by caller
+
debug("cSkinEnigmaDisplayMenu::SetupAreas\n");
+ fSetupAreasDone = true;
+ SetColors();
+
+#ifndef DISABLE_ANIMATED_TEXT
+ EnigmaTextEffects.Clear();
+ idTitle = -1;
+ nOldIndex = -1;
+ for (int i = 0; i < MaxTabs; i++)
+ idListItem[i] = -1;
+#endif
- DrawTitle(strTitle);
+ xItemRight = (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - (EnigmaConfig.showMarker ? lineHeight : SmallGap);
+
+ // clear transparent areas (without date/logo borders)
+ osd->DrawRectangle(xBodyLeft, yTitleDecoBottom, xDateLeft - 1, yBodyTop - 1, clrTransparent);
+ osd->DrawRectangle(xBodyLeft, yMessageBottom, xInfoRight - 1, yButtonsTop - 1, clrTransparent);
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle) {
+ idTitle = TE_TITLE(osd, idTitle, strTitle, pFontOsdTitle, xTitleRight - xTitleLeft - Roundness, this);
+ } else
+#endif
+ DrawTitle(strTitle);
// draw date area
- osd->DrawRectangle(xDateLeft, yDateTop, xDateRight - 1, yDateBottom - 1,
- fShowLogo ? Theme.Color(clrLogoBg) : Theme.Color(clrBackground));
+ if (fShowLogo) {
+ osd->DrawRectangle(xDateLeft + SmallGap, yDateTop, xLogoRight - 1, yDateBottom - SmallGap - 1, Theme.Color(clrLogoBg));
+ //draw borders
+ osd->DrawRectangle(xDateLeft, yDateTop, xDateLeft + SmallGap - 1, yLogoBottom - SmallGap - 1, clrTransparent);
+ osd->DrawRectangle(xDateLeft, yLogoBottom - SmallGap, xDateRight, yLogoBottom - 1, clrTransparent);
+ } else {
+ osd->DrawRectangle(xDateLeft + SmallGap, yDateTop, xLogoRight - 1, yTitleDecoBottom - 1, Theme.Color(clrLogoBg));
+ //draw borders
+ osd->DrawRectangle(xDateLeft, yDateTop, xDateLeft + SmallGap - 1, yTitleDecoBottom - 1, clrTransparent);
+ osd->DrawRectangle(xDateLeft, yTitleDecoBottom, xInfoRight, yBodyTop - 1, clrTransparent);
+ }
+
+ // draw body area
+ osd->DrawRectangle(xBodyLeft, yBodyTop, xBodyRight - 1, yBodyBottom - 1, Theme.Color(clrBackground));
// draw info area
if (fShowInfo) {
osd->DrawRectangle(xInfoLeft, fShowLogo ? yInfoTop : yBodyTop, xInfoRight - 1, yInfoBottom - 1, Theme.Color(clrAltBackground));
- const cFont *font = cFont::GetFont(fontOsd);
- int h = font->Height();
int x = xInfoLeft + Gap;
int y = fShowLogo ? yInfoTop : yBodyTop;
int w = xInfoRight - x;
@@ -940,17 +1268,24 @@ void cSkinEnigmaDisplayMenu::SetupAreas(void)
p->Service("Epgsearch-lastconflictinfo-v1.0", serviceData);
if (serviceData->relevantConflicts > 0) {
- int yWarning = yMaxHeight - 3 * h; // Needed space for warning
+ int yWarning = yMaxHeight -
+ pFontInfoWarnHeadline->Height() -
+ 2 * pFontInfoWarnText->Height(); // Needed space for warning
yMaxHeight = yWarning;
osd->DrawRectangle(xInfoLeft, yWarning, xInfoRight - 1, yWarning + SmallGap + 1, Theme.Color(clrBackground));
- yWarning += 1 + h / 2;
- osd->DrawText(xInfoLeft, yWarning, tr("WARNING"), Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), font, w, h, taCenter);
- yWarning += h + SmallGap;
+ yWarning += pFontInfoWarnText->Height() / 2;
+ TE_BLINK(osd, -1, xInfoLeft, yWarning, tr("WARNING"),
+ Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground),
+ pFontInfoWarnHeadline,
+ w, pFontInfoWarnHeadline->Height(), taCenter);
+ yWarning += (int)(1.5 * pFontInfoWarnHeadline->Height());
char *info;
asprintf(&info, "%d %s", serviceData->relevantConflicts, (serviceData->relevantConflicts == 1 ? tr("Timer conflict") : tr("Timer conflicts")));
- osd->DrawText(x, yWarning, info, Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), font, w, h, taCenter);
- yWarning += h;
+ osd->DrawText(x, yWarning, info, Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground),
+ pFontInfoWarnText,
+ w, pFontInfoWarnText->Height(), taCenter);
+ yWarning += pFontInfoWarnText->Height();
free(info);
}
delete serviceData;
@@ -960,20 +1295,36 @@ void cSkinEnigmaDisplayMenu::SetupAreas(void)
#endif //SKINENIGMA_HAVE_EPGSEARCH
if (Timers.GetNextActiveTimer()) {
+ int h = pFontInfoTimerHeadline->Height();
// Show next active timers
y += h / 2;
- osd->DrawText(x, y, tr("TIMERS"), Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), font, w, h, taCenter);
+ osd->DrawText(x, y, tr("TIMERS"), Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground),
+ pFontInfoTimerHeadline,
+ w, pFontInfoTimerHeadline->Height(), taCenter);
y += h + h / 2;
EnigmaStatus.UpdateActiveTimers();
+ h = pFontInfoTimerText->Height();
for (tTimer *timer = EnigmaStatus.mTimers.First(); timer; timer = EnigmaStatus.mTimers.Next(timer)) {
if (y + 2 * h + SmallGap + 1 + h / 2 > yMaxHeight)
break; // don't overwrite warning or help buttons
if (timer->isRecording) {
- osd->DrawBitmap(x, y + (lineHeightOsd - bmRecording.Height()) / 2, bmRecording, Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground)); //TODO: draw red
+ osd->DrawBitmap(x, y + (h - bmRecording.Height()) / 2, bmRecording, Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground));
}
- osd->DrawText(x + (timer->isRecording ? (bmRecording.Width() + Gap) : 0), y, timer->title.c_str(), Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), font, w, h);
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollInfo)
+ TE_MARQUEE(osd, -1, x + (timer->isRecording ? (bmRecording.Width() + Gap) : 0),
+ y, timer->title.c_str(),
+ Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground),
+ pFontInfoTimerText, w, h);
+ else
+#endif
+ osd->DrawText(x + (timer->isRecording ? (bmRecording.Width() + Gap) : 0),
+ y, timer->title.c_str(),
+ Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground),
+ pFontInfoTimerText, w, h);
y += h;
char* info = NULL;
if (timer->isRecording) {
@@ -981,7 +1332,7 @@ void cSkinEnigmaDisplayMenu::SetupAreas(void)
} else {
asprintf(&info, "%d. %s / %s", timer->startDay, *TimeString(timer->startTime), timer->channelName.c_str());
}
- osd->DrawText(x, y, info, Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), font, w, h);
+ osd->DrawText(x, y, info, Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), pFontInfoTimerText, w, h);
free(info);
y += h;
osd->DrawRectangle(x, y + SmallGap, xInfoRight - Gap - 1, y + SmallGap + 1, Theme.Color(clrMenuItemSelectableFg));
@@ -996,6 +1347,12 @@ void cSkinEnigmaDisplayMenu::SetupAreas(void)
cSkinEnigmaDisplayMenu::~cSkinEnigmaDisplayMenu()
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle || fScrollInfo || fScrollListItem || fScrollOther) {
+ if (!fLocked) TE_LOCK;
+ TE_STOP;
+ }
+#endif
free(strTheme);
free(strTitle);
free(strLastDate);
@@ -1004,77 +1361,97 @@ cSkinEnigmaDisplayMenu::~cSkinEnigmaDisplayMenu()
void cSkinEnigmaDisplayMenu::SetScrollbar(void)
{
+ //Must be TE_LOCKed by caller
+
// check if scrollbar is needed
if (textScroller.CanScroll()) {
- int h = lineHeightOsd;
- int w = lineHeightOsd;
int yt = textScroller.Top();
int yb = yt + textScroller.Height();
- int st = yt + h + Gap;
- int sb = yb - h - Gap;
+ int st = yt + ScrollbarHeight + Gap;
+ int sb = yb - ScrollbarHeight - Gap;
int tt = st + (sb - st) * textScroller.Offset() / textScroller.Total();
int tb = tt + (sb - st) * textScroller.Shown() / textScroller.Total();
int xl = textScroller.Width() + SmallGap;
// arrow up
- osd->DrawRectangle(xl, yt, xl + w, yt + SmallGap,
- textScroller.CanScrollUp() ? Theme.Color(clrMenuScrollbarShown) : Theme.Color(clrAltBackground));
- osd->DrawRectangle(xl + w - SmallGap, yt + SmallGap, xl + w, yt + h,
- textScroller.CanScrollUp() ? Theme.Color(clrMenuScrollbarShown) : Theme.Color(clrAltBackground));
+ osd->DrawRectangle(xl, yt, xl + ScrollbarWidth, yt + SmallGap,
+ textScroller.CanScrollUp() ? Theme.Color(clrMenuTxtFg) : Theme.Color(clrAltBackground));
+ osd->DrawRectangle(xl + ScrollbarWidth - SmallGap, yt + SmallGap, xl + ScrollbarWidth, yt + ScrollbarHeight,
+ textScroller.CanScrollUp() ? Theme.Color(clrMenuTxtFg) : Theme.Color(clrAltBackground));
// draw background of scrollbar
- osd->DrawRectangle(xl + w - SmallGap, st, xl + w, sb, Theme.Color(clrMenuScrollbarTotal));
+ osd->DrawRectangle(xl + ScrollbarWidth - SmallGap, st, xl + ScrollbarWidth, sb, Theme.Color(clrAltBackground));
// draw visible area of scrollbar
- osd->DrawRectangle(xl + w - SmallGap, tt, xl + w, tb, Theme.Color(clrMenuScrollbarShown));
+ osd->DrawRectangle(xl + ScrollbarWidth - SmallGap, tt, xl + ScrollbarWidth, tb, Theme.Color(clrMenuTxtFg));
// arrow down
- osd->DrawRectangle(xl + w - SmallGap, yb - h, xl + w, yb - SmallGap,
- textScroller.CanScrollDown() ? Theme.Color(clrMenuScrollbarShown) : Theme.Color(clrAltBackground));
- osd->DrawRectangle(xl, yb - SmallGap, xl + w, yb,
- textScroller.CanScrollDown() ? Theme.Color(clrMenuScrollbarShown) : Theme.Color(clrAltBackground));
+ osd->DrawRectangle(xl + ScrollbarWidth - SmallGap, yb - ScrollbarHeight, xl + ScrollbarWidth, yb - SmallGap,
+ textScroller.CanScrollDown() ? Theme.Color(clrMenuTxtFg) : Theme.Color(clrAltBackground));
+ osd->DrawRectangle(xl, yb - SmallGap, xl + ScrollbarWidth, yb,
+ textScroller.CanScrollDown() ? Theme.Color(clrMenuTxtFg) : Theme.Color(clrAltBackground));
}
}
void cSkinEnigmaDisplayMenu::Scroll(bool Up, bool Page)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
cSkinDisplayMenu::Scroll(Up, Page);
SetScrollbar();
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
int cSkinEnigmaDisplayMenu::MaxItems(void)
{
// max number of items
- return (yBodyBottom - yBodyTop) / lineHeightOsd;
+ return (yBodyBottom - yBodyTop) / pFontList->Height();
}
void cSkinEnigmaDisplayMenu::Clear(void)
{
debug("cSkinEnigmaDisplayMenu::Clear\n");
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+ nOldIndex = -1;
+ for (int i = 0; i < MaxTabs; i++) {
+ if (idListItem[i] >= 0) {
+ EnigmaTextEffects.ResetText(idListItem[i], Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrBackground), !fLocked);
+ idListItem[i] = -1;
+ }
+ }
+#endif
+
textScroller.Reset();
if (strcmp(strTheme, Theme.Name()) != 0) {
free(strTheme);
strTheme = strdup(Theme.Name());
- int i = 0;
- cBitmap *bitmap = osd->GetBitmap(i);
- while (bitmap) {
- bitmap->Reset();
- i++;
- bitmap = osd->GetBitmap(i);
- }
-
SetupAreas();
} else {
// clear items area
- osd->DrawRectangle(xBodyLeft, yBodyTop, (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - 1, yBodyBottom - 1, Theme.Color(clrBackground));
+ if (fShowLogo || fShowInfo) {
+ osd->DrawRectangle(xBodyLeft, yBodyTop, xBodyRight - 1, yBodyBottom - 1, Theme.Color(clrBackground));
+ //TODO? clear logo and/or info area?
+ } else {
+ osd->DrawRectangle(xBodyLeft, yBodyTop, xInfoRight - 1, yBodyBottom - 1, Theme.Color(clrBackground));
+ }
}
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
+
}
void cSkinEnigmaDisplayMenu::SetTitle(const char *Title)
{
debug("cSkinEnigmaDisplayMenu::SetTitle(%s)\n", Title);
+ bool fTitleChanged = false;
if (Title && strTitle) {
if (strcmp(Title, strTitle) != 0) {
+ fTitleChanged = true;
free(strTitle);
strTitle = strdup(Title);
}
@@ -1089,18 +1466,25 @@ void cSkinEnigmaDisplayMenu::SetTitle(const char *Title)
char *strTitlePrefix = NULL;
asprintf(&strTitlePrefix, "%s - ", tr("VDR"));
- if (!(isMainMenu && Title && strncmp(strTitlePrefix, Title, strlen(strTitlePrefix)) == 0)) {
+ if ((Title == NULL) || (isMainMenu && strncmp(strTitlePrefix, Title, strlen(strTitlePrefix)) == 0)) {
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+ if (fScrollTitle) {
+ idTitle = TE_TITLE(osd, idTitle, strTitle, pFontOsdTitle, xTitleRight - xTitleLeft - Roundness, this);
+ } else
+#endif
+ DrawTitle(Title);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
+ } else {
bool old_isMainMenu = isMainMenu;
bool old_fShowLogo = fShowLogo;
bool old_fShowInfo = fShowInfo;
if (strTitle == NULL || strncmp(strTitlePrefix, strTitle, strlen(strTitlePrefix)) == 0) {
isMainMenu = true;
-#ifdef SKINENIGMA_NO_MENULOGO
- fShowLogo = false;
-#else
- fShowLogo = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3);
-#endif
+ fShowLogo = fShowLogoDefault ? EnigmaConfig.showSymbolsMenu : false;
fShowInfo = EnigmaConfig.showInfo;
} else {
isMainMenu = false;
@@ -1108,17 +1492,43 @@ void cSkinEnigmaDisplayMenu::SetTitle(const char *Title)
fShowInfo = false;
}
- if (old_isMainMenu != isMainMenu
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fTitleChanged) {
+ if (!fLocked) TE_LOCK;
+ EnigmaTextEffects.Clear();
+ idTitle = -1;
+ nOldIndex = -1;
+ for (int i = 0; i < MaxTabs; i++)
+ idListItem[i] = -1;
+ if (!fLocked) TE_UNLOCK;
+ }
+#endif
+
+ if (!fSetupAreasDone
+ || old_isMainMenu != isMainMenu
|| old_fShowLogo != fShowLogo
|| old_fShowInfo != fShowInfo) {
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
SetupAreas();
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
} else {
- DrawTitle(Title);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+ if (fScrollTitle) {
+ idTitle = TE_TITLE(osd, idTitle, strTitle, pFontOsdTitle, xTitleRight - xTitleLeft - Roundness, this);
+ } else
+#endif
+ DrawTitle(Title);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
- } else {
- DrawTitle(Title);
}
-
free (strTitlePrefix);
free(strLastDate);
@@ -1127,43 +1537,49 @@ void cSkinEnigmaDisplayMenu::SetTitle(const char *Title)
void cSkinEnigmaDisplayMenu::DrawTitle(const char *Title)
{
+ //Must be TE_LOCKed by caller
+
// draw titlebar
osd->DrawRectangle(xTitleLeft, yTitleTop, xTitleRight - 1, yTitleBottom - 1, Theme.Color(clrTitleBg));
+ osd->DrawRectangle(xTitleLeft, yTitleBottom, xTitleRight - 1, yTitleDecoTop - 1, clrTransparent);
osd->DrawRectangle(xTitleLeft, yTitleDecoTop, xTitleRight - 1, yTitleDecoBottom - 1, Theme.Color(clrTitleBg));
// draw rounded left corner of title bar
osd->DrawEllipse(xTitleLeft, yTitleTop, xTitleLeft + Roundness - 1, yTitleTop + Roundness - 1, clrTransparent, -2);
// debug("DrawTitle(%s)\n", Title);
if (Title) {
+ int y = yTitleTop + (yTitleBottom - yTitleTop - pFontOsdTitle->Height()) / 2;
// draw title with shadow
- osd->DrawText(xTitleLeft + Roundness + 3, yTitleTop + 3, Title,
+ osd->DrawText(xTitleLeft + Roundness + 3, y + 3, Title,
Theme.Color(clrTitleShadow), clrTransparent,
- cFont::GetFont(fontOsd),
+ pFontOsdTitle,
xTitleRight - xTitleLeft - Roundness - 3,
- yTitleBottom - yTitleTop - 3);
- osd->DrawText(xTitleLeft + Roundness, yTitleTop, Title,
+ yTitleBottom - y - 3);
+ osd->DrawText(xTitleLeft + Roundness, y, Title,
Theme.Color(clrTitleFg), clrTransparent,
- cFont::GetFont(fontOsd),
- xTitleRight - xTitleLeft - Roundness,
- yTitleBottom - yTitleTop);
+ pFontOsdTitle,
+ xTitleRight - xTitleLeft - Roundness - 3,
+ yTitleBottom - y);
}
}
void cSkinEnigmaDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
{
debug("cSkinEnigmaDisplayMenu::SetButtons(%s, %s, %s, %s)\n", Red, Green, Yellow, Blue);
- const cFont *font = cFont::GetFont(fontOsd);
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
int w = (xButtonsRight - xButtonsLeft) / 4;
int t3 = xButtonsLeft + xButtonsRight - xButtonsLeft - w;
int t2 = t3 - w;
int t1 = t2 - w;
int t0 = xButtonsLeft;
- // clear background
- osd->DrawRectangle(xButtonsLeft, yButtonsTop, xButtonsRight, yButtonsBottom, clrTransparent);
+
// draw color buttons
if (Red)
osd->DrawText(t0, yButtonsTop, Red, Theme.Color(clrButtonRedFg),
- Theme.Color(clrButtonRedBg), font, t1 - t0 + 1,
+ Theme.Color(clrButtonRedBg), pFontHelpKeys, t1 - t0 + 1,
yButtonsBottom - yButtonsTop, taCenter);
else {
osd->DrawRectangle(t0, yButtonsTop, Green ? t1 - 1 : t1, yButtonsBottom - 1, Theme.Color(clrBottomBg));
@@ -1171,46 +1587,55 @@ void cSkinEnigmaDisplayMenu::SetButtons(const char *Red, const char *Green, cons
}
if (Green)
osd->DrawText(t1, yButtonsTop, Green, Theme.Color(clrButtonGreenFg),
- Theme.Color(clrButtonGreenBg), font, w,
+ Theme.Color(clrButtonGreenBg), pFontHelpKeys, w,
yButtonsBottom - yButtonsTop, taCenter);
else
osd->DrawRectangle(t1, yButtonsTop, Yellow ? t1 + w : t2 - 1, yButtonsBottom - 1, Theme.Color(clrBottomBg));
if (Yellow)
osd->DrawText(t2, yButtonsTop, Yellow, Theme.Color(clrButtonYellowFg),
- Theme.Color(clrButtonYellowBg), font, w,
+ Theme.Color(clrButtonYellowBg), pFontHelpKeys, w,
yButtonsBottom - yButtonsTop, taCenter);
else
osd->DrawRectangle(t2, yButtonsTop, Blue ? t2 + w : t3 - 1, yButtonsBottom - 1, Theme.Color(clrBottomBg));
if (Blue)
osd->DrawText(t3, yButtonsTop, Blue, Theme.Color(clrButtonBlueFg),
- Theme.Color(clrButtonBlueBg), font, w,
+ Theme.Color(clrButtonBlueBg), pFontHelpKeys, w,
yButtonsBottom - yButtonsTop, taCenter);
else {
osd->DrawRectangle(t3, yButtonsTop, xButtonsRight, yButtonsBottom, Theme.Color(clrBottomBg));
osd->DrawEllipse(xButtonsRight - Roundness, yButtonsBottom - Roundness,
xButtonsRight - 1, yButtonsBottom - 1, clrTransparent, -4);
}
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayMenu::SetMessage(eMessageType Type, const char *Text)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
// check if message
if (Text) {
-
+#ifndef DISABLE_ANIMATED_TEXT
+ EnigmaTextEffects.PauseEffects(yMessageTop);
+#endif
// save osd region
if (nMessagesShown == 0)
osd->SaveRegion(xMessageLeft, yMessageTop, xMessageRight - 1, yMessageBottom - 1);
+
// draw message
osd->DrawRectangle(xMessageLeft, yMessageTop, xMessageRight - 1,
yMessageBottom - 1, clrTransparent);
osd->DrawRectangle(xMessageLeft, yMessageTop + SmallGap, xMessageRight - 1,
- yMessageBottom - 1, Theme.Color(clrMessageBorder));
- osd->DrawText(xMessageLeft + Gap, yMessageTop + 2 * SmallGap, Text,
+ yMessageBottom - 1, Theme.Color(clrButtonRedBg));
+ osd->DrawText(xMessageLeft, yMessageTop + 2 * SmallGap, Text,
Theme.Color(clrMessageStatusFg + 2 * Type),
Theme.Color(clrMessageStatusBg + 2 * Type),
- cFont::GetFont(fontOsd),
- xMessageRight - Gap - xMessageLeft - Gap - 1,
+ pFontMessage,
+ xMessageRight - xMessageLeft,
yMessageBottom - SmallGap - yMessageTop - 2 * SmallGap,
taCenter);
nMessagesShown++;
@@ -1220,25 +1645,43 @@ void cSkinEnigmaDisplayMenu::SetMessage(eMessageType Type, const char *Text)
// restore saved osd region
if (nMessagesShown == 0)
osd->RestoreRegion();
+#ifndef DISABLE_ANIMATED_TEXT
+ EnigmaTextEffects.PauseEffects();
+#endif
+ }
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
+}
+
+bool cSkinEnigmaDisplayMenu::HasTabbedText(const char *s, int Tab)
+{
+ if (!s)
+ return false;
+
+ const char *b = strchrnul(s, '\t');
+ while (*b && Tab-- > 0) {
+ b = strchrnul(b + 1, '\t');
}
+ if (!*b)
+ return (Tab <= 0) ? true : false;
+ return true;
}
void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
{
- int xItemLeft = xBodyLeft + (EnigmaConfig.showMarker ? lineHeightOsd : SmallGap);
- int xItemRight = (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - (EnigmaConfig.showMarker ? lineHeightOsd : SmallGap);
- int numItems = (yBodyBottom - yBodyTop) / lineHeightOsd;
- int top = yBodyTop + (yBodyBottom - yBodyTop - numItems * lineHeightOsd) / 2;
-
- int y = top + Index * lineHeightOsd;
+ int y = yItemTop + Index * lineHeight;
if (nMessagesShown > 0 && y >= yMessageTop)
return; //Don't draw above messages
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
tColor ColorFg, ColorBg;
// select colors
if (Current) {
- ColorFg = Theme.Color(clrMenuItemCurrentFg);
- ColorBg = Theme.Color(clrMenuHighlight);
+ ColorFg = Theme.Color(clrMenuItemSelectableFg);
+ ColorBg = Theme.Color(clrAltBackground);
} else {
if (Selectable) {
ColorFg = Theme.Color(clrMenuItemSelectableFg);
@@ -1248,13 +1691,28 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
ColorBg = Theme.Color(clrBackground);
}
}
- const cFont *font = cFont::GetFont(fontOsd);
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!Current && Index == nOldIndex) {
+ for (int i = 0; i < MaxTabs; i++) {
+ if (idListItem[i] >= 0) {
+ EnigmaTextEffects.ResetText(idListItem[i], ColorFg, ColorBg);
+ idListItem[i] = -1;
+ }
+ }
+ } else if (Current) {
+ nOldIndex = Index;
+ }
+#endif
+
// this should prevent menu flickering
- osd->DrawRectangle(xItemLeft, y + lineHeightOsd / 2, xItemLeft + 1, y + lineHeightOsd / 2 + 1, Theme.Color(clrBackground));
+ osd->DrawRectangle(xItemLeft, y + lineHeight / 2, xItemLeft + 1, y + lineHeight / 2 + 1, ColorBg);
+ osd->DrawRectangle(xItemRight - 2, y + lineHeight / 2, xItemRight - 1, y + lineHeight / 2 + 1, ColorBg);
+
if (EnigmaConfig.showMarker) {
- osd->DrawRectangle(xBodyLeft, y, xItemLeft - 1, y + lineHeightOsd - 1, ColorBg);
- osd->DrawEllipse(xBodyLeft + MarkerGap, y + MarkerGap, xBodyLeft + lineHeightOsd - MarkerGap, y + lineHeightOsd - MarkerGap, Current ? ColorFg : ColorBg);
- osd->DrawRectangle(xItemRight, y, (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - 1, y + lineHeightOsd - 1, ColorBg);
+ osd->DrawRectangle(xBodyLeft, y, xItemLeft - 1, y + lineHeight - 1, ColorBg);
+ osd->DrawEllipse(xBodyLeft + MarkerGap, y + MarkerGap, xBodyLeft + lineHeight - MarkerGap, y + lineHeight - MarkerGap, Current ? ColorFg : ColorBg);
+ osd->DrawRectangle(xItemRight, y, (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - 1, y + lineHeight - 1, ColorBg);
}
// draw item
for (int i = 0; i < MaxTabs; i++) {
@@ -1318,33 +1776,33 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
int evx = xt + Gap;
const char *p = s;
// draw background
- osd->DrawRectangle(xt, y, xItemRight, y + lineHeightOsd - 1, ColorBg);
+ osd->DrawRectangle(xt, y, xItemRight, y + lineHeight - 1, ColorBg);
// draw symbols
for (; *p; ++p) {
switch (*p) {
case 't':
// partial timer event
- osd->DrawBitmap(evx, y + (lineHeightOsd - bmEventPartTimer.Height()) / 2, bmEventPartTimer, ColorFg, ColorBg);
+ osd->DrawBitmap(evx, y + (lineHeight - bmEventPartTimer.Height()) / 2, bmEventPartTimer, ColorFg, ColorBg);
evx += bmEventPartTimer.Width();
break;
case 'T':
// timer event
- osd->DrawBitmap(evx, y + (lineHeightOsd - bmEventTimer.Height()) / 2, bmEventTimer, ColorFg, ColorBg);
+ osd->DrawBitmap(evx, y + (lineHeight - bmEventTimer.Height()) / 2, bmEventTimer, ColorFg, ColorBg);
evx += bmEventTimer.Width();
break;
case 'R':
// recording event (epgsearch)
- osd->DrawBitmap(evx, y + (lineHeightOsd - bmEventRecording.Height()) / 2, bmEventRecording, ColorFg, ColorBg);
+ osd->DrawBitmap(evx, y + (lineHeight - bmEventRecording.Height()) / 2, bmEventRecording, ColorFg, ColorBg);
evx += bmEventRecording.Width();
break;
case 'V':
// vps event
- osd->DrawBitmap(evx, y + (lineHeightOsd - bmEventVPS.Height()) / 2, bmEventVPS, ColorFg, ColorBg);
+ osd->DrawBitmap(evx, y + (lineHeight - bmEventVPS.Height()) / 2, bmEventVPS, ColorFg, ColorBg);
evx += bmEventVPS.Width();
break;
case '*':
// running event
- osd->DrawBitmap(evx, y + (lineHeightOsd - bmEventRunning.Height()) / 2, bmEventRunning, ColorFg, ColorBg);
+ osd->DrawBitmap(evx, y + (lineHeight - bmEventRunning.Height()) / 2, bmEventRunning, ColorFg, ColorBg);
evx += bmEventRunning.Width();
break;
case ' ':
@@ -1355,9 +1813,9 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
}
} else if (isnewrecording) {
// draw text
- osd->DrawText(xt, y, buffer, ColorFg, ColorBg, font, xItemRight - xt);
+ osd->DrawText(xt, y, buffer, ColorFg, ColorBg, pFontList, xItemRight - xt);
// draw symbol
- osd->DrawBitmap(xt + font->Width(buffer), y + (lineHeightOsd - bmRecordingNew.Height()) / 2, bmRecordingNew, ColorFg, ColorBg);
+ osd->DrawBitmap(xt + pFontList->Width(buffer), y + (lineHeight - bmRecordingNew.Height()) / 2, bmRecordingNew, ColorFg, ColorBg);
} else if (isprogressbar) {
// define x coordinates of progressbar
int px0 = xt;
@@ -1365,17 +1823,29 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
int px = px0 + max((int)((float) now * (float) (px1 - px0) / (float) total), ListProgressBarBorder);
// define y coordinates of progressbar
int py0 = y + ListProgressBarGap;
- int py1 = y + lineHeightOsd - ListProgressBarGap;
+ int py1 = y + lineHeight - ListProgressBarGap;
// draw background
- osd->DrawRectangle(px0, y, px1, y + lineHeightOsd - 1, ColorBg);
+ osd->DrawRectangle(px0, y, /*TODO? px1 */ xItemRight - 1, y + lineHeight - 1, ColorBg);
// draw progressbar
osd->DrawRectangle(px0, py0, px, py1, ColorFg);
osd->DrawRectangle(px + 1, py0, px1, py0 + ListProgressBarBorder, ColorFg);
osd->DrawRectangle(px + 1, py1 - ListProgressBarBorder, px1, py1, ColorFg);
osd->DrawRectangle(px1 - ListProgressBarBorder, py0, px1, py1, ColorFg);
} else {
+ int w = (Tab(i + 1) && HasTabbedText(Text, i + 1) ? (xItemLeft + Tab(i + 1)) : xItemRight) - xt;
+ //TODO? int w = xItemRight - xt;
// draw text
- osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xItemRight - xt, nMessagesShown ? min(yMessageTop - y, lineHeightOsd) : 0 );
+ if (Current) {
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollListItem) {
+// if (i > 0)
+//TODO? EnigmaTextEffects.UpdateTextWidth(idListItem[i - 1], Tab(i) - Tab(i - 1));
+ idListItem[i] = TE_MARQUEE(osd, idListItem[i], xt, y, s, ColorFg, ColorBg, pFontList, w, nMessagesShown ? min(yMessageTop - y, lineHeight) : 0 );
+ } else
+#endif
+ osd->DrawText(xt, y, s, ColorFg, ColorBg, pFontList, w, nMessagesShown ? min(yMessageTop - y, lineHeight) : 0 );
+ } else
+ osd->DrawText(xt, y, s, ColorFg, ColorBg, pFontList, w, nMessagesShown ? min(yMessageTop - y, lineHeight) : 0 );
}
}
if (!Tab(i + 1))
@@ -1417,10 +1887,6 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/stop");
else if (strcmp(ItemText, tr(" Cancel editing")) == 0)
fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/cancel");
-/*TODO: obsolete?
- else if (strcmp(ItemText, tr("Summary")) == 0)
- fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/summary");
-*/
else if (strcmp(ItemText2, GetPluginMainMenuName("audiorecorder")) == 0)
fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/audiorecorder");
else if (strcmp(ItemText2, GetPluginMainMenuName("burn")) == 0)
@@ -1494,7 +1960,8 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
else if (strcmp(ItemText2, GetPluginMainMenuName("vdrc")) == 0)
fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdrc");
else if (strcmp(ItemText2, GetPluginMainMenuName("vdrcd")) == 0
- || strcmp(ItemText2, GetPluginMainMenuName("mediad")) == 0)
+ || strcmp(ItemText2, GetPluginMainMenuName("mediad")) == 0
+ || strcmp(ItemText2, GetPluginMainMenuName("mediamanager")) == 0)
fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdrcd");
else if (strcmp(ItemText2, GetPluginMainMenuName("vdrrip")) == 0)
fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdrrip");
@@ -1517,6 +1984,10 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current,
}
}
#endif
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
const char *cSkinEnigmaDisplayMenu::GetPluginMainMenuName(const char *plugin)
@@ -1532,11 +2003,13 @@ const char *cSkinEnigmaDisplayMenu::GetPluginMainMenuName(const char *plugin)
int cSkinEnigmaDisplayMenu::DrawFlag(int x, int y, const tComponent *p)
{
+ //Must be TE_LOCKed by caller
+
if (p == NULL)
return 0;
if ((p->stream == 2) && p->language) {
- string flag("flags/");
+ std::string flag("flags/");
flag += p->language;
/*TODO
if (p->description) {
@@ -1558,21 +2031,17 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
if (!Event)
return;
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
isMainMenu = false;
fShowInfo = false;
-#ifdef SKINENIGMA_NO_MENULOGO
- fShowLogo = false;
-#else
- fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3);
-#endif
-
- const cFont *font = cFont::GetFont(fontOsd);
- const cFont *smlfont = cFont::GetFont(fontSml);
- int wsb = lineHeightOsd + 2 * SmallGap; //scrollbar width
+ fShowLogo = fShowLogoDefault ? EnigmaConfig.showImages : false;
+ SetupAreas();
time_t now = time(NULL);
// draw recording date string
- stringstream sstrDate;
+ std::stringstream sstrDate;
sstrDate << *Event->GetDateString()
<< " " << *Event->GetTimeString()
<< " - " << *Event->GetEndTimeString()
@@ -1581,7 +2050,7 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
sstrDate << (now - Event->StartTime()) / 60 << '/';
sstrDate << Event->Duration() / 60 << tr("min") << ")";
- int y = yDateBottom + (smlfont->Height() - bmVPS.Height()) / 2;
+ int y = yDateBottom + (pFontDetailsDate->Height() - bmVPS.Height()) / 2;
int xs = xDateRight - Gap;
// check if event has VPS
if (EnigmaConfig.showVps && Event->Vps()) {
@@ -1591,10 +2060,10 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
struct tm tm_r;
time_t t_vps = Event->Vps();
strftime(vps, sizeof(vps), "%H:%M", localtime_r(&t_vps, &tm_r));
- xs -= smlfont->Width(vps);
+ xs -= pFontDetailsDate->Width(vps);
osd->DrawText(xs, yDateBottom, vps,
Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground),
- smlfont, smlfont->Width(vps), smlfont->Height());
+ pFontDetailsDate, pFontDetailsDate->Width(vps), pFontDetailsDate->Height());
xs -= TinyGap;
}
xs -= bmVPS.Width();
@@ -1606,23 +2075,25 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
// draw running symbol
xs -= (bmRun.Width() + Gap);
osd->DrawBitmap(xs, y, bmRun, Theme.Color(clrSymbolRunActive), Theme.Color(clrBackground));
+ xs -= Gap;
}
// check if event has timer
if (Event->HasTimer()) {
if (Event->IsRunning()) {
// draw recording symbol
- xs -= (bmRecording.Width() + Gap);
+ xs -= bmRecording.Width();
osd->DrawBitmap(xs, y, bmRecording, Theme.Color(clrSymbolRecActive), Theme.Color(clrBackground));
} else {
// draw timer symbol
- xs -= (bmTimer.Width() + Gap);
+ xs -= bmTimer.Width();
osd->DrawBitmap(xs, y, bmTimer, Theme.Color(clrSymbolTimerActive), Theme.Color(clrBackground));
}
+ xs -= Gap;
}
- string stringInfo;
+ std::string stringInfo;
const cComponents *Components = Event->Components();
if (Components) {
- stringstream sstrInfo;
+ std::stringstream sstrInfo;
for (int i = 0; i < Components->NumComponents(); i++) {
const tComponent *p = Components->Component(i);
if (p && (p->stream == 2) && p->language) {
@@ -1643,17 +2114,26 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
}
int yHeadlineBottom = yDateBottom;
int xHeadlineRight = fShowLogo ? xDateLeft : xInfoRight;
- // draw recording title
osd->DrawRectangle(xBodyLeft, yBodyTop, xHeadlineRight - 1,
yHeadlineBottom - 1, Theme.Color(clrAltBackground));
- int th = font->Height() + (Event->Description() && Event->ShortText() ? Gap + smlfont->Height() : 0);
+ int th = pFontDetailsTitle->Height() + (!isempty(Event->Description()) && !isempty(Event->ShortText()) ? Gap + pFontDetailsSubtitle->Height() : 0);
y = yBodyTop + (yHeadlineBottom - yBodyTop - th) / 2;
- osd->DrawText(xBodyLeft + Gap, y, Event->Title(),
- Theme.Color(clrMenuEventTitle), Theme.Color(clrAltBackground),
- font, xHeadlineRight - xBodyLeft - Gap - 1, font->Height());
+
+ // draw recording title
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollOther)
+ TE_MARQUEE(osd, -1, xBodyLeft + Gap, y, Event->Title(),
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontDetailsTitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsTitle->Height());
+ else
+#endif
+ osd->DrawText(xBodyLeft + Gap, y, Event->Title(),
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontDetailsTitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsTitle->Height());
+
osd->DrawText(xBodyLeft + Gap, yHeadlineBottom, sstrDate.str().c_str(),
Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground),
- smlfont, xDateLeft - xBodyLeft - Gap - 1, smlfont->Height());
+ pFontDetailsDate, xs - xBodyLeft - Gap - 1, pFontDetailsDate->Height());
// draw recording short text and description
const char *strDescr = NULL;
@@ -1667,23 +2147,31 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
// check if short text
if (!isempty(Event->ShortText())) {
// draw below Event->Title
- y += lineHeightOsd + Gap;
+ y += pFontDetailsTitle->Height() + Gap;
+
// draw short text
- osd->DrawText(xBodyLeft + Gap, y, Event->ShortText(),
- Theme.Color(clrMenuEventShortText), Theme.Color(clrAltBackground),
- smlfont, xHeadlineRight - xBodyLeft - Gap - 1, lineHeightSml);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollOther)
+ TE_MARQUEE(osd, -1, xBodyLeft + Gap, y, Event->ShortText(),
+ Theme.Color(clrMenuItemNotSelectableFg), Theme.Color(clrAltBackground),
+ pFontDetailsSubtitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsSubtitle->Height());
+ else
+#endif
+ osd->DrawText(xBodyLeft + Gap, y, Event->ShortText(),
+ Theme.Color(clrMenuItemNotSelectableFg), Theme.Color(clrAltBackground),
+ pFontDetailsSubtitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsSubtitle->Height());
}
// draw description
strDescr = Event->Description();
}
- string stringReruns;
+ std::string stringReruns;
#ifdef SKINENIGMA_HAVE_EPGSEARCH
// try to find a rerun of the show using epgsearch-service
if (EnigmaConfig.numReruns > 0 && !isempty(Event->Title())) {
- stringstream sstrReruns;
+ std::stringstream sstrReruns;
Epgsearch_searchresults_v1_0 data;
- string strQuery = Event->Title();
+ std::string strQuery = Event->Title();
if (EnigmaConfig.useSubtitleRerun > 0) {
if (EnigmaConfig.useSubtitleRerun == 2 || !isempty(Event->ShortText()))
strQuery += "~";
@@ -1702,7 +2190,7 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>* list = data.pResultList;
if (list && (list->Count() > 1)) {
//TODO: current event is shown as rerun
- sstrReruns << tr("RERUNS OF THIS SHOW") << ':' << endl;
+ sstrReruns << tr("RERUNS OF THIS SHOW") << ':' << std::endl;
int i = 0;
for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r && i < EnigmaConfig.numReruns; r = list->Next(r)) {
i++;
@@ -1712,7 +2200,7 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
<< ": " << r->event->Title();
if (!isempty(r->event->ShortText()))
sstrReruns << "~" << r->event->ShortText();
- sstrReruns << endl;
+ sstrReruns << std::endl;
}
delete list;
}
@@ -1732,15 +2220,16 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
strSecond = strDescr;
}
if (strFirst || strSecond || strSecond) {
- y = yHeadlineBottom + SmallGap + 2 * smlfont->Height();
+ y = yHeadlineBottom + SmallGap + 2 * pFontDetailsDate->Height();
char *mytext;
asprintf(&mytext, "%s%s%s%s%s", strFirst ? strFirst : "",
strSecond ? "\n\n" : "", strSecond ? strSecond : "",
(strFirst || strSecond) && strThird ? "\n\n" : "", strThird ? strThird : "");
textScroller.Set(osd, xBodyLeft + Gap, y,
- xInfoRight - xBodyLeft - wsb - Gap, yBodyBottom - Gap - y,
- mytext, font, Theme.Color(clrMenuTxtFg),
- Theme.Color(clrBackground));
+ xInfoRight - SmallGap - ScrollbarWidth - SmallGap - Gap - xBodyLeft,
+ yBodyBottom - y,
+ mytext, pFontDetailsText,
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground));
SetScrollbar();
free(mytext);
}
@@ -1749,11 +2238,7 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
if (fShowLogo) {
// draw logo
osd->DrawRectangle(xDateLeft + SmallGap, yDateTop, xDateRight - 1, yDateBottom - SmallGap - 1, Theme.Color(clrLogoBg));
- if (EnigmaConfig.showImages && EnigmaLogoCache.LoadEventImage(Event, xLogoRight - xLogoLeft, yLogoBottom - yLogoTop, nNumImageColors)) {
- osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2,
- yDateTop + (yDateBottom - yDateTop - EnigmaLogoCache.Get().Height()) / 2,
- EnigmaLogoCache.Get(), 0, 0, true);
- } else {
+ if (!(EnigmaConfig.showImages && EnigmaLogoCache.DrawEventImage(Event, xLogoLeft, yLogoTop, xLogoRight - xLogoLeft, yLogoBottom - yLogoTop, nNumImageColors, osd->GetBitmap(2) ? osd->GetBitmap(2) : osd->GetBitmap(0)))) {
if (EnigmaLogoCache.LoadIcon("icons/menu/schedule"))
osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2,
yLogoTop + (yLogoBottom - yLogoTop - EnigmaLogoCache.Get().Height()) / 2,
@@ -1764,6 +2249,9 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event)
osd->DrawRectangle(xDateLeft, yLogoBottom - SmallGap, xDateRight, yLogoBottom - 1, clrTransparent);
}
#endif
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
int cSkinEnigmaDisplayMenu::ReadSizeVdr(const char *strPath)
@@ -1794,31 +2282,27 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording)
if (!Recording)
return;
- isMainMenu = false;
- fShowInfo = false;
-#ifdef SKINENIGMA_NO_MENULOGO
- fShowLogo = false;
-#else
- fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3);
-#endif
-
const cRecordingInfo *Info = Recording->Info();
- const cFont *font = cFont::GetFont(fontOsd);
- const cFont *smlfont = cFont::GetFont(fontSml);
- int wsb = lineHeightOsd + 2 * SmallGap; //scrollbar width
-
if (Info == NULL) {
//TODO: draw error message
return;
}
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
+ isMainMenu = false;
+ fShowInfo = false;
+ fShowLogo = fShowLogoDefault ? EnigmaConfig.showImages : false;;
+ SetupAreas();
+
// draw recording date string
- stringstream sstrDate;
+ std::stringstream sstrDate;
sstrDate << *DateString(Recording->start)
<< " " << *TimeString(Recording->start);
// draw additional information
- stringstream sstrInfo;
+ std::stringstream sstrInfo;
int dirSize = -1;
if (EnigmaConfig.showRecSize > 0) {
if ((dirSize = ReadSizeVdr(Recording->FileName())) < 0 && EnigmaConfig.showRecSize == 2) {
@@ -1827,19 +2311,20 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording)
}
cChannel *channel = Channels.GetByChannelID(((cRecordingInfo *)Info)->ChannelID());
if (channel)
- sstrInfo << tr("Channel") << ": " << channel->Number() << " - " << channel->Name() << endl;
+ sstrInfo << tr("Channel") << ": " << channel->Number() << " - " << channel->Name() << std::endl;
if (dirSize >= 0)
- sstrInfo << tr("Size") << ": " << setprecision(3) << (dirSize > 1023 ? dirSize / 1024.0 : dirSize) << (dirSize > 1023 ? "GB\n" : "MB\n");
- sstrInfo << tr("Priority") << ": " << Recording->priority << endl
- << tr("Lifetime") << ": " << Recording->lifetime << endl;
+ sstrInfo << tr("Size") << ": " << std::setprecision(3) << (dirSize > 1023 ? dirSize / 1024.0 : dirSize) << (dirSize > 1023 ? "GB\n" : "MB\n");
+ sstrInfo << tr("Priority") << ": " << Recording->priority << std::endl
+ << tr("Lifetime") << ": " << Recording->lifetime << std::endl;
if (Info->Aux()) {
- sstrInfo << endl << tr("Auxiliary information") << ":\n"
+ sstrInfo << std::endl << tr("Auxiliary information") << ":\n"
<< parseaux(Info->Aux());
}
+ int xs = xDateRight - Gap;
const cComponents *Components = Info->Components();
if (Components) {
//TODO: show flaggs?
- stringstream info;
+ std::stringstream info;
for (int i = 0; i < Components->NumComponents(); i++) {
const tComponent *p = Components->Component(i);
if ((p->stream == 2) && p->language) {
@@ -1860,19 +2345,28 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording)
int yHeadlineBottom = yDateBottom;
int xHeadlineRight = fShowLogo ? xDateLeft : xInfoRight;
- // draw recording title
const char *Title = Info->Title();
if (isempty(Title))
Title = Recording->Name();
osd->DrawRectangle(xBodyLeft, yBodyTop, xHeadlineRight - 1, yHeadlineBottom - 1, Theme.Color(clrAltBackground));
- int th = font->Height() + (Info->Description() && Info->ShortText() ? Gap + smlfont->Height() : 0);
+ int th = pFontDetailsTitle->Height() + (!isempty(Info->Description()) && !isempty(Info->ShortText()) ? Gap + pFontDetailsSubtitle->Height() : 0);
int y = yBodyTop + (yHeadlineBottom - yBodyTop - th) / 2;
- osd->DrawText(xBodyLeft + Gap, y, Title,
- Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
- font, xHeadlineRight - xBodyLeft - Gap - 1, font->Height());
+
+ // draw recording title
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollOther)
+ TE_MARQUEE(osd, -1, xBodyLeft + Gap, y, Title,
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontDetailsTitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsTitle->Height());
+ else
+#endif
+ osd->DrawText(xBodyLeft + Gap, y, Title,
+ Theme.Color(clrMenuTxtFg), Theme.Color(clrAltBackground),
+ pFontDetailsTitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsTitle->Height());
+
osd->DrawText(xBodyLeft + Gap, yHeadlineBottom, sstrDate.str().c_str(),
Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground),
- smlfont, xHeadlineRight - xBodyLeft - Gap - 1, smlfont->Height());
+ pFontDetailsDate, xs - xBodyLeft - Gap - 1, pFontDetailsDate->Height());
// draw recording short text and description
const char* strDescr = NULL;
if (isempty(Info->Description())) {
@@ -1885,28 +2379,36 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording)
// check if short text
if (!isempty(Info->ShortText())) {
// draw below Title
- y += lineHeightOsd + Gap;
+ y += pFontDetailsTitle->Height() + Gap;
+
// draw short text
- osd->DrawText(xBodyLeft + Gap, y, Info->ShortText(),
- Theme.Color(clrMenuEventShortText), Theme.Color(clrAltBackground),
- smlfont, xHeadlineRight - xBodyLeft - Gap - 1, lineHeightSml);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollOther)
+ TE_MARQUEE(osd, -1, xBodyLeft + Gap, y, Info->ShortText(),
+ Theme.Color(clrMenuItemNotSelectableFg), Theme.Color(clrAltBackground),
+ pFontDetailsSubtitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsSubtitle->Height());
+ else
+#endif
+ osd->DrawText(xBodyLeft + Gap, y, Info->ShortText(),
+ Theme.Color(clrMenuItemNotSelectableFg), Theme.Color(clrAltBackground),
+ pFontDetailsSubtitle, xHeadlineRight - xBodyLeft - Gap - 1, pFontDetailsSubtitle->Height());
}
// draw description
strDescr = Info->Description();
}
- string stringInfo = sstrInfo.str();
+ std::string stringInfo = sstrInfo.str();
const char *strInfo = stringInfo.empty() ? NULL : stringInfo.c_str();
if (strDescr || strInfo) {
- y = yHeadlineBottom + 2 * smlfont->Height();
+ y = yHeadlineBottom + pFontDetailsDate->Height() + BigGap;
char *mytext;
if (EnigmaConfig.showAuxInfo)
asprintf(&mytext, "%s%s%s", strDescr ? strDescr : "", strInfo && strDescr ? "\n\n" : "", strInfo ? strInfo : "");
else
asprintf(&mytext, "%s%s%s", strInfo ? strInfo : "", strInfo && strDescr ? "\n\n" : "", strDescr ? strDescr : "");
textScroller.Set(osd, xBodyLeft + Gap, y,
- xInfoRight - xBodyLeft - Gap - wsb,
- yBodyBottom - Gap - y, mytext, font,
+ xInfoRight - SmallGap - ScrollbarWidth - SmallGap - Gap - xBodyLeft,
+ yBodyBottom - y, mytext, pFontDetailsText,
Theme.Color(clrMenuTxtFg),
Theme.Color(clrBackground));
SetScrollbar();
@@ -1916,11 +2418,7 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording)
#ifndef SKINENIGMA_NO_MENULOGO
if (fShowLogo) {
osd->DrawRectangle(xDateLeft + SmallGap, yDateTop, xDateRight - 1, yDateBottom - SmallGap - 1, Theme.Color(clrLogoBg));
- if (EnigmaConfig.showImages && EnigmaLogoCache.LoadRecordingImage(Recording, xLogoRight - xLogoLeft, yLogoBottom - yLogoTop, nNumImageColors)) {
- osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2,
- yDateTop + (yDateBottom - yDateTop - EnigmaLogoCache.Get().Height()) / 2,
- EnigmaLogoCache.Get(), 0, 0, true);
- } else {
+ if (!(EnigmaConfig.showImages && EnigmaLogoCache.DrawRecordingImage(Recording, xLogoLeft, yLogoTop, xLogoRight - xLogoLeft, yLogoBottom - yLogoTop, nNumImageColors, osd->GetBitmap(2) ? osd->GetBitmap(2) : osd->GetBitmap(0)))) {
// draw logo
if (EnigmaLogoCache.LoadIcon("icons/menu/recordings"))
osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2,
@@ -1932,36 +2430,47 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording)
osd->DrawRectangle(xDateLeft, yLogoBottom - SmallGap, xDateRight, yLogoBottom - 1, clrTransparent);
}
#endif
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayMenu::SetText(const char *Text, bool FixedFont)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
// draw text
textScroller.Set(osd, xBodyLeft + Gap, yBodyTop + Gap,
GetTextAreaWidth(),
- yBodyBottom - yBodyTop - 2 * Gap, Text,
+ yBodyBottom - Gap - yBodyTop - Gap, Text,
GetTextAreaFont(FixedFont),
Theme.Color(clrMenuTxtFg), Theme.Color(clrBackground));
SetScrollbar();
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
int cSkinEnigmaDisplayMenu::GetTextAreaWidth(void) const
{
- int wsb = lineHeightOsd + 2 * SmallGap; //scrollbar width
-
// max text area width
- return (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - 2 * Gap - wsb;
+ return (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - Gap - SmallGap - ScrollbarWidth - SmallGap;
}
const cFont *cSkinEnigmaDisplayMenu::GetTextAreaFont(bool FixedFont) const
{
// text area font
- return cFont::GetFont(FixedFont ? fontFix : fontOsd);
+ return FixedFont ? pFontFixed : pFontDetailsText;
}
void cSkinEnigmaDisplayMenu::Flush(void)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
//debug("cSkinEnigmaDisplayMenu::Flush\n");
+
if (fShowLogo) {
time_t t = time(NULL);
cString time = TimeString(t);
@@ -1971,8 +2480,7 @@ void cSkinEnigmaDisplayMenu::Flush(void)
int x = xDateLeft + SmallGap;
int w = xLogoLeft - x;
- const cFont *font = cFont::GetFont(fontOsd);
- int ys = yDateTop + (yDateBottom - yDateTop - 3 * lineHeightOsd) / 2;
+ int ys = yDateTop + (yDateBottom - yDateTop - 3 * pFontDate->Height()) / 2;
char temp[32];
struct tm tm_r;
@@ -1980,45 +2488,49 @@ void cSkinEnigmaDisplayMenu::Flush(void)
strftime(temp, sizeof(temp), "%A", tm);
osd->DrawText(x, ys, temp, Theme.Color(clrMenuTxtFg),
- Theme.Color(clrLogoBg), font, w,
- lineHeightOsd, taCenter);
- ys += lineHeightOsd;
+ Theme.Color(clrLogoBg), pFontDate, w,
+ pFontDate->Height(), taCenter);
+ ys += pFontDate->Height();
strftime(temp, sizeof(temp), "%d.%m.%Y", tm);
osd->DrawText(x, ys, temp, Theme.Color(clrMenuTxtFg),
- Theme.Color(clrLogoBg), font, w,
- lineHeightOsd, taCenter);
- ys += lineHeightOsd;
+ Theme.Color(clrLogoBg), pFontDate, w,
+ pFontDate->Height(), taCenter);
+ ys += pFontDate->Height();
osd->DrawText(x, ys, time, Theme.Color(clrMenuTxtFg),
- Theme.Color(clrLogoBg), font, w,
- lineHeightOsd, taCenter);
- //draw borders
- osd->DrawRectangle(xDateLeft, yDateTop, xDateLeft + SmallGap - 1, yLogoBottom - SmallGap - 1, clrTransparent);
- osd->DrawRectangle(xDateLeft, yLogoBottom - SmallGap, xDateRight, yLogoBottom - 1, clrTransparent);
+ Theme.Color(clrLogoBg), pFontDate, w,
+ pFontDate->Height(), taCenter);
}
} else {
cString date = DayDateTime();
if ((strLastDate == NULL) || strcmp(strLastDate, (const char*)date) != 0) {
free(strLastDate);
strLastDate = strdup((const char*)date);
- const cFont *font = cFont::GetFont(fontOsd);
osd->DrawText(xDateLeft + SmallGap, yDateTop, date, Theme.Color(clrMenuTxtFg),
- Theme.Color(clrLogoBg), font, xDateRight - xDateLeft - SmallGap,
+ Theme.Color(clrLogoBg), pFontDate, xDateRight - xDateLeft - SmallGap,
yTitleDecoBottom - yDateTop, taCenter);
- //draw borders
- osd->DrawRectangle(xDateLeft, yDateTop, xDateLeft + SmallGap - 1, yTitleDecoBottom - 1, clrTransparent);
- osd->DrawRectangle(xDateLeft, yTitleDecoBottom, xDateRight, yBodyTop - 1, clrTransparent);
}
}
osd->Flush();
+#ifndef DISABLE_ANIMATED_TEXT
+ TE_UNLOCK;
+ if (fLocked) {
+ fLocked = false;
+ TE_WAKEUP;
+ }
+#endif
}
// --- cSkinEnigmaDisplayReplay ---------------------------------------------
-class cSkinEnigmaDisplayReplay:public cSkinDisplayReplay {
+class cSkinEnigmaDisplayReplay : public cSkinDisplayReplay, public cSkinEnigmaOsd {
private:
cOsd *osd;
+ const cFont *pFontOsdTitle;
+ const cFont *pFontReplayTimes;
+ const cFont *pFontDate;
+ const cFont *pFontMessage;
int xTitleLeft, xTitleRight, yTitleTop, yTitleBottom, yTitleDecoTop, yTitleDecoBottom;
int xLogoLeft, xLogoRight, yLogoTop, yLogoBottom;
@@ -2027,9 +2539,17 @@ private:
int xBottomLeft, xBottomRight, yBottomTop, yBottomBottom;
int xMessageLeft, xMessageRight, yMessageTop, yMessageBottom;
- int lineHeight;
+ char *strLastDate;
bool modeonly;
int nJumpWidth;
+ int nCurrentWidth;
+ bool fShowSymbol;
+#ifndef DISABLE_ANIMATED_TEXT
+ bool fLocked;
+ bool fScrollTitle;
+ int idTitle;
+#endif
+
public:
cSkinEnigmaDisplayReplay(bool ModeOnly);
virtual ~ cSkinEnigmaDisplayReplay();
@@ -2041,20 +2561,38 @@ public:
virtual void SetJump(const char *Jump);
virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
+ virtual void DrawTitle(const char *s);
};
cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly)
{
+ struct EnigmaOsdSize OsdSize;
+ EnigmaConfig.GetOsdSize(&OsdSize);
+
+ pFontOsdTitle = EnigmaConfig.GetFont(FONT_OSDTITLE);
+ pFontReplayTimes = EnigmaConfig.GetFont(FONT_REPLAYTIMES);
+ pFontDate = EnigmaConfig.GetFont(FONT_DATE);
+ pFontMessage = EnigmaConfig.GetFont(FONT_MESSAGE);
+
+ strLastDate = NULL;
+
+ int MessageHeight = 2 * SmallGap + pFontMessage->Height() + 2 * SmallGap;
+
modeonly = ModeOnly;
nJumpWidth = 0;
- lineHeight = cFont::GetFont(fontOsd)->Height();
+ nCurrentWidth = 0;
+ fShowSymbol = EnigmaConfig.showSymbols && EnigmaConfig.showSymbolsReplay;
+#ifndef DISABLE_ANIMATED_TEXT
+ fScrollTitle = !modeonly && EnigmaConfig.useTextEffects && EnigmaConfig.scrollTitle;
+ idTitle = -1;
+#endif
- int LogoSize = IconHeight;
+ int LogoSize = Gap + IconHeight + Gap;
LogoSize += (LogoSize % 2 ? 1 : 0);
xTitleLeft = 0;
- xTitleRight = Setup.OSDWidth;
+ xTitleRight = OsdSize.w;
yTitleTop = 0;
- yTitleBottom = yTitleTop + lineHeight;
+ yTitleBottom = yTitleTop + pFontOsdTitle->Height();
yTitleDecoTop = yTitleBottom + TitleDecoGap;
yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight;
xLogoLeft = xTitleLeft;
@@ -2064,7 +2602,7 @@ cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly)
xTimeLeft = xLogoRight + LogoDecoGap2;
xTimeRight = xTitleRight;
xTimeLeft += (xTimeRight - xTimeLeft) - ((xTimeRight - xTimeLeft) & ~0x07);
- yTimeTop = yLogoBottom - SmallGap - lineHeight - SmallGap;
+ yTimeTop = yLogoBottom - SmallGap - pFontReplayTimes->Height() - SmallGap;
yTimeBottom = yLogoBottom;
xProgressLeft = xTimeLeft;
xProgressRight = xTitleRight;
@@ -2073,18 +2611,20 @@ cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly)
xBottomLeft = xTitleLeft;
xBottomRight = xTitleRight;
yBottomTop = yLogoBottom + SmallGap;
- yBottomBottom = yBottomTop + lineHeight;
+ yBottomBottom = yBottomTop + pFontDate->Height();
xMessageLeft = xProgressLeft;
xMessageRight = xProgressRight;
yMessageTop = yLogoTop + (LogoSize - MessageHeight) / 2;
yMessageBottom = yMessageTop + MessageHeight;
// create osd
- osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - yBottomBottom);
- tArea Areas[] = { {xTitleLeft, yTitleTop, xBottomRight - 1, yBottomBottom - 1, EnigmaConfig.singleArea8Bpp ? 8 : 4} };
- if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ osd = cOsdProvider::NewOsd(OsdSize.x, OsdSize.y + OsdSize.h - yBottomBottom);
+ tArea Areas[] = { {xTitleLeft, yTitleTop, xBottomRight - 1, yBottomBottom - 1, fShowSymbol ? 8 : 4} };
+ if ((Areas[0].bpp < 8 || EnigmaConfig.singleArea8Bpp) && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ debug("cSkinEnigmaDisplayReplay: using %dbpp single area\n", Areas[0].bpp);
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} else {
+ debug("cSkinEnigmaDisplayReplay: using multiple areas\n");
tArea Areas[] = { {xTitleLeft, yTitleTop, xTitleRight - 1, yTitleDecoBottom - 1, 2},
{xLogoLeft, yLogoTop, xLogoRight + 1, yLogoBottom - 1, 4}, //TODO? "+1" because of wrong colors with "-1"
{xProgressLeft, yProgressTop, xTimeRight - 1, yTimeBottom - 1, 4},
@@ -2105,7 +2645,7 @@ cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly)
osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent);
if (modeonly) {
// draw logo area
- osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2) ? Theme.Color(clrLogoBg) : clrTransparent);
+ osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, fShowSymbol ? Theme.Color(clrLogoBg) : clrTransparent);
} else {
// draw title area
osd->DrawRectangle(xTitleLeft, yTitleTop, xTitleRight - 1,
@@ -2132,15 +2672,46 @@ cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly)
osd->DrawEllipse(xBottomRight - Roundness, yBottomBottom - Roundness,
xBottomRight - 1, yBottomBottom - 1, clrTransparent, -4);
}
+
+#ifndef DISABLE_ANIMATED_TEXT
+ fLocked = false;
+ if (fScrollTitle) {
+ TE_START(osd);
+ fLocked = true;
+ }
+#endif
}
cSkinEnigmaDisplayReplay::~cSkinEnigmaDisplayReplay()
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (fScrollTitle) {
+ if (!fLocked) TE_LOCK;
+ TE_STOP;
+ }
+#endif
+ free(strLastDate);
delete osd;
}
void cSkinEnigmaDisplayReplay::SetTitle(const char *Title)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+ if (fScrollTitle) {
+ idTitle = TE_TITLE(osd, idTitle, Title, pFontOsdTitle, xTitleRight - Roundness - xTitleLeft - Roundness, this);
+ } else
+#endif
+ DrawTitle(Title);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
+}
+
+void cSkinEnigmaDisplayReplay::DrawTitle(const char *Title)
+{
+ //Must be TE_LOCKed by caller
+
// draw title area
osd->DrawRectangle(xTitleLeft, yTitleTop, xTitleRight - 1,
yTitleBottom - 1, Theme.Color(clrTitleBg));
@@ -2156,37 +2727,44 @@ void cSkinEnigmaDisplayReplay::SetTitle(const char *Title)
// draw titlebar
osd->DrawText(xTitleLeft + Roundness + 3, yTitleTop + 3, Title,
Theme.Color(clrTitleShadow), clrTransparent,
- cFont::GetFont(fontOsd),
+ pFontOsdTitle,
xTitleRight - Roundness - xTitleLeft - Roundness - 3,
yTitleBottom - yTitleTop - 3);
osd->DrawText(xTitleLeft + Roundness, yTitleTop, Title,
Theme.Color(clrTitleFg), clrTransparent,
- cFont::GetFont(fontOsd),
- xTitleRight - Roundness - xTitleLeft - Roundness,
+ pFontOsdTitle,
+ xTitleRight - Roundness - xTitleLeft - Roundness - 3,
yTitleBottom - yTitleTop);
}
}
void cSkinEnigmaDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
+
bool fFoundLogo = false;
if (Speed < -1)
Speed = -1;
- if ((!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2)) {
+ if (modeonly) {
+ osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, clrTransparent);
+ osd->DrawEllipse(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg));
+ } else {
osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg));
+ }
+ if (fShowSymbol) {
char *logo = NULL;
asprintf(&logo, "icons/menu/%s", EnigmaStatus.ReplayModeName());
if (EnigmaLogoCache.LoadIcon(logo)) {
osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2,
yLogoTop + (yLogoBottom - yLogoTop - EnigmaLogoCache.Get().Height()) / 2,
EnigmaLogoCache.Get(), EnigmaLogoCache.Get().Color(1),
- Theme.Color(clrLogoBg), true);
+ clrTransparent, true, true);
}
free(logo);
- } else {
- osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg));
}
if (Speed == -1)
@@ -2208,11 +2786,17 @@ void cSkinEnigmaDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2,
yLogoTop + (yLogoBottom - yLogoTop - EnigmaLogoCache.Get().Height()) / 2,
EnigmaLogoCache.Get(), EnigmaLogoCache.Get().Color(1),
- Theme.Color(clrLogoBg), false, true);
+ clrTransparent, false, true);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayReplay::SetProgress(int Current, int Total)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
// create progressbar
cProgressBar pb(xProgressRight - xProgressLeft - 2 * BigGap,
yProgressBottom - yProgressTop - 2 * BigGap, Current, Total,
@@ -2223,6 +2807,9 @@ void cSkinEnigmaDisplayReplay::SetProgress(int Current, int Total)
Theme.Color(clrReplayProgressCurrent));
// draw progressbar
osd->DrawBitmap(xProgressLeft + BigGap, yProgressTop + BigGap, pb);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayReplay::SetCurrent(const char *Current)
@@ -2231,11 +2818,19 @@ void cSkinEnigmaDisplayReplay::SetCurrent(const char *Current)
return;
// draw current time
- const cFont *font = cFont::GetFont(fontOsd);
- int w = font->Width(Current);
+ int w = pFontReplayTimes->Width(Current);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
osd->DrawText(xTimeLeft + BigGap, yTimeTop, Current,
- Theme.Color(clrReplayCurrent), Theme.Color(clrAltBackground), font,
+ Theme.Color(clrReplayCurrent), Theme.Color(clrAltBackground), pFontReplayTimes,
w, yTimeBottom - yTimeTop, taLeft);
+ if (nCurrentWidth > w)
+ osd->DrawRectangle(xTimeLeft + BigGap + w, yTimeTop, xTimeLeft + BigGap + nCurrentWidth - 1, yTimeBottom - 1, Theme.Color(clrAltBackground));
+ nCurrentWidth = w;
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayReplay::SetTotal(const char *Total)
@@ -2244,22 +2839,29 @@ void cSkinEnigmaDisplayReplay::SetTotal(const char *Total)
return;
// draw total time
- const cFont *font = cFont::GetFont(fontOsd);
- int w = font->Width(Total);
+ int w = pFontReplayTimes->Width(Total);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
osd->DrawText(xTimeRight - BigGap - w, yTimeTop, Total,
- Theme.Color(clrReplayTotal), Theme.Color(clrAltBackground), font, w,
+ Theme.Color(clrReplayTotal), Theme.Color(clrAltBackground), pFontReplayTimes, w,
yTimeBottom - yTimeTop, taRight);
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayReplay::SetJump(const char *Jump)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
if (Jump) {
// draw jump prompt
- const cFont *font = cFont::GetFont(fontOsd);
- nJumpWidth = font->Width(Jump);
+ nJumpWidth = pFontReplayTimes->Width(Jump);
osd->DrawText(xTimeLeft + (xTimeRight - xTimeLeft - nJumpWidth) / 2,
yTimeTop, Jump, Theme.Color(clrReplayModeJump),
- Theme.Color(clrAltBackground), font, nJumpWidth,
+ Theme.Color(clrAltBackground), pFontReplayTimes, nJumpWidth,
yTimeBottom - yTimeTop, taLeft);
} else {
// erase old prompt
@@ -2268,10 +2870,16 @@ void cSkinEnigmaDisplayReplay::SetJump(const char *Jump)
xTimeLeft + (xTimeRight - xTimeLeft - nJumpWidth) / 2 +
nJumpWidth - 1, yTimeBottom - 1, Theme.Color(clrAltBackground));
}
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayReplay::SetMessage(eMessageType Type, const char *Text)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
if (Text) {
// save current osd
osd->SaveRegion(xMessageLeft, yMessageTop, xMessageRight, yMessageBottom);
@@ -2280,46 +2888,65 @@ void cSkinEnigmaDisplayReplay::SetMessage(eMessageType Type, const char *Text)
yMessageBottom - 1, clrTransparent);
osd->DrawRectangle(xMessageLeft, yMessageTop + SmallGap, xMessageRight - 1,
yMessageBottom - SmallGap - 1,
- Theme.Color(clrMessageBorder));
- osd->DrawText(xMessageLeft + Gap, yMessageTop + 2 * SmallGap, Text,
+ Theme.Color(clrButtonRedBg));
+ osd->DrawText(xMessageLeft, yMessageTop + 2 * SmallGap, Text,
Theme.Color(clrMessageStatusFg + 2 * Type),
Theme.Color(clrMessageStatusBg + 2 * Type),
- cFont::GetFont(fontOsd),
- xMessageRight - Gap - xMessageLeft - Gap - 1,
+ pFontMessage,
+ xMessageRight - xMessageLeft,
yMessageBottom - 2 * SmallGap - yMessageTop - 2 * SmallGap,
taCenter);
} else {
// restore saved osd
osd->RestoreRegion();
}
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayReplay::Flush(void)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
// update date
if (!modeonly) {
cString date = DayDateTime();
- osd->DrawText(xBottomLeft + Roundness, yBottomTop, date,
- Theme.Color(clrTitleFg), Theme.Color(clrBottomBg),
- cFont::GetFont(fontOsd),
- xBottomRight - Roundness - xBottomLeft - Roundness - 1,
- yBottomBottom - yBottomTop - 1, taRight);
+ if ((strLastDate == NULL) || strcmp(strLastDate, (const char*)date) != 0) {
+ free(strLastDate);
+ strLastDate = strdup((const char*)date);
+ osd->DrawText(xBottomLeft + Roundness, yBottomTop, date,
+ Theme.Color(clrTitleFg), Theme.Color(clrBottomBg),
+ pFontDate,
+ xBottomRight - Roundness - xBottomLeft - Roundness - 1,
+ yBottomBottom - yBottomTop - 1, taRight);
+ }
}
osd->Flush();
+#ifndef DISABLE_ANIMATED_TEXT
+ TE_UNLOCK;
+ if (fLocked) {
+ fLocked = false;
+ TE_WAKEUP;
+ }
+#endif
}
// --- cSkinEnigmaDisplayVolume ---------------------------------------------
-class cSkinEnigmaDisplayVolume:public cSkinDisplayVolume {
+class cSkinEnigmaDisplayVolume : public cSkinDisplayVolume {
private:
cOsd *osd;
+ const cFont *pFontOsdTitle;
+ const cFont *pFontDate;
int xTitleLeft, xTitleRight, yTitleTop, yTitleBottom, yTitleDecoTop, yTitleDecoBottom;
int xLogoLeft, xLogoRight, yLogoTop, yLogoBottom, xLogoDecoLeft, xLogoDecoRight;
int xBodyLeft, xBodyRight, yBodyTop, yBodyBottom;
int xBottomLeft, xBottomRight, yBottomTop, yBottomBottom;
- int lineHeight;
+ time_t lastTime;
bool fShowSymbol;
public:
@@ -2331,10 +2958,19 @@ public:
cSkinEnigmaDisplayVolume::cSkinEnigmaDisplayVolume()
{
- fShowSymbol = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2);
- lineHeight = cFont::GetFont(fontOsd)->Height();
+ struct EnigmaOsdSize OsdSize;
+ EnigmaConfig.GetOsdSize(&OsdSize);
+
+ pFontOsdTitle = EnigmaConfig.GetFont(FONT_OSDTITLE);
+ pFontDate = EnigmaConfig.GetFont(FONT_DATE);
- int LogoSize = max(3 * lineHeight + TitleDeco + SmallGap, IconHeight);
+ lastTime = 0;
+ fShowSymbol = EnigmaConfig.showSymbols && EnigmaConfig.showSymbolsAudio;
+
+ int LogoSize = max(pFontOsdTitle->Height() +
+ cFont::GetFont(fontOsd)->Height() +
+ pFontDate->Height() +
+ TitleDeco + SmallGap, IconHeight);
LogoSize += (LogoSize % 2 ? 1 : 0);
xLogoLeft = 0;
xLogoRight = LogoSize;
@@ -2343,14 +2979,14 @@ cSkinEnigmaDisplayVolume::cSkinEnigmaDisplayVolume()
yLogoTop = 0;
yLogoBottom = yLogoTop + LogoSize;
xTitleLeft = fShowSymbol ? (xLogoDecoRight + LogoDecoGap2) : 0;
- xTitleRight = Setup.OSDWidth;
+ xTitleRight = OsdSize.w;
yTitleTop = yLogoTop;
- yTitleBottom = yTitleTop + lineHeight;
+ yTitleBottom = yTitleTop + pFontOsdTitle->Height();
yTitleDecoTop = yTitleBottom + TitleDecoGap;
yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight;
xBottomLeft = xTitleLeft;
- xBottomRight = Setup.OSDWidth;
- yBottomTop = yLogoBottom - lineHeight;
+ xBottomRight = OsdSize.w;
+ yBottomTop = yLogoBottom - pFontDate->Height();
yBottomBottom = yLogoBottom;
xBodyLeft = xTitleLeft;
xBodyRight = xTitleRight;
@@ -2358,11 +2994,13 @@ cSkinEnigmaDisplayVolume::cSkinEnigmaDisplayVolume()
yBodyBottom = yBottomTop - SmallGap;
// create osd
- osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - yBottomBottom);
- tArea Areas[] = { {xLogoLeft, yLogoTop, xTitleRight - 1, yBottomBottom - 1, EnigmaConfig.singleArea8Bpp ? 8 : 4} };
- if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ osd = cOsdProvider::NewOsd(OsdSize.x, OsdSize.y + OsdSize.h - yBottomBottom);
+ tArea Areas[] = { {xLogoLeft, yLogoTop, xTitleRight - 1, yBottomBottom - 1, fShowSymbol ? 8 : 4} };
+ if ((Areas[0].bpp < 8 || EnigmaConfig.singleArea8Bpp) && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ debug("cSkinEnigmaDisplayVolume: using %dbpp single area\n", Areas[0].bpp);
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} else {
+ debug("cSkinEnigmaDisplayVolume: using multiple areas\n");
cBitmap *bitmap = NULL;
if (fShowSymbol) {
tArea Areas[] = { {xLogoLeft, yLogoTop, xLogoRight + LogoDecoGap + LogoDecoWidth - 1, yLogoBottom - 1, 4},
@@ -2439,7 +3077,6 @@ void cSkinEnigmaDisplayVolume::SetVolume(int Current, int Total, bool Mute)
{
tColor ColorBar;
const char *Prompt;
- const cFont *font = cFont::GetFont(fontOsd);
bool fFoundLogo = false;
// select behaviour
@@ -2466,11 +3103,11 @@ void cSkinEnigmaDisplayVolume::SetVolume(int Current, int Total, bool Mute)
osd->DrawRectangle(xTitleLeft + (fShowSymbol ? Gap : Roundness), yTitleTop, xTitleRight - Roundness - 1,
yTitleBottom - 1, Theme.Color(clrTitleBg));
osd->DrawText(xTitleLeft + (fShowSymbol ? Gap : Roundness) + 3, yTitleTop + 3, Prompt,
- Theme.Color(clrTitleShadow), clrTransparent, font,
- xTitleRight - Roundness - xTitleLeft, lineHeight, taCenter);
+ Theme.Color(clrTitleShadow), clrTransparent, pFontOsdTitle,
+ xTitleRight - Roundness - xTitleLeft, pFontOsdTitle->Height(), taCenter);
osd->DrawText(xTitleLeft + (fShowSymbol ? Gap : Roundness), yTitleTop, Prompt,
- Theme.Color(clrTitleFg), clrTransparent, font,
- xTitleRight - Roundness - xTitleLeft, lineHeight, taCenter);
+ Theme.Color(clrTitleFg), clrTransparent, pFontOsdTitle,
+ xTitleRight - Roundness - xTitleLeft, pFontOsdTitle->Height(), taCenter);
// draw volumebar
osd->DrawRectangle(xBodyLeft + Gap, yBodyTop + Gap, xBodyRight - Gap - 1,
yBodyBottom - Gap - 1, Theme.Color(clrBackground));
@@ -2480,19 +3117,26 @@ void cSkinEnigmaDisplayVolume::SetVolume(int Current, int Total, bool Mute)
void cSkinEnigmaDisplayVolume::Flush(void)
{
- cString date = DayDateTime();
- osd->DrawText(xBottomLeft + (fShowSymbol ? 0 : Roundness), yBottomTop, date, Theme.Color(clrTitleFg),
- Theme.Color(clrBottomBg), cFont::GetFont(fontOsd),
- xBottomRight - (fShowSymbol ? Gap : (2 * Roundness)) - xBottomLeft - 1,
- yBottomBottom - yBottomTop - 1, taRight);
+ time_t now = time(NULL);
+ if (now != lastTime) {
+ lastTime = now;
+ cString date = DayDateTime();
+ osd->DrawText(xBottomLeft + (fShowSymbol ? 0 : Roundness), yBottomTop, date, Theme.Color(clrTitleFg),
+ Theme.Color(clrBottomBg), pFontDate,
+ xBottomRight - (fShowSymbol ? Gap : (2 * Roundness)) - xBottomLeft - 1,
+ yBottomBottom - yBottomTop - 1, taRight);
+ }
osd->Flush();
}
// --- cSkinEnigmaDisplayTracks ---------------------------------------------
-class cSkinEnigmaDisplayTracks:public cSkinDisplayTracks {
+class cSkinEnigmaDisplayTracks : public cSkinDisplayTracks {
private:
cOsd *osd;
+ const cFont *pFontOsdTitle;
+ const cFont *pFontDate;
+ const cFont *pFontListItem;
int xTitleLeft, xTitleRight, yTitleTop, yTitleBottom, yTitleDecoTop, yTitleDecoBottom;
int xLogoLeft, xLogoRight, yLogoTop, yLogoBottom;
@@ -2502,6 +3146,7 @@ private:
int lineHeight;
int currentIndex;
bool fShowSymbol;
+ time_t lastTime;
void SetItem(const char *Text, int Index, bool Current);
public:
@@ -2515,26 +3160,33 @@ public:
cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTracks, const char *const *Tracks)
{
- fShowSymbol = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2);
+ struct EnigmaOsdSize OsdSize;
+ EnigmaConfig.GetOsdSize(&OsdSize);
+
+ pFontOsdTitle = EnigmaConfig.GetFont(FONT_OSDTITLE);
+ pFontDate = EnigmaConfig.GetFont(FONT_DATE);
+ pFontListItem = EnigmaConfig.GetFont(FONT_LISTITEM);
- const cFont *font = cFont::GetFont(fontOsd);
- lineHeight = font->Height();
+ lastTime = 0;
+ fShowSymbol = EnigmaConfig.showSymbols && EnigmaConfig.showSymbolsAudio;
+
+ lineHeight = pFontListItem->Height();
int LogoSize = IconHeight;
LogoSize += (LogoSize % 2 ? 1 : 0);
currentIndex = -1;
int ItemsWidth = 0;
for (int i = 0; i < NumTracks; i++)
- ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
+ ItemsWidth = max(ItemsWidth, pFontListItem->Width(Tracks[i]));
ItemsWidth += (EnigmaConfig.showMarker ? lineHeight : SmallGap) + SmallGap;
ItemsWidth = max(ItemsWidth, LogoSize);
int width = ItemsWidth;
if (fShowSymbol)
width += LogoSize + LogoDecoGap2;
- width = max(width, font->Width(DayDateTime()) + 2 * Roundness);
- width = max(width, font->Width(Title) + 2 * Roundness + (fShowSymbol ? 0 : (bmAudio[0].Width() + SmallGap)));
+ width = max(width, pFontDate->Width(DayDateTime()) + 2 * Roundness);
+ width = max(width, pFontOsdTitle->Width(Title) + 2 * Roundness + (fShowSymbol ? 0 : (bmAudio[0].Width() + SmallGap)));
xTitleLeft = 0;
- xTitleRight = Setup.OSDWidth;
+ xTitleRight = OsdSize.w;
int d = xTitleRight - xTitleLeft;
if (d > width) {
d = (d - width) & ~0x07; // must be multiple of 8
@@ -2542,13 +3194,13 @@ cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTra
}
yTitleTop = 0;
- yTitleBottom = lineHeight;
+ yTitleBottom = pFontOsdTitle->Height();
yTitleDecoTop = yTitleBottom + TitleDecoGap;
yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight;
xLogoLeft = xTitleLeft;
xLogoRight = xLogoLeft + LogoSize;
yLogoTop = yTitleDecoBottom + TitleDecoGap2;
- yLogoBottom = yLogoTop + LogoSize;
+ yLogoBottom = yLogoTop + max(LogoSize, NumTracks * lineHeight);
xListLeft = fShowSymbol ? (xLogoRight + LogoDecoGap2) : 0;
xListRight = xTitleRight;
yListTop = yLogoTop;
@@ -2556,18 +3208,20 @@ cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTra
xBottomLeft = xTitleLeft;
xBottomRight = xTitleRight;
yBottomTop = yListBottom + SmallGap;
- yBottomBottom = yBottomTop + lineHeight;
+ yBottomBottom = yBottomTop + pFontDate->Height();
// create osd
- osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - yBottomBottom);
- tArea Areas[] = { {xTitleLeft, yTitleTop, xBottomRight - 1, yBottomBottom - 1, EnigmaConfig.singleArea8Bpp ? 8 : 4} };
- if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ osd = cOsdProvider::NewOsd(OsdSize.x, OsdSize.y + OsdSize.h - yBottomBottom);
+ tArea Areas[] = { {xTitleLeft, yTitleTop, xBottomRight - 1, yBottomBottom - 1, fShowSymbol ? 8 : 4} };
+ if ((Areas[0].bpp < 8 || EnigmaConfig.singleArea8Bpp) && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ debug("cSkinEnigmaDisplayTracks: using %dbpp single area\n", Areas[0].bpp);
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} else {
+ debug("cSkinEnigmaDisplayTracks: using multiple areas\n");
if (fShowSymbol) {
tArea Areas[] = { {xTitleLeft, yTitleTop, xTitleRight - 1, yTitleDecoBottom- 1, 2},
{xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, 4},
- {xListLeft, yListTop, xListRight - 1, yListBottom - 1, 4},
+ {xListLeft, yListTop, xListRight - 1, yListBottom - 1, 2},
{xBottomLeft, yBottomTop, xBottomRight - 1, yBottomBottom - 1, 2}
};
int rc = osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea));
@@ -2582,7 +3236,7 @@ cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTra
}
} else {
tArea Areas[] = { {xTitleLeft, yTitleTop, xTitleRight - 1, yTitleDecoBottom- 1, 2},
- {xListLeft, yListTop, xListRight - 1, yListBottom - 1, 4},
+ {xListLeft, yListTop, xListRight - 1, yListBottom - 1, 2},
{xBottomLeft, yBottomTop, xBottomRight - 1, yBottomBottom - 1, 2}
};
int rc = osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea));
@@ -2603,12 +3257,14 @@ cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTra
osd->DrawRectangle(xTitleLeft, yTitleTop, xTitleRight - 1, yTitleBottom - 1, Theme.Color(clrTitleBg));
osd->DrawRectangle(xTitleLeft, yTitleDecoTop, xTitleRight - 1, yTitleDecoBottom - 1, Theme.Color(clrTitleBg));
osd->DrawText(xTitleLeft + Roundness + 3, yTitleTop + 3, Title,
- Theme.Color(clrTitleShadow), clrTransparent, font,
+ Theme.Color(clrTitleShadow), clrTransparent,
+ pFontOsdTitle,
xTitleRight - Roundness - xTitleLeft - Roundness,
- lineHeight - 3, fShowSymbol ? taCenter : taLeft);
+ yTitleBottom - yTitleTop - 3, fShowSymbol ? taCenter : taLeft);
osd->DrawText(xTitleLeft + Roundness, yTitleTop, Title,
- Theme.Color(clrTitleFg), clrTransparent, font,
- xTitleRight - Roundness - xTitleLeft - Roundness, lineHeight,
+ Theme.Color(clrTitleFg), clrTransparent,
+ pFontOsdTitle,
+ xTitleRight - Roundness - xTitleLeft - Roundness, yTitleBottom - yTitleTop,
fShowSymbol ? taCenter : taLeft);
// draw rounded left corner of titlebar
osd->DrawEllipse(xTitleLeft, yTitleTop, xTitleLeft + Roundness - 1,
@@ -2642,12 +3298,11 @@ cSkinEnigmaDisplayTracks::~cSkinEnigmaDisplayTracks()
void cSkinEnigmaDisplayTracks::SetItem(const char *Text, int Index, bool Current)
{
int xItemLeft = xListLeft + (EnigmaConfig.showMarker ? lineHeight : SmallGap);
- const cFont *font = cFont::GetFont(fontOsd);
int y = yListTop + Index * lineHeight;
tColor ColorFg, ColorBg;
if (Current) {
- ColorFg = Theme.Color(clrMenuItemCurrentFg);
- ColorBg = Theme.Color(clrMenuHighlight);
+ ColorFg = Theme.Color(clrMenuItemSelectableFg);
+ ColorBg = Theme.Color(clrAltBackground);
currentIndex = Index;
} else {
ColorFg = Theme.Color(clrMenuItemSelectableFg);
@@ -2661,7 +3316,7 @@ void cSkinEnigmaDisplayTracks::SetItem(const char *Text, int Index, bool Current
y + lineHeight - MarkerGap,
Current ? ColorFg : ColorBg);
}
- osd->DrawText(xItemLeft, y, Text, ColorFg, ColorBg, font, xListRight - xItemLeft - SmallGap, lineHeight);
+ osd->DrawText(xItemLeft, y, Text, ColorFg, ColorBg, pFontListItem, xListRight - xItemLeft - SmallGap, lineHeight);
}
void cSkinEnigmaDisplayTracks::SetAudioChannel(int AudioChannel)
@@ -2695,28 +3350,37 @@ void cSkinEnigmaDisplayTracks::SetTrack(int Index, const char *const *Tracks)
void cSkinEnigmaDisplayTracks::Flush(void)
{
- cString date = DayDateTime();
- osd->DrawText(xBottomLeft + Roundness, yBottomTop, date,
- Theme.Color(clrTitleFg), Theme.Color(clrBottomBg),
- cFont::GetFont(fontOsd),
- xBottomRight - Roundness - xBottomLeft - Roundness - 1,
- yBottomBottom - yBottomTop - 1, taRight);
+ time_t now = time(NULL);
+ if (now != lastTime) {
+ lastTime = now;
+ cString date = DayDateTime();
+ osd->DrawText(xBottomLeft + Roundness, yBottomTop, date,
+ Theme.Color(clrTitleFg), Theme.Color(clrBottomBg),
+ pFontDate,
+ xBottomRight - Roundness - xBottomLeft - Roundness - 1,
+ yBottomBottom - yBottomTop - 1, taRight);
+ }
osd->Flush();
}
// --- cSkinEnigmaDisplayMessage --------------------------------------------
-class cSkinEnigmaDisplayMessage:public cSkinDisplayMessage {
+class cSkinEnigmaDisplayMessage : public cSkinDisplayMessage {
private:
cOsd *osd;
+ const cFont *pFontMessage;
int xTitleLeft, xTitleRight, yTitleTop, yTitleBottom, yTitleDecoTop, yTitleDecoBottom;
int xLogoLeft, xLogoRight, yLogoTop, yLogoBottom, xLogoDecoLeft, xLogoDecoRight;
int xMessageLeft, xMessageRight, yMessageTop, yMessageBottom;
int xBottomLeft, xBottomRight, yBottomTop, yBottomBottom;
- int lineHeight;
bool fShowSymbol;
+#ifndef DISABLE_ANIMATED_TEXT
+ int idMessage;
+ bool fLocked;
+#endif
+
public:
cSkinEnigmaDisplayMessage();
virtual ~ cSkinEnigmaDisplayMessage();
@@ -2726,10 +3390,24 @@ public:
cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage()
{
- lineHeight = cFont::GetFont(fontOsd)->Height();
- fShowSymbol = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2);
+ struct EnigmaOsdSize OsdSize;
+ EnigmaConfig.GetOsdSize(&OsdSize);
+
+ const cFont *pFontOsdTitle;
+ const cFont *pFontDate;
+ pFontMessage = EnigmaConfig.GetFont(FONT_MESSAGE);
+ pFontOsdTitle = EnigmaConfig.GetFont(FONT_OSDTITLE);
+ pFontDate = EnigmaConfig.GetFont(FONT_DATE);
- int LogoSize = max(3 * lineHeight + TitleDeco + 5 * SmallGap, IconHeight);
+#ifndef DISABLE_ANIMATED_TEXT
+ idMessage = -1;
+#endif
+ fShowSymbol = EnigmaConfig.showSymbols && EnigmaConfig.showSymbolsMsgs;
+
+ int LogoSize = max(pFontOsdTitle->Height() + TitleDeco +
+ pFontMessage->Height() +
+ 5 * SmallGap +
+ pFontDate->Height(), IconHeight);
LogoSize += (LogoSize % 2 ? 1 : 0);
xLogoLeft = 0;
@@ -2739,14 +3417,14 @@ cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage()
yLogoTop = 0;
yLogoBottom = yLogoTop + LogoSize;
xTitleLeft = fShowSymbol ? xLogoDecoRight + LogoDecoGap2 : 0;
- xTitleRight = Setup.OSDWidth;
+ xTitleRight = OsdSize.w;
yTitleTop = yLogoTop;
- yTitleBottom = yTitleTop + lineHeight;
+ yTitleBottom = yTitleTop + pFontOsdTitle->Height();
yTitleDecoTop = yTitleBottom + TitleDecoGap;
yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight;
xBottomLeft = xTitleLeft;
xBottomRight = xTitleRight;
- yBottomTop = yLogoBottom - lineHeight;
+ yBottomTop = yLogoBottom - pFontDate->Height();
yBottomBottom = yLogoBottom;
xMessageLeft = xTitleLeft;
xMessageRight = xTitleRight;
@@ -2754,11 +3432,13 @@ cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage()
yMessageBottom = yBottomTop - SmallGap;
// create osd
- osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - yBottomBottom);
- tArea Areas[] = { {xLogoLeft, yLogoTop, xBottomRight - 1, yBottomBottom - 1, EnigmaConfig.singleArea8Bpp ? 8 : 4} };
- if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ osd = cOsdProvider::NewOsd(OsdSize.x, OsdSize.y + OsdSize.h - yBottomBottom);
+ tArea Areas[] = { {xLogoLeft, yLogoTop, xBottomRight - 1, yBottomBottom - 1, fShowSymbol ? 8 : 4} };
+ if ((Areas[0].bpp < 8 || EnigmaConfig.singleArea8Bpp) && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) {
+ debug("cSkinEnigmaDisplayMessage: using %dbpp single area\n", Areas[0].bpp);
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} else {
+ debug("cSkinEnigmaDisplayMessage: using multiple areas\n");
if (fShowSymbol) {
tArea Areas[] = { {xLogoLeft, yLogoTop, xLogoRight + LogoDecoGap + LogoDecoWidth - 1, yLogoBottom - 1, 4},
{xTitleLeft, yTitleTop, xBottomRight - 1, yBottomBottom - 1, 4} };
@@ -2788,15 +3468,36 @@ cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage()
}
// clear all
osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent);
+
+#ifndef DISABLE_ANIMATED_TEXT
+ fLocked = false;
+ if (EnigmaConfig.useTextEffects && EnigmaConfig.scrollOther) {
+ TE_START(osd);
+ fLocked = true;
+ }
+#endif
}
cSkinEnigmaDisplayMessage::~cSkinEnigmaDisplayMessage()
{
+ debug("cSkinEnigmaDisplayMessage::~cSkinEnigmaDisplayMessage\n");
+
+#ifndef DISABLE_ANIMATED_TEXT
+ if (EnigmaConfig.useTextEffects && EnigmaConfig.scrollOther) {
+ if (!fLocked) TE_LOCK;
+ TE_STOP;
+ }
+#endif
delete osd;
}
void cSkinEnigmaDisplayMessage::SetMessage(eMessageType Type, const char *Text)
{
+ debug("cSkinEnigmaDisplayMessage::SetMessage\n");
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked && EnigmaConfig.useTextEffects && EnigmaConfig.scrollOther)
+ TE_LOCK;
+#endif
if (fShowSymbol) {
// draw logo
osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg));
@@ -2813,13 +3514,23 @@ void cSkinEnigmaDisplayMessage::SetMessage(eMessageType Type, const char *Text)
// draw centered message text
osd->DrawRectangle(xMessageLeft, yMessageTop, xMessageRight - 1, yMessageBottom - 1, clrTransparent);
osd->DrawRectangle(xMessageLeft, yMessageTop, xMessageRight - 1,
- yMessageBottom - 1, Theme.Color(clrMessageBorder));
- osd->DrawText(xMessageLeft, yMessageTop + 2 * SmallGap, Text,
- Theme.Color(clrMessageStatusFg + 2 * Type),
- Theme.Color(clrMessageStatusBg + 2 * Type),
- cFont::GetFont(fontOsd),
- xMessageRight - xMessageLeft,
- yMessageBottom - 2 * SmallGap - yMessageTop - 2 * SmallGap, taCenter);
+ yMessageBottom - 1, Theme.Color(clrButtonRedBg));
+#ifndef DISABLE_ANIMATED_TEXT
+ if (EnigmaConfig.useTextEffects && EnigmaConfig.scrollOther)
+ idMessage = TE_MARQUEE(osd, idMessage, xMessageLeft, yMessageTop + 2 * SmallGap, Text,
+ Theme.Color(clrMessageStatusFg + 2 * Type),
+ Theme.Color(clrMessageStatusBg + 2 * Type),
+ pFontMessage,
+ xMessageRight - xMessageLeft,
+ yMessageBottom - 2 * SmallGap - yMessageTop - 2 * SmallGap, taCenter);
+ else
+#endif
+ osd->DrawText(xMessageLeft, yMessageTop + SmallGap, Text,
+ Theme.Color(clrMessageStatusFg + 2 * Type),
+ Theme.Color(clrMessageStatusBg + 2 * Type),
+ pFontMessage,
+ xMessageRight - xMessageLeft - 1,
+ yMessageBottom - SmallGap - yMessageTop - SmallGap - 1, taCenter);
// draw bottom
osd->DrawRectangle(xBottomLeft, yBottomTop, xBottomRight - 1, yBottomBottom - 1, Theme.Color(clrBottomBg));
osd->DrawEllipse(xBottomRight - Roundness, yBottomBottom - Roundness,
@@ -2831,11 +3542,25 @@ void cSkinEnigmaDisplayMessage::SetMessage(eMessageType Type, const char *Text)
osd->DrawEllipse(xBottomLeft, yBottomBottom - Roundness,
xBottomLeft + Roundness - 1, yBottomBottom - 1, clrTransparent, -3);
}
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked && EnigmaConfig.useTextEffects && EnigmaConfig.scrollOther)
+ TE_UNLOCK;
+#endif
}
void cSkinEnigmaDisplayMessage::Flush(void)
{
+#ifndef DISABLE_ANIMATED_TEXT
+ if (!fLocked) TE_LOCK;
+#endif
osd->Flush();
+#ifndef DISABLE_ANIMATED_TEXT
+ TE_UNLOCK;
+ if (fLocked) {
+ fLocked = false;
+ TE_WAKEUP;
+ }
+#endif
}
// --- cSkinEnigma ----------------------------------------------------------
diff --git a/enigma.h b/enigma.h
index 76b28e3..7bf4356 100644
--- a/enigma.h
+++ b/enigma.h
@@ -1,17 +1,19 @@
/*
- * enigma.h: The 'EnigmaNG' VDR skin
+ * enigma.h: 'EnigmaNG' skin for the Video Disk Recorder
*
*/
#ifndef __ENIGMA_H
#define __ENIGMA_H
+#include "common.h"
+
#include <vdr/skins.h>
#include <vdr/skinclassic.h>
class cSkinEnigma : public cSkin {
private:
- cSkin *skinFallback;
+ cSkin *skinFallback;
public:
cSkinEnigma();
@@ -22,6 +24,19 @@ public:
virtual cSkinDisplayVolume *DisplayVolume(void);
virtual cSkinDisplayTracks *DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
virtual cSkinDisplayMessage *DisplayMessage(void);
- };
+};
+
+
+// common interface
+class cSkinEnigmaOsd {
+friend class cEnigmaTextEffects;
+
+public:
+ virtual ~cSkinEnigmaOsd(void)
+ {};
+ virtual void DrawTitle(const char *Title) = 0;
+};
#endif //__ENIGMA_H
+
+// vim:et:sw=2:ts=2:
diff --git a/font.c b/font.c
new file mode 100644
index 0000000..f8ef9ee
--- /dev/null
+++ b/font.c
@@ -0,0 +1,220 @@
+/*
+ * font.c: 'EnigmaNG' skin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * Taken from GraphTFT
+ */
+
+#include "common.h"
+#include "font.h"
+#include <iconv.h>
+#include <stdio.h>
+
+cGraphtftFont::cGraphtftFont()
+{
+ _library = 0;
+ _face = 0;
+
+ // init freetype2 lib
+ int error = FT_Init_FreeType(&_library);
+ if (error)
+ {
+ error("ERROR: Could not init freetype library");
+ }
+}
+
+cGraphtftFont::~cGraphtftFont()
+{
+ Clear();
+
+ if (_face)
+ {
+ FT_Done_Face(_face);
+ }
+
+ if (_library)
+ {
+ FT_Done_FreeType(_library);
+ }
+}
+
+bool cGraphtftFont::Load(string Filename, string CacheName, int Size, int Language, int Width, int format)
+{
+ if ( _cache.find(CacheName) != _cache.end() )
+ return true;
+
+ int error = FT_New_Face(_library, Filename.c_str(), format, &_face);
+
+ // every thing ok?
+ if (error == FT_Err_Unknown_File_Format)
+ {
+ error("ERROR: Font file (%s) could be opened and read, but it appears that its font format is unsupported", Filename.c_str());
+ return false;
+ }
+ else if (error)
+ {
+ error("ERROR: Font file (%s) could be opened or read, or simply it is broken", Filename.c_str());
+ return false;
+ }
+
+ // set slot
+ _slot = _face->glyph;
+
+ if (Width > 0)
+ Width = Size * Width / 100;
+
+ // set Size
+ FT_Set_Char_Size
+ (
+ _face, // handle to face object
+ Width*64, // char_width in 1/64th of points
+ Size*64, // char_height in 1/64th of points
+ 0, // horizontal device resolution (dpi)
+ 0 // vertical device resolution (dpi)
+ );
+
+ iconv_t cd;
+ char from_code[255];
+ wchar_t utf_buff[256];
+
+ // XXX: Get this values from i18n
+ switch(Language) {
+ case 11:
+ strcpy(from_code,"ISO8859-7");
+ break;
+ case 13:
+ case 17:
+ strcpy(from_code,"ISO8859-2");
+ break;
+ case 16:
+ strcpy(from_code,"ISO8859-5");
+ break;
+ default :
+ strcpy(from_code,"ISO8859-15");
+ break;
+ }
+
+ if ((cd = iconv_open("WCHAR_T",from_code)) == (iconv_t)-1) {
+ esyslog("ERROR: Iconv encoding not supported: %m");
+ return false; //encoding no supportet
+ }
+
+ for (int c = 0; c < 256; c++) {
+
+ char char_buff = c;
+ wchar_t wchar_buff;
+
+ char *in_buff,*out_buff;
+ size_t in_len, out_len, count;
+
+ in_len=1; out_len=4;
+ in_buff=(char*)&char_buff;
+ out_buff=(char *)&wchar_buff;
+ count = iconv(cd,&in_buff,&in_len,&out_buff,&out_len);
+ if ( (size_t)-1 == count ){
+ //printf("ERROR - PREPARING TABLE CHAR %d \n", c);
+ utf_buff[c] = 0;
+ }
+ utf_buff[c] = wchar_buff;
+ }
+ iconv_close(cd);
+
+ cFont::tPixelData value;
+ int num_rows_global = (_face->size->metrics.height / 64 )+1;
+ int num_rows = num_rows_global + 2;
+
+ cFont::tPixelData * font_data = new cFont::tPixelData[225 * num_rows];
+
+ for (int i = 0; i < 225; i++)
+ for (int j = 0; j < num_rows; j++)
+ font_data[(i*num_rows)+j]=0x0000000000000000;
+
+ // Time to put char 32..255 in font_data
+ FT_UInt glyph_index;
+ for ( int num_char = 32, num_char_array = 0; num_char < 256; num_char++, num_char_array++ )
+ {
+
+ //Get FT char index
+ glyph_index = FT_Get_Char_Index( _face, utf_buff[num_char] );
+
+ //Load the char
+ error = FT_Load_Glyph( _face, glyph_index, FT_LOAD_DEFAULT );
+ if ( error ) continue; /* ignore errors */
+
+ // now, convert to vdr font data
+ int width = (_slot->metrics.horiAdvance / 64) + 1;
+ int bearingX = (_slot->metrics.horiBearingX / 64) +1;
+ width = (width > (int)sizeof(cFont::tPixelData) * 8) ? (((int)sizeof(cFont::tPixelData) * 8)-2) :width ;
+
+ font_data[(num_char_array*num_rows)+0]=width;
+ font_data[(num_char_array*num_rows)+1]=num_rows_global;
+
+ // convert to a mono bitmap
+ error = FT_Render_Glyph( _face->glyph, ft_render_mode_mono );
+ if ( error ) continue;
+
+ int top = _slot->bitmap_top;
+ int y_off = Size - top;
+
+ unsigned char *bmp = _slot->bitmap.buffer;
+
+ for (int y = 0; y < _slot->bitmap.rows; ++y , y_off++) {
+ int pos = 0;
+ int bit = 0x80;
+ value = 0x00;
+
+ for (int x = 0; x < _slot->bitmap.width; ++x) {
+ if (bmp[pos] & bit && x < width + 1 )
+ value = value | (cFont::tPixelData)1 << width - bearingX - x ;
+
+ bit >>= 1;
+ if (bit == 0) {
+ bit = 0x80;
+ ++pos;
+ }
+ }
+ bmp += _slot->bitmap.pitch;
+ font_data[(num_char_array*num_rows)+y_off+2] = value;
+ }
+
+ }
+ // If all was ok, put the vdr font into the cache and return true
+ cFont* newFont = NULL;
+ newFont = new cFont(font_data);
+ if (newFont) {
+ _cache[CacheName] = newFont;
+ _del[CacheName] = font_data;
+ return true;
+ }
+ delete(font_data);
+ // Something went wrong!
+ return false;
+}
+
+const cFont* cGraphtftFont::GetFont(string CacheName){
+ if (CacheName == "Sml") return cFont::GetFont(fontSml);
+ else if (CacheName == "Fix") return cFont::GetFont(fontFix);
+ else if ( _cache.find(CacheName) != _cache.end() ){
+ return _cache[CacheName];
+ }
+ return cFont::GetFont(fontOsd);
+}
+
+void cGraphtftFont::Clear(string CacheName)
+{
+ Clear();
+}
+
+void cGraphtftFont::Clear()
+{
+ cache_map::iterator it = _cache.begin();
+ for (; it != _cache.end(); ++it)
+ delete((*it).second);
+ _cache.clear();
+
+ del_map::iterator del_it = _del.begin();
+ for (; del_it != _del.end(); ++del_it)
+ delete[]((*del_it).second);
+ _del.clear();
+}
diff --git a/font.h b/font.h
new file mode 100644
index 0000000..cf991f4
--- /dev/null
+++ b/font.h
@@ -0,0 +1,50 @@
+/*
+ * font.h: 'EnigmaNG' skin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * Taken from GraphTFT
+ */
+
+#ifndef VDR__GRAPHTFTFONT_H
+#define VDR__GRAPHTFTFONT_H
+
+#include "common.h"
+
+#include <map>
+#include <vector>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <vdr/font.h>
+#include <vdr/config.h>
+
+using std::map;
+using std::string;
+using std::vector;
+
+
+class cGraphtftFont
+{
+private:
+ typedef map<string,cFont*> cache_map;
+ typedef map<string,cFont::tPixelData*> del_map;
+
+public:
+ cGraphtftFont();
+ ~cGraphtftFont();
+
+ bool Load(string Filename, string CacheName, int Size, int Language = 0, int Width = 0, int Format = 0);
+ const cFont* GetFont(string CacheName);
+ void Clear(string CacheName);
+ void Clear();
+
+private:
+ FT_Library _library;
+ FT_Face _face;
+ FT_GlyphSlot _slot;
+ cache_map _cache;
+ del_map _del;
+
+};
+
+#endif // VDR__GRAPHTFTFONT_H
diff --git a/i18n.c b/i18n.c
index 52fec19..3ff1bbe 100644
--- a/i18n.c
+++ b/i18n.c
@@ -1,10 +1,11 @@
/*
- * i18n.c: The 'EnigmaNG' VDR skin
+ * i18n.c: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
+#include "common.h"
#include "i18n.h"
const tI18nPhrase Phrases[] = {
@@ -14,7 +15,7 @@ const tI18nPhrase Phrases[] = {
"it_IT", // Italiano
"nl_NL", // Nederlands
"pt_PT", // Português
- "fr_FR", // Français
+ "fr_FR", // Français Patrice Staudt 18.05.2007
"no_NO", // Norsk
"fi_FI", // suomi (Finnish)
"pl_PL", // Polski
@@ -34,7 +35,7 @@ const tI18nPhrase Phrases[] = {
"EnigmaNG Oberfläche", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "EnigmaNG skin", // Nederlands
"", // Português
"Skin EnigmaNG", // Français
"", // Norsk
@@ -56,7 +57,7 @@ const tI18nPhrase Phrases[] = {
"EnigmaNG", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "EnigmaNG", // Nederlands
"", // Português
"EnigmaNG", // Français
"", // Norsk
@@ -78,7 +79,7 @@ const tI18nPhrase Phrases[] = {
"min", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "min", // Nederlands
"", // Português
"min", // Français
"", // Norsk
@@ -100,7 +101,7 @@ const tI18nPhrase Phrases[] = {
"Stereo", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Stereo", // Nederlands
"", // Português
"Stéréo", // Français
"", // Norsk
@@ -122,7 +123,7 @@ const tI18nPhrase Phrases[] = {
"Links", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Links", // Nederlands
"", // Português
"Gauche", // Français
"", // Norsk
@@ -144,7 +145,7 @@ const tI18nPhrase Phrases[] = {
"Rechts", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Rechts", // Nederlands
"", // Português
"Droite", // Français
"", // Norsk
@@ -166,7 +167,7 @@ const tI18nPhrase Phrases[] = {
"Stumm", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Geluid uit", // Nederlands
"", // Português
"Muet", // Français
"", // Norsk
@@ -188,7 +189,7 @@ const tI18nPhrase Phrases[] = {
"Lautstärke", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Volume", // Nederlands
"", // Português
"Volume", // Français
"", // Norsk
@@ -210,7 +211,7 @@ const tI18nPhrase Phrases[] = {
"Kanal-Logos anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Toon kanaallogo's", // Nederlands
"", // Português
"Afficher logo des chaînes", // Français
"", // Norsk
@@ -228,25 +229,25 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"Identify channel by", // English
- "Kanal-Identifikation durch", // Deutsch
+ {" Identify channel by", // English
+ " Kanal-Identifikation durch", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ " Kanaalidentificatie door", // Nederlands
"", // Português
- "Identifier chaîne par", // Français
+ " Identifier chaîne par", // Français
"", // Norsk
- "Tunnista kanava", // suomi (Finnish)
- "Rozpoznaj kana³ po", // Polski
- "Identificar el canal por...", // Español
+ " Tunnista kanava", // suomi (Finnish)
+ " Rozpoznaj kana³ po", // Polski
+ " Identificar el canal por...", // Español
"", // ÅëëçíéêÜ (Greek)
- "Identifiera kanal med", // Svenska
+ " Identifiera kanal med", // Svenska
"", // Românã
"", // Magyar
"", // Català
- "¾ßàÕÔÕÛïâì ÚÐÝÐÛ ßÞ", // ÀãááÚØÙ (Russian)
+ " ¾ßàÕÔÕÛïâì ÚÐÝÐÛ ßÞ", // ÀãááÚØÙ (Russian)
"", // Hrvatski
- "Kanali tuvastamise meetod", // Eesti
+ " Kanali tuvastamise meetod", // Eesti
"", // Dansk
"", // Èesky (Czech)
},
@@ -254,7 +255,7 @@ const tI18nPhrase Phrases[] = {
"Name", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "naam", // Nederlands
"", // Português
"Nom", // Français
"", // Norsk
@@ -266,7 +267,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "ØÜï", // ÀãááÚØÙ (Russian)
+ "ÝÐ×ÒÐÝØî", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"nimi", // Eesti
"", // Dansk
@@ -276,7 +277,7 @@ const tI18nPhrase Phrases[] = {
"ID", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "data", // Nederlands
"", // Português
"Donnée", // Français
"", // Norsk
@@ -288,7 +289,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "ÔÐÝÝëÕ", // ÀãááÚØÙ (Russian)
+ "ÔÐÝÝëÜ", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"andmed", // Eesti
"", // Dansk
@@ -298,7 +299,7 @@ const tI18nPhrase Phrases[] = {
"Größe des Logo-Caches", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Kanaallogo cache", // Nederlands
"", // Português
"Taille du cache des logo", // Français
"", // Norsk
@@ -320,7 +321,7 @@ const tI18nPhrase Phrases[] = {
"Cache leeren", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Cache legen", // Nederlands
"", // Português
"Supprimer cache", // Français
"", // Norsk
@@ -342,7 +343,7 @@ const tI18nPhrase Phrases[] = {
"Logo-Cache wird geleert...", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Kanaallogo cache legen...", // Nederlands
"", // Português
"Suppression du cache...", // Français
"", // Norsk
@@ -364,7 +365,7 @@ const tI18nPhrase Phrases[] = {
"Sprachen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Talen", // Nederlands
"", // Português
"Langues", // Français
"", // Norsk
@@ -386,7 +387,7 @@ const tI18nPhrase Phrases[] = {
"Zusatzinformation", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Hulp informatie", // Nederlands
"", // Português
"Information auxiliare", // Français
"", // Norsk
@@ -408,7 +409,7 @@ const tI18nPhrase Phrases[] = {
"Zusatzinfo anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Toon hulp informatie", // Nederlands
"", // Português
"Afficher information auxiliaire", // Français
"", // Norsk
@@ -430,7 +431,7 @@ const tI18nPhrase Phrases[] = {
"Zeige abgel./restl. Zeit", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Toon resterend/gedane tijd", // Nederlands
"", // Português
"Afficher le temps écoulé/restant", // Français
"", // Norsk
@@ -442,7 +443,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "¿ÞÚÐ×ëÒÐâì ÞáâÐÒ/ßàÞèÕÔ ÒàÕÜï", // ÀãááÚØÙ (Russian)
+ "¿ÞÚÐ×ëÒÐâì ÞáâÐÒ./ßàÞèÕÔ. ÒàÕÜï", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -452,7 +453,7 @@ const tI18nPhrase Phrases[] = {
"restliche", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "resterend", // Nederlands
"", // Português
"restant", // Français
"", // Norsk
@@ -474,7 +475,7 @@ const tI18nPhrase Phrases[] = {
"abgelaufene", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "gedane", // Nederlands
"", // Português
"écoulé", // Français
"", // Norsk
@@ -496,7 +497,7 @@ const tI18nPhrase Phrases[] = {
"Infobereich im Hauptmenü", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Info in hoofdmenu", // Nederlands
"", // Português
"Surface d'infos dans le menu principale", // Français
"", // Norsk
@@ -518,7 +519,7 @@ const tI18nPhrase Phrases[] = {
"Symbol vor Listeneinträgen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Markering in lijsten tonen", // Nederlands
"", // Português
"Symbole dans les listes", // Français
"", // Norsk
@@ -540,7 +541,7 @@ const tI18nPhrase Phrases[] = {
"Fortschrittbalken anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Progressiebalk tonen", // Nederlands
"", // Português
"Afficher barre de progression", // Français
"", // Norsk
@@ -562,7 +563,7 @@ const tI18nPhrase Phrases[] = {
"Symbole anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Symbolen tonen", // Nederlands
"", // Português
"Afficher symbole", // Français
"", // Norsk
@@ -584,7 +585,7 @@ const tI18nPhrase Phrases[] = {
"VPS anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "VPS tonen", // Nederlands
"", // Português
"Afficher le VPS", // Français
"", // Norsk
@@ -606,7 +607,7 @@ const tI18nPhrase Phrases[] = {
"WARNUNG", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "WAARSCHUWING", // Nederlands
"", // Português
"ATTENTION", // Français
"", // Norsk
@@ -628,7 +629,7 @@ const tI18nPhrase Phrases[] = {
"Timerkonflikt", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Timerconflict", // Nederlands
"", // Português
"Conflit de programmation", // Français
"", // Norsk
@@ -650,7 +651,7 @@ const tI18nPhrase Phrases[] = {
"Timerkonflikte", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Timerconflicten", // Nederlands
"", // Português
"Conflits de programmation", // Français
"", // Norsk
@@ -672,7 +673,7 @@ const tI18nPhrase Phrases[] = {
"TIMER", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "TIMER", // Nederlands
"", // Português
"PROGRAMMATION", // Français
"", // Norsk
@@ -694,7 +695,7 @@ const tI18nPhrase Phrases[] = {
"WIEDERHOLUNGEN", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "HERHALINGEN", // Nederlands
"", // Português
"REPETITION", // Français
"", // Norsk
@@ -716,7 +717,7 @@ const tI18nPhrase Phrases[] = {
"*** Ungültiger Kanal ***", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "*** Ongeldig Kanaal ***", // Nederlands
"", // Português
"*** Chaînes non valable ***", // Français
"", // Norsk
@@ -738,7 +739,7 @@ const tI18nPhrase Phrases[] = {
"Größe", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Grootte", // Nederlands
"", // Português
"Taille", // Français
"", // Norsk
@@ -760,7 +761,7 @@ const tI18nPhrase Phrases[] = {
"Stumm", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Geluid uit", // Nederlands
"Muet", // Português
"", // Français
"", // Norsk
@@ -782,7 +783,7 @@ const tI18nPhrase Phrases[] = {
"Lautstärke", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Volume", // Nederlands
"", // Português
"Volume", // Français
"", // Norsk
@@ -804,7 +805,7 @@ const tI18nPhrase Phrases[] = {
"Symbole in Listen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Symbolen in lijsten", // Nederlands
"", // Português
"Symboles dans les listes", // Français
"", // Norsk
@@ -822,37 +823,15 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"One area (if possible)", // English
- "Ein Bildbereich (wenn möglich)", // Deutsch
+ {"Try 8bpp single area", // English
+ "Einen 8bpp Bereich versuchen", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Une partie d'image (si possible)", // Français
- "", // Norsk
- "Pyri käyttämään yhtä kuva-aluetta",// suomi (Finnish)
- "", // Polski
- "", // Español
- "", // ÅëëçíéêÜ (Greek)
- "", // Svenska
- "", // Românã
- "", // Magyar
- "", // Català
- "¾ÔÝÐ ÞÑÛÐáâì(ÕáÛØ ÒÞ×ÜÞÖÝÞ)", // ÀãááÚØÙ (Russian)
- "", // Hrvatski
- "", // Eesti
- "", // Dansk
- "", // Èesky (Czech)
- },
- {"Bpp in single area", // English
- "Tiefe des Bildbereichs", // Deutsch
- "", // Slovenski
- "", // Italiano
- "", // Nederlands
- "", // Português
- "Profondeur d'une partie d'image", // Français
+ "", // Français
"", // Norsk
- "Kuva-alueen värisyvyys", // suomi (Finnish)
+ "Suosi yhtä 8bpp kuva-aluetta", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -860,7 +839,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "³ÛãÑØÝÐ ÞÑÛÐáâØ Ø×ÞÑàÐÖÕÝØï", // ÀãááÚØÙ (Russian)
+ "", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -870,7 +849,7 @@ const tI18nPhrase Phrases[] = {
"Fahnen anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Vlaggen tonen", // Nederlands
"", // Português
"Afficher drapeau", // Français
"", // Norsk
@@ -892,7 +871,7 @@ const tI18nPhrase Phrases[] = {
"Symbole im Menü", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Symbolen in menu", // Nederlands
"", // Português
"Symboles dans le menu", // Français
"", // Norsk
@@ -914,7 +893,7 @@ const tI18nPhrase Phrases[] = {
"nie", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "nooit", // Nederlands
"", // Português
"jamais", // Français
"", // Norsk
@@ -936,7 +915,7 @@ const tI18nPhrase Phrases[] = {
"immer", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Altijd", // Nederlands
"", // Português
"toujours", // Français
"", // Norsk
@@ -954,55 +933,11 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"not in menu", // English
- "nicht im Menü", // Deutsch
- "", // Slovenski
- "", // Italiano
- "", // Nederlands
- "", // Português
- "pas dans le menu", // Français
- "", // Norsk
- "ei valikossa", // suomi (Finnish)
- "", // Polski
- "", // Español
- "", // ÅëëçíéêÜ (Greek)
- "", // Svenska
- "", // Românã
- "", // Magyar
- "", // Català
- "ÝÕ Ò ÜÕÝî", // ÀãááÚØÙ (Russian)
- "", // Hrvatski
- "", // Eesti
- "", // Dansk
- "", // Èesky (Czech)
- },
- {"only in menu", // English
- "nur im Menü", // Deutsch
- "", // Slovenski
- "", // Italiano
- "", // Nederlands
- "", // Português
- "que dans le menu", // Français
- "", // Norsk
- "vain valikossa", // suomi (Finnish)
- "", // Polski
- "", // Español
- "", // ÅëëçíéêÜ (Greek)
- "", // Svenska
- "", // Românã
- "", // Magyar
- "", // Català
- "âÞÛìÚÞ Ò ÜÕÝî", // ÀãááÚØÙ (Russian)
- "", // Hrvatski
- "", // Eesti
- "", // Dansk
- "", // Èesky (Czech)
- },
{"percent", // English
"Prozent", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "procent", // Nederlands
"", // Português
"Pourcentage", // Français
"", // Norsk
@@ -1024,7 +959,7 @@ const tI18nPhrase Phrases[] = {
"wenn vorhanden", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "wanneer aanwezig", // Nederlands
"", // Português
"si existant", // Français
"", // Norsk
@@ -1046,7 +981,7 @@ const tI18nPhrase Phrases[] = {
"Anzahl Wiederholungen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "aantal herhalingen", // Nederlands
"", // Português
"Nombre de répétitions", // Français
"", // Norsk
@@ -1068,7 +1003,7 @@ const tI18nPhrase Phrases[] = {
"Verw. Untertitel für Wdh.", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Gebr. ondertitlel voor herh.", // Nederlands
"", // Português
"Utilise sous-titre pour les répétitions", // Français
"", // Norsk
@@ -1090,7 +1025,7 @@ const tI18nPhrase Phrases[] = {
"Timerkonflikte anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Timerconflict tonen", // Nederlands
"", // Português
"Afficher les conflits de programmation", // Français
"", // Norsk
@@ -1112,7 +1047,7 @@ const tI18nPhrase Phrases[] = {
"Überwachung", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Monitoren", // Nederlands
"", // Português
"Observation de la programmation", // Français
"", // Norsk
@@ -1134,7 +1069,7 @@ const tI18nPhrase Phrases[] = {
"EPGSearch", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "EPGsearch", // Nederlands
"", // Português
"Recherche EPG", // Français
"", // Norsk
@@ -1156,7 +1091,7 @@ const tI18nPhrase Phrases[] = {
"Logos & Symbole", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Logo's & Symbolen", // Nederlands
"", // Português
"Logos et symboles", // Français
"", // Norsk
@@ -1178,7 +1113,7 @@ const tI18nPhrase Phrases[] = {
"nur size.vdr verwenden", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "alleen size.vdr gebruiken", // Nederlands
"", // Português
"utiliser seulement size.vdr", // Français Patrice Staudt 29.03.2007
"", // Norsk
@@ -1190,7 +1125,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "", // ÀãááÚØÙ (Russian)
+ "ØáßÞÛì×ÞÒÐâì âÞÛìÚÞ size.vdr", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -1200,7 +1135,7 @@ const tI18nPhrase Phrases[] = {
"Aufnahmengröße anzeigen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "Opnamegrootte tonen", // Nederlands
"", // Português
"Afficher la taille des l'enregistrements", // Français
"", // Norsk
@@ -1212,7 +1147,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "", // ÀãááÚØÙ (Russian)
+ "¿ÞÚÐ×ëÒÐâì àÐ×ÜÕàë ×ÐßØáÕÙ", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -1222,7 +1157,7 @@ const tI18nPhrase Phrases[] = {
"Pixel-Algorithmus", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "pixelalgoritme", // Nederlands
"", // Português
"Algorithme pixel", // Français
"", // Norsk
@@ -1234,7 +1169,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "", // ÀãááÚØÙ (Russian)
+ "ÐÛÓÞàØâÜ ßØÚáÕÛï", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -1244,7 +1179,7 @@ const tI18nPhrase Phrases[] = {
"Ratio-Algorithmus", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "algoritmeratio", // Nederlands
"", // Português
"Algorithme ratio", // Français
"", // Norsk
@@ -1256,7 +1191,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "", // ÀãááÚØÙ (Russian)
+ "ÐÛÓÞàØâÜ áÞÞâÝÞèÕÝØï", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -1266,7 +1201,7 @@ const tI18nPhrase Phrases[] = {
"Zoomen", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "zoomen", // Nederlands
"", // Português
"Agrandit image", // Français
"", // Norsk
@@ -1278,7 +1213,7 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "", // ÀãááÚØÙ (Russian)
+ "ÃÒÕÛØçØâì", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
@@ -1288,7 +1223,7 @@ const tI18nPhrase Phrases[] = {
"Bilder in EPG/Aufnahmendetails", // Deutsch
"", // Slovenski
"", // Italiano
- "", // Nederlands
+ "EPG/opnamedetails tonen", // Nederlands
"", // Português
"Images dans les EPG et détails d'enregistrements", // Français
"", // Norsk
@@ -1300,21 +1235,178 @@ const tI18nPhrase Phrases[] = {
"", // Românã
"", // Magyar
"", // Català
- "", // ÀãááÚØÙ (Russian)
+ "¸×ÞÑàÐÖÕÝØï Ò EPG", // ÀãááÚØÙ (Russian)
"", // Hrvatski
"", // Eesti
"", // Dansk
"", // Èesky (Czech)
},
- {"Resize images", // English
- "Bildberechnung benutzt", // Deutsch
+ {" Resize images", // English
+ " Bildberechnung benutzt", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ " Aanpassen beeldgrootte", // Nederlands
+ "", // Português
+ " Redimension les images", // Français
+ "", // Norsk
+ " Muokkaa kuvien kokoa", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ " ¿ÕàÕàÕèÐâì ØáßÞÛì×ãï", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Image width", // English
+ " Bildbreite", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ " Beeldbreedte", // Nederlands
+ "", // Português
+ " Largeur d'image ", // Français
+ "", // Norsk
+ " Kuvien leveys", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ " ÈØàØÝÐ Ø×ÞÑàÐÖÕÝØï", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Image height", // English
+ " Bildhöhe", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ " Beeldhoogte", // Nederlands
+ "", // Português
+ " Hauteur d'image", // Français
+ "", // Norsk
+ " Kuvien korkeus", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ " ²ëáÞâÐ Ø×ÞÑàÐÖÕÝØï", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Image format", // English
+ " Bildformat", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ " Beeldformaat", // Nederlands
+ "", // Português
+ " Format d'image", // Français
+ "", // Norsk
+ " Kuvaformaatti", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ " ÄÞàÜÐâ Ø×ÞÑàÐÖÕÝØï", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Full title width", // English
+ "Volle Titelbreite", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "Volle titelbreedte", // Nederlands
+ "", // Português
+ "Largeur total pour le titre", // Français
+ "", // Norsk
+ "Levitä otsikkopalkki", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "¿ÞÛÝÐï èØàØÝÐ ×ÐÓÞÛÞÒÚÐ", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+#ifdef USE_PLUGIN_MAILBOX
+ {"Show mail icon", // English
+ "Zeige Mail-Icon", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "Mail-ikoon tonen", // Nederlands
+ "", // Português
+ "Affiche l'icone courriel", // Français
+ "", // Norsk
+ "Näytä sähköpostikuvake", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "¿ÞÚÐ×Ðâì ×ÝÐçÞÚ íÛÕÚâ. ßÞçâë", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"only if new mail present", // English
+ "nur bei neuer Mail", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "alleen bij nieuwe mail", // Nederlands
+ "", // Português
+ "juste lors d'un courriel", // Français
+ "", // Norsk
+ "jos uutta postia", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "âÞÛìÚÞ ßàØ ÝÞÒÞÜ áÞÞÑéÕÝØØ", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+#endif
+#ifndef DISABLE_ANIMATED_TEXT
+ {"Animated Text", // English
+ "Bewegter Text", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Redimension les images", // Français
+ "Texte défilant", // Français
"", // Norsk
- "Muokkaa kuvien kokoa", // suomi (Finnish)
+ "Tekstien elävöinti", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1328,15 +1420,15 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"Image width", // English
- "Bildbreite", // Deutsch
+ {"Enable", // English
+ "Verwenden", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Largeur d'image ", // Français
+ "Permettre", // Français
"", // Norsk
- "Kuvien leveys", // suomi (Finnish)
+ "Käytä elävöintiä", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1350,15 +1442,15 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"Image height", // English
- "Bildhöhe", // Deutsch
+ {" Scoll behaviour", // English
+ " Scroll-Verhalten", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Hauteur d'image", // Français
+ " Comportement de défilement", // Français
"", // Norsk
- "Kuvien korkeus", // suomi (Finnish)
+ " Vieritystapa", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1372,15 +1464,15 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"Image format", // English
- "Bildformat", // Deutsch
+ {"to the left", // English
+ "nach links", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Format d'image", // Français
+ "vers la gauche", // Français
"", // Norsk
- "Kuvaformaatti", // suomi (Finnish)
+ "vasemmalle", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1394,15 +1486,15 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"Full title width", // English
- "Volle Titelbreite", // Deutsch
+ {"left and right", // English
+ "links und rechts", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Largeur total pour le titre", // Français
+ "gauche et droite", // Français
"", // Norsk
- "Levitä otsikkopalkki", // suomi (Finnish)
+ "edestakaisin", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1416,16 +1508,15 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
-#ifdef USE_PLUGIN_MAILBOX
- {"Show mail icon", // English
- "Zeige Mail-Icon", // Deutsch
+ {" Scroll delay (ms)", // English
+ " Scroll-Verzögerung (ms)", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "Affiche l'icone Email", // Français
+ " Délai de défilement (ms)",// Français
"", // Norsk
- "Näytä sähköpostikuvake", // suomi (Finnish)
+ " Vierityksen viive (ms)", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1439,15 +1530,919 @@ const tI18nPhrase Phrases[] = {
"", // Dansk
"", // Èesky (Czech)
},
- {"only if new mail present", // English
- "nur bei neuer Mail", // Deutsch
+ {" Scroll pause (ms)", // English
+ " Scroll-Pause (ms)", // Deutsch
"", // Slovenski
"", // Italiano
"", // Nederlands
"", // Português
- "juste lors d'un Email", // Français
+ " Pause de défilement (ms)",// Français
"", // Norsk
- "jos uutta postia", // suomi (Finnish)
+ " Vierityksen tauko (ms)", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Blink pause (ms)", // English
+ " Blink-Pause (ms)", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Pause de clignotement (ms)",// Français
+ "", // Norsk
+ " Vilkutuksen tauko (ms)", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Scroll OSD title", // English
+ " OSD Titel scrollen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Défillement dans le titre du OSD", // Français
+ "", // Norsk
+ " Vieritä valikon otsikkoa",// suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Scroll info area", // English
+ " Infobereich scrollen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Barre de défilement dans la surface info", // Français
+ "", // Norsk
+ " Vieritä infoaluetta", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Scroll active list items", // English
+ " Aktive Listenzeile scrollen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Barre de défilement dans la liste active", // Français
+ "", // Norsk
+ " Vieritä aktiivista valintaa", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Scroll other items", // English
+ " Andere Bereiche scrollen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Barre de défilement dans d'autre partie", // Français
+ "", // Norsk
+ " Vieritä muita alueita", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+#endif
+ {" Show symbols in menu", // English
+ " Symbole im Menü", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Afficher les symboles dans le menu", // Français
+ "", // Norsk
+ " Näytä symbolit valikossa", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Show symbols in replay", // English
+ " Symbole bei der Wiedergabe", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Afficher les symboles dans lecture", // Français
+ "", // Norsk
+ " Näytä symbolit toistettaessa", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Show symbols in messages", // English
+ " Symbole bei den Meldungen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Afficher les symboles dans les messages", // Français
+ "", // Norsk
+ " Näytä symbolit viesteissä", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {" Show symbols in audio", // English
+ " Symbole bei Audio", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ " Afficher les symboles dans audio", // Français
+ "", // Norsk
+ " Näytä symbolit äänivalikossa", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Fonts", // English
+ "Fonts", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Les polices", // Français
+ "", // Norsk
+ "Kirjasimet", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"OSD title", // English
+ "OSD Titel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "OSD Titre", // Français
+ "", // Norsk
+ "Valikon otsikko", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Date", // English
+ "Datum", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Date", // Français
+ "", // Norsk
+ "", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Messages", // English
+ "Meldungen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Message", // Français
+ "", // Norsk
+ "Viestit", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Help keys", // English
+ "Farb-Tasten", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Touche couleur", // Français
+ "", // Norsk
+ "Värinäppäimet", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Channelinfo: title", // English
+ "Kanalinfo: Titel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Channel info: titre ", // Français
+ "", // Norsk
+ "Kanavatieto: ohjelman nimi",// suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Channelinfo: subtitle", // English
+ "Kanalinfo: Untertitel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Channel info: sous-titre", // Français
+ "", // Norsk
+ "Kanavatieto: ohjelman kuvaus", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Channelinfo: language", // English
+ "Kanalinfo: Sprache", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Channel info: langue", // Français
+ "", // Norsk
+ "Kanavatieto: kieli", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"List items", // English
+ "Listen", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Liste", // Français
+ "", // Norsk
+ "Listat", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Info area: timers title", // English
+ "Infobereich: Timer Titel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Barre d'information: Titre Progammation", // Français
+ "", // Norsk
+ "Infoalue: ajastimen otsikko", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Info area: timers text", // English
+ "Infobereich: Timer Text", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Barre d'information: Text programmation", // Français
+ "", // Norsk
+ "Infoalue: ajastimen leipäteksti", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Info area: warning title", // English
+ "Infobereich: Warnung Titel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Barre d'information: avertissement titre", // Français
+ "", // Norsk
+ "Infoalue: varoituksen otsikko", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Info area: warning text", // English
+ "Infobereich: Warnung Text", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Barre d'information: texte d'avertissement", // Français
+ "", // Norsk
+ "Infoalue: varoituksen leipäteksti", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Details: title", // English
+ "Details: Titel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Détails: Titre", // Français
+ "", // Norsk
+ "Lisätiedot: ohjelman nimi", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Details: subtitle", // English
+ "Details: Untertitel", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Détails: Sous-titre", // Français
+ "", // Norsk
+ "Lisätiedot: ohjelman kuvaus", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Details: date", // English
+ "Details: Datumszeile", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Détails: date", // Français
+ "", // Norsk
+ "Lisätiedot: päivämäärä", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Details: text", // English
+ "Details: Text", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Détails: Text", // Français
+ "", // Norsk
+ "Lisätiedot: leipäteksti", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Replay: times", // English
+ "Wiedergabe: Zeiten", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Rejouer : périodes", // Français
+ "", // Norsk
+ "Toisto: kellonajat", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Default OSD Font", // English
+ "Std. OSD Font", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Police OSD standart", // Français
+ "", // Norsk
+ "oletuskirjasin", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Default Fixed Size Font", // English
+ "Std. Schrift mit fester Breite", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Police largeur fixe standart", // Français
+ "", // Norsk
+ "kiinteäkokoinen oletuskirjasin", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Default Small Font", // English
+ "Std. kleine Schrift", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Petite police standart", // Français
+ "", // Norsk
+ "pieni oletuskirjasin", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Channel:", // English
+ "Kanal:", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Chaîne:", // Français
+ "", // Norsk
+ "Kanava:", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Search pattern:", // English
+ "Suchmuster:", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Modèle de recherche", // Français
+ "", // Norsk
+ "Hakutapa:", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"No timer check", // English
+ "Ohne Überwachung", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Sans surveillance", // Français
+ "", // Norsk
+ "Ei valvontaa", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"General", // English
+ "Allgemein", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Généralité", // Français
+ "", // Norsk
+ "Yleiset", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Name", // English
+ "Name", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Nom", // Français
+ "", // Norsk
+ "Nimi", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Width", // English
+ "Weite", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Largeur", // Français
+ "", // Norsk
+ "Leveys", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Button$Set", // English
+ "Ändern", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Changer", // Français
+ "", // Norsk
+ "Aseta", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"TrueType Font", // English
+ "TrueType Schrift", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Police TrueType", // Français
+ "", // Norsk
+ "TrueType-kirjasin", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"No TTF support!", // English
+ "TTF nicht unterstützt!", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "Les polices TrueType ne sont pas supportées!", // Français
+ "", // Norsk
+ "Ei TTF-tukea!", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+ {"Fixed Font", // English
+ "Schrift mit fester Breite", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "", // suomi (Finnish)
+ "", // Polski
+ "", // Español
+ "", // ÅëëçíéêÜ (Greek)
+ "", // Svenska
+ "", // Românã
+ "", // Magyar
+ "", // Català
+ "", // ÀãááÚØÙ (Russian)
+ "", // Hrvatski
+ "", // Eesti
+ "", // Dansk
+ "", // Èesky (Czech)
+ },
+#ifdef USE_PLUGIN_AVARDS
+ {"Dynamic OSD size", // English
+ "Dynamische OSD-Größe", // Deutsch
+ "", // Slovenski
+ "", // Italiano
+ "", // Nederlands
+ "", // Português
+ "", // Français
+ "", // Norsk
+ "", // suomi (Finnish)
"", // Polski
"", // Español
"", // ÅëëçíéêÜ (Greek)
@@ -1464,3 +2459,4 @@ const tI18nPhrase Phrases[] = {
#endif
{NULL}
};
+// vim:et:sw=2:ts=2:
diff --git a/i18n.h b/i18n.h
index 5068d5b..718e5b8 100644
--- a/i18n.h
+++ b/i18n.h
@@ -1,5 +1,5 @@
/*
- * i18n.h: The 'EnigmaNG' VDR skin
+ * i18n.h: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -8,8 +8,11 @@
#ifndef __ENIGMA_I18N_H
#define __ENIGMA_I18N_H
+#include "common.h"
+
#include <vdr/i18n.h>
extern const tI18nPhrase Phrases[];
#endif // __ENIGMA_I18N_H
+// vim:et:sw=2:ts=2:
diff --git a/logo.c b/logo.c
index 30a0cbe..69d5eb5 100644
--- a/logo.c
+++ b/logo.c
@@ -1,17 +1,15 @@
/*
- * logo.c: The 'EnigmaNG' VDR skin
+ * logo.c: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
-#include <strings.h>
-
-#include "bitmap.h"
#include "common.h"
+#include "bitmap.h"
#include "config.h"
#include "logo.h"
-#include <vdr/tools.h>
+
#include <vdr/plugin.h>
cEnigmaLogoCache EnigmaLogoCache(0);
@@ -45,32 +43,35 @@ bool cEnigmaLogoCache::Resize(unsigned int cacheSizeP)
return true;
}
-bool cEnigmaLogoCache::LoadEventImage(const cEvent *Event, int w, int h, int c)
+bool cEnigmaLogoCache::DrawEventImage(const cEvent *Event, int x, int y, int w, int h, int c, cBitmap *bmp)
{
- if (Event == NULL)
+ if (Event == NULL || bmp == NULL)
return false;
char *strFilename = NULL;
asprintf(&strFilename, "%s/%d.%s", EnigmaConfig.GetImagesDir(), Event->EventID(), EnigmaConfig.GetImageExtension());
- int rc = LoadImage(strFilename, w, h, c);
+ int rc = DrawImage(strFilename, x, y, w, h, c, bmp);
free (strFilename);
return rc;
}
-bool cEnigmaLogoCache::LoadRecordingImage(const cRecording *Recording, int w, int h, int c)
+bool cEnigmaLogoCache::DrawRecordingImage(const cRecording *Recording, int x, int y, int w, int h, int c, cBitmap *bmp)
{
- if (Recording == NULL)
+ if (Recording == NULL || bmp == NULL)
return false;
char *strFilename = NULL;
asprintf(&strFilename, "%s/%s.%s", Recording->FileName(), RECORDING_COVER, EnigmaConfig.GetImageExtension());
- int rc = LoadImage(strFilename, w, h, c);
+ int rc = DrawImage(strFilename, x, y, w, h, c, bmp);
free (strFilename);
return rc;
}
-bool cEnigmaLogoCache::LoadImage(const char *fileNameP, int w, int h, int c)
+bool cEnigmaLogoCache::DrawImage(const char *fileNameP, int x, int y, int w, int h, int c, cBitmap *bmp)
{
+ if (fileNameP== NULL || bmp == NULL)
+ return false;
+
struct stat stbuf;
if (lstat(fileNameP, &stbuf) != 0) {
error("cPluginSkinEnigma::LoadImage(%s) FILE NOT FOUND\n", fileNameP);
@@ -79,11 +80,13 @@ bool cEnigmaLogoCache::LoadImage(const char *fileNameP, int w, int h, int c)
}
#ifdef HAVE_IMAGEMAGICK
- int rc = image.LoadImage(fileNameP, w, h, c, *bmpImage);
- bitmapM = rc ? bmpImage : NULL;
- return rc;
+ bitmapM = NULL;
+ return image.DrawImage(fileNameP, x, y, w, h, c, bmp);
#else
- return LoadXpm(fileNameP, w, h);
+ int rc = LoadXpm(fileNameP, w, h);
+ if (rc)
+ bmp->DrawBitmap(x, y, *bitmapM); //TODO?
+ return rc;
#endif
}
@@ -226,13 +229,10 @@ bool cEnigmaLogoCache::Flush(void)
if (!cacheMapM.empty()) {
debug("cPluginSkinEnigma::Flush() NON-EMPTY\n");
// delete bitmaps and clear map
- for (std::map < std::string, cBitmap * >::iterator i = cacheMapM.begin();
- i != cacheMapM.end(); ++i) {
- cBitmap *bmp = i->second;
- if (bmp)
- DELETENULL(bmp);
- cacheMapM.erase(i);
+ for (std::map<std::string, cBitmap *>::iterator i = cacheMapM.begin(); i != cacheMapM.end(); i++) {
+ delete((*i).second);
}
+ cacheMapM.clear();
// nullify bitmap pointer
bitmapM = NULL;
}
diff --git a/logo.h b/logo.h
index a58727a..24968c6 100644
--- a/logo.h
+++ b/logo.h
@@ -1,5 +1,5 @@
/*
- * logo.h: The 'EnigmaNG' VDR skin
+ * logo.h: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -8,17 +8,18 @@
#ifndef __SKINENIGMA_LOGO_H
#define __SKINENIGMA_LOGO_H
+#include "common.h"
+
+#ifdef HAVE_IMAGEMAGICK
+#include "bitmap.h"
+#endif
+
#include <map>
-#include <string>
#include <vdr/channels.h>
#include <vdr/epg.h>
#include <vdr/recording.h>
#include <vdr/osd.h>
-#ifdef HAVE_IMAGEMAGICK
-#include "bitmap.h"
-#endif
-
// size of channel logos
#define ChannelLogoWidth 80
#define ChannelLogoHeight 80
@@ -31,26 +32,26 @@
class cEnigmaLogoCache {
private:
- bool fImageRequested;
+ bool fImageRequested;
unsigned int cacheSizeM;
cBitmap *bitmapM;
#ifdef HAVE_IMAGEMAGICK
- cOSDImageBitmap image;
- cBitmap *bmpImage;
+ cOSDImageBitmap image;
+ cBitmap *bmpImage;
#endif
std::map<std::string, cBitmap*> cacheMapM;
- bool LoadImage(const char *fileNameP, int w, int h, int c);
+ bool DrawImage(const char *fileNameP, int x, int y, int w, int h, int c, cBitmap *bmp);
bool LoadXpm(const char *fileNameP, int w, int h);
- bool Load(const char *fileNameP, int w, int h);
+ bool Load(const char *fileNameP, int w, int h);
public:
cEnigmaLogoCache(unsigned int cacheSizeP);
~cEnigmaLogoCache();
bool Resize(unsigned int cacheSizeP);
- bool LoadEventImage(const cEvent *Event, int w, int h, int c);
- bool LoadRecordingImage(const cRecording *Recording, int w, int h, int c);
- bool LoadChannelLogo(const cChannel *Channel);
- bool LoadSymbol(const char *fileNameP);
- bool LoadIcon(const char *fileNameP);
+ bool DrawEventImage(const cEvent *Event, int x, int y, int w, int h, int c, cBitmap *bmp);
+ bool DrawRecordingImage(const cRecording *Recording, int x, int y, int w, int h, int c, cBitmap *bmp);
+ bool LoadChannelLogo(const cChannel *Channel);
+ bool LoadSymbol(const char *fileNameP);
+ bool LoadIcon(const char *fileNameP);
cBitmap& Get(void);
bool Flush(void);
};
@@ -58,3 +59,5 @@ public:
extern cEnigmaLogoCache EnigmaLogoCache;
#endif // __SKINENIGMA_LOGO_H
+
+// vim:et:sw=2:ts=2:
diff --git a/setup.c b/setup.c
new file mode 100644
index 0000000..4dde105
--- /dev/null
+++ b/setup.c
@@ -0,0 +1,546 @@
+/*
+ * setup.c: 'EnigmaNG' skin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "common.h"
+#include "config.h"
+#include "i18n.h"
+#include "logo.h"
+#include "setup.h"
+#include "tools.h"
+
+#ifdef HAVE_FREETYPE
+#include "texteffects.h"
+#endif
+
+static const char *allFonts[] = {
+#ifdef HAVE_FREETYPE
+ "TrueType Font",
+#else
+ "No TTF support!",
+#endif
+ "Default OSD Font",
+ "Default Fixed Size Font",
+ "Default Small Font",
+ SKINENIGMA_FONTS
+};
+
+// cPluginSkinEnigmaSetup
+cPluginSkinEnigmaSetup::cPluginSkinEnigmaSetup(void)
+{
+ // create setup menu
+ debug("cPluginSkinEnigmaSetup()\n");
+
+ data = EnigmaConfig;
+ Setup();
+}
+
+void cPluginSkinEnigmaSetup::AddCategory(const char *Title) {
+ char *buffer = NULL;
+
+ asprintf(&buffer, "--- %s ----------------------------------------------------------------------------------", Title );
+
+ cOsdItem *item = new cOsdItem(buffer);
+ free(buffer);
+
+ if (item) {
+ item->SetSelectable(false);
+ Add(item);
+ }
+}
+
+void cPluginSkinEnigmaSetup::Setup(void)
+{
+ // update setup display
+ int current = Current();
+
+ Clear();
+
+ Add(new cOsdItem(tr("General")));
+ Add(new cOsdItem(tr("Logos & Symbols")));
+#ifndef DISABLE_ANIMATED_TEXT
+ Add(new cOsdItem(tr("Animated Text")));
+#endif
+ if (::Setup.UseSmallFont == 1) { // only if "Use small font" = "skin dependent"
+ Add(new cOsdItem(tr("Fonts")));
+ }
+#ifdef SKINENIGMA_HAVE_EPGSEARCH
+ Add(new cOsdItem(tr("EPGSearch")));
+#endif
+
+ SetCurrent(Get(current));
+ Display();
+ SetHelp(NULL, NULL, NULL, tr("Button$Open"));
+}
+
+void cPluginSkinEnigmaSetup::Store(void)
+{
+ // store setup data
+ debug("cPluginSkinEnigmaSetup::Store()\n");
+
+ EnigmaConfig = data;
+ SetupStore("SingleArea8Bpp", EnigmaConfig.singleArea8Bpp);
+ SetupStore("ShowAuxInfo", EnigmaConfig.showAuxInfo);
+ SetupStore("ShowRemaining", EnigmaConfig.showRemaining);
+ SetupStore("ShowProgressBar", EnigmaConfig.showProgressbar);
+ SetupStore("ShowListSymbols", EnigmaConfig.showListSymbols);
+ SetupStore("ShowSymbols", EnigmaConfig.showSymbols);
+ SetupStore("ShowSymbolsMenu", EnigmaConfig.showSymbolsMenu);
+ SetupStore("ShowSymbolsReplay", EnigmaConfig.showSymbolsReplay);
+ SetupStore("ShowSymbolsMsgs", EnigmaConfig.showSymbolsMsgs);
+ SetupStore("ShowSymbolsAudio", EnigmaConfig.showSymbolsAudio);
+ SetupStore("ShowLogo", EnigmaConfig.showLogo);
+ SetupStore("ShowInfo", EnigmaConfig.showInfo);
+ SetupStore("ShowVPS", EnigmaConfig.showVps);
+ SetupStore("ShowFlags", EnigmaConfig.showFlags);
+ SetupStore("ShowMarker", EnigmaConfig.showMarker);
+ SetupStore("CacheSize", EnigmaConfig.cacheSize);
+ SetupStore("UseChannelId", EnigmaConfig.useChannelId);
+ SetupStore("NumReruns", EnigmaConfig.numReruns);
+ SetupStore("UseSubtitleRerun", EnigmaConfig.useSubtitleRerun);
+ SetupStore("ShowTimerConflicts", EnigmaConfig.showTimerConflicts);
+ SetupStore("ShowRecSize", EnigmaConfig.showRecSize);
+ SetupStore("ShowImages", EnigmaConfig.showImages);
+ SetupStore("ResizeImages", EnigmaConfig.resizeImages);
+ SetupStore("ShowMailIcon", EnigmaConfig.showMailIcon);
+ SetupStore("ImageWidth", EnigmaConfig.imageWidth);
+ SetupStore("ImageHeight", EnigmaConfig.imageHeight);
+ SetupStore("ImageExtension", EnigmaConfig.imageExtension);
+ SetupStore("FullTitleWidth", EnigmaConfig.fullTitleWidth);
+ SetupStore("UseTextEffects", EnigmaConfig.useTextEffects);
+ SetupStore("ScrollDelay", EnigmaConfig.scrollDelay);
+ SetupStore("ScrollPause", EnigmaConfig.scrollPause);
+ SetupStore("ScrollMode", EnigmaConfig.scrollMode);
+ SetupStore("BlinkPause", EnigmaConfig.blinkPause);
+ SetupStore("ScrollInfo", EnigmaConfig.scrollInfo);
+ SetupStore("ScrollListItem", EnigmaConfig.scrollListItem);
+ SetupStore("ScrollOther", EnigmaConfig.scrollOther);
+ SetupStore("ScrollTitle", EnigmaConfig.scrollTitle);
+ SetupStore("DynOSD", EnigmaConfig.dynOsd);
+
+ char tmp[sizeof(EnigmaConfig.allFonts[0].Name) + 8];
+ for (int id = 0; id < FONT_NUMFONTS; id++) {
+ SetupStore(allFontConfig[id].KeyId, EnigmaConfig.allFonts[id].VdrId);
+ if (EnigmaConfig.allFonts[id].Name[0] != 0) {
+ sprintf(tmp, "%s:%d,%d", EnigmaConfig.allFonts[id].Name, EnigmaConfig.allFonts[id].Size, EnigmaConfig.allFonts[id].Width);
+ SetupStore(allFontConfig[id].KeyName, tmp);
+ }
+ }
+
+ // resize logo cache
+ EnigmaLogoCache.Resize(EnigmaConfig.cacheSize);
+}
+
+eOSState cPluginSkinEnigmaSetup::ProcessKey(eKeys Key)
+{
+ bool hadSubMenu = HasSubMenu();
+ eOSState state = cMenuSetupPage::ProcessKey(Key);
+
+ if (hadSubMenu && Key == kOk)
+ Store();
+
+ if (!HasSubMenu() && (state == osUnknown || Key == kOk)) {
+ if ((Key == kOk && !hadSubMenu) || Key == kBlue) {
+ const char* ItemText = Get(Current())->Text();
+ if (strcmp(ItemText, tr("General")) == 0)
+ state = AddSubMenu(new cMenuSetupGeneral(&data));
+ else if (strcmp(ItemText, tr("Logos & Symbols")) == 0)
+ state = AddSubMenu(new cMenuSetupLogos(&data));
+#ifndef DISABLE_ANIMATED_TEXT
+ else if (strcmp(ItemText, tr("Animated Text")) == 0)
+ state = AddSubMenu(new cMenuSetupAnimText(&data));
+#endif
+ else if (strcmp(ItemText, tr("Fonts")) == 0)
+ state = AddSubMenu(new cMenuSetupFonts(&data));
+#ifdef SKINENIGMA_HAVE_EPGSEARCH
+ else if (strcmp(ItemText, tr("EPGSearch")) == 0)
+ state = AddSubMenu(new cMenuSetupEpgSearch(&data));
+#endif
+ }
+ }
+
+ return state;
+}
+
+// Setup: SubMenu
+cMenuSetupSubMenu::cMenuSetupSubMenu(const char* Title, cEnigmaConfig* Data) : cOsdMenu(Title, 30)
+{
+ data = Data;
+}
+
+eOSState cMenuSetupSubMenu::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kOk:
+ return osBack;
+ default:
+ break;
+ }
+ }
+
+ return state;
+}
+
+// Setup: General
+cMenuSetupGeneral::cMenuSetupGeneral(cEnigmaConfig* Data) : cMenuSetupSubMenu(tr("General"), Data)
+{
+ showRemainingTexts[0] = tr("elapsed");
+ showRemainingTexts[1] = tr("remaining");
+ showRemainingTexts[2] = tr("percent");
+
+ showRecSizeTexts[0] = tr("never");
+ showRecSizeTexts[1] = tr("use size.vdr only");
+ showRecSizeTexts[2] = tr("always");
+
+ Set();
+}
+
+eOSState cMenuSetupGeneral::ProcessKey(eKeys Key)
+{
+ return cMenuSetupSubMenu::ProcessKey(Key);
+}
+
+void cMenuSetupGeneral::Set(void)
+{
+ int current = Current();
+ Clear();
+
+ Add(new cMenuEditBoolItem(tr("Try 8bpp single area"), &data->singleArea8Bpp));
+ Add(new cMenuEditBoolItem(tr("Show info area in main menu"), &data->showInfo));
+ Add(new cMenuEditBoolItem(tr("Show auxiliary information"), &data->showAuxInfo, tr("top"), tr("bottom")));
+ Add(new cMenuEditStraItem(tr("Show recording's size"), &data->showRecSize, 3, showRecSizeTexts));
+ Add(new cMenuEditBoolItem(tr("Full title width"), &data->fullTitleWidth));
+ Add(new cMenuEditStraItem(tr("Show remaining/elapsed time"), &data->showRemaining, 3, showRemainingTexts));
+ Add(new cMenuEditBoolItem(tr("Show VPS"), &data->showVps));
+ Add(new cMenuEditBoolItem(tr("Show progressbar"), &data->showProgressbar));
+#ifdef USE_PLUGIN_AVARDS
+ Add(new cMenuEditBoolItem(tr("Dynamic OSD size"), &data->dynOsd));
+#endif
+
+ SetCurrent(Get(current));
+ Display();
+ SetHelp(NULL, NULL, NULL, NULL);
+}
+
+// Setup: Logos & Symbols
+cMenuSetupLogos::cMenuSetupLogos(cEnigmaConfig* Data) : cMenuSetupSubMenu(tr("Logos & Symbols"), Data)
+{
+#ifndef SKINENIGMA_NO_MENULOGO
+ resizeImagesTexts[0] = tr("pixel algo");
+ resizeImagesTexts[1] = tr("ratio algo");
+ resizeImagesTexts[2] = tr("zoom image");
+#endif
+
+#ifdef USE_PLUGIN_MAILBOX
+ showMailIconTexts[0] = tr("never");
+ showMailIconTexts[1] = tr("only if new mail present");
+ showMailIconTexts[2] = tr("always");
+#endif
+
+ Set();
+}
+
+eOSState cMenuSetupLogos::ProcessKey(eKeys Key)
+{
+ int oldShowLogo = data->showLogo;
+ int oldShowSymbols = data->showSymbols;
+ int oldShowSymbolsMenu = data->showSymbolsMenu;
+ int oldShowImages = data->showImages;
+
+ eOSState state = cMenuSetupSubMenu::ProcessKey(Key);
+
+ if ((state == osUnknown) && (Key == kRed)) {
+ Skins.Message(mtInfo, tr("Flushing channel logo cache..."));
+ EnigmaLogoCache.Flush();
+ Skins.Message(mtInfo, NULL);
+ state = osContinue;
+ }
+
+ if (Key != kNone &&
+ ((data->showLogo != oldShowLogo)
+ || (data->showSymbols != oldShowSymbols)
+ || (data->showSymbolsMenu != oldShowSymbolsMenu)
+ || (data->showImages != oldShowImages)
+ )) {
+ Set();
+ }
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kOk:
+ return osBack;
+ default:
+ break;
+ }
+ }
+
+ return state;
+}
+
+void cMenuSetupLogos::Set(void)
+{
+ int current = Current();
+ Clear();
+
+ Add(new cMenuEditBoolItem(tr("Show symbols"), &data->showSymbols)); //TODO? symbols -> icons
+
+ if (data->showSymbols) {
+#ifndef SKINENIGMA_NO_MENULOGO
+ Add(new cMenuEditBoolItem(tr(" Show symbols in menu"), &data->showSymbolsMenu));
+#endif
+ Add(new cMenuEditBoolItem(tr(" Show symbols in replay"), &data->showSymbolsReplay));
+ Add(new cMenuEditBoolItem(tr(" Show symbols in messages"), &data->showSymbolsMsgs));
+ Add(new cMenuEditBoolItem(tr(" Show symbols in audio"), &data->showSymbolsAudio));
+ }
+
+ Add(new cMenuEditBoolItem(tr("Show symbols in lists"), &data->showListSymbols));
+ Add(new cMenuEditBoolItem(tr("Show marker in lists"), &data->showMarker));
+ Add(new cMenuEditBoolItem(tr("Show flags"), &data->showFlags));
+
+#ifdef USE_PLUGIN_MAILBOX
+ cPlugin *MailBoxPlugin = cPluginManager::GetPlugin("mailbox");
+ if (MailBoxPlugin && MailBoxPlugin->Service("MailBox-HasNewMail-1.0", 0)) {
+ Add(new cMenuEditStraItem(tr("Show mail icon"), &data->showMailIcon, 3, showMailIconTexts));
+ }
+#endif
+
+#ifndef SKINENIGMA_NO_MENULOGO
+ if (data->showSymbols && data->showSymbolsMenu) {
+ Add(new cMenuEditBoolItem(tr("Show event/recording images"), &data->showImages));
+ if (data->showImages) {
+#ifdef HAVE_IMAGEMAGICK
+ Add(new cMenuEditStraItem(tr(" Resize images"), &data->resizeImages, 3, resizeImagesTexts));
+#endif
+ Add(new cMenuEditIntItem(tr(" Image width" ), &data->imageWidth, 80, 180));
+ Add(new cMenuEditIntItem(tr(" Image height" ), &data->imageHeight, 80, 144));
+#ifdef HAVE_IMAGEMAGICK
+ Add(new cMenuEditStraItem(tr(" Image format"), &data->imageExtension, 3, imageExtensionTexts));
+#endif
+ }
+ }
+#endif //SKINENIGMA_NO_MENULOGO
+
+ Add(new cMenuEditBoolItem(tr("Show channel logos"), &data->showLogo));
+ if (data->showLogo) {
+ Add(new cMenuEditBoolItem(tr(" Identify channel by"), &data->useChannelId, tr("name"), tr("data")));
+ }
+ if (data->showLogo || data->showSymbols) {
+ Add(new cMenuEditIntItem(tr("Channel logo cache size"), &data->cacheSize, 0, 1000));
+ }
+
+ SetCurrent(Get(current));
+ Display();
+ SetHelp(tr("Button$Flush cache"), NULL, NULL, NULL);
+}
+
+#ifndef DISABLE_ANIMATED_TEXT
+// Setup: Animated Text
+cMenuSetupAnimText::cMenuSetupAnimText(cEnigmaConfig* Data) : cMenuSetupSubMenu(tr("General"), Data)
+{
+ scrollModeTexts[0] = tr("left and right");
+ scrollModeTexts[1] = tr("to the left");
+
+ Set();
+}
+
+eOSState cMenuSetupAnimText::ProcessKey(eKeys Key)
+{
+ int oldUseTextEffects = data->useTextEffects;
+
+ eOSState state = cMenuSetupSubMenu::ProcessKey(Key);
+
+ if (Key != kNone && oldUseTextEffects != data->useTextEffects)
+ Set();
+
+ return state;
+}
+
+void cMenuSetupAnimText::Set(void)
+{
+ int current = Current();
+ Clear();
+
+ Add(new cMenuEditBoolItem(tr("Enable"), &data->useTextEffects));
+ if (data->useTextEffects) {
+ Add(new cMenuEditBoolItem(tr(" Scroll OSD title"), &data->scrollTitle));
+ Add(new cMenuEditBoolItem(tr(" Scroll info area"), &data->scrollInfo));
+ Add(new cMenuEditBoolItem(tr(" Scroll active list items"), &data->scrollListItem));
+ Add(new cMenuEditBoolItem(tr(" Scroll other items"), &data->scrollOther));
+ Add(new cMenuEditStraItem(tr(" Scoll behaviour"), &data->scrollMode, 2, scrollModeTexts));
+ Add(new cMenuEditIntItem(tr(" Scroll delay (ms)"), &data->scrollDelay, 50, 1000));
+ Add(new cMenuEditIntItem(tr(" Scroll pause (ms)"), &data->scrollPause, 500, 2000));
+ Add(new cMenuEditIntItem(tr(" Blink pause (ms)"), &data->blinkPause, 500, 2000));
+ }
+
+ SetCurrent(Get(current));
+ Display();
+ SetHelp(NULL, NULL, NULL, NULL);
+}
+#endif
+
+#ifdef HAVE_FREETYPE
+// Setup: TTF
+cMenuSetupTTF::cMenuSetupTTF(FontInfo* Data) : cOsdMenu(tr("TrueType Font"), 10)
+{
+ data = Data;
+ availTTFs = EnigmaTextEffects.GetAvailTTFs();
+ nMaxTTFs = EnigmaTextEffects.GetNumAvailTTFs();
+ nFont = 0;
+ for (int i = 0; i < nMaxTTFs; i++) {
+ if (availTTFs[i]) {
+ if (strcmp(availTTFs[i], data->Name) == 0) {
+ nFont = i;
+ break;
+ }
+ }
+ }
+ nWidth = data->Width;
+ nSize = data->Size;
+ SetHelp(NULL, NULL, NULL, NULL);
+ Set();
+}
+
+void cMenuSetupTTF::Set(void)
+{
+ int current = Current();
+ Clear();
+
+ Add(new cMenuEditStraItem(tr("Name"), &nFont, nMaxTTFs, availTTFs));
+ Add(new cMenuEditIntItem(tr("Size"), &nSize, 10, 40));
+ Add(new cMenuEditIntItem(tr("Width"), &nWidth, 50, 150));
+
+ SetCurrent(Get(current));
+ Display();
+}
+
+eOSState cMenuSetupTTF::ProcessKey(eKeys Key)
+{
+ eOSState state = cOsdMenu::ProcessKey(Key);
+
+ if (state == osUnknown) {
+ switch (Key) {
+ case kOk:
+ Store();
+ state = osBack;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return state;
+}
+
+void cMenuSetupTTF::Store(void)
+{
+ strncpy(data->Name, availTTFs[nFont], sizeof(data->Name));
+ data->Width = nWidth;
+ data->Size = nSize;
+}
+#endif
+
+// Setup: Fonts
+cMenuSetupFonts::cMenuSetupFonts(cEnigmaConfig* Data) : cMenuSetupSubMenu(tr("General"), Data)
+{
+ allFonts[0] = tr(allFonts[0]);
+ allFonts[1] = tr(allFonts[1]);
+ allFonts[2] = tr(allFonts[2]);
+ allFonts[3] = tr(allFonts[3]);
+
+ Set();
+}
+
+cMenuSetupFonts::~cMenuSetupFonts(void)
+{
+}
+
+eOSState cMenuSetupFonts::ProcessKey(eKeys Key)
+{
+ eOSState state = cMenuSetupSubMenu::ProcessKey(Key);
+
+#ifdef HAVE_FREETYPE
+ if (state == osUnknown && Key == kBlue && data->allFonts[Current()].VdrId == FONT_TRUETYPE) {
+ state = AddSubMenu(new cMenuSetupTTF(&data->allFonts[Current()]));
+ } else {
+ if (!HasSubMenu() && data->allFonts[Current()].VdrId == FONT_TRUETYPE)
+ SetHelp(NULL, NULL, NULL, tr("Button$Set"));
+ else
+ SetHelp(NULL, NULL, NULL, NULL);
+ }
+#endif
+
+ return state;
+}
+
+void cMenuSetupFonts::Set(void)
+{
+ int current = Current();
+ Clear();
+
+ int numAvailFonts = sizeof(allFonts)/sizeof(char*);
+ Add(new cMenuEditStraItem(tr("OSD title"), &data->allFonts[FONT_OSDTITLE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Messages"), &data->allFonts[FONT_MESSAGE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Date"), &data->allFonts[FONT_DATE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Help keys"), &data->allFonts[FONT_HELPKEYS].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Channelinfo: title"), &data->allFonts[FONT_CITITLE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Channelinfo: subtitle"), &data->allFonts[FONT_CISUBTITLE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Channelinfo: language"), &data->allFonts[FONT_CILANGUAGE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("List items"), &data->allFonts[FONT_LISTITEM].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Info area: timers title"), &data->allFonts[FONT_INFOTIMERHEADLINE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Info area: timers text"), &data->allFonts[FONT_INFOTIMERTEXT].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Info area: warning title"), &data->allFonts[FONT_INFOWARNHEADLINE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Info area: warning text"), &data->allFonts[FONT_INFOWARNTEXT].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Details: title"), &data->allFonts[FONT_DETAILSTITLE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Details: subtitle"), &data->allFonts[FONT_DETAILSSUBTITLE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Details: date"), &data->allFonts[FONT_DETAILSDATE].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Details: text"), &data->allFonts[FONT_DETAILSTEXT].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Replay: times"), &data->allFonts[FONT_REPLAYTIMES].VdrId, numAvailFonts, allFonts));
+ Add(new cMenuEditStraItem(tr("Fixed Font"), &data->allFonts[FONT_FIXED].VdrId, numAvailFonts, allFonts));
+
+ SetCurrent(Get(current));
+ Display();
+ if (data->allFonts[Current()].VdrId == FONT_TRUETYPE)
+ SetHelp(NULL, NULL, NULL, tr("Button$Set"));
+ else
+ SetHelp(NULL, NULL, NULL, NULL);
+}
+
+#ifdef SKINENIGMA_HAVE_EPGSEARCH
+// Setup: EpgSearch
+cMenuSetupEpgSearch::cMenuSetupEpgSearch(cEnigmaConfig* Data) : cMenuSetupSubMenu(tr("General"), Data)
+{
+ useSubtitleRerunTexts[0] = tr("never");
+ useSubtitleRerunTexts[1] = tr("if exists");
+ useSubtitleRerunTexts[2] = tr("always");
+
+ Set();
+}
+
+eOSState cMenuSetupEpgSearch::ProcessKey(eKeys Key)
+{
+ return cMenuSetupSubMenu::ProcessKey(Key);
+}
+
+void cMenuSetupEpgSearch::Set(void)
+{
+ int current = Current();
+ Clear();
+
+ Add(new cMenuEditIntItem(tr("Number of Reruns"), &data->numReruns, 0, 10));
+ Add(new cMenuEditStraItem(tr("Use Subtitle for reruns"), &data->useSubtitleRerun, 3, useSubtitleRerunTexts));
+ if (data->showInfo) {
+ Add(new cMenuEditBoolItem(tr("Show timer conflicts"), &data->showTimerConflicts));
+ }
+
+ SetCurrent(Get(current));
+ Display();
+ SetHelp(NULL, NULL, NULL, NULL);
+}
+#endif
+// vim:et:sw=2:ts=2:
diff --git a/setup.h b/setup.h
new file mode 100644
index 0000000..de4f019
--- /dev/null
+++ b/setup.h
@@ -0,0 +1,111 @@
+/*
+ * setup.h: 'EnigmaNG' skin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "common.h"
+#include "config.h"
+#include <vdr/plugin.h>
+
+class cPluginSkinEnigmaSetup : public cMenuSetupPage {
+private:
+ cEnigmaConfig data;
+
+ virtual void Setup(void);
+ void AddCategory(const char *Title);
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ virtual void Store(void);
+public:
+ cPluginSkinEnigmaSetup(void);
+};
+
+class cMenuSetupSubMenu : public cOsdMenu {
+protected:
+ cEnigmaConfig *data;
+ virtual eOSState ProcessKey(eKeys Key);
+ virtual void Set(void) = 0;
+public:
+ cMenuSetupSubMenu(const char *Title, cEnigmaConfig *Data);
+};
+
+class cMenuSetupGeneral : public cMenuSetupSubMenu {
+private:
+ const char *showRemainingTexts[3];
+ const char *showRecSizeTexts[3];
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ void Set(void);
+public:
+ cMenuSetupGeneral(cEnigmaConfig *Data);
+};
+
+class cMenuSetupLogos : public cMenuSetupSubMenu {
+private:
+ const char *showSymbolsTexts[4];
+ const char *resizeImagesTexts[3];
+#ifdef USE_PLUGIN_MAILBOX
+ const char *showMailIconTexts[3];
+#endif
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ void Set(void);
+public:
+ cMenuSetupLogos(cEnigmaConfig *Data);
+};
+
+#ifndef DISABLE_ANIMATED_TEXT
+class cMenuSetupAnimText : public cMenuSetupSubMenu {
+private:
+ const char *scrollModeTexts[2];
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ void Set(void);
+public:
+ cMenuSetupAnimText(cEnigmaConfig *Data);
+};
+#endif
+
+#ifdef HAVE_FREETYPE
+class cMenuSetupTTF : public cOsdMenu {
+private:
+ FontInfo *data;
+ int nFont;
+ int nWidth;
+ int nSize;
+ const char **availTTFs;
+ int nMaxTTFs;
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ void Set(void);
+ void Store(void);
+public:
+ cMenuSetupTTF(FontInfo *fontinfo);
+};
+
+#endif
+
+class cMenuSetupFonts : public cMenuSetupSubMenu {
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ void Set(void);
+public:
+ cMenuSetupFonts(cEnigmaConfig *Data);
+ virtual ~cMenuSetupFonts(void);
+};
+
+#ifdef SKINENIGMA_HAVE_EPGSEARCH
+class cMenuSetupEpgSearch : public cMenuSetupSubMenu {
+private:
+ const char *useSubtitleRerunTexts[3];
+protected:
+ virtual eOSState ProcessKey(eKeys Key);
+ void Set(void);
+public:
+ cMenuSetupEpgSearch(cEnigmaConfig *Data);
+};
+#endif
+
+// vim:et:sw=2:ts=2:
diff --git a/skinenigmang.c b/skinenigmang.c
index 10ad221..76ee4b4 100644
--- a/skinenigmang.c
+++ b/skinenigmang.c
@@ -1,5 +1,5 @@
/*
- * enigma.c: A plugin for the Video Disk Recorder
+ * skinenigmang.c: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -7,10 +7,12 @@
#include "common.h"
#include "config.h"
+#include "enigma.h"
#include "i18n.h"
#include "logo.h"
-#include "enigma.h"
+#include "setup.h"
#include "status.h"
+
#include <getopt.h>
#include <vdr/plugin.h>
@@ -18,13 +20,16 @@
#error "VDR-1.4.0 API version or greater is required!"
#endif
-static const char VERSION[] = "0.0.4";
+static const char VERSION[] = "0.0.5rc";
static const char DESCRIPTION[] = "EnigmaNG skin";
class cPluginSkinEnigma : public cPlugin {
private:
bool fLogodirSet;
bool fImagesDirSet;
+#ifdef HAVE_FREETYPE
+ bool fFontsDirSet;
+#endif
public:
cPluginSkinEnigma(void);
@@ -56,27 +61,6 @@ public:
virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
};
-class cPluginSkinEnigmaSetup : public cMenuSetupPage {
-private:
- cEnigmaConfig data;
- const char *showSymbolsTexts[4];
- const char *showRemainingTexts[3];
- const char *useSubtitleRerunTexts[3];
- const char *showRecSizeTexts[3];
- const char *resizeImagesTexts[3];
-#ifdef USE_PLUGIN_MAILBOX
- const char *showMailIconTexts[3];
-#endif
-
- virtual void Setup(void);
- void AddCategory(const char *Title);
-protected:
- virtual eOSState ProcessKey(eKeys Key);
- virtual void Store(void);
-public:
- cPluginSkinEnigmaSetup(void);
-};
-
cPluginSkinEnigma::cPluginSkinEnigma(void)
{
// initialize any member variables here.
@@ -84,6 +68,9 @@ cPluginSkinEnigma::cPluginSkinEnigma(void)
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
fLogodirSet = false;
fImagesDirSet = false;
+#ifdef HAVE_FREETYPE
+ fFontsDirSet = false;
+#endif
}
cPluginSkinEnigma::~cPluginSkinEnigma()
@@ -94,7 +81,11 @@ cPluginSkinEnigma::~cPluginSkinEnigma()
const char *cPluginSkinEnigma::CommandLineHelp(void)
{
// return a string that describes all known command line options.
- return " -i <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored\n"
+ return
+#ifdef HAVE_FREETYPE
+ " -f <FONTSDIR>, --fonts=<FONTSDIR> Set directory where truetype fonts are stored\n"
+#endif
+ " -i <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored\n"
" -l <LOGODIR>, --logodir=<LOGODIR> Set directory where logos are stored.\n";
}
@@ -102,14 +93,23 @@ bool cPluginSkinEnigma::ProcessArgs(int argc, char *argv[])
{
// implement command line argument processing here if applicable.
static const struct option long_options[] = {
- { "logodir", required_argument, NULL, 'l' },
+#ifdef HAVE_FREETYPE
+ { "fonts", required_argument, NULL, 'f' },
+#endif
{ "epgimages", required_argument, NULL, 'i' },
+ { "logodir", required_argument, NULL, 'l' },
{ NULL }
};
int c;
- while ((c = getopt_long(argc, argv, "l:i:", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "i:f:l:", long_options, NULL)) != -1) {
switch (c) {
+#ifdef HAVE_FREETYPE
+ case 'f':
+ EnigmaConfig.SetFontsDir(optarg);
+ fFontsDirSet = true;
+ break;
+#endif
case 'i':
EnigmaConfig.SetImagesDir(optarg);
fImagesDirSet = true;
@@ -152,6 +152,19 @@ bool cPluginSkinEnigma::Start(void)
free(dir);
}
}
+#ifdef HAVE_FREETYPE
+ if (!fFontsDirSet) {
+ // set fonts directory
+ char *dir = NULL;
+ asprintf(&dir, "%s/fonts", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
+ if (dir) {
+ EnigmaConfig.SetFontsDir(dir);
+ fFontsDirSet = true;
+ free(dir);
+ }
+ }
+#endif
+
// resize logo cache
EnigmaLogoCache.Resize(EnigmaConfig.cacheSize);
// create skin
@@ -186,59 +199,83 @@ cMenuSetupPage *cPluginSkinEnigma::SetupMenu(void)
bool cPluginSkinEnigma::SetupParse(const char *Name, const char *Value)
{
// parse your own setup parameters and store their values.
- debug("cPluginSkinEnigma::SetupParse()\n");
- if (!strcasecmp(Name, "TrySingleArea"))
- EnigmaConfig.singleArea = atoi(Value);
- else if (!strcasecmp(Name, "SingleArea8Bpp")) {
- EnigmaConfig.singleArea8Bpp = atoi(Value);
- } else if (!strcasecmp(Name, "ShowAuxInfo"))
- EnigmaConfig.showAuxInfo = atoi(Value);
- else if (!strcasecmp(Name, "ShowProgressBar"))
- EnigmaConfig.showProgressbar = atoi(Value);
- else if (!strcasecmp(Name, "ShowRemaining"))
- EnigmaConfig.showRemaining = atoi(Value);
- else if (!strcasecmp(Name, "ShowListSymbols"))
- EnigmaConfig.showListSymbols = atoi(Value);
- else if (!strcasecmp(Name, "ShowSymbols"))
- EnigmaConfig.showSymbols = atoi(Value);
- else if (!strcasecmp(Name, "ShowLogo"))
- EnigmaConfig.showLogo = atoi(Value);
- else if (!strcasecmp(Name, "ShowInfo"))
- EnigmaConfig.showInfo = atoi(Value);
- else if (!strcasecmp(Name, "ShowMarker"))
- EnigmaConfig.showMarker = atoi(Value);
- else if (!strcasecmp(Name, "ShowVPS"))
- EnigmaConfig.showVps = atoi(Value);
- else if (!strcasecmp(Name, "ShowFlags"))
- EnigmaConfig.showFlags = atoi(Value);
- else if (!strcasecmp(Name, "CacheSize"))
- EnigmaConfig.cacheSize = atoi(Value);
- else if (!strcasecmp(Name, "UseChannelId"))
- EnigmaConfig.useChannelId = atoi(Value);
- else if (!strcasecmp(Name, "NumReruns"))
- EnigmaConfig.numReruns = atoi(Value);
- else if (!strcasecmp(Name, "UseSubtitleRerun"))
- EnigmaConfig.useSubtitleRerun = atoi(Value);
- else if (!strcasecmp(Name, "ShowTimerConflicts"))
- EnigmaConfig.showTimerConflicts = atoi(Value);
- else if (!strcasecmp(Name, "ShowRecSize"))
- EnigmaConfig.showRecSize = atoi(Value);
- else if (!strcasecmp(Name, "ShowImages"))
- EnigmaConfig.showImages = atoi(Value);
- else if (!strcasecmp(Name, "ResizeImages"))
- EnigmaConfig.resizeImages = atoi(Value);
- else if (!strcasecmp(Name, "ShowMailIcon"))
- EnigmaConfig.showMailIcon = atoi(Value);
- else if (!strcasecmp(Name, "ImageWidth"))
- EnigmaConfig.imageWidth = atoi(Value);
- else if (!strcasecmp(Name, "ImageHeight"))
- EnigmaConfig.imageHeight = atoi(Value);
- else if (!strcasecmp(Name, "ImageExtension"))
- EnigmaConfig.imageExtension = atoi(Value);
- else if (!strcasecmp(Name, "FullTitleWidth"))
- EnigmaConfig.fullTitleWidth = atoi(Value);
- else
- return false;
+// debug("cPluginSkinEnigma::SetupParse()\n");
+
+ if (!strcasecmp(Name, "SingleArea8Bpp")) EnigmaConfig.singleArea8Bpp = atoi(Value);
+ else if (!strcasecmp(Name, "ShowAuxInfo")) EnigmaConfig.showAuxInfo = atoi(Value);
+ else if (!strcasecmp(Name, "ShowProgressBar")) EnigmaConfig.showProgressbar = atoi(Value);
+ else if (!strcasecmp(Name, "ShowRemaining")) EnigmaConfig.showRemaining = atoi(Value);
+ else if (!strcasecmp(Name, "ShowListSymbols")) EnigmaConfig.showListSymbols = atoi(Value);
+ else if (!strcasecmp(Name, "ShowSymbols")) EnigmaConfig.showSymbols = atoi(Value);
+ else if (!strcasecmp(Name, "ShowSymbolsMenu")) EnigmaConfig.showSymbolsMenu = atoi(Value);
+ else if (!strcasecmp(Name, "ShowSymbolsReplay")) EnigmaConfig.showSymbolsReplay = atoi(Value);
+ else if (!strcasecmp(Name, "ShowSymbolsMsgs")) EnigmaConfig.showSymbolsMsgs = atoi(Value);
+ else if (!strcasecmp(Name, "ShowSymbolsAudio")) EnigmaConfig.showSymbolsAudio = atoi(Value);
+ else if (!strcasecmp(Name, "ShowLogo")) EnigmaConfig.showLogo = atoi(Value);
+ else if (!strcasecmp(Name, "ShowInfo")) EnigmaConfig.showInfo = atoi(Value);
+ else if (!strcasecmp(Name, "ShowMarker")) EnigmaConfig.showMarker = atoi(Value);
+ else if (!strcasecmp(Name, "ShowVPS")) EnigmaConfig.showVps = atoi(Value);
+ else if (!strcasecmp(Name, "ShowFlags")) EnigmaConfig.showFlags = atoi(Value);
+ else if (!strcasecmp(Name, "CacheSize")) EnigmaConfig.cacheSize = atoi(Value);
+ else if (!strcasecmp(Name, "UseChannelId")) EnigmaConfig.useChannelId = atoi(Value);
+ else if (!strcasecmp(Name, "NumReruns")) EnigmaConfig.numReruns = atoi(Value);
+ else if (!strcasecmp(Name, "UseSubtitleRerun")) EnigmaConfig.useSubtitleRerun = atoi(Value);
+ else if (!strcasecmp(Name, "ShowTimerConflicts")) EnigmaConfig.showTimerConflicts = atoi(Value);
+ else if (!strcasecmp(Name, "ShowRecSize")) EnigmaConfig.showRecSize = atoi(Value);
+ else if (!strcasecmp(Name, "ShowImages")) EnigmaConfig.showImages = atoi(Value);
+ else if (!strcasecmp(Name, "ResizeImages")) EnigmaConfig.resizeImages = atoi(Value);
+ else if (!strcasecmp(Name, "ShowMailIcon")) EnigmaConfig.showMailIcon = atoi(Value);
+ else if (!strcasecmp(Name, "ImageWidth")) EnigmaConfig.imageWidth = atoi(Value);
+ else if (!strcasecmp(Name, "ImageHeight")) EnigmaConfig.imageHeight = atoi(Value);
+ else if (!strcasecmp(Name, "ImageExtension")) EnigmaConfig.imageExtension = atoi(Value);
+ else if (!strcasecmp(Name, "FullTitleWidth")) EnigmaConfig.fullTitleWidth = atoi(Value);
+ else if (!strcasecmp(Name, "UseTextEffects")) EnigmaConfig.useTextEffects = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollDelay")) EnigmaConfig.scrollDelay = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollPause")) EnigmaConfig.scrollPause = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollMode")) EnigmaConfig.scrollMode = atoi(Value);
+ else if (!strcasecmp(Name, "BlinkPause")) EnigmaConfig.blinkPause = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollInfo")) EnigmaConfig.scrollInfo = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollListItem")) EnigmaConfig.scrollListItem = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollOther")) EnigmaConfig.scrollOther = atoi(Value);
+ else if (!strcasecmp(Name, "ScrollTitle")) EnigmaConfig.scrollTitle = atoi(Value);
+ else if (!strcasecmp(Name, "FontOsdTitle")) EnigmaConfig.SetFont(FONT_OSDTITLE, atoi(Value));
+ else if (!strcasecmp(Name, "FontOsdTitleName")) EnigmaConfig.SetFont(FONT_OSDTITLE, Value);
+ else if (!strcasecmp(Name, "FontMessage")) EnigmaConfig.SetFont(FONT_MESSAGE, atoi(Value));
+ else if (!strcasecmp(Name, "FontMessageName")) EnigmaConfig.SetFont(FONT_MESSAGE, Value);
+ else if (!strcasecmp(Name, "FontDate")) EnigmaConfig.SetFont(FONT_DATE, atoi(Value));
+ else if (!strcasecmp(Name, "FontDateName")) EnigmaConfig.SetFont(FONT_DATE, Value);
+ else if (!strcasecmp(Name, "FontHelpKeys")) EnigmaConfig.SetFont(FONT_HELPKEYS, atoi(Value));
+ else if (!strcasecmp(Name, "FontHelpKeysName")) EnigmaConfig.SetFont(FONT_HELPKEYS, Value);
+ else if (!strcasecmp(Name, "FontCiTitle")) EnigmaConfig.SetFont(FONT_CITITLE, atoi(Value));
+ else if (!strcasecmp(Name, "FontCiTitleName")) EnigmaConfig.SetFont(FONT_CITITLE, Value);
+ else if (!strcasecmp(Name, "FontCiSubtitle")) EnigmaConfig.SetFont(FONT_CISUBTITLE, atoi(Value));
+ else if (!strcasecmp(Name, "FontCiSubtitleName")) EnigmaConfig.SetFont(FONT_CISUBTITLE, Value);
+ else if (!strcasecmp(Name, "FontCiLanguage")) EnigmaConfig.SetFont(FONT_CILANGUAGE, atoi(Value));
+ else if (!strcasecmp(Name, "FontCiLanguageName")) EnigmaConfig.SetFont(FONT_CILANGUAGE, Value);
+ else if (!strcasecmp(Name, "FontListItem")) EnigmaConfig.SetFont(FONT_LISTITEM, atoi(Value));
+ else if (!strcasecmp(Name, "FontListItemName")) EnigmaConfig.SetFont(FONT_LISTITEM, Value);
+ else if (!strcasecmp(Name, "FontInfoTimerHeadline")) EnigmaConfig.SetFont(FONT_INFOTIMERHEADLINE, atoi(Value));
+ else if (!strcasecmp(Name, "FontInfoTimerHeadlineName")) EnigmaConfig.SetFont(FONT_INFOTIMERHEADLINE, Value);
+ else if (!strcasecmp(Name, "FontInfoTimerText")) EnigmaConfig.SetFont(FONT_INFOTIMERTEXT, atoi(Value));
+ else if (!strcasecmp(Name, "FontInfoTimerTextName")) EnigmaConfig.SetFont(FONT_INFOTIMERTEXT, Value);
+ else if (!strcasecmp(Name, "FontInfoWarnHeadline")) EnigmaConfig.SetFont(FONT_INFOWARNHEADLINE, atoi(Value));
+ else if (!strcasecmp(Name, "FontInfoWarnHeadlineName")) EnigmaConfig.SetFont(FONT_INFOWARNHEADLINE, Value);
+ else if (!strcasecmp(Name, "FontInfoWarnText")) EnigmaConfig.SetFont(FONT_INFOWARNTEXT, atoi(Value));
+ else if (!strcasecmp(Name, "FontInfoWarnTextName")) EnigmaConfig.SetFont(FONT_INFOWARNTEXT, Value);
+ else if (!strcasecmp(Name, "FontDetailsTitle")) EnigmaConfig.SetFont(FONT_DETAILSTITLE, atoi(Value));
+ else if (!strcasecmp(Name, "FontDetailsTitleName")) EnigmaConfig.SetFont(FONT_DETAILSTITLE, Value);
+ else if (!strcasecmp(Name, "FontDetailsSubtitle")) EnigmaConfig.SetFont(FONT_DETAILSSUBTITLE, atoi(Value));
+ else if (!strcasecmp(Name, "FontDetailsSubtitleName")) EnigmaConfig.SetFont(FONT_DETAILSSUBTITLE, Value);
+ else if (!strcasecmp(Name, "FontDetailsDate")) EnigmaConfig.SetFont(FONT_DETAILSDATE, atoi(Value));
+ else if (!strcasecmp(Name, "FontDetailsDateName")) EnigmaConfig.SetFont(FONT_DETAILSDATE, Value);
+ else if (!strcasecmp(Name, "FontDetailsText")) EnigmaConfig.SetFont(FONT_DETAILSTEXT, atoi(Value));
+ else if (!strcasecmp(Name, "FontDetailsTextName")) EnigmaConfig.SetFont(FONT_DETAILSTEXT, Value);
+ else if (!strcasecmp(Name, "FontReplayTimes")) EnigmaConfig.SetFont(FONT_REPLAYTIMES, atoi(Value));
+ else if (!strcasecmp(Name, "FontReplayTimesName")) EnigmaConfig.SetFont(FONT_REPLAYTIMES, Value);
+ else if (!strcasecmp(Name, "FontFixed")) EnigmaConfig.SetFont(FONT_FIXED, atoi(Value));
+ else if (!strcasecmp(Name, "FontFixedName")) EnigmaConfig.SetFont(FONT_FIXED, Value);
+ else if (!strcasecmp(Name, "DynOSD")) EnigmaConfig.dynOsd = atoi(Value);
+ else return false;
return true;
}
@@ -261,227 +298,5 @@ cString cPluginSkinEnigma::SVDRPCommand(const char *Command, const char *Option,
return NULL;
}
-cPluginSkinEnigmaSetup::cPluginSkinEnigmaSetup(void)
-{
- // create setup menu
- debug("cPluginSkinEnigmaSetup()\n");
- data = EnigmaConfig;
- Setup();
- SetHelp(tr("Button$Flush cache"), NULL, NULL, NULL);
-}
-
-void cPluginSkinEnigmaSetup::AddCategory(const char *Title) {
- char *buffer = NULL;
-
- asprintf(&buffer, "--- %s ----------------------------------------------------------------------------------", Title );
-
- cOsdItem *item = new cOsdItem(buffer);
- free(buffer);
-
- if (item) {
- item->SetSelectable(false);
- Add(item);
- }
-}
-
-void cPluginSkinEnigmaSetup::Setup(void)
-{
- // update setup display
- int current = Current();
-
- Clear();
-
- showSymbolsTexts[0] = tr("never");
- showSymbolsTexts[1] = tr("always");
-#ifndef SKINENIGMA_NO_MENULOGO
-#define NUM_SHOWSYMBOLSTEXTS 4
- showSymbolsTexts[2] = tr("not in menu");
- showSymbolsTexts[3] = tr("only in menu");
-#else
-#define NUM_SHOWSYMBOLSTEXTS 2
-#endif
-
- showRemainingTexts[0] = tr("elapsed");
- showRemainingTexts[1] = tr("remaining");
- showRemainingTexts[2] = tr("percent");
-
- useSubtitleRerunTexts[0] = tr("never");
- useSubtitleRerunTexts[1] = tr("if exists");
- useSubtitleRerunTexts[2] = tr("always");
-
- showRecSizeTexts[0] = tr("never");
- showRecSizeTexts[1] = tr("use size.vdr only");
- showRecSizeTexts[2] = tr("always");
-
-#ifndef SKINENIGMA_NO_MENULOGO
- resizeImagesTexts[0] = tr("pixel algo");
- resizeImagesTexts[1] = tr("ratio algo");
- resizeImagesTexts[2] = tr("zoom image");
-#endif
-
-#ifdef USE_PLUGIN_MAILBOX
- showMailIconTexts[0] = tr("never");
- showMailIconTexts[1] = tr("only if new mail present");
- showMailIconTexts[2] = tr("always");
-#endif
-
- Add(new cMenuEditBoolItem(tr("One area (if possible)"), &data.singleArea,
- tr("no"), tr("yes")));
- if (data.singleArea) {
- Add(new cMenuEditBoolItem(tr("Bpp in single area"), &data.singleArea8Bpp,
- "4", "8"));
- }
- Add(new cMenuEditBoolItem(tr("Show info area in main menu"), &data.showInfo,
- tr("no"), tr("yes")));
- Add(new cMenuEditBoolItem(tr("Show auxiliary information"), &data.showAuxInfo,
- tr("top"), tr("bottom")));
- Add(new cMenuEditStraItem(tr("Show recording's size"), &data.showRecSize,
- 3, showRecSizeTexts));
- Add(new cMenuEditBoolItem(tr("Full title width"), &data.fullTitleWidth,
- tr("no"), tr("yes")));
- Add(new cMenuEditStraItem(tr("Show remaining/elapsed time"), &data.showRemaining,
- 3, showRemainingTexts));
- Add(new cMenuEditBoolItem(tr("Show VPS"), &data.showVps,
- tr("no"), tr("yes")));
- Add(new cMenuEditBoolItem(tr("Show progressbar"), &data.showProgressbar,
- tr("no"), tr("yes")));
-
- AddCategory(tr("Logos & Symbols"));
- if (!data.singleArea || data.singleArea8Bpp) {
- Add(new cMenuEditStraItem(tr("Show symbols"), &data.showSymbols,
- NUM_SHOWSYMBOLSTEXTS, showSymbolsTexts));
- }
- Add(new cMenuEditBoolItem(tr("Show symbols in lists"), &data.showListSymbols,
- tr("no"), tr("yes")));
- Add(new cMenuEditBoolItem(tr("Show marker in lists"), &data.showMarker,
- tr("no"), tr("yes")));
- if (!data.singleArea || data.singleArea8Bpp) {
- Add(new cMenuEditBoolItem(tr("Show flags"), &data.showFlags,
- tr("no"), tr("yes")));
- }
-
-#ifdef USE_PLUGIN_MAILBOX
- cPlugin *MailBoxPlugin = cPluginManager::GetPlugin("mailbox");
- if (MailBoxPlugin && MailBoxPlugin->Service("MailBox-HasNewMail-1.0", 0)) {
- Add(new cMenuEditStraItem(tr("Show mail icon"), &data.showMailIcon,
- 3, showMailIconTexts));
- }
-#endif
-
-#ifndef SKINENIGMA_NO_MENULOGO
- if ((!data.singleArea || data.singleArea8Bpp) && (data.showSymbols == 1 || data.showSymbols == 3)) {
- Add(new cMenuEditBoolItem(tr("Show event/recording images"), &data.showImages,
- tr("no"), tr("yes")));
- if (data.showImages) {
-#ifdef HAVE_IMAGEMAGICK
- Add(new cMenuEditStraItem(tr("Resize images"), &data.resizeImages,
- 3, resizeImagesTexts));
-#endif
- Add(new cMenuEditIntItem(tr("Image width" ), &data.imageWidth,
- 80, 180));
- Add(new cMenuEditIntItem(tr("Image height" ), &data.imageHeight,
- 80, 144));
-#ifdef HAVE_IMAGEMAGICK
- Add(new cMenuEditStraItem(tr("Image format"), &data.imageExtension,
- 3, imageExtensionTexts));
-#endif
- }
- }
-#endif //SKINENIGMA_NO_MENULOGO
-
- if (!data.singleArea || data.singleArea8Bpp) {
- Add(new cMenuEditBoolItem(tr("Show channel logos"), &data.showLogo,
- tr("no"), tr("yes")));
- if (data.showLogo) {
- Add(new cMenuEditBoolItem(tr("Identify channel by"), &data.useChannelId,
- tr("name"), tr("data")));
- }
- if (data.showLogo || data.showSymbols) {
- Add(new cMenuEditIntItem(tr("Channel logo cache size"), &data.cacheSize,
- 0, 1000));
- }
- }
-
-#ifdef SKINENIGMA_HAVE_EPGSEARCH
- AddCategory(tr("EPGSearch"));
- Add(new cMenuEditIntItem(tr("Number of Reruns"), &data.numReruns,
- 0, 10));
- Add(new cMenuEditStraItem(tr("Use Subtitle for reruns"), &data.useSubtitleRerun,
- 3, useSubtitleRerunTexts));
- if (data.showInfo) {
- Add(new cMenuEditBoolItem(tr("Show timer conflicts"), &data.showTimerConflicts,
- tr("no"), tr("yes")));
- }
-#endif
-
- SetCurrent(Get(current));
- Display();
-}
-
-void cPluginSkinEnigmaSetup::Store(void)
-{
- // store setup data
- debug("cPluginSkinEnigmaSetup::Store()\n");
- EnigmaConfig = data;
- SetupStore("TrySingleArea", EnigmaConfig.singleArea);
- SetupStore("SingleArea8Bpp", EnigmaConfig.singleArea8Bpp);
- SetupStore("ShowAuxInfo", EnigmaConfig.showAuxInfo);
- SetupStore("ShowRemaining", EnigmaConfig.showRemaining);
- SetupStore("ShowProgressBar", EnigmaConfig.showProgressbar);
- SetupStore("ShowListSymbols", EnigmaConfig.showListSymbols);
- SetupStore("ShowSymbols", EnigmaConfig.showSymbols);
- SetupStore("ShowLogo", EnigmaConfig.showLogo);
- SetupStore("ShowInfo", EnigmaConfig.showInfo);
- SetupStore("ShowVPS", EnigmaConfig.showVps);
- SetupStore("ShowFlags", EnigmaConfig.showFlags);
- SetupStore("ShowMarker", EnigmaConfig.showMarker);
- SetupStore("CacheSize", EnigmaConfig.cacheSize);
- SetupStore("UseChannelId", EnigmaConfig.useChannelId);
- SetupStore("NumReruns", EnigmaConfig.numReruns);
- SetupStore("UseSubtitleRerun", EnigmaConfig.useSubtitleRerun);
- SetupStore("ShowTimerConflicts", EnigmaConfig.showTimerConflicts);
- SetupStore("ShowRecSize", EnigmaConfig.showRecSize);
- SetupStore("ShowImages", EnigmaConfig.showImages);
- SetupStore("ResizeImages", EnigmaConfig.resizeImages);
- SetupStore("ShowMailIcon", EnigmaConfig.showMailIcon);
- SetupStore("ImageWidth", EnigmaConfig.imageWidth);
- SetupStore("ImageHeight", EnigmaConfig.imageHeight);
- SetupStore("ImageExtension", EnigmaConfig.imageExtension);
- SetupStore("FullTitleWidth", EnigmaConfig.fullTitleWidth);
- // resize logo cache
- EnigmaLogoCache.Resize(EnigmaConfig.cacheSize);
-}
-
-eOSState cPluginSkinEnigmaSetup::ProcessKey(eKeys Key)
-{
- // process key presses
- int oldShowLogo = data.showLogo;
- int oldShowSymbols = data.showSymbols;
- int oldSingleArea = data.singleArea;
- int oldSingleArea8Bpp = data.singleArea8Bpp;
- int oldShowInfo = data.showInfo;
- int oldShowImages = data.showImages;
-
- eOSState state = cMenuSetupPage::ProcessKey(Key);
- if ((state == osUnknown) && (Key == kRed)) {
- Skins.Message(mtInfo, tr("Flushing channel logo cache..."));
- EnigmaLogoCache.Flush();
- Skins.Message(mtInfo, NULL);
- state = osContinue;
- }
- if (Key != kNone &&
- ((data.singleArea != oldSingleArea)
- || (data.singleArea8Bpp != oldSingleArea8Bpp)
- || (data.showLogo != oldShowLogo)
- || (data.showSymbols != oldShowSymbols)
- || (oldShowInfo != data.showInfo)
- || (oldShowImages != data.showImages)
- )) {
- Setup();
- }
-
- return state;
-}
-
VDRPLUGINCREATOR(cPluginSkinEnigma); // don't touch this!
// vim:et:sw=2:ts=2:
diff --git a/status.c b/status.c
index 749aea2..622d8d9 100644
--- a/status.c
+++ b/status.c
@@ -1,5 +1,5 @@
/*
- * status.c: The 'EnigmaNG' VDR skin.
+ * status.c: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -7,6 +7,7 @@
#include "common.h"
#include "status.h"
+
#include <vdr/timers.h>
#include <vdr/plugin.h>
#include <vdr/menu.h>
@@ -114,3 +115,4 @@ void cEnigmaStatus::UpdateActiveTimers(void)
Timers.DecBeingEdited();
mTimers.Sort();
}
+// vim:et:sw=2:ts=2:
diff --git a/status.h b/status.h
index 9a6ad2a..7c2eb5c 100644
--- a/status.h
+++ b/status.h
@@ -1,5 +1,5 @@
/*
- * status.h: The 'EnigmaNG' VDR skin.
+ * status.h: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -9,6 +9,7 @@
#define __SKINENIGMA_STATUS_H
#include "common.h"
+
#include <vdr/status.h>
extern const char *ReplayNames[7];
@@ -85,3 +86,4 @@ public:
extern cEnigmaStatus EnigmaStatus;
#endif // __SKINENIGMA_STATUS_H
+// vim:et:sw=2:ts=2:
diff --git a/texteffects.c b/texteffects.c
new file mode 100644
index 0000000..59b4e9c
--- /dev/null
+++ b/texteffects.c
@@ -0,0 +1,447 @@
+#include "common.h"
+#include "config.h"
+#include "texteffects.h"
+#include "tools.h"
+
+#include <algorithm>
+
+#ifndef DISABLE_ANIMATED_TEXT
+//Redefine macros
+#undef TE_LOCK
+#define TE_LOCK UpdateLock()
+#undef TE_UNLOCK
+#define TE_UNLOCK UpdateUnlock()
+#endif
+
+#ifdef HAVE_FREETYPE
+// needed for case-insensitive sort of vector (for fonts)
+struct NoCase {
+ bool operator()(const string& x, const string& y) {
+ string lv(x);
+ string rv(y);
+ lcase(lv);
+ lcase(rv);
+ return lv < rv;
+ }
+
+ void lcase(string& s) {
+ int n = s.size();
+ for(int i = 0; i < n; i++)
+ s[i] = tolower(s[i]);
+ }
+};
+#endif
+
+
+#ifdef DISABLE_ANIMATED_TEXT
+cEnigmaTextEffects EnigmaTextEffects;
+#else
+cEnigmaTextEffects EnigmaTextEffects("EnigmaNG effects");
+#endif
+
+#ifdef DISABLE_ANIMATED_TEXT
+cEnigmaTextEffects::cEnigmaTextEffects(void) : osd(NULL)
+#else
+cEnigmaTextEffects::cEnigmaTextEffects(const char *Description) : cThread(Description), osd(NULL), condSleep(), mutexSleep(), mutexRunning()
+#endif
+{
+// SetPriority(19);
+
+#ifdef HAVE_FREETYPE
+ availTTFs = NULL;
+ nMaxTTFs = 0;
+#endif
+}
+
+cEnigmaTextEffects::~cEnigmaTextEffects(void)
+{
+#ifndef DISABLE_ANIMATED_TEXT
+//TODO? Stop();
+#endif
+
+#ifdef HAVE_FREETYPE
+ if (availTTFs) {
+ char **ptr = availTTFs;
+ while (*ptr) {
+ delete(*ptr);
+ ptr++;
+ }
+ free(availTTFs);
+ availTTFs = NULL;
+ }
+#endif
+}
+
+#ifndef DISABLE_ANIMATED_TEXT
+void cEnigmaTextEffects::Action(void)
+{
+ mutexRunning.Lock();
+ mutexSleep.Lock();
+
+ debug("cEnigmaTextEffects::Action() %p\n", pthread_self());
+
+ while (EnigmaConfig.useTextEffects && osd) {
+ uint64_t nNow = cTimeMs::Now();
+ int nSleepMs = 0;
+
+ TE_LOCK; //This causes an initial wait until thet first Flush() is called (which TE_UNKOCKs)
+ for (tEffects::iterator effect = vecEffects.begin(); (effect != vecEffects.end()) && osd; effect++) {
+ tEffect *e = (*effect);
+ if (e == NULL)
+ continue;
+
+ if (e->nNextUpdate == 0) {
+ e->nNextUpdate = nNow + (e->nAction == 0 ? EnigmaConfig.scrollPause : EnigmaConfig.blinkPause);
+ } else if(nNow >= e->nNextUpdate) {
+ DoEffect(e, nNow);
+ }
+
+// printf("NOW=%llu NEXT=%llu DIFF=%d SLEEP=%d\n", nNow, e->nNextUpdate, (int)(e->nNextUpdate - nNow), nSleepMs);
+ int nDiff = max(3, (int)(e->nNextUpdate - nNow));
+ if (nSleepMs == 0 || nDiff < nSleepMs)
+ nSleepMs = nDiff;
+ }
+
+ if (osd)
+ osd->Flush();
+ TE_UNLOCK;
+
+ if (osd) {
+// printf("SLEEP1: %d, %p\n", nSleepMs, pthread_self());
+ if (nSleepMs)
+ condSleep.TimedWait(mutexSleep, nSleepMs);
+ else
+ condSleep.TimedWait(mutexSleep, EnigmaConfig.scrollPause); //TODO
+// printf("SLEEP2: %d, %p\n", nSleepMs, pthread_self());
+ }
+ }
+
+ mutexSleep.Unlock();
+ mutexRunning.Unlock();
+}
+
+void cEnigmaTextEffects::DoEffect(tEffect *e, uint64_t nNow)
+{
+ bool fDrawItem = ((yMessageTop == 0) || (e->y + e->Height < yMessageTop));
+
+ switch (e->nAction) {
+ case 0: // Scroll
+ DoScroll(e, nNow, fDrawItem);
+ break;
+
+ case 1: // Blink
+ DoBlink(e, nNow, fDrawItem);
+ break;
+ }
+}
+
+void cEnigmaTextEffects::DoScroll(tEffect *e, uint64_t nNow, bool fDrawItem)
+{
+// debug("cEnigmaTextEffects::DoScroll()\n");
+ if (e->Font->Width(e->strText.c_str()) <= e->Width) {
+ if (fDrawItem) {
+ if (e->Skin)
+ e->Skin->DrawTitle(e->strText.c_str());
+ else
+ osd->DrawText(e->x, e->y, e->strText.c_str(), e->ColorFg, e->ColorBg, e->Font, e->Width, e->Height, e->Alignment);
+ }
+
+ if (nNow)
+ e->nNextUpdate = nNow + EnigmaConfig.scrollPause;
+ return;
+ }
+
+ if (nNow) {
+ int nDelay = EnigmaConfig.scrollDelay;
+ if (fDrawItem) {
+ switch (e->nDirection) {
+ case 0: // Scroll from left to right
+ if (e->Font->Width(e->strText.c_str() + e->nOffset) <= e->Width) {
+ if (EnigmaConfig.scrollMode)
+ e->nDirection = 2;
+ else
+ e->nDirection = 1;
+ nDelay = EnigmaConfig.scrollPause;
+ } else if (e->nOffset < e->strText.length())
+ e->nOffset++;
+ break;
+
+ case 1: // Scroll from right to left
+ if (e->nOffset > 0)
+ e->nOffset--;
+ if (e->nOffset <= 0) {
+ e->nDirection = false;
+ nDelay = EnigmaConfig.scrollPause;
+ }
+ break;
+
+ case 2: // Restart scrolling from the left
+ nDelay = EnigmaConfig.scrollPause;
+ e->nOffset = 0;
+ e->nDirection = 0;
+ break;
+ }
+ }
+ e->nNextUpdate = nNow + nDelay;
+ }
+
+ if (fDrawItem) {
+// printf("SCROLL: %d %d %d/%d (%s) %d %lu %lu\n", e->nOffset, e->nDirection, e->Font->Width(e->strText.c_str() + e->nOffset), e->Width, e->strText.c_str() + e->nOffset, e->strText.length(), nNow, e->nNextUpdate);
+ if (e->Skin)
+ e->Skin->DrawTitle(e->strText.c_str() + e->nOffset);
+ else
+ osd->DrawText(e->x, e->y, e->strText.c_str() + e->nOffset, e->ColorFg, e->ColorBg, e->Font, e->Width, e->Height);
+ }
+}
+
+void cEnigmaTextEffects::DoBlink(tEffect *e, uint64_t nNow, bool fDrawItem)
+{
+// debug("cEnigmaTextEffects::DoBlink()\n");
+ if (fDrawItem) {
+ if (nNow) {
+ e->nDirection = (e->nDirection == 0 ? 1 : 0);
+ e->nNextUpdate = nNow + EnigmaConfig.blinkPause;
+ }
+ if (e->nDirection == 1)
+ osd->DrawText(e->x, e->y, e->strText.c_str() + e->nOffset, e->ColorFg, e->ColorBg, e->Font, e->Width, e->Height, e->Alignment);
+ else
+ osd->DrawText(e->x, e->y, e->strText.c_str() + e->nOffset, e->ColorBg, e->ColorBg, e->Font, e->Width, e->Height, e->Alignment);
+ } else {
+ e->nNextUpdate = nNow + EnigmaConfig.blinkPause;
+ }
+}
+
+bool cEnigmaTextEffects::Start(cOsd *o)
+{
+ osd = o;
+
+ if (!EnigmaConfig.useTextEffects)
+ return false;
+
+ debug("cEnigmaTextEffects::Start(%p) %p\n", osd, pthread_self());
+
+ if (osd == NULL)
+ return false;
+
+ if (Running()) {
+ error("cEnigmaTextEffects::Start - already running\n");
+ return false; //TODO? maybe Cancel()
+ }
+
+ yMessageTop = 0;
+
+ TE_LOCK;
+ return cThread::Start();
+}
+
+void cEnigmaTextEffects::Stop(void)
+{
+ //Must be TE_LOCKed by caller (calls TE_UNLOCK)
+
+ debug("cEnigmaTextEffects::Stop()\n");
+ osd = NULL;
+ Clear();
+ TE_UNLOCK;
+ Wakeup(); // break sleeping Action() thread
+ mutexRunning.Lock(); // Wait for Action() to finish
+ mutexRunning.Unlock();
+}
+
+void cEnigmaTextEffects::Clear(void)
+{
+ debug("cEnigmaTextEffects::Clear()\n");
+
+ //Must be TE_LOCKed by caller
+
+ for (tEffects::iterator effect = vecEffects.begin(); effect != vecEffects.end(); effect++) {
+ delete(*effect);
+ }
+
+ vecEffects.clear();
+}
+
+void cEnigmaTextEffects::PauseEffects(int y)
+{
+ debug("cEnigmaTextEffects::PauseEffects(%d)\n", y);
+
+ //Must be TE_LOCKed by caller
+
+ yMessageTop = y;
+}
+
+void cEnigmaTextEffects::ResetText(int i, tColor ColorFg, tColor ColorBg, bool fDraw)
+{
+ debug("cEnigmaTextEffects::ResetText(%d)\n", i);
+
+ //Must be TE_LOCKed by caller
+
+ if (i < 0 || i >= (int)vecEffects.size())
+ return;
+
+ tEffect *e = vecEffects[i];
+ if (e) {
+ if (fDraw && osd)
+ osd->DrawText(e->x, e->y, e->strText.c_str(),
+ ColorFg ? ColorFg : e->ColorFg,
+ ColorBg ? ColorBg : e->ColorBg,
+ e->Font, e->Width, e->Height);
+ delete(e);
+ vecEffects[i] = NULL;
+ }
+}
+
+void cEnigmaTextEffects::UpdateTextWidth(int i, int Width)
+{
+ debug("cEnigmaTextEffects::UpdateTextWidth(%d)\n", i);
+
+ //Must be TE_LOCKed by caller
+
+ if (i < 0 || i >= (int)vecEffects.size())
+ return;
+
+ tEffect *e = vecEffects[i];
+ if (e) {
+ e->Width = Width;
+ }
+}
+
+int cEnigmaTextEffects::DrawAnimatedTitle(int o_id, int action, const char *s, const cFont *Font, int Width, cSkinEnigmaOsd *skin)
+{
+ //Must be TE_LOCKed by caller
+
+ if (Font == NULL || osd == NULL || skin == NULL)
+ return -1;
+
+ debug("cEnigmaTextEffects::DrawAnimatedTitle(%d, %d, %s)\n", o_id, EnigmaConfig.useTextEffects, s);
+
+ if (o_id >= 0) {
+ // Update animated text
+ tEffect *effect = vecEffects[o_id];
+ if (effect) {
+ if (s == NULL)
+ effect->strText = "";
+ else if (strcmp(effect->strText.c_str(), s) != 0) {
+ effect->strText = s;
+ effect->nOffset = 0;
+ effect->nDirection = 0;
+ }
+ DoEffect(effect);
+ return o_id;
+ } else {
+ return -1;
+ }
+ } else {
+ skin->DrawTitle(s);
+ if (EnigmaConfig.useTextEffects && ((Font->Width(s ? s : "") > Width) || (action > 0))) {
+ // New scrolling text
+ tEffect *effect = new tEffect;
+ if (effect == NULL) {
+ return -1;
+ }
+
+ effect->nAction = action;
+ effect->strText = std::string(s ? s : "");
+ effect->Width = Width;
+ effect->Font = Font;
+ effect->Skin = skin;
+ vecEffects.push_back(effect);
+ int id = vecEffects.size() - 1;
+ return id;
+ } else {
+ return -1;
+ }
+ }
+}
+
+int cEnigmaTextEffects::DrawAnimatedText(int o_id, int action, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment)
+{
+ //Must be TE_LOCKed by caller
+
+ if (Font == NULL || osd == NULL)
+ return -1;
+
+ debug("cEnigmaTextEffects::DrawAnimatedText(%d, %d, %s)\n", o_id, EnigmaConfig.useTextEffects, s);
+
+ if (o_id >= 0) {
+ // Update animated text
+ tEffect *effect = vecEffects[o_id];
+ if (effect) {
+ if (s == NULL)
+ effect->strText = "";
+ else if (strcmp(effect->strText.c_str(), s) != 0) {
+ effect->strText = s;
+ effect->nOffset = 0;
+ effect->nDirection = 0;
+ }
+ DoEffect(effect);
+ return o_id;
+ } else {
+ return -1;
+ }
+ } else {
+ if (Height == 0)
+ Height = Font->Height(s);
+ osd->DrawText(x, y, s ? s : "", ColorFg, ColorBg, Font, Width, Height, Alignment);
+ // New animated text
+ tEffect *effect = new tEffect;
+ if (effect == NULL) {
+ return -1;
+ }
+
+ effect->nAction = action;
+ effect->strText = std::string(s ? s : "");
+ effect->x = x;
+ effect->y = y;
+ effect->Width = Width;
+ effect->Height = Height;
+ effect->ColorFg = ColorFg;
+ effect->ColorBg = ColorBg;
+ effect->Font = Font;
+ effect->Alignment = Alignment;
+ vecEffects.push_back(effect);
+ int id = vecEffects.size() - 1;
+ return id;
+ }
+}
+#endif //DISABLE_ANIMATED_TEXT
+
+#ifdef HAVE_FREETYPE
+const char **cEnigmaTextEffects::GetAvailTTFs(void)
+{
+ if (availTTFs == NULL) {
+ std::vector<std::string> vecFonts;
+ cReadDir d(EnigmaConfig.GetFontsDir());
+ struct dirent *e;
+ while ((e = d.Next()) != NULL) {
+ if ((strcmp(e->d_name, ".") != 0) && (strcmp(e->d_name, "..") != 0)) {
+ if (strcmp(e->d_name + strlen(e->d_name) - 4, ".ttf") == 0) {
+ printf("Loading %s\n", e->d_name);
+ vecFonts.push_back(std::string(e->d_name));
+ } else {
+ printf("Ignoring non-font file: %s\n", e->d_name);
+ }
+ }
+ }
+
+ if (vecFonts.size() > 0) {
+ sort(vecFonts.begin(), vecFonts.end(), NoCase());
+ availTTFs = (char **)calloc(vecFonts.size() + 1, sizeof(char*));
+ if (availTTFs) {
+ char **ptr = availTTFs;
+ for (vector<std::string>::iterator i = vecFonts.begin(); i != vecFonts.end(); i++) {
+ if (!(*i).empty()) {
+ *ptr = strdup((*i).c_str());
+ ptr++;
+ nMaxTTFs++;
+ }
+ }
+ }
+ }
+
+ vecFonts.clear();
+ }
+
+ return (const char**)availTTFs;
+}
+#endif
+// vim:et:sw=2:ts=2:
diff --git a/texteffects.h b/texteffects.h
new file mode 100644
index 0000000..eb6dd8a
--- /dev/null
+++ b/texteffects.h
@@ -0,0 +1,148 @@
+/*
+ * status.h: 'EnigmaNG' skin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#ifndef __TEXTEFFECTS_H
+#define __TEXTEFFECTS_H
+
+#include "common.h"
+#include "enigma.h"
+
+#ifndef DISABLE_ANIMATED_TEXT
+#include <vector>
+#endif
+
+#include <vdr/skins.h>
+
+#ifdef DISABLE_ANIMATED_TEXT
+#define TE_START(osd) ;
+#define TE_STOP ;
+#define TE_LOCK ;
+#define TE_UNLOCK ;
+#define TE_WAKEUP ;
+#define TE_MARQUEE(osd, id, x...) osd->DrawText(x)
+#define TE_BLINK(osd, id, x...) osd->DrawText(x)
+#define TE_TITLE(osd, id, s, Font, Width, skin) osd->DrawTitle(s)
+
+#else // !DISABLE_ANIMATED_TEXT
+#include <vdr/thread.h>
+
+#define TE_START(osd) EnigmaTextEffects.Start(osd);
+#define TE_STOP EnigmaTextEffects.Stop();
+#define TE_LOCK EnigmaTextEffects.UpdateLock();
+#define TE_UNLOCK EnigmaTextEffects.UpdateUnlock();
+#define TE_WAKEUP EnigmaTextEffects.RefreshEffects();
+#define TE_MARQUEE(osd, id, x...) EnigmaTextEffects.DrawAnimatedText(id, 0, x)
+#define TE_BLINK(osd, id, x...) EnigmaTextEffects.DrawAnimatedText(id, 1, x)
+#define TE_TITLE(osd, id, x...) EnigmaTextEffects.DrawAnimatedTitle(id, 0, x)
+
+#endif //DISABLE_ANIMATED_TEXT
+
+#ifdef DISABLE_ANIMATED_TEXT
+class cEnigmaTextEffects {
+#else
+class cEnigmaTextEffects : public cThread {
+#endif
+private:
+ cOsd *osd;
+
+#ifdef HAVE_FREETYPE
+ char **availTTFs;
+ int nMaxTTFs;
+#endif
+
+#ifndef DISABLE_ANIMATED_TEXT
+ int yMessageTop;
+
+ struct tEffect {
+ int nAction;
+ uint nOffset;
+ int nDirection;
+ uint64_t nNextUpdate;
+ std::string strText;
+ int x, y, Width, Height;
+ tColor ColorFg, ColorBg;
+ const cFont *Font;
+ int Alignment;
+ cSkinEnigmaOsd *Skin;
+
+ public:
+ tEffect(void) : nAction(0), nOffset(0), nDirection(0),
+ nNextUpdate(0), x(0), y(0), Width(0), Height(0),
+ ColorFg(0), ColorBg(0), Font(NULL), Alignment(taDefault),
+ Skin(NULL)
+ {};
+ };
+
+ typedef std::vector<tEffect*> tEffects;
+ tEffects vecEffects;
+ cCondVar condSleep;
+ cMutex mutexSleep;
+ cMutex mutexRunning;
+
+ void DoEffect(tEffect *e, uint64_t nNow = 0);
+ void DoScroll(tEffect *e, uint64_t nNow, bool fDrawItem);
+ void DoBlink(tEffect *e, uint64_t nNow, bool fDrawItem);
+
+ void Wakeup(void)
+ {
+// printf("WAKE1: %p\n", pthread_self());
+ mutexSleep.Lock();
+ condSleep.Broadcast();
+ mutexSleep.Unlock();
+// printf("WAKE2: %p\n", pthread_self());
+ }
+#endif //DISABLE_ANIMATED_TEXT
+
+public:
+#ifdef DISABLE_ANIMATED_TEXT
+ cEnigmaTextEffects(void);
+ ~cEnigmaTextEffects(void);
+
+#else
+ cEnigmaTextEffects(const char *Description = NULL);
+ ~cEnigmaTextEffects(void);
+
+ virtual void Action(void);
+
+ bool Start(cOsd *o);
+ void Stop(void);
+ void Clear(void);
+
+ void ResetText(int i, tColor ColorFg = 0, tColor ColorBg = 0, bool fDraw = true);
+ void PauseEffects(int y = 0);
+ void UpdateTextWidth(int i, int Width);
+ int DrawAnimatedTitle(int o_id, int action, const char *s, const cFont *Font, int Width, cSkinEnigmaOsd *skin);
+ int DrawAnimatedText(int o_id, int action, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
+
+ void UpdateLock(void)
+ {
+// printf("LOCK1: %p\n", pthread_self());
+ Lock();
+// printf("LOCK2: %p\n", pthread_self());
+ }
+
+ void UpdateUnlock(void)
+ {
+// printf("UNLOCK1: %p\n", pthread_self());
+ Unlock();
+// printf("UNLOCK2: %p\n", pthread_self());
+ }
+
+ void RefreshEffects(void)
+ { Wakeup(); }
+#endif //DISABLE_ANIMATED_TEXT
+
+#ifdef HAVE_FREETYPE
+ int GetNumAvailTTFs(void) { return nMaxTTFs; }
+ const char **GetAvailTTFs(void);
+#endif
+};
+
+extern cEnigmaTextEffects EnigmaTextEffects;
+
+#endif //__TEXTEFFECTS_H
+// vim:et:sw=2:ts=2:
diff --git a/themes/EnigmaNG-AppleGreen.theme b/themes/EnigmaNG-AppleGreen.theme
index 862645a..94851b6 100644
--- a/themes/EnigmaNG-AppleGreen.theme
+++ b/themes/EnigmaNG-AppleGreen.theme
@@ -25,7 +25,6 @@ clrButtonYellowFg = FF000000
clrButtonYellowBg = E5C4C400
clrButtonBlueFg = FFFFFFFF
clrButtonBlueBg = E50000C4
-clrMessageBorder = E5FF0000
clrMessageStatusFg = FF000000
clrMessageStatusBg = E5D7FFD1
clrMessageInfoFg = FF000000
@@ -36,14 +35,8 @@ clrMessageErrorFg = FF000000
clrMessageErrorBg = E5FFD1D1
clrVolumeBar = FF33CC33
clrVolumeBarMute = FFFF0000
-clrMenuItemCurrentFg = FF000000
-clrMenuHighlight = E5BFE6C2
clrMenuItemSelectableFg = FF000000
clrMenuItemNotSelectableFg = E54158BC
-clrMenuEventTitle = FF000000
-clrMenuEventShortText = FF1D2F7D
-clrMenuScrollbarTotal = E5B2BBD6
-clrMenuScrollbarShown = FF000000
clrReplayCurrent = FF2D7D1D
clrReplayTotal = FF2D7D1D
clrReplayModeJump = FF2D7D1D
diff --git a/themes/EnigmaNG-Blue.theme b/themes/EnigmaNG-Blue.theme
new file mode 100644
index 0000000..172145f
--- /dev/null
+++ b/themes/EnigmaNG-Blue.theme
@@ -0,0 +1,47 @@
+Description = Blue
+clrBackground = EE496DCC
+clrAltBackground = EE393D8C
+clrTitleBg = EE4158BC
+clrLogoBg = EE496DAC
+clrBottomBg = EE1D2F7D
+clrBotProgBarBg = FF808080
+clrBotProgBarFg = EEC4C400
+clrMenuTxtFg = FFDDDDDD
+clrTitleFg = FFDDDDDD
+clrTitleShadow = FF000000
+clrSymbolActive = FFC4C400
+clrSymbolInactive = FF808080
+clrSymbolRecord = FFC40000
+clrSymbolRecordBg = FFDDDDDD
+clrSymbolTimerActive = FF0000C4
+clrSymbolVpsActive = FFC4C400
+clrSymbolRecActive = FFC40000
+clrSymbolRunActive = FF00C400
+clrButtonRedFg = FFDDDDDD
+clrButtonRedBg = E8C40000
+clrButtonGreenFg = FF111111
+clrButtonGreenBg = E800C400
+clrButtonYellowFg = FF111111
+clrButtonYellowBg = E8C4C400
+clrButtonBlueFg = FFDDDDDD
+clrButtonBlueBg = E80000C4
+clrMessageStatusFg = FF111111
+clrMessageStatusBg = E8C4C400
+clrMessageInfoFg = FF111111
+clrMessageInfoBg = E8C4C400
+clrMessageWarningFg = FF111111
+clrMessageWarningBg = E8C4C400
+clrMessageErrorFg = FF111111
+clrMessageErrorBg = E8C4C400
+clrVolumeBar = FF33CC33
+clrVolumeBarMute = EE496DCC
+clrMenuItemSelectableFg = FFDDDDDD
+clrMenuItemNotSelectableFg = FFAFAFCF
+clrReplayCurrent = EEC3CAFA
+clrReplayTotal = EEC3CAFA
+clrReplayModeJump = EEC3CAFA
+clrReplayBarAreaBg = EE496DCC
+clrReplayProgressSeen = EE33CC33
+clrReplayProgressRest = EE496DCC
+clrReplayProgressSelected = EE292D5C
+clrReplayProgressMark = EE292D5C
diff --git a/themes/EnigmaNG-Blue2.theme b/themes/EnigmaNG-Blue2.theme
new file mode 100644
index 0000000..458532d
--- /dev/null
+++ b/themes/EnigmaNG-Blue2.theme
@@ -0,0 +1,47 @@
+Description = Blue2
+clrBackground = EE393D8C
+clrAltBackground = EE191D6C
+clrTitleBg = EE4158BC
+clrLogoBg = EE496DAC
+clrBottomBg = EE1D2F7D
+clrBotProgBarBg = FF808080
+clrBotProgBarFg = EEC4C400
+clrMenuTxtFg = FFDDDDDD
+clrTitleFg = FFDDDDDD
+clrTitleShadow = FF000000
+clrSymbolActive = FFC4C400
+clrSymbolInactive = FF808080
+clrSymbolRecord = FFC40000
+clrSymbolRecordBg = FFDDDDDD
+clrSymbolTimerActive = FF0000C4
+clrSymbolVpsActive = FFC4C400
+clrSymbolRecActive = FFC40000
+clrSymbolRunActive = FF00C400
+clrButtonRedFg = FFDDDDDD
+clrButtonRedBg = E8C40000
+clrButtonGreenFg = FF111111
+clrButtonGreenBg = E800C400
+clrButtonYellowFg = FF111111
+clrButtonYellowBg = E8C4C400
+clrButtonBlueFg = FFDDDDDD
+clrButtonBlueBg = E80000C4
+clrMessageStatusFg = FF111111
+clrMessageStatusBg = E8C4C400
+clrMessageInfoFg = FF111111
+clrMessageInfoBg = E8C4C400
+clrMessageWarningFg = FF111111
+clrMessageWarningBg = E8C4C400
+clrMessageErrorFg = FF111111
+clrMessageErrorBg = E8C4C400
+clrVolumeBar = FF33CC33
+clrVolumeBarMute = EE393D8C
+clrMenuItemSelectableFg = FFDDDDDD
+clrMenuItemNotSelectableFg = FFAFAFCF
+clrReplayCurrent = EEC3CAFA
+clrReplayTotal = EEC3CAFA
+clrReplayModeJump = EEC3CAFA
+clrReplayBarAreaBg = EE191D6C
+clrReplayProgressSeen = EE33CC33
+clrReplayProgressRest = EE393D8C
+clrReplayProgressSelected = EEC3CAFA
+clrReplayProgressMark = EEC3CAFA
diff --git a/themes/EnigmaNG-Blue3.theme b/themes/EnigmaNG-Blue3.theme
new file mode 100644
index 0000000..cbee2d6
--- /dev/null
+++ b/themes/EnigmaNG-Blue3.theme
@@ -0,0 +1,47 @@
+Description = Blue3
+clrBackground = EE333388
+clrAltBackground = EE000066
+clrTitleBg = EE4158BC
+clrLogoBg = EE496DAC
+clrBottomBg = EE1D2F7D
+clrBotProgBarBg = FF808080
+clrBotProgBarFg = EEC4C400
+clrMenuTxtFg = FFDDDDDD
+clrTitleFg = FFDDDDDD
+clrTitleShadow = FF000000
+clrSymbolActive = FFC4C400
+clrSymbolInactive = FF808080
+clrSymbolRecord = FFC40000
+clrSymbolRecordBg = FFDDDDDD
+clrSymbolTimerActive = FF0000C4
+clrSymbolVpsActive = FFC4C400
+clrSymbolRecActive = FFC40000
+clrSymbolRunActive = FF00C400
+clrButtonRedFg = FFDDDDDD
+clrButtonRedBg = E8C40000
+clrButtonGreenFg = FF111111
+clrButtonGreenBg = E800C400
+clrButtonYellowFg = FF111111
+clrButtonYellowBg = E8C4C400
+clrButtonBlueFg = FFDDDDDD
+clrButtonBlueBg = E80000C4
+clrMessageStatusFg = FF111111
+clrMessageStatusBg = E8C4C400
+clrMessageInfoFg = FF111111
+clrMessageInfoBg = E8C4C400
+clrMessageWarningFg = FF111111
+clrMessageWarningBg = E8C4C400
+clrMessageErrorFg = FF111111
+clrMessageErrorBg = E8C4C400
+clrVolumeBar = FF33CC33
+clrVolumeBarMute = EE333388
+clrMenuItemSelectableFg = FFDDDDDD
+clrMenuItemNotSelectableFg = FFAFAFCF
+clrReplayCurrent = EEC3CAFA
+clrReplayTotal = EEC3CAFA
+clrReplayModeJump = EEC3CAFA
+clrReplayBarAreaBg = EE191D6C
+clrReplayProgressSeen = EE33CC33
+clrReplayProgressRest = EE393D8C
+clrReplayProgressSelected = EEC3CAFA
+clrReplayProgressMark = EEC3CAFA
diff --git a/themes/EnigmaNG-Coolblue.theme b/themes/EnigmaNG-Coolblue.theme
new file mode 100644
index 0000000..481db0d
--- /dev/null
+++ b/themes/EnigmaNG-Coolblue.theme
@@ -0,0 +1,69 @@
+Description = CoolBlue
+# MenueHauptfarbe
+clrBackground = EE000066
+# MenuFarbe RECHTS (neuer Timer Bereich)
+clrAltBackground = EE333388
+# Titleleiste ganz oben u. beim Umschalten blau: C8000088
+clrTitleBg = EEC40000
+clrLogoBg = EEAAAADD
+# Umschalten Kasten unten passend mit Titelleiste! C8000088
+clrBottomBg = EEC40000
+clrBotProgBarBg = FF808080
+#clrBotProgBarFg = FFDDDDDD
+clrBotProgBarFg = EEC4C400
+# Im Menue RECHTS OBEN bei Logo Schriftfarbe !
+# und in allen Programm u. Aufzeichnungsbeschreibungen !
+clrMenuTxtFg = FFDDDDDD
+# title-Text weiss
+clrTitleFg = FFDDDDDD
+clrTitleShadow = FF000000
+clrSymbolActive = FFC4C400
+clrSymbolInactive = FF808080
+clrSymbolRecord = FFC40000
+clrSymbolRecordBg = FFDDDDDD
+clrSymbolTimerActive = FF0000C4
+clrSymbolVpsActive = FFC4C400
+clrSymbolRecActive = FFC40000
+clrSymbolRunActive = FF00C400
+# 4 Farben buttons
+clrButtonRedFg = FFDDDDDD
+clrButtonRedBg = EEC40000
+clrButtonGreenFg = FF111111
+clrButtonGreenBg = EE00C400
+clrButtonYellowFg = FF111111
+clrButtonYellowBg = EEC4C400
+clrButtonBlueFg = FFDDDDDD
+clrButtonBlueBg = EE0000C4
+#clrMessageBorder = D8FF0000
+clrMessageStatusFg = FF111111
+clrMessageStatusBg = EEC4C400
+clrMessageInfoFg = FF111111
+clrMessageInfoBg = EEC4C400
+clrMessageWarningFg = FF111111
+clrMessageWarningBg = EEC4C400
+clrMessageErrorFg = FF111111
+clrMessageErrorBg = EEC4C400
+# jetzt ist das die Farbe des GELB-Buttons:
+#clrVolumeBar = EEC4C400
+clrVolumeBar = EE33CC33
+#clrVolumeBarMute = FFFF0000
+# bei Mute kein ProgressBar!
+clrVolumeBarMute = EE000066
+# Farbe Scrollbalken Menue TEXT ausgewaehlt (statt weiss gelb = zuviel)
+#clrMenuItemCurrentFg = FFDDDDDD
+# Scrollbar im Menue !!! = Farbe von Menue-Bereich rechts!
+#clrMenuHighlight = C8333388
+#clrAltBackground = EE333388
+# Schriftfarbe des Menues, PRG usw...
+clrMenuItemSelectableFg = FFDDDDDD
+# vorher B88EA4E3
+clrMenuItemNotSelectableFg = FFAAAADD
+# Bei Aufnahme Scrollbar selbsterklaerend
+clrReplayCurrent = EEC3CAFA
+clrReplayTotal = EEC3CAFA
+clrReplayModeJump = EEC3CAFA
+clrReplayBarAreaBg = EE191D6C
+clrReplayProgressSeen = EE33CC33
+clrReplayProgressRest = EE393D8C
+clrReplayProgressSelected = EEC3CAFA
+clrReplayProgressMark = EEC3CAFA
diff --git a/themes/EnigmaNG-DarkBlue.theme b/themes/EnigmaNG-DarkBlue.theme
index 264ff6b..7a61984 100644
--- a/themes/EnigmaNG-DarkBlue.theme
+++ b/themes/EnigmaNG-DarkBlue.theme
@@ -25,7 +25,6 @@ clrButtonYellowFg = FFFFFFFF
clrButtonYellowBg = B8C4C400
clrButtonBlueFg = FFFFFFFF
clrButtonBlueBg = B80000C4
-clrMessageBorder = B8FF0000
clrMessageStatusFg = FFFFFFFF
clrMessageStatusBg = B86B7F68
clrMessageInfoFg = FFFFFFFF
@@ -36,14 +35,8 @@ clrMessageErrorFg = FFFFFFFF
clrMessageErrorBg = B87F6868
clrVolumeBar = FF33CC33
clrVolumeBarMute = FFFF0000
-clrMenuItemCurrentFg = FFFFFFFF
-clrMenuHighlight = B8171720
clrMenuItemSelectableFg = FFFFFFFF
clrMenuItemNotSelectableFg = B88EA4E3
-clrMenuEventTitle = FFFFFFFF
-clrMenuEventShortText = FFC3CAFA
-clrMenuScrollbarTotal = B8DEE5FA
-clrMenuScrollbarShown = FF000000
clrReplayCurrent = FFC3CAFA
clrReplayTotal = FFC3CAFA
clrReplayModeJump = FFC3CAFA
diff --git a/themes/EnigmaNG-MoBuntu.theme b/themes/EnigmaNG-MoBuntu.theme
new file mode 100644
index 0000000..f2c63c2
--- /dev/null
+++ b/themes/EnigmaNG-MoBuntu.theme
@@ -0,0 +1,48 @@
+Description = MoBuntu
+clrBackground = E5200F02
+clrAltBackground = E54C2F1A
+clrTitleBg = E5793809
+clrLogoBg = E5E6731E
+clrBottomBg = E5793809
+clrBotProgBarBg = FF808080
+clrBotProgBarFg = FFFFFFFF
+clrMenuTxtFg = FFFFFFFF
+clrTitleFg = FFFFFFFF
+clrTitleShadow = FF000000
+clrSymbolActive = FFC4C400
+clrSymbolInactive = FF808080
+clrSymbolRecord = FFC40000
+clrSymbolRecordBg = FFFFFFFF
+clrSymbolTimerActive = FF0000C4
+clrSymbolVpsActive = FFC4C400
+clrSymbolRecActive = FFC40000
+clrSymbolRunActive = FF00C400
+clrButtonRedFg = FFFFFFFF
+clrButtonRedBg = E5C40000
+clrButtonGreenFg = FF000000
+clrButtonGreenBg = E500C400
+clrButtonYellowFg = FF000000
+clrButtonYellowBg = E5C4C400
+clrButtonBlueFg = FFFFFFFF
+clrButtonBlueBg = E50000C4
+clrMessageStatusFg = FF000000
+clrMessageStatusBg = E5D7FFD1
+clrMessageInfoFg = FF000000
+clrMessageInfoBg = E5D1DDFF
+clrMessageWarningFg = FF000000
+clrMessageWarningBg = E5F9FFD1
+clrMessageErrorFg = FF000000
+clrMessageErrorBg = E5FFD1D1
+clrVolumeBar = FF33CC33
+clrVolumeBarMute = FFFF0000
+clrMenuItemSelectableFg = FFFFFFFF
+clrMenuItemNotSelectableFg = FFF8BF24
+clrReplayCurrent = FF1D2F7D
+clrReplayTotal = FF1D2F7D
+clrReplayModeJump = FF1D2F7D
+clrReplayBarAreaBg = E5DEE5FA
+clrReplayProgressSeen = FF8EA4E3
+clrReplayProgressRest = E5DEE5FA
+clrReplayProgressSelected = FF4158BC
+clrReplayProgressMark = FF4158BC
+clrReplayProgressCurrent = FFFF0000
diff --git a/themes/EnigmaNG-WineRed.theme b/themes/EnigmaNG-WineRed.theme
index 513271e..a427e34 100644
--- a/themes/EnigmaNG-WineRed.theme
+++ b/themes/EnigmaNG-WineRed.theme
@@ -25,7 +25,6 @@ clrButtonYellowFg = FF000000
clrButtonYellowBg = E5C4C400
clrButtonBlueFg = FFFFFFFF
clrButtonBlueBg = E50000C4
-clrMessageBorder = E5FF0000
clrMessageStatusFg = FF000000
clrMessageStatusBg = E5D7FFD1
clrMessageInfoFg = FF000000
@@ -36,14 +35,8 @@ clrMessageErrorFg = FF000000
clrMessageErrorBg = E5FFD1D1
clrVolumeBar = FF33CC33
clrVolumeBarMute = FFFF0000
-clrMenuItemCurrentFg = FF000000
-clrMenuHighlight = E5E6BFBF
clrMenuItemSelectableFg = FF000000
clrMenuItemNotSelectableFg = E54158BC
-clrMenuEventTitle = FF000000
-clrMenuEventShortText = FF1D2F7D
-clrMenuScrollbarTotal = E5B2BBD6
-clrMenuScrollbarShown = FF000000
clrReplayCurrent = FF7D1D1D
clrReplayTotal = FF7D1D1D
clrReplayModeJump = FF7D1D1D
diff --git a/themes/EnigmaNG-WomenLike.theme b/themes/EnigmaNG-WomenLike.theme
index a50cd3f..b5de6b3 100644
--- a/themes/EnigmaNG-WomenLike.theme
+++ b/themes/EnigmaNG-WomenLike.theme
@@ -25,7 +25,6 @@ clrButtonYellowFg = FF000000
clrButtonYellowBg = E5C4C400
clrButtonBlueFg = FFFFFFFF
clrButtonBlueBg = E50000C4
-clrMessageBorder = E5FF0000
clrMessageStatusFg = FF000000
clrMessageStatusBg = E5D7FFD1
clrMessageInfoFg = FF000000
@@ -36,14 +35,8 @@ clrMessageErrorFg = FF000000
clrMessageErrorBg = E5FFD1D1
clrVolumeBar = FF33CC33
clrVolumeBarMute = FFFF0000
-clrMenuItemCurrentFg = FF000000
-clrMenuHighlight = E5E6BFE3
clrMenuItemSelectableFg = FF000000
clrMenuItemNotSelectableFg = E54158BC
-clrMenuEventTitle = FF000000
-clrMenuEventShortText = FF1D2F7D
-clrMenuScrollbarTotal = E5B2BBD6
-clrMenuScrollbarShown = FF000000
clrReplayCurrent = FF7D1D75
clrReplayTotal = FF7D1D75
clrReplayModeJump = FF7D1D75
diff --git a/themes/EnigmaNG-YellowSun.theme b/themes/EnigmaNG-YellowSun.theme
index 0617ff1..9fcb2c6 100644
--- a/themes/EnigmaNG-YellowSun.theme
+++ b/themes/EnigmaNG-YellowSun.theme
@@ -25,7 +25,6 @@ clrButtonYellowFg = FF000000
clrButtonYellowBg = E5f4f115
clrButtonBlueFg = FFFFFFFF
clrButtonBlueBg = E50000C4
-clrMessageBorder = E5FF0000
clrMessageStatusFg = FF000000
clrMessageStatusBg = E5ffe29b
clrMessageInfoFg = FF000000
@@ -36,14 +35,8 @@ clrMessageErrorFg = FF000000
clrMessageErrorBg = E5FFD1D1
clrVolumeBar = FFffaa33
clrVolumeBarMute = FFFF0000
-clrMenuItemCurrentFg = FF000000
-clrMenuHighlight = E5f3e396
clrMenuItemSelectableFg = FF000000
clrMenuItemNotSelectableFg = E54158BC
-clrMenuEventTitle = FF000000
-clrMenuEventShortText = FF1D2F7D
-clrMenuScrollbarTotal = E5B2BBD6
-clrMenuScrollbarShown = FF000000
clrReplayCurrent = FFd4870e
clrReplayTotal = FFd4870e
clrReplayModeJump = FFd4870e
diff --git a/themes/EnigmaNG-default.theme b/themes/EnigmaNG-default.theme
index e2ed390..8c84110 100644
--- a/themes/EnigmaNG-default.theme
+++ b/themes/EnigmaNG-default.theme
@@ -25,7 +25,6 @@ clrButtonYellowFg = FF000000
clrButtonYellowBg = E5C4C400
clrButtonBlueFg = FFFFFFFF
clrButtonBlueBg = E50000C4
-clrMessageBorder = E5FF0000
clrMessageStatusFg = FF000000
clrMessageStatusBg = E5D7FFD1
clrMessageInfoFg = FF000000
@@ -36,14 +35,8 @@ clrMessageErrorFg = FF000000
clrMessageErrorBg = E5FFD1D1
clrVolumeBar = FF33CC33
clrVolumeBarMute = FFFF0000
-clrMenuItemCurrentFg = FF000000
-clrMenuHighlight = E5B2BBD6
clrMenuItemSelectableFg = FF000000
clrMenuItemNotSelectableFg = E54158BC
-clrMenuEventTitle = FF000000
-clrMenuEventShortText = FF1D2F7D
-clrMenuScrollbarTotal = E5B2BBD6
-clrMenuScrollbarShown = FF000000
clrReplayCurrent = FF1D2F7D
clrReplayTotal = FF1D2F7D
clrReplayModeJump = FF1D2F7D
diff --git a/tools.c b/tools.c
index 2a2859e..f9bf8a8 100644
--- a/tools.c
+++ b/tools.c
@@ -5,26 +5,22 @@
*
*/
-#include <sstream>
-
-#ifndef __STL_CONFIG_H
-#define __STL_CONFIG_H
-#endif
-
-#include <stdlib.h>
-#include <string.h>
#include "common.h"
#include "i18n.h"
-#include "tools.h"
-using namespace std;
+#include <sstream>
+#include <string.h>
+
+#include "tools.h"
#define AUX_HEADER_EPGSEARCH "EPGSearch: "
#define AUX_TAGS_EPGSEARCH_START "<epgsearch>"
-#define AUX_TAGS_EPGSEARCH_ITEM_1A_START "<Channel>"
-#define AUX_TAGS_EPGSEARCH_ITEM_1A_END "</Channel>"
-#define AUX_TAGS_EPGSEARCH_ITEM_2A_START "<Search timer>"
-#define AUX_TAGS_EPGSEARCH_ITEM_2A_END "</Search timer>"
+#define AUX_TAGS_EPGSEARCH_ITEM_1A_START "<channel>"
+#define AUX_TAGS_EPGSEARCH_ITEM_1A_END "</channel>"
+#define AUX_TAGS_EPGSEARCH_ITEM_2A_START "<searchtimer>"
+#define AUX_TAGS_EPGSEARCH_ITEM_2A_END "</searchtimer>"
+#define AUX_TAGS_EPGSEARCH_ITEM_3A_START "<Search timer>"
+#define AUX_TAGS_EPGSEARCH_ITEM_3A_END "</Search timer>"
#define AUX_TAGS_EPGSEARCH_ITEM_1B_START "<update>"
#define AUX_TAGS_EPGSEARCH_ITEM_1B_END "</update>"
#define AUX_TAGS_EPGSEARCH_ITEM_2B_START "<eventid>"
@@ -43,10 +39,10 @@ using namespace std;
#define AUX_TAGS_PIN_ITEM1_END "</protected>"
#define AUX_TAGS_PIN_END "</pin-plugin>"
-const char *parseaux(const char *aux)
+std::string parseaux(const char *aux)
{
- bool founditem = false;
- stringstream sstrReturn;
+ bool founditem = false;
+ std::stringstream sstrReturn;
char *start, *end;
// check if egpsearch
start = strcasestr(aux, AUX_TAGS_EPGSEARCH_START);
@@ -58,47 +54,67 @@ const char *parseaux(const char *aux)
char *tmp;
if ((tmp = strcasestr(start, AUX_TAGS_EPGSEARCH_ITEM_1A_START)) != NULL) {
if (tmp < end) {
- tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_1A_START);
+ tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_1A_START);
char *tmp2;
if ((tmp2 = strcasestr(tmp, AUX_TAGS_EPGSEARCH_ITEM_1A_END)) != NULL) {
// add channel
- sstrReturn << string(tmp, tmp2 - tmp);
+ sstrReturn << tr("Channel:") << " " << std::string(tmp, tmp2 - tmp);
founditem = true;
} else {
founditem = false;
}
}
}
- // parse second item
- if ((tmp = strcasestr(start, AUX_TAGS_EPGSEARCH_ITEM_2A_START)) != NULL) {
- if (tmp < end) {
- tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_2A_START);
- char *tmp2;
- if ((tmp2 = strcasestr(tmp, AUX_TAGS_EPGSEARCH_ITEM_2A_END)) != NULL) {
- // add separator
- if (founditem) {
- sstrReturn << ", ";
+ if (founditem) { // Channel tag found
+ // parse second item
+ if ((tmp = strcasestr(start, AUX_TAGS_EPGSEARCH_ITEM_2A_START)) != NULL) {
+ if (tmp < end) {
+ tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_2A_START);
+ char *tmp2;
+ if ((tmp2 = strcasestr(tmp, AUX_TAGS_EPGSEARCH_ITEM_2A_END)) != NULL) {
+ // add separator
+ if (founditem) {
+ sstrReturn << ", ";
+ }
+ // add search item
+ sstrReturn << tr("Search pattern:") << " " << std::string(tmp, tmp2 - tmp);
+ founditem = true;
+ } else {
+ founditem = false;
+ }
+ }
+ } else {
+ // parse second item
+ if ((tmp = strcasestr(start, AUX_TAGS_EPGSEARCH_ITEM_3A_START)) != NULL) {
+ if (tmp < end) {
+ tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_3A_START);
+ char *tmp2;
+ if ((tmp2 = strcasestr(tmp, AUX_TAGS_EPGSEARCH_ITEM_3A_END)) != NULL) {
+ // add separator
+ if (founditem) {
+ sstrReturn << ", ";
+ }
+ // add search item
+ sstrReturn << tr("Search pattern:") << " " << std::string(tmp, tmp2 - tmp);
+ founditem = true;
+ } else {
+ founditem = false;
+ }
}
- // add search item
- sstrReturn << string(tmp, tmp2 - tmp);
- founditem = true;
- } else {
- founditem = false;
}
}
}
// timer check?
if ((tmp = strcasestr(start, AUX_TAGS_EPGSEARCH_ITEM_1B_START)) != NULL) {
if (tmp < end) {
- tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_1B_START);
+ tmp += strlen(AUX_TAGS_EPGSEARCH_ITEM_1B_START);
char *tmp2;
if ((tmp2 = strcasestr(tmp, AUX_TAGS_EPGSEARCH_ITEM_1B_END)) != NULL) {
- if (string(tmp, tmp2 - tmp) != "0") {
+ if (std::string(tmp, tmp2 - tmp) != "0") {
// add separator
if (founditem) {
sstrReturn << ", ";
}
- founditem = true;
// add search item
sstrReturn << tr("Timer check");
@@ -113,13 +129,17 @@ const char *parseaux(const char *aux)
sstrReturn << ", ";
}
// add search item
- sstrReturn << "eventid=" << string(tmp, tmp2 - tmp);
+ sstrReturn << "eventid=" << std::string(tmp, tmp2 - tmp);
}
}
}
} else {
- founditem = false;
+ if (founditem) {
+ sstrReturn << ", ";
+ }
+ sstrReturn << tr("No timer check");
}
+ founditem = true;
} else {
founditem = false;
}
@@ -129,9 +149,9 @@ const char *parseaux(const char *aux)
// use old syntax
if (!founditem) {
start += strlen(AUX_HEADER_EPGSEARCH);
- sstrReturn << string(start, end - start);
+ sstrReturn << std::string(start, end - start);
}
- sstrReturn << endl;
+ sstrReturn << std::endl;
}
// check if VDRAdmin-AM
start = strcasestr(aux, AUX_TAGS_VDRADMIN_START);
@@ -143,11 +163,11 @@ const char *parseaux(const char *aux)
char *tmp;
if ((tmp = strcasestr(start, AUX_TAGS_VDRADMIN_ITEM1_START)) != NULL) {
if (tmp < end) {
- tmp += strlen(AUX_TAGS_VDRADMIN_ITEM1_START);
+ tmp += strlen(AUX_TAGS_VDRADMIN_ITEM1_START);
char *tmp2;
if ((tmp2 = strcasestr(tmp, AUX_TAGS_VDRADMIN_ITEM1_END)) != NULL) {
// add search item
- sstrReturn << string(tmp, tmp2 - tmp) << endl;
+ sstrReturn << std::string(tmp, tmp2 - tmp) << std::endl;
}
}
}
@@ -162,20 +182,20 @@ const char *parseaux(const char *aux)
char *tmp;
if ((tmp = strcasestr(start, AUX_TAGS_PIN_ITEM1_START)) != NULL) {
if (tmp < end) {
- tmp += strlen(AUX_TAGS_PIN_ITEM1_START);
+ tmp += strlen(AUX_TAGS_PIN_ITEM1_START);
char *tmp2;
if ((tmp2 = strcasestr(tmp, AUX_TAGS_PIN_ITEM1_END)) != NULL) {
// add search item
- sstrReturn << string(tmp, tmp2 - tmp) << endl;
+ sstrReturn << std::string(tmp, tmp2 - tmp) << std::endl;
}
}
}
}
- if (!sstrReturn.str().empty())
- return sstrReturn.str().c_str();
+ if (!sstrReturn.str().empty())
+ return sstrReturn.str();
- return aux;
+ return std::string(aux);
}
bool ischaracters(const char *str, const char *mask)
@@ -193,3 +213,5 @@ bool ischaracters(const char *str, const char *mask)
}
return match;
}
+
+// vim:et:sw=2:ts=2:
diff --git a/tools.h b/tools.h
index 7c8ff13..d19d785 100644
--- a/tools.h
+++ b/tools.h
@@ -1,5 +1,5 @@
/*
- * tools.h: The 'EnigmaNG' VDR skin
+ * tools.h: 'EnigmaNG' skin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
@@ -8,9 +8,20 @@
#ifndef __SKINENIGMA_TOOLS_H
#define __SKINENIGMA_TOOLS_H
-#include <vdr/tools.h>
+#include "common.h"
-const char *parseaux(const char *str);
+#ifdef min
+#undef min
+#endif
+#define min(x, y) (x < y ? x : y)
+
+#ifdef max
+#undef max
+#endif
+#define max(x, y) (x > y ? x : y)
+
+std::string parseaux(const char *str);
bool ischaracters(const char *aux, const char *mask);
#endif // __SKINENIGMA_TOOLS_H
+// vim:et:sw=2:ts=2: