From 16d8a31c12e02272d3fcc91a3ba5fe9407e6a8e4 Mon Sep 17 00:00:00 2001 From: Ryzerth Date: Tue, 8 Dec 2020 16:27:52 +0100 Subject: [PATCH] center tuning and more --- core/src/gui/icons.cpp | 4 +++ core/src/gui/icons.h | 2 ++ core/src/gui/main_window.cpp | 33 +++++++++++++++++++++- core/src/gui/widgets/frequency_select.cpp | 5 +++- core/src/signal_path/sink.cpp | 4 ++- core/src/signal_path/sink.h | 2 +- root_dev/config.json | 6 ++-- root_dev/res/icons/center_tuning.png | Bin 0 -> 6667 bytes root_dev/res/icons/normal_tuning.png | Bin 0 -> 2785 bytes 9 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 root_dev/res/icons/center_tuning.png create mode 100644 root_dev/res/icons/normal_tuning.png diff --git a/core/src/gui/icons.cpp b/core/src/gui/icons.cpp index bf0c6e5f..72447e46 100644 --- a/core/src/gui/icons.cpp +++ b/core/src/gui/icons.cpp @@ -13,6 +13,8 @@ namespace icons { ImTextureID MENU; ImTextureID MUTED; ImTextureID UNMUTED; + ImTextureID NORMAL_TUNING; + ImTextureID CENTER_TUNING; GLuint loadTexture(std::string path) { int w,h,n; @@ -35,5 +37,7 @@ namespace icons { MENU = (ImTextureID)(uintptr_t)loadTexture(ROOT_DIR "/res/icons/menu.png"); MUTED = (ImTextureID)(uintptr_t)loadTexture(ROOT_DIR "/res/icons/muted.png"); UNMUTED = (ImTextureID)(uintptr_t)loadTexture(ROOT_DIR "/res/icons/unmuted.png"); + NORMAL_TUNING = (ImTextureID)(uintptr_t)loadTexture(ROOT_DIR "/res/icons/normal_tuning.png"); + CENTER_TUNING = (ImTextureID)(uintptr_t)loadTexture(ROOT_DIR "/res/icons/center_tuning.png"); } } \ No newline at end of file diff --git a/core/src/gui/icons.h b/core/src/gui/icons.h index e71ca59a..74c4a842 100644 --- a/core/src/gui/icons.h +++ b/core/src/gui/icons.h @@ -10,6 +10,8 @@ namespace icons { extern ImTextureID MENU; extern ImTextureID MUTED; extern ImTextureID UNMUTED; + extern ImTextureID NORMAL_TUNING; + extern ImTextureID CENTER_TUNING; GLuint loadTexture(std::string path); void load(); diff --git a/core/src/gui/main_window.cpp b/core/src/gui/main_window.cpp index 0a370854..702ca88a 100644 --- a/core/src/gui/main_window.cpp +++ b/core/src/gui/main_window.cpp @@ -163,6 +163,8 @@ void windowInit() { // Add default main config to avoid having to ship one // Have a good directory system on both linux and windows (should fix occassional underruns) // Switch to double buffering + // Fix gain not updated on startup, soapysdr + // Fix memory leak when enabling and disabling repeatedly // TODO for 0.2.6 // Add a module add/remove/change order menu @@ -232,6 +234,7 @@ void setVFO(double freq) { if (centerTuning) { gui::waterfall.setViewOffset((BW / 2.0) - (viewBW / 2.0)); gui::waterfall.setCenterFrequency(freq); + gui::waterfall.setViewOffset(0); sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, 0); sigpath::sourceManager.tune(freq); return; @@ -310,6 +313,9 @@ void drawWindow() { if (vfo != NULL) { if (vfo->centerOffsetChanged) { + if (centerTuning) { + setVFO(gui::waterfall.getCenterFrequency() + vfo->generalOffset); + } gui::freqSelect.setFrequency(gui::waterfall.getCenterFrequency() + vfo->generalOffset); gui::freqSelect.frequencyChanged = false; core::configManager.aquire(); @@ -401,12 +407,37 @@ void drawWindow() { ImGui::SameLine(); //ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8); - sigpath::sinkManager.showVolumeSlider(gui::waterfall.selectedVFO, "##_sdrpp_main_volume_", 248, 30, 5); + sigpath::sinkManager.showVolumeSlider(gui::waterfall.selectedVFO, "##_sdrpp_main_volume_", 248, 30, 5, true); ImGui::SameLine(); gui::freqSelect.draw(); + //ImGui::SameLine(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 9); + if (centerTuning) { + ImGui::PushID(ImGui::GetID("sdrpp_ena_st_btn")); + if (ImGui::ImageButton(icons::CENTER_TUNING, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5)) { + centerTuning = false; + core::configManager.aquire(); + core::configManager.conf["centerTuning"] = centerTuning; + core::configManager.release(true); + } + ImGui::PopID(); + } + else { // TODO: Might need to check if there even is a device + ImGui::PushID(ImGui::GetID("sdrpp_dis_st_btn")); + if (ImGui::ImageButton(icons::NORMAL_TUNING, ImVec2(30, 30), ImVec2(0, 0), ImVec2(1, 1), 5)) { + centerTuning = true; + setVFO(gui::freqSelect.frequency); + core::configManager.aquire(); + core::configManager.conf["centerTuning"] = centerTuning; + core::configManager.release(true); + } + ImGui::PopID(); + } + ImGui::SameLine(); // Logo button diff --git a/core/src/gui/widgets/frequency_select.cpp b/core/src/gui/widgets/frequency_select.cpp index be0d2110..ba611bb2 100644 --- a/core/src/gui/widgets/frequency_select.cpp +++ b/core/src/gui/widgets/frequency_select.cpp @@ -151,7 +151,10 @@ void FrequencySelect::draw() { frequency = freq; ImGui::PopFont(); - ImGui::NewLine(); + + ImGui::SetCursorPosX(digitBottomMaxs[11].x + 17); + + //ImGui::NewLine(); } void FrequencySelect::setFrequency(uint64_t freq) { diff --git a/core/src/signal_path/sink.cpp b/core/src/signal_path/sink.cpp index a1a2d3ae..90361ab4 100644 --- a/core/src/signal_path/sink.cpp +++ b/core/src/signal_path/sink.cpp @@ -164,7 +164,7 @@ void SinkManager::setStreamSink(std::string name, std::string providerName) { spdlog::warn("setStreamSink is NOT implemented!!!"); } -void SinkManager::showVolumeSlider(std::string name, std::string prefix, float width, float btnHeight, int btwBorder) { +void SinkManager::showVolumeSlider(std::string name, std::string prefix, float width, float btnHeight, int btwBorder, bool sameLine) { // TODO: Replace map with some hashmap for it to be faster float height = ImGui::GetTextLineHeightWithSpacing() + 2; float sliderHeight = height; @@ -185,6 +185,7 @@ void SinkManager::showVolumeSlider(std::string name, std::string prefix, float w ImGui::SetCursorPosY(ypos + ((height - sliderHeight) / 2.0f) + btwBorder); ImGui::SliderFloat((prefix + name).c_str(), &dummy, 0.0f, 1.0f, ""); style::endDisabled(); + if (sameLine) { ImGui::SetCursorPosY(ypos); } return; } @@ -221,6 +222,7 @@ void SinkManager::showVolumeSlider(std::string name, std::string prefix, float w saveStreamConfig(name); core::configManager.release(true); } + if (sameLine) { ImGui::SetCursorPosY(ypos); } //ImGui::SetCursorPosY(ypos); } diff --git a/core/src/signal_path/sink.h b/core/src/signal_path/sink.h index 26e8ec43..ca30355e 100644 --- a/core/src/signal_path/sink.h +++ b/core/src/signal_path/sink.h @@ -99,7 +99,7 @@ public: void setStreamSink(std::string name, std::string providerName); - void showVolumeSlider(std::string name, std::string prefix, float width, float btnHeight = -1.0f, int btwBorder = 0); + void showVolumeSlider(std::string name, std::string prefix, float width, float btnHeight = -1.0f, int btwBorder = 0, bool sameLine = false); dsp::stream* bindStream(std::string name); void unbindStream(std::string name, dsp::stream* stream); diff --git a/root_dev/config.json b/root_dev/config.json index 3b68a2e3..07af47b2 100644 --- a/root_dev/config.json +++ b/root_dev/config.json @@ -1,9 +1,9 @@ { "bandPlan": "General", "bandPlanEnabled": true, - "centerTuning": false, + "centerTuning": true, "fftHeight": 300, - "frequency": 100100000, + "frequency": 99000000, "max": 0.0, "maximized": false, "menuOrder": [ @@ -41,7 +41,7 @@ "Radio": { "muted": false, "sink": "Audio", - "volume": 0.29591837525367737 + "volume": 0.47959184646606445 }, "Radio 1": { "muted": false, diff --git a/root_dev/res/icons/center_tuning.png b/root_dev/res/icons/center_tuning.png new file mode 100644 index 0000000000000000000000000000000000000000..00bf8482f9f9f3ca38e76569ad00f7a0d9c0e1ad GIT binary patch literal 6667 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 literal 0 HcmV?d00001