Switched to new cleaner argument system

This commit is contained in:
AlexandreRouma 2022-02-24 20:49:53 +01:00
parent 5c138aa4a5
commit 2779516378
50 changed files with 777 additions and 205 deletions

View File

@ -50,6 +50,7 @@ option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Depend
# Decoders
option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies: ffplay)" OFF)
option(OPT_BUILD_KG_SSTV_DECODER "Build the M17 decoder module (no dependencies required)" OFF)
option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (no dependencies required)" OFF)
option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON)
option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
@ -64,7 +65,7 @@ option(OPT_BUILD_SCANNER "Frequency scanner" OFF)
option(OPT_BUILD_SCHEDULER "Build the scheduler" OFF)
# Other options
option(USE_INTERNAL_LIBCORRECT "Use an external version of libcorrect" ON)
option(USE_INTERNAL_LIBCORRECT "Use an internal version of libcorrect" ON)
option(USE_BUNDLE_DEFAULTS "Set the default resource and module directories to the right ones for a MacOS .app" OFF)
# Core of SDR++
@ -159,6 +160,10 @@ if (OPT_BUILD_FALCON9_DECODER)
add_subdirectory("decoder_modules/falcon9_decoder")
endif (OPT_BUILD_FALCON9_DECODER)
if (OPT_BUILD_KG_SSTV_DECODER)
add_subdirectory("decoder_modules/kg_sstv_decoder")
endif (OPT_BUILD_KG_SSTV_DECODER)
if (OPT_BUILD_M17_DECODER)
add_subdirectory("decoder_modules/m17_decoder")
endif (OPT_BUILD_M17_DECODER)

View File

@ -124,9 +124,7 @@ class MainActivity : NativeActivity() {
// We assume dispatchKeyEvent() of the NativeActivity is actually called for every
// KeyEvent and not consumed by any View before it reaches here
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
Log.w(TAG, "Key Action");
if (event.action == KeyEvent.ACTION_DOWN) {
Log.w(TAG, "Key Pressed");
unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState))
}
return super.dispatchKeyEvent(event)

View File

