2020-09-19 12:48:34 +02:00
|
|
|
#include "imgui.h"
|
|
|
|
#include "imgui_impl_glfw.h"
|
|
|
|
#include "imgui_impl_opengl3.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <GL/glew.h>
|
|
|
|
#include <GLFW/glfw3.h>
|
2020-09-20 00:19:39 +02:00
|
|
|
#include <gui/main_window.h>
|
|
|
|
#include <gui/style.h>
|
2020-11-30 21:17:36 +01:00
|
|
|
#include <gui/gui.h>
|
2020-09-20 00:19:39 +02:00
|
|
|
#include <gui/icons.h>
|
2020-09-19 12:48:34 +02:00
|
|
|
#include <version.h>
|
|
|
|
#include <spdlog/spdlog.h>
|
2020-12-05 22:42:12 +01:00
|
|
|
#include <gui/widgets/bandplan.h>
|
2020-09-19 12:48:34 +02:00
|
|
|
#include <stb_image.h>
|
|
|
|
#include <config.h>
|
2020-09-24 19:36:57 +02:00
|
|
|
#include <core.h>
|
2020-12-22 14:50:26 +01:00
|
|
|
#include <options.h>
|
2020-10-07 14:44:39 +02:00
|
|
|
#include <duktape/duktape.h>
|
|
|
|
#include <duktape/duk_console.h>
|
2020-12-23 00:11:12 +01:00
|
|
|
#include <filesystem>
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
|
|
|
#include <stb_image_resize.h>
|
2020-10-07 22:44:54 +02:00
|
|
|
#include <gui/gui.h>
|
|
|
|
#include <signal_path/signal_path.h>
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <Windows.h>
|
|
|
|
#endif
|
|
|
|
|
2020-09-24 19:36:57 +02:00
|
|
|
namespace core {
|
|
|
|
ConfigManager configManager;
|
2020-10-07 14:44:39 +02:00
|
|
|
ScriptManager scriptManager;
|
2020-12-08 04:36:37 +01:00
|
|
|
ModuleManager moduleManager;
|
2020-10-02 01:44:18 +02:00
|
|
|
|
|
|
|
void setInputSampleRate(double samplerate) {
|
|
|
|
// NOTE: Zoom controls won't work
|
|
|
|
gui::waterfall.setBandwidth(samplerate);
|
2020-12-14 18:14:04 +01:00
|
|
|
gui::waterfall.setViewOffset(0);
|
|
|
|
gui::waterfall.setViewBandwidth(samplerate);
|
2020-10-02 01:44:18 +02:00
|
|
|
sigpath::signalPath.setSampleRate(samplerate);
|
2020-12-14 18:14:04 +01:00
|
|
|
setViewBandwidthSlider(samplerate);
|
2020-10-02 01:44:18 +02:00
|
|
|
}
|
2020-09-24 19:36:57 +02:00
|
|
|
};
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
bool maximized = false;
|
|
|
|
bool fullScreen = false;
|
|
|
|
|
|
|
|
static void glfw_error_callback(int error, const char* description) {
|
|
|
|
spdlog::error("Glfw Error {0}: {1}", error, description);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void maximized_callback(GLFWwindow* window, int n) {
|
|
|
|
if (n == GLFW_TRUE) {
|
|
|
|
maximized = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
maximized = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-07 14:44:39 +02:00
|
|
|
duk_ret_t test_func(duk_context *ctx) {
|
|
|
|
printf("Hello from C++\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-09-19 12:48:34 +02:00
|
|
|
// main
|
2020-12-22 14:50:26 +01:00
|
|
|
int sdrpp_main(int argc, char *argv[]) {
|
2020-09-19 12:48:34 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
//FreeConsole();
|
2020-10-24 14:51:55 +02:00
|
|
|
// ConfigManager::setResourceDir("./res");
|
|
|
|
// ConfigManager::setConfigDir(".");
|
2020-09-19 12:48:34 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
spdlog::info("SDR++ v" VERSION_STR);
|
|
|
|
|
2020-12-22 14:50:26 +01:00
|
|
|
// Load default options and parse command line
|
|
|
|
options::loadDefaults();
|
|
|
|
if (!options::parse(argc, argv)) { return -1; }
|
|
|
|
|
2020-12-23 00:11:12 +01:00
|
|
|
// 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_directory(options::opts.root)) {
|
|
|
|
spdlog::error("Could not create root directory {0}", options::opts.root);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!std::filesystem::is_directory(options::opts.root)) {
|
|
|
|
spdlog::error("{0} is not a directory", options::opts.root);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-12-10 05:18:40 +01: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;
|
2020-12-12 05:34:58 +01:00
|
|
|
defConfig["centerTuning"] = false;
|
2020-12-10 05:18:40 +01:00
|
|
|
defConfig["fftHeight"] = 300;
|
|
|
|
defConfig["frequency"] = 100000000.0;
|
|
|
|
defConfig["max"] = 0.0;
|
|
|
|
defConfig["maximized"] = false;
|
|
|
|
defConfig["menuOrder"] = {
|
|
|
|
"Source",
|
|
|
|
"Radio",
|
|
|
|
"Recorder",
|
|
|
|
"Sinks",
|
|
|
|
"Audio",
|
|
|
|
"Scripting",
|
|
|
|
"Band Plan",
|
|
|
|
"Display"
|
|
|
|
};
|
|
|
|
defConfig["menuWidth"] = 300;
|
|
|
|
defConfig["min"] = -70.0;
|
2020-12-23 00:11:12 +01:00
|
|
|
|
2020-12-10 05:18:40 +01:00
|
|
|
defConfig["moduleInstances"]["Radio"] = "radio";
|
|
|
|
defConfig["moduleInstances"]["Recorder"] = "recorder";
|
|
|
|
defConfig["moduleInstances"]["SoapySDR Source"] = "soapy_source";
|
2020-12-24 14:43:14 +01:00
|
|
|
defConfig["moduleInstances"]["PlutoSDR Source"] = "plutosdr_source";
|
|
|
|
defConfig["moduleInstances"]["RTL-TCP Source"] = "rtl_tcp_source";
|
|
|
|
defConfig["moduleInstances"]["AirspyHF+ Source"] = "airspyhf_source";
|
2020-12-26 00:42:15 +01:00
|
|
|
defConfig["moduleInstances"]["HackRF Source"] = "hackrf_source";
|
2020-12-24 14:43:14 +01:00
|
|
|
defConfig["moduleInstances"]["Audio Sink"] = "audio_sink";
|
2020-12-23 00:11:12 +01:00
|
|
|
|
2020-12-10 05:18:40 +01:00
|
|
|
defConfig["modules"] = json::array();
|
|
|
|
defConfig["offset"] = 0.0;
|
|
|
|
defConfig["showWaterfall"] = true;
|
|
|
|
defConfig["source"] = "";
|
|
|
|
defConfig["streams"] = json::object();
|
|
|
|
defConfig["windowSize"]["h"] = 720;
|
|
|
|
defConfig["windowSize"]["w"] = 1280;
|
2020-12-23 00:11:12 +01:00
|
|
|
|
|
|
|
defConfig["bandColors"]["broadcast"] = "#0000FFFF";
|
|
|
|
defConfig["bandColors"]["amateur"] = "#FF0000FF";
|
|
|
|
defConfig["bandColors"]["aviation"] = "#00FF00FF";
|
|
|
|
defConfig["bandColors"]["marine"] = "#00FFFFFF";
|
|
|
|
defConfig["bandColors"]["military"] = "#FFFF00FF";
|
2020-12-10 05:18:40 +01:00
|
|
|
|
2020-12-22 22:39:24 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
defConfig["modulesDirectory"] = "./modules";
|
|
|
|
defConfig["resourcesDirectory"] = "./res";
|
|
|
|
#else
|
|
|
|
defConfig["modulesDirectory"] = "/usr/lib/sdrpp/plugins";
|
|
|
|
defConfig["resourcesDirectory"] = "/usr/share/sdrpp";
|
|
|
|
#endif
|
|
|
|
|
2020-09-19 12:48:34 +02:00
|
|
|
// Load config
|
2020-12-22 18:42:30 +01:00
|
|
|
spdlog::info("Loading config");
|
2020-12-22 14:50:26 +01:00
|
|
|
core::configManager.setPath(options::opts.root + "/config.json");
|
2020-12-10 05:18:40 +01:00
|
|
|
core::configManager.load(defConfig);
|
2020-09-24 19:36:57 +02:00
|
|
|
core::configManager.enableAutoSave();
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
// Setup window
|
|
|
|
glfwSetErrorCallback(glfw_error_callback);
|
|
|
|
if (!glfwInit()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-24 23:38:45 +01:00
|
|
|
#ifdef __APPLE__
|
|
|
|
// GL 3.2 + GLSL 150
|
|
|
|
const char* glsl_version = "#version 150";
|
2020-09-19 12:48:34 +02:00
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
|
|
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
|
|
|
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
|
2020-12-24 23:38:45 +01:00
|
|
|
#else
|
|
|
|
// GL 3.0 + GLSL 120
|
|
|
|
const char* glsl_version = "#version 120";
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
|
|
#endif
|
2020-09-19 12:48:34 +02:00
|
|
|
|
2020-09-24 19:36:57 +02:00
|
|
|
core::configManager.aquire();
|
|
|
|
int winWidth = core::configManager.conf["windowSize"]["w"];
|
|
|
|
int winHeight = core::configManager.conf["windowSize"]["h"];
|
|
|
|
maximized = core::configManager.conf["maximized"];
|
2020-12-22 22:39:24 +01:00
|
|
|
std::string resDir = core::configManager.conf["resourcesDirectory"];
|
2020-12-23 00:11:12 +01:00
|
|
|
json bandColors = core::configManager.conf["bandColors"];
|
2020-09-24 19:36:57 +02:00
|
|
|
core::configManager.release();
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
// Create window with graphics context
|
|
|
|
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
|
|
|
GLFWwindow* window = glfwCreateWindow(winWidth, winHeight, "SDR++ v" VERSION_STR " (Built at " __TIME__ ", " __DATE__ ")", NULL, NULL);
|
|
|
|
if (window == NULL)
|
|
|
|
return 1;
|
|
|
|
glfwMakeContextCurrent(window);
|
|
|
|
|
2020-10-22 18:09:58 +02:00
|
|
|
#if (GLFW_VERSION_MAJOR == 3) && (GLFW_VERSION_MINOR >= 3)
|
2020-09-19 12:48:34 +02:00
|
|
|
if (maximized) {
|
|
|
|
glfwMaximizeWindow(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
glfwSetWindowMaximizeCallback(window, maximized_callback);
|
2020-10-22 17:55:49 +02:00
|
|
|
#endif
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
// Load app icon
|
|
|
|
GLFWimage icons[10];
|
2020-12-22 23:10:49 +01:00
|
|
|
icons[0].pixels = stbi_load(((std::string)(resDir + "/icons/sdrpp.png")).c_str(), &icons[0].width, &icons[0].height, 0, 4);
|
2020-09-19 12:48:34 +02:00
|
|
|
icons[1].pixels = (unsigned char*)malloc(16 * 16 * 4); icons[1].width = icons[1].height = 16;
|
|
|
|
icons[2].pixels = (unsigned char*)malloc(24 * 24 * 4); icons[2].width = icons[2].height = 24;
|
|
|
|
icons[3].pixels = (unsigned char*)malloc(32 * 32 * 4); icons[3].width = icons[3].height = 32;
|
|
|
|
icons[4].pixels = (unsigned char*)malloc(48 * 48 * 4); icons[4].width = icons[4].height = 48;
|
|
|
|
icons[5].pixels = (unsigned char*)malloc(64 * 64 * 4); icons[5].width = icons[5].height = 64;
|
|
|
|
icons[6].pixels = (unsigned char*)malloc(96 * 96 * 4); icons[6].width = icons[6].height = 96;
|
|
|
|
icons[7].pixels = (unsigned char*)malloc(128 * 128 * 4); icons[7].width = icons[7].height = 128;
|
|
|
|
icons[8].pixels = (unsigned char*)malloc(196 * 196 * 4); icons[8].width = icons[8].height = 196;
|
|
|
|
icons[9].pixels = (unsigned char*)malloc(256 * 256 * 4); icons[9].width = icons[9].height = 256;
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[1].pixels, 16, 16, 16 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[2].pixels, 24, 24, 24 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[3].pixels, 32, 32, 32 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[4].pixels, 48, 48, 48 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[5].pixels, 64, 64, 64 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[6].pixels, 96, 96, 96 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[7].pixels, 128, 128, 128 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[8].pixels, 196, 196, 196 * 4, 4);
|
|
|
|
stbir_resize_uint8(icons[0].pixels, icons[0].width, icons[0].height, icons[0].width * 4, icons[9].pixels, 256, 256, 256 * 4, 4);
|
|
|
|
glfwSetWindowIcon(window, 10, icons);
|
|
|
|
stbi_image_free(icons[0].pixels);
|
|
|
|
for (int i = 1; i < 10; i++) {
|
|
|
|
free(icons[i].pixels);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (glewInit() != GLEW_OK) {
|
|
|
|
spdlog::error("Failed to initialize OpenGL loader!");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Setup Dear ImGui context
|
|
|
|
IMGUI_CHECKVERSION();
|
|
|
|
ImGui::CreateContext();
|
|
|
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
|
|
|
io.IniFilename = NULL;
|
|
|
|
|
|
|
|
// Setup Platform/Renderer bindings
|
|
|
|
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
2020-12-24 23:38:45 +01:00
|
|
|
ImGui_ImplOpenGL3_Init(glsl_version);
|
2020-09-19 12:48:34 +02:00
|
|
|
|
2020-12-22 22:39:24 +01:00
|
|
|
if (!style::setDarkStyle(resDir)) { return -1; }
|
2020-09-19 12:48:34 +02:00
|
|
|
|
2020-11-30 21:17:36 +01:00
|
|
|
LoadingScreen::setWindow(window);
|
2020-09-19 12:48:34 +02:00
|
|
|
|
2020-11-30 21:17:36 +01:00
|
|
|
LoadingScreen::show("Loading icons");
|
2020-09-19 12:48:34 +02:00
|
|
|
spdlog::info("Loading icons");
|
2020-12-22 22:39:24 +01:00
|
|
|
if (!icons::load(resDir)) { return -1; }
|
2020-09-19 12:48:34 +02:00
|
|
|
|
2020-11-30 21:17:36 +01:00
|
|
|
LoadingScreen::show("Loading band plans");
|
2020-09-19 12:48:34 +02:00
|
|
|
spdlog::info("Loading band plans");
|
2020-12-23 00:11:12 +01:00
|
|
|
bandplan::loadFromDir(resDir + "/bandplans");
|
2020-09-19 12:48:34 +02:00
|
|
|
|
2020-11-30 21:17:36 +01:00
|
|
|
LoadingScreen::show("Loading band plan colors");
|
2020-09-19 12:48:34 +02:00
|
|
|
spdlog::info("Loading band plans color table");
|
2020-12-23 00:11:12 +01:00
|
|
|
bandplan::loadColorTable(bandColors);
|
2020-09-19 12:48:34 +02:00
|
|
|
|
|
|
|
windowInit();
|
|
|
|
|
|
|
|
spdlog::info("Ready.");
|
|
|
|
|
|
|
|
bool _maximized = maximized;
|
|
|
|
int fsWidth, fsHeight, fsPosX, fsPosY;
|
|
|
|
|
|
|
|
// Main loop
|
|
|
|
while (!glfwWindowShouldClose(window)) {
|
|
|
|
glfwPollEvents();
|
|
|
|
|
|
|
|
// Start the Dear ImGui frame
|
|
|
|
ImGui_ImplOpenGL3_NewFrame();
|
|
|
|
ImGui_ImplGlfw_NewFrame();
|
|
|
|
ImGui::NewFrame();
|
|
|
|
|
2020-10-04 02:56:02 +02:00
|
|
|
//ImGui::ShowDemoWindow();
|
|
|
|
|
2020-09-19 12:48:34 +02:00
|
|
|
if (_maximized != maximized) {
|
|
|
|
_maximized = maximized;
|
2020-09-24 19:36:57 +02:00
|
|
|
core::configManager.aquire();
|
|
|
|
core::configManager.conf["maximized"]= _maximized;
|
2020-09-19 12:48:34 +02:00
|
|
|
if (!maximized) {
|
2020-09-24 19:36:57 +02:00
|
|
|
glfwSetWindowSize(window, core::configManager.conf["windowSize"]["w"], core::configManager.conf["windowSize"]["h"]);
|
2020-09-19 12:48:34 +02:00
|
|
|
}
|
2020-09-24 19:36:57 +02:00
|
|
|
core::configManager.release(true);
|
2020-09-19 12:48:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int _winWidth, _winHeight;
|
|
|
|
glfwGetWindowSize(window, &_winWidth, &_winHeight);
|
|
|
|
|
|
|
|
if (ImGui::IsKeyPressed(GLFW_KEY_F11)) {
|
|
|
|
fullScreen = !fullScreen;
|
|
|
|
if (fullScreen) {
|
|
|
|
spdlog::info("Fullscreen: ON");
|
|
|
|
fsWidth = _winWidth;
|
|
|
|
fsHeight = _winHeight;
|
|
|
|
glfwGetWindowPos(window, &fsPosX, &fsPosY);
|
|
|
|
const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
|
|
|
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
spdlog::info("Fullscreen: OFF");
|
|
|
|
glfwSetWindowMonitor(window, nullptr, fsPosX, fsPosY, fsWidth, fsHeight, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((_winWidth != winWidth || _winHeight != winHeight) && !maximized && _winWidth > 0 && _winHeight > 0) {
|
|
|
|
winWidth = _winWidth;
|
|
|
|
winHeight = _winHeight;
|
2020-09-24 19:36:57 +02:00
|
|
|
core::configManager.aquire();
|
|
|
|
core::configManager.conf["windowSize"]["w"] = winWidth;
|
|
|
|
core::configManager.conf["windowSize"]["h"] = winHeight;
|
|
|
|
core::configManager.release(true);
|
2020-09-19 12:48:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (winWidth > 0 && winHeight > 0) {
|
|
|
|
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
|
|
|
ImGui::SetNextWindowSize(ImVec2(_winWidth, _winHeight));
|
|
|
|
drawWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rendering
|
|
|
|
ImGui::Render();
|
|
|
|
int display_w, display_h;
|
|
|
|
glfwGetFramebufferSize(window, &display_w, &display_h);
|
|
|
|
glViewport(0, 0, display_w, display_h);
|
|
|
|
glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f);
|
|
|
|
//glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
|
|
|
2020-12-04 20:12:36 +01:00
|
|
|
glfwSwapInterval(1); // Enable vsync
|
2020-09-19 12:48:34 +02:00
|
|
|
glfwSwapBuffers(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cleanup
|
|
|
|
ImGui_ImplOpenGL3_Shutdown();
|
|
|
|
ImGui_ImplGlfw_Shutdown();
|
|
|
|
ImGui::DestroyContext();
|
|
|
|
|
|
|
|
glfwDestroyWindow(window);
|
|
|
|
glfwTerminate();
|
|
|
|
|
|
|
|
return 0;
|
2020-10-22 17:55:49 +02:00
|
|
|
}
|