Browse Source

VST3: Fixed an AudioProcessorParameterGroup bug

tags/2021-05-28
Tom Poole 6 years ago
parent
commit
17be524798
1 changed files with 249 additions and 106 deletions
  1. +249
    -106
      modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp

+ 249
- 106
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -89,7 +89,7 @@ using namespace Steinberg;
#endif
//==============================================================================
class JuceAudioProcessor : public FUnknown
class JuceAudioProcessor : public Vst::IUnitInfo
{
public:
JuceAudioProcessor (AudioProcessor* source) noexcept
@@ -105,6 +105,99 @@ public:
JUCE_DECLARE_VST3_COM_QUERY_METHODS
JUCE_DECLARE_VST3_COM_REF_METHODS
//==============================================================================
enum InternalParameters
{
paramPreset = 0x70727374, // 'prst'
paramMidiControllerOffset = 0x6d636d00, // 'mdm*'
paramBypass = 0x62797073 // 'byps'
};
//==============================================================================
Steinberg::int32 PLUGIN_API getUnitCount() override
{
return parameterGroups.size() + 1;
}
tresult PLUGIN_API getUnitInfo (Steinberg::int32 unitIndex, Vst::UnitInfo& info) override
{
if (unitIndex == 0)
{
info.id = Vst::kRootUnitId;
info.parentUnitId = Vst::kNoParentUnitId;
info.programListId = Vst::kNoProgramListId;
toString128 (info.name, TRANS("Root Unit"));
return kResultTrue;
}
if (auto* group = parameterGroups[unitIndex - 1])
{
info.id = JuceAudioProcessor::getUnitID (group);
info.parentUnitId = JuceAudioProcessor::getUnitID (group->getParent());
info.programListId = Vst::kNoProgramListId;
toString128 (info.name, group->getName());
return kResultTrue;
}
return kResultFalse;
}
Steinberg::int32 PLUGIN_API getProgramListCount() override
{
if (audioProcessor->getNumPrograms() > 0)
return 1;
return 0;
}
tresult PLUGIN_API getProgramListInfo (Steinberg::int32 listIndex, Vst::ProgramListInfo& info) override
{
if (listIndex == 0)
{
info.id = paramPreset;
info.programCount = (Steinberg::int32) audioProcessor->getNumPrograms();
toString128 (info.name, TRANS("Factory Presets"));
return kResultTrue;
}
jassertfalse;
zerostruct (info);
return kResultFalse;
}
tresult PLUGIN_API getProgramName (Vst::ProgramListID listId, Steinberg::int32 programIndex, Vst::String128 name) override
{
if (listId == paramPreset
&& isPositiveAndBelow ((int) programIndex, audioProcessor->getNumPrograms()))
{
toString128 (name, audioProcessor->getProgramName ((int) programIndex));
return kResultTrue;
}
jassertfalse;
toString128 (name, juce::String());
return kResultFalse;
}
tresult PLUGIN_API getProgramInfo (Vst::ProgramListID, Steinberg::int32, Vst::CString, Vst::String128) override { return kNotImplemented; }
tresult PLUGIN_API hasProgramPitchNames (Vst::ProgramListID, Steinberg::int32) override { return kNotImplemented; }
tresult PLUGIN_API getProgramPitchName (Vst::ProgramListID, Steinberg::int32, Steinberg::int16, Vst::String128) override { return kNotImplemented; }
tresult PLUGIN_API selectUnit (Vst::UnitID) override { return kNotImplemented; }
tresult PLUGIN_API setUnitProgramData (Steinberg::int32, Steinberg::int32, IBStream*) override { return kNotImplemented; }
Vst::UnitID PLUGIN_API getSelectedUnit() override { return Vst::kRootUnitId; }
tresult PLUGIN_API getUnitByBus (Vst::MediaType, Vst::BusDirection, Steinberg::int32, Steinberg::int32, Vst::UnitID& unitId) override
{
zerostruct (unitId);
return kNotImplemented;
}
//==============================================================================
inline Vst::ParamID getVSTParamIDForIndex (int paramIndex) const noexcept
{
@@ -140,11 +233,6 @@ public:
bool bypassIsRegularParameter = false;
private:
enum InternalParameters
{
paramBypass = 0x62797073 // 'byps'
};
//==============================================================================
bool isBypassPartOfRegularParemeters() const
{
@@ -160,6 +248,8 @@ private:
void setupParameters()
{
parameterGroups = audioProcessor->getParameterTree().getSubgroups (true);
#if JUCE_FORCE_USE_LEGACY_PARAM_IDS
const bool forceLegacyParamIDs = true;
#else
@@ -235,6 +325,7 @@ private:
LegacyAudioParametersWrapper juceParameters;
HashMap<int32, AudioProcessorParameter*> paramMap;
std::unique_ptr<AudioProcessorParameter> ownedBypassParameter;
Array<const AudioProcessorParameterGroup*> parameterGroups;
JuceAudioProcessor() = delete;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceAudioProcessor)
@@ -247,6 +338,7 @@ static ThreadLocalValue<bool> inParameterChangedCallback;
//==============================================================================
class JuceVST3EditController : public Vst::EditController,
public Vst::IMidiMapping,
public Vst::IUnitInfo,
public Vst::ChannelContext::IInfoListener,
public AudioProcessorListener,
private AudioProcessorParameter::Listener
@@ -281,6 +373,7 @@ public:
TEST_FOR_AND_RETURN_IF_VALID (targetIID, Vst::IEditController2)
TEST_FOR_AND_RETURN_IF_VALID (targetIID, Vst::IConnectionPoint)
TEST_FOR_AND_RETURN_IF_VALID (targetIID, Vst::IMidiMapping)
TEST_FOR_AND_RETURN_IF_VALID (targetIID, Vst::IUnitInfo)
TEST_FOR_AND_RETURN_IF_VALID (targetIID, Vst::ChannelContext::IInfoListener)
TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID (targetIID, IPluginBase, Vst::IEditController)
TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID (targetIID, IDependent, Vst::IEditController)
@@ -325,12 +418,6 @@ public:
}
//==============================================================================
enum InternalParameters
{
paramPreset = 0x70727374, // 'prst'
paramMidiControllerOffset = 0x6d636d00 // 'mdm*'
};
struct Param : public Vst::Parameter
{
Param (JuceVST3EditController& editController, AudioProcessorParameter& p,
@@ -440,7 +527,7 @@ public:
{
jassert (owner.getNumPrograms() > 1);
info.id = paramPreset;
info.id = JuceAudioProcessor::paramPreset;
toString128 (info.title, "Program");
toString128 (info.shortTitle, "Program");
toString128 (info.units, "");
@@ -553,8 +640,8 @@ public:
auto numPrograms = pluginInstance->getNumPrograms();
if (numPrograms > 1)
setParamNormalized (paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (numPrograms - 1));
setParamNormalized (JuceAudioProcessor::paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (numPrograms - 1));
}
if (auto* handler = getComponentHandler())
@@ -626,6 +713,133 @@ public:
static_cast<Vst::ParamID> (numElementsInArray (parameterToMidiController))));
}
//==============================================================================
Steinberg::int32 PLUGIN_API getUnitCount() override
{
if (audioProcessor != nullptr)
return audioProcessor->getUnitCount();
jassertfalse;
return 1;
}
tresult PLUGIN_API getUnitInfo (Steinberg::int32 unitIndex, Vst::UnitInfo& info) override
{
if (audioProcessor != nullptr)
return audioProcessor->getUnitInfo (unitIndex, info);
if (unitIndex == 0)
{
info.id = Vst::kRootUnitId;
info.parentUnitId = Vst::kNoParentUnitId;
info.programListId = Vst::kNoProgramListId;
toString128 (info.name, TRANS("Root Unit"));
return kResultTrue;
}
jassertfalse;
zerostruct (info);
return kResultFalse;
}
Steinberg::int32 PLUGIN_API getProgramListCount() override
{
if (audioProcessor != nullptr)
return audioProcessor->getProgramListCount();
jassertfalse;
return 0;
}
tresult PLUGIN_API getProgramListInfo (Steinberg::int32 listIndex, Vst::ProgramListInfo& info) override
{
if (audioProcessor != nullptr)
return audioProcessor->getProgramListInfo (listIndex, info);
jassertfalse;
zerostruct (info);
return kResultFalse;
}
tresult PLUGIN_API getProgramName (Vst::ProgramListID listId, Steinberg::int32 programIndex, Vst::String128 name) override
{
if (audioProcessor != nullptr)
return audioProcessor->getProgramName (listId, programIndex, name);
jassertfalse;
toString128 (name, juce::String());
return kResultFalse;
}
tresult PLUGIN_API getProgramInfo (Vst::ProgramListID listId, Steinberg::int32 programIndex,
Vst::CString attributeId, Vst::String128 attributeValue) override
{
if (audioProcessor != nullptr)
return audioProcessor->getProgramInfo (listId, programIndex, attributeId, attributeValue);
jassertfalse;
return kResultFalse;
}
tresult PLUGIN_API hasProgramPitchNames (Vst::ProgramListID listId, Steinberg::int32 programIndex) override
{
if (audioProcessor != nullptr)
return audioProcessor->hasProgramPitchNames (listId, programIndex);
jassertfalse;
return kResultFalse;
}
tresult PLUGIN_API getProgramPitchName (Vst::ProgramListID listId, Steinberg::int32 programIndex,
Steinberg::int16 midiPitch, Vst::String128 name) override
{
if (audioProcessor != nullptr)
return audioProcessor->getProgramPitchName (listId, programIndex, midiPitch, name);
jassertfalse;
return kResultFalse;
}
tresult PLUGIN_API selectUnit (Vst::UnitID unitId) override
{
if (audioProcessor != nullptr)
return audioProcessor->selectUnit (unitId);
jassertfalse;
return kResultFalse;
}
tresult PLUGIN_API setUnitProgramData (Steinberg::int32 listOrUnitId, Steinberg::int32 programIndex,
Steinberg::IBStream* data) override
{
if (audioProcessor != nullptr)
return audioProcessor->setUnitProgramData (listOrUnitId, programIndex, data);
jassertfalse;
return kResultFalse;
}
Vst::UnitID PLUGIN_API getSelectedUnit() override
{
if (audioProcessor != nullptr)
return audioProcessor->getSelectedUnit();
jassertfalse;
return kResultFalse;
}
tresult PLUGIN_API getUnitByBus (Vst::MediaType type, Vst::BusDirection dir, Steinberg::int32 busIndex,
Steinberg::int32 channel, Vst::UnitID& unitId) override
{
if (audioProcessor != nullptr)
return audioProcessor->getUnitByBus (type, dir, busIndex, channel, unitId);
jassertfalse;
return kResultFalse;
}
//==============================================================================
IPlugView* PLUGIN_API createView (const char* name) override
{
@@ -669,8 +883,8 @@ public:
if (auto* pluginInstance = getPluginInstance())
{
if (pluginInstance->getNumPrograms() > 1)
EditController::setParamNormalized (paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (pluginInstance->getNumPrograms() - 1));
EditController::setParamNormalized (JuceAudioProcessor::paramPreset, static_cast<Vst::ParamValue> (pluginInstance->getCurrentProgram())
/ static_cast<Vst::ParamValue> (pluginInstance->getNumPrograms() - 1));
}
if (componentHandler != nullptr)
@@ -758,7 +972,7 @@ private:
}
#if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (audioProcessor->isUsingManagedParameters() ? paramMidiControllerOffset
parameterToMidiControllerOffset = static_cast<Vst::ParamID> (audioProcessor->isUsingManagedParameters() ? JuceAudioProcessor::paramMidiControllerOffset
: parameters.getParameterCount());
initialiseMidiControllerMappings();
@@ -1349,8 +1563,6 @@ public:
// and not AudioChannelSet::discreteChannels (2) etc.
jassert (checkBusFormatsAreNotDiscrete());
parameterGroups = pluginInstance->parameterTree.getSubgroups (true);
comPluginInstance = new JuceAudioProcessor (pluginInstance);
zerostruct (processContext);
@@ -1844,89 +2056,22 @@ public:
}
//==============================================================================
Steinberg::int32 PLUGIN_API getUnitCount() override
{
return parameterGroups.size() + 1;
}
tresult PLUGIN_API getUnitInfo (Steinberg::int32 unitIndex, Vst::UnitInfo& info) override
{
if (unitIndex == 0)
{
info.id = Vst::kRootUnitId;
info.parentUnitId = Vst::kNoParentUnitId;
info.programListId = Vst::kNoProgramListId;
toString128 (info.name, TRANS("Root Unit"));
return kResultTrue;
}
if (auto* group = parameterGroups[unitIndex - 1])
{
info.id = JuceAudioProcessor::getUnitID (group);
info.parentUnitId = JuceAudioProcessor::getUnitID (group->getParent());
info.programListId = Vst::kNoProgramListId;
toString128 (info.name, group->getName());
return kResultTrue;
}
return kResultFalse;
}
Steinberg::int32 PLUGIN_API getProgramListCount() override
{
if (getPluginInstance().getNumPrograms() > 0)
return 1;
return 0;
}
tresult PLUGIN_API getProgramListInfo (Steinberg::int32 listIndex, Vst::ProgramListInfo& info) override
{
if (listIndex == 0)
{
info.id = JuceVST3EditController::paramPreset;
info.programCount = (Steinberg::int32) getPluginInstance().getNumPrograms();
toString128 (info.name, TRANS("Factory Presets"));
return kResultTrue;
}
jassertfalse;
zerostruct (info);
return kResultFalse;
}
tresult PLUGIN_API getProgramName (Vst::ProgramListID listId, Steinberg::int32 programIndex, Vst::String128 name) override
{
if (listId == JuceVST3EditController::paramPreset
&& isPositiveAndBelow ((int) programIndex, getPluginInstance().getNumPrograms()))
{
toString128 (name, getPluginInstance().getProgramName ((int) programIndex));
return kResultTrue;
}
jassertfalse;
toString128 (name, juce::String());
return kResultFalse;
}
tresult PLUGIN_API getProgramInfo (Vst::ProgramListID, Steinberg::int32, Vst::CString, Vst::String128) override { return kNotImplemented; }
tresult PLUGIN_API hasProgramPitchNames (Vst::ProgramListID, Steinberg::int32) override { return kNotImplemented; }
tresult PLUGIN_API getProgramPitchName (Vst::ProgramListID, Steinberg::int32, Steinberg::int16, Vst::String128) override { return kNotImplemented; }
tresult PLUGIN_API selectUnit (Vst::UnitID) override { return kNotImplemented; }
tresult PLUGIN_API setUnitProgramData (Steinberg::int32, Steinberg::int32, IBStream*) override { return kNotImplemented; }
Vst::UnitID PLUGIN_API getSelectedUnit() override { return Vst::kRootUnitId; }
tresult PLUGIN_API getUnitByBus (Vst::MediaType, Vst::BusDirection, Steinberg::int32, Steinberg::int32, Vst::UnitID& unitId) override
{
zerostruct (unitId);
return kNotImplemented;
}
Steinberg::int32 PLUGIN_API getUnitCount() override { return comPluginInstance->getUnitCount(); }
tresult PLUGIN_API getUnitInfo (Steinberg::int32 unitIndex, Vst::UnitInfo& info) override { return comPluginInstance->getUnitInfo (unitIndex, info); }
Steinberg::int32 PLUGIN_API getProgramListCount() override { return comPluginInstance->getProgramListCount(); }
tresult PLUGIN_API getProgramListInfo (Steinberg::int32 listIndex, Vst::ProgramListInfo& info) override { return comPluginInstance->getProgramListInfo (listIndex, info); }
tresult PLUGIN_API getProgramName (Vst::ProgramListID listId, Steinberg::int32 programIndex, Vst::String128 name) override { return comPluginInstance->getProgramName (listId, programIndex, name); }
tresult PLUGIN_API getProgramInfo (Vst::ProgramListID listId, Steinberg::int32 programIndex,
Vst::CString attributeId, Vst::String128 attributeValue) override { return comPluginInstance->getProgramInfo (listId, programIndex, attributeId, attributeValue); }
tresult PLUGIN_API hasProgramPitchNames (Vst::ProgramListID listId, Steinberg::int32 programIndex) override { return comPluginInstance->hasProgramPitchNames (listId, programIndex); }
tresult PLUGIN_API getProgramPitchName (Vst::ProgramListID listId, Steinberg::int32 programIndex,
Steinberg::int16 midiPitch, Vst::String128 name) override { return comPluginInstance->getProgramPitchName (listId, programIndex, midiPitch, name); }
tresult PLUGIN_API selectUnit (Vst::UnitID unitId) override { return comPluginInstance->selectUnit (unitId); }
tresult PLUGIN_API setUnitProgramData (Steinberg::int32 listOrUnitId, Steinberg::int32 programIndex,
Steinberg::IBStream* data) override { return comPluginInstance->setUnitProgramData (listOrUnitId, programIndex, data); }
Vst::UnitID PLUGIN_API getSelectedUnit() override { return comPluginInstance->getSelectedUnit(); }
tresult PLUGIN_API getUnitByBus (Vst::MediaType type, Vst::BusDirection dir, Steinberg::int32 busIndex,
Steinberg::int32 channel, Vst::UnitID& unitId) override { return comPluginInstance->getUnitByBus (type, dir, busIndex, channel, unitId); }
//==============================================================================
bool getCurrentPosition (CurrentPositionInfo& info) override
@@ -2262,7 +2407,7 @@ public:
{
auto vstParamID = paramQueue->getParameterId();
if (vstParamID == JuceVST3EditController::paramPreset)
if (vstParamID == JuceAudioProcessor::paramPreset)
{
auto numPrograms = pluginInstance->getNumPrograms();
auto programValue = roundToInt (value * (jmax (0, numPrograms - 1)));
@@ -2622,8 +2767,6 @@ private:
ScopedJuceInitialiser_GUI libraryInitialiser;
static const char* kJucePrivateDataIdentifier;
Array<const AudioProcessorParameterGroup*> parameterGroups;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Component)
};


Loading…
Cancel
Save