summaryrefslogtreecommitdiff
path: root/libcore/imagecache.c
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2014-09-27 09:25:14 +0200
committerlouis <louis.braun@gmx.de>2014-09-27 09:25:14 +0200
commitb0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch)
tree22b302342f22843e0815eb5f516c85f1478cbf0b /libcore/imagecache.c
downloadvdr-plugin-skindesigner-b0509b5182b6e0d04f05e6b3d5676b0d21f51966.tar.gz
vdr-plugin-skindesigner-b0509b5182b6e0d04f05e6b3d5676b0d21f51966.tar.bz2
initial commit version 0.0.10.0.1
Diffstat (limited to 'libcore/imagecache.c')
-rw-r--r--libcore/imagecache.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/libcore/imagecache.c b/libcore/imagecache.c
new file mode 100644
index 0000000..7347c0a
--- /dev/null
+++ b/libcore/imagecache.c
@@ -0,0 +1,389 @@
+#include <string>
+#include <sstream>
+#include <map>
+#include <fstream>
+#include <sys/stat.h>
+#include "imagecache.h"
+#include "../config.h"
+#include "helpers.h"
+
+using namespace Magick;
+
+cMutex cImageCache::mutex;
+
+string cImageCache::items[16] = { "Schedule", "Channels", "Timers", "Recordings", "Setup", "Commands",
+ "OSD", "EPG", "DVB", "LNB", "CAM", "Recording", "Replay", "Miscellaneous", "Plugins", "Restart"};
+
+cImageCache::cImageCache() : cImageMagickWrapper() {
+ tempStaticLogo = NULL;
+}
+
+cImageCache::~cImageCache() {
+ Clear();
+ if (tempStaticLogo) {
+ delete tempStaticLogo;
+ tempStaticLogo = NULL;
+ }
+}
+
+void cImageCache::CacheLogo(int width, int height) {
+ if (config.numLogosPerSizeInitial == 0)
+ return;
+ if (width == 0 || height == 0)
+ return;
+
+ int channelsCached = 0;
+
+ for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
+ if (channelsCached >= config.numLogosPerSizeInitial)
+ break;
+ if (channel->GroupSep()) {
+ continue;
+ }
+ bool success = LoadLogo(channel);
+ if (success) {
+ channelsCached++;
+ cImage *image = CreateImage(width, height);
+ stringstream logoName;
+ logoName << *channel->GetChannelID().ToString() << "_" << width << "x" << height;
+ std::map<std::string, cImage*>::iterator hit = channelLogoCache.find(logoName.str());
+ if (hit != channelLogoCache.end()) {
+ delete image;
+ return;
+ }
+ channelLogoCache.insert(pair<string, cImage*>(logoName.str(), image));
+ }
+ }
+}
+
+cImage *cImageCache::GetLogo(string channelID, int width, int height) {
+ cMutexLock MutexLock(&mutex);
+
+ stringstream logoName;
+ logoName << channelID << "_" << width << "x" << height;
+
+ std::map<std::string, cImage*>::iterator hit = channelLogoCache.find(logoName.str());
+
+ if (hit != channelLogoCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ tChannelID chanID = tChannelID::FromString(channelID.c_str());
+ const cChannel *channel = Channels.GetByChannelID(chanID);
+ if (!channel)
+ return NULL;
+ bool success = LoadLogo(channel);
+ if (success) {
+ if (config.limitLogoCache && (channelLogoCache.size() >= config.numLogosMax)) {
+ //logo cache is full, don't cache anymore
+ if (tempStaticLogo) {
+ delete tempStaticLogo;
+ tempStaticLogo = NULL;
+ }
+ tempStaticLogo = CreateImage(width, height);
+ return tempStaticLogo;
+ } else {
+ //add requested logo to cache
+ cImage *image = CreateImage(width, height);
+ channelLogoCache.insert(pair<string, cImage*>(logoName.str(), image));
+ hit = channelLogoCache.find(logoName.str());
+ if (hit != channelLogoCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+cImage *cImageCache::GetSeparatorLogo(string name, int width, int height) {
+ cMutexLock MutexLock(&mutex);
+
+ stringstream logoName;
+ logoName << name << "_" << width << "x" << height;
+
+ std::map<std::string, cImage*>::iterator hit = channelLogoCache.find(logoName.str());
+
+ if (hit != channelLogoCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ bool success = LoadSeparatorLogo(name);
+ if (success) {
+ //add requested logo to cache
+ cImage *image = CreateImage(width, height);
+ channelLogoCache.insert(pair<string, cImage*>(logoName.str(), image));
+ hit = channelLogoCache.find(logoName.str());
+ if (hit != channelLogoCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ }
+ return NULL;
+}
+
+bool cImageCache::LogoExists(string channelID) {
+ tChannelID chanID = tChannelID::FromString(channelID.c_str());
+ const cChannel *channel = Channels.GetByChannelID(chanID);
+ if (!channel)
+ return false;
+ string logoPath = *cString::sprintf("%s%s/logos/", *config.skinPath, Setup.OSDTheme);
+ string logoLower = StrToLowerCase(channel->Name());
+ string logoExt = *config.logoExtension;
+ bool logoExists = FileExists(logoPath, logoLower, logoExt);
+ if (logoExists) {
+ return true;
+ }
+ logoExists = FileExists(logoPath, channelID, logoExt);
+ if (logoExists) {
+ return true;
+ }
+ return false;
+}
+
+bool cImageCache::SeparatorLogoExists(string name) {
+ string separatorPath = *cString::sprintf("%s%s/logos/separatorlogos/", *config.skinPath, Setup.OSDTheme);
+ string nameLower = StrToLowerCase(name.c_str());
+ string logoExt = *config.logoExtension;
+ bool logoExists = FileExists(separatorPath, nameLower, logoExt);
+ if (logoExists) {
+ return true;
+ }
+ return false;
+}
+
+void cImageCache::CacheIcon(eImageType type, string name, int width, int height) {
+ if (width < 1 || width > 1920 || height < 1 || height > 1080)
+ return;
+ bool success = LoadIcon(type, name);
+ if (!success)
+ return;
+ stringstream iconName;
+ iconName << name << "_" << width << "x" << height;
+ cImage *image = CreateImage(width, height, true);
+ iconCache.insert(pair<string, cImage*>(iconName.str(), image));
+}
+
+cImage *cImageCache::GetIcon(eImageType type, string name, int width, int height) {
+ if (width < 1 || width > 1920 || height < 1 || height > 1080)
+ return NULL;
+ cMutexLock MutexLock(&mutex);
+ stringstream iconName;
+ iconName << name << "_" << width << "x" << height;
+ map<string, cImage*>::iterator hit = iconCache.find(iconName.str());
+ if (hit != iconCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ bool success = LoadIcon(type, name);
+ if (!success)
+ return NULL;
+ cImage *image = CreateImage(width, height, true);
+ iconCache.insert(pair<string, cImage*>(iconName.str(), image));
+ hit = iconCache.find(iconName.str());
+ if (hit != iconCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ return NULL;
+}
+
+string cImageCache::GetIconName(string label) {
+ //check for standard menu entries
+ for (int i=0; i<16; i++) {
+ string s = trVDR(items[i].c_str());
+ if (s == label) {
+ return *cString::sprintf("standardicons/%s", items[i].c_str());
+ }
+ }
+ //check for special main menu entries "stop recording", "stop replay"
+ string stopRecording = skipspace(trVDR(" Stop recording "));
+ string stopReplay = skipspace(trVDR(" Stop replaying"));
+ try {
+ if (label.substr(0, stopRecording.size()) == stopRecording) {
+ return "standardicons/StopRecording";
+ }
+ if (label.substr(0, stopReplay.size()) == stopReplay) {
+ return "standardicons/StopReplay";
+ }
+ } catch (...) {}
+ //check for Plugins
+ for (int i = 0; ; i++) {
+ cPlugin *p = cPluginManager::GetPlugin(i);
+ if (p) {
+ const char *mainMenuEntry = p->MainMenuEntry();
+ if (mainMenuEntry) {
+ string plugMainEntry = mainMenuEntry;
+ try {
+ if (label.substr(0, plugMainEntry.size()) == plugMainEntry) {
+ return *cString::sprintf("pluginicons/%s", p->Name());
+ }
+ } catch (...) {}
+ }
+ } else
+ break;
+ }
+ return *cString::sprintf("customicons/%s", label.c_str());
+}
+
+void cImageCache::CacheSkinpart(string name, int width, int height) {
+ if (width < 1 || width > 1920 || height < 1 || height > 1080)
+ return;
+ bool success = LoadSkinpart(name);
+ if (!success)
+ return;
+ stringstream iconName;
+ iconName << name << "_" << width << "x" << height;
+ cImage *image = CreateImage(width, height, false);
+ skinPartsCache.insert(pair<string, cImage*>(iconName.str(), image));
+}
+
+cImage *cImageCache::GetSkinpart(string name, int width, int height) {
+ if (width < 1 || width > 1920 || height < 1 || height > 1080)
+ return NULL;
+ cMutexLock MutexLock(&mutex);
+ stringstream iconName;
+ iconName << name << "_" << width << "x" << height;
+ map<string, cImage*>::iterator hit = skinPartsCache.find(iconName.str());
+ if (hit != skinPartsCache.end()) {
+ return (cImage*)hit->second;
+ } else {
+ bool success = LoadSkinpart(name);
+ if (!success)
+ return NULL;
+ cImage *image = CreateImage(width, height, false);
+ skinPartsCache.insert(pair<string, cImage*>(iconName.str(), image));
+ hit = skinPartsCache.find(iconName.str());
+ if (hit != skinPartsCache.end()) {
+ return (cImage*)hit->second;
+ }
+ }
+ return NULL;
+}
+
+bool cImageCache::LoadIcon(eImageType type, string name) {
+ bool success = false;
+ cString subdir("");
+ if (type == itMenuIcon)
+ subdir = "menuicons";
+ else if (type == itIcon)
+ subdir = "icons";
+ cString iconPath = cString::sprintf("%s%s/graphics/%s/", *config.skinPath, Setup.OSDTheme, *subdir);
+ success = LoadImage(name, *iconPath, "png");
+ if (success) {
+ return true;
+ }
+ return false;
+}
+
+bool cImageCache::LoadLogo(const cChannel *channel) {
+ if (!channel)
+ return false;
+ cString logoPath = cString::sprintf("%s%s/logos/", *config.skinPath, Setup.OSDTheme);
+ string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
+ string logoLower = StrToLowerCase(channel->Name());
+ bool success = false;
+ success = LoadImage(channelID.c_str(), *logoPath, *config.logoExtension);
+ if (success)
+ return true;
+ success = LoadImage(logoLower.c_str(), *logoPath, *config.logoExtension);
+ if (success)
+ return true;
+ return false;
+}
+
+bool cImageCache::LoadSeparatorLogo(string name) {
+ cString separatorPath = cString::sprintf("%s%s/logos/separatorlogos/", *config.skinPath, Setup.OSDTheme);
+ string nameLower = StrToLowerCase(name.c_str());
+ bool success = false;
+ success = LoadImage(nameLower.c_str(), *separatorPath, *config.logoExtension);
+ if (success)
+ return true;
+ return false;
+}
+
+bool cImageCache::LoadSkinpart(string name) {
+ bool success = false;
+ cString iconPath = cString::sprintf("%s%s/graphics/skinparts/", *config.skinPath, Setup.OSDTheme);
+ success = LoadImage(name, *iconPath, "png");
+ if (success) {
+ return true;
+ }
+ return false;
+}
+
+void cImageCache::Clear(void) {
+ for(map<string, cImage*>::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ iconCache.clear();
+
+ for(map<string, cImage*>::const_iterator it = channelLogoCache.begin(); it != channelLogoCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ channelLogoCache.clear();
+
+ for(map<std::string, cImage*>::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) {
+ cImage *img = (cImage*)it->second;
+ delete img;
+ }
+ skinPartsCache.clear();
+}
+
+void cImageCache::Debug(bool full) {
+ int sizeIconCache = 0;
+ int numIcons = 0;
+ GetIconCacheSize(numIcons, sizeIconCache);
+ dsyslog("skindesigner: cached %d icons - size %d byte", numIcons, sizeIconCache);
+ if (full) {
+ for(std::map<std::string, cImage*>::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) {
+ string name = it->first;
+ dsyslog("skindesigner: cached icon %s", name.c_str());
+ }
+ }
+
+ int sizeLogoCache = 0;
+ int numLogos = 0;
+ GetLogoCacheSize(numLogos, sizeLogoCache);
+ dsyslog("skindesigner: cached %d logos - size %d byte", numLogos, sizeLogoCache);
+ if (full) {
+ for(std::map<std::string, cImage*>::const_iterator it = channelLogoCache.begin(); it != channelLogoCache.end(); it++) {
+ string name = it->first;
+ dsyslog("skindesigner: cached logo %s", name.c_str());
+ }
+ }
+
+ int sizeSkinpartCache = 0;
+ int numSkinparts = 0;
+ GetSkinpartsCacheSize(numSkinparts, sizeSkinpartCache);
+ dsyslog("skindesigner: cached %d skinparts - size %d byte", numSkinparts, sizeSkinpartCache);
+ if (full) {
+ for(std::map<std::string, cImage*>::const_iterator it = skinPartsCache.begin(); it != skinPartsCache.end(); it++) {
+ string name = it->first;
+ dsyslog("skindesigner: cached skinpart %s", name.c_str());
+ }
+ }
+}
+
+void cImageCache::GetIconCacheSize(int &num, int &size) {
+ num = iconCache.size();
+ for (map<string, cImage*>::iterator icon = iconCache.begin(); icon != iconCache.end(); icon++) {
+ cImage* img = icon->second;
+ size += img->Width() * img->Height() * sizeof(tColor);
+ }
+}
+
+void cImageCache::GetLogoCacheSize(int &num, int &size) {
+ num = channelLogoCache.size();
+ for (map<string, cImage*>::iterator logo = channelLogoCache.begin(); logo != channelLogoCache.end(); logo++) {
+ cImage* img = logo->second;
+ size += img->Width() * img->Height() * sizeof(tColor);
+ }
+}
+
+void cImageCache::GetSkinpartsCacheSize(int &num, int &size) {
+ num = skinPartsCache.size();
+ for (map<string, cImage*>::iterator skinpart = skinPartsCache.begin(); skinpart != skinPartsCache.end(); skinpart++) {
+ cImage* img = skinpart->second;
+ size += img->Width() * img->Height() * sizeof(tColor);
+ }
+}