diff options
author | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
commit | b0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch) | |
tree | 22b302342f22843e0815eb5f516c85f1478cbf0b /libcore/imagecache.c | |
download | vdr-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.c | 389 |
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); + } +} |