mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Re-worked plug-in wrappers to all use new parameter system via LegacyAudioParameter wrapper class
This commit is contained in:
parent
2ff4d858c6
commit
e05a1549f2
13 changed files with 842 additions and 779 deletions
|
|
@ -307,6 +307,7 @@ struct GraphEditorPanel::FilterComponent : public Component
|
|||
case 12: showWindow (PluginWindow::Type::generic); break;
|
||||
case 20: showWindow (PluginWindow::Type::audioIO); break;
|
||||
case 21: testStateSaveLoad(); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
#include "../utility/juce_WindowsHooks.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
|
||||
#include "../../juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
|
|
@ -635,6 +637,7 @@ namespace AAXClasses
|
|||
AAX_Result Uninitialize() override
|
||||
{
|
||||
cancelPendingUpdate();
|
||||
juceParameters.clear();
|
||||
|
||||
if (isPrepared && pluginInstance != nullptr)
|
||||
{
|
||||
|
|
@ -724,11 +727,11 @@ namespace AAXClasses
|
|||
// * The preset is loaded in PT 10 using the AAX version.
|
||||
// * The session is then saved, and closed.
|
||||
// * The saved session is loaded, but acting as if the preset was never loaded.
|
||||
auto numParameters = pluginInstance->getNumParameters();
|
||||
auto numParameters = juceParameters.getNumParameters();
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
if (auto paramID = getAAXParamIDFromJuceIndex(i))
|
||||
SetParameterNormalizedValue (paramID, (double) pluginInstance->getParameter(i));
|
||||
SetParameterNormalizedValue (paramID, juceParameters.getParamForIndex (i)->getValue());
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
|
@ -782,22 +785,20 @@ namespace AAXClasses
|
|||
return AAX_SUCCESS;
|
||||
}
|
||||
|
||||
void setAudioProcessorParameter (int index, float value)
|
||||
void setAudioProcessorParameter (AAX_CParamID paramID, double value)
|
||||
{
|
||||
if (auto* param = pluginInstance->getParameters()[index])
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
{
|
||||
if (value != param->getValue())
|
||||
auto newValue = static_cast<float> (value);
|
||||
|
||||
if (newValue != param->getValue())
|
||||
{
|
||||
param->setValue (value);
|
||||
param->setValue (newValue);
|
||||
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (value);
|
||||
param->sendValueChangedMessageToListeners (newValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pluginInstance->setParameter (index, value);
|
||||
}
|
||||
}
|
||||
|
||||
AAX_Result UpdateParameterNormalizedValue (AAX_CParamID paramID, double value, AAX_EUpdateSource source) override
|
||||
|
|
@ -805,7 +806,7 @@ namespace AAXClasses
|
|||
auto result = AAX_CEffectParameters::UpdateParameterNormalizedValue (paramID, value, source);
|
||||
|
||||
if (! isBypassParam (paramID))
|
||||
setAudioProcessorParameter (getParamIndexFromID (paramID), (float) value);
|
||||
setAudioProcessorParameter (paramID, value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -818,10 +819,13 @@ namespace AAXClasses
|
|||
return AAX_SUCCESS;
|
||||
}
|
||||
|
||||
if (AudioProcessorParameter* param = pluginInstance->getParameters() [getParamIndexFromID (paramID)])
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
{
|
||||
*result = param->getValueForText (text.Get());
|
||||
return AAX_SUCCESS;
|
||||
if (! LegacyAudioParameter::isLegacy (param))
|
||||
{
|
||||
*result = param->getValueForText (text.Get());
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return AAX_CEffectParameters::GetParameterValueFromString (paramID, result, text);
|
||||
|
|
@ -835,15 +839,8 @@ namespace AAXClasses
|
|||
}
|
||||
else
|
||||
{
|
||||
auto paramIndex = getParamIndexFromID (paramID);
|
||||
juce::String text;
|
||||
|
||||
if (auto* param = pluginInstance->getParameters() [paramIndex])
|
||||
text = param->getText ((float) value, maxLen);
|
||||
else
|
||||
text = pluginInstance->getParameterText (paramIndex, maxLen);
|
||||
|
||||
result->Set (text.toRawUTF8());
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
result->Set (param->getText ((float) value, maxLen).toRawUTF8());
|
||||
}
|
||||
|
||||
return AAX_SUCCESS;
|
||||
|
|
@ -852,9 +849,14 @@ namespace AAXClasses
|
|||
AAX_Result GetParameterNumberofSteps (AAX_CParamID paramID, int32_t* result) const
|
||||
{
|
||||
if (isBypassParam (paramID))
|
||||
{
|
||||
*result = 2;
|
||||
}
|
||||
else
|
||||
*result = pluginInstance->getParameterNumSteps (getParamIndexFromID (paramID));
|
||||
{
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
*result = param->getNumSteps();
|
||||
}
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
|
@ -864,7 +866,11 @@ namespace AAXClasses
|
|||
if (isBypassParam (paramID))
|
||||
return AAX_CEffectParameters::GetParameterNormalizedValue (paramID, result);
|
||||
|
||||
*result = pluginInstance->getParameter (getParamIndexFromID (paramID));
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
*result = (double) param->getValue();
|
||||
else
|
||||
*result = 0.0;
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -876,7 +882,7 @@ namespace AAXClasses
|
|||
if (auto* p = mParameterManager.GetParameterByID (paramID))
|
||||
p->SetValueWithFloat ((float) newValue);
|
||||
|
||||
setAudioProcessorParameter (getParamIndexFromID (paramID), (float) newValue);
|
||||
setAudioProcessorParameter (paramID, (float) newValue);
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
|
@ -886,13 +892,15 @@ namespace AAXClasses
|
|||
if (isBypassParam (paramID))
|
||||
return AAX_CEffectParameters::SetParameterNormalizedRelative (paramID, newDeltaValue);
|
||||
|
||||
auto paramIndex = getParamIndexFromID (paramID);
|
||||
auto newValue = pluginInstance->getParameter (paramIndex) + (float) newDeltaValue;
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
{
|
||||
auto newValue = param->getValue() + (float) newDeltaValue;
|
||||
|
||||
setAudioProcessorParameter (paramIndex, jlimit (0.0f, 1.0f, newValue));
|
||||
setAudioProcessorParameter (paramID, jlimit (0.0f, 1.0f, newValue));
|
||||
|
||||
if (auto* p = mParameterManager.GetParameterByID (paramID))
|
||||
p->SetValueWithFloat (newValue);
|
||||
if (auto* p = mParameterManager.GetParameterByID (paramID))
|
||||
p->SetValueWithFloat (newValue);
|
||||
}
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
|
@ -900,11 +908,15 @@ namespace AAXClasses
|
|||
AAX_Result GetParameterNameOfLength (AAX_CParamID paramID, AAX_IString* result, int32_t maxLen) const override
|
||||
{
|
||||
if (isBypassParam (paramID))
|
||||
{
|
||||
result->Set (maxLen >= 13 ? "Master Bypass"
|
||||
: (maxLen >= 8 ? "Mast Byp"
|
||||
: (maxLen >= 6 ? "MstByp" : "MByp")));
|
||||
else
|
||||
result->Set (pluginInstance->getParameterName (getParamIndexFromID (paramID), maxLen).toRawUTF8());
|
||||
}
|
||||
else if (auto* param = getParameterFromID (paramID))
|
||||
{
|
||||
result->Set (param->getName (maxLen).toRawUTF8());
|
||||
}
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
|
@ -913,8 +925,8 @@ namespace AAXClasses
|
|||
{
|
||||
if (isBypassParam (paramID))
|
||||
result->Set ("Master Bypass");
|
||||
else
|
||||
result->Set (pluginInstance->getParameterName (getParamIndexFromID (paramID), 31).toRawUTF8());
|
||||
else if (auto* param = getParameterFromID (paramID))
|
||||
result->Set (param->getName (31).toRawUTF8());
|
||||
|
||||
return AAX_SUCCESS;
|
||||
}
|
||||
|
|
@ -923,7 +935,10 @@ namespace AAXClasses
|
|||
{
|
||||
if (! isBypassParam (paramID))
|
||||
{
|
||||
*result = (double) pluginInstance->getParameterDefaultValue (getParamIndexFromID (paramID));
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
*result = (double) param->getDefaultValue();
|
||||
else
|
||||
*result = 0.0;
|
||||
|
||||
jassert (*result >= 0 && *result <= 1.0f);
|
||||
}
|
||||
|
|
@ -1014,13 +1029,13 @@ namespace AAXClasses
|
|||
{
|
||||
++mNumPlugInChanges;
|
||||
|
||||
auto numParameters = pluginInstance->getNumParameters();
|
||||
auto numParameters = juceParameters.getNumParameters();
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
{
|
||||
if (auto* p = mParameterManager.GetParameterByID (getAAXParamIDFromJuceIndex (i)))
|
||||
{
|
||||
auto newName = processor->getParameterName (i, 31);
|
||||
auto newName = juceParameters.getParamForIndex (i)->getName (31);
|
||||
|
||||
if (p->Name() != newName.toRawUTF8())
|
||||
p->SetName (AAX_CString (newName.toRawUTF8()));
|
||||
|
|
@ -1158,7 +1173,7 @@ namespace AAXClasses
|
|||
|
||||
if (meterBuffers != nullptr)
|
||||
for (int i = 0; i < numMeters; ++i)
|
||||
meterBuffers[i] = pluginInstance->getParameter (aaxMeters[i]);
|
||||
meterBuffers[i] = aaxMeters[i]->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1422,53 +1437,56 @@ namespace AAXClasses
|
|||
void addAudioProcessorParameters()
|
||||
{
|
||||
auto& audioProcessor = getPluginInstance();
|
||||
auto numParameters = audioProcessor.getNumParameters();
|
||||
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
const bool usingManagedParameters = false;
|
||||
const bool forceLegacyParamIDs = true;
|
||||
#else
|
||||
const bool usingManagedParameters = (audioProcessor.getParameters().size() == numParameters);
|
||||
const bool forceLegacyParamIDs = false;
|
||||
#endif
|
||||
|
||||
for (int parameterIndex = 0; parameterIndex < numParameters; ++parameterIndex)
|
||||
juceParameters.update (audioProcessor, forceLegacyParamIDs);
|
||||
int parameterIndex = 0;
|
||||
|
||||
for (auto* juceParam : juceParameters.params)
|
||||
{
|
||||
auto category = audioProcessor.getParameterCategory (parameterIndex);
|
||||
auto category = juceParam->getCategory();
|
||||
auto paramID = juceParameters.getParamID (audioProcessor, parameterIndex)
|
||||
.toRawUTF8();
|
||||
|
||||
aaxParamIDs.add (usingManagedParameters ? audioProcessor.getParameterID (parameterIndex)
|
||||
: String (parameterIndex));
|
||||
aaxParamIDs.add (paramID);
|
||||
auto aaxParamID = aaxParamIDs.getReference (parameterIndex++).getCharPointer();
|
||||
|
||||
auto paramID = aaxParamIDs.getReference (parameterIndex).getCharPointer();
|
||||
|
||||
paramMap.set (AAXClasses::getAAXParamHash (paramID), parameterIndex);
|
||||
paramMap.set (AAXClasses::getAAXParamHash (aaxParamID), juceParam);
|
||||
|
||||
// is this a meter?
|
||||
if (((category & 0xffff0000) >> 16) == 2)
|
||||
{
|
||||
aaxMeters.add (parameterIndex);
|
||||
aaxMeters.add (juceParam);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto parameter = new AAX_CParameter<float> (paramID,
|
||||
AAX_CString (audioProcessor.getParameterName (parameterIndex, 31).toRawUTF8()),
|
||||
audioProcessor.getParameterDefaultValue (parameterIndex),
|
||||
auto parameter = new AAX_CParameter<float> (aaxParamID,
|
||||
AAX_CString (juceParam->getName (31).toRawUTF8()),
|
||||
juceParam->getDefaultValue(),
|
||||
AAX_CLinearTaperDelegate<float, 0>(),
|
||||
AAX_CNumberDisplayDelegate<float, 3>(),
|
||||
audioProcessor.isParameterAutomatable (parameterIndex));
|
||||
juceParam->isAutomatable());
|
||||
|
||||
parameter->AddShortenedName (audioProcessor.getParameterName (parameterIndex, 4).toRawUTF8());
|
||||
parameter->AddShortenedName (juceParam->getName (4).toRawUTF8());
|
||||
|
||||
auto parameterNumSteps = audioProcessor.getParameterNumSteps (parameterIndex);
|
||||
auto parameterNumSteps = juceParam->getNumSteps();
|
||||
parameter->SetNumberOfSteps ((uint32_t) parameterNumSteps);
|
||||
|
||||
#if JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
parameter->SetType (parameterNumSteps > 1000 ? AAX_eParameterType_Continuous
|
||||
: AAX_eParameterType_Discrete);
|
||||
#else
|
||||
parameter->SetType (audioProcessor.isParameterDiscrete (parameterIndex) ? AAX_eParameterType_Discrete
|
||||
: AAX_eParameterType_Continuous);
|
||||
parameter->SetType (juceParam->isDiscrete() ? AAX_eParameterType_Discrete
|
||||
: AAX_eParameterType_Continuous);
|
||||
#endif
|
||||
|
||||
parameter->SetOrientation (audioProcessor.isParameterOrientationInverted (parameterIndex)
|
||||
parameter->SetOrientation (juceParam->isOrientationInverted()
|
||||
? (AAX_eParameterOrientation_RightMinLeftMax | AAX_eParameterOrientation_TopMinBottomMax
|
||||
| AAX_eParameterOrientation_RotarySingleDotMode | AAX_eParameterOrientation_RotaryRightMinLeftMax)
|
||||
: (AAX_eParameterOrientation_LeftMinRightMax | AAX_eParameterOrientation_BottomMinTopMax
|
||||
|
|
@ -1696,7 +1714,10 @@ namespace AAXClasses
|
|||
//==============================================================================
|
||||
inline int getParamIndexFromID (AAX_CParamID paramID) const noexcept
|
||||
{
|
||||
return paramMap [AAXClasses::getAAXParamHash (paramID)];
|
||||
if (auto* param = getParameterFromID (paramID))
|
||||
return LegacyAudioParameter::getParamIndex (getPluginInstance(), param);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline AAX_CParamID getAAXParamIDFromJuceIndex (int index) const noexcept
|
||||
|
|
@ -1707,6 +1728,11 @@ namespace AAXClasses
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
AudioProcessorParameter* getParameterFromID (AAX_CParamID paramID) const noexcept
|
||||
{
|
||||
return paramMap [AAXClasses::getAAXParamHash (paramID)];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static AudioProcessor::BusesLayout getDefaultLayout (const AudioProcessor& p, bool enableAll)
|
||||
{
|
||||
|
|
@ -1757,9 +1783,10 @@ namespace AAXClasses
|
|||
Array<int> inputLayoutMap, outputLayoutMap;
|
||||
|
||||
Array<String> aaxParamIDs;
|
||||
HashMap<int32, int> paramMap;
|
||||
HashMap<int32, AudioProcessorParameter*> paramMap;
|
||||
LegacyAudioParametersWrapper juceParameters;
|
||||
|
||||
Array<int> aaxMeters;
|
||||
Array<AudioProcessorParameter*> aaxMeters;
|
||||
|
||||
struct ChunkMemoryBlock
|
||||
{
|
||||
|
|
@ -1835,12 +1862,21 @@ namespace AAXClasses
|
|||
//==============================================================================
|
||||
static int addAAXMeters (AudioProcessor& p, AAX_IEffectDescriptor& descriptor)
|
||||
{
|
||||
const int n = p.getNumParameters();
|
||||
LegacyAudioParametersWrapper params;
|
||||
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
const bool forceLegacyParamIDs = true;
|
||||
#else
|
||||
const bool forceLegacyParamIDs = false;
|
||||
#endif
|
||||
|
||||
params.update (p, forceLegacyParamIDs);
|
||||
|
||||
int meterIdx = 0;
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
for (auto* param : params.params)
|
||||
{
|
||||
auto category = p.getParameterCategory (i);
|
||||
auto category = param->getCategory();
|
||||
|
||||
// is this a meter?
|
||||
if (((category & 0xffff0000) >> 16) == 2)
|
||||
|
|
@ -1851,7 +1887,7 @@ namespace AAXClasses
|
|||
meterProperties->AddProperty (AAX_eProperty_Meter_Orientation, AAX_eMeterOrientation_TopRight);
|
||||
|
||||
descriptor.AddMeterDescription ('Metr' + static_cast<AAX_CTypeID> (meterIdx++),
|
||||
p.getParameterName (i).toRawUTF8(), meterProperties);
|
||||
param->getName (1024).toRawUTF8(), meterProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@
|
|||
#include "../utility/juce_CarbonVisibility.h"
|
||||
|
||||
#include "../../juce_audio_basics/native/juce_mac_CoreAudioLayouts.h"
|
||||
#include "../../juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp"
|
||||
#include "../../juce_audio_processors/format_types/juce_AU_Shared.h"
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -527,15 +528,18 @@ public:
|
|||
{
|
||||
if (juceFilter != nullptr)
|
||||
{
|
||||
const int i = getJuceIndexForAUParameterID (pv->inParamID);
|
||||
const String text (String::fromCFString (pv->inString));
|
||||
if (auto* param = getParameterForAUParameterID (pv->inParamID))
|
||||
{
|
||||
const String text (String::fromCFString (pv->inString));
|
||||
|
||||
if (AudioProcessorParameter* param = juceFilter->getParameters()[i])
|
||||
pv->outValue = param->getValueForText (text) * getMaximumParameterValue (i);
|
||||
else
|
||||
pv->outValue = text.getFloatValue();
|
||||
if (LegacyAudioParameter::isLegacy (param))
|
||||
pv->outValue = text.getFloatValue();
|
||||
else
|
||||
pv->outValue = param->getValueForText (text) * getMaximumParameterValue (param);
|
||||
|
||||
return noErr;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -547,18 +551,20 @@ public:
|
|||
{
|
||||
if (juceFilter != nullptr)
|
||||
{
|
||||
const int i = getJuceIndexForAUParameterID (pv->inParamID);
|
||||
const float value = (float) *(pv->inValue);
|
||||
String text;
|
||||
if (auto* param = getParameterForAUParameterID (pv->inParamID))
|
||||
{
|
||||
const float value = (float) *(pv->inValue);
|
||||
String text;
|
||||
|
||||
if (AudioProcessorParameter* param = juceFilter->getParameters()[i])
|
||||
text = param->getText (value / getMaximumParameterValue (i), 0);
|
||||
else
|
||||
text = String (value);
|
||||
if (LegacyAudioParameter::isLegacy (param))
|
||||
text = String (value);
|
||||
else
|
||||
text = param->getText (value / getMaximumParameterValue (param), 0);
|
||||
|
||||
pv->outString = text.toCFString();
|
||||
pv->outString = text.toCFString();
|
||||
|
||||
return noErr;
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -793,7 +799,7 @@ public:
|
|||
if (inLayout == nullptr)
|
||||
return kAudioUnitErr_InvalidPropertyValue;
|
||||
|
||||
if (const AUIOElement* ioElement = GetIOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, element))
|
||||
if (const AUIOElement* ioElement = GetIOElement (isInput ? kAudioUnitScope_Input : kAudioUnitScope_Output, element))
|
||||
{
|
||||
const AudioChannelSet newChannelSet = CoreAudioLayouts::fromCoreAudio (*inLayout);
|
||||
const int currentNumChannels = static_cast<int> (ioElement->GetStreamFormat().NumberChannels());
|
||||
|
|
@ -825,82 +831,73 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
// When parameters are discrete we need to use integer values.
|
||||
float getMaximumParameterValue (int parameterIndex)
|
||||
float getMaximumParameterValue (AudioProcessorParameter* param)
|
||||
{
|
||||
#if JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
ignoreUnused (parameterIndex);
|
||||
return 1.0f;
|
||||
#else
|
||||
return juceFilter->isParameterDiscrete (parameterIndex) ? (float) (juceFilter->getParameterNumSteps (parameterIndex) - 1) : 1.0f;
|
||||
#endif
|
||||
return param->isDiscrete() && (! forceUseLegacyParamIDs) ? (float) (param->getNumSteps() - 1) : 1.0f;
|
||||
}
|
||||
|
||||
ComponentResult GetParameterInfo (AudioUnitScope inScope,
|
||||
AudioUnitParameterID inParameterID,
|
||||
AudioUnitParameterInfo& outParameterInfo) override
|
||||
{
|
||||
const int index = getJuceIndexForAUParameterID (inParameterID);
|
||||
|
||||
if (inScope == kAudioUnitScope_Global
|
||||
&& juceFilter != nullptr
|
||||
&& isPositiveAndBelow (index, juceFilter->getNumParameters()))
|
||||
if (inScope == kAudioUnitScope_Global && juceFilter != nullptr)
|
||||
{
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
|
||||
outParameterInfo.flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
|
||||
| kAudioUnitParameterFlag_IsReadable
|
||||
| kAudioUnitParameterFlag_HasCFNameString
|
||||
| kAudioUnitParameterFlag_ValuesHaveStrings);
|
||||
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
outParameterInfo.flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
|
||||
#endif
|
||||
|
||||
const String name (juceFilter->getParameterName (index));
|
||||
|
||||
// Set whether the param is automatable (unnamed parameters aren't allowed to be automated)
|
||||
if (name.isEmpty() || ! juceFilter->isParameterAutomatable (index))
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_NonRealTime;
|
||||
|
||||
const bool isParameterDiscrete = juceFilter->isParameterDiscrete (index);
|
||||
|
||||
if (! isParameterDiscrete)
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_CanRamp;
|
||||
|
||||
if (juceFilter->isMetaParameter (index))
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_IsGlobalMeta;
|
||||
|
||||
// Is this a meter?
|
||||
if (((juceFilter->getParameterCategory (index) & 0xffff0000) >> 16) == 2)
|
||||
{
|
||||
outParameterInfo.flags &= ~kAudioUnitParameterFlag_IsWritable;
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_LinearGain;
|
||||
}
|
||||
else
|
||||
if (auto* param = getParameterForAUParameterID (inParameterID))
|
||||
{
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_Generic;
|
||||
outParameterInfo.flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
|
||||
| kAudioUnitParameterFlag_IsReadable
|
||||
| kAudioUnitParameterFlag_HasCFNameString
|
||||
| kAudioUnitParameterFlag_ValuesHaveStrings);
|
||||
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
if (isParameterDiscrete)
|
||||
{
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_Indexed;
|
||||
outParameterInfo.flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
|
||||
#endif
|
||||
|
||||
if (auto* param = juceFilter->getParameters()[index])
|
||||
const String name = param->getName (1024);
|
||||
|
||||
// Set whether the param is automatable (unnamed parameters aren't allowed to be automated)
|
||||
if (name.isEmpty() || ! param->isAutomatable())
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_NonRealTime;
|
||||
|
||||
const bool isParameterDiscrete = param->isDiscrete();
|
||||
|
||||
if (! isParameterDiscrete)
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_CanRamp;
|
||||
|
||||
if (param->isMetaParameter())
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_IsGlobalMeta;
|
||||
|
||||
// Is this a meter?
|
||||
if (((param->getCategory() & 0xffff0000) >> 16) == 2)
|
||||
{
|
||||
outParameterInfo.flags &= ~kAudioUnitParameterFlag_IsWritable;
|
||||
outParameterInfo.flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_LinearGain;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
if (isParameterDiscrete)
|
||||
{
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_Indexed;
|
||||
|
||||
if (param->isBoolean())
|
||||
outParameterInfo.unit = kAudioUnitParameterUnit_Boolean;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
MusicDeviceBase::FillInParameterName (outParameterInfo, name.toCFString(), true);
|
||||
|
||||
outParameterInfo.minValue = 0.0f;
|
||||
outParameterInfo.maxValue = getMaximumParameterValue (param);
|
||||
outParameterInfo.defaultValue = param->getDefaultValue() * getMaximumParameterValue (param);
|
||||
jassert (outParameterInfo.defaultValue >= outParameterInfo.minValue
|
||||
&& outParameterInfo.defaultValue <= outParameterInfo.maxValue);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
MusicDeviceBase::FillInParameterName (outParameterInfo, name.toCFString(), true);
|
||||
|
||||
outParameterInfo.minValue = 0.0f;
|
||||
outParameterInfo.maxValue = getMaximumParameterValue (index);
|
||||
outParameterInfo.defaultValue = juceFilter->getParameterDefaultValue (index) * getMaximumParameterValue (index);
|
||||
jassert (outParameterInfo.defaultValue >= outParameterInfo.minValue
|
||||
&& outParameterInfo.defaultValue <= outParameterInfo.maxValue);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
return kAudioUnitErr_InvalidParameter;
|
||||
|
|
@ -913,21 +910,24 @@ public:
|
|||
if (outStrings == nullptr)
|
||||
return noErr;
|
||||
|
||||
const int index = getJuceIndexForAUParameterID (inParameterID);
|
||||
|
||||
if (inScope == kAudioUnitScope_Global
|
||||
&& juceFilter != nullptr
|
||||
&& isPositiveAndBelow (index, juceFilter->getNumParameters())
|
||||
&& juceFilter->isParameterDiscrete (index))
|
||||
if (inScope == kAudioUnitScope_Global && juceFilter != nullptr)
|
||||
{
|
||||
if (auto* valueStrings = parameterValueStringArrays[index])
|
||||
if (auto* param = getParameterForAUParameterID (inParameterID))
|
||||
{
|
||||
*outStrings = CFArrayCreate (NULL,
|
||||
(const void **) valueStrings->getRawDataPointer(),
|
||||
valueStrings->size(),
|
||||
NULL);
|
||||
if (param->isDiscrete())
|
||||
{
|
||||
auto index = LegacyAudioParameter::getParamIndex (*juceFilter, param);
|
||||
|
||||
return noErr;
|
||||
if (auto* valueStrings = parameterValueStringArrays[index])
|
||||
{
|
||||
*outStrings = CFArrayCreate (NULL,
|
||||
(const void **) valueStrings->getRawDataPointer(),
|
||||
valueStrings->size(),
|
||||
NULL);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -941,11 +941,13 @@ public:
|
|||
{
|
||||
if (inScope == kAudioUnitScope_Global && juceFilter != nullptr)
|
||||
{
|
||||
const auto index = getJuceIndexForAUParameterID (inID);
|
||||
const auto normValue = juceFilter->getParameter (index);
|
||||
if (auto* param = getParameterForAUParameterID (inID))
|
||||
{
|
||||
const auto normValue = param->getValue();
|
||||
|
||||
outValue = normValue * getMaximumParameterValue (index);
|
||||
return noErr;
|
||||
outValue = normValue * getMaximumParameterValue (param);
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
|
||||
return MusicDeviceBase::GetParameter (inID, inScope, inElement, outValue);
|
||||
|
|
@ -959,22 +961,17 @@ public:
|
|||
{
|
||||
if (inScope == kAudioUnitScope_Global && juceFilter != nullptr)
|
||||
{
|
||||
auto index = getJuceIndexForAUParameterID (inID);
|
||||
auto value = inValue / getMaximumParameterValue (index);
|
||||
|
||||
if (auto* param = juceFilter->getParameters()[index])
|
||||
if (auto* param = getParameterForAUParameterID (inID))
|
||||
{
|
||||
auto value = inValue / getMaximumParameterValue (param);
|
||||
|
||||
param->setValue (value);
|
||||
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
juceFilter->setParameter (index, value);
|
||||
}
|
||||
|
||||
return noErr;
|
||||
return noErr;
|
||||
}
|
||||
}
|
||||
|
||||
return MusicDeviceBase::SetParameter (inID, inScope, inElement, inValue, inBufferOffsetInFrames);
|
||||
|
|
@ -1660,12 +1657,17 @@ private:
|
|||
bool prepared, isBypassed;
|
||||
|
||||
//==============================================================================
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
bool usingManagedParameter;
|
||||
Array<AudioUnitParameterID> auParamIDs;
|
||||
HashMap<int32, int> paramMap;
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
static constexpr bool forceUseLegacyParamIDs = true;
|
||||
#else
|
||||
static constexpr bool forceUseLegacyParamIDs = false;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
LegacyAudioParametersWrapper juceParameters;
|
||||
HashMap<int32, AudioProcessorParameter*> paramMap;
|
||||
Array<AudioUnitParameterID> auParamIDs;
|
||||
|
||||
//==============================================================================
|
||||
AudioUnitEvent auEvent;
|
||||
mutable Array<AUPreset> presetsArray;
|
||||
|
|
@ -1814,109 +1816,95 @@ private:
|
|||
//==============================================================================
|
||||
void addParameters()
|
||||
{
|
||||
juceParameters.update (*juceFilter, forceUseLegacyParamIDs);
|
||||
|
||||
// check if all parameters are managed?
|
||||
const int numParams = juceFilter->getNumParameters();
|
||||
const int numParams = juceParameters.getNumParameters();
|
||||
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
usingManagedParameter = (juceFilter->getParameters().size() == numParams);
|
||||
|
||||
if (usingManagedParameter)
|
||||
for (auto* param : juceParameters.params)
|
||||
{
|
||||
for (int i = 0; i < numParams; ++i)
|
||||
{
|
||||
const AudioUnitParameterID auParamID = generateAUParameterIDForIndex (i);
|
||||
const AudioUnitParameterID auParamID = generateAUParameterID (param);
|
||||
|
||||
// Consider yourself very unlucky if you hit this assertion. The hash code of your
|
||||
// parameter ids are not unique.
|
||||
jassert (! paramMap.contains (static_cast<int32> (auParamID)));
|
||||
// Consider yourself very unlucky if you hit this assertion. The hash code of your
|
||||
// parameter ids are not unique.
|
||||
jassert (! paramMap.contains (static_cast<int32> (auParamID)));
|
||||
|
||||
auParamIDs.add (auParamID);
|
||||
paramMap.set (static_cast<int32> (auParamID), i);
|
||||
auParamIDs.add (auParamID);
|
||||
paramMap.set (static_cast<int32> (auParamID), param);
|
||||
|
||||
Globals()->SetParameter (auParamID, juceFilter->getParameter (i));
|
||||
}
|
||||
if (juceParameters.isUsingManagedParameters())
|
||||
Globals()->SetParameter (auParamID, param->getValue());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
if (! juceParameters.isUsingManagedParameters())
|
||||
Globals()->UseIndexedParameters (numParams);
|
||||
}
|
||||
|
||||
|
||||
#if JUCE_DEBUG
|
||||
// Some hosts can't handle the huge numbers of discrete parameter values created when
|
||||
// using the default number of steps.
|
||||
for (auto* param : juceFilter->getParameters())
|
||||
for (auto* param : juceParameters.params)
|
||||
if (param->isDiscrete())
|
||||
jassert (param->getNumSteps() != AudioProcessor::getDefaultNumParameterSteps());
|
||||
#endif
|
||||
|
||||
parameterValueStringArrays.ensureStorageAllocated (numParams);
|
||||
|
||||
for (int index = 0; index < numParams; ++index)
|
||||
for (auto* param : juceParameters.params)
|
||||
{
|
||||
OwnedArray<const __CFString>* stringValues = nullptr;
|
||||
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
if (auto* param = juceFilter->getParameters()[index])
|
||||
auto initialValue = param->getValue();
|
||||
|
||||
if (param->isDiscrete() && (! forceUseLegacyParamIDs))
|
||||
{
|
||||
if (param->isDiscrete())
|
||||
const auto numSteps = param->getNumSteps();
|
||||
stringValues = new OwnedArray<const __CFString>();
|
||||
stringValues->ensureStorageAllocated (numSteps);
|
||||
|
||||
const auto maxValue = getMaximumParameterValue (param);
|
||||
|
||||
for (int i = 0; i < numSteps; ++i)
|
||||
{
|
||||
const auto numSteps = param->getNumSteps();
|
||||
stringValues = new OwnedArray<const __CFString>();
|
||||
stringValues->ensureStorageAllocated (numSteps);
|
||||
auto value = (float) i / maxValue;
|
||||
|
||||
const auto maxValue = getMaximumParameterValue (index);
|
||||
|
||||
for (int i = 0; i < numSteps; ++i)
|
||||
stringValues->add (CFStringCreateCopy (nullptr, (param->getText ((float) i / maxValue, 0)).toCFString()));
|
||||
// Once legacy parameters are deprecated this can be replaced by getText
|
||||
param->setValue (value);
|
||||
stringValues->add (CFStringCreateCopy (nullptr, (param->getCurrentValueAsText().toCFString())));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
param->setValue (initialValue);
|
||||
|
||||
parameterValueStringArrays.add (stringValues);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
inline AudioUnitParameterID getAUParameterIDForIndex (int paramIndex) const noexcept { return static_cast<AudioUnitParameterID> (paramIndex); }
|
||||
inline int getJuceIndexForAUParameterID (AudioUnitParameterID address) const noexcept { return static_cast<int> (address); }
|
||||
#else
|
||||
AudioUnitParameterID generateAUParameterIDForIndex (int paramIndex) const
|
||||
AudioUnitParameterID generateAUParameterID (AudioProcessorParameter* param) const
|
||||
{
|
||||
const int n = juceFilter->getNumParameters();
|
||||
const String& juceParamID = LegacyAudioParameter::getParamID (param, forceUseLegacyParamIDs);
|
||||
AudioUnitParameterID paramHash = static_cast<AudioUnitParameterID> (juceParamID.hashCode());
|
||||
|
||||
if (isPositiveAndBelow (paramIndex, n))
|
||||
{
|
||||
const String& juceParamID = juceFilter->getParameterID (paramIndex);
|
||||
#if JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS
|
||||
// studio one doesn't like negative parameters
|
||||
paramHash &= ~(1 << (sizeof (AudioUnitParameterID) * 8 - 1));
|
||||
#endif
|
||||
|
||||
AudioUnitParameterID paramHash = static_cast<AudioUnitParameterID> (juceParamID.hashCode());
|
||||
|
||||
#if JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS
|
||||
// studio one doesn't like negative parameters
|
||||
paramHash &= ~(1 << (sizeof (AudioUnitParameterID) * 8 - 1));
|
||||
#endif
|
||||
|
||||
return usingManagedParameter ? paramHash
|
||||
: static_cast<AudioUnitParameterID> (juceParamID.getIntValue());
|
||||
}
|
||||
|
||||
return static_cast<AudioUnitParameterID> (-1);
|
||||
return juceParameters.isUsingManagedParameters() ? paramHash
|
||||
: static_cast<AudioUnitParameterID> (juceParamID.getIntValue());
|
||||
}
|
||||
|
||||
inline AudioUnitParameterID getAUParameterIDForIndex (int paramIndex) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? auParamIDs.getReference (paramIndex)
|
||||
: static_cast<AudioUnitParameterID> (paramIndex);
|
||||
return juceParameters.isUsingManagedParameters() ? auParamIDs.getReference (paramIndex)
|
||||
: static_cast<AudioUnitParameterID> (paramIndex);
|
||||
}
|
||||
|
||||
inline int getJuceIndexForAUParameterID (AudioUnitParameterID address) const noexcept
|
||||
AudioProcessorParameter* getParameterForAUParameterID (AudioUnitParameterID address) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? paramMap[static_cast<int32> (address)]
|
||||
: static_cast<int> (address);
|
||||
return paramMap[static_cast<int32> (address)];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//==============================================================================
|
||||
OSStatus syncAudioUnitWithProcessor()
|
||||
|
|
@ -1934,7 +1922,7 @@ private:
|
|||
addSupportedLayoutTags();
|
||||
|
||||
for (int i = 0; i < enabledInputs; ++i)
|
||||
if ((err = syncAudioUnitWithChannelSet (true, i, juceFilter->getChannelLayoutOfBus (true, i))) != noErr) return err;
|
||||
if ((err = syncAudioUnitWithChannelSet (true, i, juceFilter->getChannelLayoutOfBus (true, i))) != noErr) return err;
|
||||
|
||||
for (int i = 0; i < enabledOutputs; ++i)
|
||||
if ((err = syncAudioUnitWithChannelSet (false, i, juceFilter->getChannelLayoutOfBus (false, i))) != noErr) return err;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@
|
|||
#include "../../juce_graphics/native/juce_mac_CoreGraphicsHelpers.h"
|
||||
|
||||
#include "../../juce_audio_basics/native/juce_mac_CoreAudioLayouts.h"
|
||||
#include "../../juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp"
|
||||
#include "../../juce_audio_processors/format_types/juce_AU_Shared.h"
|
||||
|
||||
#define JUCE_VIEWCONTROLLER_OBJC_NAME(x) JUCE_JOIN_MACRO (x, FactoryAUv3)
|
||||
|
|
@ -909,7 +910,7 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if (isPositiveAndBelow (idx, getAudioProcessor().getNumParameters()))
|
||||
if (isPositiveAndBelow (idx, juceParameters.getNumParameters()))
|
||||
{
|
||||
if (AUParameter* param = [paramTree parameterWithAddress: getAUParameterAddressForIndex (idx)])
|
||||
{
|
||||
|
|
@ -1121,14 +1122,13 @@ private:
|
|||
}
|
||||
|
||||
// When parameters are discrete we need to use integer values.
|
||||
float getMaximumParameterValue (int parameterIndex)
|
||||
float getMaximumParameterValue (AudioProcessorParameter* juceParam)
|
||||
{
|
||||
#if JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
ignoreUnused (parameterIndex);
|
||||
ignoreUnused (juceParam);
|
||||
return 1.0f;
|
||||
#else
|
||||
auto& processor = getAudioProcessor();
|
||||
return processor.isParameterDiscrete (parameterIndex) ? (float) (processor.getParameterNumSteps (parameterIndex) - 1) : 1.0f;
|
||||
return juceParam->isDiscrete() ? (float) (juceParam->getNumSteps() - 1) : 1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1139,17 +1139,16 @@ private:
|
|||
overviewParams = [[NSMutableArray<NSNumber*> alloc] init];
|
||||
|
||||
auto& processor = getAudioProcessor();
|
||||
const int n = processor.getNumParameters();
|
||||
juceParameters.update (processor, forceLegacyParamIDs);
|
||||
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
// check if all parameters are managed?
|
||||
usingManagedParameter = (processor.getParameters().size() == processor.getNumParameters());
|
||||
#endif
|
||||
const int n = juceParameters.getNumParameters();
|
||||
|
||||
for (int idx = 0; idx < n; ++idx)
|
||||
{
|
||||
auto* juceParam = juceParameters.getParamForIndex (idx);
|
||||
|
||||
const String identifier (idx);
|
||||
const String name = processor.getParameterName (idx);
|
||||
const String name = juceParam->getName (512);
|
||||
|
||||
AudioUnitParameterUnit unit = kAudioUnitParameterUnit_Generic;
|
||||
AudioUnitParameterOptions flags = (UInt32) (kAudioUnitParameterFlag_IsWritable
|
||||
|
|
@ -1157,27 +1156,26 @@ private:
|
|||
| kAudioUnitParameterFlag_HasCFNameString
|
||||
| kAudioUnitParameterFlag_ValuesHaveStrings);
|
||||
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
|
||||
#endif
|
||||
if (! forceLegacyParamIDs)
|
||||
flags |= (UInt32) kAudioUnitParameterFlag_IsHighResolution;
|
||||
|
||||
// set whether the param is automatable (unnamed parameters aren't allowed to be automated)
|
||||
if (name.isEmpty() || ! processor.isParameterAutomatable (idx))
|
||||
if (name.isEmpty() || ! juceParam->isAutomatable())
|
||||
flags |= kAudioUnitParameterFlag_NonRealTime;
|
||||
|
||||
const bool isParameterDiscrete = processor.isParameterDiscrete (idx);
|
||||
const bool isParameterDiscrete = juceParam->isDiscrete();
|
||||
|
||||
if (! isParameterDiscrete)
|
||||
flags |= kAudioUnitParameterFlag_CanRamp;
|
||||
|
||||
if (processor.isMetaParameter (idx))
|
||||
if (juceParam->isMetaParameter())
|
||||
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)
|
||||
if (((juceParam->getCategory() & 0xffff0000) >> 16) == 2)
|
||||
{
|
||||
flags &= ~kAudioUnitParameterFlag_IsWritable;
|
||||
flags |= kAudioUnitParameterFlag_MeterReadOnly | kAudioUnitParameterFlag_DisplayLogarithmic;
|
||||
|
|
@ -1185,14 +1183,13 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
if (auto* param = processor.getParameters()[idx])
|
||||
if (! forceLegacyParamIDs)
|
||||
{
|
||||
if (param->isDiscrete())
|
||||
if (juceParam->isDiscrete())
|
||||
{
|
||||
unit = param->isBoolean() ? kAudioUnitParameterUnit_Boolean : kAudioUnitParameterUnit_Indexed;
|
||||
auto maxValue = getMaximumParameterValue (idx);
|
||||
auto numSteps = param->getNumSteps();
|
||||
unit = juceParam->isBoolean() ? kAudioUnitParameterUnit_Boolean : kAudioUnitParameterUnit_Indexed;
|
||||
auto maxValue = getMaximumParameterValue (juceParam);
|
||||
auto numSteps = juceParam->getNumSteps();
|
||||
|
||||
// Some hosts can't handle the huge numbers of discrete parameter values created when
|
||||
// using the default number of steps.
|
||||
|
|
@ -1201,24 +1198,22 @@ private:
|
|||
valueStrings.reset ([NSMutableArray new]);
|
||||
|
||||
for (int i = 0; i < numSteps; ++i)
|
||||
[valueStrings.get() addObject: juceStringToNS (param->getText ((float) i / maxValue, 0))];
|
||||
[valueStrings.get() addObject: juceStringToNS (juceParam->getText ((float) i / maxValue, 0))];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
AUParameterAddress address = static_cast<AUParameterAddress> (idx);
|
||||
#else
|
||||
AUParameterAddress address = generateAUParameterAddressForIndex (idx);
|
||||
AUParameterAddress address = forceLegacyParamIDs ? static_cast<AUParameterAddress> (idx)
|
||||
: generateAUParameterAddress (juceParam);
|
||||
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
// 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)));
|
||||
|
||||
paramAddresses.add (address);
|
||||
paramMap.set (static_cast<int64> (address), idx);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// create methods in AUParameterTree return unretained objects (!) -> see Apple header AUAudioUnitImplementation.h
|
||||
|
||||
|
|
@ -1226,14 +1221,14 @@ private:
|
|||
name: juceStringToNS (name)
|
||||
address: address
|
||||
min: 0.0f
|
||||
max: getMaximumParameterValue (idx)
|
||||
max: getMaximumParameterValue (juceParam)
|
||||
unit: unit
|
||||
unitName: nullptr
|
||||
flags: flags
|
||||
valueStrings: valueStrings.get()
|
||||
dependentParameters: nullptr] retain];
|
||||
|
||||
[param.get() setValue: processor.getParameterDefaultValue (idx)];
|
||||
[param.get() setValue: juceParam->getDefaultValue()];
|
||||
|
||||
[params addObject: param];
|
||||
[overviewParams addObject: [NSNumber numberWithUnsignedLongLong:address]];
|
||||
|
|
@ -1259,21 +1254,14 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void setAudioProcessorParameter (int index, float value)
|
||||
void setAudioProcessorParameter (AudioProcessorParameter* juceParam, float value)
|
||||
{
|
||||
if (auto* param = getAudioProcessor().getParameters()[index])
|
||||
if (value != juceParam->getValue())
|
||||
{
|
||||
if (value != param->getValue())
|
||||
{
|
||||
param->setValue (value);
|
||||
juceParam->setValue (value);
|
||||
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
}
|
||||
else if (isPositiveAndBelow (index, getAudioProcessor().getNumParameters()))
|
||||
{
|
||||
getAudioProcessor().setParameter (index, value);
|
||||
inParameterChangedCallback = true;
|
||||
juceParam->sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1329,9 +1317,9 @@ private:
|
|||
case AURenderEventParameterRamp:
|
||||
{
|
||||
const AUParameterEvent& paramEvent = event->parameter;
|
||||
const int idx = getJuceParameterIndexForAUAddress (paramEvent.parameterAddress);
|
||||
|
||||
setAudioProcessorParameter (idx, paramEvent.value);
|
||||
if (auto* p = getJuceParameterForAUAddress (paramEvent.parameterAddress))
|
||||
setAudioProcessorParameter (p, paramEvent.value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1349,7 +1337,7 @@ private:
|
|||
jassert (static_cast<int> (frameCount) <= getAudioProcessor().getBlockSize());
|
||||
|
||||
// process params
|
||||
const int numParams = processor.getNumParameters();
|
||||
const int numParams = juceParameters.getNumParameters();
|
||||
processEvents (realtimeEventListHead, numParams, static_cast<AUEventSampleTime> (timestamp->mSampleTime));
|
||||
|
||||
if (lastTimeStamp.mSampleTime != timestamp->mSampleTime)
|
||||
|
|
@ -1477,10 +1465,11 @@ private:
|
|||
{
|
||||
if (param != nullptr)
|
||||
{
|
||||
int idx = getJuceParameterIndexForAUAddress ([param address]);
|
||||
auto normalisedValue = value / getMaximumParameterValue (idx);
|
||||
|
||||
setAudioProcessorParameter (idx, normalisedValue);
|
||||
if (auto* p = getJuceParameterForAUAddress ([param address]))
|
||||
{
|
||||
auto normalisedValue = value / getMaximumParameterValue (p);
|
||||
setAudioProcessorParameter (p, normalisedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1488,11 +1477,8 @@ private:
|
|||
{
|
||||
if (param != nullptr)
|
||||
{
|
||||
const int idx = getJuceParameterIndexForAUAddress ([param address]);
|
||||
auto& processor = getAudioProcessor();
|
||||
|
||||
if (isPositiveAndBelow (idx, processor.getNumParameters()))
|
||||
return processor.getParameter (idx) * getMaximumParameterValue (idx);
|
||||
if (auto* p = getJuceParameterForAUAddress ([param address]))
|
||||
return p->getValue() * getMaximumParameterValue (p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1509,13 +1495,13 @@ private:
|
|||
|
||||
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);
|
||||
if (auto* p = getJuceParameterForAUAddress ([param address]))
|
||||
{
|
||||
if (LegacyAudioParameter::isLegacy (p))
|
||||
text = String (*value);
|
||||
else
|
||||
text = p->getText (*value / getMaximumParameterValue (p), 0);
|
||||
}
|
||||
}
|
||||
|
||||
return juceStringToNS (text);
|
||||
|
|
@ -1525,14 +1511,15 @@ private:
|
|||
{
|
||||
if (param != nullptr && str != nullptr)
|
||||
{
|
||||
const int idx = getJuceParameterIndexForAUAddress ([param address]);
|
||||
auto& processor = getAudioProcessor();
|
||||
const String text (nsStringToJuce (str));
|
||||
if (auto* p = getJuceParameterForAUAddress ([param address]))
|
||||
{
|
||||
const String text (nsStringToJuce (str));
|
||||
|
||||
if (auto* p = processor.getParameters()[idx])
|
||||
return p->getValueForText (text) * getMaximumParameterValue (idx);
|
||||
else
|
||||
return text.getFloatValue();
|
||||
if (LegacyAudioParameter::isLegacy (p))
|
||||
return text.getFloatValue();
|
||||
else
|
||||
return p->getValueForText (text) * getMaximumParameterValue (p);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1543,34 +1530,32 @@ private:
|
|||
inline AUParameterAddress getAUParameterAddressForIndex (int paramIndex) const noexcept { return static_cast<AUParameterAddress> (paramIndex); }
|
||||
inline int getJuceParameterIndexForAUAddress (AUParameterAddress address) const noexcept { return static_cast<int> (address); }
|
||||
#else
|
||||
AUParameterAddress generateAUParameterAddressForIndex (int paramIndex) const
|
||||
{
|
||||
auto& processor = getAudioProcessor();
|
||||
const int n = processor.getNumParameters();
|
||||
|
||||
if (isPositiveAndBelow (paramIndex, n))
|
||||
{
|
||||
const String& juceParamID = processor.getParameterID (paramIndex);
|
||||
return usingManagedParameter ? static_cast<AUParameterAddress> (juceParamID.hashCode64())
|
||||
: static_cast<AUParameterAddress> (juceParamID.getIntValue());
|
||||
}
|
||||
|
||||
return static_cast<AUParameterAddress> (-1);
|
||||
}
|
||||
|
||||
inline AUParameterAddress getAUParameterAddressForIndex (int paramIndex) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? paramAddresses.getReference (paramIndex)
|
||||
: static_cast<AUParameterAddress> (paramIndex);
|
||||
return juceParameters.isUsingManagedParameters() ? paramAddresses.getReference (paramIndex)
|
||||
: static_cast<AUParameterAddress> (paramIndex);
|
||||
}
|
||||
|
||||
inline int getJuceParameterIndexForAUAddress (AUParameterAddress address) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? paramMap[static_cast<int64> (address)]
|
||||
: static_cast<int> (address);
|
||||
return juceParameters.isUsingManagedParameters() ? paramMap[static_cast<int64> (address)]
|
||||
: static_cast<int> (address);
|
||||
}
|
||||
#endif
|
||||
|
||||
AUParameterAddress generateAUParameterAddress (AudioProcessorParameter* param) const
|
||||
{
|
||||
const String& juceParamID = LegacyAudioParameter::getParamID (param, forceLegacyParamIDs);
|
||||
|
||||
return juceParameters.isUsingManagedParameters() ? static_cast<AUParameterAddress> (juceParamID.hashCode64())
|
||||
: static_cast<AUParameterAddress> (juceParamID.getIntValue());
|
||||
}
|
||||
|
||||
AudioProcessorParameter* getJuceParameterForAUAddress (AUParameterAddress address) const noexcept
|
||||
{
|
||||
return juceParameters.getParamForIndex (getJuceParameterIndexForAUAddress (address));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static const double kDefaultSampleRate;
|
||||
|
||||
|
|
@ -1587,10 +1572,10 @@ private:
|
|||
ObjCBlock<AUImplementorValueFromStringCallback> valueFromStringProvider;
|
||||
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
bool usingManagedParameter;
|
||||
Array<AUParameterAddress> paramAddresses;
|
||||
HashMap<int64, int> paramMap;
|
||||
#endif
|
||||
LegacyAudioParametersWrapper juceParameters;
|
||||
|
||||
// to avoid recursion on parameter changes, we need to add an
|
||||
// editor observer to do the parameter changes
|
||||
|
|
@ -1620,6 +1605,11 @@ private:
|
|||
String contextName;
|
||||
|
||||
ThreadLocalValue<bool> inParameterChangedCallback;
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
static constexpr bool forceLegacyParamIDs = true;
|
||||
#else
|
||||
static constexpr bool forceLegacyParamIDs = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
const double JuceAudioUnitv3::kDefaultSampleRate = 44100.0;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@
|
|||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
|
||||
#include "../../juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp"
|
||||
#include "../../juce_audio_processors/format_types/juce_VSTCommon.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
@ -281,6 +282,8 @@ public:
|
|||
processor->setPlayHead (this);
|
||||
processor->addListener (this);
|
||||
|
||||
juceParameters.update (*processor, false);
|
||||
|
||||
memset (&vstEffect, 0, sizeof (vstEffect));
|
||||
vstEffect.interfaceIdentifier = juceVstInterfaceIdentifier;
|
||||
vstEffect.dispatchFunction = dispatcherCB;
|
||||
|
|
@ -288,7 +291,7 @@ public:
|
|||
vstEffect.setParameterValueFunction = setParameterCB;
|
||||
vstEffect.getParameterValueFunction = getParameterCB;
|
||||
vstEffect.numPrograms = jmax (1, af->getNumPrograms());
|
||||
vstEffect.numParameters = af->getNumParameters();
|
||||
vstEffect.numParameters = juceParameters.getNumParameters();
|
||||
vstEffect.numInputChannels = maxNumInChannels;
|
||||
vstEffect.numOutputChannels = maxNumOutChannels;
|
||||
vstEffect.latency = processor->getLatencySamples();
|
||||
|
|
@ -706,11 +709,10 @@ public:
|
|||
//==============================================================================
|
||||
float getParameter (int32 index) const
|
||||
{
|
||||
if (processor == nullptr)
|
||||
return 0.0f;
|
||||
if (auto* param = juceParameters.getParamForIndex (index))
|
||||
return param->getValue();
|
||||
|
||||
jassert (isPositiveAndBelow (index, processor->getNumParameters()));
|
||||
return processor->getParameter (index);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static float getParameterCB (VstEffectInterface* vstInterface, int32 index)
|
||||
|
|
@ -720,20 +722,12 @@ public:
|
|||
|
||||
void setParameter (int32 index, float value)
|
||||
{
|
||||
if (processor != nullptr)
|
||||
if (auto* param = juceParameters.getParamForIndex (index))
|
||||
{
|
||||
if (auto* param = processor->getParameters()[index])
|
||||
{
|
||||
param->setValue (value);
|
||||
param->setValue (value);
|
||||
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (isPositiveAndBelow (index, processor->getNumParameters()));
|
||||
processor->setParameter (index, value);
|
||||
}
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1472,6 +1466,8 @@ private:
|
|||
VSTMidiEventList outgoingEvents;
|
||||
float editorScaleFactor = 1.0f;
|
||||
|
||||
LegacyAudioParametersWrapper juceParameters;
|
||||
|
||||
bool isProcessing = false, isBypassed = false, hasShutdown = false;
|
||||
bool firstProcessCallback = true, shouldDeleteEditor = false;
|
||||
|
||||
|
|
@ -1664,11 +1660,10 @@ private:
|
|||
|
||||
pointer_sized_int handleGetParameterLabel (VstOpCodeArguments args)
|
||||
{
|
||||
if (processor != nullptr)
|
||||
if (auto* param = juceParameters.getParamForIndex (args.index))
|
||||
{
|
||||
jassert (isPositiveAndBelow (args.index, processor->getNumParameters()));
|
||||
// length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
|
||||
processor->getParameterLabel (args.index).copyToUTF8 ((char*) args.ptr, 24 + 1);
|
||||
param->getLabel().copyToUTF8 ((char*) args.ptr, 24 + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1676,11 +1671,10 @@ private:
|
|||
|
||||
pointer_sized_int handleGetParameterText (VstOpCodeArguments args)
|
||||
{
|
||||
if (processor != nullptr)
|
||||
if (auto* param = juceParameters.getParamForIndex (args.index))
|
||||
{
|
||||
jassert (isPositiveAndBelow (args.index, processor->getNumParameters()));
|
||||
// length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
|
||||
processor->getParameterText (args.index, 24).copyToUTF8 ((char*) args.ptr, 24 + 1);
|
||||
param->getCurrentValueAsText().copyToUTF8 ((char*) args.ptr, 24 + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1688,11 +1682,10 @@ private:
|
|||
|
||||
pointer_sized_int handleGetParameterName (VstOpCodeArguments args)
|
||||
{
|
||||
if (processor != nullptr)
|
||||
if (auto* param = juceParameters.getParamForIndex (args.index))
|
||||
{
|
||||
jassert (isPositiveAndBelow (args.index, processor->getNumParameters()));
|
||||
// length should technically be kVstMaxParamStrLen, which is 8, but hosts will normally allow a bit more.
|
||||
processor->getParameterName (args.index, 32).copyToUTF8 ((char*) args.ptr, 32 + 1);
|
||||
param->getName (32).copyToUTF8 ((char*) args.ptr, 32 + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1823,20 +1816,20 @@ private:
|
|||
|
||||
pointer_sized_int handleIsParameterAutomatable (VstOpCodeArguments args)
|
||||
{
|
||||
if (processor == nullptr)
|
||||
return 0;
|
||||
if (auto* param = juceParameters.getParamForIndex (args.index))
|
||||
{
|
||||
const bool isMeter = (((param->getCategory() & 0xffff0000) >> 16) == 2);
|
||||
return (param->isAutomatable() && (! isMeter) ? 1 : 0);
|
||||
}
|
||||
|
||||
const bool isMeter = (((processor->getParameterCategory (args.index) & 0xffff0000) >> 16) == 2);
|
||||
return (processor->isParameterAutomatable (args.index) && (! isMeter) ? 1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pointer_sized_int handleParameterValueForText (VstOpCodeArguments args)
|
||||
{
|
||||
if (processor != nullptr)
|
||||
if (auto* param = juceParameters.getParamForIndex (args.index))
|
||||
{
|
||||
jassert (isPositiveAndBelow (args.index, processor->getNumParameters()));
|
||||
|
||||
if (auto* param = processor->getParameters()[args.index])
|
||||
if (! LegacyAudioParameter::isLegacy (param))
|
||||
{
|
||||
auto value = param->getValueForText (String::fromUTF8 ((char*) args.ptr));
|
||||
param->setValue (value);
|
||||
|
|
@ -2120,11 +2113,14 @@ private:
|
|||
{
|
||||
if (processor != nullptr && dest != nullptr)
|
||||
{
|
||||
if (auto* param = processor->getParameters()[(int) paramIndex])
|
||||
if (auto* param = juceParameters.getParamForIndex ((int) paramIndex))
|
||||
{
|
||||
String text (param->getText (value, 1024));
|
||||
memcpy (dest, text.toRawUTF8(), ((size_t) text.length()) + 1);
|
||||
return 0xbeef;
|
||||
if (! LegacyAudioParameter::isLegacy (param))
|
||||
{
|
||||
String text (param->getText (value, 1024));
|
||||
memcpy (dest, text.toRawUTF8(), ((size_t) text.length()) + 1);
|
||||
return 0xbeef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "../utility/juce_IncludeModuleHeaders.h"
|
||||
#include "../utility/juce_WindowsHooks.h"
|
||||
#include "../utility/juce_FakeMouseMoveGenerator.h"
|
||||
#include "../../juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp"
|
||||
#include "../../juce_audio_processors/format_types/juce_VST3Common.h"
|
||||
|
||||
#ifndef JUCE_VST3_CAN_REPLACE_VST2
|
||||
|
|
@ -89,7 +90,12 @@ using namespace Steinberg;
|
|||
class JuceAudioProcessor : public FUnknown
|
||||
{
|
||||
public:
|
||||
JuceAudioProcessor (AudioProcessor* source) noexcept : audioProcessor (source) {}
|
||||
JuceAudioProcessor (AudioProcessor* source) noexcept
|
||||
: audioProcessor (source)
|
||||
{
|
||||
setupParameters();
|
||||
}
|
||||
|
||||
virtual ~JuceAudioProcessor() {}
|
||||
|
||||
AudioProcessor* get() const noexcept { return audioProcessor; }
|
||||
|
|
@ -97,15 +103,85 @@ public:
|
|||
JUCE_DECLARE_VST3_COM_QUERY_METHODS
|
||||
JUCE_DECLARE_VST3_COM_REF_METHODS
|
||||
|
||||
static const FUID iid;
|
||||
//==============================================================================
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept { return static_cast<Vst::ParamID> (paramIndex); }
|
||||
#else
|
||||
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept
|
||||
{
|
||||
return isUsingManagedParameters() ? vstParamIDs.getReference (paramIndex)
|
||||
: static_cast<Vst::ParamID> (paramIndex);
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioProcessorParameter* getParamForVSTParamID (Vst::ParamID paramID) const noexcept
|
||||
{
|
||||
return paramMap[static_cast<int32> (paramID)];
|
||||
}
|
||||
|
||||
int getNumParameters() const noexcept { return vstParamIDs.size(); }
|
||||
bool isUsingManagedParameters() const noexcept { return juceParameters.isUsingManagedParameters(); }
|
||||
|
||||
//==============================================================================
|
||||
static const FUID iid;
|
||||
Array<Vst::ParamID> vstParamIDs;
|
||||
Vst::ParamID bypassParamID = 0;
|
||||
bool isBypassed = false;
|
||||
|
||||
private:
|
||||
enum InternalParameters
|
||||
{
|
||||
paramBypass = 0x62797073 // 'byps'
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void setupParameters()
|
||||
{
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
const bool forceLegacyParamIDs = true;
|
||||
#else
|
||||
const bool forceLegacyParamIDs = false;
|
||||
#endif
|
||||
|
||||
juceParameters.update (*audioProcessor, forceLegacyParamIDs);
|
||||
auto numParameters = juceParameters.getNumParameters();
|
||||
|
||||
int i = 0;
|
||||
for (auto* juceParam : juceParameters.params)
|
||||
{
|
||||
Vst::ParamID vstParamID = forceLegacyParamIDs ? static_cast<Vst::ParamID> (i++)
|
||||
: generateVSTParamIDForParam (juceParam);
|
||||
|
||||
vstParamIDs.add (vstParamID);
|
||||
paramMap.set (static_cast<int32> (vstParamID), juceParam);
|
||||
}
|
||||
|
||||
bypassParamID = static_cast<Vst::ParamID> (isUsingManagedParameters() ? paramBypass : numParameters);
|
||||
}
|
||||
|
||||
Vst::ParamID generateVSTParamIDForParam (AudioProcessorParameter* param)
|
||||
{
|
||||
auto juceParamID = LegacyAudioParameter::getParamID (param, false);
|
||||
auto paramHash = static_cast<Vst::ParamID> (juceParamID.hashCode());
|
||||
|
||||
#if JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS
|
||||
// studio one doesn't like negative parameters
|
||||
paramHash &= ~(1 << (sizeof (Vst::ParamID) * 8 - 1));
|
||||
#endif
|
||||
|
||||
return isUsingManagedParameters() ? paramHash
|
||||
: static_cast<Vst::ParamID> (juceParamID.getIntValue());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Atomic<int> refCount;
|
||||
ScopedPointer<AudioProcessor> audioProcessor;
|
||||
ScopedJuceInitialiser_GUI libraryInitialiser;
|
||||
|
||||
//==============================================================================
|
||||
LegacyAudioParametersWrapper juceParameters;
|
||||
HashMap<int32, AudioProcessorParameter*> paramMap;
|
||||
|
||||
JuceAudioProcessor() = delete;
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceAudioProcessor)
|
||||
};
|
||||
|
|
@ -197,39 +273,38 @@ public:
|
|||
enum InternalParameters
|
||||
{
|
||||
paramPreset = 0x70727374, // 'prst'
|
||||
paramBypass = 0x62797073, // 'byps'
|
||||
paramMidiControllerOffset = 0x6d636d00 // 'mdm*'
|
||||
};
|
||||
|
||||
struct Param : public Vst::Parameter
|
||||
{
|
||||
Param (AudioProcessor& p, int index, Vst::ParamID paramID) : owner (p), paramIndex (index)
|
||||
Param (JuceVST3EditController& editController, AudioProcessorParameter& p,
|
||||
Vst::ParamID vstParamID, bool forceLegacyParamIDs)
|
||||
: owner (editController), param (p)
|
||||
{
|
||||
info.id = paramID;
|
||||
info.id = vstParamID;
|
||||
|
||||
toString128 (info.title, p.getParameterName (index));
|
||||
toString128 (info.shortTitle, p.getParameterName (index, 8));
|
||||
toString128 (info.units, p.getParameterLabel (index));
|
||||
toString128 (info.title, param.getName (128));
|
||||
toString128 (info.shortTitle, param.getName (8));
|
||||
toString128 (info.units, param.getLabel());
|
||||
|
||||
info.stepCount = (Steinberg::int32) 0;
|
||||
|
||||
#if ! JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE
|
||||
if (p.isParameterDiscrete (index))
|
||||
#endif
|
||||
if (! forceLegacyParamIDs && param.isDiscrete())
|
||||
{
|
||||
const int numSteps = p.getParameterNumSteps (index);
|
||||
const int numSteps = param.getNumSteps();
|
||||
info.stepCount = (Steinberg::int32) (numSteps > 0 && numSteps < 0x7fffffff ? numSteps - 1 : 0);
|
||||
}
|
||||
|
||||
info.defaultNormalizedValue = p.getParameterDefaultValue (index);
|
||||
info.defaultNormalizedValue = param.getDefaultValue();
|
||||
jassert (info.defaultNormalizedValue >= 0 && info.defaultNormalizedValue <= 1.0f);
|
||||
info.unitId = Vst::kRootUnitId;
|
||||
|
||||
// Is this a meter?
|
||||
if (((p.getParameterCategory (index) & 0xffff0000) >> 16) == 2)
|
||||
if (((param.getCategory() & 0xffff0000) >> 16) == 2)
|
||||
info.flags = Vst::ParameterInfo::kIsReadOnly;
|
||||
else
|
||||
info.flags = p.isParameterAutomatable (index) ? Vst::ParameterInfo::kCanAutomate : 0;
|
||||
info.flags = param.isAutomatable() ? Vst::ParameterInfo::kCanAutomate : 0;
|
||||
|
||||
valueNormalized = info.defaultNormalizedValue;
|
||||
}
|
||||
|
|
@ -251,17 +326,10 @@ public:
|
|||
{
|
||||
auto value = static_cast<float> (v);
|
||||
|
||||
if (auto* param = owner.getParameters()[paramIndex])
|
||||
{
|
||||
param->setValue (value);
|
||||
param.setValue (value);
|
||||
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.setParameter (paramIndex, value);
|
||||
}
|
||||
inParameterChangedCallback = true;
|
||||
param.sendValueChangedMessageToListeners (value);
|
||||
}
|
||||
|
||||
changed();
|
||||
|
|
@ -273,18 +341,14 @@ public:
|
|||
|
||||
void toString (Vst::ParamValue value, Vst::String128 result) const override
|
||||
{
|
||||
if (auto* p = owner.getParameters()[paramIndex])
|
||||
toString128 (result, p->getText ((float) value, 128));
|
||||
else
|
||||
// remain backward-compatible with old JUCE code
|
||||
toString128 (result, owner.getParameterText (paramIndex, 128));
|
||||
toString128 (result, param.getText ((float) value, 128));
|
||||
}
|
||||
|
||||
bool fromString (const Vst::TChar* text, Vst::ParamValue& outValueNormalized) const override
|
||||
{
|
||||
if (auto* p = owner.getParameters()[paramIndex])
|
||||
if (! LegacyAudioParameter::isLegacy (¶m))
|
||||
{
|
||||
outValueNormalized = p->getValueForText (getStringFromVstTChars (text));
|
||||
outValueNormalized = param.getValueForText (getStringFromVstTChars (text));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -300,8 +364,8 @@ public:
|
|||
Vst::ParamValue toNormalized (Vst::ParamValue v) const override { return v; }
|
||||
|
||||
private:
|
||||
AudioProcessor& owner;
|
||||
int paramIndex;
|
||||
JuceVST3EditController& owner;
|
||||
AudioProcessorParameter& param;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Param)
|
||||
};
|
||||
|
|
@ -502,12 +566,8 @@ public:
|
|||
// Cubase and Nuendo need to inform the host of the current parameter values
|
||||
if (auto* pluginInstance = getPluginInstance())
|
||||
{
|
||||
auto numParameters = pluginInstance->getNumParameters();
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
setParamNormalized (getVSTParamIDForIndex (i), (double) pluginInstance->getParameter (i));
|
||||
|
||||
setParamNormalized (bypassParamID, audioProcessor->isBypassed ? 1.0f : 0.0f);
|
||||
for (auto vstParamId : audioProcessor->vstParamIDs)
|
||||
setParamNormalized (vstParamId, audioProcessor->getParamForVSTParamID (vstParamId)->getValue());
|
||||
|
||||
auto numPrograms = pluginInstance->getNumPrograms();
|
||||
|
||||
|
|
@ -601,10 +661,7 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override { beginEdit (getVSTParamIDForIndex (index)); }
|
||||
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override { endEdit (getVSTParamIDForIndex (index)); }
|
||||
|
||||
void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue) override
|
||||
void paramChanged (Vst::ParamID vstParamId, float newValue)
|
||||
{
|
||||
if (inParameterChangedCallback.get())
|
||||
{
|
||||
|
|
@ -613,8 +670,17 @@ public:
|
|||
}
|
||||
|
||||
// NB: Cubase has problems if performEdit is called without setParamNormalized
|
||||
EditController::setParamNormalized (getVSTParamIDForIndex (index), (double) newValue);
|
||||
performEdit (getVSTParamIDForIndex (index), (double) newValue);
|
||||
EditController::setParamNormalized (vstParamId, (double) newValue);
|
||||
performEdit (vstParamId, (double) newValue);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override { beginEdit (audioProcessor->getVSTParamIDForIndex (index)); }
|
||||
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override { endEdit (audioProcessor->getVSTParamIDForIndex (index)); }
|
||||
|
||||
void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue) override
|
||||
{
|
||||
paramChanged (audioProcessor->getVSTParamIDForIndex (index), newValue);
|
||||
}
|
||||
|
||||
void audioProcessorChanged (AudioProcessor*) override
|
||||
|
|
@ -641,6 +707,7 @@ public:
|
|||
|
||||
private:
|
||||
friend class JuceVST3Component;
|
||||
friend struct Param;
|
||||
|
||||
//==============================================================================
|
||||
ComSmartPtr<JuceAudioProcessor> audioProcessor;
|
||||
|
|
@ -657,53 +724,41 @@ private:
|
|||
Vst::ParamID midiControllerToParameter[numMIDIChannels][Vst::kCountCtrlNumber];
|
||||
|
||||
//==============================================================================
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
bool usingManagedParameter = false;
|
||||
Array<Vst::ParamID> vstParamIDs;
|
||||
#endif
|
||||
Vst::ParamID bypassParamID;
|
||||
Atomic<int> vst3IsPlaying { 0 };
|
||||
|
||||
//==============================================================================
|
||||
void setupParameters()
|
||||
{
|
||||
if (auto* pluginInstance = getPluginInstance())
|
||||
{
|
||||
pluginInstance->addListener (this);
|
||||
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
const bool usingManagedParameter = false;
|
||||
#endif
|
||||
|
||||
if (parameters.getParameterCount() <= 0)
|
||||
{
|
||||
auto numParameters = pluginInstance->getNumParameters();
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
const bool forceLegacyParamIDs = true;
|
||||
#else
|
||||
const bool forceLegacyParamIDs = false;
|
||||
#endif
|
||||
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
usingManagedParameter = (pluginInstance->getParameters().size() == numParameters);
|
||||
#endif
|
||||
auto n = audioProcessor->getNumParameters();
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
const Vst::ParamID vstParamID = static_cast<Vst::ParamID> (i);
|
||||
#else
|
||||
const Vst::ParamID vstParamID = generateVSTParamIDForIndex (pluginInstance, i);
|
||||
vstParamIDs.add (vstParamID);
|
||||
#endif
|
||||
auto vstParamID = audioProcessor->getVSTParamIDForIndex (i);
|
||||
auto* juceParam = audioProcessor->getParamForVSTParamID (vstParamID);
|
||||
|
||||
parameters.addParameter (new Param (*pluginInstance, i, vstParamID));
|
||||
parameters.addParameter (new Param (*this, *juceParam, vstParamID, forceLegacyParamIDs));
|
||||
}
|
||||
|
||||
bypassParamID = static_cast<Vst::ParamID> (usingManagedParameter ? paramBypass : numParameters);
|
||||
parameters.addParameter (new BypassParam (bypassParamID));
|
||||
parameters.addParameter (new BypassParam (audioProcessor->bypassParamID));
|
||||
|
||||
if (pluginInstance->getNumPrograms() > 1)
|
||||
parameters.addParameter (new ProgramChangeParameter (*pluginInstance));
|
||||
}
|
||||
|
||||
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
|
||||
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (usingManagedParameter ? paramMidiControllerOffset
|
||||
: parameters.getParameterCount());
|
||||
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (audioProcessor->isUsingManagedParameters() ? paramMidiControllerOffset
|
||||
: parameters.getParameterCount());
|
||||
|
||||
initialiseMidiControllerMappings();
|
||||
#endif
|
||||
|
|
@ -742,41 +797,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept { return static_cast<Vst::ParamID> (paramIndex); }
|
||||
#else
|
||||
static Vst::ParamID generateVSTParamIDForIndex (AudioProcessor* const pluginFilter, int paramIndex)
|
||||
{
|
||||
jassert (pluginFilter != nullptr);
|
||||
|
||||
const int n = pluginFilter->getNumParameters();
|
||||
const bool managedParameter = (pluginFilter->getParameters().size() == n);
|
||||
|
||||
if (isPositiveAndBelow (paramIndex, n))
|
||||
{
|
||||
auto juceParamID = pluginFilter->getParameterID (paramIndex);
|
||||
auto paramHash = static_cast<Vst::ParamID> (juceParamID.hashCode());
|
||||
|
||||
#if JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS
|
||||
// studio one doesn't like negative parameters
|
||||
paramHash &= ~(1 << (sizeof (Vst::ParamID) * 8 - 1));
|
||||
#endif
|
||||
|
||||
return managedParameter ? paramHash
|
||||
: static_cast<Vst::ParamID> (juceParamID.getIntValue());
|
||||
}
|
||||
|
||||
return static_cast<Vst::ParamID> (-1);
|
||||
}
|
||||
|
||||
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? vstParamIDs.getReference (paramIndex)
|
||||
: static_cast<Vst::ParamID> (paramIndex);
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
class JuceVST3Editor : public Vst::EditorView,
|
||||
public Steinberg::IPlugViewContentScaleSupport,
|
||||
|
|
@ -1172,17 +1192,14 @@ public:
|
|||
processSetup.sampleRate = 44100.0;
|
||||
processSetup.symbolicSampleSize = Vst::kSample32;
|
||||
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
vstBypassParameterId = static_cast<Vst::ParamID> (pluginInstance->getNumParameters());
|
||||
#else
|
||||
cacheParameterIDs();
|
||||
#endif
|
||||
|
||||
pluginInstance->setPlayHead (this);
|
||||
}
|
||||
|
||||
~JuceVST3Component()
|
||||
{
|
||||
if (juceVST3EditController != nullptr)
|
||||
juceVST3EditController->vst3IsPlaying = 0;
|
||||
|
||||
if (pluginInstance != nullptr)
|
||||
if (pluginInstance->getPlayHead() == this)
|
||||
pluginInstance->setPlayHead (nullptr);
|
||||
|
|
@ -1246,6 +1263,9 @@ public:
|
|||
|
||||
tresult PLUGIN_API disconnect (IConnectionPoint*) override
|
||||
{
|
||||
if (juceVST3EditController != nullptr)
|
||||
juceVST3EditController->vst3IsPlaying = 0;
|
||||
|
||||
juceVST3EditController = nullptr;
|
||||
return kResultTrue;
|
||||
}
|
||||
|
|
@ -2020,7 +2040,7 @@ public:
|
|||
{
|
||||
auto vstParamID = paramQueue->getParameterId();
|
||||
|
||||
if (vstParamID == vstBypassParameterId)
|
||||
if (vstParamID == comPluginInstance->bypassParamID)
|
||||
setBypassed (static_cast<float> (value) != 0.0f);
|
||||
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
|
||||
else if (juceVST3EditController->isMidiControllerParamID (vstParamID))
|
||||
|
|
@ -2037,20 +2057,15 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
auto index = getJuceIndexForVSTParamID (vstParamID);
|
||||
auto floatValue = static_cast<float> (value);
|
||||
|
||||
if (auto* param = pluginInstance->getParameters()[index])
|
||||
if (auto* param = comPluginInstance->getParamForVSTParamID (vstParamID))
|
||||
{
|
||||
param->setValue (floatValue);
|
||||
|
||||
inParameterChangedCallback = true;
|
||||
param->sendValueChangedMessageToListeners (floatValue);
|
||||
}
|
||||
else if (isPositiveAndBelow (index, pluginInstance->getNumParameters()))
|
||||
{
|
||||
pluginInstance->setParameter (index, floatValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2088,12 +2103,16 @@ public:
|
|||
if (data.processContext != nullptr)
|
||||
{
|
||||
processContext = *data.processContext;
|
||||
pluginInstance->vst3IsPlaying = processContext.state & Vst::ProcessContext::kPlaying;
|
||||
|
||||
if (juceVST3EditController != nullptr)
|
||||
juceVST3EditController->vst3IsPlaying = processContext.state & Vst::ProcessContext::kPlaying;
|
||||
}
|
||||
else
|
||||
{
|
||||
zerostruct (processContext);
|
||||
pluginInstance->vst3IsPlaying = 0;
|
||||
|
||||
if (juceVST3EditController != nullptr)
|
||||
juceVST3EditController->vst3IsPlaying = 0;
|
||||
}
|
||||
|
||||
midiBuffer.clear();
|
||||
|
|
@ -2164,14 +2183,6 @@ private:
|
|||
#endif
|
||||
|
||||
ScopedJuceInitialiser_GUI libraryInitialiser;
|
||||
|
||||
#if ! JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
bool usingManagedParameter;
|
||||
Array<Vst::ParamID> vstParamIDs;
|
||||
HashMap<int32, int> paramMap;
|
||||
#endif
|
||||
Vst::ParamID vstBypassParameterId;
|
||||
|
||||
static const char* kJucePrivateDataIdentifier;
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -2387,44 +2398,6 @@ private:
|
|||
p.prepareToPlay (sampleRate, bufferSize);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
|
||||
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept { return static_cast<Vst::ParamID> (paramIndex); }
|
||||
inline int getJuceIndexForVSTParamID (Vst::ParamID paramID) const noexcept { return static_cast<int> (paramID); }
|
||||
#else
|
||||
void cacheParameterIDs()
|
||||
{
|
||||
const int numParameters = pluginInstance->getNumParameters();
|
||||
usingManagedParameter = (pluginInstance->getParameters().size() == numParameters);
|
||||
|
||||
vstBypassParameterId = static_cast<Vst::ParamID> (usingManagedParameter ? JuceVST3EditController::paramBypass : numParameters);
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
{
|
||||
auto paramID = JuceVST3EditController::generateVSTParamIDForIndex (pluginInstance, i);
|
||||
|
||||
// Consider yourself very unlucky if you hit this assertion. The hash code of your
|
||||
// parameter ids are not unique.
|
||||
jassert (! vstParamIDs.contains (paramID));
|
||||
|
||||
vstParamIDs.add (paramID);
|
||||
paramMap.set (static_cast<int32> (paramID), i);
|
||||
}
|
||||
}
|
||||
|
||||
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? vstParamIDs.getReference (paramIndex)
|
||||
: static_cast<Vst::ParamID> (paramIndex);
|
||||
}
|
||||
|
||||
inline int getJuceIndexForVSTParamID (Vst::ParamID paramID) const noexcept
|
||||
{
|
||||
return usingManagedParameter ? paramMap[static_cast<int32> (paramID)]
|
||||
: static_cast<int> (paramID);
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Component)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_GCC
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif JUCE_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif JUCE_MSVC
|
||||
#pragma warning (push, 0)
|
||||
#pragma warning (disable: 4996)
|
||||
#endif
|
||||
|
||||
class LegacyAudioParameter : public AudioProcessorParameter
|
||||
{
|
||||
public:
|
||||
LegacyAudioParameter (AudioProcessor& audioProcessorToUse, int audioParameterIndex)
|
||||
: audioProcessor (audioProcessorToUse), idx (audioParameterIndex)
|
||||
{
|
||||
jassert (idx < audioProcessor.getNumParameters());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
float getValue() const override { return audioProcessor.getParameter (idx); }
|
||||
void setValue (float newValue) override { audioProcessor.setParameter (idx, newValue); }
|
||||
float getDefaultValue() const override { return audioProcessor.getParameterDefaultValue (idx); }
|
||||
String getName (int maxLen) const override { return audioProcessor.getParameterName (idx, maxLen); }
|
||||
String getLabel() const override { return audioProcessor.getParameterLabel (idx); }
|
||||
int getNumSteps() const override { return audioProcessor.getParameterNumSteps (idx); }
|
||||
bool isDiscrete() const override { return audioProcessor.isParameterDiscrete (idx); }
|
||||
bool isBoolean() const override { return false; }
|
||||
bool isOrientationInverted() const override { return audioProcessor.isParameterOrientationInverted (idx); }
|
||||
bool isAutomatable() const override { return audioProcessor.isParameterAutomatable (idx); }
|
||||
bool isMetaParameter() const override { return audioProcessor.isMetaParameter (idx); }
|
||||
Category getCategory() const override { return audioProcessor.getParameterCategory (idx); }
|
||||
String getCurrentValueAsText() const override { return audioProcessor.getParameterText (idx); }
|
||||
String getParamID() const { return audioProcessor.getParameterID (idx); }
|
||||
|
||||
//==============================================================================
|
||||
float getValueForText (const String&) const override
|
||||
{
|
||||
// legacy parameters do not support this method
|
||||
jassertfalse;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
String getText (float, int) const override
|
||||
{
|
||||
// legacy parameters do not support this method
|
||||
jassertfalse;
|
||||
return {};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool isLegacy (AudioProcessorParameter* param) noexcept
|
||||
{
|
||||
return (dynamic_cast<LegacyAudioParameter*> (param) != nullptr);
|
||||
}
|
||||
|
||||
static int getParamIndex (AudioProcessor& processor, AudioProcessorParameter* param) noexcept
|
||||
{
|
||||
if (auto* legacy = dynamic_cast<LegacyAudioParameter*> (param))
|
||||
{
|
||||
return legacy->idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto n = processor.getNumParameters();
|
||||
jassert (n == processor.getParameters().size());
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (processor.getParameters()[i] == param)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static String getParamID (AudioProcessorParameter* param, bool forceLegacyParamIDs) noexcept
|
||||
{
|
||||
if (auto* legacy = dynamic_cast<LegacyAudioParameter*> (param))
|
||||
{
|
||||
return legacy->getParamID();
|
||||
}
|
||||
else if (auto* paramWithID = dynamic_cast<AudioProcessorParameterWithID*> (param))
|
||||
{
|
||||
if (! forceLegacyParamIDs)
|
||||
return paramWithID->paramID;
|
||||
}
|
||||
|
||||
return String (param->getParameterIndex());
|
||||
}
|
||||
private:
|
||||
AudioProcessor& audioProcessor;
|
||||
int idx;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class LegacyAudioParametersWrapper
|
||||
{
|
||||
public:
|
||||
void update (AudioProcessor& audioProcessor, bool forceLegacyParamIDs)
|
||||
{
|
||||
clear();
|
||||
|
||||
legacyParamIDs = forceLegacyParamIDs;
|
||||
|
||||
auto numParameters = audioProcessor.getNumParameters();
|
||||
usingManagedParameters = (audioProcessor.getParameters().size() == numParameters) && (! legacyParamIDs);
|
||||
|
||||
for (int i = 0; i < numParameters; ++i)
|
||||
{
|
||||
AudioProcessorParameter* param = usingManagedParameters ? audioProcessor.getParameters()[i]
|
||||
: (legacy.add (new LegacyAudioParameter (audioProcessor, i)));
|
||||
params.add (param);
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
legacy.clear();
|
||||
params.clear();
|
||||
}
|
||||
|
||||
AudioProcessorParameter* getParamForIndex (int index) const
|
||||
{
|
||||
if (isPositiveAndBelow (index, params.size()))
|
||||
return params[index];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
String getParamID (AudioProcessor& processor, int idx) const noexcept
|
||||
{
|
||||
return usingManagedParameters ? processor.getParameterID (idx) : String (idx);
|
||||
}
|
||||
|
||||
bool isUsingManagedParameters() const noexcept { return usingManagedParameters; }
|
||||
int getNumParameters() const noexcept { return params.size(); }
|
||||
|
||||
Array<AudioProcessorParameter*> params;
|
||||
|
||||
private:
|
||||
OwnedArray<LegacyAudioParameter> legacy;
|
||||
bool legacyParamIDs = false, usingManagedParameters = false;
|
||||
};
|
||||
|
||||
#if JUCE_GCC
|
||||
#pragma GCC diagnostic pop
|
||||
#elif JUCE_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#elif JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
@ -154,6 +154,7 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone
|
|||
|
||||
#include "format/juce_AudioPluginFormat.cpp"
|
||||
#include "format/juce_AudioPluginFormatManager.cpp"
|
||||
#include "format_types/juce_LegacyAudioParameter.cpp"
|
||||
#include "processors/juce_AudioProcessor.cpp"
|
||||
#include "processors/juce_AudioPluginInstance.cpp"
|
||||
#include "processors/juce_AudioProcessorEditor.cpp"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push, 0)
|
||||
|
||||
// MSVC does not like it if you override a deprecated method even if you
|
||||
// keep the deprecation attribute. Other compilers are more forgiving.
|
||||
#pragma warning (disable: 4996)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for an active instance of a plugin.
|
||||
|
|
@ -123,4 +131,8 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioPluginInstance)
|
||||
};
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -414,6 +414,18 @@ void AudioProcessor::setLatencySamples (const int newLatency)
|
|||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_GCC
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif JUCE_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#elif JUCE_MSVC
|
||||
#pragma warning (push, 0)
|
||||
#pragma warning (disable: 4996)
|
||||
#endif
|
||||
|
||||
void AudioProcessor::setParameterNotifyingHost (int parameterIndex, float newValue)
|
||||
{
|
||||
if (auto* param = getParameters()[parameterIndex])
|
||||
|
|
@ -427,12 +439,6 @@ void AudioProcessor::setParameterNotifyingHost (int parameterIndex, float newVal
|
|||
}
|
||||
}
|
||||
|
||||
AudioProcessorListener* AudioProcessor::getListenerLocked (int index) const noexcept
|
||||
{
|
||||
const ScopedLock sl (listenerLock);
|
||||
return listeners[index];
|
||||
}
|
||||
|
||||
void AudioProcessor::sendParamChangeMessageToListeners (int parameterIndex, float newValue)
|
||||
{
|
||||
if (auto* param = getParameters()[parameterIndex])
|
||||
|
|
@ -511,6 +517,49 @@ void AudioProcessor::endParameterChangeGesture (int parameterIndex)
|
|||
}
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterName (int index, int maximumStringLength)
|
||||
{
|
||||
if (auto* p = managedParameters[index])
|
||||
return p->getName (maximumStringLength);
|
||||
|
||||
return getParameterName (index).substring (0, maximumStringLength);
|
||||
}
|
||||
|
||||
const String AudioProcessor::getParameterText (int index)
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
// if you hit this, then you're probably using the old parameter control methods,
|
||||
// but have forgotten to implement either of the getParameterText() methods.
|
||||
jassert (! textRecursionCheck);
|
||||
ScopedValueSetter<bool> sv (textRecursionCheck, true, false);
|
||||
#endif
|
||||
|
||||
return getParameterText (index, 1024);
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterText (int index, int maximumStringLength)
|
||||
{
|
||||
if (auto* p = managedParameters[index])
|
||||
return p->getText (p->getValue(), maximumStringLength);
|
||||
|
||||
return getParameterText (index).substring (0, maximumStringLength);
|
||||
}
|
||||
|
||||
#if JUCE_GCC
|
||||
#pragma GCC diagnostic pop
|
||||
#elif JUCE_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#elif JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
AudioProcessorListener* AudioProcessor::getListenerLocked (int index) const noexcept
|
||||
{
|
||||
const ScopedLock sl (listenerLock);
|
||||
return listeners[index];
|
||||
}
|
||||
|
||||
void AudioProcessor::updateHostDisplay()
|
||||
{
|
||||
for (int i = listeners.size(); --i >= 0;)
|
||||
|
|
@ -567,34 +616,6 @@ String AudioProcessor::getParameterID (int index)
|
|||
return String (index);
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterName (int index, int maximumStringLength)
|
||||
{
|
||||
if (auto* p = managedParameters[index])
|
||||
return p->getName (maximumStringLength);
|
||||
|
||||
return getParameterName (index).substring (0, maximumStringLength);
|
||||
}
|
||||
|
||||
const String AudioProcessor::getParameterText (int index)
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
// if you hit this, then you're probably using the old parameter control methods,
|
||||
// but have forgotten to implement either of the getParameterText() methods.
|
||||
jassert (! textRecursionCheck);
|
||||
ScopedValueSetter<bool> sv (textRecursionCheck, true, false);
|
||||
#endif
|
||||
|
||||
return getParameterText (index, 1024);
|
||||
}
|
||||
|
||||
String AudioProcessor::getParameterText (int index, int maximumStringLength)
|
||||
{
|
||||
if (auto* p = managedParameters[index])
|
||||
return p->getText (p->getValue(), maximumStringLength);
|
||||
|
||||
return getParameterText (index).substring (0, maximumStringLength);
|
||||
}
|
||||
|
||||
int AudioProcessor::getParameterNumSteps (int index)
|
||||
{
|
||||
if (auto* p = managedParameters[index])
|
||||
|
|
@ -1368,9 +1389,6 @@ AudioProcessorParameter::~AudioProcessorParameter()
|
|||
|
||||
void AudioProcessorParameter::setValueNotifyingHost (float newValue)
|
||||
{
|
||||
// This method can't be used until the parameter has been attached to a processor!
|
||||
jassert (processor != nullptr && parameterIndex >= 0);
|
||||
|
||||
setValue (newValue);
|
||||
sendValueChangedMessageToListeners (newValue);
|
||||
}
|
||||
|
|
@ -1394,11 +1412,14 @@ void AudioProcessorParameter::beginChangeGesture()
|
|||
if (auto* l = listeners[i])
|
||||
l->parameterGestureChanged (getParameterIndex(), true);
|
||||
|
||||
// audioProcessorParameterChangeGestureBegin callbacks will shortly be deprecated and
|
||||
// this code will be removed.
|
||||
for (int i = processor->listeners.size(); --i >= 0;)
|
||||
if (auto* l = processor->listeners[i])
|
||||
l->audioProcessorParameterChangeGestureBegin (processor, getParameterIndex());
|
||||
if (processor != nullptr && parameterIndex >= 0)
|
||||
{
|
||||
// audioProcessorParameterChangeGestureBegin callbacks will shortly be deprecated and
|
||||
// this code will be removed.
|
||||
for (int i = processor->listeners.size(); --i >= 0;)
|
||||
if (auto* l = processor->listeners[i])
|
||||
l->audioProcessorParameterChangeGestureBegin (processor, getParameterIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessorParameter::endChangeGesture()
|
||||
|
|
@ -1420,11 +1441,14 @@ void AudioProcessorParameter::endChangeGesture()
|
|||
if (auto* l = listeners[i])
|
||||
l->parameterGestureChanged (getParameterIndex(), false);
|
||||
|
||||
// audioProcessorParameterChangeGestureEnd callbacks will shortly be deprecated and
|
||||
// this code will be removed.
|
||||
for (int i = processor->listeners.size(); --i >= 0;)
|
||||
if (auto* l = processor->listeners[i])
|
||||
l->audioProcessorParameterChangeGestureEnd (processor, getParameterIndex());
|
||||
if (processor != nullptr && parameterIndex >= 0)
|
||||
{
|
||||
// audioProcessorParameterChangeGestureEnd callbacks will shortly be deprecated and
|
||||
// this code will be removed.
|
||||
for (int i = processor->listeners.size(); --i >= 0;)
|
||||
if (auto* l = processor->listeners[i])
|
||||
l->audioProcessorParameterChangeGestureEnd (processor, getParameterIndex());
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue)
|
||||
|
|
@ -1435,11 +1459,14 @@ void AudioProcessorParameter::sendValueChangedMessageToListeners (float newValue
|
|||
if (auto* l = listeners [i])
|
||||
l->parameterValueChanged (getParameterIndex(), newValue);
|
||||
|
||||
// audioProcessorParameterChanged callbacks will shortly be deprecated and
|
||||
// this code will be removed.
|
||||
for (int i = processor->listeners.size(); --i >= 0;)
|
||||
if (auto* l = processor->listeners[i])
|
||||
l->audioProcessorParameterChanged (processor, getParameterIndex(), newValue);
|
||||
if (processor != nullptr && parameterIndex >= 0)
|
||||
{
|
||||
// audioProcessorParameterChanged callbacks will shortly be deprecated and
|
||||
// this code will be removed.
|
||||
for (int i = processor->listeners.size(); --i >= 0;)
|
||||
if (auto* l = processor->listeners[i])
|
||||
l->audioProcessorParameterChanged (processor, getParameterIndex(), newValue);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioProcessorParameter::isOrientationInverted() const { return false; }
|
||||
|
|
|
|||
|
|
@ -962,14 +962,14 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use the
|
||||
AudioProcessorParameter class instead to manage your parameters.
|
||||
*/
|
||||
virtual int getNumParameters();
|
||||
JUCE_DEPRECATED (virtual int getNumParameters());
|
||||
|
||||
/** Returns the name of a particular parameter.
|
||||
|
||||
NOTE! This method will eventually be deprecated! It's recommended that you use the
|
||||
AudioProcessorParameter class instead to manage your parameters.
|
||||
*/
|
||||
virtual const String getParameterName (int parameterIndex);
|
||||
JUCE_DEPRECATED (virtual const String getParameterName (int parameterIndex));
|
||||
|
||||
/** Returns the ID of a particular parameter.
|
||||
|
||||
|
|
@ -980,7 +980,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use the
|
||||
AudioProcessorParameterWithID class instead to manage your parameters.
|
||||
*/
|
||||
virtual String getParameterID (int index);
|
||||
JUCE_DEPRECATED (virtual String getParameterID (int index));
|
||||
|
||||
/** Called by the host to find out the value of one of the processor's parameters.
|
||||
|
||||
|
|
@ -993,7 +993,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use the
|
||||
AudioProcessorParameter class instead to manage your parameters.
|
||||
*/
|
||||
virtual float getParameter (int parameterIndex);
|
||||
JUCE_DEPRECATED (virtual float getParameter (int parameterIndex));
|
||||
|
||||
/** Returns the name of a parameter as a text string with a preferred maximum length.
|
||||
If you want to provide customised short versions of your parameter names that
|
||||
|
|
@ -1005,13 +1005,13 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::getName() instead.
|
||||
*/
|
||||
virtual String getParameterName (int parameterIndex, int maximumStringLength);
|
||||
JUCE_DEPRECATED (virtual String getParameterName (int parameterIndex, int maximumStringLength));
|
||||
|
||||
/** Returns the value of a parameter as a text string.
|
||||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::getText() instead.
|
||||
*/
|
||||
virtual const String getParameterText (int parameterIndex);
|
||||
JUCE_DEPRECATED (virtual const String getParameterText (int parameterIndex));
|
||||
|
||||
/** Returns the value of a parameter as a text string with a preferred maximum length.
|
||||
If you want to provide customised short versions of your parameter values that
|
||||
|
|
@ -1023,7 +1023,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::getText() instead.
|
||||
*/
|
||||
virtual String getParameterText (int parameterIndex, int maximumStringLength);
|
||||
JUCE_DEPRECATED (virtual String getParameterText (int parameterIndex, int maximumStringLength));
|
||||
|
||||
/** Returns the number of discrete steps that this parameter can represent.
|
||||
|
||||
|
|
@ -1043,7 +1043,7 @@ public:
|
|||
|
||||
@see isParameterDiscrete
|
||||
*/
|
||||
virtual int getParameterNumSteps (int parameterIndex);
|
||||
JUCE_DEPRECATED (virtual int getParameterNumSteps (int parameterIndex));
|
||||
|
||||
/** Returns the default number of steps for a parameter.
|
||||
|
||||
|
|
@ -1067,7 +1067,7 @@ public:
|
|||
|
||||
@see getParameterNumSteps
|
||||
*/
|
||||
virtual bool isParameterDiscrete (int parameterIndex) const;
|
||||
JUCE_DEPRECATED (virtual bool isParameterDiscrete (int parameterIndex) const);
|
||||
|
||||
/** Returns the default value for the parameter.
|
||||
By default, this just returns 0.
|
||||
|
|
@ -1076,7 +1076,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::getDefaultValue() instead.
|
||||
*/
|
||||
virtual float getParameterDefaultValue (int parameterIndex);
|
||||
JUCE_DEPRECATED (virtual float getParameterDefaultValue (int parameterIndex));
|
||||
|
||||
/** Some plugin types may be able to return a label string for a
|
||||
parameter's units.
|
||||
|
|
@ -1084,7 +1084,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::getLabel() instead.
|
||||
*/
|
||||
virtual String getParameterLabel (int index) const;
|
||||
JUCE_DEPRECATED (virtual String getParameterLabel (int index) const);
|
||||
|
||||
/** This can be overridden to tell the host that particular parameters operate in the
|
||||
reverse direction. (Not all plugin formats or hosts will actually use this information).
|
||||
|
|
@ -1092,7 +1092,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::isOrientationInverted() instead.
|
||||
*/
|
||||
virtual bool isParameterOrientationInverted (int index) const;
|
||||
JUCE_DEPRECATED (virtual bool isParameterOrientationInverted (int index) const);
|
||||
|
||||
/** The host will call this method to change the value of one of the processor's parameters.
|
||||
|
||||
|
|
@ -1110,7 +1110,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::setValue() instead.
|
||||
*/
|
||||
virtual void setParameter (int parameterIndex, float newValue);
|
||||
JUCE_DEPRECATED (virtual void setParameter (int parameterIndex, float newValue));
|
||||
|
||||
/** Your processor can call this when it needs to change one of its parameters.
|
||||
|
||||
|
|
@ -1133,7 +1133,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::isAutomatable() instead.
|
||||
*/
|
||||
virtual bool isParameterAutomatable (int parameterIndex) const;
|
||||
JUCE_DEPRECATED (virtual bool isParameterAutomatable (int parameterIndex) const);
|
||||
|
||||
/** Should return true if this parameter is a "meta" parameter.
|
||||
A meta-parameter is a parameter that changes other params. It is used
|
||||
|
|
@ -1143,7 +1143,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::isMetaParameter() instead.
|
||||
*/
|
||||
virtual bool isMetaParameter (int parameterIndex) const;
|
||||
JUCE_DEPRECATED (virtual bool isMetaParameter (int parameterIndex) const);
|
||||
|
||||
/** Should return the parameter's category.
|
||||
By default, this returns the "generic" category.
|
||||
|
|
@ -1151,7 +1151,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::getCategory() instead.
|
||||
*/
|
||||
virtual AudioProcessorParameter::Category getParameterCategory (int parameterIndex) const;
|
||||
JUCE_DEPRECATED (virtual AudioProcessorParameter::Category getParameterCategory (int parameterIndex) const);
|
||||
|
||||
/** Sends a signal to the host to tell it that the user is about to start changing this
|
||||
parameter.
|
||||
|
|
@ -1164,7 +1164,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::beginChangeGesture() instead.
|
||||
*/
|
||||
void beginParameterChangeGesture (int parameterIndex);
|
||||
JUCE_DEPRECATED (void beginParameterChangeGesture (int parameterIndex));
|
||||
|
||||
/** Tells the host that the user has finished changing this parameter.
|
||||
|
||||
|
|
@ -1176,7 +1176,7 @@ public:
|
|||
NOTE! This method will eventually be deprecated! It's recommended that you use
|
||||
AudioProcessorParameter::endChangeGesture() instead.
|
||||
*/
|
||||
void endParameterChangeGesture (int parameterIndex);
|
||||
JUCE_DEPRECATED (void endParameterChangeGesture (int parameterIndex));
|
||||
|
||||
/** The processor can call this when something (apart from a parameter value) has changed.
|
||||
|
||||
|
|
@ -1626,8 +1626,6 @@ private:
|
|||
friend class AudioUnitPluginInstance;
|
||||
friend class LADSPAPluginInstance;
|
||||
|
||||
Atomic<int> vst3IsPlaying { 0 };
|
||||
|
||||
// This method is no longer used - you can delete it from your AudioProcessor classes.
|
||||
JUCE_DEPRECATED_WITH_BODY (virtual bool silenceInProducesSilenceOut() const, { return false; })
|
||||
|
||||
|
|
|
|||
|
|
@ -27,166 +27,6 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
class ProcessorParameterPropertyComp : public PropertyComponent,
|
||||
private AudioProcessorListener,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
ProcessorParameterPropertyComp (const String& name, AudioProcessor& p, int paramIndex)
|
||||
: PropertyComponent (name),
|
||||
owner (p),
|
||||
index (paramIndex),
|
||||
slider (p, paramIndex)
|
||||
{
|
||||
startTimer (100);
|
||||
addAndMakeVisible (slider);
|
||||
owner.addListener (this);
|
||||
}
|
||||
|
||||
~ProcessorParameterPropertyComp()
|
||||
{
|
||||
owner.removeListener (this);
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
paramHasChanged = false;
|
||||
|
||||
if (slider.getThumbBeingDragged() < 0)
|
||||
slider.setValue (owner.getParameter (index), dontSendNotification);
|
||||
|
||||
slider.updateText();
|
||||
}
|
||||
|
||||
void audioProcessorChanged (AudioProcessor*) override {}
|
||||
|
||||
void audioProcessorParameterChanged (AudioProcessor*, int parameterIndex, float) override
|
||||
{
|
||||
if (parameterIndex == index)
|
||||
paramHasChanged = true;
|
||||
}
|
||||
|
||||
void timerCallback() override
|
||||
{
|
||||
if (paramHasChanged)
|
||||
{
|
||||
refresh();
|
||||
startTimerHz (50);
|
||||
}
|
||||
else
|
||||
{
|
||||
startTimer (jmin (1000 / 4, getTimerInterval() + 10));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class ParamSlider : public Slider
|
||||
{
|
||||
public:
|
||||
ParamSlider (AudioProcessor& p, int paramIndex) : owner (p), index (paramIndex)
|
||||
{
|
||||
auto steps = owner.getParameterNumSteps (index);
|
||||
auto category = p.getParameterCategory (index);
|
||||
bool isLevelMeter = (((category & 0xffff0000) >> 16) == 2);
|
||||
|
||||
if (steps > 1 && steps < 0x7fffffff)
|
||||
setRange (0.0, 1.0, 1.0 / (steps - 1.0));
|
||||
else
|
||||
setRange (0.0, 1.0);
|
||||
|
||||
setEnabled (! isLevelMeter);
|
||||
setSliderStyle (Slider::LinearBar);
|
||||
setTextBoxIsEditable (false);
|
||||
setScrollWheelEnabled (true);
|
||||
}
|
||||
|
||||
void valueChanged() override
|
||||
{
|
||||
auto newVal = static_cast<float> (getValue());
|
||||
|
||||
if (owner.getParameter (index) != newVal)
|
||||
{
|
||||
owner.setParameterNotifyingHost (index, newVal);
|
||||
updateText();
|
||||
}
|
||||
}
|
||||
|
||||
void startedDragging() override
|
||||
{
|
||||
owner.beginParameterChangeGesture (index);
|
||||
}
|
||||
|
||||
void stoppedDragging() override
|
||||
{
|
||||
owner.endParameterChangeGesture (index);
|
||||
}
|
||||
|
||||
String getTextFromValue (double /*value*/) override
|
||||
{
|
||||
return (owner.getParameterText (index) + " " + owner.getParameterLabel (index)).trimEnd();
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
AudioProcessor& owner;
|
||||
const int index;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamSlider)
|
||||
};
|
||||
|
||||
AudioProcessor& owner;
|
||||
const int index;
|
||||
bool volatile paramHasChanged = false;
|
||||
ParamSlider slider;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProcessorParameterPropertyComp)
|
||||
};
|
||||
|
||||
struct LegacyParametersPanel : public Component
|
||||
{
|
||||
LegacyParametersPanel (AudioProcessor* const processor)
|
||||
{
|
||||
addAndMakeVisible (panel);
|
||||
|
||||
Array<PropertyComponent*> params;
|
||||
|
||||
auto numParams = processor->getNumParameters();
|
||||
int totalHeight = 0;
|
||||
|
||||
for (int i = 0; i < numParams; ++i)
|
||||
{
|
||||
String name (processor->getParameterName (i));
|
||||
|
||||
if (name.trim().isEmpty())
|
||||
name = "Unnamed";
|
||||
|
||||
auto* pc = new ProcessorParameterPropertyComp (name, *processor, i);
|
||||
params.add (pc);
|
||||
totalHeight += pc->getPreferredHeight();
|
||||
}
|
||||
|
||||
panel.addProperties (params);
|
||||
|
||||
setSize (400, jmax (25, totalHeight));
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
panel.setBounds (getLocalBounds());
|
||||
}
|
||||
|
||||
PropertyPanel panel;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LegacyParametersPanel)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ParameterListener : private AudioProcessorParameter::Listener,
|
||||
private Timer
|
||||
{
|
||||
|
|
@ -615,7 +455,7 @@ private:
|
|||
class ParametersPanel : public Component
|
||||
{
|
||||
public:
|
||||
ParametersPanel (const OwnedArray<AudioProcessorParameter>& parameters)
|
||||
ParametersPanel (const Array<AudioProcessorParameter*>& parameters)
|
||||
{
|
||||
for (auto* param : parameters)
|
||||
if (param->isAutomatable())
|
||||
|
|
@ -647,25 +487,40 @@ private:
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const p)
|
||||
: AudioProcessorEditor (p)
|
||||
struct GenericAudioProcessorEditor::Pimpl
|
||||
{
|
||||
jassert (p != nullptr);
|
||||
setOpaque (true);
|
||||
Pimpl (GenericAudioProcessorEditor& parent)
|
||||
: owner (parent)
|
||||
{
|
||||
auto* p = parent.getAudioProcessor();
|
||||
jassert (p != nullptr);
|
||||
|
||||
auto& parameters = p->getParameters();
|
||||
juceParameters.update (*p, false);
|
||||
|
||||
if (parameters.size() == p->getNumParameters())
|
||||
view.setViewedComponent (new ParametersPanel (parameters));
|
||||
else
|
||||
view.setViewedComponent (new LegacyParametersPanel (p));
|
||||
owner.setOpaque (true);
|
||||
|
||||
addAndMakeVisible (view);
|
||||
view.setViewedComponent (new ParametersPanel (juceParameters.params));
|
||||
owner.addAndMakeVisible (view);
|
||||
|
||||
view.setScrollBarsShown (true, false);
|
||||
setSize (view.getViewedComponent()->getWidth() + view.getVerticalScrollBar().getWidth(),
|
||||
jmin (view.getViewedComponent()->getHeight(), 400));
|
||||
}
|
||||
view.setScrollBarsShown (true, false);
|
||||
owner.setSize (view.getViewedComponent()->getWidth() + view.getVerticalScrollBar().getWidth(),
|
||||
jmin (view.getViewedComponent()->getHeight(), 400));
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
GenericAudioProcessorEditor& owner;
|
||||
LegacyAudioParametersWrapper juceParameters;
|
||||
Viewport view;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
GenericAudioProcessorEditor::GenericAudioProcessorEditor (AudioProcessor* const p)
|
||||
: AudioProcessorEditor (p), pimpl (new Pimpl (*this))
|
||||
{}
|
||||
|
||||
GenericAudioProcessorEditor::~GenericAudioProcessorEditor() {}
|
||||
|
||||
|
|
@ -676,7 +531,7 @@ void GenericAudioProcessorEditor::paint (Graphics& g)
|
|||
|
||||
void GenericAudioProcessorEditor::resized()
|
||||
{
|
||||
view.setBounds (getLocalBounds());
|
||||
pimpl->view.setBounds (getLocalBounds());
|
||||
}
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
Viewport view;
|
||||
struct Pimpl;
|
||||
ScopedPointer<Pimpl> pimpl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GenericAudioProcessorEditor)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue