]> git.vomp.tv Git - vompclient.git/commitdiff
Start work on local JSON config system. Start using it with Input classes
authorChris Tallon <chris@vomp.tv>
Wed, 1 Sep 2021 20:12:38 +0000 (21:12 +0100)
committerChris Tallon <chris@vomp.tv>
Wed, 1 Sep 2021 20:12:38 +0000 (21:12 +0100)
12 files changed:
.gitignore
GNUmakefile
config.cc [new file with mode: 0644]
config.h [new file with mode: 0644]
config.json.sample [new file with mode: 0644]
inputlirc.cc
inputlirc.h
inputman.cc
inputman.h
main.cc
objects.mk
vepgsettimer.cc

index 8aa4cc78ae55d2e6b686255338fefbe77c05c9f8..26a69ca9745544d964dd2024f80a7d88c92f326f 100644 (file)
@@ -9,3 +9,4 @@ target-*
 .project
 .cproject
 .#*
+config.json
index 36ae7aa382e9b23733ab1707d7be280d02ad86b7..d3a4878eb950a981c34ea13dd0bc30849e090b64 100644 (file)
@@ -94,7 +94,7 @@ LDFLAGS = -Wall $(PICTURES) $(SYSROOT) \
  -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
diff --git a/config.cc b/config.cc
new file mode 100644 (file)
index 0000000..7ebd89b
--- /dev/null
+++ b/config.cc
@@ -0,0 +1,146 @@
+#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;
+}
+
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..ecd1663
--- /dev/null
+++ b/config.h
@@ -0,0 +1,53 @@
+/*
+    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
diff --git a/config.json.sample b/config.json.sample
new file mode 100644 (file)
index 0000000..0400f10
--- /dev/null
@@ -0,0 +1,48 @@
+/* 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":
+    {
+    }
+  }
+}
index a1a6c0b483a1afffb7c9ea433a8c4dd9e08ba638..a56e77ce9f548ca054c917a14fb55e11092a8ad5 100644 (file)
 #include <algorithm>
 #include <stdexcept>
 
+#include "config.h"
 #include "log.h"
 
+#include "inputman.h"
+
 #include "inputlirc.h"
 
 const char* InputLIRC::myModName = "InputLIRC";
@@ -41,13 +44,48 @@ bool InputLIRC::init()
     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;
 }
 
index e4dee3b68856d133cd9bcd353ac5395fc71eff2e..6f38b1b1d068e6beb091480c7b33477d234997fc 100644 (file)
@@ -37,6 +37,7 @@ class InputLIRC : public Input
     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();
 
index dc9e2fe146f495a214660dc83c75b107c1541325..864e558505ffb7f64d95ec45187cda082d0f6376 100644 (file)
@@ -17,6 +17,7 @@
     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
 */
 
+#include "config.h"
 #include "log.h"
 #include "wremoteconfig.h"
 #include "wtabbar.h"
@@ -64,29 +65,42 @@ bool InputMan::init()
   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();
@@ -119,14 +133,31 @@ bool InputMan::start()
 
   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");
@@ -378,6 +409,60 @@ const char* InputMan::getVompKeyName(UCHAR number)
   }
 }
 
+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
index 1705ee2f9476d54b64caf10621e521abfc1234db..cc08427331f3ee0810f954a22107c70ae22012ec 100644 (file)
@@ -117,6 +117,8 @@ class InputMan: public AbstractOption
     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);
diff --git a/main.cc b/main.cc
index 506f7fe97e211b2a9d3dbeb988de6bec944baf72..42c9b3a42b2352083a3a88ead61c347a1bcbb89f 100644 (file)
--- a/main.cc
+++ b/main.cc
@@ -30,7 +30,6 @@
 #include <thread>
 #include <string>
 
-
 #ifndef WIN32
   #include <unistd.h>
   #include <endian.h>
@@ -43,6 +42,7 @@
   #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;
 
@@ -80,8 +81,17 @@ int main(int argc, char** argv)
   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)
@@ -125,7 +135,7 @@ int main(int argc, char** argv)
 
   // Daemonize --------------------------------------------------------------------------------------------------
 
-  if (daemonize)
+  if (daemonize) // NCONFIG
   {
     // Fork away
     pid_t forkTest = fork();
@@ -191,6 +201,10 @@ int main(int argc, char** argv)
   }
 #endif
 
+  // Test area ------------------------------------------------------------------------------------------------------
+
+
+
   // Run control ----------------------------------------------------------------------------------------------------
 
   control = new Control();
@@ -212,7 +226,6 @@ int main(int argc, char** argv)
   control->shutdown();
 
   shutdown(0);
-  return 0;
 }
 
 // -------------------------------------------------------------------------------------------------------------------
@@ -240,7 +253,7 @@ void threadSignalReceiverFunction()
 
 // -------------------------------------------------------------------------------------------------------------------
 
-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
@@ -262,6 +275,11 @@ void shutdown(int code)
     delete logger;
   }
 
+  if (config)
+  {
+    delete config;
+  }
+
   exit(code);
 }
 
@@ -279,7 +297,7 @@ int getClockRealTime(struct timespec *tp) // FIXME - del if all goes chrono
   return clock_gettime(CLOCK_REALTIME, tp);
 }
 
-const std::string& getCommandLineServer()
+const std::string& getCommandLineServer() // NCONFIG
 {
   return argvServer;
 }
index 30d496efab4a8142efbf460b1c8403fb9e91fe27..a9d1c0532a9eeb91f671e9be51a490503076bd0d 100644 (file)
@@ -18,7 +18,7 @@ OBJ_COMMON = util.o control.o thread.o timers.o i18n.o udp4.o udp6.o vdpc.o tcp.
              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                                       \
index 59704d9cb464ea2d1ca4d5e748faceae68b4c5d8..71a025a7094d0ba7a0a29a4e992ee9c597a2e51c 100644 (file)
@@ -101,7 +101,7 @@ char* VEpgSetTimer::genTimerString()
 
   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);