mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-25 12:07:49 +02:00
Backend abstraction + added android support + partial high DPI scaling
This commit is contained in:
@ -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)
|
||||
|
@ -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
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -4,5 +4,6 @@
|
||||
#include <mutex>
|
||||
|
||||
namespace LoadingScreen {
|
||||
void init();
|
||||
void show(std::string msg);
|
||||
};
|
@ -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;
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -3,5 +3,6 @@
|
||||
|
||||
namespace thememenu {
|
||||
void init(std::string resDir);
|
||||
void applyTheme();
|
||||
void draw(void* ctx);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_STR "1.0.5"
|
||||
#define VERSION_STR "1.0.6"
|
Reference in New Issue
Block a user