vdr-plugin-skindesigner/skindesigner.c

378 lines
12 KiB
C
Raw Normal View History

2014-09-27 09:25:14 +02:00
/*
* skindesigner.c: A plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
* $Id$
*/
#include <getopt.h>
#include <vdr/plugin.h>
#include <vdr/device.h>
2014-09-27 09:25:14 +02:00
#define DEFINE_CONFIG 1
#include "config.h"
#include "designer.h"
#include "setup.h"
2016-01-26 18:32:38 +01:00
#include "libskindesignerapi/skindesignerapi.h"
2016-05-04 16:21:42 +02:00
#include "extensions/globaltimers.h"
2014-09-27 09:25:14 +02:00
2016-03-13 16:06:17 +01:00
#if defined(APIVERSNUM) && APIVERSNUM < 20200
#error "VDR-2.2.0 API version or greater is required!"
2014-09-27 09:25:14 +02:00
#endif
2021-03-15 14:15:07 +01:00
static const char *VERSION = "1.2.15";
2015-01-27 17:46:21 +01:00
static const char *DESCRIPTION = trNOOP("Skin Designer");
2014-09-27 09:25:14 +02:00
2015-04-02 15:09:41 +02:00
class cPluginSkinDesigner : public cPlugin, public skindesignerapi::SkindesignerAPI {
2014-09-27 09:25:14 +02:00
private:
2015-04-03 09:18:26 +02:00
string libskindesignerApiVersion;
2016-01-26 18:32:38 +01:00
skindesignerapi::cPluginStructure *skinPreviewStruct;
2015-04-02 15:09:41 +02:00
protected:
bool ServiceRegisterPlugin(skindesignerapi::cPluginStructure *plugStructure);
skindesignerapi::ISDDisplayMenu *ServiceGetDisplayMenu(void);
2016-01-26 18:32:38 +01:00
skindesignerapi::ISkinDisplayPlugin *ServiceGetDisplayPlugin(int plugId);
2014-09-27 09:25:14 +02:00
public:
cPluginSkinDesigner(void);
virtual ~cPluginSkinDesigner();
virtual const char *Version(void) { return VERSION; }
2015-01-27 17:46:21 +01:00
virtual const char *Description(void) { return tr(DESCRIPTION); }
2014-09-27 09:25:14 +02:00
virtual const char *CommandLineHelp(void);
virtual bool ProcessArgs(int argc, char *argv[]);
virtual bool Initialize(void);
virtual bool Start(void);
virtual void Stop(void);
virtual void Housekeeping(void);
virtual void MainThreadHook(void);
virtual cString Active(void);
virtual time_t WakeupTime(void);
virtual const char *MainMenuEntry(void) {return NULL;}
virtual cOsdObject *MainMenuAction(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
virtual bool Service(const char *Id, void *Data = NULL);
virtual const char **SVDRPHelpPages(void);
virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
};
cPluginSkinDesigner::cPluginSkinDesigner(void) {
2015-04-03 09:18:26 +02:00
libskindesignerApiVersion = "undefined";
config.SetVersion(VERSION);
2016-01-26 18:32:38 +01:00
skinPreviewStruct = NULL;
2014-09-27 09:25:14 +02:00
}
cPluginSkinDesigner::~cPluginSkinDesigner() {
2016-01-26 18:32:38 +01:00
delete skinPreviewStruct;
2014-09-27 09:25:14 +02:00
}
const char *cPluginSkinDesigner::CommandLineHelp(void) {
return
2015-05-22 13:34:23 +02:00
" -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"
2014-09-27 09:25:14 +02:00
" -e <EPGIMAGESPATH>, --epgimages=<IMAGESPATH> Set directory where epgimages are stored\n";
}
bool cPluginSkinDesigner::ProcessArgs(int argc, char *argv[]) {
// Implement command line argument processing here if applicable.
static const struct option long_options[] = {
{ "epgimages", required_argument, NULL, 'e' },
{ "logopath", required_argument, NULL, 'l' },
2014-09-27 09:25:14 +02:00
{ "skinpath", required_argument, NULL, 's' },
2015-05-22 13:34:23 +02:00
{ "installerpath", required_argument, NULL, 'i' },
2014-09-27 09:25:14 +02:00
{ 0, 0, 0, 0 }
};
int c;
2015-05-22 13:34:23 +02:00
while ((c = getopt_long(argc, argv, "e:s:l:i:", long_options, NULL)) != -1) {
2014-09-27 09:25:14 +02:00
switch (c) {
case 'e':
config.SetEpgImagePath(cString(optarg));
break;
case 'l':
config.SetLogoPath(cString(optarg));
break;
2014-09-27 09:25:14 +02:00
case 's':
config.SetSkinPath(cString(optarg));
break;
2015-05-22 13:34:23 +02:00
case 'i':
config.SetInstallerSkinPath(cString(optarg));
break;
2014-09-27 09:25:14 +02:00
default:
return false;
}
}
return true;
}
bool cPluginSkinDesigner::Initialize(void) {
plgManager = new cSDPluginManager();
2014-09-27 09:25:14 +02:00
return true;
}
bool cPluginSkinDesigner::Start(void) {
cXmlParser::InitLibXML();
2014-11-23 13:07:43 +01:00
cImageImporterSVG::InitLibRSVG();
2016-05-04 16:21:42 +02:00
cGlobalTimers::StartRefreshThread();
bool trueColorAvailable = true;
2018-02-16 18:12:48 +01:00
2014-09-27 09:25:14 +02:00
if (!cOsdProvider::SupportsTrueColor()) {
esyslog("skindesigner: No TrueColor OSD found! Using default Skin LCARS!");
trueColorAvailable = false;
2014-09-27 09:25:14 +02:00
} else
dsyslog("skindesigner: TrueColor OSD found");
2015-04-03 09:18:26 +02:00
libskindesignerApiVersion = LIBSKINDESIGNERAPIVERSION;
dsyslog("skindesigner: using libskindesigner API Version %s", libskindesignerApiVersion.c_str());
2016-01-26 18:32:38 +01:00
skinPreviewStruct = new skindesignerapi::cPluginStructure();
skinPreviewStruct->name = "setup";
skinPreviewStruct->libskindesignerAPIVersion = LIBSKINDESIGNERAPIVERSION;
skindesignerapi::cTokenContainer *tkSkinPreview = new skindesignerapi::cTokenContainer();
cSkindesignerSkinPreview::DefineTokens(tkSkinPreview);
skinPreviewStruct->RegisterMenu(0, skindesignerapi::mtText, "skinpreview.xml", tkSkinPreview);
if (RegisterPlugin(skinPreviewStruct)) {
dsyslog("skindesigner: skinsetup template successfully registered at skindesigner, id %d", skinPreviewStruct->id);
}
2015-05-30 16:43:59 +02:00
2015-01-21 18:33:19 +01:00
config.SetOsdLanguage();
config.SetPathes();
config.ReadSkins();
config.InitSkinIterator();
string skin = "";
2015-05-30 16:43:59 +02:00
bool skinAvailable = false;
while (config.GetSkin(skin)) {
2015-01-19 09:23:15 +01:00
config.ReadSkinSetup(skin);
2016-02-14 15:06:30 +01:00
cTheme *theme = new cTheme();
config.StoreTheme(theme);
cSkinDesigner *newSkin = new cSkinDesigner(skin, theme);
2015-05-30 16:43:59 +02:00
config.AddSkin(newSkin);
skinAvailable = true;
if (!trueColorAvailable) {
newSkin->ActivateBackupSkin();
}
}
config.TranslateSetup();
config.SetSkinSetupParameters();
2015-05-30 16:43:59 +02:00
if (!skinAvailable) {
esyslog("skindesigner: no skins found! Using default Skin LCARS!");
}
2016-05-26 10:47:45 +02:00
#ifdef USE_ZAPCOCKPIT
dsyslog("skindesigner: zapcockpit patch available");
#endif
return true;
2014-09-27 09:25:14 +02:00
}
void cPluginSkinDesigner::Stop(void) {
delete imgCache;
delete fontManager;
2016-01-26 18:32:38 +01:00
delete plgManager;
cXmlParser::CleanupLibXML();
2016-05-04 16:21:42 +02:00
cGlobalTimers::StopRefreshThread();
2014-09-27 09:25:14 +02:00
}
void cPluginSkinDesigner::Housekeeping(void) {
}
void cPluginSkinDesigner::MainThreadHook(void) {
int w, h;
double a;
static int mode;
cDevice::PrimaryDevice()->GetVideoSize(w, h, a);
if (!w && !h && !mode) {
mode = 1;
config.mode_changed = 1;
dsyslog("skindesigner: w %d h %d mode changed to %d\n", w, h, mode);
}
else if (w && h && mode) {
mode = 0;
config.mode_changed = 1;
dsyslog("skindesigner: w %d h %d mode changed to %d\n", w, h, mode);
}
2014-09-27 09:25:14 +02:00
}
cString cPluginSkinDesigner::Active(void) {
return NULL;
}
time_t cPluginSkinDesigner::WakeupTime(void) {
return 0;
}
cOsdObject *cPluginSkinDesigner::MainMenuAction(void) {
return NULL;
}
cMenuSetupPage *cPluginSkinDesigner::SetupMenu(void) {
2016-01-26 18:32:38 +01:00
return new cSkinDesignerSetup(skinPreviewStruct);
2014-09-27 09:25:14 +02:00
}
bool cPluginSkinDesigner::SetupParse(const char *Name, const char *Value) {
return config.SetupParse(Name, Value);
}
bool cPluginSkinDesigner::Service(const char *Id, void *Data) {
return false;
}
const char **cPluginSkinDesigner::SVDRPHelpPages(void) {
static const char *HelpPages[] = {
"RELD\n"
" force reload of templates and caches",
"DLIC\n"
" delete image cache",
2016-01-26 18:32:38 +01:00
"SCIT\n"
" Set custom Integer Token key = value",
"SCST\n"
" Set custom String Token key = value",
"LCTK\n"
" List custom Tokens",
2014-09-27 09:25:14 +02:00
"LSTF\n"
" List available Fonts",
0
};
return HelpPages;
}
cString cPluginSkinDesigner::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) {
2018-02-16 18:12:48 +01:00
cSkinDesigner *activeSkin = NULL;
2015-05-30 16:43:59 +02:00
cSkinDesigner *availableSkin = NULL;
config.InitSkinRefsIterator();
int result = 0;
2015-05-30 16:43:59 +02:00
while (availableSkin = config.GetNextSkinRef()) {
string activeSkinName = Setup.OSDSkin;
2015-05-30 16:43:59 +02:00
string currentSkinName = availableSkin->Description();
if (!currentSkinName.compare(activeSkinName)) {
2015-05-30 16:43:59 +02:00
activeSkin = availableSkin;
break;
2014-09-27 09:25:14 +02:00
}
}
if (!activeSkin) {
ReplyCode = 550;
2016-02-21 23:31:36 +01:00
return "SKINDESIGNER not active.";
}
if (strcasecmp(Command, "RELD") == 0) {
if (!activeSkin->Initialized()) {
ReplyCode = 503;
return "SKINDESIGNER reload of templates and caches failed: initialization not finished.";
}
config.ClearSkinSetups();
config.InitSkinIterator();
string skin = "";
while (config.GetSkin(skin)) {
config.ReadSkinSetup(skin);
}
config.TranslateSetup();
config.SetSkinSetupParameters();
result = activeSkin->Reload();
switch (result) {
case 0:
ReplyCode = 250;
return "SKINDESIGNER reload of templates and caches forced.";
case 1:
ReplyCode = 501;
return "SKINDESIGNER reload of templates and caches failed: error during loading - using LCARS as backup.";
case 2:
ReplyCode = 503;
return "SKINDESIGNER reload of templates and caches failed: OSD is open, close first.";
default:
ReplyCode = 500;
return "SKINDESIGNER reload of templates and caches failed: unknown reason (check code).";
};
} else if (strcasecmp(Command, "DLIC") == 0) {
if (imgCache)
delete imgCache;
imgCache = new cImageCache();
imgCache->SetPathes();
ReplyCode = 250;
return "SKINDESIGNER Image Cache deleted.";
2014-09-27 09:25:14 +02:00
} else if (strcasecmp(Command, "LSTF") == 0) {
activeSkin->ListAvailableFonts();
ReplyCode = 250;
return "SKINDESIGNER available fonts listed in syslog.";
2016-01-26 18:32:38 +01:00
} else if (strcasecmp(Command, "SCIT") == 0) {
if (!Option) {
ReplyCode = 501;
2016-01-26 18:32:38 +01:00
return "SKINDESIGNER SCIK Error: no Token name = value set";
}
2016-01-26 18:32:38 +01:00
bool optionOk = activeSkin->SetCustomIntToken(Option);
if (optionOk) {
ReplyCode = 250;
2016-01-26 18:32:38 +01:00
return cString::sprintf("SKINDESIGNER Set custom Int Token %s", Option);
} else {
ReplyCode = 501;
2016-01-26 18:32:38 +01:00
return cString::sprintf("SKINDESIGNER Invalid custom Int Token %s", Option);
}
} else if (strcasecmp(Command, "SCST") == 0) {
if (!Option) {
ReplyCode = 501;
return "SKINDESIGNER SCSK Error: no Token name = value set";
}
bool optionOk = activeSkin->SetCustomStringToken(Option);
if (optionOk) {
ReplyCode = 250;
return cString::sprintf("SKINDESIGNER Set custom String Token %s", Option);
} else {
ReplyCode = 501;
return cString::sprintf("SKINDESIGNER Invalid custom String Token %s", Option);
}
} else if (strcasecmp(Command, "LCTK") == 0) {
activeSkin->ListCustomTokens();
ReplyCode = 250;
return "SKINDESIGNER Custom Tokens listed in Log";
2014-09-27 09:25:14 +02:00
}
ReplyCode = 502;
2016-02-21 23:31:36 +01:00
return "SKINDESIGNER invalid SVDRP command.";
2014-09-27 09:25:14 +02:00
}
2016-01-26 18:32:38 +01:00
2015-04-02 15:09:41 +02:00
bool cPluginSkinDesigner::ServiceRegisterPlugin(skindesignerapi::cPluginStructure *plugStructure) {
2016-01-26 18:32:38 +01:00
if (plugStructure->menus.size() < 1 && plugStructure->rootview.size() < 1) {
2015-04-02 15:09:41 +02:00
esyslog("skindesigner: error - plugin without menus or views registered");
return false;
}
2016-01-26 18:32:38 +01:00
//basic plugin interface
2015-04-02 15:09:41 +02:00
if (plugStructure->menus.size() > 0)
2016-01-26 18:32:38 +01:00
plgManager->RegisterBasicPlugin(plugStructure);
//advanced plugin interface
if (plugStructure->rootview.size() > 0)
plgManager->RegisterAdvancedPlugin(plugStructure);
2015-04-02 15:09:41 +02:00
return true;
}
skindesignerapi::ISDDisplayMenu *cPluginSkinDesigner::ServiceGetDisplayMenu(void) {
cSkin *current = Skins.Current();
2015-05-30 16:43:59 +02:00
cSkinDesigner *availableSkin = NULL;
config.InitSkinRefsIterator();
while (availableSkin = config.GetNextSkinRef()) {
if (availableSkin == current) {
cSDDisplayMenu *displayMenu = availableSkin->GetDisplayMenu();
2015-04-02 15:09:41 +02:00
if (displayMenu) {
return displayMenu;
} else {
return NULL;
}
}
}
return NULL;
}
2016-01-26 18:32:38 +01:00
skindesignerapi::ISkinDisplayPlugin *cPluginSkinDesigner::ServiceGetDisplayPlugin(int plugId) {
2015-04-02 15:09:41 +02:00
cSkin *current = Skins.Current();
2015-05-30 16:43:59 +02:00
cSkinDesigner *availableSkin = NULL;
config.InitSkinRefsIterator();
while (availableSkin = config.GetNextSkinRef()) {
if (availableSkin == current) {
2016-01-26 18:32:38 +01:00
return availableSkin->GetDisplayPlugin(plugId);
2015-04-02 15:09:41 +02:00
}
}
return NULL;
}
2014-09-27 09:25:14 +02:00
VDRPLUGINCREATOR(cPluginSkinDesigner); // Don't touch this!