diff options
author | Andreas Mair <amair.sob@googlemail.com> | 2007-04-02 11:38:08 +0200 |
---|---|---|
committer | Andreas Mair <amair.sob@googlemail.com> | 2007-04-02 11:38:08 +0200 |
commit | c562d549bc6274265991eec634f99b1e311323df (patch) | |
tree | 2f4f23396e60f381cb2899ef7be87c1b54dc153c | |
parent | de39678a54ab87364a3c8c5e3b058d313451db5b (diff) | |
download | vdr-plugin-skinenigmang-c562d549bc6274265991eec634f99b1e311323df.tar.gz vdr-plugin-skinenigmang-c562d549bc6274265991eec634f99b1e311323df.tar.bz2 |
2007-04-02: Version 0.0.4v0.0.4
- Changed text color in themes for green and yellow buttons.
- Fixed false colors problem after theme changes.
- Updated Finnish translation. (Submitted by Rolf Ahrenberg)
- Updated French translation. (Submitted by pat @vdr-portal.de)
- Do not overwrite status messages in mainmenu with list items.
- New setup option that replaces SKINENIGMA_FULL_CHANNELINFO_TITLE define.
- Disable logos/symbols/flags if 4bpp single area is configured in setup. (Will eventually replace SKINENIGMA_NO_MENULOGO define)
- Added support for mailbox plugin; shows mail symbol in channel info (Based on patch by triple955 @vdr-portal.de).
- Introduced new HAVE_IMAGEMAGICK define to enable non-xpm images in event's and recording's details.
- Fixed "blinking" date in channel info (Reported by several people).
- Changed background for recording symbol in channel info to white (Suggested by gromit @vdr-portal.de).
- Long channel group names are no longer drawn at the right side of the date (Reported by several people).
- New setup option for displaying a recording's size and use size.vdr (Suggested by vejoun @vdr-portal.de).
- Show stop time of running timers in info area in main menu. (Suggested by viking @vdr-portal.de)
- Updated Russian translation. (Submitted by neptunvasja @vdr-portal.de)
- New defines "ListProgressBarGap" & "ListProgressBarBorder" to customize the progressbar in lists:
* "ListProgressBarGap" sets the gap above/below the progressbar (relative to the font's height).
* "ListProgressBarBorder" sets the border's width.
- Added fallback to "classic" skin if any of the OSD menus fails to open.
- Fix possible NULL pointer accesses.
- Fixed compiler error with certain gcc versions.
- Minor bugfixes and graphical changes.
-rw-r--r-- | HISTORY | 24 | ||||
-rw-r--r-- | Makefile | 29 | ||||
-rw-r--r-- | README | 164 | ||||
-rw-r--r-- | bitmap.c | 79 | ||||
-rw-r--r-- | bitmap.h | 20 | ||||
-rw-r--r-- | config.c | 28 | ||||
-rw-r--r-- | config.h | 19 | ||||
-rw-r--r-- | enigma.c | 503 | ||||
-rw-r--r-- | enigma.h | 3 | ||||
-rw-r--r-- | i18n.c | 402 | ||||
-rw-r--r-- | logo.c | 154 | ||||
-rw-r--r-- | logo.h | 29 | ||||
-rw-r--r-- | skinenigmang.c | 209 | ||||
-rw-r--r-- | symbols/small/mail.xpm | 24 | ||||
-rw-r--r-- | themes/EnigmaNG-AppleGreen.theme | 5 | ||||
-rw-r--r-- | themes/EnigmaNG-DarkBlue.theme | 1 | ||||
-rw-r--r-- | themes/EnigmaNG-WineRed.theme | 5 | ||||
-rw-r--r-- | themes/EnigmaNG-WomenLike.theme | 5 | ||||
-rw-r--r-- | themes/EnigmaNG-YellowSun.theme | 3 | ||||
-rw-r--r-- | themes/EnigmaNG-default.theme | 5 |
20 files changed, 1322 insertions, 389 deletions
@@ -1,6 +1,30 @@ VDR Skin 'EnigmaNG' Revision History ------------------------------------------ +2007-04-02: Version 0.0.4 +- Changed text color in themes for green and yellow buttons. +- Fixed false colors problem after theme changes. +- Updated Finnish translation. (Submitted by Rolf Ahrenberg) +- Updated French translation. (Submitted by pat @vdr-portal.de) +- Do not overwrite status messages in mainmenu with list items. +- New setup option that replaces SKINENIGMA_FULL_CHANNELINFO_TITLE define. +- Disable logos/symbols/flags if 4bpp single area is configured in setup. (Will eventually replace SKINENIGMA_NO_MENULOGO define) +- Added support for mailbox plugin; shows mail symbol in channel info (Based on patch by triple955 @vdr-portal.de). +- Introduced new HAVE_IMAGEMAGICK define to enable non-xpm images in event's and recording's details. +- Fixed "blinking" date in channel info (Reported by several people). +- Changed background for recording symbol in channel info to white (Suggested by gromit @vdr-portal.de). +- Long channel group names are no longer drawn at the right side of the date (Reported by several people). +- New setup option for displaying a recording's size and use size.vdr (Suggested by vejoun @vdr-portal.de). +- Show stop time of running timers in info area in main menu. (Suggested by viking @vdr-portal.de) +- Updated Russian translation. (Submitted by neptunvasja @vdr-portal.de) +- New defines "ListProgressBarGap" & "ListProgressBarBorder" to customize the progressbar in lists: + * "ListProgressBarGap" sets the gap above/below the progressbar (relative to the font's height). + * "ListProgressBarBorder" sets the border's width. +- Added fallback to "classic" skin if any of the OSD menus fails to open. +- Fix possible NULL pointer accesses. +- Fixed compiler error with certain gcc versions. +- Minor bugfixes and graphical changes. + 2007-03-06: Version 0.0.3 - New command line option "-l" to set the logo path. - Added support for epgsearch's timer check auxiliary info in a recording's info. @@ -1,7 +1,7 @@ # # Makefile for a Video Disk Recorder plugin # -# $Id: Makefile,v 1.4 2007/03/06 07:02:27 amair Exp $ +# $Id: Makefile,v 1.8 2007/03/28 10:01:33 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. @@ -14,9 +14,14 @@ # Debugging on/off #SKINENIGMA_DEBUG = 1 -# If set the top and bottom borders are drawn around the channel logo -# in the channel info. TEMPORARY OPTION?!? -#SKINENIGMA_FULL_CHANNELINFO_TITLE = 1 +# If you have installed ImageMagick and want to use +# images in event's and recording's details. +#HAVE_IMAGEMAGICK = 1 + +# 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_USE_PLUGIN_MAILBOX = 1 # Strip debug symbols? Set eg. to /bin/true if not #STRIP = strip @@ -74,14 +79,24 @@ ifdef SKINENIGMA_NO_MENULOGO DEFINES += -DSKINENIGMA_NO_MENULOGO endif -ifdef SKINENIGMA_FULL_CHANNELINFO_TITLE -DEFINES += -DSKINENIGMA_FULL_CHANNELINFO_TITLE +ifdef SKINENIGMA_USE_PLUGIN_MAILBOX +DEFINES += -DUSE_PLUGIN_MAILBOX +endif + +ifdef HAVE_IMAGEMAGICK +DEFINES += -DHAVE_IMAGEMAGICK endif +DEFINES += -DRECORDING_COVER='"Cover-Enigma"' ### The object files (add further files here): OBJS = $(PLUGIN).o enigma.o config.o logo.o i18n.o tools.o status.o +ifdef HAVE_IMAGEMAGICK +OBJS += bitmap.o +LIBS += -lMagick++ +endif + ### Implicit rules: %.o: %.c @@ -101,7 +116,7 @@ $(DEPFILE): Makefile all: libvdr-$(PLUGIN).so libvdr-$(PLUGIN).so: $(OBJS) - $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ + $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -o $@ ifndef SKINENIGMA_DEBUG @$(STRIP) $@ endif @@ -37,9 +37,14 @@ SKINENIGMA_NO_MENULOGO = 1 This turns usage of logos in the main menu complete. This might also improve the performance of the menus. EXPERIMENTAL!!! -SKINENIGMA_FULL_CHANNELINFO_TITLE = 1 -If set the top and bottom borders are drawn around the channel logo -in the channel info. TEMPORARY OPTION?!? +HAVE_IMAGEMAGICK = 1 +If you have installed ImageMagick and want to use images in event's +and recording's details. + +SKINENIGMA_USE_PLUGIN_MAILBOX = 1 +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. Patches @@ -86,8 +91,11 @@ some things before: Options ------- - -l path, --logodir=path - Path to the logos. + -l path, --logodir=path + Path to the logos (Default: <vdrconfdir>/skinenigmang). + + -i path, --epgimages=path + Path to the epgimages (Default: <logodir>/epgimages). Usage @@ -101,38 +109,56 @@ Setup Options - One area (if possible) 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 - can handle that area (e.g. softdevice) it will be used. Otherwise multiple - areas are used. - This option might be useful for 4MB modded DVB cards because they say they - can handle the 8bpp single area but the OSD will be slower. If you own such - a card you may want to play with that option and see if you can increase - OSD speed. - NOTE: after commit the settings you have to fully close and re-open the OSD - to make the change affect. + 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 + can handle that area (e.g. softdevice) it will be used. Otherwise multiple + areas are used. + This option might be useful for 4MB modded DVB cards because they say they + can handle the 8bpp single area but the OSD will be slower. If you own such + a card you may want to play with that option and see if you can increase + OSD speed. + 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 you should also disable "Show symbols" because - otherwise a palette overflow is very likely. + 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 been defined). + timers and the number of timer conflicts (if SKINENIGMA_HAVE_EPGSEARCH has + been defined). - Show auxiliary information (top/bottom) Here you can set where you want to have the auxiliary information - when you open an event's or recording's info screen. This information - includes for a recording its channel, size, priority, lifetime, audio - languages and some values that selected plugins (epgsearch, VDRAdmin-AM, - pin) have set. For an event the audio languages are shown. + when you open an event's or recording's info screen. This information + includes for a recording its channel, size, priority, lifetime, audio + languages and some values that selected plugins (epgsearch, VDRAdmin-AM, + pin) have set. For an event the audio languages are shown. + +- Show recording's size (never/use size.vdr only/always) + This setting controls if a recording's size is shown in the recording's + details. + never - never show the size + use size.vdr only - only show the size if size.vdr exists in the + recording's directory. The first line of size.vdr is + read and has to be the recording's size in megabytes + (MB). You can create size.vdr by adding a line like + du -sm | cut -f1 >"$2/size.vdr" + to your VDR's recording script's "after" and "edited" + sections. + always - This will also use size.vdr if available. Otherwise + it will calculate the size itself. + +- Full title width + If enabled the titlebar in the channel info will be drawn above the channel + logo. This has no effect if channel logos are disabled. - Show remaining/elapsed time (elapsed/remaining/percent) Here you can set if you want to read the number of minutes an event is - already running (preceded by "+") or the number of minutes an event will - run (preceded by "-") or the percent the event has been running in the + already running (preceded by "+") or the number of minutes an event will + run (preceded by "-") or the percent the event has been running in the channel info. - Show VPS @@ -140,14 +166,14 @@ Setup Options - Show progressbar This replaces progressbars shown with pipes (e.g. [|| ]) by a graphical - progressbar. + progressbar. * Logos & Symbols - Show symbols (never/always/not in menu/only in menu) 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. + 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 @@ -163,38 +189,66 @@ Setup Options - Show flags If enabled graphical flags are drawn for the audio channel languages if the requested flag file exists. Else language's abbreviation is drawn. - + +- Show mail icon (never/only if new mail present/always) + Enables mail icon in channel info. + +- Show event/recording images + Enable or disable images in the right top corner in an event's or recording's + info. The recording's image must be named "Cover-Enigma.xpm" in the recording's + directory. An event's image must be named "<eventid>.xpm" and must be stored in + the directory given with the "--epgimages" option. + If imagemagick support is compiled in you can use different image extensions, + see below. + +- Resize images (pixel algo/ratio algo/zoom image) + (NOTE: only visible if Imagemagick support is compiled in!) + The algorithm to use for resizing. Please ask the Imagemagick documentation if + you want to know how the algorithms work. + +- Image width (80 - 180) + (NOTE: only visible if Imagemagick support is compiled in!) + The width for event/recording images. + +- Image height (80 - 144) + (NOTE: only visible if Imagemagick support is compiled in!) + The height for event/recording images. + +- Image format (xpm/jpg/png) + (NOTE: only visible if Imagemagick support is compiled in!) + The extension to use for event/recording images. + - Show channel logos Hide or show channel logos in channel info. - Identify channel by (name/data) Here you can choose if the channel logo should be searched by the channel's - name (e.g. "YLETV2" -> "YLETV2.xpm") or by the channel's unique id (e.g. - "T-8438-4097-33.xpm"). - NOTE: the available logo packs are named by channel name only! + name (e.g. "YLETV2" -> "YLETV2.xpm") or by the channel's unique id (e.g. + "T-8438-4097-33.xpm"). + NOTE: the available logo packs are named by channel name only! - Channel logo cache size The number of logos/symbols to keep in the cache. -* EPGSearch +* 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. - Use Subtitle for reruns (never/if exists/always) If set to "never" all events will match that _contain_ the current event's - title in their title, e.g. if title is "Brisant" it will also find - "Brisant Classix". - If set to "if exists" it will use the subtitle to find reruns if the - current event contains a subtitle. This will also require a full title match, - e.g. if title is "Brisant" and subtitle is "Boulevard Magazin" it will find - only events with title and subtitle beeing exactly "Brisant" and "Boulevard - Magazin". It won't find events named "Brisant Classix" or "Brisant" without - subtitle. - If set to "always" it will always use the subtitle even if it's empty. As a - sideeffect also the event titles must match exactly, e.g. if title is - "Tagesschau" it will only find events named "Tagesschau" and not "Tagesschau - vor 30 Jahren". + title in their title, e.g. if title is "Brisant" it will also find + "Brisant Classix". + If set to "if exists" it will use the subtitle to find reruns if the + current event contains a subtitle. This will also require a full title match, + e.g. if title is "Brisant" and subtitle is "Boulevard Magazin" it will find + only events with title and subtitle beeing exactly "Brisant" and "Boulevard + Magazin". It won't find events named "Brisant Classix" or "Brisant" without + subtitle. + If set to "always" it will always use the subtitle even if it's empty. As a + sideeffect also the event titles must match exactly, e.g. if title is + "Tagesschau" it will only find events named "Tagesschau" and not "Tagesschau + vor 30 Jahren". - Show timer conflicts Enable or disable showing the number of timer conflicts in the main menu's @@ -215,11 +269,12 @@ Credits ------- - Rolf Ahrenberg for the Soppalusikka skin where I've lent some code. - http://www.saunalahti.fi/~rahrenbe/vdr/soppalusikka/ + http://www.saunalahti.fi/~rahrenbe/vdr/soppalusikka/ - Andreas Burger for the original "Enigma" for Text2Skin and his Text2Skin patches. http://brougs78.vdr-developer.org/ - http://www.vdr-portal.de/board/thread.php?threadid=28730 + http://www.vdr-portal.de/board/thread.php?threadid=28730 + http://www.vdr-wiki.de/wiki/index.php/Entwicklung_-_Tipps_und_Tricks - Sascha Volkenandt for Text2Skin where I've lent some code. http://linux.kompiliert.net/ @@ -228,20 +283,21 @@ Credits http://www.speedbomb.de/hobby/myhtpc/index.php?view=logos - zulu @vdr-portal.de for some symbols. - http://www.vdr-portal.de/board/thread.php?postid=514251#post514251 + http://www.vdr-portal.de/board/thread.php?postid=514251#post514251 - Thomas @vdr-portal.de for some logos. - http://senderlogos.vdr-developer.org/ + http://senderlogos.vdr-developer.org/ - FrankJepsen @vdr-portal.de for some logos. - http://www.vdr-portal.de/board/thread.php?postid=531412#post531412 + http://www.vdr-portal.de/board/thread.php?postid=531412#post531412 - chrisz @vdr-portal.de for some radio logos and original Enigma themes. - WomensLike: http://www.vdr-portal.de/board/thread.php?threadid=59651 - WineRed: http://www.vdr-portal.de/board/thread.php?threadid=59416 - AppleGreen: http://www.vdr-portal.de/board/thread.php?threadid=59427 - YellowSun: http://www.vdr-portal.de/board/thread.php?postid=581117 + WomensLike: http://www.vdr-portal.de/board/thread.php?threadid=59651 + WineRed: http://www.vdr-portal.de/board/thread.php?threadid=59416 + AppleGreen: http://www.vdr-portal.de/board/thread.php?threadid=59427 + YellowSun: http://www.vdr-portal.de/board/thread.php?postid=581117 - skiller2k1 @vdr-portal.de for Comedy Central logo. http://www.vdr-portal.de/board/thread.php?postid=567887#post567887 +// vim:et:sw=2:ts=2: diff --git a/bitmap.c b/bitmap.c new file mode 100644 index 0000000..59bf98b --- /dev/null +++ b/bitmap.c @@ -0,0 +1,79 @@ +#ifdef HAVE_IMAGEMAGICK +#include "bitmap.h" +#include "config.h" + +#include <vdr/themes.h> + +#define X_DISPLAY_MISSING +#include <Magick++.h> +using namespace Magick; + +#include <vector> +using namespace std; + +cOSDImageBitmap::cOSDImageBitmap() +{} + + +cOSDImageBitmap::~cOSDImageBitmap() +{} + +bool cOSDImageBitmap::LoadImage(const char *fileNameP, int w, int h, int colors, cBitmap &bmp) +{ + return LoadMagick(fileNameP, w, h, colors, bmp); +} + +bool cOSDImageBitmap::LoadMagick(const char *Filename, int width, int height, int colors, cBitmap &bmp) +{ + Image image; + try { + image.read(Filename); + int w = image.columns(); + int h = image.rows(); + if (height != h || width != w) { + switch (EnigmaConfig.resizeImages) { + case 0: + image.sample(Geometry(width, height)); + break; + case 1: + image.scale(Geometry(width, height)); + break; + case 2: + image.zoom(Geometry(width, height)); + break; + } + } + w = image.columns(); + h = image.rows(); + if (colors != 0){ + image.opacity(OpaqueOpacity); + image.backgroundColor(Color(0, 0, 0, 0)); + image.quantizeColorSpace(RGBColorspace); + image.quantizeColors(colors); + image.quantize(); + } + bmp.SetSize(w, h); + bmp.SetBpp(colors <= 16 ? 4 : 8); + + const PixelPacket *pix = image.getConstPixels(0, 0, w, h); + for (int iy = 0; iy < h; ++iy) { + for (int ix = 0; ix < w; ++ix) { + tColor col = (~(pix->opacity * 255 / MaxRGB) << 24) + | ((pix->red * 255 / MaxRGB) << 16) + | ((pix->green * 255 / MaxRGB) << 8) + | (pix->blue * 255 / MaxRGB); + bmp.DrawPixel(ix, iy, col); + ++pix; + } + } + } catch (Exception &e) { + esyslog("ERROR: Couldn't load %s: %s", Filename, e.what()); + return false; + } catch (...) { + esyslog("ERROR: Couldn't load %s: Unknown exception caught", Filename); + return false; + } + return true; +} +#endif //HAVE_IMAGEMAGICK +// vim:et:sw=2:ts=2: diff --git a/bitmap.h b/bitmap.h new file mode 100644 index 0000000..5692b9d --- /dev/null +++ b/bitmap.h @@ -0,0 +1,20 @@ +#ifdef HAVE_IMAGEMAGICK + +#ifndef _OSDIMAGE_BITMAP_H_ +#define _OSDIMAGE_BITMAP_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); + +private: + bool LoadMagick(const char *Filename, int height, int width, int colors, cBitmap &bmp); +}; + +#endif +#endif //HAVE_IMAGEMAGICK @@ -9,15 +9,22 @@ #include "common.h" #include "config.h" +#ifdef HAVE_IMAGEMAGICK +const char *imageExtensionTexts[NUM_IMAGEEXTENSIONTEXTS] = { "xpm", "jpg", "png" }; +#endif + cEnigmaConfig EnigmaConfig; cEnigmaConfig::cEnigmaConfig() : showAuxInfo(1), showLogo(1), showVps(1), showSymbols(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) + useSubtitleRerun(1), showTimerConflicts(1), showRecSize(2), + showImages(1), resizeImages(0), showMailIcon(0), + imageWidth(120), imageHeight(120), imageExtension(0), fullTitleWidth(0) { memset(logoDir, 0, sizeof(logoDir)); + memset(strImagesDir, 0, sizeof(strImagesDir)); } cEnigmaConfig::~cEnigmaConfig() @@ -32,3 +39,22 @@ void cEnigmaConfig::SetLogoDir(const char *logodirP) strncpy(logoDir, logodirP, sizeof(logoDir)); } } + +void cEnigmaConfig::SetImagesDir(const char *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]; +#else + return "xpm"; +#endif +} + @@ -8,15 +8,26 @@ #ifndef __SKINENIGMA_CONFIG_H #define __SKINENIGMA_CONFIG_H +#ifdef HAVE_IMAGEMAGICK +#define NUM_IMAGEEXTENSIONTEXTS 3 +extern const char *imageExtensionTexts[NUM_IMAGEEXTENSIONTEXTS]; +#else +#define NUM_IMAGEEXTENSIONTEXTS 0 +#endif + struct cEnigmaConfig { private: char logoDir[255]; + char strImagesDir[255]; 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); int showAuxInfo; int showLogo; int showVps; @@ -34,6 +45,14 @@ public: int numReruns; int useSubtitleRerun; int showTimerConflicts; + int showRecSize; + int showImages; + int resizeImages; + int showMailIcon; + int imageWidth; + int imageHeight; + int imageExtension; + int fullTitleWidth; }; extern cEnigmaConfig EnigmaConfig; @@ -9,6 +9,7 @@ #include <ctype.h> #include <sstream> #include <iomanip> +#include <locale.h> #ifndef __STL_CONFIG_H #define __STL_CONFIG_H @@ -59,6 +60,9 @@ using namespace std; #include "symbols/small/recording.xpm" #include "symbols/small/timer.xpm" #include "symbols/small/run.xpm" +#ifdef USE_PLUGIN_MAILBOX +#include "symbols/small/mail.xpm" +#endif static cBitmap bmEventPartTimer(eventparttimer_xpm); static cBitmap bmEventTimer(eventtimer_xpm); @@ -81,6 +85,9 @@ static cBitmap bmTeletext(teletext_xpm); static cBitmap bmVPS(vps_xpm); static cBitmap bmRun(run_xpm); static cBitmap bmTimer(timer_xpm); +#ifdef USE_PLUGIN_MAILBOX +static cBitmap bmMail(mail_xpm); +#endif // audio menu static const char *strAudio_large[MAX_AUDIO_BITMAPS] = { @@ -145,6 +152,7 @@ THEME_CLR(Theme, clrTitleShadow, 0xFF000000); THEME_CLR(Theme, clrSymbolActive, 0xFFC4C400); THEME_CLR(Theme, clrSymbolInactive, 0xFF808080); THEME_CLR(Theme, clrSymbolRecord, 0xFFC40000); +THEME_CLR(Theme, clrSymbolRecordBg, 0xFFFFFFFF); THEME_CLR(Theme, clrSymbolTimerActive, 0xFF0000C4); THEME_CLR(Theme, clrSymbolVpsActive, 0xFFC4C400); THEME_CLR(Theme, clrSymbolRecActive, 0xFFC40000); @@ -152,9 +160,9 @@ THEME_CLR(Theme, clrSymbolRunActive, 0xFF00C400); // Help buttons THEME_CLR(Theme, clrButtonRedFg, 0xFFFFFFFF); THEME_CLR(Theme, clrButtonRedBg, 0xE5C40000); -THEME_CLR(Theme, clrButtonGreenFg, 0xFFFFFFFF); +THEME_CLR(Theme, clrButtonGreenFg, 0xFF000000); THEME_CLR(Theme, clrButtonGreenBg, 0xE500C400); -THEME_CLR(Theme, clrButtonYellowFg, 0xFFFFFFFF); +THEME_CLR(Theme, clrButtonYellowFg, 0xFF000000); THEME_CLR(Theme, clrButtonYellowBg, 0xE5C4C400); THEME_CLR(Theme, clrButtonBlueFg, 0xFFFFFFFF); THEME_CLR(Theme, clrButtonBlueBg, 0xE50000C4); @@ -208,9 +216,8 @@ THEME_CLR(Theme, clrReplayProgressCurrent, 0xFFFF0000); #define LogoDecoGap2 Gap #define LogoDecoWidth SmallGap #define MarkerGap 6 - -#define SymbolHeight 18 -#define LogoHeight 80 +#define ListProgressBarGap Gap +#define ListProgressBarBorder TinyGap // --- cSkinEnigmaDisplayChannel -------------------------------------------- @@ -248,25 +255,21 @@ public: cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo) { - fShowLogo = EnigmaConfig.showLogo; + fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && EnigmaConfig.showLogo; xFirstSymbol = 0; lastTime = 0; lineHeightSml = cFont::GetFont(fontSml)->Height(); lineHeightOsd = cFont::GetFont(fontOsd)->Height(); - int LogoSize = max(lineHeightSml * 2 + lineHeightOsd * 2 + SmallGap, LogoHeight); + int LogoSize = max(lineHeightSml * 2 + lineHeightOsd * 2 + SmallGap, ChannelLogoHeight); LogoSize += (LogoSize % 2 ? 1 : 0); // title bar & logo area xLogoLeft = 0; xLogoRight = xLogoLeft + LogoSize; xLogoDecoLeft = xLogoRight + LogoDecoGap; xLogoDecoRight = xLogoDecoLeft + LogoDecoWidth; -#ifdef SKINENIGMA_FULL_CHANNELINFO_TITLE - xTitleLeft = xLogoLeft; -#else - xTitleLeft = (fShowLogo ? xLogoDecoRight + LogoDecoGap2 : 0); -#endif + xTitleLeft = (fShowLogo && !EnigmaConfig.fullTitleWidth ? xLogoDecoRight + LogoDecoGap2 : xLogoLeft); xTitleRight = xTitleLeft + ((Setup.OSDWidth - xTitleLeft) & ~0x07); // width must be multiple of 8 yTitleTop = 0; yTitleBottom = yTitleTop + lineHeightOsd; @@ -274,14 +277,10 @@ cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo) yTitleDecoBottom = yTitleDecoTop + TitleDecoHeight; yLogoTop = yTitleDecoBottom + TitleDecoGap2; yLogoBottom = yLogoTop + LogoSize; - xLogoPos = xLogoLeft + (LogoSize - LogoHeight) / 2; - yLogoPos = yLogoTop + (LogoSize - LogoHeight) / 2; + xLogoPos = xLogoLeft + (LogoSize - ChannelLogoHeight) / 2; + yLogoPos = yLogoTop + (LogoSize - ChannelLogoHeight) / 2; // current event area -#ifdef SKINENIGMA_FULL_CHANNELINFO_TITLE - xEventNowLeft = (fShowLogo ? xLogoDecoRight + LogoDecoGap2 : 0); -#else - xEventNowLeft = xTitleLeft; -#endif + xEventNowLeft = (fShowLogo ? xLogoDecoRight + LogoDecoGap2 : xTitleLeft); xEventNowRight = xTitleRight; yEventNowTop = yLogoTop; yEventNowBottom = yEventNowTop + lineHeightOsd + lineHeightSml; @@ -320,6 +319,9 @@ cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo) osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayChannel: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } else { @@ -332,6 +334,9 @@ cSkinEnigmaDisplayChannel::cSkinEnigmaDisplayChannel(bool WithInfo) osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayChannel: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } @@ -387,18 +392,14 @@ void cSkinEnigmaDisplayChannel::DrawGroupInfo(const cChannel *Channel, int Numbe DrawAreas(); const cFont *font = cFont::GetFont(fontOsd); - int xName = xTitleLeft + Roundness + font->Width("0000-") + Gap; -#ifdef SKINENIGMA_FULL_CHANNELINFO_TITLE - if (fShowLogo) - xName = xEventNowLeft; -#endif + 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 - xTitleLeft - 3, lineHeightOsd - 3); + xTitleRight - Roundness - xName - 3, lineHeightOsd - 3); osd->DrawText(xName, yTitleTop, GetChannelName(Channel), Theme.Color(clrTitleFg), clrTransparent, font, - xTitleRight - xTitleLeft, lineHeightOsd); + xTitleRight - Roundness - xName, lineHeightOsd); } void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Number) @@ -408,20 +409,18 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num const cFont *font = cFont::GetFont(fontOsd); int xNumber = xTitleLeft + Roundness; int xName = xNumber + font->Width("0000-") + Gap; -#ifdef SKINENIGMA_FULL_CHANNELINFO_TITLE - if (fShowLogo) { + if (fShowLogo && EnigmaConfig.fullTitleWidth) { xNumber = xTitleLeft + Roundness; xName = xEventNowLeft; } -#endif // draw channel number osd->DrawText(xNumber + 3, yTitleTop + 3, GetChannelNumber(Channel, Number), Theme.Color(clrTitleShadow), clrTransparent, font, - xName - xNumber - Gap - 3, yTitleBottom - yTitleTop - 3, taRight); + xName - xNumber - Gap - 3, yTitleBottom - yTitleTop - 3, taCenter); osd->DrawText(xNumber, yTitleTop, GetChannelNumber(Channel, Number), Theme.Color(clrTitleFg), clrTransparent, font, - xName - xNumber - Gap, yTitleBottom - yTitleTop, taRight); + xName - xNumber - Gap, yTitleBottom - yTitleTop, taCenter); // draw channel name osd->DrawText(xName + 3, yTitleTop + 3, GetChannelName(Channel), Theme.Color(clrTitleShadow), clrTransparent, font, @@ -455,10 +454,10 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num } bool fFlagFound = false; - if (EnigmaConfig.showFlags) { + if ((!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && EnigmaConfig.showFlags && !isempty(Channel->Alang(0))) { char *strFile = NULL; asprintf(&strFile, "flags/%s", Channel->Alang(0)); - if (EnigmaLogoCache.Load(strFile)) { + if (EnigmaLogoCache.LoadSymbol(strFile)) { xs -= (EnigmaLogoCache.Get().Width() + SmallGap); osd->DrawBitmap(xs, ys, EnigmaLogoCache.Get()); fFlagFound = true; @@ -505,13 +504,28 @@ void cSkinEnigmaDisplayChannel::DrawChannelInfo(const cChannel *Channel, int Num Theme.Color(clrBottomBg), Theme.Color(Channel->Ca() ? clrSymbolActive : clrSymbolInactive)); // draw recording symbol xs -= (bmRecording.Width() + SmallGap); - if (cRecordControls::Active()) + if (cRecordControls::Active()) { + bool fRecording = HasChannelTimerRecording(Channel); osd->DrawBitmap(xs, ys, bmRecording, - Theme.Color(clrBottomBg), - Theme.Color(HasChannelTimerRecording(Channel) ? clrSymbolRecord : clrSymbolActive)); - else + Theme.Color(fRecording ? clrSymbolRecordBg : clrBottomBg), + Theme.Color(fRecording ? clrSymbolRecord : clrSymbolActive)); + } else osd->DrawBitmap(xs, ys, bmRecording, Theme.Color(clrBottomBg), Theme.Color(clrSymbolInactive)); + +#ifdef USE_PLUGIN_MAILBOX + if (EnigmaConfig.showMailIcon) { + cPlugin *MailBoxPlugin = cPluginManager::GetPlugin("mailbox"); + bool fHasNewMail = false; + if (MailBoxPlugin && MailBoxPlugin->Service("MailBox-HasNewMail-1.0", &fHasNewMail)) { + if (fHasNewMail || EnigmaConfig.showMailIcon > 1) { + xs -= (bmMail.Width() + SmallGap); + osd->DrawBitmap(xs, ys, bmMail, Theme.Color(clrBottomBg), + Theme.Color(fHasNewMail ? clrSymbolActive : clrSymbolInactive)); + } + } + } +#endif xFirstSymbol = xs - Gap; } @@ -546,6 +560,7 @@ cString cSkinEnigmaDisplayChannel::GetChannelNumber(const cChannel *Channel, int void cSkinEnigmaDisplayChannel::SetChannel(const cChannel *Channel, int Number) { xFirstSymbol = 0; + lastTime = 0; if (Channel) { // clear all @@ -555,31 +570,13 @@ void cSkinEnigmaDisplayChannel::SetChannel(const cChannel *Channel, int Number) // draw logo area osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg)); osd->DrawRectangle(xLogoDecoLeft, yLogoTop, xLogoDecoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg)); - char *strChannelID = EnigmaConfig.useChannelId ? strdup(*Channel->GetChannelID().ToString()) : NULL; - const char *logoname = EnigmaConfig.useChannelId ? strChannelID : Channel->Name(); - if (logoname) { - char *filename = (char *)malloc(strlen(logoname) + 20 /* should be enough for folder */); - if (filename == NULL) return; - strcpy(filename, "hqlogos/"); - strcat(filename, logoname); - bool fFoundLogo = false; - if (!(fFoundLogo = EnigmaLogoCache.Load(filename))) { - strcpy(filename, "logos/"); - strcat(filename, logoname); - if (!(fFoundLogo = EnigmaLogoCache.Load(filename))) { - fFoundLogo = EnigmaLogoCache.Load("hqlogos/no_logo"); //TODO? different default logo for channel/group? - } - } - free(filename); - if (fFoundLogo) { - osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - ChannelLogoWidth) / 2, - yLogoTop + (yLogoBottom - yLogoTop - ChannelLogoHeight) / 2, - EnigmaLogoCache.Get(), EnigmaLogoCache.Get().Color(1), - Theme.Color(clrLogoBg), true); - } + if (EnigmaLogoCache.LoadChannelLogo(Channel)) { + osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - ChannelLogoWidth) / 2, + yLogoTop + (yLogoBottom - yLogoTop - ChannelLogoHeight) / 2, + EnigmaLogoCache.Get(), EnigmaLogoCache.Get().Color(1), + Theme.Color(clrLogoBg), true); } - free(strChannelID); } if (Channel->GroupSep()) @@ -666,10 +663,6 @@ void cSkinEnigmaDisplayChannel::SetEvents(const cEvent *Present, } // draw timebar int xBarLeft = xBottomLeft + Roundness; -/*TODO? #ifdef SKINENIGMA_FULL_CHANNELINFO_TITLE - if (fShowLogo) - xBarLeft = xEventNowLeft; -#endif*/ int xBarWidth = (xFirstSymbol > xBarLeft ? (xFirstSymbol - Gap - xBarLeft) : 124); int x = xBarLeft + SmallGap + (int)(ceil((float)(now) / (float)(total) * (float)(xBarWidth - Gap - SmallGap))); x = min(x, xBarLeft + Gap + xBarWidth - SmallGap - 1); @@ -765,6 +758,7 @@ private: char *strTitle; char *strLastDate; + char *strTheme; bool isMainMenu; bool fShowLogo; bool fShowInfo; @@ -779,12 +773,15 @@ private: int lineHeightOsd; int lineHeightSml; + int nMessagesShown; + int nNumImageColors; void SetScrollbar(void); void SetupAreas(void); void DrawTitle(const char *Title); int DrawFlag(int x, int y, const tComponent *p); const char *GetPluginMainMenuName(const char *plugin); + int ReadSizeVdr(const char *strPath); public: cSkinEnigmaDisplayMenu(); virtual ~cSkinEnigmaDisplayMenu(); @@ -809,21 +806,27 @@ cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void) osd = NULL; strTitle = NULL; strLastDate = NULL; + strTheme = strdup(Theme.Name()); isMainMenu = true; #ifdef SKINENIGMA_NO_MENULOGO fShowLogo = false; #else - fShowLogo = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3); + fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3); #endif fShowInfo = EnigmaConfig.showInfo; + nMessagesShown = 0; + nNumImageColors = 2; lineHeightSml = cFont::GetFont(fontSml)->Height(); lineHeightOsd = cFont::GetFont(fontOsd)->Height(); - int LogoSize = max(lineHeightOsd + TitleDeco + lineHeightOsd + lineHeightSml, - max(3 * lineHeightOsd, LogoHeight) - ); - int RightColWidth = (144 + LogoSize) & ~0x07; // must be multiple of 8 + int LogoHeight = max(lineHeightOsd + TitleDeco + lineHeightOsd + lineHeightSml, + max(3 * lineHeightOsd, + 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 // title bar xTitleLeft = 0; @@ -848,10 +851,10 @@ cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void) 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 - LogoSize; + xLogoLeft = Setup.OSDWidth - LogoWidth; xLogoRight = Setup.OSDWidth; yLogoTop = yTitleTop; - yLogoBottom = yLogoTop + LogoSize + SmallGap; + yLogoBottom = yLogoTop + LogoHeight + SmallGap; // info box xInfoLeft = Setup.OSDWidth - RightColWidth; xInfoRight = Setup.OSDWidth; @@ -869,8 +872,7 @@ cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void) tArea Areas[] = { {xTitleLeft, yTitleTop, xMessageRight - 1, yButtonsBottom - 1, EnigmaConfig.singleArea8Bpp ? 8 : 4} }; if (EnigmaConfig.singleArea && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) { osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); - // clear all - osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent); + nNumImageColors = (EnigmaConfig.singleArea8Bpp ? 230 : 2); //TODO: find correct number of colors } else { tArea Areas[] = { {xTitleLeft, yTitleTop, xTitleRight - 1, yTitleDecoBottom - 1, 2}, //title area {xBodyLeft, yBodyTop, xBodyRight - 1, yLogoBottom - 1, 2}, //body area (beside date/logo area) @@ -890,24 +892,18 @@ cSkinEnigmaDisplayMenu::cSkinEnigmaDisplayMenu(void) osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayMenu: CanHandleAreas() [1] returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } - // clear all - osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent); - - // reset colors for list areas - osd->GetBitmap(1)->Reset(); -#ifdef SKINENIGMA_NO_MENULOGO - osd->GetBitmap(3)->Reset(); - osd->GetBitmap(4)->Reset(); - osd->GetBitmap(5)->Reset(); -#else - osd->GetBitmap(3)->Reset(); - osd->GetBitmap(4)->Reset(); -#endif + nNumImageColors = 13; // "16 available colors" - "clrTransparent" - "clrLogoBg" - "clrMenuTxtFg" } + // clear all + osd->DrawRectangle(0, 0, osd->Width(), osd->Height(), clrTransparent); + SetupAreas(); } @@ -980,7 +976,11 @@ void cSkinEnigmaDisplayMenu::SetupAreas(void) osd->DrawText(x + (timer->isRecording ? (bmRecording.Width() + Gap) : 0), y, timer->title.c_str(), Theme.Color(clrMenuItemSelectableFg), Theme.Color(clrAltBackground), font, w, h); y += h; char* info = NULL; - asprintf(&info, "%d. %s / %s", timer->startDay, *TimeString(timer->startTime), timer->channelName.c_str()); + if (timer->isRecording) { + asprintf(&info, "- %s / %s", *TimeString(timer->stopTime), timer->channelName.c_str()); + } 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); free(info); y += h; @@ -996,6 +996,7 @@ void cSkinEnigmaDisplayMenu::SetupAreas(void) cSkinEnigmaDisplayMenu::~cSkinEnigmaDisplayMenu() { + free(strTheme); free(strTitle); free(strLastDate); delete osd; @@ -1046,9 +1047,26 @@ int cSkinEnigmaDisplayMenu::MaxItems(void) void cSkinEnigmaDisplayMenu::Clear(void) { debug("cSkinEnigmaDisplayMenu::Clear\n"); + textScroller.Reset(); - // clear items area - osd->DrawRectangle(xBodyLeft, yBodyTop, (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - 1, yBodyBottom - 1, Theme.Color(clrBackground)); + + 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)); + } } void cSkinEnigmaDisplayMenu::SetTitle(const char *Title) @@ -1179,8 +1197,10 @@ void cSkinEnigmaDisplayMenu::SetMessage(eMessageType Type, const char *Text) { // check if message if (Text) { + // save osd region - osd->SaveRegion(xMessageLeft, yMessageTop, xMessageRight - 1, yMessageBottom - 1); + if (nMessagesShown == 0) + osd->SaveRegion(xMessageLeft, yMessageTop, xMessageRight - 1, yMessageBottom - 1); // draw message osd->DrawRectangle(xMessageLeft, yMessageTop, xMessageRight - 1, yMessageBottom - 1, clrTransparent); @@ -1193,9 +1213,13 @@ void cSkinEnigmaDisplayMenu::SetMessage(eMessageType Type, const char *Text) xMessageRight - Gap - xMessageLeft - Gap - 1, yMessageBottom - SmallGap - yMessageTop - 2 * SmallGap, taCenter); + nMessagesShown++; } else { + if (nMessagesShown > 0) + nMessagesShown--; // restore saved osd region - osd->RestoreRegion(); + if (nMessagesShown == 0) + osd->RestoreRegion(); } } @@ -1205,8 +1229,11 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current, int xItemRight = (fShowLogo || fShowInfo ? xBodyRight : xInfoRight) - (EnigmaConfig.showMarker ? lineHeightOsd : SmallGap); int numItems = (yBodyBottom - yBodyTop) / lineHeightOsd; int top = yBodyTop + (yBodyBottom - yBodyTop - numItems * lineHeightOsd) / 2; -// debug("top=%d yBodyTop=%d yBodyBottom=%d lineHeightOsd=%d\n", top, yBodyTop, yBodyBottom, lineHeightOsd); + int y = top + Index * lineHeightOsd; + if (nMessagesShown > 0 && y >= yMessageTop) + return; //Don't draw above messages + tColor ColorFg, ColorBg; // select colors if (Current) { @@ -1247,10 +1274,6 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current, && strchr(" V", s[1]) && strchr(" *", s[2])) { // update status iseventinfo = true; - } else if (strlen(s) == 4 && s[0] == ' ' && strchr(" tTR", s[1]) - && strchr(" V", s[2]) && strchr(" *", s[3])) { - // update status - iseventinfo = true; } // check if new recording: "01.01.06*", "10:10*" @@ -1339,20 +1362,20 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current, // define x coordinates of progressbar int px0 = xt; int px1 = (Selectable ? (Tab(i + 1) ? Tab(i + 1) : xItemRight) : xItemRight) - 1; - int px = px0 + (int) ((float) now * (float) (px1 - px0) / (float) total); + int px = px0 + max((int)((float) now * (float) (px1 - px0) / (float) total), ListProgressBarBorder); // define y coordinates of progressbar - int py0 = y + Gap; - int py1 = y + lineHeightOsd - Gap; + int py0 = y + ListProgressBarGap; + int py1 = y + lineHeightOsd - ListProgressBarGap; // draw background osd->DrawRectangle(px0, y, px1, y + lineHeightOsd - 1, ColorBg); // draw progressbar osd->DrawRectangle(px0, py0, px, py1, ColorFg); - osd->DrawRectangle(px + 1, py0, px1, py0, ColorFg); - osd->DrawRectangle(px + 1, py1, px1, py1, ColorFg); - osd->DrawRectangle(px1, py0, px1, 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 { // draw text - osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xItemRight - xt); + osd->DrawText(xt, y, s, ColorFg, ColorBg, font, xItemRight - xt, nMessagesShown ? min(yMessageTop - y, lineHeightOsd) : 0 ); } } if (!Tab(i + 1)) @@ -1374,114 +1397,116 @@ void cSkinEnigmaDisplayMenu::SetItem(const char *Text, int Index, bool Current, //debug("SetItem: %d (%s) %d %d %d\n", n, ItemText, Index, Current, Selectable); bool fFoundLogo = false; if (strcmp(ItemText, tr("Schedule")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/schedule"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/schedule"); else if (strcmp(ItemText, tr("Channels")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/channels"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/channels"); else if (strcmp(ItemText, tr("Timers")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("timerinfo")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/timers"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/timers"); else if (strcmp(ItemText, tr("Recordings")) == 0 || strcmp(ItemText, tr("Recording info")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("extrecmenu")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/recordings"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/recordings"); else if (strcmp(ItemText, tr("Setup")) == 0 || strcmp(ItemText2, tr("Setup")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/setup"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/setup"); else if (strcmp(ItemText, tr("Commands")) == 0 || strcmp(ItemText2, tr("Commands")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/commands"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/commands"); else if (strcmp(ItemText, tr(" Stop replaying")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/stop"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/stop"); else if (strcmp(ItemText, tr(" Cancel editing")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/cancel"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/cancel"); +/*TODO: obsolete? else if (strcmp(ItemText, tr("Summary")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/summary"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/summary"); +*/ else if (strcmp(ItemText2, GetPluginMainMenuName("audiorecorder")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/audiorecorder"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/audiorecorder"); else if (strcmp(ItemText2, GetPluginMainMenuName("burn")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/burn"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/burn"); else if (strcmp(ItemText2, GetPluginMainMenuName("cdda")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/cdda"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/cdda"); else if (strcmp(ItemText2, GetPluginMainMenuName("chanorg")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/chanorg"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/chanorg"); else if (strcmp(ItemText2, GetPluginMainMenuName("channelscan")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/channelscan"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/channelscan"); else if (strcmp(ItemText2, GetPluginMainMenuName("digicam")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/digicam"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/digicam"); else if (strcmp(ItemText2, GetPluginMainMenuName("director")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/director"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/director"); else if (strcmp(ItemText2, GetPluginMainMenuName("dvd")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/dvd"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/dvd"); else if (strcmp(ItemText2, GetPluginMainMenuName("dvdselect")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("dvdswitch")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/dvdselect"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/dvdselect"); else if (strcmp(ItemText2, GetPluginMainMenuName("dxr3")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("softdevice")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/device"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/device"); else if (strcmp(ItemText2, GetPluginMainMenuName("epgsearch")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("epgsearchonly")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("conflictcheckonly")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("nordlichtsepg")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/epgsearch"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/epgsearch"); else if (strcmp(ItemText2, GetPluginMainMenuName("externalplayer")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/externalplayer"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/externalplayer"); else if (strcmp(ItemText2, GetPluginMainMenuName("femon")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/femon"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/femon"); else if (strcmp(ItemText2, GetPluginMainMenuName("filebrowser")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/filebrowser"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/filebrowser"); else if (strcmp(ItemText2, GetPluginMainMenuName("fussball")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/fussball"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/fussball"); else if (strcmp(ItemText2, GetPluginMainMenuName("games")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/games"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/games"); else if (strcmp(ItemText2, GetPluginMainMenuName("image")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("osdimage")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/image"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/image"); else if (strcmp(ItemText2, GetPluginMainMenuName("mp3")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("mp3ng")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("muggle")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/mp3"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/mp3"); else if (strcmp(ItemText2, GetPluginMainMenuName("mplayer")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/mplayer"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/mplayer"); else if (strcmp(ItemText2, GetPluginMainMenuName("newsticker")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/newsticker"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/newsticker"); else if (strcmp(ItemText2, GetPluginMainMenuName("osdpip")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/osdpip"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/osdpip"); else if (strcmp(ItemText2, GetPluginMainMenuName("pin")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/pin"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/pin"); else if (strcmp(ItemText2, GetPluginMainMenuName("radio")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/radio"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/radio"); else if (strcmp(ItemText2, GetPluginMainMenuName("rotor")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/rotor"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/rotor"); else if (strcmp(ItemText2, GetPluginMainMenuName("solitaire")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/solitaire"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/solitaire"); else if (strcmp(ItemText2, GetPluginMainMenuName("streamdev-client")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("streamdev-server")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/streamdev"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/streamdev"); else if (strcmp(ItemText2, GetPluginMainMenuName("sudoku")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/sudoku"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/sudoku"); else if (strcmp(ItemText2, GetPluginMainMenuName("teletext")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("osdteletext")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/teletext"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/teletext"); else if (strcmp(ItemText2, GetPluginMainMenuName("tvonscreen")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/tvonscreen"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/tvonscreen"); else if (strcmp(ItemText2, GetPluginMainMenuName("vcd")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/vcd"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vcd"); else if (strcmp(ItemText2, GetPluginMainMenuName("vdrc")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/vdrc"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdrc"); else if (strcmp(ItemText2, GetPluginMainMenuName("vdrcd")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("mediad")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/vdrcd"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdrcd"); else if (strcmp(ItemText2, GetPluginMainMenuName("vdrrip")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/vdrrip"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdrrip"); else if (strcmp(ItemText2, GetPluginMainMenuName("weather")) == 0 || strcmp(ItemText2, GetPluginMainMenuName("weatherng")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/weather"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/weather"); else if (strcmp(ItemText2, GetPluginMainMenuName("webepg")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/webepg"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/webepg"); else if (strcmp(ItemText2, GetPluginMainMenuName("xineliboutput")) == 0) - fFoundLogo = EnigmaLogoCache.Load("icons/menu/xineliboutput"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/xineliboutput"); else - fFoundLogo = EnigmaLogoCache.Load("icons/menu/vdr"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/menu/vdr"); osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoTop - 1, Theme.Color(clrLogoBg)); if (fFoundLogo) { @@ -1518,7 +1543,7 @@ int cSkinEnigmaDisplayMenu::DrawFlag(int x, int y, const tComponent *p) } */ - if (EnigmaLogoCache.Load(flag.c_str())) { + if (EnigmaLogoCache.LoadSymbol(flag.c_str())) { osd->DrawBitmap(x, y - EnigmaLogoCache.Get().Height(), EnigmaLogoCache.Get()); return EnigmaLogoCache.Get().Width(); } @@ -1538,7 +1563,7 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event) #ifdef SKINENIGMA_NO_MENULOGO fShowLogo = false; #else - fShowLogo = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3); + fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3); #endif const cFont *font = cFont::GetFont(fontOsd); @@ -1724,10 +1749,16 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event) if (fShowLogo) { // draw logo osd->DrawRectangle(xDateLeft + SmallGap, yDateTop, xDateRight - 1, yDateBottom - SmallGap - 1, Theme.Color(clrLogoBg)); - if (EnigmaLogoCache.Load("icons/menu/schedule")) + if (EnigmaConfig.showImages && EnigmaLogoCache.LoadEventImage(Event, xLogoRight - xLogoLeft, yLogoBottom - yLogoTop, nNumImageColors)) { 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)); + yDateTop + (yDateBottom - yDateTop - EnigmaLogoCache.Get().Height()) / 2, + EnigmaLogoCache.Get(), 0, 0, true); + } else { + if (EnigmaLogoCache.LoadIcon("icons/menu/schedule")) + 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)); + } // draw borders osd->DrawRectangle(xDateLeft, yDateTop, xDateLeft + SmallGap - 1, yDateBottom - 1, clrTransparent); osd->DrawRectangle(xDateLeft, yLogoBottom - SmallGap, xDateRight, yLogoBottom - 1, clrTransparent); @@ -1735,6 +1766,28 @@ void cSkinEnigmaDisplayMenu::SetEvent(const cEvent *Event) #endif } +int cSkinEnigmaDisplayMenu::ReadSizeVdr(const char *strPath) +{ + int dirSize = -1; + char buffer[20]; + char *strFilename = NULL; + asprintf(&strFilename, "%s/size.vdr", strPath); + if (strFilename) { + struct stat st; + if (stat(strFilename, &st) == 0) { + int fd = open(strFilename, O_RDONLY); + if (fd >= 0) { + if (safe_read(fd, &buffer, sizeof(buffer)) >= 0) { + dirSize = atoi(buffer); + } + close(fd); + } + } + free(strFilename); + } + return dirSize; +} + void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording) { // check if recording @@ -1746,7 +1799,7 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording) #ifdef SKINENIGMA_NO_MENULOGO fShowLogo = false; #else - fShowLogo = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3); + fShowLogo = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 3); #endif const cRecordingInfo *Info = Recording->Info(); @@ -1754,6 +1807,11 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording) const cFont *smlfont = cFont::GetFont(fontSml); int wsb = lineHeightOsd + 2 * SmallGap; //scrollbar width + if (Info == NULL) { + //TODO: draw error message + return; + } + // draw recording date string stringstream sstrDate; sstrDate << *DateString(Recording->start) @@ -1761,12 +1819,18 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording) // draw additional information stringstream sstrInfo; - int dirSize = DirSizeMB(Recording->FileName()); + int dirSize = -1; + if (EnigmaConfig.showRecSize > 0) { + if ((dirSize = ReadSizeVdr(Recording->FileName())) < 0 && EnigmaConfig.showRecSize == 2) { + dirSize = DirSizeMB(Recording->FileName()); + } + } cChannel *channel = Channels.GetByChannelID(((cRecordingInfo *)Info)->ChannelID()); if (channel) sstrInfo << tr("Channel") << ": " << channel->Number() << " - " << channel->Name() << endl; - sstrInfo << tr("Size") << ": " << setprecision(3) << (dirSize > 1023 ? dirSize / 1024.0 : dirSize) << (dirSize > 1023 ? "GB\n" : "MB\n") - << tr("Priority") << ": " << Recording->priority << 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; if (Info->Aux()) { sstrInfo << endl << tr("Auxiliary information") << ":\n" @@ -1851,12 +1915,18 @@ void cSkinEnigmaDisplayMenu::SetRecording(const cRecording *Recording) #ifndef SKINENIGMA_NO_MENULOGO if (fShowLogo) { - // draw logo osd->DrawRectangle(xDateLeft + SmallGap, yDateTop, xDateRight - 1, yDateBottom - SmallGap - 1, Theme.Color(clrLogoBg)); - if (EnigmaLogoCache.Load("icons/menu/recordings")) + if (EnigmaConfig.showImages && EnigmaLogoCache.LoadRecordingImage(Recording, xLogoRight - xLogoLeft, yLogoBottom - yLogoTop, nNumImageColors)) { 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)); + yDateTop + (yDateBottom - yDateTop - EnigmaLogoCache.Get().Height()) / 2, + EnigmaLogoCache.Get(), 0, 0, true); + } else { + // draw logo + if (EnigmaLogoCache.LoadIcon("icons/menu/recordings")) + 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)); + } // draw borders osd->DrawRectangle(xDateLeft, yDateTop, xDateLeft + SmallGap - 1, yDateBottom - 1, clrTransparent); osd->DrawRectangle(xDateLeft, yLogoBottom - SmallGap, xDateRight, yLogoBottom - 1, clrTransparent); @@ -1979,7 +2049,7 @@ cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly) nJumpWidth = 0; lineHeight = cFont::GetFont(fontOsd)->Height(); - int LogoSize = LogoHeight; + int LogoSize = IconHeight; LogoSize += (LogoSize % 2 ? 1 : 0); xTitleLeft = 0; xTitleRight = Setup.OSDWidth; @@ -2025,6 +2095,9 @@ cSkinEnigmaDisplayReplay::cSkinEnigmaDisplayReplay(bool ModeOnly) osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayReplay: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } @@ -2100,12 +2173,12 @@ void cSkinEnigmaDisplayReplay::SetMode(bool Play, bool Forward, int Speed) if (Speed < -1) Speed = -1; - if (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2) { + if ((!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2)) { osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg)); char *logo = NULL; asprintf(&logo, "icons/menu/%s", EnigmaStatus.ReplayModeName()); - if (EnigmaLogoCache.Load(logo)) { + 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), @@ -2117,19 +2190,19 @@ void cSkinEnigmaDisplayReplay::SetMode(bool Play, bool Forward, int Speed) } if (Speed == -1) - fFoundLogo = EnigmaLogoCache.Load(Play ? "icons/replay/play" : "icons/replay/pause"); + fFoundLogo = EnigmaLogoCache.LoadIcon(Play ? "icons/replay/play" : "icons/replay/pause"); else if (Play) { if (Speed > MAX_SPEED_BITMAPS - 1) { error("MAX SPEED %d > 9\n", Speed); Speed = MAX_SPEED_BITMAPS - 1; } - fFoundLogo = EnigmaLogoCache.Load(Forward ? strFastForward_large[Speed] : strFastRewind_large[Speed]); + fFoundLogo = EnigmaLogoCache.LoadIcon(Forward ? strFastForward_large[Speed] : strFastRewind_large[Speed]); } else { // trick speed if (Speed > MAX_TRICKSPEED_BITMAPS - 1) { error("MAX SPEED %d > 3\n", Speed); Speed = MAX_TRICKSPEED_BITMAPS - 1; } - fFoundLogo = EnigmaLogoCache.Load(Forward ? strSlowForward_large[Speed] : strSlowRewind_large[Speed]); + fFoundLogo = EnigmaLogoCache.LoadIcon(Forward ? strSlowForward_large[Speed] : strSlowRewind_large[Speed]); } if (fFoundLogo) osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2, @@ -2258,10 +2331,10 @@ public: cSkinEnigmaDisplayVolume::cSkinEnigmaDisplayVolume() { - fShowSymbol = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2); + fShowSymbol = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2); lineHeight = cFont::GetFont(fontOsd)->Height(); - int LogoSize = max(3 * lineHeight + TitleDeco + SmallGap, LogoHeight); + int LogoSize = max(3 * lineHeight + TitleDeco + SmallGap, IconHeight); LogoSize += (LogoSize % 2 ? 1 : 0); xLogoLeft = 0; xLogoRight = LogoSize; @@ -2300,6 +2373,9 @@ cSkinEnigmaDisplayVolume::cSkinEnigmaDisplayVolume() osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayVolume: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } bitmap = osd->GetBitmap(1); @@ -2311,6 +2387,9 @@ cSkinEnigmaDisplayVolume::cSkinEnigmaDisplayVolume() osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayVolume: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } bitmap = osd->GetBitmap(0); @@ -2368,18 +2447,18 @@ void cSkinEnigmaDisplayVolume::SetVolume(int Current, int Total, bool Mute) ColorBar = Theme.Color(clrVolumeBarMute); Prompt = tr("Mute"); if (fShowSymbol) - fFoundLogo = EnigmaLogoCache.Load("icons/volume/muteOn"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/volume/muteOn"); } else { ColorBar = Theme.Color(clrVolumeBar); Prompt = tr("Volume"); if (fShowSymbol) - fFoundLogo = EnigmaLogoCache.Load("icons/volume/muteOff"); + fFoundLogo = EnigmaLogoCache.LoadIcon("icons/volume/muteOff"); } // logo if (fShowSymbol && fFoundLogo) osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2, yLogoTop + (yLogoBottom - yLogoTop - EnigmaLogoCache.Get().Height()) / 2, - EnigmaLogoCache.Get(),EnigmaLogoCache.Get().Color(1), + EnigmaLogoCache.Get(), EnigmaLogoCache.Get().Color(1), Theme.Color(clrLogoBg)); // current volume int vol = xBodyLeft + Gap + (xBodyRight - Gap - xBodyLeft - Gap) * Current / Total; @@ -2436,11 +2515,11 @@ public: cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTracks, const char *const *Tracks) { - fShowSymbol = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2); + fShowSymbol = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2); const cFont *font = cFont::GetFont(fontOsd); lineHeight = font->Height(); - int LogoSize = LogoHeight; + int LogoSize = IconHeight; LogoSize += (LogoSize % 2 ? 1 : 0); currentIndex = -1; int ItemsWidth = 0; @@ -2496,6 +2575,9 @@ cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTra osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayTracks: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } else { @@ -2508,6 +2590,9 @@ cSkinEnigmaDisplayTracks::cSkinEnigmaDisplayTracks(const char *Title, int NumTra osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayTracks: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } @@ -2586,10 +2671,10 @@ void cSkinEnigmaDisplayTracks::SetAudioChannel(int AudioChannel) osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg)); if (!(AudioChannel >= 0 && AudioChannel < MAX_AUDIO_BITMAPS)) AudioChannel = 0; - if (EnigmaLogoCache.Load(strAudio_large[AudioChannel])) + if (EnigmaLogoCache.LoadIcon(strAudio_large[AudioChannel])) osd->DrawBitmap(xLogoLeft + (xLogoRight - xLogoLeft - EnigmaLogoCache.Get().Width()) / 2, yLogoTop + (yLogoBottom - yLogoTop - EnigmaLogoCache.Get().Height()) / 2, - EnigmaLogoCache.Get(),EnigmaLogoCache.Get().Color(1), + EnigmaLogoCache.Get(), EnigmaLogoCache.Get().Color(1), Theme.Color(clrLogoBg)); } else { if (!(AudioChannel >= 0 && AudioChannel < MAX_AUDIO_BITMAPS)) @@ -2642,9 +2727,9 @@ public: cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage() { lineHeight = cFont::GetFont(fontOsd)->Height(); - fShowSymbol = (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2); + fShowSymbol = (!EnigmaConfig.singleArea || EnigmaConfig.singleArea8Bpp) && (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2); - int LogoSize = max(3 * lineHeight + TitleDeco + 5 * SmallGap, LogoHeight); + int LogoSize = max(3 * lineHeight + TitleDeco + 5 * SmallGap, IconHeight); LogoSize += (LogoSize % 2 ? 1 : 0); xLogoLeft = 0; @@ -2682,6 +2767,9 @@ cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage() osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayMessage: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } else { @@ -2691,6 +2779,9 @@ cSkinEnigmaDisplayMessage::cSkinEnigmaDisplayMessage() osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); else { error("cSkinEnigmaDisplayMessage: CanHandleAreas() returned %d\n", rc); + delete osd; + osd = NULL; + throw 1; return; } } @@ -2706,11 +2797,11 @@ cSkinEnigmaDisplayMessage::~cSkinEnigmaDisplayMessage() void cSkinEnigmaDisplayMessage::SetMessage(eMessageType Type, const char *Text) { - if (EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2) { + if (fShowSymbol) { // draw logo osd->DrawRectangle(xLogoLeft, yLogoTop, xLogoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg)); osd->DrawRectangle(xLogoDecoLeft, yLogoTop, xLogoDecoRight - 1, yLogoBottom - 1, Theme.Color(clrLogoBg)); - if (EnigmaLogoCache.Load("icons/message/info")) + if (EnigmaLogoCache.LoadIcon("icons/message/info")) 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)); @@ -2734,7 +2825,7 @@ void cSkinEnigmaDisplayMessage::SetMessage(eMessageType Type, const char *Text) osd->DrawEllipse(xBottomRight - Roundness, yBottomBottom - Roundness, xBottomRight - 1, yBottomBottom - 1, clrTransparent, -4); - if (!(EnigmaConfig.showSymbols == 1 || EnigmaConfig.showSymbols == 2)) { + if (!(fShowSymbol)) { // draw ellipse if not showing logo osd->DrawEllipse(xTitleLeft, yTitleTop, xTitleLeft + Roundness - 1, yTitleTop + Roundness - 1, clrTransparent, -2); osd->DrawEllipse(xBottomLeft, yBottomBottom - Roundness, @@ -2750,7 +2841,17 @@ void cSkinEnigmaDisplayMessage::Flush(void) // --- cSkinEnigma ---------------------------------------------------------- cSkinEnigma::cSkinEnigma() : cSkin("EnigmaNG", &::Theme) -{} +{ + // Get the "classic" skin to be used as fallback skin if any of the OSD + // menu fails to open. + skinFallback = Skins.First(); + for (cSkin *Skin = Skins.First(); Skin; Skin = Skins.Next(Skin)) { + if (strcmp(Skin->Name(), "classic") == 0) { + skinFallback = Skin; + break; + } + } +} const char *cSkinEnigma::Description(void) { @@ -2759,32 +2860,56 @@ const char *cSkinEnigma::Description(void) cSkinDisplayChannel *cSkinEnigma::DisplayChannel(bool WithInfo) { - return new cSkinEnigmaDisplayChannel(WithInfo); + try { + return new cSkinEnigmaDisplayChannel(WithInfo); + } catch(...) { + return skinFallback->DisplayChannel(WithInfo); + } } cSkinDisplayMenu *cSkinEnigma::DisplayMenu(void) { - return new cSkinEnigmaDisplayMenu; + try { + return new cSkinEnigmaDisplayMenu; + } catch (...) { + return skinFallback->DisplayMenu(); + } } cSkinDisplayReplay *cSkinEnigma::DisplayReplay(bool ModeOnly) { - return new cSkinEnigmaDisplayReplay(ModeOnly); + try { + return new cSkinEnigmaDisplayReplay(ModeOnly); + } catch (...) { + return skinFallback->DisplayReplay(ModeOnly); + } } cSkinDisplayVolume *cSkinEnigma::DisplayVolume(void) { - return new cSkinEnigmaDisplayVolume; + try { + return new cSkinEnigmaDisplayVolume; + } catch (...) { + return skinFallback->DisplayVolume(); + } } cSkinDisplayTracks *cSkinEnigma::DisplayTracks(const char *Title, int NumTracks, const char *const *Tracks) { - return new cSkinEnigmaDisplayTracks(Title, NumTracks, Tracks); + try { + return new cSkinEnigmaDisplayTracks(Title, NumTracks, Tracks); + } catch (...) { + return skinFallback->DisplayTracks(Title, NumTracks, Tracks); + } } cSkinDisplayMessage *cSkinEnigma::DisplayMessage(void) { - return new cSkinEnigmaDisplayMessage; + try { + return new cSkinEnigmaDisplayMessage; + } catch (...) { + return skinFallback->DisplayMessage(); + } } // vim:et:sw=2:ts=2: @@ -10,6 +10,9 @@ #include <vdr/skinclassic.h> class cSkinEnigma : public cSkin { +private: + cSkin *skinFallback; + public: cSkinEnigma(); virtual const char *Description(void); @@ -178,7 +178,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "²ëÚÛ.·ÒãÚ", // ÀãááÚØÙ (Russian) + "²ëÚÛ. ×ÒãÚ", // ÀãááÚØÙ (Russian) "", // Hrvatski "Hääletu", // Eesti "", // Dansk @@ -266,7 +266,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "¸Üï", // ÀãááÚØÙ (Russian) + "ØÜï", // ÀãááÚØÙ (Russian) "", // Hrvatski "nimi", // Eesti "", // Dansk @@ -288,7 +288,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "´ÐÝÝëÕ", // ÀãááÚØÙ (Russian) + "ÔÐÝÝëÕ", // ÀãááÚØÙ (Russian) "", // Hrvatski "andmed", // Eesti "", // Dansk @@ -310,7 +310,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "ÀÐ×ÜÕà ÚÕèÐ ÛÞÓÐâØßÞÒ ÚÐÝÐÛÞÒ", // ÀãááÚØÙ (Russian) + "ÀÐ×ÜÕà ÚÕèÐ ÛÞÓoâØßÞÒ ÚÐÝÐÛÞÒ", // ÀãááÚØÙ (Russian) "", // Hrvatski "Kanalilogo vahemälu suurus", // Eesti "", // Dansk @@ -464,7 +464,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "¾áâÐÛÞáì", // ÀãááÚØÙ (Russian) + "ÞáâÐÛìÝëÕ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -486,7 +486,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "¿àÞèÛÞ", // ÀãááÚØÙ (Russian) + "ØáâÕÚèØÕ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -508,7 +508,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "¿ÞÚÐ×ëÒÐâì ØÝä. ÞÑÛÐáâ Ò ÓÛ. ÜÕÝî", // ÀãááÚØÙ (Russian) + "¿ÞÚÐ×ëÒÐâì ØÝä. ÞÑÛÐáìâ Ò ÓÛ. ÜÕÝî", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -552,7 +552,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "¿ÞÚÐ×ëÒÐâì ßÞÛÞáã ßàÞÚàãâÚØ", // ÀãááÚØÙ (Russian) + "¿ÞÚÐ×ëÒÐâì ØÝÔØÚÐâÞà ßàÞÔÒØÖÕÝØï", // ÀãááÚØÙ (Russian) "", // Hrvatski "Edenemisriba näitamine", // Eesti "", // Dansk @@ -662,7 +662,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "ÂÐÙÜÕàë ÚÞÝäÛØÚâãîâ", // ÀãááÚØÙ (Russian) + "ºÞÝäÛØÚâë âÐÙÜÕàÞÒ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -684,7 +684,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "ÂÐÙÜÕàë", // ÀãááÚØÙ (Russian) + "°¹¼µÀË", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -706,7 +706,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "¿¾²Â¾Àµ½¸Ï", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -728,7 +728,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "½ÕßàÐÒØÛìÝëÙ ÚÐÝÐÛ", // ÀãááÚØÙ (Russian) + "*** ½ÕßàÐÒØÛìÝëÙ ÚÐÝÐÛ ***", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -772,7 +772,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "²ëÚÛ.·ÒãÚ", // ÀãááÚØÙ (Russian) + "²ëÚÛ.×ÒãÚ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -806,7 +806,7 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "Symbole dans les listes", // Français + "Symboles dans les listes", // Français "", // Norsk "Näytä tapahtumien symbolit",// suomi (Finnish) "", // Polski @@ -828,7 +828,7 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Une partie d'image (si possible)", // Français "", // Norsk "Pyri käyttämään yhtä kuva-aluetta",// suomi (Finnish) "", // Polski @@ -850,7 +850,7 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Profondeur d'une partie d'image", // Français "", // Norsk "Kuva-alueen värisyvyys", // suomi (Finnish) "", // Polski @@ -860,7 +860,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "³ÛãÑØÝÐ ÞÑÛÐáâØ Ø×ÞÑàÐÖÕÝØï", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -872,9 +872,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Afficher drapeau", // Français "", // Norsk - "", // suomi (Finnish) + "Näytä liput", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -882,7 +882,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "¿ÞÚÐ×Ðâì äÛÐÓØ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -894,9 +894,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Symboles dans le menu", // Français "", // Norsk - "", // suomi (Finnish) + "Näytä valikkosymbolit", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -904,7 +904,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "¿ÞÚÐ×Ðâì áØÜÒÞÛë Ò ÜÕÝî", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -916,9 +916,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "jamais", // Français "", // Norsk - "", // suomi (Finnish) + "ei koskaan", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -926,7 +926,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "ÝØÚÞÓÔÐ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -938,9 +938,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "toujours", // Français "", // Norsk - "", // suomi (Finnish) + "aina", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -948,7 +948,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "ÒáÕÓÔÐ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -960,9 +960,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "pas dans le menu", // Français "", // Norsk - "", // suomi (Finnish) + "ei valikossa", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -970,7 +970,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "ÝÕ Ò ÜÕÝî", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -982,9 +982,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "que dans le menu", // Français "", // Norsk - "", // suomi (Finnish) + "vain valikossa", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -992,7 +992,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "âÞÛìÚÞ Ò ÜÕÝî", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1004,9 +1004,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Pourcentage", // Français "", // Norsk - "", // suomi (Finnish) + "prosentti", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1014,7 +1014,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "ßàÞæÕÝâ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1026,9 +1026,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "si existant", // Français "", // Norsk - "", // suomi (Finnish) + "jos olemassa", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1036,7 +1036,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "ÕáÛØ Ò ÝÐÛØçØØ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1048,9 +1048,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Nombre de répétitions", // Français "", // Norsk - "", // suomi (Finnish) + "Uusintojen lukumäärä", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1058,7 +1058,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "ºÞÛØçÕáâÒÞ ßÞÒâÞàÕÝØÙ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1070,9 +1070,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Utilise sous-titre pour les répétitions", // Français "", // Norsk - "", // suomi (Finnish) + "Käytä lyhyttä kuvausta uusinnoille", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1080,7 +1080,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "¸áßÞÛì×. ßÞÔ×ÐÓÞÛÞÒÚØ ÔÛï ßÞÒâÞàÕÝØï", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1092,9 +1092,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Afficher les conflits de programmation", // Français "", // Norsk - "", // suomi (Finnish) + "Näytä päällekkäiset ajastimet", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1102,7 +1102,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "¿ÞÚÐ×Ðâì ÚÞÝäÛØÚâë âÐÙÜÕàÞÒ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1114,9 +1114,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Observation de la programmation", // Français "", // Norsk - "", // suomi (Finnish) + "Ajastimien valvonta", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1124,7 +1124,7 @@ const tI18nPhrase Phrases[] = { "", // Românã "", // Magyar "", // Català - "", // ÀãááÚØÙ (Russian) + "¿àÞÒÕàÚÐ âÐÙÜÕàÞÒ", // ÀãááÚØÙ (Russian) "", // Hrvatski "", // Eesti "", // Dansk @@ -1136,9 +1136,9 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Recherche EPG", // Français "", // Norsk - "", // suomi (Finnish) + "EPGSearch", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1158,9 +1158,296 @@ const tI18nPhrase Phrases[] = { "", // Italiano "", // Nederlands "", // Português - "", // Français + "Logos et symboles", // Français + "", // Norsk + "Logot ja symbolit", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "»ÞÓÞâØßë & áØÜÒÞÛë", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"use size.vdr only", // English + "nur size.vdr verwenden", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "utiliser seulement size.vdr", // Français Patrice Staudt 29.03.2007 + "", // Norsk + "vain jos size.vdr", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"Show recording's size", // English + "Aufnahmengröße anzeigen", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "Afficher la taille des l'enregistrements", // Français + "", // Norsk + "Näytä tallenteen koko", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"pixel algo", // English + "Pixel-Algorithmus", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "Algorithme pixel", // Français + "", // Norsk + "näytteistys", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"ratio algo", // English + "Ratio-Algorithmus", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "Algorithme ratio", // Français + "", // Norsk + "skaalaus", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"zoom image", // English + "Zoomen", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "Agrandit image", // Français + "", // Norsk + "zoomaus", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"Show event/recording images", // English + "Bilder in EPG/Aufnahmendetails", // Deutsch + "", // Slovenski + "", // Italiano + "", // Nederlands + "", // Português + "Images dans les EPG et détails d'enregistrements", // Français + "", // Norsk + "Näytä kuvat lisätietovalikossa", // suomi (Finnish) + "", // Polski + "", // Español + "", // ÅëëçíéêÜ (Greek) + "", // Svenska + "", // Românã + "", // Magyar + "", // Català + "", // ÀãááÚØÙ (Russian) + "", // Hrvatski + "", // Eesti + "", // Dansk + "", // Èesky (Czech) + }, + {"Resize images", // English + "Bildberechnung benutzt", // Deutsch + "", // Slovenski + "", // Italiano + "", // 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 + "", // 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 + "", // 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 + "", // 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 + "", // 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 + "", // Nederlands + "", // Português + "Affiche l'icone Email", // 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 + "", // Nederlands + "", // Português + "juste lors d'un Email", // Français "", // Norsk - "", // suomi (Finnish) + "jos uutta postia", // suomi (Finnish) "", // Polski "", // Español "", // ÅëëçíéêÜ (Greek) @@ -1174,5 +1461,6 @@ const tI18nPhrase Phrases[] = { "", // Dansk "", // Èesky (Czech) }, +#endif {NULL} }; @@ -5,22 +5,30 @@ * */ +#include <strings.h> + +#include "bitmap.h" #include "common.h" #include "config.h" #include "logo.h" #include <vdr/tools.h> #include <vdr/plugin.h> -#undef debug -#define debug(x...) ; - cEnigmaLogoCache EnigmaLogoCache(0); cEnigmaLogoCache::cEnigmaLogoCache(unsigned int cacheSizeP) :cacheSizeM(cacheSizeP), bitmapM(NULL) -{ } +{ +#ifdef HAVE_IMAGEMAGICK + bmpImage = new cBitmap(8, 8, 1); +#endif +} cEnigmaLogoCache::~cEnigmaLogoCache() { +#ifdef HAVE_IMAGEMAGICK + delete bmpImage; +#endif + // let's flush the cache Flush(); } @@ -37,11 +45,97 @@ bool cEnigmaLogoCache::Resize(unsigned int cacheSizeP) return true; } -bool cEnigmaLogoCache::Load(const char *fileNameP) +bool cEnigmaLogoCache::LoadEventImage(const cEvent *Event, int w, int h, int c) +{ + if (Event == NULL) + return false; + + char *strFilename = NULL; + asprintf(&strFilename, "%s/%d.%s", EnigmaConfig.GetImagesDir(), Event->EventID(), EnigmaConfig.GetImageExtension()); + int rc = LoadImage(strFilename, w, h, c); + free (strFilename); + return rc; +} + +bool cEnigmaLogoCache::LoadRecordingImage(const cRecording *Recording, int w, int h, int c) +{ + if (Recording == NULL) + return false; + + char *strFilename = NULL; + asprintf(&strFilename, "%s/%s.%s", Recording->FileName(), RECORDING_COVER, EnigmaConfig.GetImageExtension()); + int rc = LoadImage(strFilename, w, h, c); + free (strFilename); + return rc; +} + +bool cEnigmaLogoCache::LoadImage(const char *fileNameP, int w, int h, int c) { - debug("cPluginSkinEnigma::Load(%s)\n", fileNameP); + struct stat stbuf; + if (lstat(fileNameP, &stbuf) != 0) { + error("cPluginSkinEnigma::LoadImage(%s) FILE NOT FOUND\n", fileNameP); + bitmapM = NULL; + return false; + } + +#ifdef HAVE_IMAGEMAGICK + int rc = image.LoadImage(fileNameP, w, h, c, *bmpImage); + bitmapM = rc ? bmpImage : NULL; + return rc; +#else + return LoadXpm(fileNameP, w, h); +#endif +} + +bool cEnigmaLogoCache::LoadChannelLogo(const cChannel *Channel) +{ + if (Channel == NULL) + return false; + + bool fFoundLogo = false; + char *strChannelID = EnigmaConfig.useChannelId ? strdup(*Channel->GetChannelID().ToString()) : NULL; + const char *logoname = EnigmaConfig.useChannelId ? strChannelID : Channel->Name(); + if (logoname) { + char *filename = (char *)malloc(strlen(logoname) + 20 /* should be enough for folder */); + if (filename == NULL) return false; + strcpy(filename, "hqlogos/"); + strcat(filename, logoname); + if (!(fFoundLogo = Load(filename, ChannelLogoWidth, ChannelLogoHeight))) { + strcpy(filename, "logos/"); + strcat(filename, logoname); + if (!(fFoundLogo = EnigmaLogoCache.Load(filename, ChannelLogoWidth, ChannelLogoHeight))) { + fFoundLogo = Load("hqlogos/no_logo", ChannelLogoWidth, ChannelLogoHeight); //TODO? different default logo for channel/group? + } + } + free(filename); + free(strChannelID); + } + return fFoundLogo; +} + +bool cEnigmaLogoCache::LoadSymbol(const char *fileNameP) +{ + return Load(fileNameP, SymbolWidth, SymbolHeight); +} + +bool cEnigmaLogoCache::LoadIcon(const char *fileNameP) +{ + return Load(fileNameP, IconWidth, IconHeight); +} + +bool cEnigmaLogoCache::Load(const char *fileNameP, int w, int h) +{ + if (fileNameP == NULL) + return false; + + char *strFilename; + asprintf(&strFilename, "%s/%s.xpm", EnigmaConfig.GetLogoDir(), fileNameP); + if (strFilename == NULL) + return false; + + debug("cPluginSkinEnigma::Load(%s)\n", strFilename); // does the logo exist already in map - std::map < std::string, cBitmap * >::iterator i = cacheMapM.find(fileNameP); + std::map < std::string, cBitmap * >::iterator i = cacheMapM.find(strFilename); if (i != cacheMapM.end()) { // yes - cache hit! debug("cPluginSkinEnigma::Load() CACHE HIT!\n"); @@ -49,6 +143,7 @@ bool cEnigmaLogoCache::Load(const char *fileNameP) if (i->second == NULL) { debug("cPluginSkinEnigma::Load() EMPTY\n"); // empty logo in cache + free(strFilename); return false; } bitmapM = i->second; @@ -56,7 +151,8 @@ bool cEnigmaLogoCache::Load(const char *fileNameP) // no - cache miss! debug("cPluginSkinEnigma::Load() CACHE MISS!\n"); // try to load xpm logo - LoadXpm(fileNameP); + if (!LoadXpm(strFilename, w, h)) + return false; // check if cache is active if (cacheSizeM) { // update map @@ -72,16 +168,18 @@ bool cEnigmaLogoCache::Load(const char *fileNameP) cacheMapM.erase(cacheMapM.begin()); } // insert logo into map - debug("cPluginSkinEnigma::Load() INSERT(%s)\n", fileNameP); - cacheMapM.insert(std::make_pair(fileNameP, bitmapM)); + debug("cPluginSkinEnigma::Load() INSERT(%s)\n", strFilename); + cacheMapM.insert(std::make_pair(strFilename, bitmapM)); } // check if logo really exist if (bitmapM == NULL) { debug("cPluginSkinEnigma::Load() EMPTY\n"); // empty logo in cache + free(strFilename); return false; } } + free(strFilename); return true; } @@ -90,30 +188,34 @@ cBitmap & cEnigmaLogoCache::Get(void) return *bitmapM; } -bool cEnigmaLogoCache::LoadXpm(const char *fileNameP) +bool cEnigmaLogoCache::LoadXpm(const char *fileNameP, int w, int h) { + if (fileNameP == NULL) + return false; + struct stat stbuf; - char *filename; cBitmap *bmp = new cBitmap(1, 1, 1); // create absolute filename - asprintf(&filename, "%s/%s.xpm", EnigmaConfig.GetLogoDir(), fileNameP); - debug("cPluginSkinEnigma::LoadXpm(%s)\n", filename); + debug("cPluginSkinEnigma::LoadXpm(%s)\n", fileNameP); // check validity - if ((stat(filename, &stbuf) == 0) && bmp->LoadXpm(filename) - /*TODO? && (bmp->Width() == ChannelLogoWidth) - && (bmp->Height() == ChannelLogoHeight)*/) { - debug("cPluginSkinEnigma::LoadXpm() LOGO FOUND\n"); - // assign bitmap - bitmapM = bmp; - free(filename); - return true; + if ((lstat(fileNameP, &stbuf) == 0) && bmp->LoadXpm(fileNameP)) { + if ((bmp->Width() <= w) && (bmp->Height() <= h)) { + debug("cPluginSkinEnigma::LoadXpm(%s) LOGO FOUND\n", fileNameP); + // assign bitmap + bitmapM = bmp; + return true; + } else { + // wrong size + error("cPluginSkinEnigma::LoadXpm(%s) LOGO HAS WRONG SIZE %d/%d (%d/%d)\n", fileNameP, bmp->Width(), bmp->Height(), w, h); + } + } else { + // no xpm logo found + error("cPluginSkinEnigma::LoadXpm(%s) LOGO NOT FOUND\n", fileNameP); } - // no xpm logo found - delete bitmap - error("cPluginSkinEnigma::LoadXpm(%s) LOGO NOT FOUND\n", filename); + delete bmp; bitmapM = NULL; - free(filename); return false; } @@ -136,3 +238,5 @@ bool cEnigmaLogoCache::Flush(void) } return true; } + +// vim:et:sw=2:ts=2: @@ -10,22 +10,47 @@ #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 +// size of icons, e.g. icons top right in the main menu... +#define IconWidth 80 +#define IconHeight 80 +// size of symbols, e.g. the flags +#define SymbolWidth 27 +#define SymbolHeight 18 class cEnigmaLogoCache { private: + bool fImageRequested; unsigned int cacheSizeM; cBitmap *bitmapM; +#ifdef HAVE_IMAGEMAGICK + cOSDImageBitmap image; + cBitmap *bmpImage; +#endif std::map<std::string, cBitmap*> cacheMapM; - bool LoadXpm(const char *fileNameP); + bool LoadImage(const char *fileNameP, int w, int h, int c); + bool LoadXpm(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 Load(const char *fileNameP); + 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); cBitmap& Get(void); bool Flush(void); }; diff --git a/skinenigmang.c b/skinenigmang.c index 323cffb..10ad221 100644 --- a/skinenigmang.c +++ b/skinenigmang.c @@ -18,12 +18,13 @@ #error "VDR-1.4.0 API version or greater is required!" #endif -static const char VERSION[] = "0.0.3"; +static const char VERSION[] = "0.0.4"; static const char DESCRIPTION[] = "EnigmaNG skin"; class cPluginSkinEnigma : public cPlugin { private: - bool fLogodirSet; + bool fLogodirSet; + bool fImagesDirSet; public: cPluginSkinEnigma(void); @@ -61,6 +62,11 @@ private: 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); @@ -76,7 +82,8 @@ cPluginSkinEnigma::cPluginSkinEnigma(void) // initialize any member variables here. // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! - fLogodirSet = false; + fLogodirSet = false; + fImagesDirSet = false; } cPluginSkinEnigma::~cPluginSkinEnigma() @@ -87,28 +94,34 @@ cPluginSkinEnigma::~cPluginSkinEnigma() const char *cPluginSkinEnigma::CommandLineHelp(void) { // return a string that describes all known command line options. - return " -l <LOGODIR>, --logodir=<LOGODIR> Define a directory for channel logos.\n"; + return " -i <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored\n" + " -l <LOGODIR>, --logodir=<LOGODIR> Set directory where logos are stored.\n"; } 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' }, - { NULL } - }; - - int c; - while ((c = getopt_long(argc, argv, "l:", long_options, NULL)) != -1) { - switch (c) { - case 'l': - EnigmaConfig.SetLogoDir(optarg); - fLogodirSet = true; - break; - default: - return false; - } - } + static const struct option long_options[] = { + { "logodir", required_argument, NULL, 'l' }, + { "epgimages", required_argument, NULL, 'i' }, + { NULL } + }; + + int c; + while ((c = getopt_long(argc, argv, "l:i:", long_options, NULL)) != -1) { + switch (c) { + case 'i': + EnigmaConfig.SetImagesDir(optarg); + fImagesDirSet = true; + break; + case 'l': + EnigmaConfig.SetLogoDir(optarg); + fLogodirSet = true; + break; + default: + return false; + } + } return true; } @@ -124,11 +137,21 @@ bool cPluginSkinEnigma::Start(void) // start any background activities the plugin shall perform. debug("cPluginSkinEnigma::Start()\n"); RegisterI18n(Phrases); - if (!fLogodirSet) { - // set logo directory - EnigmaConfig.SetLogoDir(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N)); - fLogodirSet = true; - } + if (!fLogodirSet) { + // set logo directory + EnigmaConfig.SetLogoDir(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N)); + fLogodirSet = true; + } + if (!fImagesDirSet) { + // set epgimages directory + char *dir = NULL; + asprintf(&dir, "%s/epgimages", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N)); + if (dir) { + EnigmaConfig.SetImagesDir(dir); + fImagesDirSet = true; + free(dir); + } + } // resize logo cache EnigmaLogoCache.Resize(EnigmaConfig.cacheSize); // create skin @@ -198,6 +221,22 @@ bool cPluginSkinEnigma::SetupParse(const char *Name, const char *Value) 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; @@ -234,13 +273,15 @@ cPluginSkinEnigmaSetup::cPluginSkinEnigmaSetup(void) void cPluginSkinEnigmaSetup::AddCategory(const char *Title) { char *buffer = NULL; - asprintf(&buffer, "--- %s ----------------------------------------------------------------", Title ); + asprintf(&buffer, "--- %s ----------------------------------------------------------------------------------", Title ); cOsdItem *item = new cOsdItem(buffer); free(buffer); - item->SetSelectable(false); - Add(item); + if (item) { + item->SetSelectable(false); + Add(item); + } } void cPluginSkinEnigmaSetup::Setup(void) @@ -252,8 +293,13 @@ void cPluginSkinEnigmaSetup::Setup(void) 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"); @@ -263,16 +309,36 @@ void cPluginSkinEnigmaSetup::Setup(void) 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, + 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, @@ -281,24 +347,59 @@ void cPluginSkinEnigmaSetup::Setup(void) tr("no"), tr("yes"))); AddCategory(tr("Logos & Symbols")); - Add(new cMenuEditStraItem(tr("Show symbols"), &data.showSymbols, - 4, showSymbolsTexts)); + 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"))); - Add(new cMenuEditBoolItem(tr("Show flags"), &data.showFlags, - tr("no"), tr("yes"))); - Add(new cMenuEditBoolItem(tr("Show channel logos"), &data.showLogo, - tr("no"), tr("yes"))); + if (!data.singleArea || data.singleArea8Bpp) { + Add(new cMenuEditBoolItem(tr("Show flags"), &data.showFlags, + tr("no"), tr("yes"))); + } - if (data.showLogo) { - Add(new cMenuEditBoolItem(tr("Identify channel by"), &data.useChannelId, - tr("name"), tr("data"))); +#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 + } } - if (data.showLogo || data.showSymbols) { - Add(new cMenuEditIntItem(tr("Channel logo cache size"), &data.cacheSize, - 0, 1000)); +#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 @@ -339,6 +440,14 @@ void cPluginSkinEnigmaSetup::Store(void) 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); } @@ -348,8 +457,10 @@ eOSState cPluginSkinEnigmaSetup::ProcessKey(eKeys Key) // process key presses int oldShowLogo = data.showLogo; int oldShowSymbols = data.showSymbols; - int oldSingleArea = data.singleArea; + 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)) { @@ -358,7 +469,14 @@ eOSState cPluginSkinEnigmaSetup::ProcessKey(eKeys Key) Skins.Message(mtInfo, NULL); state = osContinue; } - if (Key != kNone && ((data.singleArea != oldSingleArea) || (data.showLogo != oldShowLogo) || (data.showSymbols != oldShowSymbols) || (oldShowInfo != data.showInfo))) { + if (Key != kNone && + ((data.singleArea != oldSingleArea) + || (data.singleArea8Bpp != oldSingleArea8Bpp) + || (data.showLogo != oldShowLogo) + || (data.showSymbols != oldShowSymbols) + || (oldShowInfo != data.showInfo) + || (oldShowImages != data.showImages) + )) { Setup(); } @@ -366,3 +484,4 @@ eOSState cPluginSkinEnigmaSetup::ProcessKey(eKeys Key) } VDRPLUGINCREATOR(cPluginSkinEnigma); // don't touch this! +// vim:et:sw=2:ts=2: diff --git a/symbols/small/mail.xpm b/symbols/small/mail.xpm new file mode 100644 index 0000000..2eb5158 --- /dev/null +++ b/symbols/small/mail.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * mail_xpm[] = { +"27 18 3 1", +" c None", +". c #8D8F8D", +"+ c #000000", +"...........................", +"...........................", +"..+++++++++++++++++++++++..", +"..+++++++++++++++++++++++..", +"..++++...............++++..", +"..++.++.............++.++..", +"..++..++...........++..++..", +"..++...++.........++...++..", +"..++....++.......++....++..", +"..++....+++.....+++....++..", +"..++...++.++...++.++...++..", +"..++..++...++.++...++..++..", +"..++.++.....+++.....++.++..", +"..++++.......+.......++++..", +"..+++++++++++++++++++++++..", +"..+++++++++++++++++++++++..", +"...........................", +"..........................."}; diff --git a/themes/EnigmaNG-AppleGreen.theme b/themes/EnigmaNG-AppleGreen.theme index cce1922..862645a 100644 --- a/themes/EnigmaNG-AppleGreen.theme +++ b/themes/EnigmaNG-AppleGreen.theme @@ -12,15 +12,16 @@ clrTitleShadow = FF000000 clrSymbolActive = FF41C400 clrSymbolInactive = FF808080 clrSymbolRecord = FFC40000 +clrSymbolRecordBg = FFFFFFFF clrSymbolTimerActive = FF98C400 clrSymbolVpsActive = FFC4C400 clrSymbolRecActive = FFC40000 clrSymbolRunActive = FF00C400 clrButtonRedFg = FFFFFFFF clrButtonRedBg = E5C40000 -clrButtonGreenFg = FFFFFFFF +clrButtonGreenFg = FF000000 clrButtonGreenBg = E500C400 -clrButtonYellowFg = FFFFFFFF +clrButtonYellowFg = FF000000 clrButtonYellowBg = E5C4C400 clrButtonBlueFg = FFFFFFFF clrButtonBlueBg = E50000C4 diff --git a/themes/EnigmaNG-DarkBlue.theme b/themes/EnigmaNG-DarkBlue.theme index 923e5ad..264ff6b 100644 --- a/themes/EnigmaNG-DarkBlue.theme +++ b/themes/EnigmaNG-DarkBlue.theme @@ -12,6 +12,7 @@ clrTitleShadow = FF000000 clrSymbolActive = FFC4C400 clrSymbolInactive = FF808080 clrSymbolRecord = FFC40000 +clrSymbolRecordBg = FFFFFFFF clrSymbolTimerActive = FF0000C4 clrSymbolVpsActive = FFC4C400 clrSymbolRecActive = FFC40000 diff --git a/themes/EnigmaNG-WineRed.theme b/themes/EnigmaNG-WineRed.theme index f5e4b6c..513271e 100644 --- a/themes/EnigmaNG-WineRed.theme +++ b/themes/EnigmaNG-WineRed.theme @@ -12,15 +12,16 @@ clrTitleShadow = FF000000 clrSymbolActive = FF20C400 clrSymbolInactive = FF808080 clrSymbolRecord = FFC40000 +clrSymbolRecordBg = FFFFFFFF clrSymbolTimerActive = FF0000C4 clrSymbolVpsActive = FFC4C400 clrSymbolRecActive = FFC40000 clrSymbolRunActive = FF00C400 clrButtonRedFg = FFFFFFFF clrButtonRedBg = E5C40000 -clrButtonGreenFg = FFFFFFFF +clrButtonGreenFg = FF000000 clrButtonGreenBg = E500C400 -clrButtonYellowFg = FFFFFFFF +clrButtonYellowFg = FF000000 clrButtonYellowBg = E5C4C400 clrButtonBlueFg = FFFFFFFF clrButtonBlueBg = E50000C4 diff --git a/themes/EnigmaNG-WomenLike.theme b/themes/EnigmaNG-WomenLike.theme index c7309a7..a50cd3f 100644 --- a/themes/EnigmaNG-WomenLike.theme +++ b/themes/EnigmaNG-WomenLike.theme @@ -12,15 +12,16 @@ clrTitleShadow = FF000000 clrSymbolActive = FF41C400 clrSymbolInactive = FF808080 clrSymbolRecord = FFC40000 +clrSymbolRecordBg = FFFFFFFF clrSymbolTimerActive = FF0000C4 clrSymbolVpsActive = FFC4C400 clrSymbolRecActive = FFC40000 clrSymbolRunActive = FF00C400 clrButtonRedFg = FFFFFFFF clrButtonRedBg = E5C40000 -clrButtonGreenFg = FFFFFFFF +clrButtonGreenFg = FF000000 clrButtonGreenBg = E500C400 -clrButtonYellowFg = FFFFFFFF +clrButtonYellowFg = FF000000 clrButtonYellowBg = E5C4C400 clrButtonBlueFg = FFFFFFFF clrButtonBlueBg = E50000C4 diff --git a/themes/EnigmaNG-YellowSun.theme b/themes/EnigmaNG-YellowSun.theme index fe8c0ff..0617ff1 100644 --- a/themes/EnigmaNG-YellowSun.theme +++ b/themes/EnigmaNG-YellowSun.theme @@ -12,13 +12,14 @@ clrTitleShadow = FF9f9f9f clrSymbolActive = FFb12e2e clrSymbolInactive = FF808080 clrSymbolRecord = FFC40000 +clrSymbolRecordBg = FFFFFFFF clrSymbolTimerActive = FFe98400 clrSymbolVpsActive = FF002ec4 clrSymbolRecActive = FFC40000 clrSymbolRunActive = FF00C400 clrButtonRedFg = FFFFFFFF clrButtonRedBg = E5C40000 -clrButtonGreenFg = FFFFFFFF +clrButtonGreenFg = FF000000 clrButtonGreenBg = E500C400 clrButtonYellowFg = FF000000 clrButtonYellowBg = E5f4f115 diff --git a/themes/EnigmaNG-default.theme b/themes/EnigmaNG-default.theme index 743f8be..e2ed390 100644 --- a/themes/EnigmaNG-default.theme +++ b/themes/EnigmaNG-default.theme @@ -12,15 +12,16 @@ clrTitleShadow = FF000000 clrSymbolActive = FFC4C400 clrSymbolInactive = FF808080 clrSymbolRecord = FFC40000 +clrSymbolRecordBg = FFFFFFFF clrSymbolTimerActive = FF0000C4 clrSymbolVpsActive = FFC4C400 clrSymbolRecActive = FFC40000 clrSymbolRunActive = FF00C400 clrButtonRedFg = FFFFFFFF clrButtonRedBg = E5C40000 -clrButtonGreenFg = FFFFFFFF +clrButtonGreenFg = FF000000 clrButtonGreenBg = E500C400 -clrButtonYellowFg = FFFFFFFF +clrButtonYellowFg = FF000000 clrButtonYellowBg = E5C4C400 clrButtonBlueFg = FFFFFFFF clrButtonBlueBg = E50000C4 |