Thereās no built in preset management in Tracktion Engine, you can deal with that however you like.
The only thing you need to do in the Engine is set the Pluginās state via the base class AutomatableEditItem::restorePluginStateFromValueTree (const juce::ValueTree&).
You get the current preset by just copying its state. You might need to call AutomatableEditItem::flushPluginStateToValueTree if its an ExternalPlugin or a subclass that doesnāt automatically update the state.
Yes this helped me.
Just one question :
Iāve an External parameter (VST3) and when i call plugin->flushPluginStateToValueTree(...) and save the plugin->state to a file ( file.preset ) and then i load this file and call plugin->restorePluginStateFromValueTree (ValueTree::fromXml(file.toXmlString()) all parameters is setted to 0.0.
Any hints for this problem ?
Sorry i did not write it.
When i load the file.preset i call presetVt.getChildWithName(āPLUGINā) and so to the plugin->restorePluginStateFromValueTree(...) i pass the PLUGIN vt and not the PRESET
Yes this part of code is covered , it gets the state and then call the setStateInformation via the callBlock(ā¦) method for each chunk.
it seems like that when i call the plugin->flushPluginStateToValueTree(...) the current aut param values are not stored or something like thatā¦
In the specific the plugin->flushPluginStateToValueTree(...) calls this method :
void AutomatableEditItem::saveChangedParametersToState()
{
juce::MemoryOutputStream stream;
for (auto ap : automatableParams)
{
if (ap->getCurrentValue() != ap->getCurrentExplicitValue())
{
stream.writeString (ap->paramID);
stream.writeFloat (ap->getCurrentExplicitValue());
}
}
stream.flush();
auto um = &edit.getUndoManager();
if (stream.getDataSize() > 0)
elementState.setProperty (IDs::parameters, stream.getMemoryBlock(), um);
else
elementState.removeProperty (IDs::parameters, um);
}
and this compairson if (ap->getCurrentValue() != ap->getCurrentExplicitValue()) is always false⦠maybe this could be the problem ?
After called the restorePluginStateFromValueTree(...) a strage thing happensā¦
When i call autParam->getCurrentValueAsString() it returns the correct value ( 7 Hz for example ) while calling autParam->getCurrentValue() it returns always 0⦠how does it possibile ?
The value passed in the currentValueChanged(AutomatableParameter&ap , flaot value ) is always 0.
I use this callback to set up sliders and other stuffsā¦
Can you step in to getCurrentValueAsString? Is it calling AutomatableParameter::getCurrentValueAsString or ExternalAutomatableParameter::getCurrentValueAsString?
Did you see my comment here?
I need to know the answer from this in order to advise further.
E.g. why does the call to setParameterValue not end up in your plugin setting the parameter to the same value as currentParameterValue? Are you doing some internal scaling or something?
Now the problem is that the value passed as a parameter turns out to be always 0 , as you can see from the picture , while the current value is correct
Then is sounds like pluginInstance.cachedParamValues.get (vstParamIndex); is incorrectly all 0s?
Shouldnāt they be the last values set during the set-state operation?
It sounds like the juce::VST3PluginInstance::VST3Parameter isnāt being updated at the correct time (i.e. when setStateInformation is called on the plugin instance?
Can you perhaps step through juce::VST3PluginInstance::setStateInformation and see why either resetParameters() isnāt being called or why the values are all 0 if it is being called?
Iām at ADC this week so canāt really look in to it myself Iām afraid.
The resetParameters() method is called and the value of the parameters is correct !
But then this method is called :
void refreshParameterList() override
{
AudioProcessorParameterGroup newParameterTree;
// We're going to add parameter groups to the tree recursively in the same order as the
// first parameters contained within them.
std::map<Vst::UnitID, Vst::UnitInfo> infoMap;
std::map<Vst::UnitID, AudioProcessorParameterGroup*> groupMap;
groupMap[Vst::kRootUnitId] = &newParameterTree;
if (unitInfo != nullptr)
{
const auto numUnits = unitInfo->getUnitCount();
for (int i = 1; i < numUnits; ++i)
{
Vst::UnitInfo ui{};
unitInfo->getUnitInfo (i, ui);
infoMap[ui.id] = std::move (ui);
}
}
{
auto allIds = getAllParamIDs (*editController);
inputParameterChanges ->initialise (allIds);
outputParameterChanges->initialise (allIds);
cachedParamValues = CachedParamValues { std::move (allIds) };
}
and here cachedParamValues = CachedParamValues { std::move (allIds) }; the cachedParamValues is setted to all zero and then these values are passed to the parameterChanged(ā¦) callback.
The parameter in the native plugin UI update correctly their values⦠but when the callback is called ( with wich i can update my sandBox ) they are always 0.
Iāve added even an async updater but the problem is still present.
I think this sounds like a JUCE bug then. I donāt think refreshParameterList() should be clearing the parameter values if they already exist. @reuk, is this new behaviour since the introduction of the VST3 parameter cache?
From reading the conversation, it sounds like weād expect something like this to work:
std::vector<float> values;
for (auto* param : processor->getParameters())
values.push_back (param->getValue());
processor->refreshParameterList();
for (auto* param : processor->getParameters())
jassert (param->getValue() == values[param->getParameterIndex()]);
Have I understood the problem?
If so, it looks like this did indeed work before CachedParamValues was added, so this seems to be a regression. (This might be a good Pluginval test!)
Having said that, I donāt really understand why refreshParameters() is implemented at all for VST3 plugins. The VST3 format disallows adding/removing parameters at runtime, so this only seems useful if the parameter unitIDs may change at runtime (i.e. the tree structure changes), but itās not clear to me whether this is allowed by the spec. Thereās no āunit IDs changedā flag in the VST3 RestartFlags, so I suspect this is not allowed.
@dave96 do you happen to know of any VST3 plug-ins for which refreshParameterList should actually change the parameter values/layout? If not, Iām leaning towards turning refreshParameterList into a no-op for VST3 plug-ins.
Yes, I think thatās the test case that should pass (and yes, would make a good addition to pluginval ).
I think we call refreshParameters as perhaps that was required for changed names (as can happen with macro parameters). If in the VST3 impl that happens without refreshing the params I think youāre right and it could be a no-op.