diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index b790e68174..3478fbfe9e 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -694,8 +694,8 @@ public: tresult PLUGIN_API notifyProgramListChange (Vst::ProgramListID, Steinberg::int32) override { - jassertfalse; - return kResultFalse; + owner->syncProgramNames(); + return kResultTrue; } //============================================================================== @@ -1594,6 +1594,7 @@ public: : module (handle), numInputAudioBusses (0), numOutputAudioBusses (0), + programParameterID (-1), inputParameterChanges (new ParamValueQueueList()), outputParameterChanges (new ParamValueQueueList()), midiInputs (new MidiEventList()), @@ -1663,6 +1664,7 @@ public: grabInformationObjects(); synchroniseStates(); interconnectComponentAndController(); + syncProgramNames(); setupIO(); return true; } @@ -1951,16 +1953,22 @@ public: } //============================================================================== - int getNumPrograms() override { return getProgramListInfo (0).programCount; } - int getCurrentProgram() override { return 0; } - void setCurrentProgram (int) override {} + int getNumPrograms() override { return programNames.size(); } + const String getProgramName (int index) override { return programNames[index]; } + int getCurrentProgram() override { return jmax (0, (int) editController->getParamNormalized (programParameterID) * (programNames.size() - 1)); } void changeProgramName (int, const String&) override {} - const String getProgramName (int index) override + void setCurrentProgram (int program) override { - Vst::String128 result; - unitInfo->getProgramName (getProgramListInfo (0).id, index, result); - return toString (result); + if (programNames.size() > 0 && editController != nullptr) + { + Vst::ParamValue value = + static_cast (program) / static_cast (programNames.size()); + + editController->setParamNormalized (programParameterID, value); + Steinberg::int32 index; + inputParameterChanges->addParameterData (programParameterID, index)->addPoint (0, value, index); + } } //============================================================================== @@ -2167,6 +2175,9 @@ private: VST3FloatAndDoubleBusMapComposite inputBusMap, outputBusMap; Array inputBusses, outputBusses; + StringArray programNames; + Vst::ParamID programParameterID; + //============================================================================== template static void appendStateFrom (XmlElement& head, ComSmartPtr& object, const String& identifier) @@ -2453,6 +2464,82 @@ private: return paramInfo; } + void syncProgramNames () + { + programNames.clear(); + + if (processor == nullptr || editController == nullptr) + return; + + Vst::UnitID programUnitID; + int stepCount; + Vst::ParameterInfo paramInfo = { 0 }; + + { + int idx, num = editController->getParameterCount(); + for (idx = 0; idx < num; ++idx) + if (editController->getParameterInfo (idx, paramInfo) == kResultOk + && (paramInfo.flags & Steinberg::Vst::ParameterInfo::kIsProgramChange) != 0) + break; + + if (idx >= num) return; + + programParameterID = paramInfo.id; + programUnitID = paramInfo.unitId; + stepCount = paramInfo.stepCount; + } + + if (unitInfo != nullptr) + { + Vst::UnitInfo info = { 0 }; + const int unitCount = unitInfo->getUnitCount(); + + for (int idx = 0; idx < unitCount; ++idx) + { + if (unitInfo->getUnitInfo(idx, info) == kResultOk + && info.id == programUnitID) + { + const int programListCount = unitInfo->getProgramListCount(); + + for (int j = 0; j < programListCount; ++j) + { + Vst::ProgramListInfo programListInfo = { 0 }; + + if (unitInfo->getProgramListInfo (j, programListInfo) == kResultOk + && programListInfo.id == info.programListId) + { + Vst::String128 name; + + for (int k = 0; k < programListInfo.programCount; ++k) + if (unitInfo->getProgramName (programListInfo.id, k, name) == kResultOk) + programNames.add (toString (name)); + + return; + } + + break; + } + + break; + } + } + + } + + if (editController != nullptr + && paramInfo.stepCount > 0) + { + const int numPrograms = paramInfo.stepCount + 1; + for (int i = 0; i < numPrograms; ++i) + { + Vst::String128 programName; + Vst::ParamValue valueNormalized = static_cast (i) / static_cast (paramInfo.stepCount); + if (editController->getParamStringByValue (paramInfo.id, valueNormalized, programName) == kResultOk) + programNames.add (toString (programName)); + } + } + } + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VST3PluginInstance) };