vdr-plugin-skindesigner/config.c

538 lines
17 KiB
C

#include "config.h"
#include "extensions/helpers.h"
#include "extensions/imageloader.h"
cDesignerConfig::cDesignerConfig() {
tmplGlobals = NULL;
epgImagePathSet = false;
skinPathSet = false;
installerSkinPathSet = false;
logoPathSet = false;
//Common
cacheImagesInitial = 1;
numLogosPerSizeInitial = 30;
limitLogoCache = 1;
numLogosMax = 200;
debugImageLoading = 0;
replaceDecPoint = false;
//settings for rerun display
useSubtitleRerun = 0;
rerunAmount = 10;
rerunDistance = 2;
rerunMaxChannel = 0;
//max number of custom int and string tokens
numCustomTokens = 10;
//Frames per Second to display animations
FPS = 50;
//remember current skin and theme, osd size and osd fonts
SetSkin();
SetOSDSize();
SetOSDFonts();
osdLanguage = "";
setupCloseDoReload = false;
}
cDesignerConfig::~cDesignerConfig() {
ClearSkinSetups();
for (vector<cTheme*>::iterator it = themes.begin(); it != themes.end(); it++) {
delete *it;
}
}
void cDesignerConfig::SetPathes(void) {
if (!skinPathSet)
skinPath = cString::sprintf("%s/skins/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
if (!installerSkinPathSet)
installerSkinPath = cString::sprintf("%s/installerskins/", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
if (!logoPathSet)
logoPath = cString::sprintf("%s/logos/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
if (!epgImagePathSet)
epgImagePath = cString::sprintf("%s/epgimages/", cPlugin::CacheDirectory(PLUGIN_NAME_I18N));
dsyslog("skindesigner: using Skin Directory %s", *skinPath);
#ifndef DO_NOT_USE_SKININSTALLER
dsyslog("skindesigner: using Installer Skin Directory %s", *installerSkinPath);
#endif
dsyslog("skindesigner: using common ChannelLogo Directory %s", *logoPath);
dsyslog("skindesigner: using EPG Images Directory %s", *epgImagePath);
vdrThemesPath = cPlugin::ConfigDirectory(PLUGIN_NAME_I18N);
size_t found = vdrThemesPath.find("/plugins");
if (found != string::npos)
vdrThemesPath = vdrThemesPath.substr(0, found);
vdrThemesPath += "/themes/";
}
void cDesignerConfig::SetSkinPath(cString path) {
skinPath = CheckSlashAtEnd(*path);
skinPathSet = true;
}
void cDesignerConfig::SetInstallerSkinPath(cString path) {
installerSkinPath = CheckSlashAtEnd(*path);
installerSkinPathSet = true;
}
void cDesignerConfig::SetLogoPath(cString path) {
logoPath = CheckSlashAtEnd(*path);
logoPathSet = true;
}
void cDesignerConfig::SetEpgImagePath(cString path) {
epgImagePath = CheckSlashAtEnd(*path);
epgImagePathSet = true;
}
bool cDesignerConfig::GetThemeColor(string &name, tColor &col) {
if (!tmplGlobals)
return false;
return tmplGlobals->GetColor(name, col);
}
void cDesignerConfig::StoreTheme(cTheme *theme) {
themes.push_back(theme);
}
void cDesignerConfig::ReadSkinFolder(cString &skinFolder, vector<string> *container) {
DIR *folder = NULL;
struct dirent *dirEntry;
folder = opendir(skinFolder);
if (!folder) {
esyslog("skindesigner: no skins found in %s", *skinFolder);
return;
}
while (dirEntry = readdir(folder)) {
string dirEntryName = dirEntry->d_name;
int dirEntryType = dirEntry->d_type;
cString subfolder = cString::sprintf("%s%s", *skinFolder, dirEntryName.c_str());
if (!dirEntryName.compare(".") || !dirEntryName.compare("..") || !dirEntryName.compare("skinrepositories"))
continue;
if (dirEntryType != DT_DIR && dirEntryType != DT_LNK && !DirectoryOk(*subfolder, false))
continue;
container->push_back(dirEntryName);
}
dsyslog("skindesigner %ld skins found in %s", container->size(), *skinFolder);
}
void cDesignerConfig::ReadSkins(void) {
ReadSkinFolder(skinPath, &deliveredSkins);
#ifndef DO_NOT_USE_SKININSTALLER
ReadSkinFolder(installerSkinPath, &installerSkins);
#endif
for (vector<string>::iterator it = deliveredSkins.begin(); it != deliveredSkins.end(); it++) {
skins.push_back(*it);
}
#ifndef DO_NOT_USE_SKININSTALLER
for (vector<string>::iterator it = installerSkins.begin(); it != installerSkins.end(); it++) {
string instSkin = *it;
bool found = false;
for (vector<string>::iterator it2 = deliveredSkins.begin(); it2 != deliveredSkins.end(); it2++) {
if (!instSkin.compare(*it2)) {
found = true;
break;
}
}
if (!found)
skins.push_back(instSkin);
}
#endif
}
void cDesignerConfig::ClearSkinSetups(void) {
for (map < string, cSkinSetup* >::iterator it = skinSetups.begin(); it != skinSetups.end(); it++) {
delete it->second;
}
skinSetups.clear();
}
void cDesignerConfig::DebugSkinSetups(void) {
dsyslog("skindesigner: skin setups:");
InitSetupIterator();
cSkinSetup *skinSetup = NULL;
while (skinSetup = GetNextSkinSetup()) {
skinSetup->Debug();
}
}
void cDesignerConfig::DebugSkinSetupParameters(void) {
dsyslog("skindesigner: skin setup parameters:");
for (vector<pair<string, int> >::iterator it = skinSetupParameters.begin(); it != skinSetupParameters.end(); it++) {
dsyslog("skindesigner: parameter %s value %d", (*it).first.c_str(), (*it).second);
}
}
void cDesignerConfig::ReadSkinSetup(string skin) {
cSkinSetup *skinSetup = new cSkinSetup(skin);
if (skinSetup->ReadFromXML()) {
//skinSetup->Debug();
skinSetups.insert(pair<string, cSkinSetup* >(skin, skinSetup));
}
}
bool cDesignerConfig::GetSkin(string &skin) {
if (skinIterator == skins.end()) {
return false;
}
skin = *skinIterator;
skinIterator++;
return true;
}
cString cDesignerConfig::GetSkinPath(string skin) {
for (vector<string>::iterator it = deliveredSkins.begin(); it != deliveredSkins.end(); it++) {
if (!skin.compare(*it)) {
return skinPath;
}
}
return installerSkinPath;
}
void cDesignerConfig::AddNewSkinRef(string skin) {
cTheme *theme = new cTheme();
StoreTheme(theme);
cSkinDesigner *newSkin = new cSkinDesigner(skin, theme);
AddSkin(newSkin);
skins.push_back(skin);
installerSkins.push_back(skin);
ReadSkinSetup(skin);
map < string, cSkinSetup* >::iterator hit = skinSetups.find(skin);
if (hit != skinSetups.end())
(hit->second)->TranslateSetup();
}
bool cDesignerConfig::SkinActive(string skin) {
cSkin *activeSkin = Skins.Current();
if (activeSkin && !skin.compare(activeSkin->Name()))
return true;
return false;
}
void cDesignerConfig::DeleteSkin(string skin) {
dsyslog("skindesigner: deleting skin %s", skin.c_str());
cSkin *deleteSkin = NULL;
bool found = false;
for (deleteSkin = Skins.First(); deleteSkin; deleteSkin = Skins.Next(deleteSkin)) {
if (!skin.compare(deleteSkin->Name())) {
found = true;
break;
}
}
if (!found || !deleteSkin) {
esyslog("skindesigner: skin %s to delete not found", skin.c_str());
return;
}
vector<cSkinDesigner*>::iterator delIt;
for (delIt = skinRefs.begin(); delIt != skinRefs.end(); delIt++) {
if (*delIt == deleteSkin)
break;
}
if (delIt != skinRefs.end())
skinRefs.erase(delIt);
vector<string>::iterator delIt2;
for (delIt2 = installerSkins.begin(); delIt2 != installerSkins.end(); delIt2++) {
if (!skin.compare(*delIt2))
break;
}
if (delIt2 != installerSkins.end())
installerSkins.erase(delIt2);
vector<string>::iterator delIt3;
for (delIt3 = skins.begin(); delIt3 != skins.end(); delIt3++) {
if (!skin.compare(*delIt3))
break;
}
if (delIt3 != skins.end())
skins.erase(delIt3);
Skins.Del(deleteSkin);
stringstream deletePath;
deletePath << *installerSkinPath << skin;
string delPath = deletePath.str();
if (FolderExists(delPath)) {
dsyslog("skindesigner: deleting skin %s", delPath.c_str());
cString command = cString::sprintf("rm -rf %s", delPath.c_str());
int ok = system(*command);
if (!ok) {
esyslog("skindesigner: error deleting skin %s", delPath.c_str());
}
}
}
cSkinDesigner* cDesignerConfig::GetNextSkinRef(void) {
if (skinRefsIterator == skinRefs.end()) {
return NULL;
}
cSkinDesigner *skin = *skinRefsIterator;
skinRefsIterator++;
return skin;
}
cSkinSetup* cDesignerConfig::GetSkinSetup(string &skin) {
map< string, cSkinSetup* >::iterator hit = skinSetups.find(skin);
if (hit != skinSetups.end()) {
return hit->second;
}
return NULL;
}
cSkinSetup* cDesignerConfig::GetNextSkinSetup(void) {
if (setupIt == skinSetups.end()) {
return NULL;
}
cSkinSetup* skinSetup = setupIt->second;
setupIt++;
return skinSetup;
}
cSkinSetupMenu* cDesignerConfig::GetSkinSetupMenu(string &skin, string &menu) {
cSkinSetup *skinSetup = GetSkinSetup(skin);
if (!skinSetup)
return NULL;
return skinSetup->GetMenu(menu);
}
void cDesignerConfig::TranslateSetup(void) {
for (map< string, cSkinSetup* >::iterator it = skinSetups.begin(); it != skinSetups.end(); it++) {
(it->second)->TranslateSetup();
}
}
void cDesignerConfig::UpdateSkinSetupParameter(string name, int value) {
vector<pair<string,int> >::iterator hit;
for (hit = skinSetupParameters.begin(); hit != skinSetupParameters.end(); hit++) {
if (!name.compare((*hit).first)) {
skinSetupParameters.erase(hit);
break;
}
}
skinSetupParameters.push_back(pair<string,int>(name, value));
}
void cDesignerConfig::SetSkinSetupParameters(void) {
for (vector < pair <string, int> >::iterator it = skinSetupParameters.begin(); it != skinSetupParameters.end(); it++) {
string name = (*it).first;
int value = (*it).second;
InitSkinIterator();
string activeSkin = "";
bool skinFound = false;
while (GetSkin(activeSkin)) {
stringstream checkString;
checkString << activeSkin << ".";
size_t hit = name.find(checkString.str());
if (hit != 0)
continue;
skinFound = true;
break;
}
if (skinFound) {
cSkinSetup* skinSetup = GetSkinSetup(activeSkin);
if (skinSetup != NULL) {
string paramName = name.substr(activeSkin.size()+1);
cSkinSetupParameter *skinSetupParam = skinSetup->GetParameter(paramName);
if (skinSetupParam) {
skinSetupParam->value = value;
continue;
}
}
}
esyslog("skindesigner: ERROR Unknown Setup Parameter %s", name.c_str());
}
}
void cDesignerConfig::ReadSkinRepos(void) {
#ifndef DO_NOT_USE_SKININSTALLER
skinRepos.Init(*installerSkinPath);
skinRepos.Read(*installerSkinPath);
dsyslog("skindesigner: read %d skinrepositories from %s", skinRepos.Count(), *installerSkinPath);
#endif
}
bool cDesignerConfig::CheckVersion(string name, string &neededVersion) {
cSkinRepo *repo = skinRepos.GetRepo(name);
if (!repo)
return false;
neededVersion = repo->MinSDVersion();
splitstring minVer(neededVersion.c_str());
vector<string> tokensMinVer = minVer.split('.', 1);
if (tokensMinVer.size() != 3) {
esyslog("skindesigner: incorrect minimumskindesignerversion definition: %s", neededVersion.c_str());
return false;
}
splitstring ver(version.c_str());
vector<string> tokensVer = ver.split('.', 1);
if (tokensVer.size() < 3) {
esyslog("skindesigner: incorrect version definition: %s", version.c_str());
return false;
}
int minVerMajor = atoi(tokensMinVer[0].c_str());
int minVerMinor = atoi(tokensMinVer[1].c_str());
int minVerMikro = atoi(tokensMinVer[2].c_str());
int verMajor = atoi(tokensVer[0].c_str());
int verMinor = atoi(tokensVer[1].c_str());
int verMikro = atoi(tokensVer[2].c_str());
if (minVerMajor < verMajor)
return true;
if (minVerMajor > verMajor)
return false;
if (minVerMinor < verMinor)
return true;
if (minVerMinor > verMinor)
return false;
if (minVerMikro <= verMikro)
return true;
return false;
}
bool cDesignerConfig::SkinInstalled(string name) {
for (vector<string>::iterator it = installerSkins.begin(); it != installerSkins.end(); it++) {
if (!name.compare(*it))
return true;
}
return false;
}
void cDesignerConfig::UpdateGlobals(void) {
string activeSkin = Setup.OSDSkin;
cSkinSetup *skinSetupActiveSkin = GetSkinSetup(activeSkin);
if (skinSetupActiveSkin && tmplGlobals) {
dsyslog("skindesigner: globals for skin %s adapted to skin setup", activeSkin.c_str());
skinSetupActiveSkin->AddToGlobals(tmplGlobals);
}
}
void cDesignerConfig::CheckDecimalPoint(void) {
struct lconv *pLocInfo;
pLocInfo = localeconv();
string decimalPoint = pLocInfo->decimal_point;
if (decimalPoint.compare(".")) {
dsyslog("skindesigner: using decimal point %s", decimalPoint.c_str());
replaceDecPoint = true;
decPoint = decimalPoint[0];
}
}
void cDesignerConfig::SetSkin(void) {
osdSkin = Setup.OSDSkin;
osdTheme = Setup.OSDTheme;
}
bool cDesignerConfig::SkinChanged(void) {
bool changed = false;
if (osdSkin.compare(Setup.OSDSkin) != 0) {
dsyslog("skindesigner: skin changed from %s to %s", osdSkin.c_str(), Setup.OSDSkin);
changed = true;
}
if (osdTheme.compare(Setup.OSDTheme) != 0) {
dsyslog("skindesigner: theme changed from %s to %s", osdTheme.c_str(), Setup.OSDTheme);
changed = true;
}
if (changed)
SetSkin();
return changed;
}
void cDesignerConfig::SetOSDSize(void) {
osdSize.SetWidth(cOsd::OsdWidth());
osdSize.SetHeight(cOsd::OsdHeight());
osdSize.SetX(cOsd::OsdLeft());
osdSize.SetY(cOsd::OsdTop());
}
bool cDesignerConfig::OsdSizeChanged(void) {
if ((osdSize.Width() != cOsd::OsdWidth()) ||
(osdSize.Height() != cOsd::OsdHeight()) ||
(osdSize.X() != cOsd::OsdLeft()) ||
(osdSize.Y() != cOsd::OsdTop())) {
dsyslog("skindesigner: osd size changed");
dsyslog("skindesigner: old osd size: top %d left %d size %d * %d", osdSize.X(), osdSize.Y(), osdSize.Width(), osdSize.Height());
SetOSDSize();
dsyslog("skindesigner: new osd size: top %d left %d size %d * %d", osdSize.X(), osdSize.Y(), osdSize.Width(), osdSize.Height());
return true;
}
return false;
}
// If softhddevice is suspended, it gives the video size 0x0
// We use this for detect a play mode change and drop the cache, because it is corrupted after being suspended
bool cDesignerConfig::PlayModeChanged(void) {
if (mode_changed) {
mode_changed = 0;
return true;
}
return false;
}
void cDesignerConfig::SetOSDFonts(void) {
fontFix = Setup.FontFix;
fontOsd = Setup.FontOsd;
fontSml = Setup.FontSml;
}
bool cDesignerConfig::OsdFontsChanged(void) {
bool changed = false;
if (fontFix.compare(Setup.FontFix) != 0) {
changed = true;
}
if (fontOsd.compare(Setup.FontOsd) != 0) {
changed = true;
}
if (fontSml.compare(Setup.FontSml) != 0) {
changed = true;
}
if (changed)
SetOSDFonts();
return changed;
}
bool cDesignerConfig::OsdLanguageChanged(void) {
if (osdLanguage.compare(Setup.OSDLanguage)) {
osdLanguage = Setup.OSDLanguage;
return true;
}
return false;
}
cString cDesignerConfig::GetSkinRessourcePath(void) {
return cString::sprintf("%s%s", *skinPath, osdSkin.c_str());
}
cString cDesignerConfig::CheckSlashAtEnd(std::string path) {
try {
if (!(path.at(path.size()-1) == '/'))
return cString::sprintf("%s/", path.c_str());
} catch (...) {return path.c_str();}
return path.c_str();
}
bool cDesignerConfig::SetupParse(const char *Name, const char *Value) {
bool pluginSetupParam = true;
if (!strcasecmp(Name, "DebugImageLoading")) debugImageLoading = atoi(Value);
else if (!strcasecmp(Name, "CacheImagesInitial")) cacheImagesInitial = atoi(Value);
else if (!strcasecmp(Name, "LimitChannelLogoCache")) limitLogoCache = atoi(Value);
else if (!strcasecmp(Name, "NumberLogosInitially")) numLogosPerSizeInitial = atoi(Value);
else if (!strcasecmp(Name, "NumberLogosMax")) numLogosMax = atoi(Value);
else if (!strcasecmp(Name, "UseSubtitleRerun")) useSubtitleRerun = atoi(Value);
else if (!strcasecmp(Name, "RerunAmount")) rerunAmount = atoi(Value);
else if (!strcasecmp(Name, "RerunDistance")) rerunDistance = atoi(Value);
else if (!strcasecmp(Name, "RerunMaxChannel")) rerunMaxChannel = atoi(Value);
else if (!strcasecmp(Name, "NumCustomTokens")) numCustomTokens = atoi(Value);
else if (!strcasecmp(Name, "FPS")) FPS = atoi(Value);
else pluginSetupParam = false;
if (!pluginSetupParam) {
skinSetupParameters.push_back(pair <string, int>(Name, atoi(Value)));
}
return true;
}