aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--lib/Json.cpp102
-rw-r--r--lib/Json.h66
-rw-r--r--lib/RemoteControl.cpp94
-rw-r--r--lib/RemoteControl.h8
-rw-r--r--src/DabModulator.cpp4
-rw-r--r--src/DabModulator.h2
-rw-r--r--src/FIRFilter.cpp4
-rw-r--r--src/FIRFilter.h2
-rw-r--r--src/GainControl.cpp4
-rw-r--r--src/GainControl.h2
-rw-r--r--src/GuardIntervalInserter.cpp4
-rw-r--r--src/GuardIntervalInserter.h2
-rw-r--r--src/MemlessPoly.cpp4
-rw-r--r--src/MemlessPoly.h2
-rw-r--r--src/OfdmGenerator.cpp4
-rw-r--r--src/OfdmGenerator.h2
-rw-r--r--src/TII.cpp4
-rw-r--r--src/TII.h2
-rw-r--r--src/TimestampDecoder.cpp4
-rw-r--r--src/TimestampDecoder.h2
-rw-r--r--src/output/SDR.cpp6
-rw-r--r--src/output/SDR.h2
-rw-r--r--src/output/SDRDevice.h2
24 files changed, 220 insertions, 110 deletions
diff --git a/Makefile.am b/Makefile.am
index 0e09236..6e7c9ce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -98,6 +98,8 @@ odr_dabmod_SOURCES = src/DabMod.cpp \
lib/RemoteControl.h \
lib/Log.cpp \
lib/Log.h \
+ lib/Json.h \
+ lib/Json.cpp \
lib/Globals.cpp \
lib/INIReader.h \
lib/crc.h \
diff --git a/lib/Json.cpp b/lib/Json.cpp
new file mode 100644
index 0000000..9bda8c3
--- /dev/null
+++ b/lib/Json.cpp
@@ -0,0 +1,102 @@
+/*
+ Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
+ Her Majesty the Queen in Right of Canada (Communications Research
+ Center Canada)
+
+ Copyright (C) 2023
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://www.opendigitalradio.org
+ */
+/*
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+#include <list>
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+#include <string>
+#include <algorithm>
+
+#include "Json.h"
+
+namespace json {
+ static std::string escape_json(const std::string &s) {
+ std::ostringstream o;
+ for (auto c = s.cbegin(); c != s.cend(); c++) {
+ switch (*c) {
+ case '"': o << "\\\""; break;
+ case '\\': o << "\\\\"; break;
+ case '\b': o << "\\b"; break;
+ case '\f': o << "\\f"; break;
+ case '\n': o << "\\n"; break;
+ case '\r': o << "\\r"; break;
+ case '\t': o << "\\t"; break;
+ default:
+ if ('\x00' <= *c && *c <= '\x1f') {
+ o << "\\u"
+ << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(*c);
+ } else {
+ o << *c;
+ }
+ }
+ }
+ return o.str();
+ }
+
+ std::string map_to_json(const map_t& values) {
+ std::ostringstream ss;
+ ss << "{ ";
+ size_t ix = 0;
+ for (const auto& element : values) {
+ if (ix > 0) {
+ ss << ",";
+ }
+
+ ss << "\"" << escape_json(element.first) << "\": ";
+
+ const auto& value = element.second.data;
+ if (std::holds_alternative<std::string>(value)) {
+ ss << "\"" << escape_json(std::get<std::string>(value)) << "\"";
+ }
+ else if (std::holds_alternative<double>(value)) {
+ ss << std::defaultfloat << std::get<double>(value);
+ }
+ else if (std::holds_alternative<ssize_t>(value)) {
+ ss << std::get<ssize_t>(value);
+ }
+ else if (std::holds_alternative<size_t>(value)) {
+ ss << std::get<size_t>(value);
+ }
+ else if (std::holds_alternative<bool>(value)) {
+ ss << (std::get<bool>(value) ? "true" : "false");
+ }
+ else if (std::holds_alternative<std::nullopt_t>(value)) {
+ ss << "null";
+ }
+ else if (std::holds_alternative<json::map_t>(value)) {
+ ss << map_to_json(std::get<json::map_t>(value));
+ }
+ else {
+ throw std::logic_error("variant alternative not handled");
+ }
+
+ ix++;
+ }
+ ss << " }";
+
+ return ss.str();
+ }
+}
diff --git a/lib/Json.h b/lib/Json.h
new file mode 100644
index 0000000..26da9a8
--- /dev/null
+++ b/lib/Json.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
+ Her Majesty the Queen in Right of Canada (Communications Research
+ Center Canada)
+
+ Copyright (C) 2023
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://www.opendigitalradio.org
+
+ This module adds remote-control capability to some of the dabmux/dabmod modules.
+ */
+/*
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <list>
+#include <memory>
+#include <optional>
+#include <stdexcept>
+#include <string>
+#include <unordered_map>
+#include <variant>
+
+namespace json {
+
+ using map_t = std::unordered_map<std::string, struct value_t>;
+
+ struct value_t {
+ std::variant<
+ map_t,
+ std::string,
+ double,
+ size_t,
+ ssize_t,
+ bool,
+ std::nullopt_t> data;
+
+ template<class T>
+ value_t operator=(const T& map) {
+ value_t v;
+ v.data = map;
+ return v;
+ }
+
+ };
+
+ std::string map_to_json(const map_t& values);
+}
diff --git a/lib/RemoteControl.cpp b/lib/RemoteControl.cpp
index fd0ea77..b544461 100644
--- a/lib/RemoteControl.cpp
+++ b/lib/RemoteControl.cpp
@@ -105,71 +105,14 @@ std::list< std::vector<std::string> > RemoteControllers::get_param_list_values(c
}
-static std::string escape_json(const std::string &s) {
- std::ostringstream o;
- for (auto c = s.cbegin(); c != s.cend(); c++) {
- switch (*c) {
- case '"': o << "\\\""; break;
- case '\\': o << "\\\\"; break;
- case '\b': o << "\\b"; break;
- case '\f': o << "\\f"; break;
- case '\n': o << "\\n"; break;
- case '\r': o << "\\r"; break;
- case '\t': o << "\\t"; break;
- default:
- if ('\x00' <= *c && *c <= '\x1f') {
- o << "\\u"
- << std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(*c);
- } else {
- o << *c;
- }
- }
- }
- return o.str();
-}
-
-std::string RemoteControllers::get_params_json(const std::string& name) {
- RemoteControllable* controllable = get_controllable_(name);
- const auto& values = controllable->get_all_values();
-
- std::ostringstream ss;
- ss << "{ ";
- size_t ix = 0;
- for (const auto& element : values) {
- if (ix > 0) {
- ss << ",";
- }
-
- ss << "\"" << escape_json(element.first) << "\": ";
-
- const auto& value = element.second;
- if (std::holds_alternative<string>(value)) {
- ss << "\"" << escape_json(std::get<string>(value)) << "\"";
- }
- else if (std::holds_alternative<double>(value)) {
- ss << std::defaultfloat << std::get<double>(value);
- }
- else if (std::holds_alternative<ssize_t>(value)) {
- ss << std::get<ssize_t>(value);
- }
- else if (std::holds_alternative<size_t>(value)) {
- ss << std::get<size_t>(value);
- }
- else if (std::holds_alternative<bool>(value)) {
- ss << (std::get<bool>(value) ? "true" : "false");
- }
- else if (std::holds_alternative<std::nullopt_t>(value)) {
- ss << "null";
- }
- else {
- throw std::logic_error("variant alternative not handled");
- }
- ix++;
+std::string RemoteControllers::get_showjson() {
+ json::map_t root;
+ for (auto &controllable : rcs.controllables) {
+ root[controllable->get_rc_name()].data = controllable->get_all_values();
}
- ss << " }";
- return ss.str();
+ return json::map_to_json(root);
}
std::string RemoteControllers::get_param(const std::string& name, const std::string& param) {
@@ -590,6 +533,19 @@ void RemoteControllerZmq::process()
repSocket.send(zmsg, (--cohort_size > 0) ? zmq::send_flags::sndmore : zmq::send_flags::none);
}
}
+ else if (msg.size() == 1 && command == "showjson") {
+ try {
+ std::string json = rcs.get_showjson();
+
+ zmq::message_t zmsg(json.size());
+ memcpy(zmsg.data(), json.data(), json.size());
+
+ repSocket.send(zmsg, zmq::send_flags::none);
+ }
+ catch (const ParameterError &err) {
+ send_fail_reply(repSocket, err.what());
+ }
+ }
else if (msg.size() == 2 && command == "show") {
const std::string module((char*) msg[1].data(), msg[1].size());
try {
@@ -608,20 +564,6 @@ void RemoteControllerZmq::process()
send_fail_reply(repSocket, err.what());
}
}
- else if (msg.size() == 2 && command == "showjson") {
- const std::string module((char*) msg[1].data(), msg[1].size());
- try {
- std::string json = rcs.get_params_json(module);
-
- zmq::message_t zmsg(json.size());
- memcpy(zmsg.data(), json.data(), json.size());
-
- repSocket.send(zmsg, zmq::send_flags::none);
- }
- catch (const ParameterError &err) {
- send_fail_reply(repSocket, err.what());
- }
- }
else if (msg.size() == 3 && command == "get") {
const std::string module((char*) msg[1].data(), msg[1].size());
const std::string parameter((char*) msg[2].data(), msg[2].size());
diff --git a/lib/RemoteControl.h b/lib/RemoteControl.h
index 4bc3b68..26f30d9 100644
--- a/lib/RemoteControl.h
+++ b/lib/RemoteControl.h
@@ -48,6 +48,7 @@
#include "Log.h"
#include "Socket.h"
+#include "Json.h"
#define RC_ADD_PARAMETER(p, desc) { \
std::vector<std::string> p; \
@@ -120,10 +121,7 @@ class RemoteControllable {
/* Getting a parameter always returns a string. */
virtual const std::string get_parameter(const std::string& parameter) const = 0;
- using value_t = std::variant<std::string, double, size_t, ssize_t, bool, std::nullopt_t>;
- using map_t = std::unordered_map<std::string, value_t>;
-
- virtual const map_t get_all_values() const = 0;
+ virtual const json::map_t get_all_values() const = 0;
protected:
std::string m_rc_name;
@@ -140,7 +138,7 @@ class RemoteControllers {
void check_faults();
std::list< std::vector<std::string> > get_param_list_values(const std::string& name);
std::string get_param(const std::string& name, const std::string& param);
- std::string get_params_json(const std::string& name);
+ std::string get_showjson();
void set_param(
const std::string& name,
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index 5213d8d..0fe9c6d 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -435,9 +435,9 @@ const string DabModulator::get_parameter(const string& parameter) const
return ss.str();
}
-const RemoteControllable::map_t DabModulator::get_all_values() const
+const json::map_t DabModulator::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["rate"] = m_settings.outputRate;
map["num_clipped_samples"] = m_formatConverter ? m_formatConverter->get_num_clipped_samples() : 0;
return map;
diff --git a/src/DabModulator.h b/src/DabModulator.h
index 6381252..140f313 100644
--- a/src/DabModulator.h
+++ b/src/DabModulator.h
@@ -64,7 +64,7 @@ public:
/******* REMOTE CONTROL ********/
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
protected:
void setMode(unsigned mode);
diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp
index 523d405..d2a6121 100644
--- a/src/FIRFilter.cpp
+++ b/src/FIRFilter.cpp
@@ -347,9 +347,9 @@ const string FIRFilter::get_parameter(const string& parameter) const
return ss.str();
}
-const RemoteControllable::map_t FIRFilter::get_all_values() const
+const json::map_t FIRFilter::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["ntaps"] = m_taps.size();
map["tapsfile"] = m_taps_file;
return map;
diff --git a/src/FIRFilter.h b/src/FIRFilter.h
index 2a469aa..a4effa1 100644
--- a/src/FIRFilter.h
+++ b/src/FIRFilter.h
@@ -61,7 +61,7 @@ public:
/******* REMOTE CONTROL ********/
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
protected:
virtual int internal_process(Buffer* const dataIn, Buffer* dataOut) override;
diff --git a/src/GainControl.cpp b/src/GainControl.cpp
index d90da45..beb93f6 100644
--- a/src/GainControl.cpp
+++ b/src/GainControl.cpp
@@ -583,9 +583,9 @@ const string GainControl::get_parameter(const string& parameter) const
return ss.str();
}
-const RemoteControllable::map_t GainControl::get_all_values() const
+const json::map_t GainControl::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["digital"] = m_digGain;
switch (m_gainmode) {
case GainMode::GAIN_FIX:
diff --git a/src/GainControl.h b/src/GainControl.h
index f024fa2..04f6b58 100644
--- a/src/GainControl.h
+++ b/src/GainControl.h
@@ -66,7 +66,7 @@ class GainControl : public PipelinedModCodec, public RemoteControllable
/* Functions for the remote control */
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
protected:
virtual int internal_process(
diff --git a/src/GuardIntervalInserter.cpp b/src/GuardIntervalInserter.cpp
index d5c71fb..80394b7 100644
--- a/src/GuardIntervalInserter.cpp
+++ b/src/GuardIntervalInserter.cpp
@@ -303,9 +303,9 @@ const std::string GuardIntervalInserter::get_parameter(const std::string& parame
return ss.str();
}
-const RemoteControllable::map_t GuardIntervalInserter::get_all_values() const
+const json::map_t GuardIntervalInserter::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["windowlen"] = d_windowOverlap;
return map;
}
diff --git a/src/GuardIntervalInserter.h b/src/GuardIntervalInserter.h
index f88bdac..5aaad2b 100644
--- a/src/GuardIntervalInserter.h
+++ b/src/GuardIntervalInserter.h
@@ -58,7 +58,7 @@ class GuardIntervalInserter : public ModCodec, public RemoteControllable
/******* REMOTE CONTROL ********/
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
protected:
void update_window(size_t new_window_overlap);
diff --git a/src/MemlessPoly.cpp b/src/MemlessPoly.cpp
index a2b0082..30d4ce9 100644
--- a/src/MemlessPoly.cpp
+++ b/src/MemlessPoly.cpp
@@ -467,9 +467,9 @@ const string MemlessPoly::get_parameter(const string& parameter) const
return ss.str();
}
-const RemoteControllable::map_t MemlessPoly::get_all_values() const
+const json::map_t MemlessPoly::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["ncoefs"] = m_coefs_am.size();
map["coefs"] = serialise_coefficients();
map["coeffile"] = m_coefs_file;
diff --git a/src/MemlessPoly.h b/src/MemlessPoly.h
index 09adc13..91e6860 100644
--- a/src/MemlessPoly.h
+++ b/src/MemlessPoly.h
@@ -68,7 +68,7 @@ public:
/******* REMOTE CONTROL ********/
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
private:
int internal_process(Buffer* const dataIn, Buffer* dataOut) override;
diff --git a/src/OfdmGenerator.cpp b/src/OfdmGenerator.cpp
index d161861..cb799d3 100644
--- a/src/OfdmGenerator.cpp
+++ b/src/OfdmGenerator.cpp
@@ -458,9 +458,9 @@ const std::string OfdmGenerator::get_parameter(const std::string& parameter) con
return ss.str();
}
-const RemoteControllable::map_t OfdmGenerator::get_all_values() const
+const json::map_t OfdmGenerator::get_all_values() const
{
- map_t map;
+ json::map_t map;
// TODO needs rework of the values
return map;
}
diff --git a/src/OfdmGenerator.h b/src/OfdmGenerator.h
index 90e562a..dc1ad46 100644
--- a/src/OfdmGenerator.h
+++ b/src/OfdmGenerator.h
@@ -61,7 +61,7 @@ class OfdmGenerator : public ModCodec, public RemoteControllable
/* Functions for the remote control */
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
protected:
struct cfr_iter_stat_t {
diff --git a/src/TII.cpp b/src/TII.cpp
index b329cdb..9068630 100644
--- a/src/TII.cpp
+++ b/src/TII.cpp
@@ -385,9 +385,9 @@ const std::string TII::get_parameter(const std::string& parameter) const
return ss.str();
}
-const RemoteControllable::map_t TII::get_all_values() const
+const json::map_t TII::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["enable"] = m_conf.enable;
map["pattern"] = m_conf.pattern;
map["comb"] = m_conf.comb;
diff --git a/src/TII.h b/src/TII.h
index b0ba646..a8d0ca9 100644
--- a/src/TII.h
+++ b/src/TII.h
@@ -89,7 +89,7 @@ class TII : public ModCodec, public RemoteControllable
/******* REMOTE CONTROL ********/
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
protected:
// Fill m_Acp with the correct carriers for the pattern/comb
diff --git a/src/TimestampDecoder.cpp b/src/TimestampDecoder.cpp
index 149cd50..4277e55 100644
--- a/src/TimestampDecoder.cpp
+++ b/src/TimestampDecoder.cpp
@@ -301,9 +301,9 @@ const std::string TimestampDecoder::get_parameter(
return ss.str();
}
-const RemoteControllable::map_t TimestampDecoder::get_all_values() const
+const json::map_t TimestampDecoder::get_all_values() const
{
- map_t map;
+ json::map_t map;
map["offset"] = timestamp_offset;
if (full_timestamp_received) {
map["timestamp"] = time_secs + ((double)time_pps / 16384000.0);
diff --git a/src/TimestampDecoder.h b/src/TimestampDecoder.h
index dc5aa78..b90c328 100644
--- a/src/TimestampDecoder.h
+++ b/src/TimestampDecoder.h
@@ -120,7 +120,7 @@ class TimestampDecoder : public RemoteControllable
/* Base function to set parameters. */
virtual void set_parameter(const std::string& parameter, const std::string& value) override;
virtual const std::string get_parameter(const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
const char* name() { return "TS"; }
diff --git a/src/output/SDR.cpp b/src/output/SDR.cpp
index 11321f2..4fc3277 100644
--- a/src/output/SDR.cpp
+++ b/src/output/SDR.cpp
@@ -450,7 +450,7 @@ const string SDR::get_parameter(const string& parameter) const
if (m_device) {
const auto stat = m_device->get_run_statistics();
try {
- const auto& value = stat.at(parameter);
+ const auto& value = stat.at(parameter).data;
if (std::holds_alternative<string>(value)) {
ss << std::get<string>(value);
}
@@ -485,9 +485,9 @@ const string SDR::get_parameter(const string& parameter) const
return ss.str();
}
-const RemoteControllable::map_t SDR::get_all_values() const
+const json::map_t SDR::get_all_values() const
{
- map_t stat = m_device->get_run_statistics();
+ json::map_t stat = m_device->get_run_statistics();
stat["txgain"] = m_config.txgain;
stat["rxgain"] = m_config.rxgain;
diff --git a/src/output/SDR.h b/src/output/SDR.h
index 94c972b..960de0c 100644
--- a/src/output/SDR.h
+++ b/src/output/SDR.h
@@ -67,7 +67,7 @@ class SDR : public ModOutput, public ModMetadata, public RemoteControllable {
virtual const std::string get_parameter(
const std::string& parameter) const override;
- virtual const RemoteControllable::map_t get_all_values() const override;
+ virtual const json::map_t get_all_values() const override;
private:
void process_thread_entry(void);
diff --git a/src/output/SDRDevice.h b/src/output/SDRDevice.h
index f84b340..f728d8b 100644
--- a/src/output/SDRDevice.h
+++ b/src/output/SDRDevice.h
@@ -116,7 +116,7 @@ struct FrameData {
// All SDR Devices must implement the SDRDevice interface
class SDRDevice {
public:
- using run_statistics_t = RemoteControllable::map_t;
+ using run_statistics_t = json::map_t;
virtual void tune(double lo_offset, double frequency) = 0;
virtual double get_tx_freq(void) const = 0;