diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp index 8c1b6ae089..a68f25ef9f 100644 --- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp @@ -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 paramMap; std::unique_ptr ownedBypassParameter; + Array parameterGroups; JuceAudioProcessor() = delete; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceAudioProcessor) @@ -247,6 +338,7 @@ static ThreadLocalValue 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 (pluginInstance->getCurrentProgram()) - / static_cast (numPrograms - 1)); + setParamNormalized (JuceAudioProcessor::paramPreset, static_cast (pluginInstance->getCurrentProgram()) + / static_cast (numPrograms - 1)); } if (auto* handler = getComponentHandler()) @@ -626,6 +713,133 @@ public: static_cast (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 (pluginInstance->getCurrentProgram()) - / static_cast (pluginInstance->getNumPrograms() - 1)); + EditController::setParamNormalized (JuceAudioProcessor::paramPreset, static_cast (pluginInstance->getCurrentProgram()) + / static_cast (pluginInstance->getNumPrograms() - 1)); } if (componentHandler != nullptr) @@ -758,7 +972,7 @@ private: } #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS - parameterToMidiControllerOffset = static_cast (audioProcessor->isUsingManagedParameters() ? paramMidiControllerOffset + parameterToMidiControllerOffset = static_cast (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 parameterGroups; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Component) };