|
|
|
@@ -113,7 +113,7 @@ public: |
|
|
|
float getDenormalisedValue() const { return unnormalisedValue; }
|
|
|
|
float& getRawDenormalisedValue() { return unnormalisedValue; }
|
|
|
|
|
|
|
|
bool flushToTree (ValueTree tree, const Identifier& key, UndoManager* um)
|
|
|
|
bool flushToTree (const Identifier& key, UndoManager* um)
|
|
|
|
{
|
|
|
|
auto needsUpdateTestValue = true;
|
|
|
|
|
|
|
|
@@ -136,6 +136,8 @@ public: |
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueTree tree;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void parameterGestureChanged (int, bool) override {}
|
|
|
|
|
|
|
|
@@ -180,7 +182,7 @@ private: |
|
|
|
//==============================================================================
|
|
|
|
AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& processorToConnectTo,
|
|
|
|
UndoManager* undoManagerToUse,
|
|
|
|
const juce::Identifier& valueTreeType,
|
|
|
|
const Identifier& valueTreeType,
|
|
|
|
ParameterLayout parameterLayout)
|
|
|
|
: AudioProcessorValueTreeState (processorToConnectTo, undoManagerToUse)
|
|
|
|
{
|
|
|
|
@@ -197,7 +199,7 @@ AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& proc |
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
state->parameters.emplace_back (std::make_unique<ParameterAdapter> (*param));
|
|
|
|
state->addParameterAdapter (*param);
|
|
|
|
state->processor.addParameter (param.release());
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -213,7 +215,7 @@ AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& proc |
|
|
|
{
|
|
|
|
if (const auto rangedParam = dynamic_cast<RangedAudioParameter*> (param))
|
|
|
|
{
|
|
|
|
state->parameters.emplace_back (std::make_unique<ParameterAdapter> (*rangedParam));
|
|
|
|
state->addParameterAdapter (*rangedParam);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
@@ -280,18 +282,23 @@ RangedAudioParameter* AudioProcessorValueTreeState::createAndAddParameter (std:: |
|
|
|
if (getParameter (param->paramID) != nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
parameters.emplace_back (std::make_unique<ParameterAdapter> (*param));
|
|
|
|
addParameterAdapter (*param);
|
|
|
|
|
|
|
|
processor.addParameter (param.get());
|
|
|
|
|
|
|
|
return param.release();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
void AudioProcessorValueTreeState::addParameterAdapter (RangedAudioParameter& param)
|
|
|
|
{
|
|
|
|
adapterTable.emplace (param.paramID, std::make_unique<ParameterAdapter> (param));
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioProcessorValueTreeState::ParameterAdapter* AudioProcessorValueTreeState::getParameterAdapter (StringRef paramID) const
|
|
|
|
{
|
|
|
|
auto it = find_if (std::begin (parameters), std::end (parameters),
|
|
|
|
[&](const std::unique_ptr<ParameterAdapter>& p) { return p->getParameter().paramID == paramID; });
|
|
|
|
return it == std::end (parameters) ? nullptr : it->get();
|
|
|
|
auto it = adapterTable.find (paramID);
|
|
|
|
return it == adapterTable.end() ? nullptr : it->second.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::addParameterListener (StringRef paramID, Listener* listener)
|
|
|
|
@@ -308,10 +315,9 @@ void AudioProcessorValueTreeState::removeParameterListener (StringRef paramID, L |
|
|
|
|
|
|
|
Value AudioProcessorValueTreeState::getParameterAsValue (StringRef paramID) const
|
|
|
|
{
|
|
|
|
auto v = getChildValueTree (paramID);
|
|
|
|
|
|
|
|
if (v.isValid())
|
|
|
|
return v.getPropertyAsValue (valuePropertyID, undoManager);
|
|
|
|
if (auto* adapter = getParameterAdapter (paramID))
|
|
|
|
if (adapter->tree.isValid())
|
|
|
|
return adapter->tree.getPropertyAsValue (valuePropertyID, undoManager);
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
@@ -357,63 +363,56 @@ void AudioProcessorValueTreeState::replaceState (const ValueTree& newState) |
|
|
|
undoManager->clearUndoHistory();
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueTree AudioProcessorValueTreeState::getChildValueTree (const String& paramID) const
|
|
|
|
void AudioProcessorValueTreeState::setNewState (ValueTree vt)
|
|
|
|
{
|
|
|
|
return { state.getChildWithProperty (idPropertyID, paramID) };
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueTree AudioProcessorValueTreeState::getOrCreateChildValueTree (const String& paramID)
|
|
|
|
{
|
|
|
|
auto v = getChildValueTree (paramID);
|
|
|
|
jassert (vt.getParent() == state);
|
|
|
|
|
|
|
|
if (! v.isValid())
|
|
|
|
if (auto* p = getParameterAdapter (vt.getProperty (idPropertyID).toString()))
|
|
|
|
{
|
|
|
|
v = ValueTree (valueType);
|
|
|
|
v.setProperty (idPropertyID, paramID, nullptr);
|
|
|
|
state.appendChild (v, nullptr);
|
|
|
|
p->tree = vt;
|
|
|
|
p->setDenormalisedValue (p->tree.getProperty (valuePropertyID, p->getDenormalisedDefaultValue()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::setNewState (ParameterAdapter& p)
|
|
|
|
{
|
|
|
|
const auto tree = getOrCreateChildValueTree (p.getParameter().paramID);
|
|
|
|
p.setDenormalisedValue (tree.getProperty (valuePropertyID, p.getDenormalisedDefaultValue()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::updateParameterConnectionsToChildTrees()
|
|
|
|
{
|
|
|
|
ScopedLock lock (valueTreeChanging);
|
|
|
|
|
|
|
|
for (const auto& p : parameters)
|
|
|
|
setNewState (*p);
|
|
|
|
for (auto& p : adapterTable)
|
|
|
|
p.second->tree = ValueTree();
|
|
|
|
|
|
|
|
for (const auto& child : state)
|
|
|
|
setNewState (child);
|
|
|
|
|
|
|
|
for (auto& p : adapterTable)
|
|
|
|
{
|
|
|
|
auto& adapter = *p.second;
|
|
|
|
|
|
|
|
if (! adapter.tree.isValid())
|
|
|
|
{
|
|
|
|
adapter.tree = ValueTree (valueType);
|
|
|
|
adapter.tree.setProperty (idPropertyID, adapter.getParameter().paramID, nullptr);
|
|
|
|
state.appendChild (adapter.tree, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::valueTreePropertyChanged (ValueTree& tree, const Identifier& property)
|
|
|
|
void AudioProcessorValueTreeState::valueTreePropertyChanged (ValueTree& tree, const Identifier&)
|
|
|
|
{
|
|
|
|
if (! (tree.hasType (valueType) && tree.getParent() == state))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (property == idPropertyID)
|
|
|
|
updateParameterConnectionsToChildTrees();
|
|
|
|
else if (property == valuePropertyID)
|
|
|
|
if (auto adapter = getParameterAdapter (tree.getProperty (idPropertyID).toString()))
|
|
|
|
adapter->setDenormalisedValue (tree.getProperty (valuePropertyID));
|
|
|
|
if (tree.hasType (valueType) && tree.getParent() == state)
|
|
|
|
setNewState (tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::valueTreeChildAdded (ValueTree& parent, ValueTree& tree)
|
|
|
|
{
|
|
|
|
if (parent == state && tree.hasType (valueType))
|
|
|
|
if (auto* param = getParameterAdapter (tree.getProperty (idPropertyID).toString()))
|
|
|
|
setNewState (*param);
|
|
|
|
setNewState (tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::valueTreeChildRemoved (ValueTree& parent, ValueTree& tree, int)
|
|
|
|
{
|
|
|
|
if (parent == state && tree.hasType (valueType))
|
|
|
|
if (auto* param = getParameterAdapter (tree.getProperty (idPropertyID).toString()))
|
|
|
|
setNewState (*param);
|
|
|
|
setNewState (tree);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioProcessorValueTreeState::valueTreeRedirected (ValueTree& v)
|
|
|
|
@@ -431,10 +430,8 @@ bool AudioProcessorValueTreeState::flushParameterValuesToValueTree() |
|
|
|
|
|
|
|
bool anyUpdated = false;
|
|
|
|
|
|
|
|
for (auto& p : parameters)
|
|
|
|
anyUpdated |= p->flushToTree (getChildValueTree (p->getParameter().paramID),
|
|
|
|
valuePropertyID,
|
|
|
|
undoManager);
|
|
|
|
for (auto& p : adapterTable)
|
|
|
|
anyUpdated |= p.second->flushToTree (valuePropertyID, undoManager);
|
|
|
|
|
|
|
|
return anyUpdated;
|
|
|
|
}
|
|
|
|
@@ -792,7 +789,7 @@ static struct ParameterAdapterTests final : public UnitTest |
|
|
|
|
|
|
|
beginTest ("Floats can be converted to text");
|
|
|
|
{
|
|
|
|
const auto test = [&](NormalisableRange<float> range, float value, juce::String expected)
|
|
|
|
const auto test = [&](NormalisableRange<float> range, float value, String expected)
|
|
|
|
{
|
|
|
|
AudioParameterFloat param ({}, {}, range, {}, {});
|
|
|
|
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
|
|
|
|
@@ -808,7 +805,7 @@ static struct ParameterAdapterTests final : public UnitTest |
|
|
|
|
|
|
|
beginTest ("Text can be converted to floats");
|
|
|
|
{
|
|
|
|
const auto test = [&](NormalisableRange<float> range, juce::String text, float expected)
|
|
|
|
const auto test = [&](NormalisableRange<float> range, String text, float expected)
|
|
|
|
{
|
|
|
|
AudioParameterFloat param ({}, {}, range, {}, {});
|
|
|
|
AudioProcessorValueTreeState::ParameterAdapter adapter (param);
|
|
|
|
@@ -1044,7 +1041,7 @@ public: |
|
|
|
key,
|
|
|
|
String(),
|
|
|
|
String(),
|
|
|
|
juce::NormalisableRange<float> (0.0f, 100.0f, 10.0f),
|
|
|
|
NormalisableRange<float> (0.0f, 100.0f, 10.0f),
|
|
|
|
value,
|
|
|
|
nullptr,
|
|
|
|
nullptr));
|
|
|
|
|