LCOV - code coverage report
Current view: top level - src/gui/views - gui_tuner.cpp (source / functions) Coverage Total Hit
Test: merged.info Lines: 89.9 % 89 80
Test Date: 2026-06-07 15:51:50 Functions: 100.0 % 1 1

            Line data    Source code
       1              : #include "gui/views/gui_tuner.h"
       2              : 
       3              : #include <imgui.h>
       4              : 
       5              : #include <cmath>
       6              : #include <cstdio>
       7              : 
       8              : #include "common.h"
       9              : #include "gui/theme/theme.h"
      10              : 
      11              : namespace Amplitron {
      12              : 
      13            9 : void GuiTuner::render(bool& show) {
      14            9 :     ImGui::SetNextWindowSize(ImVec2(360, 320), ImGuiCond_FirstUseEver);
      15            9 :     bool open = show;
      16            9 :     if (!ImGui::Begin("Chromatic Tuner", &open)) {
      17            0 :         if (!open) show = false;
      18            0 :         ImGui::End();
      19            2 :         return;
      20              :     }
      21            9 :     if (!open) {
      22            3 :         show = false;
      23            3 :         ImGui::End();
      24            3 :         return;
      25              :     }
      26              : 
      27            6 :     const TunerProps& p = props_;
      28            6 :     ImDrawList* dl = ImGui::GetWindowDrawList();
      29            6 :     float win_w = ImGui::GetContentRegionAvail().x;
      30              : 
      31            6 :     if (p.has_signal && p.note_idx >= 0 && p.note_name_fn) {
      32              :         // ── Note name (large, centered) ──
      33            1 :         char note_buf[16];
      34            3 :         std::snprintf(note_buf, sizeof(note_buf), "%s%d", p.note_name_fn(p.note_idx), p.octave);
      35            3 :         ImVec2 note_size = ImGui::CalcTextSize(note_buf);
      36            3 :         float scale = 3.0f;
      37            3 :         float note_w = note_size.x * scale;
      38            3 :         ImVec2 note_pos = ImGui::GetCursorScreenPos();
      39            3 :         note_pos.x += (win_w - note_w) * 0.5f;
      40            4 :         dl->AddText(ImGui::GetFont(), ImGui::GetFontSize() * scale, note_pos, Theme::TEXT_PRIMARY,
      41            1 :                     note_buf);
      42            3 :         ImGui::Dummy(ImVec2(0, ImGui::GetFontSize() * scale + 8));
      43              : 
      44              :         // ── Cents indicator ──
      45            3 :         float abs_cents = std::fabs(p.cents);
      46            4 :         ImVec4 cents_col = (abs_cents < 2.0f)    ? ImVec4(0.2f, 0.9f, 0.3f, 1.0f)
      47            3 :                            : (abs_cents < 15.0f) ? ImVec4(0.9f, 0.8f, 0.2f, 1.0f)
      48            2 :                                                  : ImVec4(0.9f, 0.2f, 0.2f, 1.0f);
      49            1 :         char cents_buf[32];
      50            3 :         std::snprintf(cents_buf, sizeof(cents_buf), "%+.1f cents", p.cents);
      51            3 :         ImVec2 cents_size = ImGui::CalcTextSize(cents_buf);
      52            3 :         ImGui::SetCursorPosX((win_w - cents_size.x) * 0.5f);
      53            3 :         ImGui::TextColored(cents_col, "%s", cents_buf);
      54              : 
      55            3 :         ImGui::Spacing();
      56              : 
      57              :         // ── Cents deviation bar ──
      58            3 :         float bar_w = win_w - 40;
      59            3 :         float bar_h = 14;
      60            3 :         ImVec2 bar_pos = ImGui::GetCursorScreenPos();
      61            3 :         bar_pos.x += 20;
      62            3 :         dl->AddRectFilled(bar_pos, ImVec2(bar_pos.x + bar_w, bar_pos.y + bar_h), Theme::KNOB_BG,
      63              :                           4.0f);
      64              : 
      65            3 :         float cx = bar_pos.x + bar_w * 0.5f;
      66            3 :         dl->AddLine(ImVec2(cx, bar_pos.y - 2), ImVec2(cx, bar_pos.y + bar_h + 2), Theme::TEXT_DIM,
      67              :                     2.0f);
      68              : 
      69            3 :         float needle_norm = clamp(p.cents / 50.0f, -1.0f, 1.0f);
      70            3 :         float needle_x = cx + needle_norm * (bar_w * 0.5f);
      71            3 :         ImU32 needle_col = ImGui::ColorConvertFloat4ToU32(cents_col);
      72            5 :         dl->AddRectFilled(ImVec2(needle_x - 4, bar_pos.y - 3),
      73            3 :                           ImVec2(needle_x + 4, bar_pos.y + bar_h + 3), needle_col, 3.0f);
      74            3 :         ImGui::Dummy(ImVec2(0, bar_h + 12));
      75              : 
      76              :         // ── Frequency ──
      77            1 :         char freq_buf[32];
      78            3 :         std::snprintf(freq_buf, sizeof(freq_buf), "%.1f Hz", p.freq);
      79            3 :         float freq_w = ImGui::CalcTextSize(freq_buf).x;
      80            3 :         ImGui::SetCursorPosX((win_w - freq_w) * 0.5f);
      81            3 :         ImGui::TextColored(Theme::TextSecondary(), "%s", freq_buf);
      82              : 
      83            1 :     } else {
      84              :         // ── No signal ──
      85            3 :         const char* dash = "---";
      86            3 :         ImVec2 dash_size = ImGui::CalcTextSize(dash);
      87            3 :         float scale = 3.0f;
      88            3 :         ImVec2 pos = ImGui::GetCursorScreenPos();
      89            3 :         pos.x += (win_w - dash_size.x * scale) * 0.5f;
      90            3 :         dl->AddText(ImGui::GetFont(), ImGui::GetFontSize() * scale, pos, Theme::TEXT_DIM, dash);
      91            3 :         ImGui::Dummy(ImVec2(0, ImGui::GetFontSize() * scale + 8));
      92              : 
      93            3 :         const char* waiting = "Play a note...";
      94            3 :         ImVec2 wt_size = ImGui::CalcTextSize(waiting);
      95            3 :         ImGui::SetCursorPosX((win_w - wt_size.x) * 0.5f);
      96            3 :         ImGui::TextColored(Theme::TextDim(), "%s", waiting);
      97            3 :         ImGui::Dummy(ImVec2(0, 40));
      98              :     }
      99              : 
     100            6 :     ImGui::Spacing();
     101            6 :     ImGui::Separator();
     102            6 :     ImGui::Spacing();
     103              : 
     104              :     // ── Mute toggle ──
     105            6 :     if (p.mute_on) {
     106            0 :         ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.6f, 0.15f, 0.15f, 1.0f));
     107            0 :         ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.75f, 0.2f, 0.2f, 1.0f));
     108            0 :     } else {
     109            6 :         ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15f, 0.4f, 0.15f, 1.0f));
     110            6 :         ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.55f, 0.2f, 1.0f));
     111              :     }
     112            6 :     float btn_w = 140;
     113            6 :     ImGui::SetCursorPosX((win_w - btn_w) * 0.5f);
     114            8 :     if (ImGui::Button(p.mute_on ? "MUTE ON" : "MUTE OFF", ImVec2(btn_w, 30))) {
     115            0 :         if (p.on_mute_changed) p.on_mute_changed(!p.mute_on);
     116            0 :     }
     117            6 :     ImGui::PopStyleColor(2);
     118              : 
     119              :     // ── A4 Reference ──
     120            6 :     ImGui::Spacing();
     121            6 :     float a4_ref = p.a4_ref;
     122            6 :     ImGui::SetNextItemWidth(win_w - 20);
     123            6 :     if (ImGui::SliderFloat("A4 Reference", &a4_ref, 430.0f, 450.0f, "%.0f Hz")) {
     124            0 :         if (p.on_a4_ref_changed) p.on_a4_ref_changed(a4_ref);
     125            0 :     }
     126              : 
     127            6 :     ImGui::End();
     128            3 : }
     129              : 
     130              : }  // namespace Amplitron
        

Generated by: LCOV version 2.0-1