Backend abstraction + added android support + partial high DPI scaling

This commit is contained in:
AlexandreRouma
2022-02-13 17:25:23 +01:00
parent 9969ce018b
commit e5f3d1672c
36 changed files with 693 additions and 185 deletions

View File

@ -21,6 +21,10 @@ endif ()
if (OPT_BACKEND_GLFW)
file(GLOB_RECURSE BACKEND_SRC "backends/glfw/*.cpp" "backends/glfw/*.c")
endif (OPT_BACKEND_GLFW)
if (OPT_BACKEND_ANDROID)
file(GLOB_RECURSE BACKEND_SRC "backends/android/*.cpp" "backends/android/*.c")
set(BACKEND_SRC ${BACKEND_SRC} ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
endif (OPT_BACKEND_ANDROID)
# Add code to dyn lib
add_library(sdrpp_core SHARED ${SRC} ${BACKEND_SRC})
@ -59,6 +63,10 @@ if (OPT_BACKEND_GLFW)
target_link_libraries(sdrpp_core PUBLIC ${GLFW3_LIBRARIES})
endif()
endif (OPT_BACKEND_GLFW)
if (OPT_BACKEND_ANDROID)
target_include_directories(sdrpp_core PUBLIC "backends/android")
target_include_directories(sdrpp_core PUBLIC "backends/android/imgui")
endif (OPT_BACKEND_ANDROID)
# Link to libcorrect
if (USE_INTERNAL_LIBCORRECT)
@ -98,7 +106,24 @@ if (MSVC)
# ZSTD
find_package(zstd CONFIG REQUIRED)
target_link_libraries(sdrpp_core PUBLIC zstd::libzstd_shared)
elseif (ANDROID)
target_include_directories(sdrpp_core PUBLIC
../android/deps/volk/jni
../android/deps/fftw3/jni
/mnt/android_sdr/zstd/lib
${ANDROID_NDK}/sources/android/native_app_glue
)
target_link_libraries(sdrpp_core PUBLIC
${PROJECT_SOURCE_DIR}/../android/deps/volk/${ANDROID_ABI}/libcpu_features.a
${PROJECT_SOURCE_DIR}/../android/deps/volk/${ANDROID_ABI}/libvolk.so
${PROJECT_SOURCE_DIR}/../android/deps/fftw3/${ANDROID_ABI}/libfftw3f.a
/mnt/android_sdr/output/zstd/${ANDROID_ABI}/libzstd.so
android
EGL
GLESv3
log
)
else()
find_package(PkgConfig)
find_package(OpenGL REQUIRED)

View File

@ -21,4 +21,7 @@
#define KB_KEY_LCTRL GLFW_KEY_LEFT_CONTROL
#define KB_KEY_RCTRL GLFW_KEY_RIGHT_CONTROL
#define KB_KEY_LSHIFT GLFW_KEY_LEFT_SHIFT
#define KB_KEY_RSHIFT GLFW_KEY_RIGHT_SHIFT
#define KB_KEY_RSHIFT GLFW_KEY_RIGHT_SHIFT
#define KB_KEY_A GLFW_KEY_A
#define KB_KEY_R GLFW_KEY_R

View File

@ -2,7 +2,7 @@
#include <string>
namespace backend {
int init(std::string resDir);
int init(std::string resDir = "");
void beginFrame();
void render(bool vsync = true);
void getMouseScreenPos(double& x, double& y);

View File

@ -1,7 +1,5 @@
#include <server.h>
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <stdio.h>
#include <gui/main_window.h>
#include <gui/style.h>
@ -188,6 +186,7 @@ int sdrpp_main(int argc, char* argv[]) {
defConfig["theme"] = "Dark";
defConfig["modules"] = json::array();
defConfig["offsetMode"] = (int)0; // Off
defConfig["offset"] = 0.0;
defConfig["showMenu"] = true;
@ -213,6 +212,9 @@ int sdrpp_main(int argc, char* argv[]) {
#elif defined(IS_MACOS_BUNDLE)
defConfig["modulesDirectory"] = "../Plugins";
defConfig["resourcesDirectory"] = "../Resources";
#elif defined(__ANDROID__)
defConfig["modulesDirectory"] = options::opts.root + "/modules";
defConfig["resourcesDirectory"] = options::opts.root + "/res";
#else
defConfig["modulesDirectory"] = INSTALL_PREFIX "/lib/sdrpp/plugins";
defConfig["resourcesDirectory"] = INSTALL_PREFIX "/share/sdrpp";
@ -223,8 +225,33 @@ int sdrpp_main(int argc, char* argv[]) {
core::configManager.setPath(options::opts.root + "/config.json");
core::configManager.load(defConfig);
core::configManager.enableAutoSave();
core::configManager.acquire();
// 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";
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";
#endif
// Fix missing elements in config
for (auto const& item : defConfig.items()) {
if (!core::configManager.conf.contains(item.key())) {
@ -274,6 +301,7 @@ int sdrpp_main(int argc, char* argv[]) {
if (!style::loadFonts(resDir)) { return -1; }
thememenu::init(resDir);
LoadingScreen::init();
LoadingScreen::show("Loading icons");
spdlog::info("Loading icons");
@ -294,6 +322,8 @@ int sdrpp_main(int argc, char* argv[]) {
// Run render loop (TODO: CHECK RETURN VALUE)
backend::renderLoop();
// 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();
@ -306,6 +336,7 @@ int sdrpp_main(int argc, char* argv[]) {
core::configManager.disableAutoSave();
core::configManager.save();
#endif
return 0;
}

View File

@ -8,8 +8,10 @@
namespace credits {
ImFont* bigFont;
ImVec2 imageSize(128.0f, 128.0f);
void init() {
imageSize = ImVec2(128.0f * style::uiScale, 128.0f * style::uiScale);
}
void show() {
@ -25,7 +27,7 @@ namespace credits {
ImGui::TextUnformatted("SDR++ ");
ImGui::PopFont();
ImGui::SameLine();
ImGui::Image(icons::LOGO, ImVec2(128, 128));
ImGui::Image(icons::LOGO, imageSize);
ImGui::Spacing();
ImGui::Spacing();
ImGui::Spacing();

View File

@ -1,8 +1,6 @@
#include <gui/dialogs/loading_screen.h>
#include <gui/main_window.h>
#include <imgui.h>
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <gui/icons.h>
#include <gui/style.h>
#include <credits.h>
@ -10,6 +8,11 @@
#include <backend.h>
namespace LoadingScreen {
ImVec2 imageSize(128.0f, 128.0f);
void init() {
imageSize = ImVec2(128.0f * style::uiScale, 128.0f * style::uiScale);
}
void show(std::string msg) {
backend::beginFrame();
@ -26,7 +29,7 @@ namespace LoadingScreen {
ImGui::TextUnformatted("SDR++ ");
ImGui::PopFont();
ImGui::SameLine();
ImGui::Image(icons::LOGO, ImVec2(128, 128));
ImGui::Image(icons::LOGO, imageSize);
ImVec2 origPos = ImGui::GetCursorPos();
ImGui::SetCursorPosY(origPos.y + 50);

View File

@ -4,5 +4,6 @@
#include <mutex>
namespace LoadingScreen {
void init();
void show(std::string msg);
};

View File

@ -1,8 +1,6 @@
#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 <thread>
#include <complex>
@ -126,10 +124,14 @@ void MainWindow::init() {
// Load additional modules specified through config
for (auto const& path : modules) {
#ifndef __ANDROID__
std::string apath = std::filesystem::absolute(path).string();
spdlog::info("Loading {0}", apath);
LoadingScreen::show("Loading " + std::filesystem::path(path).filename().string());
core::moduleManager.loadModule(apath);
#else
core::moduleManager.loadModule(path);
#endif
}
// Create module instances
@ -354,8 +356,9 @@ void MainWindow::draw() {
}
// To Bar
ImVec2 btnSize(30 * style::uiScale, 30 * style::uiScale);
ImGui::PushID(ImGui::GetID("sdrpp_menu_btn"));
if (ImGui::ImageButton(icons::MENU, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_MENU, false)) {
if (ImGui::ImageButton(icons::MENU, btnSize, ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_MENU, false)) {
showMenu = !showMenu;
core::configManager.acquire();
core::configManager.conf["showMenu"] = showMenu;
@ -369,14 +372,14 @@ void MainWindow::draw() {
if (playButtonLocked && !tmpPlaySate) { style::beginDisabled(); }
if (playing) {
ImGui::PushID(ImGui::GetID("sdrpp_stop_btn"));
if (ImGui::ImageButton(icons::STOP, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_END, false)) {
if (ImGui::ImageButton(icons::STOP, btnSize, ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_END, false)) {
setPlayState(false);
}
ImGui::PopID();
}
else { // TODO: Might need to check if there even is a device
ImGui::PushID(ImGui::GetID("sdrpp_play_btn"));
if (ImGui::ImageButton(icons::PLAY, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_END, false)) {
if (ImGui::ImageButton(icons::PLAY, btnSize, ImVec2(0, 0), ImVec2(1, 1), 5) || ImGui::IsKeyPressed(KB_KEY_END, false)) {
setPlayState(true);
}
ImGui::PopID();
@ -384,20 +387,21 @@ void MainWindow::draw() {
if (playButtonLocked && !tmpPlaySate) { style::endDisabled(); }
ImGui::SameLine();
float origY = ImGui::GetCursorPosY();
//ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8);
sigpath::sinkManager.showVolumeSlider(gui::waterfall.selectedVFO, "##_sdrpp_main_volume_", 248, 30, 5, true);
sigpath::sinkManager.showVolumeSlider(gui::waterfall.selectedVFO, "##_sdrpp_main_volume_", 248 * style::uiScale, btnSize.x, 5, true);
ImGui::SameLine();
ImGui::SetCursorPosY(origY);
gui::freqSelect.draw();
ImGui::SameLine();
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 9);
ImGui::SetCursorPosY(origY);
if (tuningMode == tuner::TUNER_MODE_CENTER) {
ImGui::PushID(ImGui::GetID("sdrpp_ena_st_btn"));
if (ImGui::ImageButton(icons::CENTER_TUNING, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5)) {
if (ImGui::ImageButton(icons::CENTER_TUNING, btnSize, ImVec2(0, 0), ImVec2(1, 1), 5)) {
tuningMode = tuner::TUNER_MODE_NORMAL;
gui::waterfall.VFOMoveSingleClick = false;
core::configManager.acquire();
@ -408,7 +412,7 @@ void MainWindow::draw() {
}
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)) {
if (ImGui::ImageButton(icons::NORMAL_TUNING, btnSize, ImVec2(0, 0), ImVec2(1, 1), 5)) {
tuningMode = tuner::TUNER_MODE_CENTER;
gui::waterfall.VFOMoveSingleClick = true;
tuner::tune(tuner::TUNER_MODE_CENTER, gui::waterfall.selectedVFO, gui::freqSelect.frequency);
@ -421,19 +425,20 @@ void MainWindow::draw() {
ImGui::SameLine();
int snrWidth = std::min<int>(300, ImGui::GetWindowSize().x - ImGui::GetCursorPosX() - 87);
int snrOffset = 87.0f * style::uiScale;
int snrWidth = std::min<int>(300.0f * style::uiScale, ImGui::GetWindowSize().x - ImGui::GetCursorPosX() - snrOffset);
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - (snrWidth + 87));
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - (snrWidth + snrOffset));
ImGui::SetCursorPosY(origY + (5.0f * style::uiScale));
ImGui::SetNextItemWidth(snrWidth);
ImGui::SNRMeter((vfo != NULL) ? gui::waterfall.selectedVFOSNR : 0);
ImGui::SameLine();
// 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)) {
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - (48 * style::uiScale));
ImGui::SetCursorPosY(10 * style::uiScale);
if (ImGui::ImageButton(icons::LOGO, ImVec2(32 * style::uiScale, 32 * style::uiScale), ImVec2(0, 0), ImVec2(1, 1), 0)) {
showCredits = true;
}
if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
@ -455,7 +460,7 @@ void MainWindow::draw() {
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) {
if (mousePos.x >= newWidth - (2.0f * style::uiScale) && mousePos.x <= newWidth + (2.0f * style::uiScale) && mousePos.y > curY) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
if (click) {
grabbingMenu = true;
@ -479,8 +484,8 @@ void MainWindow::draw() {
if (showMenu) {
ImGui::Columns(3, "WindowColumns", false);
ImGui::SetColumnWidth(0, menuWidth);
ImGui::SetColumnWidth(1, winSize.x - menuWidth - 60);
ImGui::SetColumnWidth(2, 60);
ImGui::SetColumnWidth(1, winSize.x - menuWidth - (60.0f * style::uiScale));
ImGui::SetColumnWidth(2, 60.0f * style::uiScale);
ImGui::BeginChild("Left Column");
if (gui::menu.draw(firstMenuRender)) {
@ -513,7 +518,7 @@ void MainWindow::draw() {
ImGui::Text("Center Frequency: %.0f Hz", gui::waterfall.getCenterFrequency());
ImGui::Text("Source name: %s", sourceName.c_str());
ImGui::Checkbox("Show demo window", &demoWindow);
ImGui::Text("ImGui version: %s", ImGui::GetVersion());
ImGui::Text("ImGui version: %s_feb_2022", ImGui::GetVersion());
ImGui::Checkbox("Bypass buffering", &sigpath::signalPath.inputBuffer.bypass);
@ -538,9 +543,9 @@ void MainWindow::draw() {
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);
ImGui::SetColumnWidth(0, 8 * style::uiScale);
ImGui::SetColumnWidth(1, winSize.x - ((8 + 60) * style::uiScale));
ImGui::SetColumnWidth(2, 60.0f * style::uiScale);
}
// Right Column
@ -602,8 +607,9 @@ void MainWindow::draw() {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Zoom").x / 2.0));
ImGui::TextUnformatted("Zoom");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
if (ImGui::VSliderFloat("##_7_", ImVec2(20.0, 150.0), &bw, 1.0, 0.0, "")) {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10 * style::uiScale);
ImVec2 wfSliderSize(20.0 * style::uiScale, 150.0 * style::uiScale);
if (ImGui::VSliderFloat("##_7_", wfSliderSize, &bw, 1.0, 0.0, "")) {
double factor = (double)bw * (double)bw;
// Map 0.0 -> 1.0 to 1000.0 -> bandwidth
@ -621,8 +627,8 @@ void MainWindow::draw() {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Max").x / 2.0));
ImGui::TextUnformatted("Max");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
if (ImGui::VSliderFloat("##_8_", ImVec2(20.0, 150.0), &fftMax, 0.0, -160.0f, "")) {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10 * style::uiScale);
if (ImGui::VSliderFloat("##_8_", wfSliderSize, &fftMax, 0.0, -160.0f, "")) {
fftMax = std::max<float>(fftMax, fftMin + 10);
core::configManager.acquire();
core::configManager.conf["max"] = fftMax;
@ -633,8 +639,8 @@ void MainWindow::draw() {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - (ImGui::CalcTextSize("Min").x / 2.0));
ImGui::TextUnformatted("Min");
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10);
if (ImGui::VSliderFloat("##_9_", ImVec2(20.0, 150.0), &fftMin, 0.0, -160.0f, "")) {
ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0) - 10 * style::uiScale);
if (ImGui::VSliderFloat("##_9_", wfSliderSize, &fftMin, 0.0, -160.0f, "")) {
fftMin = std::min<float>(fftMax - 10, fftMin);
core::configManager.acquire();
core::configManager.conf["min"] = fftMin;
@ -707,4 +713,8 @@ void MainWindow::setFFTWindow(int win) {
bool MainWindow::isPlaying() {
return playing;
}
void MainWindow::setFirstMenuRender() {
firstMenuRender = true;
}

View File

@ -19,6 +19,7 @@ public:
bool sdrIsRunning();
void setFFTSize(int size);
void setFFTWindow(int win);
void setFirstMenuRender();
// TODO: Replace with it's own class
void setVFO(double freq);

View File

@ -23,8 +23,11 @@ namespace thememenu {
it = std::find(themeNames.begin(), themeNames.end(), "Dark");
selectedThemeName = "Dark";
}
gui::themeManager.applyTheme(selectedThemeName);
themeId = std::distance(themeNames.begin(), it);
applyTheme();
// Apply scaling
ImGui::GetStyle().ScaleAllSizes(style::uiScale);
themeNamesTxt = "";
for (auto name : themeNames) {
@ -33,12 +36,16 @@ namespace thememenu {
}
}
void applyTheme() {
gui::themeManager.applyTheme(themeNames[themeId]);
}
void draw(void* ctx) {
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGui::LeftLabel("Theme");
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::Combo("##theme_select_combo", &themeId, themeNamesTxt.c_str())) {
gui::themeManager.applyTheme(themeNames[themeId]);
applyTheme();
core::configManager.acquire();
core::configManager.conf["theme"] = themeNames[themeId];
core::configManager.release(true);

View File

@ -3,5 +3,6 @@
namespace thememenu {
void init(std::string resDir);
void applyTheme();
void draw(void* ctx);
}

View File

@ -11,15 +11,21 @@ namespace style {
ImFont* bigFont;
ImFont* hugeFont;
#ifndef __ANDROID__
float uiScale = 1.0f;
#else
float uiScale = 3.0f;
#endif
bool loadFonts(std::string resDir) {
if (!std::filesystem::is_directory(resDir)) {
spdlog::error("Invalid resource directory: {0}", resDir);
return false;
}
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(), 45.0f);
hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f);
baseFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 16.0f * uiScale);
bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 45.0f * uiScale);
hugeFont = ImGui::GetIO().Fonts->AddFontFromFileTTF(((std::string)(resDir + "/fonts/Roboto-Medium.ttf")).c_str(), 128.0f * uiScale);
return true;
}

View File

@ -7,6 +7,8 @@ namespace style {
extern ImFont* bigFont;
extern ImFont* hugeFont;
extern float uiScale;
bool setDefaultStyle(std::string resDir);
bool loadFonts(std::string resDir);
void beginDisabled();

View File

@ -42,9 +42,6 @@ void FrequencySelect::onPosChange() {
}
}
void FrequencySelect::onResize() {
}
void FrequencySelect::incrementDigit(int i) {
if (i < 0) {
return;
@ -93,34 +90,27 @@ void FrequencySelect::moveCursorToDigit(int i) {
}
void FrequencySelect::draw() {
window = ImGui::GetCurrentWindow();
auto window = ImGui::GetCurrentWindow();
widgetPos = ImGui::GetWindowContentRegionMin();
widgetEndPos = ImGui::GetWindowContentRegionMax();
ImVec2 cursorPos = ImGui::GetCursorPos();
widgetPos.x += window->Pos.x + cursorPos.x;
widgetPos.y += window->Pos.y - 3;
widgetEndPos.x += window->Pos.x + cursorPos.x;
widgetEndPos.y += window->Pos.y - 3;
widgetSize = ImVec2(widgetEndPos.x - widgetPos.x, widgetEndPos.y - widgetPos.y);
ImGui::PushFont(style::bigFont);
ImVec2 digitSz = ImGui::CalcTextSize("0");
ImVec2 commaSz = ImGui::CalcTextSize(".");
widgetPos.y = cursorPos.y - ((digitSz.y / 2.0f) - ceilf(15 * style::uiScale) - 5);
if (widgetPos.x != lastWidgetPos.x || widgetPos.y != lastWidgetPos.y) {
lastWidgetPos = widgetPos;
onPosChange();
}
if (widgetSize.x != lastWidgetSize.x || widgetSize.y != lastWidgetSize.y) {
lastWidgetSize = widgetSize;
onResize();
}
ImU32 disabledColor = ImGui::GetColorU32(ImGuiCol_Text, 0.3f);
ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text);
ImVec2 digitSz = ImGui::CalcTextSize("0");
ImVec2 commaSz = ImGui::CalcTextSize(".");
int digitWidth = digitSz.x;
int commaOffset = 0;
float textOffset = 11.0f * style::uiScale;
bool zeros = true;
ImGui::ItemSize(ImRect(digitTopMins[0], ImVec2(digitBottomMaxs[11].x + 15, digitBottomMaxs[11].y)));
@ -134,7 +124,7 @@ void FrequencySelect::draw() {
zeros ? disabledColor : textColor, buf);
if ((i + 1) % 3 == 0 && i < 11) {
commaOffset += commaSz.x;
window->DrawList->AddText(ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + 11, widgetPos.y),
window->DrawList->AddText(ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + textOffset, widgetPos.y),
zeros ? disabledColor : textColor, ".");
}
}
@ -223,9 +213,7 @@ void FrequencySelect::draw() {
ImGui::PopFont();
ImGui::SetCursorPosX(digitBottomMaxs[11].x + 17);
//ImGui::NewLine();
ImGui::SetCursorPosX(digitBottomMaxs[11].x + (17.0f * style::uiScale));
}
void FrequencySelect::setFrequency(int64_t freq) {

View File

@ -26,13 +26,7 @@ private:
void moveCursorToDigit(int i);
ImVec2 widgetPos;
ImVec2 widgetEndPos;
ImVec2 widgetSize;
ImVec2 lastWidgetPos;
ImVec2 lastWidgetSize;
ImGuiWindow* window;
int digits[12];
ImVec2 digitBottomMins[12];

View File

@ -28,6 +28,7 @@ bool Menu::draw(bool updateStates) {
bool changed = false;
float menuWidth = ImGui::GetContentRegionAvailWidth();
ImGuiWindow* window = ImGui::GetCurrentWindow();
ImVec2 checkboxOffset = ImVec2(menuWidth - ImGui::GetTextLineHeight() - (6.0f * style::uiScale), - ImGui::GetTextLineHeight() - (10.0f * style::uiScale));
int displayedCount = 0;
int rawId = 0;
@ -46,6 +47,7 @@ bool Menu::draw(bool updateStates) {
continue;
}
// Draw dragged menu item
if (displayedCount == insertBefore && !draggedMenuName.empty()) {
if (updateStates) { ImGui::SetNextItemOpen(false); }
ImVec2 posMin = ImGui::GetCursorScreenPos();
@ -56,14 +58,14 @@ bool Menu::draw(bool updateStates) {
if (items[draggedOpt.name].inst != NULL) {
window->WorkRect = orignalRect;
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
ImGui::SetCursorPosX(pos.x + checkboxOffset.x);
ImGui::SetCursorPosY(pos.y + checkboxOffset.y);
bool enabled = items[draggedOpt.name].inst->isEnabled();
ImGui::Checkbox(("##_menu_checkbox_" + draggedOpt.name).c_str(), &enabled);
ImGui::SetCursorPos(pos);
}
style::endDisabled();
window->DrawList->AddRect(posMin, posMax, textColor);
window->DrawList->AddRect(posMin, posMax, textColor, 0.0f, 0, style::uiScale);
}
displayedCount++;
@ -72,7 +74,7 @@ bool Menu::draw(bool updateStates) {
ImRect orginalRect = window->WorkRect;
if (item.inst != NULL) {
window->WorkRect = ImRect(orginalRect.Min, ImVec2(orginalRect.Max.x - ImGui::GetTextLineHeight() - 6, orginalRect.Max.y));
window->WorkRect = ImRect(orginalRect.Min, ImVec2(orginalRect.Max.x - ImGui::GetTextLineHeight() - (6.0f * style::uiScale), orginalRect.Max.y));
}
ImVec2 posMin = ImGui::GetCursorScreenPos();
@ -93,13 +95,14 @@ bool Menu::draw(bool updateStates) {
continue;
}
// Draw menu header and menu content. There is a lot of boilerplate because the checkbox has to be drawn before the menu, TODO: fix
if (updateStates) { ImGui::SetNextItemOpen(opt.open); }
if (ImGui::CollapsingHeader((opt.name + "##sdrpp_main_menu").c_str())) {
if (item.inst != NULL) {
window->WorkRect = orginalRect;
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
ImGui::SetCursorPosX(pos.x + checkboxOffset.x);
ImGui::SetCursorPosY(pos.y + checkboxOffset.y);
bool enabled = item.inst->isEnabled();
if (ImGui::Checkbox(("##_menu_checkbox_" + opt.name).c_str(), &enabled)) {
enabled ? item.inst->enable() : item.inst->disable();
@ -120,8 +123,8 @@ bool Menu::draw(bool updateStates) {
else if (item.inst != NULL) {
window->WorkRect = orginalRect;
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
ImGui::SetCursorPosX(pos.x + checkboxOffset.x);
ImGui::SetCursorPosY(pos.y + checkboxOffset.y);
bool enabled = item.inst->isEnabled();
if (ImGui::Checkbox(("##_menu_checkbox_" + opt.name).c_str(), &enabled)) {
enabled ? item.inst->enable() : item.inst->disable();
@ -168,7 +171,7 @@ bool Menu::draw(bool updateStates) {
insertBefore = -1;
}
// TODO: Figure out why the hell this is needed
if (insertBefore == displayedCount && !draggedMenuName.empty()) {
if (updateStates) { ImGui::SetNextItemOpen(false); }
ImVec2 posMin = ImGui::GetCursorScreenPos();
@ -179,14 +182,14 @@ bool Menu::draw(bool updateStates) {
if (items[draggedOpt.name].inst != NULL) {
window->WorkRect = orignalRect;
ImVec2 pos = ImGui::GetCursorPos();
ImGui::SetCursorPosX(pos.x + menuWidth - ImGui::GetTextLineHeight() - 6);
ImGui::SetCursorPosY(pos.y - 10 - ImGui::GetTextLineHeight());
ImGui::SetCursorPosX(pos.x + checkboxOffset.x);
ImGui::SetCursorPosY(pos.y + checkboxOffset.y);
bool enabled = items[draggedOpt.name].inst->isEnabled();
ImGui::Checkbox(("##_menu_checkbox_" + draggedOpt.name).c_str(), &enabled);
ImGui::SetCursorPos(pos);
}
style::endDisabled();
window->DrawList->AddRect(posMin, posMax, textColor);
window->DrawList->AddRect(posMin, posMax, textColor, 0.0f, 0, style::uiScale);
}
if (!draggedMenuName.empty()) {

View File

@ -1,5 +1,6 @@
#include <gui/widgets/volume_meter.h>
#include <algorithm>
#include <gui/style.h>
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
@ -27,15 +28,15 @@ namespace ImGui {
float it = size.x / 9;
char buf[32];
window->DrawList->AddRectFilled(min + ImVec2(0, 1), min + ImVec2(roundf((float)val * ratio), 10), IM_COL32(0, 136, 255, 255));
window->DrawList->AddLine(min, min + ImVec2(0, 9), text);
window->DrawList->AddLine(min + ImVec2(0, 9), min + ImVec2(size.x + 1, 9), text);
window->DrawList->AddRectFilled(min + ImVec2(0, 1), min + ImVec2(roundf((float)val * ratio), 10 * style::uiScale), IM_COL32(0, 136, 255, 255));
window->DrawList->AddLine(min, min + ImVec2(0, (10.0f * style::uiScale) - 1), text, style::uiScale);
window->DrawList->AddLine(min + ImVec2(0, (10.0f * style::uiScale) - 1), min + ImVec2(size.x + 1, (10.0f * style::uiScale) - 1), text, style::uiScale);
for (int i = 0; i < 10; i++) {
window->DrawList->AddLine(min + ImVec2(roundf((float)i * it), 9), min + ImVec2(roundf((float)i * it), 14), text);
window->DrawList->AddLine(min + ImVec2(roundf((float)i * it), (10.0f * style::uiScale) - 1), min + ImVec2(roundf((float)i * it), (15.0f * style::uiScale) - 1), text, style::uiScale);
sprintf(buf, "%d", i * 10);
ImVec2 sz = ImGui::CalcTextSize(buf);
window->DrawList->AddText(min + ImVec2(roundf(((float)i * it) - (sz.x / 2.0)) + 1, 16), text, buf);
window->DrawList->AddText(min + ImVec2(roundf(((float)i * it) - (sz.x / 2.0)) + 1, 16.0f * style::uiScale), text, buf);
}
}
}

View File

@ -6,6 +6,7 @@
#include <volk/volk.h>
#include <spdlog/spdlog.h>
#include <gui/gui.h>
#include <gui/style.h>
#include <keybinds.h>
float DEFAULT_COLOR_MAP[][3] = {
@ -99,51 +100,53 @@ namespace ImGui {
ImU32 trace = ImGui::GetColorU32(ImGuiCol_PlotLines);
ImU32 shadow = ImGui::GetColorU32(ImGuiCol_PlotLines, 0.2);
ImU32 text = ImGui::GetColorU32(ImGuiCol_Text);
float textVOffset = 10.0f * style::uiScale;
// Vertical scale
for (float line = startLine; line > fftMin; line -= vRange) {
float yPos = widgetPos.y + fftHeight + 10 - ((line - fftMin) * scaleFactor);
window->DrawList->AddLine(ImVec2(roundf(widgetPos.x + 50), roundf(yPos)),
ImVec2(roundf(widgetPos.x + dataWidth + 50), roundf(yPos)),
IM_COL32(50, 50, 50, 255), 1.0);
float yPos = fftAreaMax.y - ((line - fftMin) * scaleFactor);
window->DrawList->AddLine(ImVec2(fftAreaMin.x, roundf(yPos)),
ImVec2(fftAreaMax.x, roundf(yPos)),
IM_COL32(50, 50, 50, 255), style::uiScale);
sprintf(buf, "%d", (int)line);
ImVec2 txtSz = ImGui::CalcTextSize(buf);
window->DrawList->AddText(ImVec2(widgetPos.x + 40 - txtSz.x, roundf(yPos - (txtSz.y / 2.0))), text, buf);
window->DrawList->AddText(ImVec2(fftAreaMin.x - txtSz.x - textVOffset, roundf(yPos - (txtSz.y / 2.0))), text, buf);
}
// Horizontal scale
double startFreq = ceilf(lowerFreq / range) * range;
double horizScale = (double)dataWidth / viewBandwidth;
float scaleVOfsset = 7 * style::uiScale;
for (double freq = startFreq; freq < upperFreq; freq += range) {
double xPos = widgetPos.x + 50 + ((freq - lowerFreq) * horizScale);
window->DrawList->AddLine(ImVec2(roundf(xPos), widgetPos.y + 10),
ImVec2(roundf(xPos), widgetPos.y + fftHeight + 10),
IM_COL32(50, 50, 50, 255), 1.0);
window->DrawList->AddLine(ImVec2(roundf(xPos), widgetPos.y + fftHeight + 10),
ImVec2(roundf(xPos), widgetPos.y + fftHeight + 17),
text, 1.0);
double xPos = fftAreaMin.x + ((freq - lowerFreq) * horizScale);
window->DrawList->AddLine(ImVec2(roundf(xPos), fftAreaMin.y + 1),
ImVec2(roundf(xPos), fftAreaMax.y),
IM_COL32(50, 50, 50, 255), style::uiScale);
window->DrawList->AddLine(ImVec2(roundf(xPos), fftAreaMax.y),
ImVec2(roundf(xPos), fftAreaMax.y + scaleVOfsset),
text, style::uiScale);
printAndScale(freq, buf);
ImVec2 txtSz = ImGui::CalcTextSize(buf);
window->DrawList->AddText(ImVec2(roundf(xPos - (txtSz.x / 2.0)), widgetPos.y + fftHeight + 10 + txtSz.y), text, buf);
window->DrawList->AddText(ImVec2(roundf(xPos - (txtSz.x / 2.0)), fftAreaMax.y + txtSz.y), text, buf);
}
// Data
if (latestFFT != NULL && fftLines != 0) {
for (int i = 1; i < dataWidth; i++) {
double aPos = widgetPos.y + fftHeight + 10 - ((latestFFT[i - 1] - fftMin) * scaleFactor);
double bPos = widgetPos.y + fftHeight + 10 - ((latestFFT[i] - fftMin) * scaleFactor);
aPos = std::clamp<double>(aPos, widgetPos.y + 10, widgetPos.y + fftHeight + 10);
bPos = std::clamp<double>(bPos, widgetPos.y + 10, widgetPos.y + fftHeight + 10);
window->DrawList->AddLine(ImVec2(widgetPos.x + 49 + i, roundf(aPos)),
ImVec2(widgetPos.x + 50 + i, roundf(bPos)), trace, 1.0);
window->DrawList->AddLine(ImVec2(widgetPos.x + 50 + i, roundf(bPos)),
ImVec2(widgetPos.x + 50 + i, widgetPos.y + fftHeight + 10), shadow, 1.0);
double aPos = fftAreaMax.y - ((latestFFT[i - 1] - fftMin) * scaleFactor);
double bPos = fftAreaMax.y - ((latestFFT[i] - fftMin) * scaleFactor);
aPos = std::clamp<double>(aPos, fftAreaMin.y + 1, fftAreaMax.y);
bPos = std::clamp<double>(bPos, fftAreaMin.y + 1, fftAreaMax.y);
window->DrawList->AddLine(ImVec2(fftAreaMin.x + i - 1, roundf(aPos)),
ImVec2(fftAreaMin.x + i, roundf(bPos)), trace, 1.0);
window->DrawList->AddLine(ImVec2(fftAreaMin.x + i, roundf(bPos)),
ImVec2(fftAreaMin.x + i, fftAreaMax.y), shadow, 1.0);
}
}
FFTRedrawArgs args;
args.min = ImVec2(widgetPos.x + 50, widgetPos.y + 9);
args.max = ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 10);
args.min = fftAreaMin;
args.max = fftAreaMax;
args.lowFreq = lowerFreq;
args.highFreq = upperFreq;
args.freqToPixelRatio = horizScale;
@ -152,13 +155,13 @@ namespace ImGui {
onFFTRedraw.emit(args);
// X Axis
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 10),
ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 10),
text, 1.0);
window->DrawList->AddLine(ImVec2(fftAreaMin.x, fftAreaMax.y),
ImVec2(fftAreaMax.x, fftAreaMax.y),
text, style::uiScale);
// Y Axis
window->DrawList->AddLine(ImVec2(widgetPos.x + 50, widgetPos.y + 9),
ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 9),
text, 1.0);
window->DrawList->AddLine(ImVec2(fftAreaMin.x, fftAreaMin.y),
ImVec2(fftAreaMin.x, fftAreaMax.y - 1),
text, style::uiScale);
}
void WaterFall::drawWaterfall() {
@ -173,7 +176,7 @@ namespace ImGui {
for (auto const& [name, vfo] : vfos) {
window->DrawList->AddRectFilled(vfo->wfRectMin, vfo->wfRectMax, vfo->color);
if (!vfo->lineVisible) { continue; }
window->DrawList->AddLine(vfo->wfLineMin, vfo->wfLineMax, (name == selectedVFO) ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255));
window->DrawList->AddLine(vfo->wfLineMin, vfo->wfLineMax, (name == selectedVFO) ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255), style::uiScale);
}
}
}
@ -212,7 +215,7 @@ namespace ImGui {
bool mouseClicked = ImGui::ButtonBehavior(ImRect(fftAreaMin, wfMax), GetID("WaterfallID"), &mouseHovered, &mouseHeld,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_PressedOnClick);
mouseInFFTResize = (dragOrigin.x > widgetPos.x && dragOrigin.x < widgetPos.x + widgetSize.x && dragOrigin.y >= widgetPos.y + newFFTAreaHeight - 2 && dragOrigin.y <= widgetPos.y + newFFTAreaHeight + 2);
mouseInFFTResize = (dragOrigin.x > widgetPos.x && dragOrigin.x < widgetPos.x + widgetSize.x && dragOrigin.y >= widgetPos.y + newFFTAreaHeight - (2.0f * style::uiScale) && dragOrigin.y <= widgetPos.y + newFFTAreaHeight + (2.0f * style::uiScale));
mouseInFreq = IS_IN_AREA(dragOrigin, freqAreaMin, freqAreaMax);
mouseInFFT = IS_IN_AREA(dragOrigin, fftAreaMin, fftAreaMax);
mouseInWaterfall = IS_IN_AREA(dragOrigin, wfMin, wfMax);
@ -304,7 +307,7 @@ namespace ImGui {
newFFTAreaHeight = mousePos.y - widgetPos.y;
newFFTAreaHeight = std::clamp<float>(newFFTAreaHeight, 150, widgetSize.y - 50);
ImGui::GetForegroundDrawList()->AddLine(ImVec2(widgetPos.x, newFFTAreaHeight + widgetPos.y), ImVec2(widgetEndPos.x, newFFTAreaHeight + widgetPos.y),
ImGui::GetColorU32(ImGuiCol_SeparatorActive));
ImGui::GetColorU32(ImGuiCol_SeparatorActive), style::uiScale);
return;
}
@ -417,7 +420,7 @@ namespace ImGui {
// Finally, if nothing else was selected, just move the VFO
if ((VFOMoveSingleClick ? ImGui::IsMouseClicked(ImGuiMouseButton_Left) : ImGui::IsMouseDown(ImGuiMouseButton_Left)) && (mouseInFFT | mouseInWaterfall) && (mouseMoved || hoveredVFOName == "")) {
if (selVfo != NULL) {
int refCenter = mousePos.x - (widgetPos.x + 50);
int refCenter = mousePos.x - fftAreaMin.x;
if (refCenter >= 0 && refCenter < dataWidth) {
double off = ((((double)refCenter / ((double)dataWidth / 2.0)) - 1.0) * (viewBandwidth / 2.0)) + viewOffset;
off += centerFreq;
@ -599,10 +602,10 @@ namespace ImGui {
float bpBottom;
if (bandPlanPos == BANDPLAN_POS_BOTTOM) {
bpBottom = widgetPos.y + fftHeight + 10;
bpBottom = fftAreaMax.y;
}
else {
bpBottom = widgetPos.y + height + 10;
bpBottom = fftAreaMin.y + height + 1;
}
@ -620,9 +623,9 @@ namespace ImGui {
start = std::clamp<double>(start, lowerFreq, upperFreq);
end = std::clamp<double>(end, lowerFreq, upperFreq);
center = (start + end) / 2.0;
aPos = widgetPos.x + 50 + ((start - lowerFreq) * horizScale);
bPos = widgetPos.x + 50 + ((end - lowerFreq) * horizScale);
cPos = widgetPos.x + 50 + ((center - lowerFreq) * horizScale);
aPos = fftAreaMin.x + ((start - lowerFreq) * horizScale);
bPos = fftAreaMin.x + ((end - lowerFreq) * horizScale);
cPos = fftAreaMin.x + ((center - lowerFreq) * horizScale);
width = bPos - aPos;
txtSz = ImGui::CalcTextSize(bandplan->bands[i].name.c_str());
if (bandplan::colorTable.find(bandplan->bands[i].type.c_str()) != bandplan::colorTable.end()) {
@ -633,22 +636,22 @@ namespace ImGui {
color = IM_COL32(255, 255, 255, 255);
colorTrans = IM_COL32(255, 255, 255, 100);
}
if (aPos <= widgetPos.x + 50) {
aPos = widgetPos.x + 51;
if (aPos <= fftAreaMin.x) {
aPos = fftAreaMin.x + 1;
}
if (bPos <= widgetPos.x + 50) {
bPos = widgetPos.x + 51;
if (bPos <= fftAreaMin.x) {
bPos = fftAreaMin.x + 1;
}
if (width >= 1.0) {
window->DrawList->AddRectFilled(ImVec2(roundf(aPos), bpBottom - height),
ImVec2(roundf(bPos), bpBottom), colorTrans);
if (startVis) {
window->DrawList->AddLine(ImVec2(roundf(aPos), bpBottom - height - 1),
ImVec2(roundf(aPos), bpBottom - 1), color);
ImVec2(roundf(aPos), bpBottom - 1), color, style::uiScale);
}
if (endVis) {
window->DrawList->AddLine(ImVec2(roundf(bPos), bpBottom - height - 1),
ImVec2(roundf(bPos), bpBottom - 1), color);
ImVec2(roundf(bPos), bpBottom - 1), color, style::uiScale);
}
}
if (txtSz.x <= width) {
@ -679,15 +682,15 @@ namespace ImGui {
int lastWaterfallHeight = waterfallHeight;
if (waterfallVisible) {
FFTAreaHeight = std::min<int>(FFTAreaHeight, widgetSize.y - 50);
FFTAreaHeight = std::min<int>(FFTAreaHeight, widgetSize.y - (50.0f * style::uiScale));
newFFTAreaHeight = FFTAreaHeight;
fftHeight = FFTAreaHeight - 50;
waterfallHeight = widgetSize.y - fftHeight - 52;
fftHeight = FFTAreaHeight - (50.0f * style::uiScale);
waterfallHeight = widgetSize.y - fftHeight - (50.0f * style::uiScale) - 2;
}
else {
fftHeight = widgetSize.y - 50;
fftHeight = widgetSize.y - (50.0f * style::uiScale);
}
dataWidth = widgetSize.x - 60.0;
dataWidth = widgetSize.x - (60.0f * style::uiScale);
if (waterfallVisible) {
// Raw FFT resize
@ -724,12 +727,14 @@ namespace ImGui {
latestFFT[i] = -1000.0; // Hide everything
}
fftAreaMin = ImVec2(widgetPos.x + 50, widgetPos.y + 9);
fftAreaMax = ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 10);
freqAreaMin = ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 11);
freqAreaMax = ImVec2(widgetPos.x + dataWidth + 50, widgetPos.y + fftHeight + 50);
wfMin = ImVec2(widgetPos.x + 50, widgetPos.y + fftHeight + 51);
wfMax = ImVec2(widgetPos.x + 50 + dataWidth, widgetPos.y + fftHeight + 51 + waterfallHeight);
fftAreaMin = ImVec2(widgetPos.x + (50.0f * style::uiScale), widgetPos.y + (9.0f * style::uiScale));
fftAreaMax = ImVec2(fftAreaMin.x + dataWidth, fftAreaMin.y + fftHeight + 1);
freqAreaMin = ImVec2(fftAreaMin.x, fftAreaMax.y + 1);
freqAreaMax = ImVec2(fftAreaMax.x, fftAreaMax.y + (40.0f * style::uiScale));
wfMin = ImVec2(fftAreaMin.x, freqAreaMax.y + 1);
wfMax = ImVec2(fftAreaMin.x + dataWidth, wfMin.y + waterfallHeight);
maxHSteps = dataWidth / (ImGui::CalcTextSize("000.000").x + 10);
maxVSteps = fftHeight / (ImGui::CalcTextSize("000.000").y);
@ -769,8 +774,8 @@ namespace ImGui {
//window->DrawList->AddRectFilled(widgetPos, widgetEndPos, IM_COL32( 0, 0, 0, 255 ));
ImU32 bg = ImGui::ColorConvertFloat4ToU32(gui::themeManager.waterfallBg);
window->DrawList->AddRectFilled(widgetPos, widgetEndPos, bg);
window->DrawList->AddRect(widgetPos, widgetEndPos, IM_COL32(50, 50, 50, 255));
window->DrawList->AddLine(ImVec2(widgetPos.x, widgetPos.y + fftHeight + 50), ImVec2(widgetPos.x + widgetSize.x, widgetPos.y + fftHeight + 50), IM_COL32(50, 50, 50, 255), 1.0);
window->DrawList->AddRect(widgetPos, widgetEndPos, IM_COL32(50, 50, 50, 255), 0.0, 0, style::uiScale);
window->DrawList->AddLine(ImVec2(widgetPos.x, freqAreaMax.y), ImVec2(widgetPos.x + widgetSize.x, freqAreaMax.y), IM_COL32(50, 50, 50, 255), style::uiScale);
if (!gui::mainWindow.lockWaterfallControls) {
inputHandled = false;
@ -1041,8 +1046,8 @@ namespace ImGui {
vfo->updateDrawingVars(viewBandwidth, dataWidth, viewOffset, widgetPos, fftHeight);
vfo->wfRectMin = ImVec2(vfo->rectMin.x, wfMin.y);
vfo->wfRectMax = ImVec2(vfo->rectMax.x, wfMax.y);
vfo->wfLineMin = ImVec2(vfo->lineMin.x, wfMin.y);
vfo->wfLineMax = ImVec2(vfo->lineMax.x, wfMax.y);
vfo->wfLineMin = ImVec2(vfo->lineMin.x, wfMin.y - 1);
vfo->wfLineMax = ImVec2(vfo->lineMax.x, wfMax.y - 1);
vfo->wfLbwSelMin = ImVec2(vfo->wfRectMin.x - 2, vfo->wfRectMin.y);
vfo->wfLbwSelMax = ImVec2(vfo->wfRectMin.x + 2, vfo->wfRectMax.y);
vfo->wfRbwSelMin = ImVec2(vfo->wfRectMax.x - 2, vfo->wfRectMin.y);
@ -1175,16 +1180,16 @@ namespace ImGui {
// Calculate the position of the line
if (reference == REF_LOWER) {
lineMin = ImVec2(widgetPos.x + 50 + left, widgetPos.y + 9);
lineMax = ImVec2(widgetPos.x + 50 + left, widgetPos.y + fftHeight + 9);
lineMin = ImVec2(gui::waterfall.fftAreaMin.x + left, gui::waterfall.fftAreaMin.y);
lineMax = ImVec2(gui::waterfall.fftAreaMin.x + left, gui::waterfall.fftAreaMax.y - 1);
}
else if (reference == REF_CENTER) {
lineMin = ImVec2(widgetPos.x + 50 + center, widgetPos.y + 9);
lineMax = ImVec2(widgetPos.x + 50 + center, widgetPos.y + fftHeight + 9);
lineMin = ImVec2(gui::waterfall.fftAreaMin.x + center, gui::waterfall.fftAreaMin.y);
lineMax = ImVec2(gui::waterfall.fftAreaMin.x + center, gui::waterfall.fftAreaMax.y - 1);
}
else if (reference == REF_UPPER) {
lineMin = ImVec2(widgetPos.x + 50 + right, widgetPos.y + 9);
lineMax = ImVec2(widgetPos.x + 50 + right, widgetPos.y + fftHeight + 9);
lineMin = ImVec2(gui::waterfall.fftAreaMin.x + right, gui::waterfall.fftAreaMin.y);
lineMax = ImVec2(gui::waterfall.fftAreaMin.x + right, gui::waterfall.fftAreaMax.y - 1);
}
int _left = left;
@ -1194,22 +1199,23 @@ namespace ImGui {
leftClamped = (left != _left);
rightClamped = (right != _right);
rectMin = ImVec2(widgetPos.x + 50 + left, widgetPos.y + 10);
rectMax = ImVec2(widgetPos.x + 51 + right, widgetPos.y + fftHeight + 10);
rectMin = ImVec2(gui::waterfall.fftAreaMin.x + left, gui::waterfall.fftAreaMin.y + 1);
rectMax = ImVec2(gui::waterfall.fftAreaMin.x + right + 1, gui::waterfall.fftAreaMax.y);
lbwSelMin = ImVec2(rectMin.x - 2, rectMin.y);
lbwSelMax = ImVec2(rectMin.x + 2, rectMax.y);
rbwSelMin = ImVec2(rectMax.x - 2, rectMin.y);
rbwSelMax = ImVec2(rectMax.x + 2, rectMax.y);
float gripSize = 2.0f * style::uiScale;
lbwSelMin = ImVec2(rectMin.x - gripSize, rectMin.y);
lbwSelMax = ImVec2(rectMin.x + gripSize, rectMax.y);
rbwSelMin = ImVec2(rectMax.x - gripSize, rectMin.y);
rbwSelMax = ImVec2(rectMax.x + gripSize, rectMax.y);
notchMin = ImVec2(widgetPos.x + 50 + notch - 2, widgetPos.y + 9);
notchMax = ImVec2(widgetPos.x + 50 + notch + 2, widgetPos.y + fftHeight + 9);
notchMin = ImVec2(gui::waterfall.fftAreaMin.x + notch - gripSize, gui::waterfall.fftAreaMin.y);
notchMax = ImVec2(gui::waterfall.fftAreaMin.x + notch + gripSize, gui::waterfall.fftAreaMax.y - 1);
}
void WaterfallVFO::draw(ImGuiWindow* window, bool selected) {
window->DrawList->AddRectFilled(rectMin, rectMax, color);
if (lineVisible) {
window->DrawList->AddLine(lineMin, lineMax, selected ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255));
window->DrawList->AddLine(lineMin, lineMax, selected ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255), style::uiScale);
}
if (notchVisible) {

View File

@ -236,6 +236,13 @@ namespace ImGui {
_BANDPLAN_POS_COUNT
};
ImVec2 fftAreaMin;
ImVec2 fftAreaMax;
ImVec2 freqAreaMin;
ImVec2 freqAreaMax;
ImVec2 wfMin;
ImVec2 wfMax;
private:
void drawWaterfall();
void drawFFT();
@ -260,13 +267,6 @@ namespace ImGui {
ImVec2 lastWidgetPos;
ImVec2 lastWidgetSize;
ImVec2 fftAreaMin;
ImVec2 fftAreaMax;
ImVec2 freqAreaMin;
ImVec2 freqAreaMax;
ImVec2 wfMin;
ImVec2 wfMax;
ImGuiWindow* window;
GLuint textureId;

View File

@ -4,6 +4,9 @@
ModuleManager::Module_t ModuleManager::loadModule(std::string path) {
Module_t mod;
// On android, the path has to be relative, don't make it absolute
#ifndef __ANDROID__
if (!std::filesystem::exists(path)) {
spdlog::error("{0} does not exist", path);
mod.handle = NULL;
@ -14,6 +17,7 @@ ModuleManager::Module_t ModuleManager::loadModule(std::string path) {
mod.handle = NULL;
return mod;
}
#endif
#ifdef _WIN32
mod.handle = LoadLibraryA(path.c_str());
if (mod.handle == NULL) {

View File

@ -13,6 +13,8 @@ namespace options {
#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";

View File

@ -248,6 +248,7 @@ void SinkManager::showVolumeSlider(std::string name, std::string prefix, float w
}
float ypos = ImGui::GetCursorPosY();
float sliderOffset = 8.0f * style::uiScale;
if (streams.find(name) == streams.end() || name == "") {
float dummy = 0.0f;
@ -256,7 +257,7 @@ void SinkManager::showVolumeSlider(std::string name, std::string prefix, float w
ImGui::ImageButton(icons::MUTED, ImVec2(height, height), ImVec2(0, 0), ImVec2(1, 1), btwBorder);
ImGui::PopID();
ImGui::SameLine();
ImGui::SetNextItemWidth(width - height - 8);
ImGui::SetNextItemWidth(width - height - sliderOffset);
ImGui::SetCursorPosY(ypos + ((height - sliderHeight) / 2.0f) + btwBorder);
ImGui::SliderFloat((prefix + name).c_str(), &dummy, 0.0f, 1.0f, "");
style::endDisabled();
@ -289,7 +290,7 @@ void SinkManager::showVolumeSlider(std::string name, std::string prefix, float w
ImGui::SameLine();
ImGui::SetNextItemWidth(width - height - 8);
ImGui::SetNextItemWidth(width - height - sliderOffset);
ImGui::SetCursorPosY(ypos + ((height - sliderHeight) / 2.0f) + btwBorder);
if (ImGui::SliderFloat((prefix + name).c_str(), &stream->guiVolume, 0.0f, 1.0f, "")) {
stream->setVolume(stream->guiVolume);

View File

@ -5,6 +5,9 @@
#include <GL/gl.h>
#elif defined(__APPLE__)
#include <OpenGL/gl.h>
#elif defined(__ANDROID__)
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#else
#include <GL/gl.h>
#endif

View File

@ -1,3 +1,3 @@
#pragma once
#define VERSION_STR "1.0.5"
#define VERSION_STR "1.0.6"