.project
.cproject
.#*
+config.json
-L=/opt/vc/lib -L=/usr/lib/arm-linux-gnueabihf
LIBPATHS =
LIBS = -lpthread -lstdc++ -lrt -lbrcmEGL -lbrcmOpenVG -lopenmaxil -lbcm_host -lavformat -lavcodec \
- -lavutil -lswresample -lm -ldl -lfontconfig -lfreetype -lMagick++-6.Q16 -lMagickWand-6.Q16 -lMagickCore-6.Q16
+ -lavutil -lswresample -lm -ldl -lfontconfig -lfreetype -lMagick++-6.Q16 -lMagickWand-6.Q16 -lMagickCore-6.Q16 -ljsoncpp
OBJECTS = $(OBJ_COMMON) $(OBJ_RASPBERRY)
INCLUDES = -isystem=/usr/include/arm-linux-gnueabihf -isystem=/opt/vc/include -isystem=/usr/include/freetype2 -isystem=/usr/include/arm-linux-gnueabihf/ImageMagick-6 -isystem=/usr/include/ImageMagick-6
DEFINES += -DVOMP_PLATFORM_RASPBERRY -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
--- /dev/null
+#include <iostream>
+#include <string>
+#include <fstream>
+#include <streambuf>
+
+// http://open-source-parsers.github.io/jsoncpp-docs/doxygen/namespacemembers.html
+
+
+#include "config.h"
+
+Config* Config::instance = NULL;
+
+Config::Config()
+: jconfigro(jconfig)
+{
+ instance = this;
+ applyDefaults();
+}
+
+Config::~Config()
+{
+ instance = NULL;
+}
+
+Config* Config::getInstance()
+{
+ return instance;
+}
+
+void Config::applyDefaults()
+{
+ // Insert the value only if it doesn't already exist
+ auto insertBool = [&] (const char* s, const char* k, bool v) { if (jconfig[s][k].isNull()) jconfig[s][k] = v; };
+ auto insertString = [&] (const char* s, const char* k, const char* v) { if (jconfig[s][k].isNull()) jconfig[s][k] = v; };
+
+ insertBool("main", "debug", false);
+ insertBool("main", "daemonize", true);
+
+ insertBool("log", "enabled", true);
+ insertString("log", "filename", "stdout");
+ insertString("log", "level", "debug");
+
+ #ifdef VOMP_PLATFORM_RASPBERRY
+ insertBool("input", "mod_cec_enabled", true);
+ #else
+ insertBool("input", "mod_cec_enabled", false);
+ #endif
+
+ insertBool("input", "mod_udp_enabled", true);
+ insertBool("input", "mod_lirc_enabled", false);
+}
+
+bool Config::loadFile()
+{
+ jconfig.clear();
+
+ std::ifstream configFile("config.json");
+
+ Json::CharReaderBuilder builder;
+ builder["collectComments"] = false;
+ builder["allowTrailingCommas"] = true;
+ std::string errs;
+
+ bool ok = Json::parseFromStream(builder, configFile, &jconfig, &errs);
+
+ std::cout << errs << std::endl;
+
+ if (!ok) return false;
+// std::cout << jconfig << std::endl;
+// std::cout << errs << std::endl;
+
+
+ applyDefaults();
+
+ dump();
+
+ return true;
+}
+
+bool Config::getString(const std::string& section, const std::string& key, std::string& out) const
+{
+ Json::Value v = jconfigro[section][key];
+ if (!v.isString()) return false;
+ out = v.asString();
+ return true;
+}
+
+bool Config::getInt(const std::string& section, const std::string& key, int& out) const
+{
+ Json::Value v = jconfigro[section][key];
+ if (!v.isInt64()) return false;
+ out = v.asInt64();
+ return true;
+}
+
+bool Config::getBool(const std::string& section, const std::string& key, bool& out) const
+{
+ Json::Value v = jconfigro[section][key];
+ if (!v.isBool()) return false;
+ out = v.asBool();
+ return true;
+}
+/*
+bool Config::getBool(const char* section, const char* key, bool& out) const
+{
+ Json::Value v = jconfigro[section][key];
+ if (!v.isBool()) return false;
+ out = v.asBool();
+ return true;
+}*/
+
+void Config::dump() const
+{
+ std::cout << jconfigro << std::endl;
+}
+
+bool Config::foreachInArray(const std::string& section, const std::string& key, std::function<void(const std::string&)> callback) const
+{
+ const Json::Value& v = jconfigro[section][key];
+ if (!v.isArray()) return false;
+
+ for(Json::Value::const_iterator i = v.begin(); i != v.end(); i++)
+ {
+ const Json::Value& jv = *i;
+ if (jv.isString())
+ callback(jv.asString());
+ }
+
+ return true;
+}
+
+bool Config::foreachPairInObject(const std::string& section, const std::string& key, std::function<void(const std::string&, const std::string&)> callback) const
+{
+ const Json::Value& v = jconfigro[section][key];
+ if (!v.isObject()) return false;
+
+ for(Json::Value::const_iterator i = v.begin(); i != v.end(); i++)
+ {
+ const Json::Value& jv = *i;
+ if (jv.isString())
+ callback(i.key().asString(), jv.asString());
+ }
+
+ return true;
+}
+
--- /dev/null
+/*
+ Copyright 2021 Chris Tallon
+
+ This file is part of VOMP.
+
+ VOMP is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ VOMP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with VOMP. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <functional>
+
+#include <jsoncpp/json/json.h>
+
+class Config
+{
+ public:
+ Config();
+ ~Config();
+ static Config* getInstance();
+
+ bool loadFile();
+
+ bool getString(const std::string& section, const std::string& key, std::string& out) const;
+ bool getInt(const std::string& section, const std::string& key, int& out) const;
+ bool getBool(const std::string& section, const std::string& key, bool& out) const;
+ void dump() const;
+ bool foreachInArray(const std::string& section, const std::string& key, std::function<void(const std::string&)> callback) const;
+ bool foreachPairInObject(const std::string& section, const std::string& key, std::function<void(const std::string&, const std::string&)> callback) const;
+
+ private:
+ static Config* instance;
+
+ void applyDefaults();
+
+ Json::Value jconfig;
+ const Json::Value& jconfigro;
+
+};
+
+#endif
--- /dev/null
+/* Vomp local config file
+ To use, rename to config.json and place in the current working directory for vompclient
+ This file is optional. All fields are optional
+ Anything in here overrides program defaults
+ Example data is shown below
+*/
+
+{
+ "main":
+ {
+ "debug": false,
+ "daemonize": true
+ },
+
+ "log":
+ {
+ "enabled": true,
+ "filename": "stdout",
+ "level": "debug"
+ },
+
+ "input":
+ {
+ "mod_cec_enabled": true,
+ "mod_udp_enabled": true,
+ "mod_lirc_enabled": true
+ },
+
+ "input_lirc":
+ {
+ "lirc_ip": "192.0.2.0",
+ "lirc_port": 8765,
+
+ "remotes": [ "lirc-remote-name-1", "lirc-remote-name-2" ],
+
+ "lirc-remote-name-1":
+ {
+ "KEY_POWER": "POWER",
+ "KEY_MUTE": "MUTE"
+ /* etc. List all keys to be used by Vomp
+ On the left - the Lirc key name. On the right - the Vomp keyname. See input.h (for now) */
+ },
+
+ "lirc-remote-name-2":
+ {
+ }
+ }
+}
#include <algorithm>
#include <stdexcept>
+#include "config.h"
#include "log.h"
+#include "inputman.h"
+
#include "inputlirc.h"
const char* InputLIRC::myModName = "InputLIRC";
return false;
}
- /* FIXME
- * Hard code remote keys for now. Put lines like this in inputlirc.conf
- * The 'THREE' is the VOMP key name, see input.h
- * remotes["lirc-remote-name"]["lirc-button-name"] = THREE;
- */
- #include "inputlirc.conf"
-
+ bool arraySuccess = Config::getInstance()->foreachInArray("input_lirc", "remotes", [&] (const std::string& remoteName)
+ {
+ log->log(myModName, Log::DEBUG, "Remote name: %s", remoteName.c_str());
+
+
+ bool objSuccess = Config::getInstance()->foreachPairInObject("input_lirc", remoteName, [&] (const std::string& lircName, const std::string& vompName)
+ {
+ UCHAR keyNumber = InputMan::getVompKeyNumber(vompName.c_str());
+
+ log->log(myModName, Log::DEBUG, " Lirc: %s, vomp: %s, vomp-number %i", lircName.c_str(), vompName.c_str(), keyNumber);
+
+ remotes[remoteName][lircName] = keyNumber;
+ });
+
+ if (!objSuccess)
+ {
+ log->log(myModName, Log::ERR, "Error reading config for remote %s", remoteName.c_str());
+ }
+ });
+
+ if (!arraySuccess)
+ {
+ log->log(myModName, Log::DEBUG, "Error reading remotes list");
+ }
+ else
+ {
+ log->log(myModName, Log::DEBUG, "Remotes array read OK");
+ }
+
+
+ using RemotesType = std::map<std::string, std::map<std::string, UCHAR>>;
+ using ButtonsType = std::map<std::string, UCHAR>;
+
+ for(RemotesType::iterator i = remotes.begin(); i != remotes.end(); i++)
+ {
+ ButtonsType& b = i->second;
+ for(ButtonsType:: iterator j = b.begin(); j != b.end(); j++)
+ {
+ log->log(myModName, Log::DEBUG, "%s - %s - %i", i->first.c_str(), j->first.c_str(), j->second);
+ }
+ }
+
return true;
}
bool init();
void shutdown();
+ using Input::start; // Bring all start()s from base class so our start doesn't generate compile warnings
bool start(const std::string& ip, USHORT port);
void stop();
along with VOMP. If not, see <https://www.gnu.org/licenses/>.
*/
+#include "config.h"
#include "log.h"
#include "wremoteconfig.h"
#include "wtabbar.h"
else
{ delete inputLinux; inputLinux = NULL; }
- // FIXME enable modules by new config system NCONFIG
-
-// inputCEC = new InputCEC();
-// ret = inputCEC->init();
-// if (ret)
-// oneOK = true;
-// else
-// { delete inputCEC; inputCEC = NULL; }
+ bool cecEnabled = true;
+ Config::getInstance()->getBool("input", "mod_cec_enabled", cecEnabled);
+ if (cecEnabled)
+ {
+ inputCEC = new InputCEC();
+ ret = inputCEC->init();
+ if (ret)
+ oneOK = true;
+ else
+ { delete inputCEC; inputCEC = NULL; }
+ }
#endif
- inputUDP = new InputUDP();
- ret = inputUDP->init();
- if (ret)
- oneOK = true;
- else
- { delete inputUDP; inputUDP = NULL; }
+ bool udpEnabled = true;
+ Config::getInstance()->getBool("input", "mod_udp_enabled", udpEnabled);
+ if (udpEnabled)
+ {
+ inputUDP = new InputUDP();
+ ret = inputUDP->init();
+ if (ret)
+ oneOK = true;
+ else
+ { delete inputUDP; inputUDP = NULL; }
+ }
- inputLirc = new InputLIRC();
- ret = inputLirc->init();
- if (ret)
- oneOK = true;
- else
- { delete inputLirc; inputLirc = NULL; }
+ bool lircEnabled = false;
+ Config::getInstance()->getBool("input", "mod_lirc_enabled", lircEnabled);
+ if (lircEnabled)
+ {
+ inputLirc = new InputLIRC();
+ ret = inputLirc->init();
+ if (ret)
+ oneOK = true;
+ else
+ { delete inputLirc; inputLirc = NULL; }
+ }
#ifdef WIN32
inputWin = new InputWin();
if (inputUDP && inputUDP->start()) oneOK = true;
-
- // FIXME
- std::string lircIP;
- USHORT lircPort = 8765;
- // Override lircIP in inputlirc.conf2
-#include "inputlirc.conf2"
- if (inputLirc && inputLirc->start(lircIP, lircPort)) oneOK = true;
-
+ if (inputLirc)
+ {
+ std::string lircIP;
+ bool checkA = Config::getInstance()->getString("input", "lirc_ip", lircIP);
+ int lircPort = 8765;
+ bool checkB = Config::getInstance()->getInt("input", "lirc_port", lircPort);
+
+ if (!checkA || !checkB)
+ {
+ delete inputLirc;
+ inputLirc = NULL;
+ }
+ else
+ {
+ if (inputLirc->start(lircIP, lircPort))
+ {
+ oneOK = true;
+ }
+ else
+ {
+ delete inputLirc;
+ inputLirc = NULL;
+ }
+ }
+ }
if (!oneOK)
Log::getInstance()->log("InputMan", Log::CRIT, "InputMan could not start any input module");
}
}
+const UCHAR InputMan::getVompKeyNumber(const char* vompKeyName)
+{
+ if (!strcmp(vompKeyName, "VOLUMEUP")) return Input::VOLUMEUP;
+ else if (!strcmp(vompKeyName, "VOLUMEDOWN")) return Input::VOLUMEDOWN;
+ else if (!strcmp(vompKeyName, "CHANNELUP")) return Input::CHANNELUP;
+ else if (!strcmp(vompKeyName, "CHANNELDOWN")) return Input::CHANNELDOWN;
+ else if (!strcmp(vompKeyName, "ZERO")) return Input::ZERO;
+ else if (!strcmp(vompKeyName, "ONE")) return Input::ONE;
+ else if (!strcmp(vompKeyName, "TWO")) return Input::TWO;
+ else if (!strcmp(vompKeyName, "THREE")) return Input::THREE;
+ else if (!strcmp(vompKeyName, "FOUR")) return Input::FOUR;
+ else if (!strcmp(vompKeyName, "FIVE")) return Input::FIVE;
+ else if (!strcmp(vompKeyName, "SIX")) return Input::SIX;
+ else if (!strcmp(vompKeyName, "SEVEN")) return Input::SEVEN;
+ else if (!strcmp(vompKeyName, "EIGHT")) return Input::EIGHT;
+ else if (!strcmp(vompKeyName, "NINE")) return Input::NINE;
+ else if (!strcmp(vompKeyName, "POWER")) return Input::POWER;
+ else if (!strcmp(vompKeyName, "GO")) return Input::GO;
+ else if (!strcmp(vompKeyName, "BACK")) return Input::BACK;
+ else if (!strcmp(vompKeyName, "MENU")) return Input::MENU;
+ else if (!strcmp(vompKeyName, "RED")) return Input::RED;
+ else if (!strcmp(vompKeyName, "GREEN")) return Input::GREEN;
+ else if (!strcmp(vompKeyName, "YELLOW")) return Input::YELLOW;
+ else if (!strcmp(vompKeyName, "BLUE")) return Input::BLUE;
+ else if (!strcmp(vompKeyName, "MUTE")) return Input::MUTE;
+ else if (!strcmp(vompKeyName, "RADIO")) return Input::RADIO;
+ else if (!strcmp(vompKeyName, "REVERSE")) return Input::REVERSE;
+ else if (!strcmp(vompKeyName, "PLAY")) return Input::PLAY;
+ else if (!strcmp(vompKeyName, "FORWARD")) return Input::FORWARD;
+ else if (!strcmp(vompKeyName, "RECORD")) return Input::RECORD;
+ else if (!strcmp(vompKeyName, "STOP")) return Input::STOP;
+ else if (!strcmp(vompKeyName, "PAUSE")) return Input::PAUSE;
+ else if (!strcmp(vompKeyName, "SKIPBACK")) return Input::SKIPBACK;
+ else if (!strcmp(vompKeyName, "SKIPFORWARD")) return Input::SKIPFORWARD;
+ else if (!strcmp(vompKeyName, "OK")) return Input::OK;
+ else if (!strcmp(vompKeyName, "FULL")) return Input::FULL;
+ else if (!strcmp(vompKeyName, "TV")) return Input::TV;
+ else if (!strcmp(vompKeyName, "VIDEOS")) return Input::VIDEOS;
+ else if (!strcmp(vompKeyName, "MUSIC")) return Input::MUSIC;
+ else if (!strcmp(vompKeyName, "PICTURES")) return Input::PICTURES;
+ else if (!strcmp(vompKeyName, "GUIDE")) return Input::GUIDE;
+ else if (!strcmp(vompKeyName, "UP")) return Input::UP;
+ else if (!strcmp(vompKeyName, "DOWN")) return Input::DOWN;
+ else if (!strcmp(vompKeyName, "LEFT")) return Input::LEFT;
+ else if (!strcmp(vompKeyName, "RIGHT")) return Input::RIGHT;
+ else if (!strcmp(vompKeyName, "PREVCHANNEL")) return Input::PREVCHANNEL;
+ else if (!strcmp(vompKeyName, "STAR")) return Input::STAR;
+ else if (!strcmp(vompKeyName, "HASH")) return Input::HASH;
+ else if (!strcmp(vompKeyName, "PLAYPAUSE")) return Input::PLAYPAUSE;
+ else if (!strcmp(vompKeyName, "POWERON")) return Input::POWERON;
+ else if (!strcmp(vompKeyName, "POWEROFF")) return Input::POWEROFF;
+ else return NULL;
+}
+
std::string InputMan::getHardCodedHardwareKeyNamesForVompKey(UCHAR vompKey)
{
// Go through each active Input class and get the hardware key name for vompKey
bool saveOptionstoServer();
static const char* getVompKeyName(UCHAR vompKey);
+ static const UCHAR getVompKeyNumber(const char* vompKeyName);
+
std::string getHardCodedHardwareKeyNamesForVompKey(UCHAR vompKey);
std::string getAllHardwareKeyNamesAssignedToVompKey(UCHAR vompKey);
#include <thread>
#include <string>
-
#ifndef WIN32
#include <unistd.h>
#include <endian.h>
#include <linux/vt.h>
#endif
+#include "config.h"
#include "log.h"
#include "util.h"
#include "control.h"
void threadSignalReceiverFunction();
#endif
-void shutdown(int code);
-const std::string& getCommandLineServer();
+[[ noreturn ]] void shutdown(int code);
+const std::string& getCommandLineServer(); // NCONFIG
+Config* config;
Log* logger;
Control* control;
bool daemonize = true;
bool debugEnabled = false;
bool crashed = false;
- int c;
+
+ config = new Config();
+ if (!config->loadFile())
+ {
+ printf("Parse error in config.json\n");
+ shutdown(1);
+ }
+
+
+ int c;
while ((c = getopt(argc, argv, "cdns:")) != -1)
{
switch (c)
// Daemonize --------------------------------------------------------------------------------------------------
- if (daemonize)
+ if (daemonize) // NCONFIG
{
// Fork away
pid_t forkTest = fork();
}
#endif
+ // Test area ------------------------------------------------------------------------------------------------------
+
+
+
// Run control ----------------------------------------------------------------------------------------------------
control = new Control();
control->shutdown();
shutdown(0);
- return 0;
}
// -------------------------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------
-void shutdown(int code)
+[[ noreturn ]] void shutdown(int code)
{
// FIXME, send a del all to boxstack first, then get rid of it after control?
if (control) // shut down control here in case views have posted messages
delete logger;
}
+ if (config)
+ {
+ delete config;
+ }
+
exit(code);
}
return clock_gettime(CLOCK_REALTIME, tp);
}
-const std::string& getCommandLineServer()
+const std::string& getCommandLineServer() // NCONFIG
{
return argvServer;
}
wprogressbar.o bitmap.o dvbsubtitles.o tfeed.o vteletextview.o \
teletextdecodervbiebu.o teletxt/txtfont.o movieinfo.o seriesinfo.o \
wmovieview.o wseriesview.o tvmedia.o wtvmedia.o wpictureview.o \
- osdvector.o surfacevector.o buffer.o \
+ osdvector.o surfacevector.o buffer.o config.o \
playervideorec.o playervideolive.o playerradiolive.o playerradiorec.o
OBJ_RASPBERRY = main.o threadp.o osdopenvg.o \
flags = 1; // hard coded active timer flag
- char* startMarginConfig = vdr->configLoad("Timers", "Start margin");
+ char* startMarginConfig = vdr->configLoad("Timers", "Start margin"); // NCONFIG
if (startMarginConfig)
{
strncpy(startMargin, startMarginConfig, 9);