SDRPlusPlus/core/src/gui/main_window.cpp

611 lines
22 KiB
C++
Raw Normal View History

2020-09-20 00:19:39 +02:00
#include <gui/main_window.h>
#include <gui/gui.h>
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <imgui_plot.h>
#include <thread>
#include <complex>
#include <gui/widgets/waterfall.h>
#include <gui/widgets/frequency_select.h>
#include <signal_path/dsp.h>
#include <gui/icons.h>
#include <gui/widgets/bandplan.h>
#include <gui/style.h>
#include <config.h>
#include <signal_path/signal_path.h>
#include <core.h>
#include <gui/menus/source.h>
#include <gui/menus/display.h>
#include <gui/menus/bandplan.h>
2020-11-29 20:55:00 +01:00
#include <gui/menus/sink.h>
#include <gui/menus/scripting.h>
2021-05-05 04:31:37 +02:00
#include <gui/menus/vfo_color.h>
#include <gui/menus/module_manager.h>
#include <gui/dialogs/credits.h>
2020-12-08 04:36:37 +01:00
#include <filesystem>
#include <signal_path/source.h>
2020-11-30 21:17:36 +01:00
#include <gui/dialogs/loading_screen.h>
2020-12-22 14:50:26 +01:00
#include <options.h>
#include <gui/colormaps.h>
2021-04-30 04:28:08 +02:00
#include <gui/widgets/snr_meter.h>
2021-06-20 21:17:11 +02:00
#include <gui/tuner.h>
2021-06-20 21:17:11 +02:00
void MainWindow::init() {
2020-11-30 21:17:36 +01:00
LoadingScreen::show("Initializing UI");
2020-10-22 03:16:11 +02:00
gui::waterfall.init();
gui::waterfall.setRawFFTSize(fftSize);
tempFFT = new float[fftSize];
FFTdata = new float[fftSize];
2020-09-24 19:36:57 +02:00
credits::init();
2020-10-20 00:32:17 +02:00
core::configManager.aquire();
2021-04-22 23:49:35 +02:00
json menuElements = core::configManager.conf["menuElements"];
2020-12-22 22:39:24 +01:00
std::string modulesDir = core::configManager.conf["modulesDirectory"];
std::string resourcesDir = core::configManager.conf["resourcesDirectory"];
2020-10-20 00:32:17 +02:00
core::configManager.release();
2021-04-22 23:49:35 +02:00
// Load menu elements
gui::menu.order.clear();
for (auto& elem : menuElements) {
if (!elem.contains("name")) { spdlog::error("Menu element is missing name key"); continue; }
if (!elem["name"].is_string()) { spdlog::error("Menu element name isn't a string"); continue; }
if (!elem.contains("open")) { spdlog::error("Menu element is missing open key"); continue; }
if (!elem["open"].is_boolean()) { spdlog::error("Menu element name isn't a string"); continue; }
Menu::MenuOption_t opt;
opt.name = elem["name"];
opt.open = elem["open"];
gui::menu.order.push_back(opt);
}
2020-10-01 01:21:15 +02:00
gui::menu.registerEntry("Source", sourecmenu::draw, NULL);
2020-11-29 20:55:00 +01:00
gui::menu.registerEntry("Sinks", sinkmenu::draw, NULL);
2020-10-07 14:44:39 +02:00
gui::menu.registerEntry("Scripting", scriptingmenu::draw, NULL);
gui::menu.registerEntry("Band Plan", bandplanmenu::draw, NULL);
gui::menu.registerEntry("Display", displaymenu::draw, NULL);
2021-05-04 20:41:23 +02:00
gui::menu.registerEntry("VFO Color", vfo_color_menu::draw, NULL);
2021-05-05 04:31:37 +02:00
gui::menu.registerEntry("Module Manager", module_manager_menu::draw, NULL);
2020-09-19 12:48:34 +02:00
2020-09-20 00:19:39 +02:00
gui::freqSelect.init();
2020-11-28 23:24:45 +01:00
// Set default values for waterfall in case no source init's it
gui::waterfall.setBandwidth(8000000);
gui::waterfall.setViewBandwidth(8000000);
2020-06-15 15:53:45 +02:00
2020-07-20 15:26:59 +02:00
fft_in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fft_out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
2021-06-20 21:17:11 +02:00
fftwPlan = fftwf_plan_dft_1d(fftSize, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE);
2020-06-10 04:13:56 +02:00
2021-06-20 21:17:11 +02:00
sigpath::signalPath.init(8000000, 20, fftSize, &dummyStream, (dsp::complex_t*)fft_in, fftHandler, this);
2020-09-20 00:19:39 +02:00
sigpath::signalPath.start();
2020-08-11 18:33:42 +02:00
2021-05-05 04:31:37 +02:00
vfoCreatedHandler.handler = vfoAddedHandler;
2021-06-20 21:17:11 +02:00
vfoCreatedHandler.ctx = this;
2021-05-05 04:31:37 +02:00
sigpath::vfoManager.vfoCreatedEvent.bindHandler(vfoCreatedHandler);
2020-08-12 16:43:44 +02:00
spdlog::info("Loading modules");
2020-12-08 04:36:37 +01:00
// Load modules from /module directory
2020-12-22 22:39:24 +01:00
if (std::filesystem::is_directory(modulesDir)) {
for (const auto & file : std::filesystem::directory_iterator(modulesDir)) {
2020-12-08 04:36:37 +01:00
std::string path = file.path().generic_string();
if (file.path().extension().generic_string() != SDRPP_MOD_EXTENTSION) {
continue;
}
if (!file.is_regular_file()) { continue; }
spdlog::info("Loading {0}", path);
LoadingScreen::show("Loading " + path);
core::moduleManager.loadModule(path);
}
}
else {
2020-12-22 22:39:24 +01:00
spdlog::warn("Module directory {0} does not exist, not loading modules from directory", modulesDir);
2020-12-08 04:36:37 +01:00
}
// Read module config
core::configManager.aquire();
std::vector<std::string> modules = core::configManager.conf["modules"];
std::map<std::string, std::string> modList = core::configManager.conf["moduleInstances"];
core::configManager.release();
// Load additional modules specified through config
for (auto const& path : modules) {
spdlog::info("Loading {0}", path);
LoadingScreen::show("Loading " + path);
core::moduleManager.loadModule(path);
}
// Create module instances
for (auto const& [name, module] : modList) {
spdlog::info("Initializing {0} ({1})", name, module);
LoadingScreen::show("Initializing " + name + " (" + module + ")");
core::moduleManager.createInstance(name, module);
}
2020-06-10 04:13:56 +02:00
// Load color maps
LoadingScreen::show("Loading color maps");
spdlog::info("Loading color maps");
if (std::filesystem::is_directory(resourcesDir + "/colormaps")) {
for (const auto & file : std::filesystem::directory_iterator(resourcesDir + "/colormaps")) {
std::string path = file.path().generic_string();
LoadingScreen::show("Loading " + path);
spdlog::info("Loading {0}", path);
if (file.path().extension().generic_string() != ".json") {
continue;
}
if (!file.is_regular_file()) { continue; }
colormaps::loadMap(path);
}
}
else {
spdlog::warn("Color map directory {0} does not exist, not loading modules from directory", modulesDir);
}
gui::waterfall.updatePalletteFromArray(colormaps::maps["Turbo"].map, colormaps::maps["Turbo"].entryCount);
2020-10-01 01:21:15 +02:00
sourecmenu::init();
2020-11-29 20:55:00 +01:00
sinkmenu::init();
2020-10-07 14:44:39 +02:00
scriptingmenu::init();
2020-10-01 01:21:15 +02:00
bandplanmenu::init();
displaymenu::init();
2021-05-04 20:41:23 +02:00
vfo_color_menu::init();
2021-05-05 04:31:37 +02:00
module_manager_menu::init();
2020-10-01 01:21:15 +02:00
// TODO for 0.2.5
2020-12-08 16:27:52 +01:00
// Fix gain not updated on startup, soapysdr
2020-08-21 17:11:12 +02:00
2020-08-16 03:39:05 +02:00
// Update UI settings
2020-11-30 21:17:36 +01:00
LoadingScreen::show("Loading configuration");
2020-10-20 00:32:17 +02:00
core::configManager.aquire();
2020-09-24 19:36:57 +02:00
fftMin = core::configManager.conf["min"];
fftMax = core::configManager.conf["max"];
2020-09-20 00:19:39 +02:00
gui::waterfall.setFFTMin(fftMin);
gui::waterfall.setWaterfallMin(fftMin);
gui::waterfall.setFFTMax(fftMax);
gui::waterfall.setWaterfallMax(fftMax);
2020-10-01 01:21:15 +02:00
double frequency = core::configManager.conf["frequency"];
2020-08-16 03:39:05 +02:00
2021-04-23 03:58:10 +02:00
showMenu = core::configManager.conf["showMenu"];
startedWithMenuClosed = !showMenu;
2020-09-20 00:19:39 +02:00
gui::freqSelect.setFrequency(frequency);
gui::freqSelect.frequencyChanged = false;
2020-10-01 01:21:15 +02:00
sigpath::sourceManager.tune(frequency);
2020-09-20 00:19:39 +02:00
gui::waterfall.setCenterFrequency(frequency);
2020-11-28 23:24:45 +01:00
bw = gui::waterfall.getBandwidth();
2020-09-20 00:19:39 +02:00
gui::waterfall.vfoFreqChanged = false;
gui::waterfall.centerFreqMoved = false;
gui::waterfall.selectFirstVFO();
2020-08-16 03:39:05 +02:00
2020-09-24 19:36:57 +02:00
menuWidth = core::configManager.conf["menuWidth"];
2020-08-20 18:29:23 +02:00
newWidth = menuWidth;
2020-09-24 19:36:57 +02:00
fftHeight = core::configManager.conf["fftHeight"];
2020-09-20 00:19:39 +02:00
gui::waterfall.setFFTHeight(fftHeight);
2020-09-24 19:36:57 +02:00
2021-06-20 21:17:11 +02:00
tuningMode = core::configManager.conf["centerTuning"] ? tuner::TUNER_MODE_CENTER : tuner::TUNER_MODE_NORMAL;
2020-12-08 04:36:37 +01:00
2020-09-24 19:36:57 +02:00
core::configManager.release();
2020-08-16 03:39:05 +02:00
}
2020-07-19 18:23:00 +02:00
2021-06-20 21:17:11 +02:00
void MainWindow::fftHandler(dsp::complex_t* samples, int count, void* ctx) {
MainWindow* _this = (MainWindow*)ctx;
std::lock_guard<std::mutex> lck(_this->fft_mtx);
if (count != _this->fftSize) { return; }
2020-07-19 15:59:44 +02:00
2021-06-20 21:17:11 +02:00
memcpy(_this->fft_in, samples, count * sizeof(dsp::complex_t));
fftwf_execute(_this->fftwPlan);
int half = count / 2;
2020-07-19 15:59:44 +02:00
2021-06-20 21:17:11 +02:00
float* fftBuf = gui::waterfall.getFFTBuffer();
if (fftBuf == NULL) {
gui::waterfall.pushFFT();
2020-07-19 15:59:44 +02:00
return;
}
2021-06-20 21:17:11 +02:00
volk_32fc_s32f_power_spectrum_32f(_this->tempFFT, (lv_32fc_t*)_this->fft_out, count, count);
2020-07-19 15:59:44 +02:00
2021-06-20 21:17:11 +02:00
memcpy(fftBuf, &_this->tempFFT[half], half * sizeof(float));
memcpy(&fftBuf[half], _this->tempFFT, half * sizeof(float));
2020-07-19 15:59:44 +02:00
2021-06-20 21:17:11 +02:00
gui::waterfall.pushFFT();
}
2020-07-19 15:59:44 +02:00
2021-06-20 21:17:11 +02:00
void MainWindow::vfoAddedHandler(VFOManager::VFO* vfo, void* ctx) {
MainWindow* _this = (MainWindow*)ctx;
std::string name = vfo->getName();
core::configManager.aquire();
if (!core::configManager.conf["vfoOffsets"].contains(name)) {
core::configManager.release();
return;
2020-07-19 15:59:44 +02:00
}
2021-06-20 21:17:11 +02:00
double offset = core::configManager.conf["vfoOffsets"][name];
core::configManager.release();
sigpath::vfoManager.setOffset(name, std::clamp<double>(offset, -_this->bw/2.0, _this->bw/2.0));
2020-07-19 15:59:44 +02:00
}
2020-07-11 21:15:10 +02:00
2021-06-20 21:17:11 +02:00
void MainWindow::draw() {
2020-08-16 03:39:05 +02:00
ImGui::Begin("Main", NULL, WINDOW_FLAGS);
2020-08-11 18:33:42 +02:00
2020-12-08 04:36:37 +01:00
ImGui::WaterfallVFO* vfo = NULL;
if (gui::waterfall.selectedVFO != "") {
vfo = gui::waterfall.vfos[gui::waterfall.selectedVFO];
2020-08-11 18:33:42 +02:00
}
2021-06-20 21:17:11 +02:00
// Handle VFO movement
2020-12-08 04:36:37 +01:00
if (vfo != NULL) {
if (vfo->centerOffsetChanged) {
2021-06-20 21:17:11 +02:00
if (tuningMode == tuner::TUNER_MODE_CENTER) {
tuner::tune(tuner::TUNER_MODE_CENTER, gui::waterfall.selectedVFO, gui::waterfall.getCenterFrequency() + vfo->generalOffset);
2020-12-08 16:27:52 +01:00
}
2020-12-08 04:36:37 +01:00
gui::freqSelect.setFrequency(gui::waterfall.getCenterFrequency() + vfo->generalOffset);
gui::freqSelect.frequencyChanged = false;
core::configManager.aquire();
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
2020-12-08 04:36:37 +01:00
core::configManager.release(true);
}
}
2020-09-20 00:19:39 +02:00
sigpath::vfoManager.updateFromWaterfall(&gui::waterfall);
2020-08-11 18:33:42 +02:00
2021-04-23 17:53:25 +02:00
// Handle selection of another VFO
if (gui::waterfall.selectedVFOChanged) {
gui::freqSelect.setFrequency((vfo != NULL) ? (vfo->generalOffset + gui::waterfall.getCenterFrequency()) : gui::waterfall.getCenterFrequency());
2020-09-20 00:19:39 +02:00
gui::waterfall.selectedVFOChanged = false;
gui::freqSelect.frequencyChanged = false;
2020-08-10 02:30:25 +02:00
}
2021-04-23 17:53:25 +02:00
// Handle change in selected frequency
2020-09-20 00:19:39 +02:00
if (gui::freqSelect.frequencyChanged) {
gui::freqSelect.frequencyChanged = false;
2021-06-20 21:17:11 +02:00
tuner::tune(tuningMode, gui::waterfall.selectedVFO, gui::freqSelect.frequency);
2020-12-08 04:36:37 +01:00
if (vfo != NULL) {
vfo->centerOffsetChanged = false;
vfo->lowerOffsetChanged = false;
vfo->upperOffsetChanged = false;
}
2020-09-24 19:36:57 +02:00
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
2020-09-24 19:36:57 +02:00
core::configManager.release(true);
2020-06-10 04:13:56 +02:00
}
2021-04-23 17:53:25 +02:00
// Handle dragging the frequency scale
2020-09-20 00:19:39 +02:00
if (gui::waterfall.centerFreqMoved) {
gui::waterfall.centerFreqMoved = false;
2020-10-01 01:21:15 +02:00
sigpath::sourceManager.tune(gui::waterfall.getCenterFrequency());
2020-12-08 04:36:37 +01:00
if (vfo != NULL) {
gui::freqSelect.setFrequency(gui::waterfall.getCenterFrequency() + vfo->generalOffset);
}
else {
gui::freqSelect.setFrequency(gui::waterfall.getCenterFrequency());
}
2020-09-24 19:36:57 +02:00
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
2020-09-24 19:36:57 +02:00
core::configManager.release(true);
2020-08-04 21:34:56 +02:00
}
2020-09-20 00:19:39 +02:00
int _fftHeight = gui::waterfall.getFFTHeight();
2020-08-20 18:29:23 +02:00
if (fftHeight != _fftHeight) {
fftHeight = _fftHeight;
2020-09-24 19:36:57 +02:00
core::configManager.aquire();
core::configManager.conf["fftHeight"] = fftHeight;
core::configManager.release(true);
2020-08-20 18:29:23 +02:00
}
2020-06-10 04:13:56 +02:00
ImVec2 vMin = ImGui::GetWindowContentRegionMin();
ImVec2 vMax = ImGui::GetWindowContentRegionMax();
int width = vMax.x - vMin.x;
int height = vMax.y - vMin.y;
2020-07-19 15:59:44 +02:00
// To Bar
ImGui::PushID(ImGui::GetID("sdrpp_menu_btn"));
2021-04-24 04:06:04 +02:00
if (ImGui::ImageButton(icons::MENU, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(GLFW_KEY_MENU, false)) {
2020-08-21 15:34:50 +02:00
showMenu = !showMenu;
2021-04-23 03:58:10 +02:00
core::configManager.aquire();
core::configManager.conf["showMenu"] = showMenu;
core::configManager.release(true);
2020-08-21 15:34:50 +02:00
}
2020-11-30 16:45:02 +01:00
ImGui::PopID();
2020-08-21 15:34:50 +02:00
ImGui::SameLine();
2020-07-19 15:59:44 +02:00
if (playing) {
ImGui::PushID(ImGui::GetID("sdrpp_stop_btn"));
2021-04-24 04:06:04 +02:00
if (ImGui::ImageButton(icons::STOP, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(GLFW_KEY_END, false)) {
2020-10-01 01:21:15 +02:00
sigpath::sourceManager.stop();
2020-07-19 15:59:44 +02:00
playing = false;
}
2020-11-30 16:45:02 +01:00
ImGui::PopID();
2020-07-19 15:59:44 +02:00
}
2020-10-01 01:21:15 +02:00
else { // TODO: Might need to check if there even is a device
ImGui::PushID(ImGui::GetID("sdrpp_play_btn"));
2021-04-24 04:06:04 +02:00
if (ImGui::ImageButton(icons::PLAY, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(GLFW_KEY_END, false)) {
2020-10-01 01:21:15 +02:00
sigpath::sourceManager.start();
// TODO: tune in module instead
sigpath::sourceManager.tune(gui::waterfall.getCenterFrequency());
2020-07-19 15:59:44 +02:00
playing = true;
}
2020-11-30 16:45:02 +01:00
ImGui::PopID();
2020-07-19 15:59:44 +02:00
}
ImGui::SameLine();
//ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8);
2020-12-08 16:27:52 +01:00
sigpath::sinkManager.showVolumeSlider(gui::waterfall.selectedVFO, "##_sdrpp_main_volume_", 248, 30, 5, true);
2020-07-19 15:59:44 +02:00
ImGui::SameLine();
2020-09-20 00:19:39 +02:00
gui::freqSelect.draw();
2020-07-19 15:59:44 +02:00
ImGui::SameLine();
2020-12-08 16:27:52 +01:00
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 9);
2021-06-20 21:17:11 +02:00
if (tuningMode == tuner::TUNER_MODE_CENTER) {
2020-12-08 16:27:52 +01:00
ImGui::PushID(ImGui::GetID("sdrpp_ena_st_btn"));
if (ImGui::ImageButton(icons::CENTER_TUNING, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5)) {
2021-06-20 21:17:11 +02:00
tuningMode = tuner::TUNER_MODE_NORMAL;
2020-12-08 16:27:52 +01:00
core::configManager.aquire();
2021-06-20 21:17:11 +02:00
core::configManager.conf["centerTuning"] = false;
2020-12-08 16:27:52 +01:00
core::configManager.release(true);
}
ImGui::PopID();
}
else { // TODO: Might need to check if there even is a device
ImGui::PushID(ImGui::GetID("sdrpp_dis_st_btn"));
if (ImGui::ImageButton(icons::NORMAL_TUNING, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5)) {
2021-06-20 21:17:11 +02:00
tuningMode = tuner::TUNER_MODE_CENTER;
tuner::tune(tuner::TUNER_MODE_CENTER, gui::waterfall.selectedVFO, gui::freqSelect.frequency);
2020-12-08 16:27:52 +01:00
core::configManager.aquire();
2021-06-20 21:17:11 +02:00
core::configManager.conf["centerTuning"] = true;
2020-12-08 16:27:52 +01:00
core::configManager.release(true);
}
ImGui::PopID();
}
2020-08-16 03:39:05 +02:00
ImGui::SameLine();
2021-04-30 04:28:08 +02:00
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 387);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
ImGui::SetNextItemWidth(300);
ImGui::SNRMeter((vfo != NULL) ? gui::waterfall.selectedVFOSNR : 0);
ImGui::SameLine();
2020-08-16 03:39:05 +02:00
// Logo button
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 48);
ImGui::SetCursorPosY(10);
if (ImGui::ImageButton(icons::LOGO, ImVec2(32, 32), ImVec2(0, 0), ImVec2(1, 1), 0)) {
showCredits = true;
}
if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
showCredits = false;
}
if (ImGui::IsKeyPressed(GLFW_KEY_ESCAPE)) {
showCredits = false;
}
2020-08-20 18:29:23 +02:00
// Handle menu resize
float curY = ImGui::GetCursorPosY();
2020-07-19 15:59:44 +02:00
ImVec2 winSize = ImGui::GetWindowSize();
2020-08-20 18:29:23 +02:00
ImVec2 mousePos = ImGui::GetMousePos();
bool click = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
bool down = ImGui::IsMouseDown(ImGuiMouseButton_Left);
if (grabbingMenu) {
newWidth = mousePos.x;
newWidth = std::clamp<float>(newWidth, 250, winSize.x - 250);
ImGui::GetForegroundDrawList()->AddLine(ImVec2(newWidth, curY), ImVec2(newWidth, winSize.y - 10), ImGui::GetColorU32(ImGuiCol_SeparatorActive));
}
if (mousePos.x >= newWidth - 2 && mousePos.x <= newWidth + 2 && mousePos.y > curY) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
if (click) {
grabbingMenu = true;
}
}
else {
ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
}
if(!down && grabbingMenu) {
grabbingMenu = false;
menuWidth = newWidth;
2020-09-24 19:36:57 +02:00
core::configManager.aquire();
core::configManager.conf["menuWidth"] = menuWidth;
core::configManager.release(true);
2020-08-20 18:29:23 +02:00
}
2020-06-10 04:13:56 +02:00
// Left Column
2020-08-16 03:39:05 +02:00
2020-08-21 15:34:50 +02:00
if (showMenu) {
ImGui::Columns(3, "WindowColumns", false);
ImGui::SetColumnWidth(0, menuWidth);
ImGui::SetColumnWidth(1, winSize.x - menuWidth - 60);
ImGui::SetColumnWidth(2, 60);
ImGui::BeginChild("Left Column");
float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
2020-08-16 03:39:05 +02:00
2021-04-23 03:58:10 +02:00
if (gui::menu.draw(firstMenuRender)) {
2021-04-22 23:49:35 +02:00
core::configManager.aquire();
json arr = json::array();
for (int i = 0; i < gui::menu.order.size(); i++) {
arr[i]["name"] = gui::menu.order[i].name;
arr[i]["open"] = gui::menu.order[i].open;
}
core::configManager.conf["menuElements"] = arr;
core::configManager.release(true);
}
2021-04-23 03:58:10 +02:00
if (startedWithMenuClosed) {
startedWithMenuClosed = false;
}
else {
firstMenuRender = false;
}
2020-06-10 04:13:56 +02:00
2020-08-21 15:34:50 +02:00
if(ImGui::CollapsingHeader("Debug")) {
ImGui::Text("Frame time: %.3f ms/frame", 1000.0 / ImGui::GetIO().Framerate);
2020-08-21 15:34:50 +02:00
ImGui::Text("Framerate: %.1f FPS", ImGui::GetIO().Framerate);
2020-10-22 02:47:10 +02:00
ImGui::Text("Center Frequency: %.0f Hz", gui::waterfall.getCenterFrequency());
2020-08-21 17:11:12 +02:00
ImGui::Text("Source name: %s", sourceName.c_str());
2020-12-10 05:18:40 +01:00
ImGui::Checkbox("Show demo window", &demoWindow);
ImGui::Text("ImGui version: %s", ImGui::GetVersion());
2021-02-08 20:08:59 +01:00
if (ImGui::Button("Test Bug")) {
spdlog::error("Will this make the software crash?");
}
2021-04-23 03:58:10 +02:00
if (ImGui::Button("Testing something")) {
gui::menu.order[0].open = true;
firstMenuRender = true;
}
2020-08-21 15:34:50 +02:00
ImGui::Spacing();
}
2020-06-10 04:13:56 +02:00
2020-08-21 15:34:50 +02:00
ImGui::EndChild();
}
else {
// When hiding the menu bar
ImGui::Columns(3, "WindowColumns", false);
ImGui::SetColumnWidth(0, 8);
ImGui::SetColumnWidth(1, winSize.x - 8 - 60);
ImGui::SetColumnWidth(2, 60);
}
2020-06-10 04:13:56 +02:00
// Right Column
2020-08-16 03:39:05 +02:00
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
2020-06-10 04:13:56 +02:00
ImGui::NextColumn();
2020-08-17 02:39:56 +02:00
ImGui::PopStyleVar();
2020-06-10 04:13:56 +02:00
ImGui::BeginChild("Waterfall");
2020-08-16 03:39:05 +02:00
2020-09-20 00:19:39 +02:00
gui::waterfall.draw();
2020-08-16 03:39:05 +02:00
2020-06-10 04:13:56 +02:00
ImGui::EndChild();
2020-07-19 15:59:44 +02:00
2021-04-24 04:06:04 +02:00
// Handle arrow keys
if (vfo != NULL && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) {
if (ImGui::IsKeyPressed(GLFW_KEY_LEFT) && !gui::freqSelect.digitHovered) {
double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset - vfo->snapInterval;
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
2021-06-20 21:17:11 +02:00
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
2021-04-24 04:06:04 +02:00
}
if (ImGui::IsKeyPressed(GLFW_KEY_RIGHT) && !gui::freqSelect.digitHovered) {
double nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + vfo->snapInterval;
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
2021-06-20 21:17:11 +02:00
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
2021-04-24 04:06:04 +02:00
}
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
core::configManager.release(true);
}
2021-04-24 01:24:27 +02:00
// Handle scrollwheel
int wheel = ImGui::GetIO().MouseWheel;
if (wheel != 0 && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) {
2021-04-24 04:06:04 +02:00
double nfreq;
if (vfo != NULL) {
nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + (vfo->snapInterval * wheel);
nfreq = roundl(nfreq / vfo->snapInterval) * vfo->snapInterval;
}
else {
nfreq = gui::waterfall.getCenterFrequency() - (gui::waterfall.getViewBandwidth() * wheel / 20.0);
}
2021-06-20 21:17:11 +02:00
tuner::tune(tuningMode, gui::waterfall.selectedVFO, nfreq);
2021-04-24 04:06:04 +02:00
gui::freqSelect.setFrequency(nfreq);
2021-04-24 01:24:27 +02:00
core::configManager.aquire();
core::configManager.conf["frequency"] = gui::waterfall.getCenterFrequency();
if (vfo != NULL) {
core::configManager.conf["vfoOffsets"][gui::waterfall.selectedVFO] = vfo->generalOffset;
}
core::configManager.release(true);
}
2020-08-20 18:29:23 +02:00
2020-07-19 15:59:44 +02:00
ImGui::NextColumn();
2020-08-16 03:39:05 +02:00
ImGui::BeginChild("WaterfallControls");
2020-07-19 15:59:44 +02:00
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Zoom").x / 2.0));
2020-07-19 15:59:44 +02:00
ImGui::Text("Zoom");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
2021-02-08 11:13:26 +01:00
if (ImGui::VSliderFloat("##_7_", ImVec2(20.0, 150.0), &bw, gui::waterfall.getBandwidth(), 1000.0, "")) {
2020-11-28 23:24:45 +01:00
gui::waterfall.setViewBandwidth(bw);
2020-12-08 04:36:37 +01:00
if (vfo != NULL) {
gui::waterfall.setViewOffset(vfo->centerOffset); // center vfo on screen
}
2020-11-28 23:24:45 +01:00
}
2020-07-19 15:59:44 +02:00
ImGui::NewLine();
2020-07-19 18:09:59 +02:00
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Max").x / 2.0));
2020-07-19 18:09:59 +02:00
ImGui::Text("Max");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
2021-02-12 23:11:57 +01:00
if (ImGui::VSliderFloat("##_8_", ImVec2(20.0, 150.0), &fftMax, 0.0, -160.0f, "")) {
2020-08-17 02:39:56 +02:00
fftMax = std::max<float>(fftMax, fftMin + 10);
2020-09-24 19:36:57 +02:00
core::configManager.aquire();
core::configManager.conf["max"] = fftMax;
core::configManager.release(true);
2020-08-16 03:39:05 +02:00
}
2020-07-19 15:59:44 +02:00
ImGui::NewLine();
2020-07-19 18:09:59 +02:00
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Min").x / 2.0));
2020-07-19 18:09:59 +02:00
ImGui::Text("Min");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
2021-02-12 23:11:57 +01:00
if (ImGui::VSliderFloat("##_9_", ImVec2(20.0, 150.0), &fftMin, 0.0, -160.0f, "")) {
2020-08-17 02:39:56 +02:00
fftMin = std::min<float>(fftMax - 10, fftMin);
2020-09-24 19:36:57 +02:00
core::configManager.aquire();
core::configManager.conf["min"] = fftMin;
core::configManager.release(true);
2020-08-16 03:39:05 +02:00
}
ImGui::EndChild();
2020-07-19 15:59:44 +02:00
2020-09-20 00:19:39 +02:00
gui::waterfall.setFFTMin(fftMin);
gui::waterfall.setFFTMax(fftMax);
gui::waterfall.setWaterfallMin(fftMin);
gui::waterfall.setWaterfallMax(fftMax);
2020-08-16 03:39:05 +02:00
ImGui::End();
if (showCredits) {
credits::show();
2020-08-16 03:39:05 +02:00
}
2020-12-10 05:18:40 +01:00
if (demoWindow) {
ImGui::ShowDemoWindow();
}
2020-11-28 23:24:45 +01:00
}
2021-06-20 21:17:11 +02:00
void MainWindow::setViewBandwidthSlider(float bandwidth) {
2020-11-28 23:24:45 +01:00
bw = bandwidth;
2020-12-23 19:23:47 +01:00
}
2021-06-20 21:17:11 +02:00
bool MainWindow::sdrIsRunning() {
2020-12-23 19:23:47 +01:00
return playing;
2021-04-13 18:31:38 +02:00
}
2021-06-20 21:17:11 +02:00
void MainWindow::setFFTSize(int size) {
2021-04-13 18:31:38 +02:00
std::lock_guard<std::mutex> lck(fft_mtx);
fftSize = size;
gui::waterfall.setRawFFTSize(fftSize);
sigpath::signalPath.setFFTSize(fftSize);
fftwf_free(fft_in);
fftwf_free(fft_out);
2021-06-20 21:17:11 +02:00
fftwf_destroy_plan(fftwPlan);
2021-04-13 18:31:38 +02:00
fft_in = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fft_out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize);
2021-06-20 21:17:11 +02:00
fftwPlan = fftwf_plan_dft_1d(fftSize, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE);
2020-06-10 04:13:56 +02:00
}