mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AUv3: Improved the host-provided parameter views
This commit is contained in:
parent
c24c06d2bb
commit
3c0d634b4f
2 changed files with 103 additions and 17 deletions
|
|
@ -525,11 +525,11 @@ public:
|
|||
{
|
||||
if (juceFilter != nullptr)
|
||||
{
|
||||
const int paramID = getJuceIndexForAUParameterID (pv->inParamID);
|
||||
const int i = getJuceIndexForAUParameterID (pv->inParamID);
|
||||
const String text (String::fromCFString (pv->inString));
|
||||
|
||||
if (AudioProcessorParameter* param = juceFilter->getParameters() [paramID])
|
||||
pv->outValue = param->getValueForText (text) * getMaximumParameterValue (paramID);
|
||||
if (AudioProcessorParameter* param = juceFilter->getParameters()[i])
|
||||
pv->outValue = param->getValueForText (text) * getMaximumParameterValue (i);
|
||||
else
|
||||
pv->outValue = text.getFloatValue();
|
||||
|
||||
|
|
@ -545,12 +545,12 @@ public:
|
|||
{
|
||||
if (juceFilter != nullptr)
|
||||
{
|
||||
const int paramID = getJuceIndexForAUParameterID (pv->inParamID);
|
||||
const int i = getJuceIndexForAUParameterID (pv->inParamID);
|
||||
const float value = (float) *(pv->inValue);
|
||||
String text;
|
||||
|
||||
if (AudioProcessorParameter* param = juceFilter->getParameters() [paramID])
|
||||
text = param->getText (value / getMaximumParameterValue (paramID), 0);
|
||||
if (AudioProcessorParameter* param = juceFilter->getParameters()[i])
|
||||
text = param->getText (value / getMaximumParameterValue (i), 0);
|
||||
else
|
||||
text = String (value);
|
||||
|
||||
|
|
@ -776,7 +776,7 @@ public:
|
|||
return (UInt32) layouts.size();
|
||||
}
|
||||
|
||||
OSStatus SetAudioChannelLayout(AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override
|
||||
OSStatus SetAudioChannelLayout (AudioUnitScope scope, AudioUnitElement element, const AudioChannelLayout* inLayout) override
|
||||
{
|
||||
bool isInput;
|
||||
int busNr;
|
||||
|
|
@ -877,8 +877,8 @@ public:
|
|||
else
|
||||
{
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
outParameterInfo.unit = isParameterDiscrete ? kAudioUnitParameterUnit_Indexed
|
||||
: kAudioUnitParameterUnit_Generic;
|
||||
if (isParameterDiscrete)
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_Indexed;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1082,13 +1082,22 @@ private:
|
|||
busses: array];
|
||||
}
|
||||
|
||||
// When parameters are discrete we need to use integer values.
|
||||
float getMaximumParameterValue (int parameterIndex)
|
||||
{
|
||||
#if JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
ignoreUnused (parameterIndex);
|
||||
return 1.0f;
|
||||
#else
|
||||
auto& processor = getAudioProcessor();
|
||||
return processor.isParameterDiscrete (parameterIndex) ? (float) (processor.getParameterNumSteps (parameterIndex) - 1) : 1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
void addParameters()
|
||||
{
|
||||
ScopedPointer<NSMutableArray<AUParameterNode*>> params = [[NSMutableArray<AUParameterNode*> alloc] init];
|
||||
|
||||
paramObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
|
||||
paramProvider = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
|
||||
|
||||
overviewParams = [[NSMutableArray<NSNumber*> alloc] init];
|
||||
|
||||
auto& processor = getAudioProcessor();
|
||||
|
|
@ -1118,9 +1127,17 @@ private:
|
|||
if (name.isEmpty() || ! processor.isParameterAutomatable (idx))
|
||||
flags |= kAudioUnitParameterFlag_NonRealTime;
|
||||
|
||||
const bool isParameterDiscrete = processor.isParameterDiscrete (idx);
|
||||
|
||||
if (! isParameterDiscrete)
|
||||
flags |= kAudioUnitParameterFlag_CanRamp;
|
||||
|
||||
if (processor.isMetaParameter (idx))
|
||||
flags |= kAudioUnitParameterFlag_IsGlobalMeta;
|
||||
|
||||
auto deleter = [](NSMutableArray* arr) { [arr release]; };
|
||||
std::unique_ptr<NSMutableArray, decltype (deleter)> valueStrings (nullptr, deleter);
|
||||
|
||||
// is this a meter?
|
||||
if (((processor.getParameterCategory (idx) & 0xffff0000) >> 16) == 2)
|
||||
{
|
||||
|
|
@ -1128,13 +1145,36 @@ private:
|
|||
flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
|
||||
unit = kAudioUnitParameterUnit_LinearGain;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
if (auto* param = processor.getParameters()[idx])
|
||||
{
|
||||
if (param->isDiscrete())
|
||||
{
|
||||
unit = kAudioUnitParameterUnit_Indexed;
|
||||
auto maxValue = getMaximumParameterValue (idx);
|
||||
auto numSteps = param->getNumSteps();
|
||||
|
||||
// Some hosts can't handle the huge numbers of discrete parameter values created when
|
||||
// using the default number of steps.
|
||||
jassert (numSteps != AudioProcessor::getDefaultNumParameterSteps());
|
||||
|
||||
valueStrings.reset ([NSMutableArray new]);
|
||||
|
||||
for (int i = 0; i < numSteps; ++i)
|
||||
[valueStrings.get() addObject: juceStringToNS (param->getText ((float) i / maxValue, 0))];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
AUParameterAddress address = static_cast<AUParameterAddress> (idx);
|
||||
#else
|
||||
AUParameterAddress address = generateAUParameterAddressForIndex (idx);
|
||||
|
||||
// Consider yourself very unlucky if you hit this assertion. The hash code of your
|
||||
// Consider yourself very unlucky if you hit this assertion. The hash codes of your
|
||||
// parameter ids are not unique.
|
||||
jassert (! paramMap.contains (static_cast<int64> (address)));
|
||||
|
||||
|
|
@ -1148,13 +1188,15 @@ private:
|
|||
name: juceStringToNS (name)
|
||||
address: address
|
||||
min: 0.0f
|
||||
max: 1.0f
|
||||
max: getMaximumParameterValue (idx)
|
||||
unit: unit
|
||||
unitName: nullptr
|
||||
flags: flags
|
||||
valueStrings: nullptr
|
||||
valueStrings: valueStrings.get()
|
||||
dependentParameters: nullptr] retain];
|
||||
|
||||
[param.get() setValue: processor.getParameterDefaultValue (idx)];
|
||||
|
||||
[params addObject: param];
|
||||
[overviewParams addObject: [NSNumber numberWithUnsignedLongLong:address]];
|
||||
}
|
||||
|
|
@ -1162,8 +1204,15 @@ private:
|
|||
// create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
|
||||
paramTree = [[AUParameterTree createTreeWithChildren: params] retain];
|
||||
|
||||
paramObserver = CreateObjCBlock (this, &JuceAudioUnitv3::valueChangedFromHost);
|
||||
paramProvider = CreateObjCBlock (this, &JuceAudioUnitv3::getValue);
|
||||
stringFromValueProvider = CreateObjCBlock (this, &JuceAudioUnitv3::stringFromValue);
|
||||
valueFromStringProvider = CreateObjCBlock (this, &JuceAudioUnitv3::valueFromString);
|
||||
|
||||
[paramTree setImplementorValueObserver: paramObserver];
|
||||
[paramTree setImplementorValueProvider: paramProvider];
|
||||
[paramTree setImplementorStringFromValueCallback: stringFromValueProvider];
|
||||
[paramTree setImplementorValueFromStringCallback: valueFromStringProvider];
|
||||
|
||||
if (processor.hasEditor())
|
||||
{
|
||||
|
|
@ -1375,7 +1424,7 @@ private:
|
|||
auto& processor = getAudioProcessor();
|
||||
|
||||
if (isPositiveAndBelow (idx, processor.getNumParameters()))
|
||||
processor.setParameter (idx, value);
|
||||
processor.setParameter (idx, value / getMaximumParameterValue (idx));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1387,7 +1436,7 @@ private:
|
|||
auto& processor = getAudioProcessor();
|
||||
|
||||
if (isPositiveAndBelow (idx, processor.getNumParameters()))
|
||||
return processor.getParameter (idx);
|
||||
return processor.getParameter (idx) * getMaximumParameterValue (idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1398,6 +1447,41 @@ private:
|
|||
// this will have already been handled by valueChangedFromHost
|
||||
}
|
||||
|
||||
NSString* stringFromValue (AUParameter* param, const AUValue* value)
|
||||
{
|
||||
String text;
|
||||
|
||||
if (param != nullptr && value != nullptr)
|
||||
{
|
||||
const int idx = getJuceParameterIndexForAUAddress ([param address]);
|
||||
auto& processor = getAudioProcessor();
|
||||
|
||||
if (auto* p = processor.getParameters()[idx])
|
||||
text = p->getText (*value / getMaximumParameterValue (idx), 0);
|
||||
else
|
||||
text = String (*value);
|
||||
}
|
||||
|
||||
return juceStringToNS (text);
|
||||
}
|
||||
|
||||
AUValue valueFromString (AUParameter* param, NSString* str)
|
||||
{
|
||||
if (param != nullptr && str != nullptr)
|
||||
{
|
||||
const int idx = getJuceParameterIndexForAUAddress ([param address]);
|
||||
auto& processor = getAudioProcessor();
|
||||
const String text (nsStringToJuce (str));
|
||||
|
||||
if (auto* p = processor.getParameters()[idx])
|
||||
return p->getValueForText (text) * getMaximumParameterValue (idx);
|
||||
else
|
||||
return text.getFloatValue();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
inline AUParameterAddress getAUParameterAddressForIndex (int paramIndex) const noexcept { return static_cast<AUParameterAddress> (paramIndex); }
|
||||
|
|
@ -1443,6 +1527,8 @@ private:
|
|||
|
||||
ObjCBlock<AUImplementorValueObserver> paramObserver;
|
||||
ObjCBlock<AUImplementorValueProvider> paramProvider;
|
||||
ObjCBlock<AUImplementorStringFromValueCallback> stringFromValueProvider;
|
||||
ObjCBlock<AUImplementorValueFromStringCallback> valueFromStringProvider;
|
||||
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
bool usingManagedParameter;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue