diff options
| -rw-r--r-- | Makefile.am | 1 | ||||
| -rw-r--r-- | lib/INIReader.h | 441 | ||||
| -rw-r--r-- | src/ConfigParser.cpp | 173 | 
3 files changed, 524 insertions, 91 deletions
| diff --git a/Makefile.am b/Makefile.am index e323b1d..71b0ef2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -143,6 +143,7 @@ odr_dabmod_SOURCES  = src/DabMod.cpp \  					  src/PAPRStats.cpp \  					  src/PAPRStats.h \  					  src/zmq.hpp \ +					  lib/INIReader.h \  					  lib/crc.h \  					  lib/crc.c \  					  lib/fec/char.h \ diff --git a/lib/INIReader.h b/lib/INIReader.h new file mode 100644 index 0000000..f36e8d2 --- /dev/null +++ b/lib/INIReader.h @@ -0,0 +1,441 @@ +// Read an INI file into easy-to-access name/value pairs. + +// inih and INIReader are released under the New BSD license (see LICENSE.txt). +// Go to the project home page for more info: +// +// https://github.com/benhoyt/inih +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +/* Typedef for prototype of handler function. */ +typedef int (*ini_handler)(void* user, const char* section, +                           const char* name, const char* value); + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs +   (whitespace stripped), and comments starting with ';' (semicolon). Section +   is "" if name=value pair parsed before any section heading. name:value +   pairs are also supported as a concession to Python's configparser. + +   For each name=value pair parsed, call handler function with given user +   pointer as well as section, name, and value (data only valid for duration +   of handler call). Handler should return nonzero on success, zero on error. + +   Returns 0 on success, line number of first error on parse error (doesn't +   stop on first error), -1 on file open error, or -2 on memory allocation +   error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't +   close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of +   filename. Used for implementing custom or string-based I/O. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, +                     void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's +   configparser. If allowed, ini_parse() will call the handler with the same +   name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of +   the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters +   specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match +   Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +/* Maximum line length for any line in INI file. */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +#ifdef __cplusplus +} +#endif + +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#if !INI_USE_STACK +#include <stdlib.h> +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Strip whitespace chars off end of given string, in place. Return s. */ +inline static char* rstrip(char* s) +{ +    char* p = s + strlen(s); +    while (p > s && isspace((unsigned char)(*--p))) +        *p = '\0'; +    return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +inline static char* lskip(const char* s) +{ +    while (*s && isspace((unsigned char)(*s))) +        s++; +    return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, +   or pointer to null at end of string if neither found. Inline comment must +   be prefixed by a whitespace character to register as a comment. */ +inline static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS +    int was_space = 0; +    while (*s && (!chars || !strchr(chars, *s)) && +           !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { +        was_space = isspace((unsigned char)(*s)); +        s++; +    } +#else +    while (*s && (!chars || !strchr(chars, *s))) { +        s++; +    } +#endif +    return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +inline static char* strncpy0(char* dest, const char* src, size_t size) +{ +    strncpy(dest, src, size); +    dest[size - 1] = '\0'; +    return dest; +} + +/* See documentation in header file. */ +inline int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, +                     void* user) +{ +    /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK +    char line[INI_MAX_LINE]; +#else +    char* line; +#endif +    char section[MAX_SECTION] = ""; +    char prev_name[MAX_NAME] = ""; + +    char* start; +    char* end; +    char* name; +    char* value; +    int lineno = 0; +    int error = 0; + +#if !INI_USE_STACK +    line = (char*)malloc(INI_MAX_LINE); +    if (!line) { +        return -2; +    } +#endif + +    /* Scan through stream line by line */ +    while (reader(line, INI_MAX_LINE, stream) != NULL) { +        lineno++; + +        start = line; +#if INI_ALLOW_BOM +        if (lineno == 1 && (unsigned char)start[0] == 0xEF && +                           (unsigned char)start[1] == 0xBB && +                           (unsigned char)start[2] == 0xBF) { +            start += 3; +        } +#endif +        start = lskip(rstrip(start)); + +        if (*start == ';' || *start == '#') { +            /* Per Python configparser, allow both ; and # comments at the +               start of a line */ +        } +#if INI_ALLOW_MULTILINE +        else if (*prev_name && *start && start > line) { + +#if INI_ALLOW_INLINE_COMMENTS +        end = find_chars_or_comment(start, NULL); +        if (*end) +            *end = '\0'; +        rstrip(start); +#endif + +            /* Non-blank line with leading whitespace, treat as continuation +               of previous name's value (as per Python configparser). */ +            if (!handler(user, section, prev_name, start) && !error) +                error = lineno; +        } +#endif +        else if (*start == '[') { +            /* A "[section]" line */ +            end = find_chars_or_comment(start + 1, "]"); +            if (*end == ']') { +                *end = '\0'; +                strncpy0(section, start + 1, sizeof(section)); +                *prev_name = '\0'; +            } +            else if (!error) { +                /* No ']' found on section line */ +                error = lineno; +            } +        } +        else if (*start) { +            /* Not a comment, must be a name[=:]value pair */ +            end = find_chars_or_comment(start, "=:"); +            if (*end == '=' || *end == ':') { +                *end = '\0'; +                name = rstrip(start); +                value = lskip(end + 1); +#if INI_ALLOW_INLINE_COMMENTS +                end = find_chars_or_comment(value, NULL); +                if (*end) +                    *end = '\0'; +#endif +                rstrip(value); + +                /* Valid name[=:]value pair found, call handler */ +                strncpy0(prev_name, name, sizeof(prev_name)); +                if (!handler(user, section, name, value) && !error) +                    error = lineno; +            } +            else if (!error) { +                /* No '=' or ':' found on name[=:]value line */ +                error = lineno; +            } +        } + +#if INI_STOP_ON_FIRST_ERROR +        if (error) +            break; +#endif +    } + +#if !INI_USE_STACK +    free(line); +#endif + +    return error; +} + +/* See documentation in header file. */ +inline int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ +    return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +inline int ini_parse(const char* filename, ini_handler handler, void* user) +{ +    FILE* file; +    int error; + +    file = fopen(filename, "r"); +    if (!file) +        return -1; +    error = ini_parse_file(file, handler, user); +    fclose(file); +    return error; +} + +#endif /* __INI_H__ */ + + +#ifndef __INIREADER_H__ +#define __INIREADER_H__ + +#include <map> +#include <set> +#include <string> + +// Read an INI file into easy-to-access name/value pairs. (Note that I've gone +// for simplicity here rather than speed, but it should be pretty decent.) +class INIReader +{ +public: +    // Empty Constructor +    INIReader() {}; +   +    // Construct INIReader and parse given filename. See ini.h for more info +    // about the parsing. +    INIReader(std::string filename); + +    // Return the result of ini_parse(), i.e., 0 on success, line number of +    // first error on parse error, or -1 on file open error. +    int ParseError() const; + +    // Return the list of sections found in ini file +    std::set<std::string> Sections(); + +    // Get a string value from INI file, returning default_value if not found. +    std::string Get(std::string section_name, +                    std::string default_value); + +    // Get an integer (long) value from INI file, returning default_value if +    // not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2"). +    long GetInteger(std::string section_name, long default_value); + +    // Get a real (floating point double) value from INI file, returning +    // default_value if not found or not a valid floating point value +    // according to strtod(). +    double GetReal(std::string section_name, double default_value); + +    // Get a boolean value from INI file, returning default_value if not found or if +    // not a valid true/false value. Valid true values are "true", "yes", "on", "1", +    // and valid false values are "false", "no", "off", "0" (not case sensitive). +    bool GetBoolean(std::string section_name, bool default_value); + +private: +    int _error; +    std::map<std::string, std::string> _values; +    std::set<std::string> _sections; +    static std::string MakeKey(std::string section, std::string name); +    static int ValueHandler(void* user, const char* section, const char* name, +                            const char* value); +}; + +#endif  // __INIREADER_H__ + + +#ifndef __INIREADER__ +#define __INIREADER__ + +#include <algorithm> +#include <cctype> +#include <cstdlib> + +using std::string; + +inline INIReader::INIReader(string filename) +{ +    _error = ini_parse(filename.c_str(), ValueHandler, this); +} + +inline int INIReader::ParseError() const +{ +    return _error; +} + +inline std::set<string> INIReader::Sections() +{ +    return _sections; +} + +inline string INIReader::Get(string section_name, string default_value) +{ +    string key = section_name; +    return _values.count(key) ? _values[key] : default_value; +} + +inline long INIReader::GetInteger(string section_name, long default_value) +{ +    string valstr = Get(section_name, ""); +    const char* value = valstr.c_str(); +    char* end; +    // This parses "1234" (decimal) and also "0x4D2" (hex) +    long n = strtol(value, &end, 0); +    return end > value ? n : default_value; +} + +inline double INIReader::GetReal(string section_name, double default_value) +{ +    string valstr = Get(section_name, ""); +    const char* value = valstr.c_str(); +    char* end; +    double n = strtod(value, &end); +    return end > value ? n : default_value; +} + +inline bool INIReader::GetBoolean(string section_name, bool default_value) +{ +    string valstr = Get(section_name, ""); +    // Convert to lower case to make string comparisons case-insensitive +    std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower); +    if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1") +        return true; +    else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0") +        return false; +    else +        return default_value; +} + +inline string INIReader::MakeKey(string section, string name) +{ +    string key = section+"."+name; +    // Convert to lower case to make section/name lookups case-insensitive +    std::transform(key.begin(), key.end(), key.begin(), ::tolower); +    return key; +} + +inline int INIReader::ValueHandler(void* user, const char* section, const char* name, +                            const char* value) +{ +    INIReader* reader = (INIReader*)user; +    string key = MakeKey(section, name); +    if (reader->_values[key].size() > 0) +        reader->_values[key] += "\n"; +    reader->_values[key] += value; +    reader->_sections.insert(section); +    return 1; +} + +#endif  // __INIREADER__ diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 62f1241..94a960d 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -30,8 +30,8 @@  #endif  #include <cstdint> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/ini_parser.hpp> + +#include "INIReader.h"  #include "ConfigParser.h"  #include "Utils.h" @@ -68,23 +68,20 @@ static void parse_configfile(          mod_settings_t& mod_settings)  {      // First read parameters from the file -    using boost::property_tree::ptree; -    ptree pt; +    INIReader pt(configuration_file); -    try { -        read_ini(configuration_file, pt); -    } -    catch (boost::property_tree::ini_parser::ini_parser_error &e) +    int line_err = pt.ParseError(); + +    if (line_err)      {          std::cerr << "Error, cannot read configuration file '" << configuration_file.c_str() << "'" << std::endl; -        std::cerr << "       " << e.what() << std::endl; +        std::cerr << "At line:       " << line_err << std::endl;          throw std::runtime_error("Cannot read configuration file");      } -      // remote controller: -    if (pt.get("remotecontrol.telnet", 0) == 1) { +    if (pt.GetInteger("remotecontrol.telnet", 0) == 1) {          try { -            int telnetport = pt.get<int>("remotecontrol.telnetport"); +            int telnetport = pt.GetInteger("remotecontrol.telnetport", 0);              auto telnetrc = make_shared<RemoteControllerTelnet>(telnetport);              rcs.add_controller(telnetrc);          } @@ -94,11 +91,10 @@ static void parse_configfile(              throw std::runtime_error("Configuration error");          }      } -  #if defined(HAVE_ZEROMQ) -    if (pt.get("remotecontrol.zmqctrl", 0) == 1) { +    if (pt.GetInteger("remotecontrol.zmqctrl", 0) == 1) {          try { -            std::string zmqCtrlEndpoint = pt.get("remotecontrol.zmqctrlendpoint", ""); +            std::string zmqCtrlEndpoint = pt.Get("remotecontrol.zmqctrlendpoint", "");              auto zmqrc = make_shared<RemoteControllerZmq>(zmqCtrlEndpoint);              rcs.add_controller(zmqrc);          } @@ -111,28 +107,28 @@ static void parse_configfile(  #endif      // input params: -    if (pt.get("input.loop", 0) == 1) { +    if (pt.GetInteger("input.loop", 0) == 1) {          mod_settings.loop = true;      } -    mod_settings.inputTransport = pt.get("input.transport", "file"); -    mod_settings.inputMaxFramesQueued = pt.get("input.max_frames_queued", +    mod_settings.inputTransport = pt.Get("input.transport", "file"); +    mod_settings.inputMaxFramesQueued = pt.GetInteger("input.max_frames_queued",              ZMQ_INPUT_MAX_FRAME_QUEUE); -    mod_settings.edi_max_delay_ms = pt.get("input.edi_max_delay", 0.0f); +    mod_settings.edi_max_delay_ms = pt.GetReal("input.edi_max_delay", 0.0f); -    mod_settings.inputName = pt.get("input.source", "/dev/stdin"); +    mod_settings.inputName = pt.Get("input.source", "/dev/stdin");      // log parameters: -    if (pt.get("log.syslog", 0) == 1) { +    if (pt.GetInteger("log.syslog", 0) == 1) {          LogToSyslog* log_syslog = new LogToSyslog();          etiLog.register_backend(log_syslog);      } -    if (pt.get("log.filelog", 0) == 1) { +    if (pt.GetInteger("log.filelog", 0) == 1) {          std::string logfilename;          try { -            logfilename = pt.get<std::string>("log.filename"); +            logfilename = pt.Get("log.filename", "");          }          catch (std::exception &e) {              std::cerr << "Error: " << e.what() << "\n"; @@ -144,7 +140,7 @@ static void parse_configfile(          etiLog.register_backend(log_file);      } -    auto trace_filename = pt.get<std::string>("log.trace", ""); +    std::string trace_filename = pt.Get("log.trace", "");      if (not trace_filename.empty()) {          LogTracer* tracer = new LogTracer(trace_filename);          etiLog.register_backend(tracer); @@ -152,75 +148,70 @@ static void parse_configfile(      // modulator parameters: -    const string gainMode_setting = pt.get("modulator.gainmode", "var"); +    const string gainMode_setting = pt.Get("modulator.gainmode", "var");      mod_settings.gainMode = parse_gainmode(gainMode_setting); -    mod_settings.gainmodeVariance = pt.get("modulator.normalise_variance", +    mod_settings.gainmodeVariance = pt.GetReal("modulator.normalise_variance",              mod_settings.gainmodeVariance); -    mod_settings.dabMode = pt.get("modulator.mode", mod_settings.dabMode); -    mod_settings.clockRate = pt.get("modulator.dac_clk_rate", (size_t)0); -    mod_settings.digitalgain = pt.get("modulator.digital_gain", +    mod_settings.dabMode = pt.GetInteger("modulator.mode", mod_settings.dabMode); +    mod_settings.clockRate = pt.GetInteger("modulator.dac_clk_rate", (size_t)0); +    mod_settings.digitalgain = pt.GetReal("modulator.digital_gain",              mod_settings.digitalgain); -    mod_settings.outputRate = pt.get("modulator.rate", mod_settings.outputRate); -    mod_settings.ofdmWindowOverlap = pt.get("modulator.ofdmwindowing", +    mod_settings.outputRate = pt.GetInteger("modulator.rate", mod_settings.outputRate); +    mod_settings.ofdmWindowOverlap = pt.GetInteger("modulator.ofdmwindowing",              mod_settings.ofdmWindowOverlap);      // FIR Filter parameters: -    if (pt.get("firfilter.enabled", 0) == 1) { +    if (pt.GetInteger("firfilter.enabled", 0) == 1) {          mod_settings.filterTapsFilename = -            pt.get<std::string>("firfilter.filtertapsfile", "default"); +            pt.Get("firfilter.filtertapsfile", "default");      }      // Poly coefficients: -    if (pt.get("poly.enabled", 0) == 1) { +    if (pt.GetInteger("poly.enabled", 0) == 1) {          mod_settings.polyCoefFilename = -            pt.get<std::string>("poly.polycoeffile", "dpd/poly.coef"); +            pt.Get("poly.polycoeffile", "dpd/poly.coef");          mod_settings.polyNumThreads = -            pt.get<int>("poly.num_threads", 0); +            pt.GetInteger("poly.num_threads", 0);      }      // Crest factor reduction -    if (pt.get("cfr.enabled", 0) == 1) { +    if (pt.GetInteger("cfr.enabled", 0) == 1) {          mod_settings.enableCfr = true; -        mod_settings.cfrClip = pt.get<float>("cfr.clip"); -        mod_settings.cfrErrorClip = pt.get<float>("cfr.error_clip"); +        mod_settings.cfrClip = pt.GetReal("cfr.clip", 0.0); +        mod_settings.cfrErrorClip = pt.GetReal("cfr.error_clip", 0.0);      }      // Output options -    std::string output_selected; -    try { -        output_selected = pt.get<std::string>("output.output"); -    } -    catch (std::exception &e) { -        std::cerr << "Error: " << e.what() << "\n"; +    std::string output_selected = pt.Get("output.output", ""); +    if(output_selected == "") { +        std::cerr << "Error:\n";          std::cerr << "       Configuration does not specify output\n";          throw std::runtime_error("Configuration error");      }      if (output_selected == "file") { -        try { -            mod_settings.outputName = pt.get<std::string>("fileoutput.filename"); -            mod_settings.fileOutputShowMetadata = -                (pt.get("fileoutput.show_metadata", 0) > 0); -        } -        catch (std::exception &e) { -            std::cerr << "Error: " << e.what() << "\n"; +        mod_settings.outputName = pt.Get("fileoutput.filename", ""); +        if(mod_settings.outputName == "") { +            std::cerr << "Error:\n";              std::cerr << "       Configuration does not specify file name for file output\n";              throw std::runtime_error("Configuration error");          } +        mod_settings.fileOutputShowMetadata = +                (pt.GetInteger("fileoutput.show_metadata", 0) > 0);          mod_settings.useFileOutput = true; -        mod_settings.fileOutputFormat = pt.get("fileoutput.format", +        mod_settings.fileOutputFormat = pt.Get("fileoutput.format",                  mod_settings.fileOutputFormat);      }  #if defined(HAVE_OUTPUT_UHD)      else if (output_selected == "uhd") {          Output::SDRDeviceConfig sdr_device_config; -        string device = pt.get("uhdoutput.device", ""); -        const auto usrpType = pt.get("uhdoutput.type", ""); +        string device = pt.Get("uhdoutput.device", ""); +        const auto usrpType = pt.Get("uhdoutput.type", "");          if (usrpType != "") {              if (not device.empty()) {                  device += ","; @@ -229,8 +220,8 @@ static void parse_configfile(          }          sdr_device_config.device = device; -        sdr_device_config.subDevice = pt.get("uhdoutput.subdevice", ""); -        sdr_device_config.masterClockRate = pt.get<long>("uhdoutput.master_clock_rate", 0); +        sdr_device_config.subDevice = pt.Get("uhdoutput.subdevice", ""); +        sdr_device_config.masterClockRate = pt.GetInteger("uhdoutput.master_clock_rate", 0);          if (sdr_device_config.device.find("master_clock_rate") != std::string::npos) {              std::cerr << "Warning:" @@ -242,12 +233,12 @@ static void parse_configfile(                  "setting type in [uhd] device is deprecated !\n";          } -        sdr_device_config.txgain = pt.get("uhdoutput.txgain", 0.0); -        sdr_device_config.tx_antenna = pt.get("uhdoutput.tx_antenna", ""); -        sdr_device_config.rx_antenna = pt.get("uhdoutput.rx_antenna", "RX2"); -        sdr_device_config.rxgain = pt.get("uhdoutput.rxgain", 0.0); -        sdr_device_config.frequency = pt.get<double>("uhdoutput.frequency", 0); -        std::string chan = pt.get<std::string>("uhdoutput.channel", ""); +        sdr_device_config.txgain = pt.GetReal("uhdoutput.txgain", 0.0); +        sdr_device_config.tx_antenna = pt.Get("uhdoutput.tx_antenna", ""); +        sdr_device_config.rx_antenna = pt.Get("uhdoutput.rx_antenna", "RX2"); +        sdr_device_config.rxgain = pt.GetReal("uhdoutput.rxgain", 0.0); +        sdr_device_config.frequency = pt.GetReal("uhdoutput.frequency", 0); +        std::string chan = pt.Get("uhdoutput.channel", "");          sdr_device_config.dabMode = mod_settings.dabMode;          if (sdr_device_config.frequency == 0 && chan == "") { @@ -262,13 +253,13 @@ static void parse_configfile(              throw std::runtime_error("Configuration error");          } -        sdr_device_config.lo_offset = pt.get<double>("uhdoutput.lo_offset", 0); +        sdr_device_config.lo_offset = pt.GetReal("uhdoutput.lo_offset", 0); -        sdr_device_config.refclk_src = pt.get("uhdoutput.refclk_source", "internal"); -        sdr_device_config.pps_src = pt.get("uhdoutput.pps_source", "none"); -        sdr_device_config.pps_polarity = pt.get("uhdoutput.pps_polarity", "pos"); +        sdr_device_config.refclk_src = pt.Get("uhdoutput.refclk_source", "internal"); +        sdr_device_config.pps_src = pt.Get("uhdoutput.pps_source", "none"); +        sdr_device_config.pps_polarity = pt.Get("uhdoutput.pps_polarity", "pos"); -        std::string behave = pt.get("uhdoutput.behaviour_refclk_lock_lost", "ignore"); +        std::string behave = pt.Get("uhdoutput.behaviour_refclk_lock_lost", "ignore");          if (behave == "crash") {              sdr_device_config.refclk_lock_loss_behaviour = Output::CRASH; @@ -281,9 +272,9 @@ static void parse_configfile(              throw std::runtime_error("Configuration error");          } -        sdr_device_config.maxGPSHoldoverTime = pt.get("uhdoutput.max_gps_holdover_time", 0); +        sdr_device_config.maxGPSHoldoverTime = pt.GetInteger("uhdoutput.max_gps_holdover_time", 0); -        sdr_device_config.dpdFeedbackServerPort = pt.get<long>("uhdoutput.dpd_port", 0); +        sdr_device_config.dpdFeedbackServerPort = pt.GetInteger("uhdoutput.dpd_port", 0);          mod_settings.sdr_device_config = sdr_device_config;          mod_settings.useUHDOutput = true; @@ -292,14 +283,14 @@ static void parse_configfile(  #if defined(HAVE_SOAPYSDR)      else if (output_selected == "soapysdr") {          auto& outputsoapy_conf = mod_settings.sdr_device_config; -        outputsoapy_conf.device = pt.get("soapyoutput.device", ""); -        outputsoapy_conf.masterClockRate = pt.get<long>("soapyoutput.master_clock_rate", 0); - -        outputsoapy_conf.txgain = pt.get("soapyoutput.txgain", 0.0); -        outputsoapy_conf.tx_antenna = pt.get("soapyoutput.tx_antenna", ""); -        outputsoapy_conf.lo_offset = pt.get<double>("soapyoutput.lo_offset", 0.0); -        outputsoapy_conf.frequency = pt.get<double>("soapyoutput.frequency", 0); -        std::string chan = pt.get<std::string>("soapyoutput.channel", ""); +        outputsoapy_conf.device = pt.Get("soapyoutput.device", ""); +        outputsoapy_conf.masterClockRate = pt.GetInteger("soapyoutput.master_clock_rate", 0); + +        outputsoapy_conf.txgain = pt.GetReal("soapyoutput.txgain", 0.0); +        outputsoapy_conf.tx_antenna = pt.Get("soapyoutput.tx_antenna", ""); +        outputsoapy_conf.lo_offset = pt.GetReal("soapyoutput.lo_offset", 0.0); +        outputsoapy_conf.frequency = pt.GetReal("soapyoutput.frequency", 0); +        std::string chan = pt.Get("soapyoutput.channel", "");          outputsoapy_conf.dabMode = mod_settings.dabMode;          if (outputsoapy_conf.frequency == 0 && chan == "") { @@ -314,15 +305,15 @@ static void parse_configfile(              throw std::runtime_error("Configuration error");          } -        outputsoapy_conf.dpdFeedbackServerPort = pt.get<long>("soapyoutput.dpd_port", 0); +        outputsoapy_conf.dpdFeedbackServerPort = pt.GetInteger("soapyoutput.dpd_port", 0);          mod_settings.useSoapyOutput = true;      }  #endif  #if defined(HAVE_ZEROMQ)      else if (output_selected == "zmq") { -        mod_settings.outputName = pt.get<std::string>("zmqoutput.listen"); -        mod_settings.zmqOutputSocketType = pt.get<std::string>("zmqoutput.socket_type"); +        mod_settings.outputName = pt.Get("zmqoutput.listen", ""); +        mod_settings.zmqOutputSocketType = pt.Get("zmqoutput.socket_type", "");          mod_settings.useZeroMQOutput = true;      }  #endif @@ -332,12 +323,12 @@ static void parse_configfile(      }  #if defined(HAVE_OUTPUT_UHD) -    mod_settings.sdr_device_config.enableSync = (pt.get("delaymanagement.synchronous", 0) == 1); -    mod_settings.sdr_device_config.muteNoTimestamps = (pt.get("delaymanagement.mutenotimestamps", 0) == 1); +    mod_settings.sdr_device_config.enableSync = (pt.GetInteger("delaymanagement.synchronous", 0) == 1); +    mod_settings.sdr_device_config.muteNoTimestamps = (pt.GetInteger("delaymanagement.mutenotimestamps", 0) == 1);      if (mod_settings.sdr_device_config.enableSync) { -        std::string delay_mgmt = pt.get<std::string>("delaymanagement.management", ""); -        std::string fixedoffset = pt.get<std::string>("delaymanagement.fixedoffset", ""); -        std::string offset_filename = pt.get<std::string>("delaymanagement.dynamicoffsetfile", ""); +        std::string delay_mgmt = pt.Get("delaymanagement.management", ""); +        std::string fixedoffset = pt.Get("delaymanagement.fixedoffset", ""); +        std::string offset_filename = pt.Get("delaymanagement.dynamicoffsetfile", "");          if (not(delay_mgmt.empty() and fixedoffset.empty() and offset_filename.empty())) {              std::cerr << "Warning: you are using the old config syntax for the offset management.\n"; @@ -345,7 +336,7 @@ static void parse_configfile(          }          try { -            mod_settings.tist_offset_s = pt.get<double>("delaymanagement.offset"); +            mod_settings.tist_offset_s = pt.GetReal("delaymanagement.offset", 0.0);          }          catch (std::exception &e) {              std::cerr << "Error: delaymanagement: synchronous is enabled, but no offset defined!\n"; @@ -356,10 +347,10 @@ static void parse_configfile(  #endif      /* Read TII parameters from config file */ -    mod_settings.tiiConfig.enable = pt.get("tii.enable", 0); -    mod_settings.tiiConfig.comb = pt.get("tii.comb", 0); -    mod_settings.tiiConfig.pattern = pt.get("tii.pattern", 0); -    mod_settings.tiiConfig.old_variant = pt.get("tii.old_variant", 0); +    mod_settings.tiiConfig.enable = pt.GetInteger("tii.enable", 0); +    mod_settings.tiiConfig.comb = pt.GetInteger("tii.comb", 0); +    mod_settings.tiiConfig.pattern = pt.GetInteger("tii.pattern", 0); +    mod_settings.tiiConfig.old_variant = pt.GetInteger("tii.old_variant", 0);  } | 
