From cefcd18269e45c04f3d48bd34cc7a8596f75d71a Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Thu, 28 Jan 2021 21:10:08 +0100 Subject: [PATCH] Added airspy module + changes to the UI for scaling --- CMakeLists.txt | 5 + airspy_source/CMakeLists.txt | 31 ++ airspy_source/src/main.cpp | 426 ++++++++++++++++++++++ core/src/gui/main_window.cpp | 2 +- core/src/gui/style.cpp | 4 +- core/src/gui/widgets/frequency_select.cpp | 33 +- core/src/gui/widgets/waterfall.cpp | 9 +- 7 files changed, 494 insertions(+), 16 deletions(-) create mode 100644 airspy_source/CMakeLists.txt create mode 100644 airspy_source/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bb95d285..2325c5e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies re option(OPT_BUILD_SPYSERVER_SOURCE "Build SpyServer Source Module (no dependencies required)" ON) option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Depedencies: soapysdr)" ON) option(OPT_BUILD_AIRSPYHF_SOURCE "Build Airspy HF+ Source Module (Depedencies: libairspyhf)" ON) +option(OPT_BUILD_AIRSPY_SOURCE "Build Airspy Source Module (Depedencies: libairspy)" ON) option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Depedencies: libiio, libad9361)" ON) option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Depedencies: libhackrf)" ON) option(OPT_BUILD_AUDIO_SINK "Build Audio Sink Module (Depedencies: portaudio)" ON) @@ -33,6 +34,10 @@ if (OPT_BUILD_AIRSPYHF_SOURCE) add_subdirectory("airspyhf_source") endif (OPT_BUILD_AIRSPYHF_SOURCE) +if (OPT_BUILD_AIRSPY_SOURCE) +add_subdirectory("airspy_source") +endif (OPT_BUILD_AIRSPY_SOURCE) + if (OPT_BUILD_PLUTOSDR_SOURCE) add_subdirectory("plutosdr_source") endif (OPT_BUILD_PLUTOSDR_SOURCE) diff --git a/airspy_source/CMakeLists.txt b/airspy_source/CMakeLists.txt new file mode 100644 index 00000000..605c70e7 --- /dev/null +++ b/airspy_source/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.13) +project(airspy_source) + +if (MSVC) + set(CMAKE_CXX_FLAGS "-O2 /std:c++17 /EHsc") +else() + set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive") +endif (MSVC) + +include_directories("src/") + +file(GLOB SRC "src/*.cpp") + +add_library(airspy_source SHARED ${SRC}) +target_link_libraries(airspy_source PRIVATE sdrpp_core) +set_target_properties(airspy_source PROPERTIES PREFIX "") + +if (MSVC) + # Lib path + target_link_directories(sdrpp_core PUBLIC "C:/Program Files/PothosSDR/bin/") + + target_link_libraries(airspy_source PUBLIC airspy) +else (MSVC) + find_package(PkgConfig) + + pkg_check_modules(LIBAIRSPYHF REQUIRED libairspy) + + target_include_directories(airspy_source PUBLIC ${LIBAIRSPYHF_INCLUDE_DIRS}) + target_link_directories(airspy_source PUBLIC ${LIBAIRSPYHF_LIBRARY_DIRS}) + target_link_libraries(airspy_source PUBLIC ${LIBAIRSPYHF_LIBRARIES}) +endif (MSVC) \ No newline at end of file diff --git a/airspy_source/src/main.cpp b/airspy_source/src/main.cpp new file mode 100644 index 00000000..8b411721 --- /dev/null +++ b/airspy_source/src/main.cpp @@ -0,0 +1,426 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONCAT(a, b) ((std::string(a) + b).c_str()) + +SDRPP_MOD_INFO { + /* Name: */ "airspy_source", + /* Description: */ "Airspy source module for SDR++", + /* Author: */ "Ryzerth", + /* Version: */ 0, 1, 0, + /* Max instances */ 1 +}; + +class AirspySourceModule : public ModuleManager::Instance { +public: + AirspySourceModule(std::string name) { + this->name = name; + + sampleRate = 10000000.0; + + handler.ctx = this; + handler.selectHandler = menuSelected; + handler.deselectHandler = menuDeselected; + handler.menuHandler = menuHandler; + handler.startHandler = start; + handler.stopHandler = stop; + handler.tuneHandler = tune; + handler.stream = &stream; + + refresh(); + + selectFirst(); + + sigpath::sourceManager.registerSource("Airspy", &handler); + } + + ~AirspySourceModule() { + + } + + void enable() { + enabled = true; + } + + void disable() { + enabled = false; + } + + bool isEnabled() { + return enabled; + } + + void refresh() { + devList.clear(); + devListTxt = ""; + + uint64_t serials[256]; + int n = airspy_list_devices(serials, 256); + + char buf[1024]; + for (int i = 0; i < n; i++) { + sprintf(buf, "%016" PRIX64, serials[i]); + devList.push_back(serials[i]); + devListTxt += buf; + devListTxt += '\0'; + } + } + + void selectFirst() { + if (devList.size() != 0) { + selectBySerial(devList[0]); + } + } + + void selectByString(std::string serial) { + char buf[1024]; + for (int i = 0; i < devList.size(); i++) { + sprintf(buf, "%016" PRIX64, devList[i]); + std::string str = buf; + if (serial == str) { + selectBySerial(devList[i]); + return; + } + } + selectFirst(); + } + + void selectBySerial(uint64_t serial) { + selectedSerial = serial; + airspy_device* dev; + int err = airspy_open_sn(&dev, selectedSerial); + if (err != 0) { + char buf[1024]; + sprintf(buf, "%016" PRIX64, selectedSerial); + spdlog::error("Could not open Airspy HF+ {0}", buf); + return; + } + + uint32_t sampleRates[256]; + airspy_get_samplerates(dev, sampleRates, 0); + int n = sampleRates[0]; + airspy_get_samplerates(dev, sampleRates, n); + char buf[1024]; + sampleRateList.clear(); + sampleRateListTxt = ""; + for (int i = 0; i < n; i++) { + sampleRateList.push_back(sampleRates[i]); + sprintf(buf, "%d", sampleRates[i]); + sampleRateListTxt += buf; + sampleRateListTxt += '\0'; + } + + srId = 0; + + airspy_close(dev); + } + +private: + static void menuSelected(void* ctx) { + AirspySourceModule* _this = (AirspySourceModule*)ctx; + core::setInputSampleRate(_this->sampleRate); + spdlog::info("AirspySourceModule '{0}': Menu Select!", _this->name); + } + + static void menuDeselected(void* ctx) { + AirspySourceModule* _this = (AirspySourceModule*)ctx; + spdlog::info("AirspySourceModule '{0}': Menu Deselect!", _this->name); + } + + static void start(void* ctx) { + AirspySourceModule* _this = (AirspySourceModule*)ctx; + if (_this->running) { + return; + } + if (_this->selectedSerial == 0) { + spdlog::error("Tried to start AirspyHF+ source with null serial"); + return; + } + + int err = airspy_open_sn(&_this->openDev, _this->selectedSerial); + if (err != 0) { + char buf[1024]; + sprintf(buf, "%016" PRIX64, _this->selectedSerial); + spdlog::error("Could not open Airspy {0}", buf); + return; + } + + airspy_set_samplerate(_this->openDev, _this->sampleRateList[_this->srId]); + airspy_set_freq(_this->openDev, _this->freq); + + if (_this->gainMode == 0) { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_sensitivity_gain(_this->openDev, _this->sensitiveGain); + } + else if (_this->gainMode == 1) { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_linearity_gain(_this->openDev, _this->linearGain); + } + else if (_this->gainMode == 2) { + if (_this->lnaAgc) { + airspy_set_lna_agc(_this->openDev, 1); + } + else { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_lna_gain(_this->openDev, _this->lnaGain); + } + if (_this->mixerAgc) { + airspy_set_mixer_agc(_this->openDev, 1); + } + else { + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_mixer_gain(_this->openDev, _this->mixerGain); + } + airspy_set_vga_gain(_this->openDev, _this->vgaGain); + } + + airspy_set_rf_bias(_this->openDev, _this->biasT); + + airspy_start_rx(_this->openDev, callback, _this); + + _this->running = true; + spdlog::info("AirspySourceModule '{0}': Start!", _this->name); + } + + static void stop(void* ctx) { + AirspySourceModule* _this = (AirspySourceModule*)ctx; + if (!_this->running) { + return; + } + _this->running = false; + _this->stream.stopWriter(); + airspy_close(_this->openDev); + _this->stream.clearWriteStop(); + spdlog::info("AirspySourceModule '{0}': Stop!", _this->name); + } + + static void tune(double freq, void* ctx) { + AirspySourceModule* _this = (AirspySourceModule*)ctx; + if (_this->running) { + airspy_set_freq(_this->openDev, freq); + } + _this->freq = freq; + spdlog::info("AirspySourceModule '{0}': Tune: {1}!", _this->name, freq); + } + + static void menuHandler(void* ctx) { + AirspySourceModule* _this = (AirspySourceModule*)ctx; + float menuWidth = ImGui::GetContentRegionAvailWidth(); + + if (_this->running) { style::beginDisabled(); } + + ImGui::SetNextItemWidth(menuWidth); + if (ImGui::Combo(CONCAT("##_airspy_dev_sel_", _this->name), &_this->devId, _this->devListTxt.c_str())) { + _this->selectBySerial(_this->devList[_this->devId]); + } + + if (ImGui::Combo(CONCAT("##_airspy_sr_sel_", _this->name), &_this->srId, _this->sampleRateListTxt.c_str())) { + _this->sampleRate = _this->sampleRateList[_this->srId]; + core::setInputSampleRate(_this->sampleRate); + } + + ImGui::SameLine(); + float refreshBtnWdith = menuWidth - ImGui::GetCursorPosX(); + if (ImGui::Button(CONCAT("Refresh##_airspy_refr_", _this->name), ImVec2(refreshBtnWdith, 0))) { + _this->refresh(); + _this->selectFirst(); + } + + if (_this->running) { style::endDisabled(); } + + ImGui::BeginGroup(); + ImGui::Columns(3, CONCAT("AirspyGainModeColumns##_", _this->name), false); + if (ImGui::RadioButton(CONCAT("Sensitive##_airspy_gm_", _this->name), _this->gainMode == 0)) { + _this->gainMode = 0; + if (_this->running) { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_sensitivity_gain(_this->openDev, _this->sensitiveGain); + } + } + ImGui::NextColumn(); + if (ImGui::RadioButton(CONCAT("Linear##_airspy_gm_", _this->name), _this->gainMode == 1)) { + _this->gainMode = 1; + if (_this->running) { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_linearity_gain(_this->openDev, _this->linearGain); + } + } + ImGui::NextColumn(); + if (ImGui::RadioButton(CONCAT("Free##_airspy_gm_", _this->name), _this->gainMode == 2)) { + _this->gainMode = 2; + if (_this->running) { + if (_this->lnaAgc) { + airspy_set_lna_agc(_this->openDev, 1); + } + else { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_lna_gain(_this->openDev, _this->lnaGain); + } + if (_this->mixerAgc) { + airspy_set_mixer_agc(_this->openDev, 1); + } + else { + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_mixer_gain(_this->openDev, _this->mixerGain); + } + airspy_set_vga_gain(_this->openDev, _this->vgaGain); + } + } + ImGui::Columns(1, CONCAT("EndAirspyGainModeColumns##_", _this->name), false); + ImGui::EndGroup(); + + // Gain menus + + if (_this->gainMode == 0) { + ImGui::Text("Gain"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::SliderInt(CONCAT("##_airspy_sens_gain_", _this->name), &_this->sensitiveGain, 0, 21)) { + if (_this->running) { + airspy_set_sensitivity_gain(_this->openDev, _this->sensitiveGain); + } + } + } + else if (_this->gainMode == 1) { + ImGui::Text("Gain"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::SliderInt(CONCAT("##_airspy_lin_gain_", _this->name), &_this->linearGain, 0, 21)) { + if (_this->running) { + airspy_set_linearity_gain(_this->openDev, _this->linearGain); + } + } + } + else if (_this->gainMode == 2) { + if (_this->lnaAgc) { style::beginDisabled(); } + ImGui::Text("LNA Gain"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::SliderInt(CONCAT("##_airspy_lna_gain_", _this->name), &_this->lnaGain, 0, 15)) { + if (_this->running) { + airspy_set_lna_gain(_this->openDev, _this->lnaGain); + } + } + if (_this->lnaAgc) { style::endDisabled(); } + + if (_this->mixerAgc) { style::beginDisabled(); } + ImGui::Text("Mixer Gain"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::SliderInt(CONCAT("##_airspy_mix_gain_", _this->name), &_this->mixerGain, 0, 15)) { + if (_this->running) { + airspy_set_mixer_gain(_this->openDev, _this->mixerGain); + } + } + if (_this->mixerAgc) { style::endDisabled(); } + + ImGui::Text("VGA Gain"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX()); + if (ImGui::SliderInt(CONCAT("##_airspy_vga_gain_", _this->name), &_this->vgaGain, 0, 15)) { + if (_this->running) { + airspy_set_vga_gain(_this->openDev, _this->vgaGain); + } + } + + // AGC Control + if (ImGui::Checkbox(CONCAT("LNA AGC##_airspy_", _this->name), &_this->lnaAgc)) { + if (_this->running) { + if (_this->lnaAgc) { + airspy_set_lna_agc(_this->openDev, 1); + } + else { + airspy_set_lna_agc(_this->openDev, 0); + airspy_set_lna_gain(_this->openDev, _this->lnaGain); + } + } + } + + if (ImGui::Checkbox(CONCAT("Mixer AGC##_airspy_", _this->name), &_this->mixerAgc)) { + if (_this->running) { + if (_this->mixerAgc) { + airspy_set_mixer_agc(_this->openDev, 1); + } + else { + airspy_set_mixer_agc(_this->openDev, 0); + airspy_set_mixer_gain(_this->openDev, _this->mixerGain); + } + } + } + } + + // Bias T + + if (ImGui::Checkbox(CONCAT("Bias T##_airspy_", _this->name), &_this->biasT)) { + if (_this->running) { + airspy_set_rf_bias(_this->openDev, _this->biasT); + } + } + + + } + + static int callback(airspy_transfer_t* transfer) { + AirspySourceModule* _this = (AirspySourceModule*)transfer->ctx; + memcpy(_this->stream.writeBuf, transfer->samples, transfer->sample_count * sizeof(dsp::complex_t)); + if (!_this->stream.swap(transfer->sample_count)) { return -1; } + return 0; + } + + std::string name; + airspy_device* openDev; + bool enabled = true; + dsp::stream stream; + double sampleRate; + SourceManager::SourceHandler handler; + bool running = false; + double freq; + uint64_t selectedSerial = 0; + int devId = 0; + int srId = 0; + + bool biasT = false; + + int lnaGain = 0; + int vgaGain = 0; + int mixerGain = 0; + int linearGain = 0; + int sensitiveGain = 0; + + int gainMode = 0; + + bool lnaAgc = false; + bool mixerAgc = false; + + std::vector devList; + std::string devListTxt; + std::vector sampleRateList; + std::string sampleRateListTxt; +}; + +MOD_EXPORT void _INIT_() { + +} + +MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { + return new AirspySourceModule(name); +} + +MOD_EXPORT void _DELETE_INSTANCE_(ModuleManager::Instance* instance) { + delete (AirspySourceModule*)instance; +} + +MOD_EXPORT void _END_() { + +} \ No newline at end of file diff --git a/core/src/gui/main_window.cpp b/core/src/gui/main_window.cpp index ca147e3d..e1abb501 100644 --- a/core/src/gui/main_window.cpp +++ b/core/src/gui/main_window.cpp @@ -462,7 +462,7 @@ void drawWindow() { gui::freqSelect.draw(); - //ImGui::SameLine(); + ImGui::SameLine(); ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 9); if (centerTuning) { diff --git a/core/src/gui/style.cpp b/core/src/gui/style.cpp index 6ba917b6..fff09fe8 100644 --- a/core/src/gui/style.cpp +++ b/core/src/gui/style.cpp @@ -25,7 +25,7 @@ namespace style { ImGui::GetStyle().ScrollbarRounding = 0.0f; baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 16.0f); - bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 42.0f); + bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 45.0f); hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f); ImGui::StyleColorsDark(); @@ -52,7 +52,7 @@ namespace style { ImGui::GetStyle().ScrollbarRounding = 0.0f; baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 16.0f); - bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 42.0f); + bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 45.0f); hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f); ImGui::StyleColorsDark(); diff --git a/core/src/gui/widgets/frequency_select.cpp b/core/src/gui/widgets/frequency_select.cpp index ba611bb2..2982a8b3 100644 --- a/core/src/gui/widgets/frequency_select.cpp +++ b/core/src/gui/widgets/frequency_select.cpp @@ -2,6 +2,11 @@ #include #include +#ifndef IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS +#endif +#include + bool isInArea(ImVec2 val, ImVec2 min, ImVec2 max) { return val.x >= min.x && val.x < max.x && val.y >= min.y && val.y < max.y; } @@ -18,17 +23,20 @@ void FrequencySelect::init() { } void FrequencySelect::onPosChange() { - int digitHeight = ImGui::CalcTextSize("0").y; + ImVec2 digitSz = ImGui::CalcTextSize("0"); + ImVec2 commaSz = ImGui::CalcTextSize("."); + int digitHeight = digitSz.y; + int digitWidth = digitSz.x; int commaOffset = 0; for (int i = 0; i < 12; i++) { - digitTopMins[i] = ImVec2(widgetPos.x + (i * 22) + commaOffset, widgetPos.y); - digitBottomMins[i] = ImVec2(widgetPos.x + (i * 22) + commaOffset, widgetPos.y + (digitHeight / 2)); + digitTopMins[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset, widgetPos.y); + digitBottomMins[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset, widgetPos.y + (digitHeight / 2)); - digitTopMaxs[i] = ImVec2(widgetPos.x + (i * 22) + commaOffset + 22, widgetPos.y + (digitHeight / 2)); - digitBottomMaxs[i] = ImVec2(widgetPos.x + (i * 22) + commaOffset + 22, widgetPos.y + digitHeight); + digitTopMaxs[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + digitWidth, widgetPos.y + (digitHeight / 2)); + digitBottomMaxs[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + digitWidth, widgetPos.y + digitHeight); if ((i + 1) % 3 == 0 && i < 11) { - commaOffset += 12; + commaOffset += commaSz.x; } } } @@ -90,18 +98,25 @@ void FrequencySelect::draw() { ImU32 disabledColor = ImGui::GetColorU32(ImGuiCol_Text, 0.3f); ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); + ImVec2 digitSz = ImGui::CalcTextSize("0"); + ImVec2 commaSz = ImGui::CalcTextSize("."); + int digitHeight = digitSz.y; + int digitWidth = digitSz.x; int commaOffset = 0; bool zeros = true; + + ImGui::ItemSize(ImRect(digitTopMins[0], ImVec2(digitBottomMaxs[11].x + 15, digitBottomMaxs[11].y))); + for (int i = 0; i < 12; i++) { if (digits[i] != 0) { zeros = false; } sprintf(buf, "%d", digits[i]); - window->DrawList->AddText(ImVec2(widgetPos.x + (i * 22) + commaOffset, widgetPos.y), + window->DrawList->AddText(ImVec2(widgetPos.x + (i * digitWidth) + commaOffset, widgetPos.y), zeros ? disabledColor : textColor, buf); if ((i + 1) % 3 == 0 && i < 11) { - commaOffset += 12; - window->DrawList->AddText(ImVec2(widgetPos.x + (i * 22) + commaOffset + 10, widgetPos.y), + commaOffset += commaSz.x; + window->DrawList->AddText(ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + 11, widgetPos.y), zeros ? disabledColor : textColor, "."); } } diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index 9db2227a..17b27cb6 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -347,6 +347,7 @@ namespace ImGui { cPos = widgetPos.x + 50 + ((center - lowerFreq) * horizScale); width = bPos - aPos; txtSz = ImGui::CalcTextSize(bandplan->bands[i].name.c_str()); + float height = txtSz.y * 2.5f; if (bandplan::colorTable.find(bandplan->bands[i].type.c_str()) != bandplan::colorTable.end()) { color = bandplan::colorTable[bandplan->bands[i].type].colorValue; colorTrans = bandplan::colorTable[bandplan->bands[i].type].transColorValue; @@ -362,19 +363,19 @@ namespace ImGui { bPos = widgetPos.x + 51; } if (width >= 1.0) { - window->DrawList->AddRectFilled(ImVec2(roundf(aPos), widgetPos.y + fftHeight - 25), + window->DrawList->AddRectFilled(ImVec2(roundf(aPos), widgetPos.y + fftHeight + 10 - height), ImVec2(roundf(bPos), widgetPos.y + fftHeight + 10), colorTrans); if (startVis) { - window->DrawList->AddLine(ImVec2(roundf(aPos), widgetPos.y + fftHeight - 26), + window->DrawList->AddLine(ImVec2(roundf(aPos), widgetPos.y + fftHeight + 10 - height - 1), ImVec2(roundf(aPos), widgetPos.y + fftHeight + 9), color); } if (endVis) { - window->DrawList->AddLine(ImVec2(roundf(bPos), widgetPos.y + fftHeight - 26), + window->DrawList->AddLine(ImVec2(roundf(bPos), widgetPos.y + fftHeight + 10 - height - 1), ImVec2(roundf(bPos), widgetPos.y + fftHeight + 9), color); } } if (txtSz.x <= width) { - window->DrawList->AddText(ImVec2(cPos - (txtSz.x / 2.0), widgetPos.y + fftHeight - 17), + window->DrawList->AddText(ImVec2(cPos - (txtSz.x / 2.0), widgetPos.y + fftHeight + 10 - (height / 2.0f) - (txtSz.y / 2.0f)), IM_COL32(255, 255, 255, 255), bandplan->bands[i].name.c_str()); } }