@ -16,7 +16,6 @@
#include <gui/style.h>
#include <gui/menus/theme.h>
#include <filesystem>
#include <options.h>
// Credit to the ImGui android OpenGL3 example for a lot of this code!
@ -36,9 +35,10 @@ namespace backend {
int PollUnicodeChars();
void doPartialInit() {
std::string root = core::args["root"];
backend::init();
style::loadFonts(options::opts.root + "/res"); // TODO: Don't hardcode, use config
icons::load(options::opts.root + "/res");
style::loadFonts(root + "/res"); // TODO: Don't hardcode, use config
icons::load(root + "/res");
thememenu::applyTheme();
ImGui::GetStyle().ScaleAllSizes(style::uiScale);
gui::mainWindow.setFirstMenuRender();

View File

@ -86,6 +86,31 @@ public:
return sval;
}
bool b() {
if (type != CLI_ARG_TYPE_BOOL && type != CLI_ARG_TYPE_VOID) { throw std::runtime_error("Not a bool"); }
return bval;
}
int i() {
if (type != CLI_ARG_TYPE_INT) { throw std::runtime_error("Not an int"); }
return ival;
}
float f() {
if (type != CLI_ARG_TYPE_FLOAT) { throw std::runtime_error("Not a float"); }
return (float)fval;
}
double d() {
if (type != CLI_ARG_TYPE_FLOAT) { throw std::runtime_error("Not a float"); }
return fval;
}
const std::string& s() {
if (type != CLI_ARG_TYPE_STRING) { throw std::runtime_error("Not a string"); }
return sval;
}
friend CommandArgsParser;
CLIArgType type;

View File

@ -11,7 +11,6 @@
#include <stb_image.h>
#include <config.h>
#include <core.h>
#include <options.h>
#include <filesystem>
#include <gui/menus/theme.h>
#include <backend.h>
@ -41,7 +40,7 @@ namespace core {
void setInputSampleRate(double samplerate) {
// Forward this to the server
if (options::opts.serverMode) { server::setInputSampleRate(samplerate); return; }
if (args["server"].b()) { server::setInputSampleRate(samplerate); return; }
sigpath::signalPath.sourceSampleRate = samplerate;
double effectiveSr = samplerate / ((double)(1 << sigpath::signalPath.decimation));
@ -75,25 +74,25 @@ int sdrpp_main(int argc, char* argv[]) {
return 0;
}
// Load default options and parse command line
options::loadDefaults();
if (!options::parse(argc, argv)) { return -1; }
bool serverMode = core::args["server"];
#ifdef _WIN32
if (!options::opts.showConsole && !options::opts.serverMode) { FreeConsole(); }
if (!core::args["con"].b() && !serverMode) { FreeConsole(); }
#endif
// Check root directory
if (!std::filesystem::exists(options::opts.root)) {
spdlog::warn("Root directory {0} does not exist, creating it", options::opts.root);
if (!std::filesystem::create_directories(options::opts.root)) {
spdlog::error("Could not create root directory {0}", options::opts.root);
std::string root = core::args["root"];
if (!std::filesystem::exists(root)) {
spdlog::warn("Root directory {0} does not exist, creating it", root);
if (!std::filesystem::create_directories(root)) {
spdlog::error("Could not create root directory {0}", root);
return -1;
}
}
if (!std::filesystem::is_directory(options::opts.root)) {
spdlog::error("{0} is not a directory", options::opts.root);
// Check that the path actually is a directory
if (!std::filesystem::is_directory(root)) {
spdlog::error("{0} is not a directory", root);
return -1;
}
@ -225,8 +224,8 @@ int sdrpp_main(int argc, char* argv[]) {
defConfig["modulesDirectory"] = "../Plugins";
defConfig["resourcesDirectory"] = "../Resources";
#elif defined(__ANDROID__)
defConfig["modulesDirectory"] = options::opts.root + "/modules";
defConfig["resourcesDirectory"] = options::opts.root + "/res";
defConfig["modulesDirectory"] = root + "/modules";
defConfig["resourcesDirectory"] = root + "/res";
#else
defConfig["modulesDirectory"] = INSTALL_PREFIX "/lib/sdrpp/plugins";
defConfig["resourcesDirectory"] = INSTALL_PREFIX "/share/sdrpp";
@ -234,7 +233,7 @@ int sdrpp_main(int argc, char* argv[]) {
// Load config
spdlog::info("Loading config");
core::configManager.setPath(options::opts.root + "/config.json");
core::configManager.setPath(root + "/config.json");
core::configManager.load(defConfig);
core::configManager.enableAutoSave();
core::configManager.acquire();
@ -296,7 +295,7 @@ int sdrpp_main(int argc, char* argv[]) {
core::configManager.release(true);
if (options::opts.serverMode) { return server::main(); }
if (serverMode) { return server::main(); }
core::configManager.acquire();
std::string resDir = core::configManager.conf["resourcesDirectory"];
@ -314,6 +313,9 @@ int sdrpp_main(int argc, char* argv[]) {
int biRes = backend::init(resDir);
if (biRes < 0) { return biRes; }
// Intialize SmGui in normal mode
SmGui::init(false);
if (!style::loadFonts(resDir)) { return -1; }
thememenu::init(resDir);
LoadingScreen::init();

View File

@ -1,7 +1,6 @@
#include <gui/icons.h>
#include <stdint.h>
#include <config.h>
#include <options.h>
#define STB_IMAGE_IMPLEMENTATION
#include <imgui/stb_image.h>

View File

@ -24,7 +24,6 @@
#include <filesystem>
#include <signal_path/source.h>
#include <gui/dialogs/loading_screen.h>
#include <options.h>
#include <gui/colormaps.h>
#include <gui/widgets/snr_meter.h>
#include <gui/tuner.h>

View File

@ -1,6 +1,5 @@
#include <gui/menus/theme.h>
#include <gui/gui.h>
#include <options.h>
#include <core.h>
#include <gui/style.h>

View File

@ -1,6 +1,5 @@
#include "smgui.h"
#include "style.h"
#include <options.h>
#include <gui/widgets/stepped_slider.h>
#include <gui/gui.h>
@ -25,6 +24,7 @@ namespace SmGui {
std::string diffId = "";
DrawListElem diffValue;
bool nextItemFillWidth = false;
bool serverMode = false;
std::string ImStrToString(const char* imstr) {
int len = 0;
@ -33,6 +33,10 @@ namespace SmGui {
return std::string(imstr, end);
}
void init(bool server) {
serverMode = server;
}
// Rec/Play functions
void setDiff(std::string id, SmGui::DrawListElem value) {
diffId = id;
@ -457,7 +461,7 @@ namespace SmGui {
// Format functions
void FillWidth() {
if (!options::opts.serverMode) {
if (!serverMode) {
nextItemFillWidth = true;
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
return;
@ -466,17 +470,17 @@ namespace SmGui {
}
void SameLine() {
if (!options::opts.serverMode) { ImGui::SameLine(); return; }
if (!serverMode) { ImGui::SameLine(); return; }
if (rdl) { rdl->pushStep(DRAW_STEP_SAME_LINE, false); }
}
void BeginDisabled() {
if (!options::opts.serverMode) { style::beginDisabled(); return; }
if (!serverMode) { style::beginDisabled(); return; }
if (rdl) { rdl->pushStep(DRAW_STEP_BEGIN_DISABLED, false); }
}
void EndDisabled() {
if (!options::opts.serverMode) { style::endDisabled(); return; }
if (!serverMode) { style::endDisabled(); return; }
if (rdl) { rdl->pushStep(DRAW_STEP_END_DISABLED, false); }
}
@ -484,7 +488,7 @@ namespace SmGui {
// Widget functions
bool Combo(const char *label, int *current_item, const char *items_separated_by_zeros, int popup_max_height_in_items) {
nextItemFillWidth = false;
if (!options::opts.serverMode) { return ImGui::Combo(label, current_item, items_separated_by_zeros, popup_max_height_in_items); }
if (!serverMode) { return ImGui::Combo(label, current_item, items_separated_by_zeros, popup_max_height_in_items); }
if (rdl) {
rdl->pushStep(DRAW_STEP_COMBO, forceSyncForNext);
rdl->pushString(label);
@ -501,7 +505,7 @@ namespace SmGui {
}
bool Button(const char *label, ImVec2 size) {
if (!options::opts.serverMode) {
if (!serverMode) {
if (nextItemFillWidth) {
nextItemFillWidth = false;
size.x = ImGui::GetContentRegionAvail().x;
@ -519,7 +523,7 @@ namespace SmGui {
}
void Columns(int count, const char *id, bool border) {
if (!options::opts.serverMode) { ImGui::Columns(count, id, border); return; }
if (!serverMode) { ImGui::Columns(count, id, border); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_COLUMNS, forceSyncForNext);
rdl->pushInt(count);
@ -530,12 +534,12 @@ namespace SmGui {
}
void NextColumn() {
if (!options::opts.serverMode) { ImGui::NextColumn(); return; }
if (!serverMode) { ImGui::NextColumn(); return; }
if (rdl) { rdl->pushStep(DRAW_STEP_NEXT_COLUMN, false); }
}
bool RadioButton(const char *label, bool active) {
if (!options::opts.serverMode) { return ImGui::RadioButton(label, active); }
if (!serverMode) { return ImGui::RadioButton(label, active); }
if (rdl) {
rdl->pushStep(DRAW_STEP_RADIO_BUTTON, forceSyncForNext);
rdl->pushString(label);
@ -546,17 +550,17 @@ namespace SmGui {
}
void BeginGroup() {
if (!options::opts.serverMode) { ImGui::BeginGroup(); return; }
if (!serverMode) { ImGui::BeginGroup(); return; }
if (rdl) { rdl->pushStep(DRAW_STEP_BEGIN_GROUP, false); }
}
void EndGroup() {
if (!options::opts.serverMode) { ImGui::EndGroup(); return; }
if (!serverMode) { ImGui::EndGroup(); return; }
if (rdl) { rdl->pushStep(DRAW_STEP_END_GROUP, false); }
}
void LeftLabel(const char *text) {
if (!options::opts.serverMode) { ImGui::LeftLabel(text); return; }
if (!serverMode) { ImGui::LeftLabel(text); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_LEFT_LABEL, forceSyncForNext);
rdl->pushString(text);
@ -566,7 +570,7 @@ namespace SmGui {
bool SliderInt(const char *label, int *v, int v_min, int v_max, FormatString format, ImGuiSliderFlags flags) {
nextItemFillWidth = false;
if (!options::opts.serverMode) { return ImGui::SliderInt(label, v, v_min, v_max, fmtStr[format], flags); }
if (!serverMode) { return ImGui::SliderInt(label, v, v_min, v_max, fmtStr[format], flags); }
if (rdl) {
rdl->pushStep(DRAW_STEP_SLIDER_INT, forceSyncForNext);
rdl->pushString(label);
@ -586,7 +590,7 @@ namespace SmGui {
bool SliderFloatWithSteps(const char *label, float *v, float v_min, float v_max, float v_step, FormatString display_format) {
nextItemFillWidth = false;
if (!options::opts.serverMode) { return ImGui::SliderFloatWithSteps(label, v, v_min, v_max, v_step, fmtStr[display_format]); }
if (!serverMode) { return ImGui::SliderFloatWithSteps(label, v, v_min, v_max, v_step, fmtStr[display_format]); }
if (rdl) {
rdl->pushStep(DRAW_STEP_SLIDER_FLOAT_WITH_STEPS, forceSyncForNext);
rdl->pushString(label);
@ -606,7 +610,7 @@ namespace SmGui {
bool InputInt(const char *label, int *v, int step, int step_fast, ImGuiInputTextFlags flags) {
nextItemFillWidth = false;
if (!options::opts.serverMode) { return ImGui::InputInt(label, v, step, step_fast, flags); }
if (!serverMode) { return ImGui::InputInt(label, v, step, step_fast, flags); }
if (rdl) {
rdl->pushStep(DRAW_STEP_INPUT_INT, forceSyncForNext);
rdl->pushString(label);
@ -624,7 +628,7 @@ namespace SmGui {
}
bool Checkbox(const char *label, bool *v) {
if (!options::opts.serverMode) { return ImGui::Checkbox(label, v); }
if (!serverMode) { return ImGui::Checkbox(label, v); }
if (rdl) {
rdl->pushStep(DRAW_STEP_CHECKBOX, forceSyncForNext);
rdl->pushString(label);
@ -640,7 +644,7 @@ namespace SmGui {
bool SliderFloat(const char *label, float *v, float v_min, float v_max, FormatString format, ImGuiSliderFlags flags) {
nextItemFillWidth = false;
if (!options::opts.serverMode) { return ImGui::SliderFloat(label, v, v_min, v_max, fmtStr[format], flags); }
if (!serverMode) { return ImGui::SliderFloat(label, v, v_min, v_max, fmtStr[format], flags); }
if (rdl) {
rdl->pushStep(DRAW_STEP_SLIDER_FLOAT, forceSyncForNext);
rdl->pushString(label);
@ -660,7 +664,7 @@ namespace SmGui {
bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags) {
nextItemFillWidth = false;
if (!options::opts.serverMode) { return ImGui::InputText(label, buf, buf_size, flags); }
if (!serverMode) { return ImGui::InputText(label, buf, buf_size, flags); }
if (rdl) {
rdl->pushStep(DRAW_STEP_INPUT_TEXT, forceSyncForNext);
rdl->pushString(label);
@ -677,7 +681,7 @@ namespace SmGui {
}
void Text(const char* str) {
if (!options::opts.serverMode) { ImGui::TextUnformatted(str); return; }
if (!serverMode) { ImGui::TextUnformatted(str); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_TEXT, false);
rdl->pushString(str);
@ -685,7 +689,7 @@ namespace SmGui {
}
void TextColored(const ImVec4 &col, const char *str) {
if (!options::opts.serverMode) { ImGui::TextColored(col, "%s", str); return; }
if (!serverMode) { ImGui::TextColored(col, "%s", str); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_TEXT_COLORED, false);
rdl->pushFloat(col.x);
@ -697,7 +701,7 @@ namespace SmGui {
}
void OpenPopup(const char *str_id, ImGuiPopupFlags popup_flags) {
if (!options::opts.serverMode) { ImGui::OpenPopup(str_id, popup_flags); return; }
if (!serverMode) { ImGui::OpenPopup(str_id, popup_flags); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_OPEN_POPUP, false);
rdl->pushString(str_id);
@ -706,7 +710,7 @@ namespace SmGui {
}
bool BeginPopup(const char *str_id, ImGuiWindowFlags flags) {
if (!options::opts.serverMode) { return ImGui::BeginPopup(str_id, flags); }
if (!serverMode) { return ImGui::BeginPopup(str_id, flags); }
if (rdl) {
rdl->pushStep(DRAW_STEP_BEGIN_POPUP, false);
rdl->pushString(str_id);
@ -716,14 +720,14 @@ namespace SmGui {
}
void EndPopup() {
if (!options::opts.serverMode) { ImGui::EndPopup(); return; }
if (!serverMode) { ImGui::EndPopup(); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_END_POPUP, false);
}
}
bool BeginTable(const char *str_id, int column, ImGuiTableFlags flags, const ImVec2 &outer_size, float inner_width) {
if (!options::opts.serverMode) { return ImGui::BeginTable(str_id, column, flags, outer_size, inner_width); }
if (!serverMode) { return ImGui::BeginTable(str_id, column, flags, outer_size, inner_width); }
if (rdl) {
rdl->pushStep(DRAW_STEP_BEGIN_TABLE, false);
rdl->pushString(str_id);
@ -737,14 +741,14 @@ namespace SmGui {
}
void EndTable() {
if (!options::opts.serverMode) { ImGui::EndTable(); return; }
if (!serverMode) { ImGui::EndTable(); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_END_TABLE, false);
}
}
void TableNextRow(ImGuiTableRowFlags row_flags, float min_row_height) {
if (!options::opts.serverMode) { ImGui::TableNextRow(row_flags, min_row_height); return; }
if (!serverMode) { ImGui::TableNextRow(row_flags, min_row_height); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_TABLE_NEXT_ROW, false);
rdl->pushInt(row_flags);
@ -753,7 +757,7 @@ namespace SmGui {
}
void TableSetColumnIndex(int column_n) {
if (!options::opts.serverMode) { ImGui::TableSetColumnIndex(column_n); return; }
if (!serverMode) { ImGui::TableSetColumnIndex(column_n); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_TABLE_SET_COLUMN_INDEX, false);
rdl->pushInt(column_n);
@ -761,7 +765,7 @@ namespace SmGui {
}
void SetNextItemWidth(float item_width) {
if (!options::opts.serverMode) { ImGui::SetNextItemWidth(item_width); return; }
if (!serverMode) { ImGui::SetNextItemWidth(item_width); return; }
if (rdl) {
rdl->pushStep(DRAW_STEP_SET_NEXT_ITEM_WIDTH, false);
rdl->pushFloat(item_width);

View File

@ -100,6 +100,7 @@ namespace SmGui {
// Rec/Play functions
// TODO: Maybe move verification to the load function instead of checking in drawFrame
void init(bool server);
void setDiff(std::string id, SmGui::DrawListElem value);
void startRecord(DrawList* dl);
void stopRecord();

View File

@ -2,7 +2,6 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <config.h>
#include <options.h>
#include <spdlog/spdlog.h>
#include <filesystem>

View File

@ -1,11 +1,12 @@
#include <gui/widgets/file_select.h>
#include <regex>
#include <options.h>
#include <filesystem>
#include <gui/file_dialogs.h>
#include <core.h>
FileSelect::FileSelect(std::string defaultPath, std::vector<std::string> filter) {
_filter = filter;
root = core::args["root"];
setPath(defaultPath);
}
@ -54,7 +55,7 @@ void FileSelect::setPath(std::string path, bool markChanged) {
}
std::string FileSelect::expandString(std::string input) {
input = std::regex_replace(input, std::regex("%ROOT%"), options::opts.root);
input = std::regex_replace(input, std::regex("%ROOT%"), root);
return std::regex_replace(input, std::regex("//"), "/");
}

View File

@ -22,6 +22,7 @@ private:
void worker();
std::thread workerThread;
std::vector<std::string> _filter;
std::string root = "";
bool pathValid = false;
bool dialogOpen = false;

View File

@ -1,10 +1,11 @@
#include <gui/widgets/folder_select.h>
#include <regex>
#include <options.h>
#include <filesystem>
#include <gui/file_dialogs.h>
#include <core.h>
FolderSelect::FolderSelect(std::string defaultPath) {
root = core::args["root"];
setPath(defaultPath);
}
@ -53,7 +54,7 @@ void FolderSelect::setPath(std::string path, bool markChanged) {
}
std::string FolderSelect::expandString(std::string input) {
input = std::regex_replace(input, std::regex("%ROOT%"), options::opts.root);
input = std::regex_replace(input, std::regex("%ROOT%"), root);
return std::regex_replace(input, std::regex("//"), "/");
}

View File

@ -20,6 +20,7 @@ public:
private:
void worker();
std::thread workerThread;
std::string root = "";
bool pathValid = false;
bool dialogOpen = false;

View File

@ -1,57 +0,0 @@
#include <options.h>
#include <spdlog/spdlog.h>
#include <stdlib.h>
#include <filesystem>
namespace options {
CMDLineOptions opts;
void loadDefaults() {
#if defined(_WIN32)
opts.root = ".";
opts.showConsole = false;
#elif defined(IS_MACOS_BUNDLE)
std::string homedir = getenv("HOME");
opts.root = homedir + "/Library/Application Support/sdrpp";
#elif defined(__ANDROID__)
opts.root = "/storage/self/primary/sdrpp";
#else
std::string homedir = getenv("HOME");
opts.root = homedir + "/.config/sdrpp";
#endif
opts.root = std::filesystem::absolute(opts.root).string();
opts.serverHost = "0.0.0.0";
opts.serverPort = 5259;
}
bool parse(int argc, char* argv[]) {
for (int i = 1; i < argc; i++) {
char* arg = argv[i];
if (!strcmp(arg, "-r") || !strcmp(arg, "--root")) {
if (i == argc - 1) { return false; }
opts.root = std::filesystem::absolute(argv[++i]).string();
}
else if (!strcmp(arg, "-s") || !strcmp(arg, "--show-console")) {
opts.showConsole = true;
}
else if (!strcmp(arg, "--server")) {
opts.serverMode = true;
}
else if (!strcmp(arg, "-a") || !strcmp(arg, "--addr")) {
if (i == argc - 1) { return false; }
opts.serverHost = argv[++i];
opts.showConsole = true;
}
else if (!strcmp(arg, "-p") || !strcmp(arg, "--port")) {
if (i == argc - 1) { return false; }
sscanf(argv[++i], "%d", &opts.serverPort);
opts.showConsole = true;
}
else {
spdlog::error("Invalid command line option: {0}", arg);
return false;
}
}
return true;
}
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <string>
#include <module.h>
namespace options {
struct CMDLineOptions {
std::string root;
bool showConsole;
bool serverMode;
std::string serverHost;
int serverPort;
};
SDRPP_EXPORT CMDLineOptions opts;
void loadDefaults();
bool parse(int argc, char* argv[]);
}

View File

@ -3,7 +3,6 @@
#include <spdlog/spdlog.h>
#include <version.h>
#include <config.h>
#include <options.h>
#include <filesystem>
#include <dsp/types.h>
#include <signal_path/signal_path.h>
@ -75,6 +74,7 @@ namespace server {
// Initialize compressor
cctx = ZSTD_createCCtx();
// Load config
core::configManager.acquire();
std::string modulesDir = core::configManager.conf["modulesDirectory"];
std::vector<std::string> modules = core::configManager.conf["modules"];
@ -83,8 +83,10 @@ namespace server {
core::configManager.release();
modulesDir = std::filesystem::absolute(modulesDir).string();
spdlog::info("Loading modules");
// Intialize SmGui in server mode
SmGui::init(true);
spdlog::info("Loading modules");
// Load modules and check type to only load sources ( TODO: Have a proper type parameter int the info )
// TODO LATER: Add whitelist/blacklist stuff
if (std::filesystem::is_directory(modulesDir)) {
@ -146,10 +148,12 @@ namespace server {
sigpath::sourceManager.selectSource(sourceList[sourceId]);
// TODO: Use command line option
listener = net::listen(options::opts.serverHost, options::opts.serverPort);
std::string host = core::args["addr"];
int port = core::args["port"];
listener = net::listen(host, port);
listener->acceptAsync(_clientHandler, NULL);
spdlog::info("Ready, listening on {0}:{1}", options::opts.serverHost, options::opts.serverPort);
spdlog::info("Ready, listening on {0}:{1}", host, port);
while(1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); }
return 0;

View File

@ -2,7 +2,7 @@
#include <signal_path/source.h>
#include <spdlog/spdlog.h>
#include <signal_path/signal_path.h>
#include <options.h>
#include <core.h>
SourceManager::SourceManager() {
}
@ -50,7 +50,7 @@ void SourceManager::selectSource(std::string name) {
selectedHandler = sources[name];
selectedHandler->selectHandler(selectedHandler->ctx);
selectedName = name;
if (options::opts.serverMode) {
if (core::args["server"].b()) {
server::setInput(selectedHandler->stream);
}
else {

View File

@ -4,7 +4,6 @@
#include <gui/style.h>
#include <signal_path/signal_path.h>
#include <module.h>
#include <options.h>
#include <gui/gui.h>
#include <dsp/pll.h>
#include <dsp/stream.h>

View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.13)
project(kg_sstv_decoder)
file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c")
add_library(kg_sstv_decoder SHARED ${SRC})
target_link_libraries(kg_sstv_decoder PRIVATE sdrpp_core)
set_target_properties(kg_sstv_decoder PROPERTIES PREFIX "")
target_include_directories(kg_sstv_decoder PRIVATE "src/")
if (MSVC)
target_compile_options(kg_sstv_decoder PRIVATE /O2 /Ob2 /std:c++17 /EHsc)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(kg_sstv_decoder PRIVATE -O3 -std=c++17 -Wno-unused-command-line-argument -undefined dynamic_lookup)
else ()
target_compile_options(kg_sstv_decoder PRIVATE -O3 -std=c++17)
endif ()
# Install directives
install(TARGETS kg_sstv_decoder DESTINATION lib/sdrpp/plugins)

View File

@ -0,0 +1,133 @@
○ Transmission by MSK and 4L-FSK
MSK is a type of FSK method that is a modulation method for digital signals, and is the mark frequency of FSK.
Minimize the frequency between the number and the space frequency (Minimum Shift Keying)
4L-FSK is a 4-value FSK, and 4 modulation frequencies that can be taken with a type of FSK are provided.
This makes it possible to obtain twice the transmission speed compared to MSK.
4L-FSK is more susceptible to noise because the frequency interval is narrower than MSK.
It also becomes more susceptible to deterioration of transmission line characteristics.
There are two types of choices, but when the line condition such as FM is good, the image will be sent quickly, so
Or I think you should select 4L-FSK to send high quality images. wireless
If the SSB transmission in HF where the line condition is unstable is set to MSK, the data will be as it is.
I think it will be.
The first pull-down menu from the top of the pull-down menu on the right side of Send Image
You can select MSK or 4L-FSK in the new.
○ Transmission in convolutional code mode
The second pull-down menu from the top of the pull-down menu on the right side of Send Image
New is the choice of code processing. Here no code processing (NORM) or convolutional code processing
Set whether to perform (CONV).
When convolutional code processing is performed, it becomes stronger against noise, but the same data is sent.
It takes about twice as long to complete.
Please select the code processing on a case-by-case basis while checking the transmission status.
This setting can be changed even during transmission.
○ Sending and receiving text messages
With KG-STV, a maximum of 510 half-width characters (255 full-width characters) text message can be sent once.
You can send sage.
To send a text message, text in the input box under Resp BSR
And click Send Text on the right.
When you receive a text message, the text will be displayed in the box below.
○ KG-STV transmission standard
Modulation format: MSK or composite modulation of MSK and 4-value FSK
Modulation speed: 1200baud
Modulation frequency: MSK …… Space frequency 1200Hz Mark frequency 1800Hz
4L-FSK ...
'00' 1200Hz
'01' 1400Hz
'10' 1600Hz
'11' 1800Hz
Bandwidth: 500-2500Hz
Error correction: None or Viterbi code (NASA standard K = 7, R=1/2, P=[109, 79] code)
Whitening: Yes (add M-sequence code with a period of 127 bits to each bit)
Interleaver: None
Header: 01 repeat signal is 256 bits
Basic code configuration: Synchronous code + 54-bit length information chunk + arbitrary length data chunk
Error detection: Yes (CRC 16 CCITT)
Synchronous bit: 63-bit M-sequence code
Image compression: JPEG compatible (16x16 pixels, thinning 4: 1: 1)
Character code: Shift JIS compatible
Radio format: F1D (operation in SSB mode)
F2D (operation in FM mode)
Information chunk configuration (system code version '0')
┌─────┬─────┬───┬───┬───┬───┬────┬──────┬─────┐
│ sys │ com │ c │ m │ x │ y │ sc │ size │ CRC │
└─────┴─────┴───┴───┴───┴───┴────┴──────┴─────┘
0 4 8 9 10 16 22 26 38 54bit
Sys: system code
Com: command code
C: sign mode
M: Modulation mode
X: Image block position (X)
Y: Image block position (Y)
Sc: JPEG scale size
Size: data size
CRC: Error detection code
* Information chunks always perform MSK modulation + convolution processing.
Data chunk structure (system code version '0')
┌──────┬─────┐
│ data │ CRC │
└──────┴─────┘
* Data chunks are transmitted following the CRC code of the information chunks.
Command table (system code version '0')
┌─────┬────────┐
│ Command value │ Operation │ │
├─────┼────────┤
│ 0 │ text transmission │
├─────┼────────┤
│ 1 │ Image transmission │ │
├─────┼────────┤
│ 2 │ BSR response │ │
├─────┼────────┤
│ │ 3 │ end │ │
├─────┼────────┤
│ │ 4 │ BSR request │ │
├─────┼────────┤
│ 5 │ Canceled (suspended) │
├─────┼────────┤
│ 6 │ call sign │
└─────┴────────┘
* When starting transmission, the header code of 01 shall be transmitted first.
* One data format (code configuration) is
Synchronous code + information chunk + data chunk
It will be. However, the end signal, stop signal, and BSR signal do not include data chunks.
stomach.
* In the case of image data, this data format is continuous for the number of image blocks.
It shall be sent.
* In the case of text transmission, it shall be completed in one data format.
* When the transmission is completed normally, the end signal shall be transmitted three times at the end.
* When the transmission is canceled, the cancellation signal shall be transmitted three times at the end.
Synchronous code
000011100001001000110110010110101110111100110001010100111111010
Whitening code
1110110011000100100111001111100100000100011010101001101101001010000101100001100101111111010110111011110001110100010101110000001
○ KG-STV needs more experiments
KG-STV was born from the creator's own interest in digital image communication.
However, there is a lack of practical experience due to the ability of the person himself / herself.
Therefore, the actual luck is that the transmission time is slow, the image quality is poor, and it is difficult to receive.
I think there are many situations where it is not practical in terms of use.
In such a case, I would like to research as a new issue, so by all means
We hope that many people will use it and give us their impressions.
Inconvenience such as bugs and operational problems until the degree of completion is high after receiving your opinions
We apologize for the inconvenience, but thank you for your cooperation.
Creator: K.G (JJ0OBZ Myoko City, Niigata Prefecture)
-------------------------------------------------- -------------------------------------------------- --------------------
Created and written by K.G k.g8956@ymail.plala.or.jp
Today also from the day of the plane http://www2.plala.or.jp/hikokibiyori/
-------------------------------------------------- -------------------------------------------------- --------------------

View File

@ -0,0 +1,280 @@
#pragma once
#include <dsp/block.h>
#include <dsp/stream.h>
#include <dsp/types.h>
#include <dsp/routing.h>
#include <dsp/demodulator.h>
#include <dsp/sink.h>
#include <spdlog/spdlog.h>
extern "C" {
#include <correct.h>
}
#define KGSSTV_DEVIATION 300
#define KGSSTV_BAUDRATE 1200
#define KGSSTV_RRC_ALPHA 0.7f
#define KGSSTV_4FSK_HIGH_CUT 0.5f
// const uint8_t KGSSTV_SYNC_WORD[] = {
// 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
// 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
// 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0,
// 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0,
// 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
// 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
// 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
// 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0
// };
const uint8_t KGSSTV_SYNC_WORD[] = {
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0,
1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1,
0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0
};
const uint8_t KGSSTV_SCRAMBLING[] = {
1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0,
1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1,
0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0,
1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0,
0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1,
1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0,
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1
};
const uint8_t KGSSTV_SCRAMBLING_BYTES[] = {
0b11101100, 0b11000100, 0b10011100, 0b11111001, 0b00000100,
0b01101010, 0b10011011, 0b01001010, 0b00010110, 0b00011001,
0b01111111, 0b01011011, 0b10111100, 0b01110100, 0b01010111,
0b00000010
};
static const correct_convolutional_polynomial_t kgsstv_polynomial[] = {0155, 0117};
#define KGSSTV_SYNC_WORD_SIZE sizeof(KGSSTV_SYNC_WORD)
#define KGSSTV_SYNC_SCRAMBLING_SIZE sizeof(KGSSTV_SCRAMBLING)
namespace kgsstv {
// class Slice4FSK : public dsp::generic_block<Slice4FSK> {
// public:
// Slice4FSK() {}
// Slice4FSK(dsp::stream<float>* in) { init(in); }
// void init(dsp::stream<float>* in) {
// _in = in;
// dsp::generic_block<Slice4FSK>::registerInput(_in);
// dsp::generic_block<Slice4FSK>::registerOutput(&out);
// dsp::generic_block<Slice4FSK>::_block_init = true;
// }
// void setInput(dsp::stream<float>* in) {
// assert(dsp::generic_block<Slice4FSK>::_block_init);
// std::lock_guard<std::mutex> lck(dsp::generic_block<Slice4FSK>::ctrlMtx);
// dsp::generic_block<Slice4FSK>::tempStop();
// dsp::generic_block<Slice4FSK>::unregisterInput(_in);
// _in = in;
// dsp::generic_block<Slice4FSK>::registerInput(_in);
// dsp::generic_block<Slice4FSK>::tempStart();
// }
// int run() {
// int count = _in->read();
// if (count < 0) { return -1; }
// float val;
// for (int i = 0; i < count; i++) {
// val = _in->readBuf[i];
// out.writeBuf[i * 2] = (val > 0.0f);
// if (val > 0.0f) {
// out.writeBuf[(i * 2) + 1] = (val > KGSSTV_4FSK_HIGH_CUT);
// }
// else {
// out.writeBuf[(i * 2) + 1] = (val > -KGSSTV_4FSK_HIGH_CUT);
// }
// }
// _in->flush();
// if (!out.swap(count * 2)) { return -1; }
// return count;
// }
// dsp::stream<uint8_t> out;
// private:
// dsp::stream<float>* _in;
// };
class Deframer : public dsp::generic_block<Deframer> {
public:
Deframer() {}
Deframer(dsp::stream<float>* in) { init(in); }
void init(dsp::stream<float>* in) {
_in = in;
// TODO: Destroy
conv = correct_convolutional_create(2, 7, kgsstv_polynomial);
memset(convTmp, 0x00, 1024);
dsp::generic_block<Deframer>::registerInput(_in);
dsp::generic_block<Deframer>::registerOutput(&out);
dsp::generic_block<Deframer>::_block_init = true;
}
void setInput(dsp::stream<float>* in) {
assert(dsp::generic_block<Deframer>::_block_init);
std::lock_guard<std::mutex> lck(dsp::generic_block<Deframer>::ctrlMtx);
dsp::generic_block<Deframer>::tempStop();
dsp::generic_block<Deframer>::unregisterInput(_in);
_in = in;
dsp::generic_block<Deframer>::registerInput(_in);
dsp::generic_block<Deframer>::tempStart();
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
for (int i = 0; i < count; i++) {
if (syncing) {
// If sync broken, reset sync
if ((_in->readBuf[i] > 0.0f) && !KGSSTV_SYNC_WORD[match]) {
if (++err > 4) {
i -= match - 1;
match = 0;
err = 0;
continue;
}
}
// If full syncword was detected, switch to read mode
if (++match == KGSSTV_SYNC_WORD_SIZE) {
spdlog::warn("Frame detected");
syncing = false;
readCount = 0;
writeCount = 0;
}
}
else {
// // Process symbol
// if (!(readCount % 2)) {
// int bitOffset = writeCount & 0b111;
// int byteOffset = writeCount >> 3;
// if (!bitOffset) { convTmp[byteOffset] = 0; }
// convTmp[byteOffset] |= _in->readBuf[i] << (7 - bitOffset);
// writeCount++;
// }
// Process symbol
convTmp[readCount] = std::clamp<int>((_in->readBuf[i] + 1.0f) * 128.0f, 0, 255);
// When info was read, write data and get back to
if (++readCount == 108) {
match = 0;
err = 0;
syncing = true;
// Descramble
for (int j = 0; j < 108; j++) {
if (KGSSTV_SCRAMBLING[j]) {
convTmp[j] = 255 - convTmp[j];
}
//convTmp[j >> 3] ^= KGSSTV_SCRAMBLING[j] << (7 - (j & 0b111));
}
// Decode convolutional code
int convOutCount = correct_convolutional_decode_soft(conv, convTmp, 124, out.writeBuf);
spdlog::warn("Frames written: {0}, frameBytes: {1}", ++framesWritten, convOutCount);
if (!out.swap(7)) {
_in->flush();
return -1;
}
}
}
}
_in->flush();
return count;
}
dsp::stream<uint8_t> out;
private:
dsp::stream<float>* _in;
correct_convolutional* conv = NULL;
uint8_t convTmp[1024];
int match = 0;
int err = 0;
int readCount = 0;
int writeCount = 0;
bool syncing = true;
int framesWritten = 0;
};
class Decoder : public dsp::generic_hier_block<Decoder> {
public:
Decoder() {}
Decoder(dsp::stream<dsp::complex_t>* input, float sampleRate) {
init(input, sampleRate);
}
void init(dsp::stream<dsp::complex_t>* input, float sampleRate) {
_sampleRate = sampleRate;
demod.init(input, _sampleRate, KGSSTV_DEVIATION);
rrc.init(31, _sampleRate, KGSSTV_BAUDRATE, KGSSTV_RRC_ALPHA);
fir.init(&demod.out, &rrc);
recov.init(&fir.out, _sampleRate / KGSSTV_BAUDRATE, 1e-6f, 0.01f, 0.01f);
doubler.init(&recov.out);
//slicer.init(&doubler.outA);
deframer.init(&doubler.outA);
ns2.init(&deframer.out, "kgsstv_out.bin");
diagOut = &doubler.outB;
dsp::generic_hier_block<Decoder>::registerBlock(&demod);
dsp::generic_hier_block<Decoder>::registerBlock(&fir);
dsp::generic_hier_block<Decoder>::registerBlock(&recov);
dsp::generic_hier_block<Decoder>::registerBlock(&doubler);
//dsp::generic_hier_block<Decoder>::registerBlock(&slicer);
dsp::generic_hier_block<Decoder>::registerBlock(&deframer);
dsp::generic_hier_block<Decoder>::registerBlock(&ns2);
dsp::generic_hier_block<Decoder>::_block_init = true;
}
void setInput(dsp::stream<dsp::complex_t>* input) {
assert(dsp::generic_hier_block<Decoder>::_block_init);
demod.setInput(input);
}
dsp::stream<float>* diagOut = NULL;
private:
dsp::FloatFMDemod demod;
dsp::RRCTaps rrc;
dsp::FIR<float> fir;
dsp::MMClockRecovery<float> recov;
dsp::StreamDoubler<float> doubler;
// Slice4FSK slicer;
Deframer deframer;
dsp::FileSink<uint8_t> ns2;
float _sampleRate;
};
}

View File

@ -0,0 +1,193 @@
#include <imgui.h>
#include <config.h>
#include <core.h>
#include <gui/style.h>
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <module.h>
#include <filesystem>
#include <dsp/pll.h>
#include <dsp/stream.h>
#include <dsp/demodulator.h>
#include <dsp/window.h>
#include <dsp/resampling.h>
#include <dsp/processing.h>
#include <dsp/routing.h>
#include <dsp/sink.h>
#include <gui/widgets/folder_select.h>
#include <gui/widgets/symbol_diagram.h>
#include <fstream>
#include <chrono>
#include "kg_sstv_dsp.h"
#define CONCAT(a, b) ((std::string(a) + b).c_str())
SDRPP_MOD_INFO{
/* Name: */ "kg_sstv_decoder",
/* Description: */ "KG-SSTV Digital SSTV Decoder for SDR++",
/* Author: */ "Ryzerth",
/* Version: */ 0, 1, 0,
/* Max instances */ -1
};
ConfigManager config;
#define INPUT_SAMPLE_RATE 6000
class M17DecoderModule : public ModuleManager::Instance {
public:
M17DecoderModule(std::string name) : diag(0.8, 480) {
this->name = name;
// Load config
config.acquire();
if (!config.conf.contains(name)) {
config.conf[name]["showLines"] = false;
}
showLines = config.conf[name]["showLines"];
if (showLines) {
diag.lines.push_back(-0.75f);
diag.lines.push_back(-0.25f);
diag.lines.push_back(0.25f);
diag.lines.push_back(0.75f);
}
config.release(true);
// Initialize VFO
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 3000, INPUT_SAMPLE_RATE, 3000, 3000, true);
vfo->setSnapInterval(250);
// Initialize DSP here
decoder.init(vfo->output, INPUT_SAMPLE_RATE);
reshape.init(decoder.diagOut, 480, 0);
diagHandler.init(&reshape.out, _diagHandler, this);
// Start DSO Here
decoder.start();
reshape.start();
diagHandler.start();
//stream.start();
gui::menu.registerEntry(name, menuHandler, this, this);
}
~M17DecoderModule() {
gui::menu.removeEntry(name);
// Stop DSP Here
if (enabled) {
decoder.stop();
reshape.stop();
diagHandler.stop();
sigpath::vfoManager.deleteVFO(vfo);
}
sigpath::sinkManager.unregisterStream(name);
}
void postInit() {}
void enable() {
double bw = gui::waterfall.getBandwidth();
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 9600, INPUT_SAMPLE_RATE, 9600, 9600, true);
vfo->setSnapInterval(250);
// Set Input of demod here
decoder.setInput(vfo->output);
// Start DSP here
decoder.start();
reshape.start();
diagHandler.start();
enabled = true;
}
void disable() {
// Stop DSP here
decoder.stop();
reshape.stop();
diagHandler.stop();
sigpath::vfoManager.deleteVFO(vfo);
enabled = false;
}
bool isEnabled() {
return enabled;
}
private:
static void menuHandler(void* ctx) {
M17DecoderModule* _this = (M17DecoderModule*)ctx;
float menuWidth = ImGui::GetContentRegionAvail().x;
if (!_this->enabled) { style::beginDisabled(); }
ImGui::SetNextItemWidth(menuWidth);
_this->diag.draw();
if (ImGui::Checkbox(CONCAT("Show Reference Lines##m17_showlines_", _this->name), &_this->showLines)) {
if (_this->showLines) {
_this->diag.lines.push_back(-0.75f);
_this->diag.lines.push_back(-0.25f);
_this->diag.lines.push_back(0.25f);
_this->diag.lines.push_back(0.75f);
}
else {
_this->diag.lines.clear();
}
config.acquire();
config.conf[_this->name]["showLines"] = _this->showLines;
config.release(true);
}
if (!_this->enabled) { style::endDisabled(); }
}
static void _diagHandler(float* data, int count, void* ctx) {
M17DecoderModule* _this = (M17DecoderModule*)ctx;
float* buf = _this->diag.acquireBuffer();
memcpy(buf, data, count * sizeof(float));
_this->diag.releaseBuffer();
}
std::string name;
bool enabled = true;
// DSP Chain
VFOManager::VFO* vfo;
kgsstv::Decoder decoder;
dsp::Reshaper<float> reshape;
dsp::HandlerSink<float> diagHandler;
dsp::stream<float> dummy;
ImGui::SymbolDiagram diag;
bool showLines = false;
};
MOD_EXPORT void _INIT_() {
// Create default recording directory
json def = json({});
config.setPath(core::args["root"].s() + "/kg_sstv_decoder_config.json");
config.load(def);
config.enableAutoSave();
}
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
return new M17DecoderModule(name);
}
MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
delete (M17DecoderModule*)instance;
}
MOD_EXPORT void _END_() {
config.disableAutoSave();
config.save();
}

View File

@ -5,7 +5,6 @@
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <module.h>
#include <options.h>
#include <filesystem>
#include <dsp/pll.h>
#include <dsp/stream.h>
@ -296,7 +295,7 @@ private:
MOD_EXPORT void _INIT_() {
// Create default recording directory
json def = json({});
config.setPath(options::opts.root + "/m17_decoder_config.json");
config.setPath(core::args["root"].s() + "/m17_decoder_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -5,7 +5,6 @@
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <module.h>
#include <options.h>
#include <filesystem>
#include <dsp/pll.h>
#include <dsp/stream.h>
@ -244,14 +243,15 @@ private:
MOD_EXPORT void _INIT_() {
// Create default recording directory
if (!std::filesystem::exists(options::opts.root + "/recordings")) {
std::string root = core::args["root"];
if (!std::filesystem::exists(root + "/recordings")) {
spdlog::warn("Recordings directory does not exist, creating it");
if (!std::filesystem::create_directory(options::opts.root + "/recordings")) {
if (!std::filesystem::create_directory(root + "/recordings")) {
spdlog::error("Could not create recordings directory");
}
}
json def = json({});
config.setPath(options::opts.root + "/meteor_demodulator_config.json");
config.setPath(root + "/meteor_demodulator_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -1,5 +1,4 @@
#include "radio_module.h"
#include <options.h>
SDRPP_MOD_INFO{
/* Name: */ "radio",
@ -11,7 +10,7 @@ SDRPP_MOD_INFO{
MOD_EXPORT void _INIT_() {
json def = json({});
config.setPath(options::opts.root + "/radio_config.json");
config.setPath(core::args["root"].s() + "/radio_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -5,7 +5,6 @@
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <module.h>
#include <options.h>
#include <dsp/pll.h>
#include <dsp/stream.h>

View File

@ -5,7 +5,6 @@
#include <gui/style.h>
#include <core.h>
#include <thread>
#include <options.h>
#include <radio_interface.h>
#include <signal_path/signal_path.h>
#include <vector>
@ -831,7 +830,7 @@ MOD_EXPORT void _INIT_() {
def["lists"]["General"]["showOnWaterfall"] = true;
def["lists"]["General"]["bookmarks"] = json::object();
config.setPath(options::opts.root + "/frequency_manager_config.json");
config.setPath(core::args["root"].s() + "/frequency_manager_config.json");
config.load(def);
config.enableAutoSave();

View File

@ -13,7 +13,6 @@
#include <gui/style.h>
#include <gui/widgets/volume_meter.h>
#include <regex>
#include <options.h>
#include <gui/widgets/folder_select.h>
#include <recorder_interface.h>
#include <core.h>
@ -29,11 +28,6 @@ SDRPP_MOD_INFO{
ConfigManager config;
std::string expandString(std::string input) {
input = std::regex_replace(input, std::regex("%ROOT%"), options::opts.root);
return std::regex_replace(input, std::regex("//"), "/");
}
std::string genFileName(std::string prefix, bool isVfo, std::string name = "") {
time_t now = time(0);
tm* ltm = localtime(&now);
@ -52,6 +46,8 @@ public:
RecorderModule(std::string name) : folderSelect("%ROOT%/recordings") {
this->name = name;
root = core::args["root"];
// Load config
config.acquire();
bool created = false;
@ -462,6 +458,11 @@ private:
}
}
std::string expandString(std::string input) {
input = std::regex_replace(input, std::regex("%ROOT%"), root);
return std::regex_replace(input, std::regex("//"), "/");
}
std::string name;
bool enabled = true;
@ -496,6 +497,7 @@ private:
std::string streamNamesTxt;
int streamId = 0;
std::string selectedStreamName = "";
std::string root;
// Baseband path
dsp::stream<dsp::complex_t> basebandStream;
@ -516,14 +518,15 @@ struct RecorderContext_t {
MOD_EXPORT void _INIT_() {
// Create default recording directory
if (!std::filesystem::exists(options::opts.root + "/recordings")) {
std::string root = core::args["root"];
if (!std::filesystem::exists(root + "/recordings")) {
spdlog::warn("Recordings directory does not exist, creating it");
if (!std::filesystem::create_directory(options::opts.root + "/recordings")) {
if (!std::filesystem::create_directory(root + "/recordings")) {
spdlog::error("Could not create recordings directory");
}
}
json def = json({});
config.setPath(options::opts.root + "/recorder_config.json");
config.setPath(root + "/recorder_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -8,7 +8,6 @@
#include <recorder_interface.h>
#include <meteor_demodulator_interface.h>
#include <config.h>
#include <options.h>
#include <cctype>
#include <radio_interface.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -734,7 +733,7 @@ private:
};
MOD_EXPORT void _INIT_() {
config.setPath(options::opts.root + "/rigctl_server_config.json");
config.setPath(core::args["root"].s() + "/rigctl_server_config.json");
config.load(json::object());
config.enableAutoSave();
}

View File

@ -7,7 +7,6 @@
#include <dsp/processing.h>
#include <spdlog/spdlog.h>
#include <config.h>
#include <options.h>
#include <utils/optionlist.h>
#include <aaudio/AAudio.h>
@ -175,7 +174,7 @@ private:
MOD_EXPORT void _INIT_() {
json def = json({});
config.setPath(options::opts.root + "/audio_sink_config.json");
config.setPath(core::args["root"].s() + "/audio_sink_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -8,7 +8,6 @@
#include <spdlog/spdlog.h>
#include <RtAudio.h>
#include <config.h>
#include <options.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -276,7 +275,7 @@ private:
MOD_EXPORT void _INIT_() {
json def = json({});
config.setPath(options::opts.root + "/audio_sink_config.json");
config.setPath(core::args["root"].s() + "/audio_sink_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -8,7 +8,6 @@
#include <dsp/processing.h>
#include <spdlog/spdlog.h>
#include <config.h>
#include <options.h>
#include <gui/style.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -339,7 +338,7 @@ private:
MOD_EXPORT void _INIT_() {
json def = json({});
config.setPath(options::opts.root + "/network_sink_config.json");
config.setPath(core::args["root"].s() + "/network_sink_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -9,7 +9,6 @@
#include <spdlog/spdlog.h>
#include <config.h>
#include <algorithm>
#include <options.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -424,7 +423,7 @@ private:
};
MOD_EXPORT void _INIT_() {
config.setPath(options::opts.root + "/new_audio_sink_config.json");
config.setPath(core::args["root"].s() + "/new_audio_sink_config.json");
config.load(json::object());
config.enableAutoSave();
}

View File

@ -6,7 +6,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/smgui.h>
#include <airspy.h>
@ -610,7 +609,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/airspy_config.json");
config.setPath(core::args["root"].s() + "/airspy_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -5,7 +5,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/smgui.h>
#include <airspyhf.h>
#include <gui/widgets/stepped_slider.h>
@ -407,7 +406,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/airspyhf_config.json");
config.setPath(core::args["root"].s() + "/airspyhf_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -6,7 +6,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/widgets/stepped_slider.h>
#include <libbladeRF.h>
#include <dsp/processing.h>
@ -610,7 +609,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/bladerf_config.json");
config.setPath(core::args["root"].s() + "/bladerf_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -5,7 +5,6 @@
#include <signal_path/signal_path.h>
#include <wavreader.h>
#include <core.h>
#include <options.h>
#include <gui/widgets/file_select.h>
#include <filesystem>
#include <regex>
@ -28,7 +27,7 @@ public:
FileSourceModule(std::string name) : fileSelect("", { "Wav IQ Files (*.wav)", "*.wav", "All Files", "*" }) {
this->name = name;
if (options::opts.serverMode) { return; }
if (core::args["server"].b()) { return; }
config.acquire();
fileSelect.setPath(config.conf["path"], true);
@ -200,7 +199,7 @@ private:
MOD_EXPORT void _INIT_() {
json def = json({});
def["path"] = "";
config.setPath(options::opts.root + "/file_source_config.json");
config.setPath(core::args["root"].s() + "/file_source_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -6,7 +6,6 @@
#include <gui/style.h>
#include <config.h>
#include <gui/widgets/stepped_slider.h>
#include <options.h>
#include <gui/smgui.h>
#ifndef __ANDROID__
@ -416,7 +415,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/hackrf_config.json");
config.setPath(core::args["root"].s() + "/hackrf_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -5,7 +5,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/smgui.h>
#include <lime/LimeSuite.h>
@ -522,7 +521,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/limesdr_config.json");
config.setPath(core::args["root"].s() + "/limesdr_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -7,7 +7,6 @@
#include <gui/smgui.h>
#include <iio.h>
#include <ad9361.h>
#include <options.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -298,7 +297,7 @@ MOD_EXPORT void _INIT_() {
defConf["sampleRate"] = 4000000.0f;
defConf["gainMode"] = 0;
defConf["gain"] = 0.0f;
config.setPath(options::opts.root + "/plutosdr_source_config.json");
config.setPath(core::args["root"].s() + "/plutosdr_source_config.json");
config.load(defConf);
config.enableAutoSave();
}

View File

@ -7,7 +7,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/widgets/stepped_slider.h>
#include <utils/optionlist.h>
#include <gui/smgui.h>
@ -326,7 +325,7 @@ MOD_EXPORT void _INIT_() {
def["hostname"] = "192.168.0.111";
def["port"] = 50000;
def["devices"] = json::object();
config.setPath(options::opts.root + "/rfspace_source_config.json");
config.setPath(core::args["root"].s() + "/rfspace_source_config.json");
config.load(def);
config.enableAutoSave();

View File

@ -5,7 +5,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/smgui.h>
#include <rtl-sdr.h>
@ -60,6 +59,8 @@ public:
RTLSDRSourceModule(std::string name) {
this->name = name;
serverMode = core::args["server"];
sampleRate = sampleRates[0];
handler.ctx = this;
@ -425,7 +426,7 @@ private:
SmGui::ForceSync();
// TODO: FIND ANOTHER WAY
if (options::opts.serverMode) {
if (serverMode) {
if (SmGui::SliderInt(CONCAT("##_rtlsdr_gain_", _this->name), &_this->gainId, 0, _this->gainList.size() - 1, SmGui::FMT_STR_NONE)) {
_this->updateGainTxt();
if (_this->running) {
@ -539,6 +540,7 @@ private:
int srId = 0;
int devCount = 0;
std::thread workerThread;
bool serverMode = false;
#ifdef __ANDROID__
int devFd = -1;
@ -571,7 +573,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = 0;
config.setPath(options::opts.root + "/rtl_sdr_config.json");
config.setPath(core::args["root"].s() + "/rtl_sdr_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -5,7 +5,6 @@
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <core.h>
#include <options.h>
#include <gui/smgui.h>
#include <gui/style.h>
@ -337,7 +336,7 @@ private:
};
MOD_EXPORT void _INIT_() {
config.setPath(options::opts.root + "/rtl_tcp_config.json");
config.setPath(core::args["root"].s() + "/rtl_tcp_config.json");
json defConf;
defConf["host"] = "localhost";
defConf["port"] = 1234;

View File

@ -6,7 +6,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/widgets/stepped_slider.h>
#include <libsddc.h>
@ -29,7 +28,7 @@ public:
AirspyHFSourceModule(std::string name) {
this->name = name;
if (options::opts.serverMode) { return; }
if (core::args["server"].b()) { return; }
sampleRate = 768000.0;
@ -229,7 +228,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/sddc_config.json");
config.setPath(core::args["root"].s() + "/sddc_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -6,7 +6,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <sdrplay_api.h>
#include <gui/smgui.h>
@ -1207,7 +1206,7 @@ MOD_EXPORT void _INIT_() {
json def = json({});
def["devices"] = json({});
def["device"] = "";
config.setPath(options::opts.root + "/sdrplay_config.json");
config.setPath(core::args["root"].s() + "/sdrplay_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -7,7 +7,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/widgets/stepped_slider.h>
#include <utils/optionlist.h>
#include <gui/dialogs/dialog_box.h>
@ -30,7 +29,7 @@ public:
this->name = name;
// Yeah no server-ception, sorry...
if (options::opts.serverMode) { return; }
if (core::args["server"].b()) { return; }
// Initialize lists
sampleTypeList.define("Int8", dsp::PCM_TYPE_I8);
@ -282,7 +281,7 @@ MOD_EXPORT void _INIT_() {
def["hostname"] = "localhost";
def["port"] = 5259;
def["servers"] = json::object();
config.setPath(options::opts.root + "/sdrpp_server_source_config.json");
config.setPath(core::args["root"].s() + "/sdrpp_server_source_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -10,7 +10,6 @@
#include <SoapySDR/Logger.hpp>
#include <core.h>
#include <gui/style.h>
#include <options.h>
#include <gui/smgui.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
@ -525,7 +524,7 @@ private:
};
MOD_EXPORT void _INIT_() {
config.setPath(options::opts.root + "/soapy_source_config.json");
config.setPath(core::args["root"].s() + "/soapy_source_config.json");
json defConf;
defConf["device"] = "";
defConf["devices"] = json({});

View File

@ -7,7 +7,6 @@
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <options.h>
#include <gui/widgets/stepped_slider.h>
#include <gui/smgui.h>
@ -308,7 +307,7 @@ MOD_EXPORT void _INIT_() {
def["hostname"] = "localhost";
def["port"] = 5555;
def["devices"] = json::object();
config.setPath(options::opts.root + "/spyserver_config.json");
config.setPath(core::args["root"].s() + "/spyserver_config.json");
config.load(def);
config.enableAutoSave();