|
|
|
@@ -284,13 +284,13 @@ private: |
|
|
|
class JuceAudioProcessor : public Vst::IUnitInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
JuceAudioProcessor (AudioProcessor* source) noexcept
|
|
|
|
: audioProcessor (source)
|
|
|
|
explicit JuceAudioProcessor (AudioProcessor* source) noexcept
|
|
|
|
: audioProcessor (source)
|
|
|
|
{
|
|
|
|
setupParameters();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~JuceAudioProcessor() {}
|
|
|
|
virtual ~JuceAudioProcessor() = default;
|
|
|
|
|
|
|
|
AudioProcessor* get() const noexcept { return audioProcessor.get(); }
|
|
|
|
|
|
|
|
@@ -432,14 +432,29 @@ public: |
|
|
|
return unitID;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getNumParameters() const noexcept { return vstParamIDs.size(); }
|
|
|
|
const Array<Vst::ParamID>& getParamIDs() const noexcept { return vstParamIDs; }
|
|
|
|
Vst::ParamID getBypassParamID() const noexcept { return bypassParamID; }
|
|
|
|
Vst::ParamID getProgramParamID() const noexcept { return programParamID; }
|
|
|
|
bool isBypassRegularParameter() const noexcept { return bypassIsRegularParameter; }
|
|
|
|
|
|
|
|
void setParameterValue (size_t paramIndex, float value)
|
|
|
|
{
|
|
|
|
cachedParamValues.set (paramIndex, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Callback>
|
|
|
|
void forAllChangedParameters (Callback&& callback)
|
|
|
|
{
|
|
|
|
cachedParamValues.ifSet ([&] (size_t index, float value)
|
|
|
|
{
|
|
|
|
callback (cachedParamValues.getParamID (index), value);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isUsingManagedParameters() const noexcept { return juceParameters.isUsingManagedParameters(); }
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
static const FUID iid;
|
|
|
|
Array<Vst::ParamID> vstParamIDs;
|
|
|
|
Vst::ParamID bypassParamID = 0, programParamID = static_cast<Vst::ParamID> (paramPreset);
|
|
|
|
bool bypassIsRegularParameter = false;
|
|
|
|
|
|
|
|
private:
|
|
|
|
//==============================================================================
|
|
|
|
@@ -537,6 +552,8 @@ private: |
|
|
|
vstParamIDs.add (programParamID);
|
|
|
|
paramMap.set (static_cast<int32> (programParamID), ownedProgramParameter.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
cachedParamValues = CachedParamValues { { vstParamIDs.begin(), vstParamIDs.end() } };
|
|
|
|
}
|
|
|
|
|
|
|
|
Vst::ParamID generateVSTParamIDForParam (AudioProcessorParameter* param)
|
|
|
|
@@ -557,6 +574,12 @@ private: |
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
Array<Vst::ParamID> vstParamIDs;
|
|
|
|
CachedParamValues cachedParamValues;
|
|
|
|
Vst::ParamID bypassParamID = 0, programParamID = static_cast<Vst::ParamID> (paramPreset);
|
|
|
|
bool bypassIsRegularParameter = false;
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
std::atomic<int> refCount { 0 };
|
|
|
|
std::unique_ptr<AudioProcessor> audioProcessor;
|
|
|
|
@@ -891,12 +914,12 @@ public: |
|
|
|
|
|
|
|
if (auto* pluginInstance = getPluginInstance())
|
|
|
|
{
|
|
|
|
for (auto vstParamId : audioProcessor->vstParamIDs)
|
|
|
|
for (auto vstParamId : audioProcessor->getParamIDs())
|
|
|
|
{
|
|
|
|
auto paramValue = [&]
|
|
|
|
{
|
|
|
|
if (vstParamId == audioProcessor->programParamID)
|
|
|
|
return EditController::plainParamToNormalized (audioProcessor->programParamID,
|
|
|
|
if (vstParamId == audioProcessor->getProgramParamID())
|
|
|
|
return EditController::plainParamToNormalized (audioProcessor->getProgramParamID(),
|
|
|
|
pluginInstance->getCurrentProgram());
|
|
|
|
|
|
|
|
return (double) audioProcessor->getParamForVSTParamID (vstParamId)->getValue();
|
|
|
|
@@ -1124,23 +1147,49 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void paramChanged (Vst::ParamID vstParamId, double newValue)
|
|
|
|
void beginGesture (Vst::ParamID vstParamId)
|
|
|
|
{
|
|
|
|
if (MessageManager::getInstance()->isThisTheMessageThread())
|
|
|
|
beginEdit (vstParamId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void endGesture (Vst::ParamID vstParamId)
|
|
|
|
{
|
|
|
|
if (MessageManager::getInstance()->isThisTheMessageThread())
|
|
|
|
endEdit (vstParamId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void paramChanged (int parameterIndex, Vst::ParamID vstParamId, double newValue)
|
|
|
|
{
|
|
|
|
if (inParameterChangedCallback.get())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// NB: Cubase has problems if performEdit is called without setParamNormalized
|
|
|
|
EditController::setParamNormalized (vstParamId, newValue);
|
|
|
|
performEdit (vstParamId, newValue);
|
|
|
|
if (MessageManager::getInstance()->isThisTheMessageThread())
|
|
|
|
{
|
|
|
|
// NB: Cubase has problems if performEdit is called without setParamNormalized
|
|
|
|
EditController::setParamNormalized (vstParamId, newValue);
|
|
|
|
performEdit (vstParamId, newValue);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
audioProcessor->setParameterValue ((size_t) parameterIndex, (float) newValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override { beginEdit (audioProcessor->getVSTParamIDForIndex (index)); }
|
|
|
|
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override { endEdit (audioProcessor->getVSTParamIDForIndex (index)); }
|
|
|
|
void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int index) override
|
|
|
|
{
|
|
|
|
beginGesture (audioProcessor->getVSTParamIDForIndex (index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int index) override
|
|
|
|
{
|
|
|
|
endGesture (audioProcessor->getVSTParamIDForIndex (index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue) override
|
|
|
|
{
|
|
|
|
paramChanged (audioProcessor->getVSTParamIDForIndex (index), newValue);
|
|
|
|
paramChanged (index, audioProcessor->getVSTParamIDForIndex (index), newValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void audioProcessorChanged (AudioProcessor*, const ChangeDetails& details) override
|
|
|
|
@@ -1157,20 +1206,26 @@ public: |
|
|
|
|
|
|
|
if (auto* pluginInstance = getPluginInstance())
|
|
|
|
{
|
|
|
|
if (details.programChanged && audioProcessor->getProgramParameter() != nullptr)
|
|
|
|
if (details.programChanged)
|
|
|
|
{
|
|
|
|
auto currentProgram = pluginInstance->getCurrentProgram();
|
|
|
|
auto paramValue = roundToInt (EditController::normalizedParamToPlain (audioProcessor->programParamID,
|
|
|
|
EditController::getParamNormalized (audioProcessor->programParamID)));
|
|
|
|
|
|
|
|
if (currentProgram != paramValue)
|
|
|
|
if (auto* programParameter = audioProcessor->getProgramParameter())
|
|
|
|
{
|
|
|
|
beginEdit (audioProcessor->programParamID);
|
|
|
|
paramChanged (audioProcessor->programParamID,
|
|
|
|
EditController::plainParamToNormalized (audioProcessor->programParamID, currentProgram));
|
|
|
|
endEdit (audioProcessor->programParamID);
|
|
|
|
const auto programParameterIndex = programParameter->getParameterIndex();
|
|
|
|
const auto programParameterId = audioProcessor->getProgramParamID();
|
|
|
|
const auto currentProgram = pluginInstance->getCurrentProgram();
|
|
|
|
const auto paramValue = roundToInt (EditController::normalizedParamToPlain (programParameterId,
|
|
|
|
EditController::getParamNormalized (programParameterId)));
|
|
|
|
|
|
|
|
flags |= Vst::kParamValuesChanged;
|
|
|
|
if (currentProgram != paramValue)
|
|
|
|
{
|
|
|
|
beginGesture (programParameterId);
|
|
|
|
paramChanged (programParameterIndex,
|
|
|
|
programParameterId,
|
|
|
|
EditController::plainParamToNormalized (programParameterId, currentProgram));
|
|
|
|
endGesture (programParameterId);
|
|
|
|
|
|
|
|
flags |= Vst::kParamValuesChanged;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1200,6 +1255,7 @@ private: |
|
|
|
friend class JuceVST3Component;
|
|
|
|
friend struct Param;
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
class ComponentRestarter : private AsyncUpdater
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
@@ -1218,7 +1274,7 @@ private: |
|
|
|
|
|
|
|
flags = newFlags;
|
|
|
|
|
|
|
|
if (Thread::getCurrentThreadId() == messageThreadId)
|
|
|
|
if (MessageManager::getInstance()->isThisTheMessageThread())
|
|
|
|
handleAsyncUpdate();
|
|
|
|
else
|
|
|
|
triggerAsyncUpdate();
|
|
|
|
@@ -1231,7 +1287,6 @@ private: |
|
|
|
handler->restartComponent (flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Thread::ThreadID messageThreadId = MessageManager::getInstance()->getCurrentMessageThread();
|
|
|
|
JuceVST3EditController& controller;
|
|
|
|
int32 flags = 0;
|
|
|
|
};
|
|
|
|
@@ -1263,17 +1318,17 @@ private: |
|
|
|
juceParameter.addListener (this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void parameterValueChanged (int, float newValue) override
|
|
|
|
void parameterValueChanged (int index, float newValue) override
|
|
|
|
{
|
|
|
|
owner.paramChanged (vstParamID, newValue);
|
|
|
|
owner.paramChanged (index, vstParamID, newValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void parameterGestureChanged (int, bool gestureIsStarting) override
|
|
|
|
{
|
|
|
|
if (gestureIsStarting)
|
|
|
|
owner.beginEdit (vstParamID);
|
|
|
|
owner.beginGesture (vstParamID);
|
|
|
|
else
|
|
|
|
owner.endEdit (vstParamID);
|
|
|
|
owner.endGesture (vstParamID);
|
|
|
|
}
|
|
|
|
|
|
|
|
JuceVST3EditController& owner;
|
|
|
|
@@ -1299,20 +1354,20 @@ private: |
|
|
|
pluginInstance->addListener (this);
|
|
|
|
|
|
|
|
// as the bypass is not part of the regular parameters we need to listen for it explicitly
|
|
|
|
if (! audioProcessor->bypassIsRegularParameter)
|
|
|
|
if (! audioProcessor->isBypassRegularParameter())
|
|
|
|
ownedParameterListeners.push_back (std::make_unique<OwnedParameterListener> (*this,
|
|
|
|
*audioProcessor->getBypassParameter(),
|
|
|
|
audioProcessor->bypassParamID));
|
|
|
|
audioProcessor->getBypassParamID()));
|
|
|
|
|
|
|
|
if (parameters.getParameterCount() <= 0)
|
|
|
|
{
|
|
|
|
auto n = audioProcessor->getNumParameters();
|
|
|
|
auto n = audioProcessor->getParamIDs().size();
|
|
|
|
|
|
|
|
for (int i = 0; i < n; ++i)
|
|
|
|
{
|
|
|
|
auto vstParamID = audioProcessor->getVSTParamIDForIndex (i);
|
|
|
|
|
|
|
|
if (vstParamID == audioProcessor->programParamID)
|
|
|
|
if (vstParamID == audioProcessor->getProgramParamID())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
auto* juceParam = audioProcessor->getParamForVSTParamID (vstParamID);
|
|
|
|
@@ -1320,16 +1375,16 @@ private: |
|
|
|
auto unitID = JuceAudioProcessor::getUnitID (parameterGroup);
|
|
|
|
|
|
|
|
parameters.addParameter (new Param (*this, *juceParam, vstParamID, unitID,
|
|
|
|
(vstParamID == audioProcessor->bypassParamID)));
|
|
|
|
(vstParamID == audioProcessor->getBypassParamID())));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto* programParam = audioProcessor->getProgramParameter())
|
|
|
|
{
|
|
|
|
ownedParameterListeners.push_back (std::make_unique<OwnedParameterListener> (*this,
|
|
|
|
*programParam,
|
|
|
|
audioProcessor->programParamID));
|
|
|
|
audioProcessor->getProgramParamID()));
|
|
|
|
|
|
|
|
parameters.addParameter (new ProgramChangeParameter (*pluginInstance, audioProcessor->programParamID));
|
|
|
|
parameters.addParameter (new ProgramChangeParameter (*pluginInstance, audioProcessor->getProgramParamID()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -3133,6 +3188,20 @@ private: |
|
|
|
jassert (midiBuffer.getNumEvents() <= numMidiEventsComingIn);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto* changes = data.outputParameterChanges)
|
|
|
|
{
|
|
|
|
comPluginInstance->forAllChangedParameters ([&] (Vst::ParamID paramID, float value)
|
|
|
|
{
|
|
|
|
Steinberg::int32 queueIndex = 0;
|
|
|
|
|
|
|
|
if (auto* queue = changes->addParameterData (paramID, queueIndex))
|
|
|
|
{
|
|
|
|
Steinberg::int32 pointIndex = 0;
|
|
|
|
queue->addPoint (0, value, pointIndex);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|