From 240427b94c5c22f60e6236c5216b68fc0bd8168f Mon Sep 17 00:00:00 2001 From: Bailey Pumfleet Date: Mon, 2 Nov 2026 13:03:57 -0600 Subject: [PATCH] Read either minus sign in Dialogue's sensitivity and the Leveler's percent knobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both parsers kept only ASCII signs, so a typed or pasted "−50%" (U+2212, the sign the interfaces display) read as +50%. Dialogue's sensitivity runs from −100% to +100%, so this flipped the value, and the interface's own text didn't read back. Both now use ui::format::parseLenient, like the dB fields. Co-Authored-By: Claude Opus 5.5 --- products/dialogue/source/params.cpp | 2 +- products/dialogue/tests/engine_tests.cpp | 12 ++++++++++++ products/leveler/source/ui/control_deck.cpp | 4 ++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/products/dialogue/source/params.cpp b/products/dialogue/source/params.cpp index e65482be..a0b329c0 100644 --- a/products/dialogue/source/params.cpp +++ b/products/dialogue/source/params.cpp @@ -48,7 +48,7 @@ namespace altvane::dialogue::params { return formatSensitivity(v); }) .withValueFromStringFunction([](const juce::String& t) { - return t.retainCharacters("+-.0123456789").getFloatValue() / 100.f; + return static_cast(ui::format::parseLenient(t).value_or(0.0)) / 100.f; }); for (size_t s = 0; s < dsp::kNumStems; ++s) { for (size_t n = 0; n < dsp::kSensitivityNodes; ++n) { diff --git a/products/dialogue/tests/engine_tests.cpp b/products/dialogue/tests/engine_tests.cpp index 6e8c9885..0ea5c712 100644 --- a/products/dialogue/tests/engine_tests.cpp +++ b/products/dialogue/tests/engine_tests.cpp @@ -1003,3 +1003,15 @@ TEST_CASE("level text round-trips, with Off at the bottom", "[params]") { const auto shown = voice->getText(voice->convertTo0to1(-6.f), 32); CHECK(std::abs(voice->convertFrom0to1(voice->getValueForText(shown)) + 6.f) < .05f); } + +TEST_CASE("sensitivity text reads either minus sign", "[params]") { + PluginProcessor p; + auto* sensitivity = p.parameters_.getParameter(params::sensitivityID(0, 0)); + for (const auto* text : {"-50%", "\u221250%", "\u2212 50 %"}) { + CHECK(std::abs(sensitivity->convertFrom0to1(sensitivity->getValueForText(juce::CharPointer_UTF8(text))) + .5f) < 1e-4f); + } + CHECK(std::abs(sensitivity->convertFrom0to1(sensitivity->getValueForText("+25%")) - .25f) < 1e-4f); + // what the interface shows reads back + const auto shown = sensitivity->getText(sensitivity->convertTo0to1(-.4f), 32); + CHECK(std::abs(sensitivity->convertFrom0to1(sensitivity->getValueForText(shown)) + .4f) < 1e-4f); +} diff --git a/products/leveler/source/ui/control_deck.cpp b/products/leveler/source/ui/control_deck.cpp index de5fbd68..facf5b73 100644 --- a/products/leveler/source/ui/control_deck.cpp +++ b/products/leveler/source/ui/control_deck.cpp @@ -39,8 +39,8 @@ namespace altvane::leveler { if (b.percent) { b.knob.format = [](const float v) { return params::formatPercent(v); }; b.knob.parse = [](const juce::String& t) -> std::optional { - const auto clean = t.retainCharacters("+-.0123456789"); - return clean.containsAnyOf("0123456789") ? std::optional(clean.getFloatValue() / 100.f) : std::nullopt; + const auto value = ui::format::parseLenient(t); + return value ? std::optional(static_cast(*value) / 100.f) : std::nullopt; }; } else { b.knob.format = [](const float v) { return params::formatDb(v); };