diff --git a/src/frequency_select.cpp b/src/frequency_select.cpp index dd228723..424ef32b 100644 --- a/src/frequency_select.cpp +++ b/src/frequency_select.cpp @@ -84,6 +84,9 @@ void FrequencySelect::draw() { onResize(); } + ImU32 disabledColor = ImGui::GetColorU32(ImGuiCol_Text, 0.3f); + ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text); + int commaOffset = 0; bool zeros = true; for (int i = 0; i < 12; i++) { @@ -92,11 +95,11 @@ void FrequencySelect::draw() { } sprintf(buf, "%d", digits[i]); window->DrawList->AddText(ImVec2(widgetPos.x + (i * 22) + commaOffset, widgetPos.y), - zeros ? IM_COL32(90, 90, 90, 255) : IM_COL32(255, 255, 255, 255), buf); + zeros ? disabledColor : textColor, buf); if ((i + 1) % 3 == 0 && i < 11) { commaOffset += 12; window->DrawList->AddText(ImVec2(widgetPos.x + (i * 22) + commaOffset + 10, widgetPos.y), - zeros ? IM_COL32(90, 90, 90, 255) : IM_COL32(255, 255, 255, 255), "."); + zeros ? disabledColor : textColor, "."); } } diff --git a/src/io/audio.h b/src/io/audio.h index 7f24a02f..d6c520ff 100644 --- a/src/io/audio.h +++ b/src/io/audio.h @@ -252,6 +252,7 @@ namespace io { AudioSink* _this = (AudioSink*)userData; float* outbuf = (float*)output; if (_this->_monoInput->read(_this->monoBuffer, frameCount) < 0) { + memset(outbuf, 0, sizeof(float) * frameCount); return 0; } @@ -270,6 +271,7 @@ namespace io { AudioSink* _this = (AudioSink*)userData; dsp::StereoFloat_t* outbuf = (dsp::StereoFloat_t*)output; if (_this->_stereoInput->read(_this->stereoBuffer, frameCount) < 0) { + memset(outbuf, 0, sizeof(dsp::StereoFloat_t) * frameCount); return 0; } @@ -291,6 +293,7 @@ namespace io { AudioSink* _this = (AudioSink*)userData; dsp::StereoFloat_t* outbuf = (dsp::StereoFloat_t*)output; if (_this->_monoInput->read(_this->monoBuffer, frameCount) < 0) { + memset(outbuf, 0, sizeof(dsp::StereoFloat_t) * frameCount); return 0; } @@ -310,6 +313,7 @@ namespace io { AudioSink* _this = (AudioSink*)userData; float* outbuf = (float*)output; if (_this->_stereoInput->read(_this->stereoBuffer, frameCount) < 0) { + memset(outbuf, 0, sizeof(float) * frameCount); return 0; } diff --git a/src/main.cpp b/src/main.cpp index 6c290b6c..33a96f66 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -83,6 +83,7 @@ int main() { return 1; } + // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -98,7 +99,7 @@ int main() { config::load("config.json"); config::startAutoSave(); - style::setDefaultStyle(); + style::setDarkStyle(); spdlog::info("Loading icons"); icons::load(); @@ -135,7 +136,7 @@ int main() { glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f); - //glClearColor(0.90f, 0.90f, 0.90f, 1.0f); + //glClearColor(0.9f, 0.9f, 0.9f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); diff --git a/src/main_window.cpp b/src/main_window.cpp index 85331a76..47131243 100644 --- a/src/main_window.cpp +++ b/src/main_window.cpp @@ -195,7 +195,7 @@ void windowInit() { // Load last band plan configuration - // TODO: Save/load config for audio streams + window size/fullscreen + // TODO: Save/load config window size/fullscreen // Also add a loading screen // And a module add/remove/change order menu // get rid of watchers and use if() instead @@ -203,7 +203,11 @@ void windowInit() { // Bandwidth ajustment // DSB / CW and RAW modes; // Write a recorder - + // Adjustable "snap to grid" for each VFO + // Bring VFO to a visible plane when changing sample rate if it's smaller + // Fix invalid values on the min/max sliders + // Possibility to resize waterfall and menu + // Have a proper root directory // Update UI settings fftMin = config::config["min"]; @@ -685,13 +689,14 @@ void drawWindow() { // Right Column ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); ImGui::NextColumn(); + ImGui::PopStyleVar(); + ImGui::BeginChild("Waterfall"); wtf.draw(); ImGui::EndChild(); - ImGui::PopStyleVar(); ImGui::NextColumn(); ImGui::BeginChild("WaterfallControls"); @@ -706,6 +711,7 @@ void drawWindow() { ImGui::Text("Max"); ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0f) - 10); if (ImGui::VSliderFloat("##_8_", ImVec2(20.0f, 150.0f), &fftMax, 0.0f, -100.0f, "")) { + fftMax = std::max(fftMax, fftMin + 10); config::config["max"] = fftMax; config::configModified = true; } @@ -716,6 +722,7 @@ void drawWindow() { ImGui::Text("Min"); ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.0f) - 10); if (ImGui::VSliderFloat("##_9_", ImVec2(20.0f, 150.0f), &fftMin, 0.0f, -100.0f, "")) { + fftMin = std::min(fftMax - 10, fftMin); config::config["min"] = fftMin; config::configModified = true; } diff --git a/src/style.h b/src/style.h index 3ce378ad..ae35e414 100644 --- a/src/style.h +++ b/src/style.h @@ -4,6 +4,7 @@ namespace style { void setDefaultStyle(); + void setDarkStyle(); void beginDisabled(); void endDisabled(); } \ No newline at end of file diff --git a/src/styles.cpp b/src/styles.cpp index 6eb344f4..342d6b13 100644 --- a/src/styles.cpp +++ b/src/styles.cpp @@ -15,14 +15,75 @@ namespace style { //ImGui::StyleColorsLight(); } + void setDarkStyle() { + ImGui::GetStyle().WindowRounding = 0.0f; + ImGui::GetStyle().ChildRounding = 0.0f; + ImGui::GetStyle().FrameRounding = 0.0f; + ImGui::GetStyle().GrabRounding = 0.0f; + ImGui::GetStyle().PopupRounding = 0.0f; + ImGui::GetStyle().ScrollbarRounding = 0.0f; + + ImGui::GetIO().Fonts->AddFontFromFileTTF("res/fonts/Roboto-Medium.ttf", 16.0f); + + ImGui::StyleColorsDark(); + + auto& style = ImGui::GetStyle(); + + ImVec4* colors = style.Colors; + + colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); + colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.21f, 0.22f, 0.54f); + colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.29f, 0.29f, 0.29f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.45f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.44f, 0.44f, 0.44f, 0.40f); + colors[ImGuiCol_Header] = ImVec4(0.63f, 0.63f, 0.70f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.63f, 0.63f, 0.70f, 0.40f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.63f, 0.63f, 0.70f, 0.31f); + colors[ImGuiCol_Separator] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.72f, 0.72f, 0.72f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.91f, 0.91f, 0.91f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.81f, 0.81f, 0.81f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.46f, 0.46f, 0.46f, 0.95f); + colors[ImGuiCol_PlotLines] = ImVec4(0.4f, 0.9f, 1.0f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.73f, 0.60f, 0.15f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.87f, 0.87f, 0.87f, 0.35f); + colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); + } + void beginDisabled() { ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.5f, 0.5f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.35f, 0.35f, 0.35f, 0.35f)); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.44f, 0.44f, 0.44f, 0.15f)); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.20f, 0.21f, 0.22f, 0.30f)); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 0.65f)); } void endDisabled() { ImGui::PopItemFlag(); - ImGui::PopStyleColor(2); + ImGui::PopStyleColor(3); } } \ No newline at end of file diff --git a/src/waterfall.cpp b/src/waterfall.cpp index 9fe05569..4cf9e376 100644 --- a/src/waterfall.cpp +++ b/src/waterfall.cpp @@ -106,7 +106,9 @@ namespace ImGui { float vertRange = fftMax - fftMin; float scaleFactor = fftHeight / vertRange; char buf[100]; - + + ImU32 trace = ImGui::GetColorU32(ImGuiCol_PlotLines); + ImU32 shadow = ImGui::GetColorU32(ImGuiCol_PlotLines, 0.2); // Vertical scale for (float line = startLine; line > fftMin; line -= vRange) { @@ -145,11 +147,9 @@ namespace ImGui { aPos = std::clamp(aPos, widgetPos.y + 10, widgetPos.y + fftHeight + 10); bPos = std::clamp(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)), - IM_COL32(0, 255, 255, 255), 1.0f); + ImVec2(widgetPos.x + 50 + i, roundf(bPos)), trace, 1.0f); window->DrawList->AddLine(ImVec2(widgetPos.x + 50 + i, roundf(bPos)), - ImVec2(widgetPos.x + 50 + i, widgetPos.y + fftHeight + 10), - IM_COL32(0, 255, 255, 50), 1.0f); + ImVec2(widgetPos.x + 50 + i, widgetPos.y + fftHeight + 10), shadow, 1.0f); } // X Axis @@ -361,6 +361,7 @@ namespace ImGui { waterfallHeight = widgetSize.y - fftHeight - 52; delete[] latestFFT; delete[] waterfallFb; + latestFFT = new float[dataWidth]; waterfallFb = new uint32_t[dataWidth * waterfallHeight]; memset(waterfallFb, 0, dataWidth * waterfallHeight * sizeof(uint32_t)); @@ -387,14 +388,24 @@ namespace ImGui { void WaterFall::draw() { buf_mtx.lock(); window = GetCurrentWindow(); + + // Fix for weird ImGui bug + ImVec2 tmpWidgetEndPos = ImGui::GetWindowContentRegionMax(); + if (tmpWidgetEndPos.x < 100 || tmpWidgetEndPos.y < fftHeight + 100) { + buf_mtx.unlock(); + return; + } + widgetPos = ImGui::GetWindowContentRegionMin(); - widgetEndPos = ImGui::GetWindowContentRegionMax(); + widgetEndPos = tmpWidgetEndPos; widgetPos.x += window->Pos.x; widgetPos.y += window->Pos.y; - widgetEndPos.x += window->Pos.x; + widgetEndPos.x += window->Pos.x - 4; // Padding widgetEndPos.y += window->Pos.y; widgetSize = ImVec2(widgetEndPos.x - widgetPos.x, widgetEndPos.y - widgetPos.y); + + if (widgetPos.x != lastWidgetPos.x || widgetPos.y != lastWidgetPos.y) { lastWidgetPos = widgetPos; onPositionChange();