summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--README11
-rw-r--r--config.c23
-rw-r--r--config.h6
-rw-r--r--libcore/helpers.c2
-rw-r--r--libcore/skinrepo.c255
-rw-r--r--libcore/skinrepo.h67
-rw-r--r--skindesigner.c10
-rw-r--r--skins/skinrepositories.xml32
9 files changed, 400 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index cc1c790..a99944f 100644
--- a/Makefile
+++ b/Makefile
@@ -74,6 +74,7 @@ OBJS = $(PLUGIN).o \
libcore/imageloader.o \
libcore/recfolderinfo.o \
libcore/skinsetup.o \
+ libcore/skinrepo.o \
libcore/extrecinfo.o \
libcore/timers.o \
libtemplate/globals.o \
diff --git a/README b/README
index 3d886c8..dcd850b 100644
--- a/README
+++ b/README
@@ -65,7 +65,12 @@ After installation you have to care about the paths for the XML skins and epg im
The following paths can be set at startup:
-s <SKINPATH>, --skinpath=<SKINPATH>
- Path to the XML skins (Default: <ResourceDirectory>/plugins/skindesigner/skins/)
+ Path where XML skins get installed by "make install" or by package manager
+ (Default: <ResourceDirectory>/plugins/skindesigner/skins/)
+
+-i <INSTALLERPATH>, --installerpath=<INSTALLERPATH>
+ Path where XML skins are installed by the Skindesigner Installer
+ (Default: <ConfigDirectory>/plugins/skindesigner/installerskins/)
-l <LOGOPATH>, --logopath=<LOGOPATH>
Path to common logo set for all skins (Default: <ResourceDirectory>/plugins/skindesigner/logos/)
@@ -73,11 +78,11 @@ The following paths can be set at startup:
-e path, --epgimages=path
Path to the epgimages (Default: <CacheDirectory>/epgimages/)
-ResourceDirectory and CacheDirectory are taken from your VDR configuration
+ResourceDirectory, ConfigDirectory and CacheDirectory are taken from your VDR configuration
(make.config or vdr.pc).
During a "make install" the included skins are automatically copied from
-<SkinSourceDirectory>/skins/ to the configured path.
+<SkinSourceDirectory>/skins/ to the configured skin path.
For S2-6400 Users: Disable High Level OSD, otherwise the plugin will not be
loaded because lack of true color support
diff --git a/config.c b/config.c
index b870cec..92feb46 100644
--- a/config.c
+++ b/config.c
@@ -6,6 +6,7 @@ cDesignerConfig::cDesignerConfig() {
tmplGlobals = NULL;
epgImagePathSet = false;
skinPathSet = false;
+ installerSkinPathSet = false;
logoPathSet = false;
//Common
numLogosPerSizeInitial = 30;
@@ -37,12 +38,15 @@ cDesignerConfig::~cDesignerConfig() {
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);
+ dsyslog("skindesigner: using Installer Skin Directory %s", *installerSkinPath);
dsyslog("skindesigner: using common ChannelLogo Directory %s", *logoPath);
dsyslog("skindesigner: using EPG Images Directory %s", *epgImagePath);
}
@@ -52,6 +56,11 @@ void cDesignerConfig::SetSkinPath(cString path) {
skinPathSet = true;
}
+void cDesignerConfig::SetInstallerSkinPath(cString path) {
+ installerSkinPath = CheckSlashAtEnd(*path);
+ installerSkinPathSet = true;
+}
+
void cDesignerConfig::SetLogoPath(cString path) {
logoPath = CheckSlashAtEnd(*path);
logoPathSet = true;
@@ -141,7 +150,6 @@ cSkinSetupMenu* cDesignerConfig::GetSkinSetupMenu(string &skin, string &menu) {
cSkinSetup *skinSetup = GetSkinSetup(skin);
if (!skinSetup)
return NULL;
- esyslog("skindesigner: skinsetup found");
return skinSetup->GetMenu(menu);
}
@@ -195,6 +203,19 @@ void cDesignerConfig::SetSkinSetupParameters(void) {
}
}
+void cDesignerConfig::ReadSkinRepos(void) {
+ skinRepos.Read(*skinPath);
+ skinRepos.Debug();
+ /*
+ cSkinRepo *holo = skinRepos.GetRepo("Holo");
+ if (holo) {
+ esyslog("skindesigner: installing Holo");
+ holo->Install(*installerSkinPath);
+ }
+ */
+}
+
+
void cDesignerConfig::UpdateGlobals(void) {
string activeSkin = Setup.OSDSkin;
cSkinSetup *skinSetupActiveSkin = GetSkinSetup(activeSkin);
diff --git a/config.h b/config.h
index 6b3a037..d3c6066 100644
--- a/config.h
+++ b/config.h
@@ -11,6 +11,7 @@
#include "libcore/imagecache.h"
#include "libcore/recfolderinfo.h"
#include "libcore/skinsetup.h"
+#include "libcore/skinrepo.h"
#define SCRIPTOUTPUTPATH "/tmp/skindesigner"
@@ -19,6 +20,7 @@ private:
cString CheckSlashAtEnd(string path);
bool epgImagePathSet;
bool skinPathSet;
+ bool installerSkinPathSet;
bool logoPathSet;
cRect osdSize;
string osdSkin;
@@ -40,12 +42,14 @@ private:
map < string, cSkinSetup* > skinSetups;
map < string, cSkinSetup* >::iterator setupIt;
vector < pair <string, int> > skinSetupParameters;
+ cSkinRepos skinRepos;
public:
cDesignerConfig();
~cDesignerConfig();
bool SetupParse(const char *Name, const char *Value);
void SetPathes(void);
void SetSkinPath(cString path);
+ void SetInstallerSkinPath(cString path);
void SetLogoPath(cString path);
void SetEpgImagePath(cString path);
void ReadSkins(void);
@@ -62,6 +66,7 @@ public:
void TranslateSetup(void);
void SetSkinSetupParameters(void);
void UpdateSkinSetupParameter(string name, int value);
+ void ReadSkinRepos(void);
void SetGlobals(cGlobals *globals) { tmplGlobals = globals; };
void UpdateGlobals(void);
void CheckDecimalPoint(void);
@@ -84,6 +89,7 @@ public:
int GetPluginViewElementID(string pluginName, string viewElementName, int viewID);
int GetPluginViewGridID(string pluginName, string viewGridName, int viewID);
cString skinPath;
+ cString installerSkinPath;
cString logoPath;
cString epgImagePath;
bool replaceDecPoint;
diff --git a/libcore/helpers.c b/libcore/helpers.c
index add1f7a..6aef313 100644
--- a/libcore/helpers.c
+++ b/libcore/helpers.c
@@ -1,6 +1,7 @@
#include <string>
#include <sstream>
#include <vector>
+#include <stdlib.h>
#include "helpers.h"
#include <vdr/skins.h>
@@ -245,4 +246,3 @@ string GetScreenAspectString(double aspect, bool *isWideScreen) {
}
return name;
}
-
diff --git a/libcore/skinrepo.c b/libcore/skinrepo.c
new file mode 100644
index 0000000..1d5e3e4
--- /dev/null
+++ b/libcore/skinrepo.c
@@ -0,0 +1,255 @@
+#include "skinrepo.h"
+#include "../libcore/helpers.h"
+
+using namespace std;
+
+// --- cSkinRepo -------------------------------------------------------------
+
+cSkinRepo::cSkinRepo(void) {
+ name = "";
+ repoType = rtUndefined;
+ url = "";
+ command = "";
+ tempfile = "";
+ result = -1;
+}
+
+cSkinRepo::~cSkinRepo() {
+}
+
+void cSkinRepo::Install(string path) {
+ if (Running())
+ return;
+ if (repoType == rtGit) {
+
+ command = *cString::sprintf("git clone --progress %s %s%s", url.c_str(), path.c_str(), name.c_str());
+ tempfile = *cString::sprintf("gitclone_%s_%ld.out", name.c_str(), time(0));
+
+ Start();
+
+ } else if (repoType == rtZipUrl) {
+
+ //TODO
+
+ }
+}
+
+void cSkinRepo::Action(void) {
+ if (command.size() < 1)
+ return;
+ if (tempfile.size() > 0) {
+ command = *cString::sprintf("%s > /tmp/%s 2>&1", command.c_str(), tempfile.c_str());
+ }
+ dsyslog("skindesigner: executing %s", command.c_str());
+ result = system (command.c_str());
+ dsyslog("skindesigner: execution done, result: %d", result);
+}
+
+void cSkinRepo::Debug() {
+ string strRepoType = "Undefined";
+ if (repoType == rtGit)
+ strRepoType = "Git";
+ else if (repoType == rtZipUrl)
+ strRepoType = "ZipUrl";
+ dsyslog("skindesigner: --- skinrepo %s, Type %s ---", name.c_str(), strRepoType.c_str());
+ dsyslog("skindesigner: url %s", url.c_str());
+ if (specialFonts.size() > 0) {
+ for (vector<string>::iterator it = specialFonts.begin(); it != specialFonts.end(); it++) {
+ dsyslog("skindesigner: special font %s", (*it).c_str());
+ }
+ }
+ if (supportedPlugins.size() > 0) {
+ for (vector<string>::iterator it = supportedPlugins.begin(); it != supportedPlugins.end(); it++) {
+ dsyslog("skindesigner: supported plugin %s", (*it).c_str());
+ }
+ }
+ if (screenshots.size() > 0) {
+ for (vector<pair<string,string> >::iterator it = screenshots.begin(); it != screenshots.end(); it++) {
+ string desc = (it->first).c_str();
+ string url = (it->second).c_str();
+ dsyslog("skindesigner: screenshot \"%s\", url %s", desc.c_str(), url.c_str());
+ }
+ }
+}
+
+// --- cSkinRepos -------------------------------------------------------------
+
+cSkinRepos::cSkinRepos(void) {
+ repoFile = "skinrepositories.xml";
+ doc = NULL;
+}
+
+cSkinRepos::~cSkinRepos() {
+ for (vector<cSkinRepo*>::iterator it = repos.begin(); it != repos.end(); it++) {
+ delete (*it);
+ }
+}
+
+void cSkinRepos::Read(string path) {
+ string filepath = path + repoFile;
+ esyslog("skindesigner: reading skinrepos from %s", filepath.c_str());
+ xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
+ xmlNodePtr root = NULL;
+
+ doc = xmlCtxtReadFile(ctxt, filepath.c_str(), NULL, XML_PARSE_NOENT);
+ if (doc == NULL) {
+ esyslog("skindesigner: ERROR: skinrepository file %s not loaded successfully.", filepath.c_str());
+ return;
+ }
+
+ root = xmlDocGetRootElement(doc);
+ if (root == NULL) {
+ return;
+ }
+
+ if (xmlStrcmp(root->name, (const xmlChar *) "skinrepositories")) {
+ return;
+ }
+
+ xmlNodePtr node = root->xmlChildrenNode;
+ while (node != NULL) {
+ if (node->type != XML_ELEMENT_NODE) {
+ node = node->next;
+ continue;
+ }
+ if (xmlStrcmp(node->name, (const xmlChar *) "skinrepo")) {
+ continue;
+ }
+ ReadRepository(node->xmlChildrenNode);
+ node = node->next;
+ }
+
+ if (doc) xmlFreeDoc(doc);
+ xmlFreeParserCtxt(ctxt);
+}
+
+cSkinRepo *cSkinRepos::GetRepo(string name) {
+ for (vector<cSkinRepo*>::iterator it = repos.begin(); it != repos.end(); it++) {
+ cSkinRepo *repo = (*it);
+ if (!name.compare(repo->Name()))
+ return repo;
+ }
+ return NULL;
+}
+
+
+void cSkinRepos::Debug(void) {
+ for (vector<cSkinRepo*>::iterator it = repos.begin(); it != repos.end(); it++) {
+ (*it)->Debug();
+ }
+}
+
+void cSkinRepos::ReadRepository(xmlNodePtr node) {
+ if (!node)
+ return;
+ cSkinRepo *repo = new cSkinRepo();
+ while (node != NULL) {
+ if (node->type != XML_ELEMENT_NODE) {
+ node = node->next;
+ continue;
+ }
+
+ xmlChar *value = NULL;
+ //Repo Name
+ if (!xmlStrcmp(node->name, (const xmlChar *) "name")) {
+ value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ if (value)
+ repo->SetName((const char *)value);
+ //Repo Type
+ } else if (!xmlStrcmp(node->name, (const xmlChar *) "type")) {
+ value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ if (value) {
+ eRepoType repoType = rtUndefined;
+ if (!xmlStrcmp(value, (const xmlChar *) "git"))
+ repoType = rtGit;
+ else if (!xmlStrcmp(value, (const xmlChar *) "zip"))
+ repoType = rtZipUrl;
+ repo->SetRepoType(repoType);
+ }
+ //Repo URL
+ } else if (!xmlStrcmp(node->name, (const xmlChar *) "url")) {
+ value = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+ if (value)
+ repo->SetUrl((const char *)value);
+ //Repo Specialfonts
+ } else if (!xmlStrcmp(node->name, (const xmlChar *) "specialfonts")) {
+ xmlNodePtr child = node->xmlChildrenNode;
+ while (child != NULL) {
+ if (child->type != XML_ELEMENT_NODE) {
+ child = child->next;
+ continue;
+ }
+ if (!xmlStrcmp(child->name, (const xmlChar *) "font")) {
+ xmlChar *fontvalue = NULL;
+ fontvalue = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+ if (fontvalue) {
+ repo->SetSpecialFont((const char *)fontvalue);
+ xmlFree(fontvalue);
+ }
+ }
+ child = child->next;
+ }
+ //Repo supported Plugins
+ } else if (!xmlStrcmp(node->name, (const xmlChar *) "supportedplugins")) {
+ xmlNodePtr child = node->xmlChildrenNode;
+ while (child != NULL) {
+ if (child->type != XML_ELEMENT_NODE) {
+ child = child->next;
+ continue;
+ }
+ if (!xmlStrcmp(child->name, (const xmlChar *) "plugin")) {
+ xmlChar *plugvalue = NULL;
+ plugvalue = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+ if (plugvalue) {
+ repo->SetSupportedPlugin((const char *)plugvalue);
+ xmlFree(plugvalue);
+ }
+ }
+ child = child->next;
+ }
+ //Repo Screenshots
+ } else if (!xmlStrcmp(node->name, (const xmlChar *) "screenshots")) {
+ xmlNodePtr child = node->xmlChildrenNode;
+ while (child != NULL) {
+ if (child->type != XML_ELEMENT_NODE) {
+ child = child->next;
+ continue;
+ }
+ if (!xmlStrcmp(child->name, (const xmlChar *) "screenshot")) {
+ xmlNodePtr subchild = child->xmlChildrenNode;
+ string desc = "";
+ string url = "";
+ while (subchild != NULL) {
+ if (subchild->type != XML_ELEMENT_NODE) {
+ subchild = subchild->next;
+ continue;
+ }
+ xmlChar *screenshotvalue = NULL;
+ if (!xmlStrcmp(subchild->name, (const xmlChar *) "description")) {
+ screenshotvalue = xmlNodeListGetString(doc, subchild->xmlChildrenNode, 1);
+ if (screenshotvalue) {
+ desc = (const char *)screenshotvalue;
+ xmlFree(screenshotvalue);
+ }
+ } else if (!xmlStrcmp(subchild->name, (const xmlChar *) "url")) {
+ screenshotvalue = xmlNodeListGetString(doc, subchild->xmlChildrenNode, 1);
+ if (screenshotvalue) {
+ url = (const char *)screenshotvalue;
+ xmlFree(screenshotvalue);
+ }
+ }
+ subchild = subchild->next;
+ }
+ repo->SetScreenshot(desc, url);
+ }
+ child = child->next;
+ }
+ }
+ if (value)
+ xmlFree(value);
+ node = node->next;
+
+ }
+ repos.push_back(repo);
+}
+
diff --git a/libcore/skinrepo.h b/libcore/skinrepo.h
new file mode 100644
index 0000000..c3daaf0
--- /dev/null
+++ b/libcore/skinrepo.h
@@ -0,0 +1,67 @@
+#ifndef __SKINREPO_H
+#define __SKINREPO_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlerror.h>
+#include <vdr/plugin.h>
+
+using namespace std;
+
+enum eRepoType {
+ rtUndefined,
+ rtGit,
+ rtZipUrl
+};
+
+// --- cSkinRepo -------------------------------------------------------------
+
+class cSkinRepo : public cThread {
+private:
+ string name;
+ eRepoType repoType;
+ string url;
+ vector<string> specialFonts;
+ vector<string> supportedPlugins;
+ vector< pair < string, string > > screenshots;
+ //helpers for execution
+ string command;
+ string tempfile;
+ int result;
+ virtual void Action(void);
+public:
+ cSkinRepo(void);
+ virtual ~cSkinRepo(void);
+ void SetName(string name) { this->name = name; };
+ void SetRepoType(eRepoType type) { this->repoType = type; };
+ void SetUrl(string url) { this->url = url; };
+ void SetSpecialFont(string font) { specialFonts.push_back(font); };
+ void SetSupportedPlugin(string plugin) { supportedPlugins.push_back(plugin); };
+ void SetScreenshot(string desc, string url) { screenshots.push_back(pair<string, string>(desc, url)); };
+ string Name(void) { return name; };
+ void Install(string path);
+ bool InstallationFinished(void) { return !(Running()); };
+ void Debug(void);
+};
+
+// --- cSkinRepos -------------------------------------------------------------
+
+class cSkinRepos {
+private:
+ string repoFile;
+ xmlDocPtr doc;
+ vector<cSkinRepo*> repos;
+ void ReadRepository(xmlNodePtr node);
+public:
+ cSkinRepos(void);
+ virtual ~cSkinRepos(void);
+ void Read(string path);
+ cSkinRepo *GetRepo(string name);
+ void Debug(void);
+};
+
+#endif //__SKINREPO_H
diff --git a/skindesigner.c b/skindesigner.c
index a8aecae..cae0e6e 100644
--- a/skindesigner.c
+++ b/skindesigner.c
@@ -62,7 +62,8 @@ cPluginSkinDesigner::~cPluginSkinDesigner() {
const char *cPluginSkinDesigner::CommandLineHelp(void) {
return
- " -s <SKINPATH>, --skinpath=<SKINPATH> Set directory where xml skins are stored\n"
+ " -s <SKINPATH>, --skinpath=<SKINPATH> Set directory where xml skins are stored by Package Manager\n"
+ " -i <INSTALLERPATH>, --installerpath=<INSTALLERPATH> Set directory where xml skins are stored by Installer\n"
" -l <LOGOPATH>, --logopath=<LOGOPATH> Set directory where a common logo set for all skins is stored\n"
" -e <EPGIMAGESPATH>, --epgimages=<IMAGESPATH> Set directory where epgimages are stored\n";
}
@@ -73,11 +74,12 @@ bool cPluginSkinDesigner::ProcessArgs(int argc, char *argv[]) {
{ "epgimages", required_argument, NULL, 'e' },
{ "logopath", required_argument, NULL, 'l' },
{ "skinpath", required_argument, NULL, 's' },
+ { "installerpath", required_argument, NULL, 'i' },
{ 0, 0, 0, 0 }
};
int c;
- while ((c = getopt_long(argc, argv, "e:s:l:", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "e:s:l:i:", long_options, NULL)) != -1) {
switch (c) {
case 'e':
config.SetEpgImagePath(cString(optarg));
@@ -88,6 +90,9 @@ bool cPluginSkinDesigner::ProcessArgs(int argc, char *argv[]) {
case 's':
config.SetSkinPath(cString(optarg));
break;
+ case 'i':
+ config.SetInstallerSkinPath(cString(optarg));
+ break;
default:
return false;
}
@@ -128,6 +133,7 @@ bool cPluginSkinDesigner::Start(void) {
}
config.TranslateSetup();
config.SetSkinSetupParameters();
+ config.ReadSkinRepos();
if (skins.size() == 0) {
esyslog("skindesigner: no skins found! Using default Skin LCARS!");
diff --git a/skins/skinrepositories.xml b/skins/skinrepositories.xml
new file mode 100644
index 0000000..051471d
--- /dev/null
+++ b/skins/skinrepositories.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<skinrepositories>
+ <skinrepo>
+ <name>Holo</name>
+ <type>git</type>
+ <url>https://github.com/CReimer/Holo</url>
+ <specialfonts>
+ <font>Roboto</font>
+ <font>Gedöns</font>
+ </specialfonts>
+ </skinrepo>
+ <skinrepo>
+ <name>Tryouts</name>
+ <type>git</type>
+ <url>https://github.com/BooStars/tryouts</url>
+ <screenshots>
+ <screenshot>
+ <description>Main Menu</description>
+ <url>http://www.vdr-portal.de/index.php?page=AttachmentattachmentID=37054h=1e3680e599888c373fa21ad2fcbb9e4c2c73a620</url>
+ </screenshot>
+ <screenshot>
+ <description>display Channel</description>
+ <url>http://www.vdr-portal.de/index.php?page=AttachmentattachmentID=37056h=e7cd1c6d2bd8042b6c08629c8f5d4711e8196e5f</url>
+ </screenshot>
+ </screenshots>
+ <supportedplugins>
+ <plugin>Weatherforecast</plugin>
+ <plugin>TVGuideNG</plugin>
+ </supportedplugins>
+ </skinrepo>
+</skinrepositories>