SDRPlusPlus/core/src/core.cpp

384 wiersze
14 KiB
C++
Czysty Zwykły widok Historia

2022-01-21 19:22:13 +00:00
#include <server.h>
2020-09-19 10:48:34 +00:00
#include "imgui.h"
#include <stdio.h>
2020-09-19 22:19:39 +00:00
#include <gui/main_window.h>
#include <gui/style.h>
2020-11-30 20:17:36 +00:00
#include <gui/gui.h>
2020-09-19 22:19:39 +00:00
#include <gui/icons.h>
2020-09-19 10:48:34 +00:00
#include <version.h>
#include <spdlog/spdlog.h>
#include <gui/widgets/bandplan.h>
2020-09-19 10:48:34 +00:00
#include <stb_image.h>
#include <config.h>
2020-09-24 17:36:57 +00:00
#include <core.h>
2020-12-22 23:11:12 +00:00
#include <filesystem>
2021-06-23 19:45:38 +00:00
#include <gui/menus/theme.h>
2022-01-29 19:35:08 +00:00
#include <backend.h>
2020-09-19 10:48:34 +00:00
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include <stb_image_resize.h>
#include <gui/gui.h>
#include <signal_path/signal_path.h>
2020-09-19 10:48:34 +00:00
#ifdef _WIN32
#include <Windows.h>
#endif
2021-02-11 21:49:33 +00:00
#ifndef INSTALL_PREFIX
#ifdef __APPLE__
#define INSTALL_PREFIX "/usr/local"
#else
#define INSTALL_PREFIX "/usr"
#endif
2021-02-11 21:49:33 +00:00
#endif
2020-09-24 17:36:57 +00:00
namespace core {
ConfigManager configManager;
2020-12-08 03:36:37 +00:00
ModuleManager moduleManager;
ModuleComManager modComManager;
2022-02-21 17:10:01 +00:00
CommandArgsParser args;
2020-10-01 23:44:18 +00:00
void setInputSampleRate(double samplerate) {
2022-01-21 19:22:13 +00:00
// Forward this to the server
if (args["server"].b()) { server::setInputSampleRate(samplerate); return; }
2022-01-21 19:22:13 +00:00
2022-06-15 14:08:28 +00:00
// Update IQ frontend input samplerate and get effective samplerate
sigpath::iqFrontEnd.setSampleRate(samplerate);
double effectiveSr = sigpath::iqFrontEnd.getEffectiveSamplerate();
// Reset zoom
2021-07-26 19:18:06 +00:00
gui::waterfall.setBandwidth(effectiveSr);
2020-12-14 17:14:04 +00:00
gui::waterfall.setViewOffset(0);
2021-07-26 19:18:06 +00:00
gui::waterfall.setViewBandwidth(effectiveSr);
2021-08-30 17:22:00 +00:00
gui::mainWindow.setViewBandwidthSlider(1.0);
2022-06-15 14:08:28 +00:00
// Debug logs
spdlog::info("New DSP samplerate: {0} (source samplerate is {1})", effectiveSr, samplerate);
2020-10-01 23:44:18 +00:00
}
2020-09-24 17:36:57 +00:00
};
2020-09-19 10:48:34 +00:00
// main
int sdrpp_main(int argc, char* argv[]) {
2020-09-19 10:48:34 +00:00
spdlog::info("SDR++ v" VERSION_STR);
2021-11-17 21:37:21 +00:00
#ifdef IS_MACOS_BUNDLE
2021-11-16 02:33:09 +00:00
// If this is a MacOS .app, CD to the correct directory
auto execPath = std::filesystem::absolute(argv[0]);
chdir(execPath.parent_path().string().c_str());
#endif
2022-02-21 17:10:01 +00:00
// Define command line options and parse arguments
core::args.defineAll();
2022-02-24 21:44:37 +00:00
if (core::args.parse(argc, argv) < 0) { return -1; }
2022-02-21 17:10:01 +00:00
// Show help and exit if requested
2022-02-24 21:44:37 +00:00
if (core::args["help"].b()) {
2022-02-21 17:10:01 +00:00
core::args.showHelp();
return 0;
}
2022-02-24 20:01:51 +00:00
bool serverMode = (bool)core::args["server"];
2020-12-22 13:50:26 +00:00
2021-02-06 20:28:27 +00:00
#ifdef _WIN32
if (!core::args["con"].b() && !serverMode) { FreeConsole(); }
2021-02-06 20:28:27 +00:00
#endif
2020-12-22 23:11:12 +00:00
// Check root directory
2022-02-24 20:01:51 +00:00
std::string root = (std::string)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);
2020-12-22 23:11:12 +00:00
return -1;
}
}
// Check that the path actually is a directory
if (!std::filesystem::is_directory(root)) {
spdlog::error("{0} is not a directory", root);
2020-12-22 23:11:12 +00:00
return -1;
}
2020-12-10 04:18:40 +00:00
// ======== DEFAULT CONFIG ========
json defConfig;
defConfig["bandColors"]["amateur"] = "#FF0000FF";
defConfig["bandColors"]["aviation"] = "#00FF00FF";
defConfig["bandColors"]["broadcast"] = "#0000FFFF";
defConfig["bandColors"]["marine"] = "#00FFFFFF";
defConfig["bandColors"]["military"] = "#FFFF00FF";
defConfig["bandPlan"] = "General";
defConfig["bandPlanEnabled"] = true;
2021-04-13 23:45:21 +00:00
defConfig["bandPlanPos"] = 0;
defConfig["centerTuning"] = false;
defConfig["colorMap"] = "Classic";
2022-03-31 18:16:21 +00:00
defConfig["fftHold"] = false;
defConfig["fftHoldSpeed"] = 60;
2021-04-13 02:57:42 +00:00
defConfig["fastFFT"] = false;
2020-12-10 04:18:40 +00:00
defConfig["fftHeight"] = 300;
2021-07-26 23:57:12 +00:00
defConfig["fftRate"] = 20;
2021-04-13 16:31:38 +00:00
defConfig["fftSize"] = 65536;
2022-06-23 19:30:38 +00:00
defConfig["fftWindow"] = 2;
2020-12-10 04:18:40 +00:00
defConfig["frequency"] = 100000000.0;
2021-04-13 02:57:42 +00:00
defConfig["fullWaterfallUpdate"] = false;
2020-12-10 04:18:40 +00:00
defConfig["max"] = 0.0;
defConfig["maximized"] = false;
2021-11-05 17:57:50 +00:00
defConfig["fullscreen"] = false;
2021-04-22 21:49:35 +00:00
// Menu
defConfig["menuElements"] = json::array();
defConfig["menuElements"][0]["name"] = "Source";
defConfig["menuElements"][0]["open"] = true;
defConfig["menuElements"][1]["name"] = "Radio";
defConfig["menuElements"][1]["open"] = true;
defConfig["menuElements"][2]["name"] = "Recorder";
defConfig["menuElements"][2]["open"] = true;
defConfig["menuElements"][3]["name"] = "Sinks";
defConfig["menuElements"][3]["open"] = true;
2021-07-03 17:46:21 +00:00
defConfig["menuElements"][3]["name"] = "Frequency Manager";
defConfig["menuElements"][3]["open"] = true;
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][4]["name"] = "VFO Color";
defConfig["menuElements"][4]["open"] = true;
2021-04-22 21:49:35 +00:00
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][5]["name"] = "Scripting";
defConfig["menuElements"][5]["open"] = false;
2021-04-22 21:49:35 +00:00
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][6]["name"] = "Band Plan";
2021-04-22 21:49:35 +00:00
defConfig["menuElements"][6]["open"] = true;
2021-05-04 19:05:45 +00:00
defConfig["menuElements"][7]["name"] = "Display";
defConfig["menuElements"][7]["open"] = true;
2020-12-10 04:18:40 +00:00
defConfig["menuWidth"] = 300;
2021-02-28 16:32:22 +00:00
defConfig["min"] = -120.0;
2020-12-22 23:11:12 +00:00
2021-04-23 01:58:10 +00:00
// Module instances
defConfig["moduleInstances"]["Airspy Source"]["module"] = "airspy_source";
defConfig["moduleInstances"]["Airspy Source"]["enabled"] = true;
defConfig["moduleInstances"]["AirspyHF+ Source"]["module"] = "airspyhf_source";
defConfig["moduleInstances"]["AirspyHF+ Source"]["enabled"] = true;
defConfig["moduleInstances"]["BladeRF Source"]["module"] = "bladerf_source";
defConfig["moduleInstances"]["BladeRF Source"]["enabled"] = true;
defConfig["moduleInstances"]["File Source"]["module"] = "file_source";
defConfig["moduleInstances"]["File Source"]["enabled"] = true;
defConfig["moduleInstances"]["HackRF Source"]["module"] = "hackrf_source";
defConfig["moduleInstances"]["HackRF Source"]["enabled"] = true;
defConfig["moduleInstances"]["LimeSDR Source"]["module"] = "limesdr_source";
defConfig["moduleInstances"]["LimeSDR Source"]["enabled"] = true;
2022-01-02 17:34:06 +00:00
defConfig["moduleInstances"]["RFspace Source"]["module"] = "rfspace_source";
2022-01-02 18:02:12 +00:00
defConfig["moduleInstances"]["RFspace Source"]["enabled"] = true;
defConfig["moduleInstances"]["RTL-SDR Source"]["module"] = "rtl_sdr_source";
defConfig["moduleInstances"]["RTL-SDR Source"]["enabled"] = true;
defConfig["moduleInstances"]["RTL-TCP Source"]["module"] = "rtl_tcp_source";
defConfig["moduleInstances"]["RTL-TCP Source"]["enabled"] = true;
defConfig["moduleInstances"]["SDRplay Source"]["module"] = "sdrplay_source";
defConfig["moduleInstances"]["SDRplay Source"]["enabled"] = true;
2022-01-21 19:41:39 +00:00
defConfig["moduleInstances"]["SDR++ Server Source"]["module"] = "sdrpp_server_source";
defConfig["moduleInstances"]["SDR++ Server Source"]["enabled"] = true;
defConfig["moduleInstances"]["SoapySDR Source"]["module"] = "soapy_source";
defConfig["moduleInstances"]["SoapySDR Source"]["enabled"] = true;
2021-07-19 02:52:13 +00:00
defConfig["moduleInstances"]["SpyServer Source"]["module"] = "spyserver_source";
defConfig["moduleInstances"]["SpyServer Source"]["enabled"] = true;
defConfig["moduleInstances"]["PlutoSDR Source"]["module"] = "plutosdr_source";
defConfig["moduleInstances"]["PlutoSDR Source"]["enabled"] = true;
2021-06-28 00:22:51 +00:00
2020-12-24 13:43:14 +00:00
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
defConfig["moduleInstances"]["Network Sink"] = "network_sink";
2020-12-22 23:11:12 +00:00
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["Radio"] = "radio";
2021-07-03 17:46:21 +00:00
defConfig["moduleInstances"]["Frequency Manager"] = "frequency_manager";
2021-06-28 00:22:51 +00:00
defConfig["moduleInstances"]["Recorder"] = "recorder";
2021-07-18 02:30:55 +00:00
defConfig["moduleInstances"]["Rigctl Server"] = "rigctl_server";
2022-09-28 15:15:38 +00:00
// defConfig["moduleInstances"]["Rigctl Client"] = "rigctl_client";
// TODO: Enable rigctl_client when ready
// defConfig["moduleInstances"]["Scanner"] = "scanner";
// TODO: Enable scanner when ready
2021-06-28 00:22:51 +00:00
2021-06-23 19:45:38 +00:00
// Themes
defConfig["theme"] = "Dark";
2022-03-24 19:23:07 +00:00
#ifdef __ANDROID__
defConfig["uiScale"] = 3.0f;
#else
defConfig["uiScale"] = 1.0f;
2022-03-24 19:23:07 +00:00
#endif
2021-06-23 19:45:38 +00:00
2020-12-10 04:18:40 +00:00
defConfig["modules"] = json::array();
defConfig["offsetMode"] = (int)0; // Off
2020-12-10 04:18:40 +00:00
defConfig["offset"] = 0.0;
2021-04-23 01:58:10 +00:00
defConfig["showMenu"] = true;
2020-12-10 04:18:40 +00:00
defConfig["showWaterfall"] = true;
defConfig["source"] = "";
2021-07-26 19:18:06 +00:00
defConfig["decimationPower"] = 0;
2021-07-27 21:50:48 +00:00
defConfig["iqCorrection"] = false;
2022-09-27 13:43:33 +00:00
defConfig["invertIQ"] = false;
2021-05-05 02:31:37 +00:00
defConfig["streams"]["Radio"]["muted"] = false;
defConfig["streams"]["Radio"]["sink"] = "Audio";
defConfig["streams"]["Radio"]["volume"] = 1.0f;
2020-12-10 04:18:40 +00:00
defConfig["windowSize"]["h"] = 720;
defConfig["windowSize"]["w"] = 1280;
defConfig["vfoOffsets"] = json::object();
2021-05-04 18:41:23 +00:00
defConfig["vfoColors"]["Radio"] = "#FFFFFF";
2022-03-30 23:03:31 +00:00
#ifdef __ANDROID__
defConfig["lockMenuOrder"] = true;
#else
defConfig["lockMenuOrder"] = false;
#endif
2021-11-16 02:33:09 +00:00
#if defined(_WIN32)
2020-12-22 21:39:24 +00:00
defConfig["modulesDirectory"] = "./modules";
defConfig["resourcesDirectory"] = "./res";
2021-11-17 21:37:21 +00:00
#elif defined(IS_MACOS_BUNDLE)
2021-11-16 02:33:09 +00:00
defConfig["modulesDirectory"] = "../Plugins";
defConfig["resourcesDirectory"] = "../Resources";
#elif defined(__ANDROID__)
defConfig["modulesDirectory"] = root + "/modules";
defConfig["resourcesDirectory"] = root + "/res";
2020-12-22 21:39:24 +00:00
#else
2021-02-11 22:10:01 +00:00
defConfig["modulesDirectory"] = INSTALL_PREFIX "/lib/sdrpp/plugins";
defConfig["resourcesDirectory"] = INSTALL_PREFIX "/share/sdrpp";
2020-12-22 21:39:24 +00:00
#endif
2020-09-19 10:48:34 +00:00
// Load config
2020-12-22 17:42:30 +00:00
spdlog::info("Loading config");
core::configManager.setPath(root + "/config.json");
2020-12-10 04:18:40 +00:00
core::configManager.load(defConfig);
2020-09-24 17:36:57 +00:00
core::configManager.enableAutoSave();
core::configManager.acquire();
2020-09-19 10:48:34 +00:00
// Android can't load just any .so file. This means we have to hardcode the name of the modules
#ifdef __ANDROID__
int modCount = 0;
core::configManager.conf["modules"] = json::array();
core::configManager.conf["modules"][modCount++] = "airspy_source.so";
core::configManager.conf["modules"][modCount++] = "airspyhf_source.so";
core::configManager.conf["modules"][modCount++] = "hackrf_source.so";
core::configManager.conf["modules"][modCount++] = "plutosdr_source.so";
core::configManager.conf["modules"][modCount++] = "sdrpp_server_source.so";
core::configManager.conf["modules"][modCount++] = "rfspace_source.so";
core::configManager.conf["modules"][modCount++] = "rtl_sdr_source.so";
core::configManager.conf["modules"][modCount++] = "rtl_tcp_source.so";
core::configManager.conf["modules"][modCount++] = "spyserver_source.so";
core::configManager.conf["modules"][modCount++] = "network_sink.so";
core::configManager.conf["modules"][modCount++] = "audio_sink.so";
2022-03-30 18:15:27 +00:00
core::configManager.conf["modules"][modCount++] = "m17_decoder.so";
core::configManager.conf["modules"][modCount++] = "meteor_demodulator.so";
core::configManager.conf["modules"][modCount++] = "radio.so";
core::configManager.conf["modules"][modCount++] = "frequency_manager.so";
core::configManager.conf["modules"][modCount++] = "recorder.so";
core::configManager.conf["modules"][modCount++] = "rigctl_server.so";
core::configManager.conf["modules"][modCount++] = "scanner.so";
#endif
2021-04-22 21:49:35 +00:00
// Fix missing elements in config
for (auto const& item : defConfig.items()) {
if (!core::configManager.conf.contains(item.key())) {
2021-05-04 18:41:23 +00:00
spdlog::info("Missing key in config {0}, repairing", item.key());
core::configManager.conf[item.key()] = defConfig[item.key()];
}
}
2021-04-22 21:49:35 +00:00
// Remove unused elements
auto items = core::configManager.conf.items();
for (auto const& item : items) {
if (!defConfig.contains(item.key())) {
2021-05-04 18:41:23 +00:00
spdlog::info("Unused key in config {0}, repairing", item.key());
2021-04-22 21:49:35 +00:00
core::configManager.conf.erase(item.key());
}
}
2021-04-23 01:58:10 +00:00
// Update to new module representation in config if needed
for (auto [_name, inst] : core::configManager.conf["moduleInstances"].items()) {
if (!inst.is_string()) { continue; }
std::string mod = inst;
json newMod;
newMod["module"] = mod;
newMod["enabled"] = true;
core::configManager.conf["moduleInstances"][_name] = newMod;
}
// Load UI scaling
style::uiScale = core::configManager.conf["uiScale"];
2021-11-05 17:57:50 +00:00
core::configManager.release(true);
if (serverMode) { return server::main(); }
2021-07-23 04:29:16 +00:00
core::configManager.acquire();
std::string resDir = core::configManager.conf["resourcesDirectory"];
json bandColors = core::configManager.conf["bandColors"];
core::configManager.release();
// Assert that the resource directory is absolute and check existence
resDir = std::filesystem::absolute(resDir).string();
if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Resource directory doesn't exist! Please make sure that you've configured it correctly in config.json (check readme for details)");
return 1;
}
2022-01-29 19:35:08 +00:00
// Initialize backend
int biRes = backend::init(resDir);
if (biRes < 0) { return biRes; }
2020-09-19 10:48:34 +00:00
// Initialize SmGui in normal mode
SmGui::init(false);
2020-09-19 10:48:34 +00:00
2021-06-23 19:45:38 +00:00
if (!style::loadFonts(resDir)) { return -1; }
thememenu::init(resDir);
LoadingScreen::init();
2020-09-19 10:48:34 +00:00
2020-11-30 20:17:36 +00:00
LoadingScreen::show("Loading icons");
2020-09-19 10:48:34 +00:00
spdlog::info("Loading icons");
2020-12-22 21:39:24 +00:00
if (!icons::load(resDir)) { return -1; }
2020-09-19 10:48:34 +00:00
2020-11-30 20:17:36 +00:00
LoadingScreen::show("Loading band plans");
2020-09-19 10:48:34 +00:00
spdlog::info("Loading band plans");
2020-12-22 23:11:12 +00:00
bandplan::loadFromDir(resDir + "/bandplans");
2020-09-19 10:48:34 +00:00
2020-11-30 20:17:36 +00:00
LoadingScreen::show("Loading band plan colors");
2020-09-19 10:48:34 +00:00
spdlog::info("Loading band plans color table");
2020-12-22 23:11:12 +00:00
bandplan::loadColorTable(bandColors);
2020-09-19 10:48:34 +00:00
2021-06-20 19:17:11 +00:00
gui::mainWindow.init();
2020-09-19 10:48:34 +00:00
spdlog::info("Ready.");
2022-01-29 19:35:08 +00:00
// Run render loop (TODO: CHECK RETURN VALUE)
backend::renderLoop();
2020-09-19 10:48:34 +00:00
// On android, none of this shutdown should happen due to the way the UI works
#ifndef __ANDROID__
// Shut down all modules
for (auto& [name, mod] : core::moduleManager.modules) {
mod.end();
}
2022-01-29 19:35:08 +00:00
// Terminate backend (TODO: CHECK RETURN VALUE)
backend::end();
2020-09-19 10:48:34 +00:00
2022-06-15 14:08:28 +00:00
sigpath::iqFrontEnd.stop();
core::configManager.disableAutoSave();
core::configManager.save();
#endif
2022-02-14 18:36:49 +00:00
spdlog::info("Exiting successfully");
2020-09-19 10:48:34 +00:00
return 0;
2020-10-22 15:55:49 +00:00
}