diff --git a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm index 22754be9dd..b2f2902ac3 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm @@ -878,7 +878,15 @@ public: { #if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE if (isParameterDiscrete) + { outParameterInfo.unit = kAudioUnitParameterUnit_Indexed; + + if (auto* param = juceFilter->getParameters()[index]) + { + if (param->isBoolean()) + outParameterInfo.unit = kAudioUnitParameterUnit_Boolean; + } + } #endif } @@ -1826,18 +1834,18 @@ private: OwnedArray* stringValues = nullptr; #if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE - if (juceFilter->isParameterDiscrete (index)) + if (auto* param = juceFilter->getParameters()[index]) { - if (auto* param = juceFilter->getParameters()[index]) + if (param->isDiscrete()) { - const auto numSteps = juceFilter->getParameterNumSteps (index); + const auto numSteps = param->getNumSteps(); stringValues = new OwnedArray(); stringValues->ensureStorageAllocated (numSteps); const auto maxValue = getMaximumParameterValue (index); for (int i = 0; i < numSteps; ++i) - stringValues->add (CFStringCreateCopy (nullptr, (param->getText ((float) i / maxValue, 0)).toCFString())); ; + stringValues->add (CFStringCreateCopy (nullptr, (param->getText ((float) i / maxValue, 0)).toCFString())); } } #endif diff --git a/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm b/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm index 527bf55e1c..61d6a44bd6 100644 --- a/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm +++ b/modules/juce_audio_plugin_client/AU/juce_AUv3_Wrapper.mm @@ -1182,7 +1182,7 @@ private: { if (param->isDiscrete()) { - unit = kAudioUnitParameterUnit_Indexed; + unit = param->isBoolean() ? kAudioUnitParameterUnit_Boolean : kAudioUnitParameterUnit_Indexed; auto maxValue = getMaximumParameterValue (idx); auto numSteps = param->getNumSteps(); diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp index 0e88909871..9c1d339e5b 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp +++ b/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp @@ -1365,6 +1365,7 @@ bool AudioProcessorParameter::isMetaParameter() const AudioProcessorParameter::Category AudioProcessorParameter::getCategory() const { return genericParameter; } int AudioProcessorParameter::getNumSteps() const { return AudioProcessor::getDefaultNumParameterSteps(); } bool AudioProcessorParameter::isDiscrete() const { return false; } +bool AudioProcessorParameter::isBoolean() const { return false; } String AudioProcessorParameter::getText (float value, int /*maximumStringLength*/) const { diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h b/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h index c73393f23c..0cdd8254a4 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h @@ -133,6 +133,18 @@ public: */ virtual bool isDiscrete() const; + /** Returns whether the parameter represents a boolean switch, typically with + "On" and "Off" states. + + This information may or may not be used, depending on the host. If you + want the host to display a switch, rather than a two item dropdown menu, + override this method to return true. You also need to override + isDiscrete() to return `true` and getNumSteps() to return `2`. + + @see isDiscrete getNumSteps + */ + virtual bool isBoolean() const; + /** Returns a textual version of the supplied parameter value. The default implementation just returns the floating point value as a string, but this could do anything you need for a custom type diff --git a/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h b/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h index ee143a1d35..51be1c8d79 100644 --- a/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h +++ b/modules/juce_audio_processors/utilities/juce_AudioParameterBool.h @@ -60,17 +60,19 @@ protected: private: //============================================================================== - float value; - const float defaultValue; - float getValue() const override; void setValue (float newValue) override; float getDefaultValue() const override; int getNumSteps() const override; bool isDiscrete() const override; + bool isBoolean() const override; String getText (float, int) const override; float getValueForText (const String&) const override; + float value; + const float defaultValue; + StringArray onStrings, offStrings; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterBool) }; diff --git a/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp b/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp index 82c3b76ad2..acda82fd72 100644 --- a/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp +++ b/modules/juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp @@ -121,6 +121,13 @@ AudioParameterBool::AudioParameterBool (const String& idToUse, const String& nam value (def ? 1.0f : 0.0f), defaultValue (value) { + onStrings.add (TRANS("on")); + onStrings.add (TRANS("yes")); + onStrings.add (TRANS("true")); + + offStrings.add (TRANS("off")); + offStrings.add (TRANS("no")); + offStrings.add (TRANS("false")); } AudioParameterBool::~AudioParameterBool() {} @@ -130,10 +137,29 @@ void AudioParameterBool::setValue (float newValue) { value float AudioParameterBool::getDefaultValue() const { return defaultValue; } int AudioParameterBool::getNumSteps() const { return 2; } bool AudioParameterBool::isDiscrete() const { return true; } -float AudioParameterBool::getValueForText (const String& text) const { return text.getIntValue() != 0 ? 1.0f : 0.0f; } -String AudioParameterBool::getText (float v, int /*length*/) const { return String ((int) (v > 0.5f ? 1 : 0)); } +bool AudioParameterBool::isBoolean() const { return true; } void AudioParameterBool::valueChanged (bool) {} +float AudioParameterBool::getValueForText (const String& text) const +{ + String lowercaseText (text.toLowerCase()); + + for (auto& testText : onStrings) + if (lowercaseText == testText) + return 1.0f; + + for (auto& testText : offStrings) + if (lowercaseText == testText) + return 0.0f; + + return text.getIntValue() != 0 ? 1.0f : 0.0f; +} + +String AudioParameterBool::getText (float v, int /*length*/) const +{ + return v < 0.5f ? TRANS("Off") : TRANS("On"); +} + AudioParameterBool& AudioParameterBool::operator= (bool newValue) { if (get() != newValue)