fix macOS build (following Projucer changes made in Windows, which removed /Applications/JUCE/modules from its headers). move JUCE headers under source control, so that Windows and macOS can both build against same version of JUCE. remove AUv3 target (I think it's an iOS thing, so it will never work with this macOS fluidsynth dylib).

This commit is contained in:
Alex Birch
2018-06-17 13:34:53 +01:00
parent a2be47c887
commit dff4d13a1d
1563 changed files with 601601 additions and 3466 deletions

View File

@ -0,0 +1,94 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Provides a class of AudioProcessorParameter that can be used as a boolean value.
@see AudioParameterFloat, AudioParameterInt, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioParameterBool : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterBool with the specified parameters.
@param parameterID The parameter ID to use
@param name The parameter name to use
@param defaultValue The default value
@param label An optional label for the parameter's value
@param stringFromBool An optional lambda function that converts a bool
value to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param boolFromString An optional lambda function that parses a string and
converts it into a bool value. Some hosts use this
to allow users to type in parameter values.
*/
AudioParameterBool (const String& parameterID, const String& name, bool defaultValue,
const String& label = String(),
std::function<String (bool value, int maximumStringLength)> stringFromBool = nullptr,
std::function<bool (const String& text)> boolFromString = nullptr);
/** Destructor. */
~AudioParameterBool();
/** Returns the parameter's current boolean value. */
bool get() const noexcept { return value >= 0.5f; }
/** Returns the parameter's current boolean value. */
operator bool() const noexcept { return get(); }
/** Changes the parameter's current value to a new boolean. */
AudioParameterBool& operator= (bool newValue);
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (bool newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
bool isDiscrete() const override;
bool isBoolean() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
float value;
const float defaultValue;
std::function<String (bool, int)> stringFromBoolFunction;
std::function<bool (const String&)> boolFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterBool)
};
} // namespace juce

View File

@ -0,0 +1,110 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Provides a class of AudioProcessorParameter that can be used to select
an indexed, named choice from a list.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool
@tags{Audio}
*/
class JUCE_API AudioParameterChoice : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterChoice with the specified parameters.
@param parameterID The parameter ID to use
@param name The parameter name to use
@param choices The set of choices to use
@param defaultItemIndex The index of the default choice
@param label An optional label for the parameter's value
@param stringFromIndex An optional lambda function that converts a choice
index to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param indexFromString An optional lambda function that parses a string and
converts it into a choice index. Some hosts use this
to allow users to type in parameter values.
*/
AudioParameterChoice (const String& parameterID, const String& name,
const StringArray& choices,
int defaultItemIndex,
const String& label = String(),
std::function<String (int index, int maximumStringLength)> stringFromIndex = nullptr,
std::function<int (const String& text)> indexFromString = nullptr);
/** Destructor. */
~AudioParameterChoice();
/** Returns the current index of the selected item. */
int getIndex() const noexcept { return roundToInt (value); }
/** Returns the current index of the selected item. */
operator int() const noexcept { return getIndex(); }
/** Returns the name of the currently selected item. */
String getCurrentChoiceName() const noexcept { return choices[getIndex()]; }
/** Returns the name of the currently selected item. */
operator String() const noexcept { return getCurrentChoiceName(); }
/** Changes the selected item to a new index. */
AudioParameterChoice& operator= (int newValue);
/** Provides access to the list of choices that this parameter is working with. */
const StringArray choices;
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (int newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
bool isDiscrete() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
int limitRange (int) const noexcept;
float convertTo0to1 (int) const noexcept;
int convertFrom0to1 (float) const noexcept;
float value;
const int maxIndex;
const float defaultValue;
std::function<String (int, int)> stringFromIndexFunction;
std::function<int (const String&)> indexFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterChoice)
};
} // namespace juce

View File

@ -0,0 +1,111 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
A subclass of AudioProcessorParameter that provides an easy way to create a
parameter which maps onto a given NormalisableRange.
@see AudioParameterInt, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioParameterFloat : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterFloat with the specified parameters.
@param parameterID The parameter ID to use
@param name The parameter name to use
@param normalisableRange The NormalisableRange to use
@param defaultValue The non-normalised default value
@param label An optional label for the parameter's value
@param category An optional parameter category
@param stringFromValue An optional lambda function that converts a non-normalised
value to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param valueFromString An optional lambda function that parses a string and
converts it into a non-normalised value. Some hosts use
this to allow users to type in parameter values.
*/
AudioParameterFloat (const String& parameterID, const String& name,
NormalisableRange<float> normalisableRange,
float defaultValue,
const String& label = String(),
Category category = AudioProcessorParameter::genericParameter,
std::function<String (float value, int maximumStringLength)> stringFromValue = nullptr,
std::function<float (const String& text)> valueFromString = nullptr);
/** Creates a AudioParameterFloat with an ID, name, and range.
On creation, its value is set to the default value.
For control over skew factors, you can use the other
constructor and provide a NormalisableRange.
*/
AudioParameterFloat (String parameterID, String name,
float minValue,
float maxValue,
float defaultValue);
/** Destructor. */
~AudioParameterFloat();
/** Returns the parameter's current value. */
float get() const noexcept { return value; }
/** Returns the parameter's current value. */
operator float() const noexcept { return value; }
/** Changes the parameter's current value. */
AudioParameterFloat& operator= (float newValue);
/** Provides access to the parameter's range. */
NormalisableRange<float> range;
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (float newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
float value;
const float defaultValue;
std::function<String (float, int)> stringFromValueFunction;
std::function<float (const String&)> valueFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterFloat)
};
} // namespace juce

View File

@ -0,0 +1,107 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
Provides a class of AudioProcessorParameter that can be used as an
integer value with a given range.
@see AudioParameterFloat, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioParameterInt : public AudioProcessorParameterWithID
{
public:
/** Creates a AudioParameterInt with the specified parameters.
@param parameterID The parameter ID to use
@param name The parameter name to use
@param minValue The minimum parameter value
@param maxValue The maximum parameter value
@param defaultValue The default value
@param label An optional label for the parameter's value
@param stringFromInt An optional lambda function that converts a int
value to a string with a maximum length. This may
be used by hosts to display the parameter's value.
@param intFromString An optional lambda function that parses a string
and converts it into an int. Some hosts use this
to allow users to type in parameter values.
*/
AudioParameterInt (const String& parameterID, const String& name,
int minValue, int maxValue,
int defaultValue,
const String& label = String(),
std::function<String (int value, int maximumStringLength)> stringFromInt = nullptr,
std::function<int (const String& text)> intFromString = nullptr);
/** Destructor. */
~AudioParameterInt();
/** Returns the parameter's current value as an integer. */
int get() const noexcept { return roundToInt (value); }
/** Returns the parameter's current value as an integer. */
operator int() const noexcept { return get(); }
/** Changes the parameter's current value to a new integer.
The value passed in will be snapped to the permitted range before being used.
*/
AudioParameterInt& operator= (int newValue);
/** Returns the parameter's range. */
Range<int> getRange() const noexcept { return Range<int> (minValue, maxValue); }
protected:
/** Override this method if you are interested in receiving callbacks
when the parameter value changes.
*/
virtual void valueChanged (int newValue);
private:
//==============================================================================
float getValue() const override;
void setValue (float newValue) override;
float getDefaultValue() const override;
int getNumSteps() const override;
String getText (float, int) const override;
float getValueForText (const String&) const override;
int limitRange (int) const noexcept;
float convertTo0to1 (int) const noexcept;
int convertFrom0to1 (float) const noexcept;
const int minValue, maxValue, rangeOfValues;
float value;
const float defaultValue;
std::function<String (int, int)> stringFromIntFunction;
std::function<int (const String&)> intFromStringFunction;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterInt)
};
} // namespace juce

View File

@ -0,0 +1,71 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
This abstract base class is used by some AudioProcessorParameter helper classes.
@see AudioParameterFloat, AudioParameterInt, AudioParameterBool, AudioParameterChoice
@tags{Audio}
*/
class JUCE_API AudioProcessorParameterWithID : public AudioProcessorParameter
{
public:
/** Creation of this object requires providing a name and ID which will be
constant for its lifetime.
*/
AudioProcessorParameterWithID (const String& parameterID,
const String& name,
const String& label = String(),
Category category = AudioProcessorParameter::genericParameter);
/** Destructor. */
~AudioProcessorParameterWithID();
/** Provides access to the parameter's ID string. */
const String paramID;
/** Provides access to the parameter's name. */
const String name;
/** Provides access to the parameter's label. */
const String label;
/** Provides access to the parameter's category. */
const Category category;
private:
String getName (int) const override;
String getLabel() const override;
Category getCategory() const override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameterWithID)
};
} // namespace juce

View File

@ -0,0 +1,251 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
// This file contains the implementations of the various AudioParameter[XYZ] classes..
AudioProcessorParameterWithID::AudioProcessorParameterWithID (const String& idToUse,
const String& nameToUse,
const String& labelToUse,
AudioProcessorParameter::Category categoryToUse)
: paramID (idToUse), name (nameToUse), label (labelToUse), category (categoryToUse) {}
AudioProcessorParameterWithID::~AudioProcessorParameterWithID() {}
String AudioProcessorParameterWithID::getName (int maximumStringLength) const { return name.substring (0, maximumStringLength); }
String AudioProcessorParameterWithID::getLabel() const { return label; }
AudioProcessorParameter::Category AudioProcessorParameterWithID::getCategory() const { return category; }
//==============================================================================
AudioParameterFloat::AudioParameterFloat (const String& idToUse, const String& nameToUse,
NormalisableRange<float> r, float def,
const String& labelToUse, Category categoryToUse,
std::function<String (float, int)> stringFromValue,
std::function<float (const String&)> valueFromString)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse, categoryToUse),
range (r), value (def), defaultValue (def),
stringFromValueFunction (stringFromValue),
valueFromStringFunction (valueFromString)
{
if (stringFromValueFunction == nullptr)
stringFromValueFunction = [] (float v, int length)
{
String asText (v, 2);
return length > 0 ? asText.substring (0, length) : asText;
};
if (valueFromStringFunction == nullptr)
valueFromStringFunction = [] (const String& text) { return text.getFloatValue(); };
}
AudioParameterFloat::AudioParameterFloat (String pid, String nm, float minValue, float maxValue, float def)
: AudioParameterFloat (pid, nm, { minValue, maxValue }, def)
{
}
AudioParameterFloat::~AudioParameterFloat() {}
float AudioParameterFloat::getValue() const { return range.convertTo0to1 (value); }
void AudioParameterFloat::setValue (float newValue) { value = range.convertFrom0to1 (newValue); valueChanged (get()); }
float AudioParameterFloat::getDefaultValue() const { return range.convertTo0to1 (defaultValue); }
int AudioParameterFloat::getNumSteps() const { return AudioProcessorParameterWithID::getNumSteps(); }
String AudioParameterFloat::getText (float v, int length) const { return stringFromValueFunction (range.convertFrom0to1 (v), length); }
float AudioParameterFloat::getValueForText (const String& text) const { return range.convertTo0to1 (valueFromStringFunction (text)); }
void AudioParameterFloat::valueChanged (float) {}
AudioParameterFloat& AudioParameterFloat::operator= (float newValue)
{
if (value != newValue)
setValueNotifyingHost (range.convertTo0to1 (newValue));
return *this;
}
//==============================================================================
AudioParameterInt::AudioParameterInt (const String& idToUse, const String& nameToUse,
int mn, int mx, int def,
const String& labelToUse,
std::function<String (int, int)> stringFromInt,
std::function<int (const String&)> intFromString)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse),
minValue (mn), maxValue (mx), rangeOfValues (maxValue - minValue),
value ((float) def),
defaultValue (convertTo0to1 (def)),
stringFromIntFunction (stringFromInt),
intFromStringFunction (intFromString)
{
jassert (minValue < maxValue); // must have a non-zero range of values!
if (stringFromIntFunction == nullptr)
stringFromIntFunction = [] (int v, int) { return String (v); };
if (intFromStringFunction == nullptr)
intFromStringFunction = [] (const String& text) { return text.getIntValue(); };
}
AudioParameterInt::~AudioParameterInt() {}
int AudioParameterInt::limitRange (int v) const noexcept { return jlimit (minValue, maxValue, v); }
float AudioParameterInt::convertTo0to1 (int v) const noexcept { return (limitRange (v) - minValue) / (float) rangeOfValues; }
int AudioParameterInt::convertFrom0to1 (float v) const noexcept { return limitRange (roundToInt ((v * (float) rangeOfValues) + minValue)); }
float AudioParameterInt::getValue() const { return convertTo0to1 (roundToInt (value)); }
void AudioParameterInt::setValue (float newValue) { value = (float) convertFrom0to1 (newValue); valueChanged (get()); }
float AudioParameterInt::getDefaultValue() const { return defaultValue; }
int AudioParameterInt::getNumSteps() const { return rangeOfValues + 1; }
float AudioParameterInt::getValueForText (const String& text) const { return convertTo0to1 (intFromStringFunction (text)); }
String AudioParameterInt::getText (float v, int length) const { return stringFromIntFunction (convertFrom0to1 (v), length); }
void AudioParameterInt::valueChanged (int) {}
AudioParameterInt& AudioParameterInt::operator= (int newValue)
{
if (get() != newValue)
setValueNotifyingHost (convertTo0to1 (newValue));
return *this;
}
//==============================================================================
AudioParameterBool::AudioParameterBool (const String& idToUse, const String& nameToUse,
bool def, const String& labelToUse,
std::function<String (bool, int)> stringFromBool,
std::function<bool (const String&)> boolFromString)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse),
value (def ? 1.0f : 0.0f),
defaultValue (value),
stringFromBoolFunction (stringFromBool),
boolFromStringFunction (boolFromString)
{
if (stringFromBoolFunction == nullptr)
stringFromBoolFunction = [] (bool v, int) { return v ? TRANS("On") : TRANS("Off"); };
if (boolFromStringFunction == nullptr)
{
StringArray onStrings;
onStrings.add (TRANS("on"));
onStrings.add (TRANS("yes"));
onStrings.add (TRANS("true"));
StringArray offStrings;
offStrings.add (TRANS("off"));
offStrings.add (TRANS("no"));
offStrings.add (TRANS("false"));
boolFromStringFunction = [onStrings, offStrings] (const String& text)
{
String lowercaseText (text.toLowerCase());
for (auto& testText : onStrings)
if (lowercaseText == testText)
return true;
for (auto& testText : offStrings)
if (lowercaseText == testText)
return false;
return text.getIntValue() != 0;
};
}
}
AudioParameterBool::~AudioParameterBool() {}
float AudioParameterBool::getValue() const { return value; }
void AudioParameterBool::setValue (float newValue) { value = newValue; valueChanged (get()); }
float AudioParameterBool::getDefaultValue() const { return defaultValue; }
int AudioParameterBool::getNumSteps() const { return 2; }
bool AudioParameterBool::isDiscrete() const { return true; }
bool AudioParameterBool::isBoolean() const { return true; }
void AudioParameterBool::valueChanged (bool) {}
float AudioParameterBool::getValueForText (const String& text) const
{
return boolFromStringFunction (text) ? 1.0f : 0.0f;
}
String AudioParameterBool::getText (float v, int maximumLength) const
{
return stringFromBoolFunction (v >= 0.5f, maximumLength);
}
AudioParameterBool& AudioParameterBool::operator= (bool newValue)
{
if (get() != newValue)
setValueNotifyingHost (newValue ? 1.0f : 0.0f);
return *this;
}
//==============================================================================
AudioParameterChoice::AudioParameterChoice (const String& idToUse, const String& nameToUse,
const StringArray& c, int def, const String& labelToUse,
std::function<String (int, int)> stringFromIndex,
std::function<int (const String&)> indexFromString)
: AudioProcessorParameterWithID (idToUse, nameToUse, labelToUse), choices (c),
value ((float) def),
maxIndex (choices.size() - 1),
defaultValue (convertTo0to1 (def)),
stringFromIndexFunction (stringFromIndex),
indexFromStringFunction (indexFromString)
{
jassert (choices.size() > 0); // you must supply an actual set of items to choose from!
if (stringFromIndexFunction == nullptr)
stringFromIndexFunction = [this] (int index, int) { return choices [index]; };
if (indexFromStringFunction == nullptr)
indexFromStringFunction = [this] (const String& text) { return choices.indexOf (text); };
}
AudioParameterChoice::~AudioParameterChoice() {}
int AudioParameterChoice::limitRange (int v) const noexcept { return jlimit (0, maxIndex, v); }
float AudioParameterChoice::convertTo0to1 (int v) const noexcept { return jlimit (0.0f, 1.0f, v / (float) maxIndex); }
int AudioParameterChoice::convertFrom0to1 (float v) const noexcept { return limitRange (roundToInt (v * (float) maxIndex)); }
float AudioParameterChoice::getValue() const { return convertTo0to1 (roundToInt (value)); }
void AudioParameterChoice::setValue (float newValue) { value = (float) convertFrom0to1 (newValue); valueChanged (getIndex()); }
float AudioParameterChoice::getDefaultValue() const { return defaultValue; }
int AudioParameterChoice::getNumSteps() const { return choices.size(); }
bool AudioParameterChoice::isDiscrete() const { return true; }
float AudioParameterChoice::getValueForText (const String& text) const { return convertTo0to1 (indexFromStringFunction (text)); }
String AudioParameterChoice::getText (float v, int length) const { return stringFromIndexFunction (convertFrom0to1 (v), length); }
void AudioParameterChoice::valueChanged (int) {}
AudioParameterChoice& AudioParameterChoice::operator= (int newValue)
{
if (getIndex() != newValue)
setValueNotifyingHost (convertTo0to1 (newValue));
return *this;
}
} // namespace juce

View File

@ -0,0 +1,658 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
struct AudioProcessorValueTreeState::Parameter : public AudioProcessorParameterWithID,
private ValueTree::Listener
{
Parameter (AudioProcessorValueTreeState& s,
const String& parameterID, const String& paramName, const String& labelText,
NormalisableRange<float> r, float defaultVal,
std::function<String (float)> valueToText,
std::function<float (const String&)> textToValue,
bool meta,
bool automatable,
bool discrete,
AudioProcessorParameter::Category category,
bool boolean)
: AudioProcessorParameterWithID (parameterID, paramName, labelText, category),
owner (s), valueToTextFunction (valueToText), textToValueFunction (textToValue),
range (r), value (defaultVal), defaultValue (defaultVal),
listenersNeedCalling (true),
isMetaParam (meta),
isAutomatableParam (automatable),
isDiscreteParam (discrete),
isBooleanParam (boolean)
{
value = defaultValue;
state.addListener (this);
}
~Parameter()
{
// should have detached all callbacks before destroying the parameters!
jassert (listeners.size() <= 1);
}
float getValue() const override { return range.convertTo0to1 (value); }
float getDefaultValue() const override { return range.convertTo0to1 (defaultValue); }
float getValueForText (const String& text) const override
{
return range.convertTo0to1 (textToValueFunction != nullptr ? textToValueFunction (text)
: text.getFloatValue());
}
String getText (float v, int length) const override
{
return valueToTextFunction != nullptr ? valueToTextFunction (range.convertFrom0to1 (v))
: AudioProcessorParameter::getText (v, length);
}
int getNumSteps() const override
{
if (range.interval > 0)
return (static_cast<int> ((range.end - range.start) / range.interval) + 1);
return AudioProcessor::getDefaultNumParameterSteps();
}
void setValue (float newValue) override
{
newValue = range.snapToLegalValue (range.convertFrom0to1 (newValue));
if (value != newValue || listenersNeedCalling)
{
value = newValue;
listeners.call ([=] (AudioProcessorValueTreeState::Listener& l) { l.parameterChanged (paramID, value); });
listenersNeedCalling = false;
needsUpdate = true;
}
}
void setNewState (const ValueTree& v)
{
state = v;
updateFromValueTree();
}
void setUnnormalisedValue (float newUnnormalisedValue)
{
if (value != newUnnormalisedValue)
{
const float newValue = range.convertTo0to1 (newUnnormalisedValue);
setValueNotifyingHost (newValue);
}
}
void updateFromValueTree()
{
setUnnormalisedValue (state.getProperty (owner.valuePropertyID, defaultValue));
}
void copyValueToValueTree()
{
if (auto* valueProperty = state.getPropertyPointer (owner.valuePropertyID))
{
if ((float) *valueProperty != value)
{
ScopedValueSetter<bool> svs (ignoreParameterChangedCallbacks, true);
state.setProperty (owner.valuePropertyID, value, owner.undoManager);
}
}
else
{
state.setProperty (owner.valuePropertyID, value, nullptr);
}
}
void valueTreePropertyChanged (ValueTree&, const Identifier& property) override
{
if (ignoreParameterChangedCallbacks)
return;
if (property == owner.valuePropertyID)
updateFromValueTree();
}
void valueTreeChildAdded (ValueTree&, ValueTree&) override {}
void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override {}
void valueTreeChildOrderChanged (ValueTree&, int, int) override {}
void valueTreeParentChanged (ValueTree&) override {}
static Parameter* getParameterForID (AudioProcessor& processor, StringRef paramID) noexcept
{
for (auto* ap : processor.getParameters())
{
// When using this class, you must allow it to manage all the parameters in your AudioProcessor, and
// not add any parameter objects of other types!
jassert (dynamic_cast<Parameter*> (ap) != nullptr);
auto* p = static_cast<Parameter*> (ap);
if (paramID == p->paramID)
return p;
}
return nullptr;
}
bool isMetaParameter() const override { return isMetaParam; }
bool isAutomatable() const override { return isAutomatableParam; }
bool isDiscrete() const override { return isDiscreteParam; }
bool isBoolean() const override { return isBooleanParam; }
AudioProcessorValueTreeState& owner;
ValueTree state;
ListenerList<AudioProcessorValueTreeState::Listener> listeners;
std::function<String (float)> valueToTextFunction;
std::function<float (const String&)> textToValueFunction;
NormalisableRange<float> range;
float value, defaultValue;
std::atomic<bool> needsUpdate { true };
bool listenersNeedCalling;
const bool isMetaParam, isAutomatableParam, isDiscreteParam, isBooleanParam;
bool ignoreParameterChangedCallbacks = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Parameter)
};
//==============================================================================
AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& p, UndoManager* um)
: processor (p), undoManager (um)
{
startTimerHz (10);
state.addListener (this);
}
AudioProcessorValueTreeState::~AudioProcessorValueTreeState() {}
AudioProcessorParameterWithID* AudioProcessorValueTreeState::createAndAddParameter (const String& paramID, const String& paramName,
const String& labelText, NormalisableRange<float> r,
float defaultVal, std::function<String (float)> valueToTextFunction,
std::function<float (const String&)> textToValueFunction,
bool isMetaParameter,
bool isAutomatableParameter,
bool isDiscreteParameter,
AudioProcessorParameter::Category category,
bool isBooleanParameter)
{
// All parameters must be created before giving this manager a ValueTree state!
jassert (! state.isValid());
Parameter* p = new Parameter (*this, paramID, paramName, labelText, r,
defaultVal, valueToTextFunction, textToValueFunction,
isMetaParameter, isAutomatableParameter,
isDiscreteParameter, category, isBooleanParameter);
processor.addParameter (p);
return p;
}
void AudioProcessorValueTreeState::addParameterListener (StringRef paramID, Listener* listener)
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
p->listeners.add (listener);
}
void AudioProcessorValueTreeState::removeParameterListener (StringRef paramID, Listener* listener)
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
p->listeners.remove (listener);
}
Value AudioProcessorValueTreeState::getParameterAsValue (StringRef paramID) const
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
return p->state.getPropertyAsValue (valuePropertyID, undoManager);
return {};
}
NormalisableRange<float> AudioProcessorValueTreeState::getParameterRange (StringRef paramID) const noexcept
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
return p->range;
return NormalisableRange<float>();
}
AudioProcessorParameterWithID* AudioProcessorValueTreeState::getParameter (StringRef paramID) const noexcept
{
return Parameter::getParameterForID (processor, paramID);
}
float* AudioProcessorValueTreeState::getRawParameterValue (StringRef paramID) const noexcept
{
if (Parameter* p = Parameter::getParameterForID (processor, paramID))
return &(p->value);
return nullptr;
}
ValueTree AudioProcessorValueTreeState::copyState()
{
ScopedLock lock (valueTreeChanging);
flushParameterValuesToValueTree();
return state.createCopy();
}
void AudioProcessorValueTreeState::replaceState (const ValueTree& newState)
{
ScopedLock lock (valueTreeChanging);
state = newState;
if (undoManager != nullptr)
undoManager->clearUndoHistory();
}
ValueTree AudioProcessorValueTreeState::getOrCreateChildValueTree (const String& paramID)
{
ValueTree v (state.getChildWithProperty (idPropertyID, paramID));
if (! v.isValid())
{
v = ValueTree (valueType);
v.setProperty (idPropertyID, paramID, nullptr);
state.appendChild (v, nullptr);
}
return v;
}
void AudioProcessorValueTreeState::updateParameterConnectionsToChildTrees()
{
ScopedLock lock (valueTreeChanging);
for (auto* param : processor.getParameters())
{
jassert (dynamic_cast<Parameter*> (param) != nullptr);
auto* p = static_cast<Parameter*> (param);
p->setNewState (getOrCreateChildValueTree (p->paramID));
}
}
void AudioProcessorValueTreeState::valueTreePropertyChanged (ValueTree& tree, const Identifier& property)
{
if (property == idPropertyID && tree.hasType (valueType) && tree.getParent() == state)
updateParameterConnectionsToChildTrees();
}
void AudioProcessorValueTreeState::valueTreeChildAdded (ValueTree& parent, ValueTree& tree)
{
if (parent == state && tree.hasType (valueType))
if (auto* param = Parameter::getParameterForID (processor, tree.getProperty (idPropertyID).toString()))
param->setNewState (getOrCreateChildValueTree (param->paramID));
}
void AudioProcessorValueTreeState::valueTreeChildRemoved (ValueTree& parent, ValueTree& tree, int)
{
if (parent == state && tree.hasType (valueType))
if (auto* param = Parameter::getParameterForID (processor, tree.getProperty (idPropertyID).toString()))
param->setNewState (getOrCreateChildValueTree (param->paramID));
}
void AudioProcessorValueTreeState::valueTreeRedirected (ValueTree& v)
{
if (v == state)
updateParameterConnectionsToChildTrees();
}
void AudioProcessorValueTreeState::valueTreeChildOrderChanged (ValueTree&, int, int) {}
void AudioProcessorValueTreeState::valueTreeParentChanged (ValueTree&) {}
bool AudioProcessorValueTreeState::flushParameterValuesToValueTree()
{
ScopedLock lock (valueTreeChanging);
bool anythingUpdated = false;
for (auto* ap : processor.getParameters())
{
jassert (dynamic_cast<Parameter*> (ap) != nullptr);
auto* p = static_cast<Parameter*> (ap);
bool needsUpdateTestValue = true;
if (p->needsUpdate.compare_exchange_strong (needsUpdateTestValue, false))
{
p->copyValueToValueTree();
anythingUpdated = true;
}
}
return anythingUpdated;
}
void AudioProcessorValueTreeState::timerCallback()
{
auto anythingUpdated = flushParameterValuesToValueTree();
startTimer (anythingUpdated ? 1000 / 50
: jlimit (50, 500, getTimerInterval() + 20));
}
AudioProcessorValueTreeState::Listener::Listener() {}
AudioProcessorValueTreeState::Listener::~Listener() {}
//==============================================================================
struct AttachedControlBase : public AudioProcessorValueTreeState::Listener,
public AsyncUpdater
{
AttachedControlBase (AudioProcessorValueTreeState& s, const String& p)
: state (s), paramID (p), lastValue (0)
{
state.addParameterListener (paramID, this);
}
void removeListener()
{
state.removeParameterListener (paramID, this);
}
void setNewUnnormalisedValue (float newUnnormalisedValue)
{
if (AudioProcessorParameter* p = state.getParameter (paramID))
{
const float newValue = state.getParameterRange (paramID)
.convertTo0to1 (newUnnormalisedValue);
if (p->getValue() != newValue)
p->setValueNotifyingHost (newValue);
}
}
void sendInitialUpdate()
{
if (float* v = state.getRawParameterValue (paramID))
parameterChanged (paramID, *v);
}
void parameterChanged (const String&, float newValue) override
{
lastValue = newValue;
if (MessageManager::getInstance()->isThisTheMessageThread())
{
cancelPendingUpdate();
setValue (newValue);
}
else
{
triggerAsyncUpdate();
}
}
void beginParameterChange()
{
if (AudioProcessorParameter* p = state.getParameter (paramID))
{
if (state.undoManager != nullptr)
state.undoManager->beginNewTransaction();
p->beginChangeGesture();
}
}
void endParameterChange()
{
if (AudioProcessorParameter* p = state.getParameter (paramID))
p->endChangeGesture();
}
void handleAsyncUpdate() override
{
setValue (lastValue);
}
virtual void setValue (float) = 0;
AudioProcessorValueTreeState& state;
String paramID;
float lastValue;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AttachedControlBase)
};
//==============================================================================
struct AudioProcessorValueTreeState::SliderAttachment::Pimpl : private AttachedControlBase,
private Slider::Listener
{
Pimpl (AudioProcessorValueTreeState& s, const String& p, Slider& sl)
: AttachedControlBase (s, p), slider (sl), ignoreCallbacks (false)
{
NormalisableRange<float> range (state.getParameterRange (paramID));
if (range.interval != 0 || range.skew != 0)
{
slider.setRange (range.start, range.end, range.interval);
slider.setSkewFactor (range.skew, range.symmetricSkew);
}
else
{
auto convertFrom0To1Function = [range] (double currentRangeStart,
double currentRangeEnd,
double normalisedValue) mutable
{
range.start = (float) currentRangeStart;
range.end = (float) currentRangeEnd;
return (double) range.convertFrom0to1 ((float) normalisedValue);
};
auto convertTo0To1Function = [range] (double currentRangeStart,
double currentRangeEnd,
double mappedValue) mutable
{
range.start = (float) currentRangeStart;
range.end = (float) currentRangeEnd;
return (double) range.convertTo0to1 ((float) mappedValue);
};
auto snapToLegalValueFunction = [range] (double currentRangeStart,
double currentRangeEnd,
double valueToSnap) mutable
{
range.start = (float) currentRangeStart;
range.end = (float) currentRangeEnd;
return (double) range.snapToLegalValue ((float) valueToSnap);
};
slider.setNormalisableRange ({ (double) range.start, (double) range.end,
convertFrom0To1Function,
convertTo0To1Function,
snapToLegalValueFunction });
}
if (auto* param = dynamic_cast<AudioProcessorValueTreeState::Parameter*> (state.getParameter (paramID)))
{
if (param->textToValueFunction != nullptr)
slider.valueFromTextFunction = [param] (const String& text) { return (double) param->textToValueFunction (text); };
if (param->valueToTextFunction != nullptr)
slider.textFromValueFunction = [param] (double value) { return param->valueToTextFunction ((float) value); };
slider.setDoubleClickReturnValue (true, range.convertFrom0to1 (param->getDefaultValue()));
}
sendInitialUpdate();
slider.addListener (this);
}
~Pimpl()
{
slider.removeListener (this);
removeListener();
}
void setValue (float newValue) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
{
ScopedValueSetter<bool> svs (ignoreCallbacks, true);
slider.setValue (newValue, sendNotificationSync);
}
}
void sliderValueChanged (Slider* s) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
if ((! ignoreCallbacks) && (! ModifierKeys::currentModifiers.isRightButtonDown()))
setNewUnnormalisedValue ((float) s->getValue());
}
void sliderDragStarted (Slider*) override { beginParameterChange(); }
void sliderDragEnded (Slider*) override { endParameterChange(); }
Slider& slider;
bool ignoreCallbacks;
CriticalSection selfCallbackMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
AudioProcessorValueTreeState::SliderAttachment::SliderAttachment (AudioProcessorValueTreeState& s, const String& p, Slider& sl)
: pimpl (new Pimpl (s, p, sl))
{
}
AudioProcessorValueTreeState::SliderAttachment::~SliderAttachment() {}
//==============================================================================
struct AudioProcessorValueTreeState::ComboBoxAttachment::Pimpl : private AttachedControlBase,
private ComboBox::Listener
{
Pimpl (AudioProcessorValueTreeState& s, const String& p, ComboBox& c)
: AttachedControlBase (s, p), combo (c), ignoreCallbacks (false)
{
sendInitialUpdate();
combo.addListener (this);
}
~Pimpl()
{
combo.removeListener (this);
removeListener();
}
void setValue (float newValue) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
{
ScopedValueSetter<bool> svs (ignoreCallbacks, true);
combo.setSelectedItemIndex (roundToInt (newValue), sendNotificationSync);
}
}
void comboBoxChanged (ComboBox* comboBox) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
if (! ignoreCallbacks)
{
beginParameterChange();
setNewUnnormalisedValue ((float) comboBox->getSelectedId() - 1.0f);
endParameterChange();
}
}
ComboBox& combo;
bool ignoreCallbacks;
CriticalSection selfCallbackMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
AudioProcessorValueTreeState::ComboBoxAttachment::ComboBoxAttachment (AudioProcessorValueTreeState& s, const String& p, ComboBox& c)
: pimpl (new Pimpl (s, p, c))
{
}
AudioProcessorValueTreeState::ComboBoxAttachment::~ComboBoxAttachment() {}
//==============================================================================
struct AudioProcessorValueTreeState::ButtonAttachment::Pimpl : private AttachedControlBase,
private Button::Listener
{
Pimpl (AudioProcessorValueTreeState& s, const String& p, Button& b)
: AttachedControlBase (s, p), button (b), ignoreCallbacks (false)
{
sendInitialUpdate();
button.addListener (this);
}
~Pimpl()
{
button.removeListener (this);
removeListener();
}
void setValue (float newValue) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
{
ScopedValueSetter<bool> svs (ignoreCallbacks, true);
button.setToggleState (newValue >= 0.5f, sendNotificationSync);
}
}
void buttonClicked (Button* b) override
{
const ScopedLock selfCallbackLock (selfCallbackMutex);
if (! ignoreCallbacks)
{
beginParameterChange();
setNewUnnormalisedValue (b->getToggleState() ? 1.0f : 0.0f);
endParameterChange();
}
}
Button& button;
bool ignoreCallbacks;
CriticalSection selfCallbackMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
AudioProcessorValueTreeState::ButtonAttachment::ButtonAttachment (AudioProcessorValueTreeState& s, const String& p, Button& b)
: pimpl (new Pimpl (s, p, b))
{
}
AudioProcessorValueTreeState::ButtonAttachment::~ButtonAttachment() {}
} // namespace juce

View File

@ -0,0 +1,279 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2017 - ROLI Ltd.
JUCE is an open source library subject to commercial or open-source
licensing.
By using JUCE, you agree to the terms of both the JUCE 5 End-User License
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
27th April 2017).
End User License Agreement: www.juce.com/juce-5-licence
Privacy Policy: www.juce.com/juce-5-privacy-policy
Or: You may also use this code under the terms of the GPL v3 (see
www.gnu.org/licenses).
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
/**
This class contains a ValueTree which is used to manage an AudioProcessor's entire state.
It has its own internal class of parameter object which are linked to values
within its ValueTree, and which are each identified by a string ID.
You can get access to the underlying ValueTree object via the state member variable,
so you can add extra properties to it as necessary.
It also provides some utility child classes for connecting parameters directly to
GUI controls like sliders.
To use:
1) Create an AudioProcessorValueTreeState, and give it some parameters using createAndAddParameter().
2) Initialise the state member variable with a type name.
@tags{Audio}
*/
class JUCE_API AudioProcessorValueTreeState : private Timer,
private ValueTree::Listener
{
public:
/** Creates a state object for a given processor.
The UndoManager is optional and can be a nullptr.
After creating your state object, you should add parameters with the
createAndAddParameter() method. Note that each AudioProcessorValueTreeState
should be attached to only one processor, and must have the same lifetime as the
processor, as they will have dependencies on each other.
*/
AudioProcessorValueTreeState (AudioProcessor& processorToConnectTo,
UndoManager* undoManagerToUse);
/** Destructor. */
~AudioProcessorValueTreeState();
/** Creates and returns a new parameter object for controlling a parameter
with the given ID.
Calling this will create and add a special type of AudioProcessorParameter to the
AudioProcessor to which this state is attached.
@param parameterID A unique string ID for the new parameter
@param parameterName The name that the parameter will return from AudioProcessorParameter::getName()
@param labelText The label that the parameter will return from AudioProcessorParameter::getLabel()
@param valueRange A mapping that will be used to determine the value range which this parameter uses
@param defaultValue A default value for the parameter (in non-normalised units)
@param valueToTextFunction A function that will convert a non-normalised value to a string for the
AudioProcessorParameter::getText() method. This can be nullptr to use the
default implementation
@param textToValueFunction The inverse of valueToTextFunction
@param isMetaParameter Set this value to true if this should be a meta parameter
@param isAutomatableParameter Set this value to false if this parameter should not be automatable
@param isDiscrete Set this value to true to make this parameter take discrete values in a host.
@see AudioProcessorParameter::isDiscrete
@param category Which category the parameter should use.
@see AudioProcessorParameter::Category
@param isBoolean Set this value to true to make this parameter appear as a boolean toggle in
a hosts view of your plug-ins parameters
@see AudioProcessorParameter::isBoolean
@returns the parameter object that was created
*/
AudioProcessorParameterWithID* createAndAddParameter (const String& parameterID,
const String& parameterName,
const String& labelText,
NormalisableRange<float> valueRange,
float defaultValue,
std::function<String (float)> valueToTextFunction,
std::function<float (const String&)> textToValueFunction,
bool isMetaParameter = false,
bool isAutomatableParameter = true,
bool isDiscrete = false,
AudioProcessorParameter::Category category
= AudioProcessorParameter::genericParameter,
bool isBoolean = false);
/** Returns a parameter by its ID string. */
AudioProcessorParameterWithID* getParameter (StringRef parameterID) const noexcept;
/** Returns a pointer to a floating point representation of a particular
parameter which a realtime process can read to find out its current value.
*/
float* getRawParameterValue (StringRef parameterID) const noexcept;
/** A listener class that can be attached to an AudioProcessorValueTreeState.
Use AudioProcessorValueTreeState::addParameterListener() to register a callback.
*/
struct JUCE_API Listener
{
Listener();
virtual ~Listener();
/** This callback method is called by the AudioProcessorValueTreeState when a parameter changes. */
virtual void parameterChanged (const String& parameterID, float newValue) = 0;
};
/** Attaches a callback to one of the parameters, which will be called when the parameter changes. */
void addParameterListener (StringRef parameterID, Listener* listener);
/** Removes a callback that was previously added with addParameterCallback(). */
void removeParameterListener (StringRef parameterID, Listener* listener);
/** Returns a Value object that can be used to control a particular parameter. */
Value getParameterAsValue (StringRef parameterID) const;
/** Returns the range that was set when the given parameter was created. */
NormalisableRange<float> getParameterRange (StringRef parameterID) const noexcept;
/** Returns a copy of the state value tree.
The AudioProcessorValueTreeState's ValueTree is updated internally on the
message thread, but there may be cases when you may want to access the state
from a different thread (getStateInformation is a good example). This method
flushes all pending audio parameter value updates and returns a copy of the
state in a thread safe way.
Note: This method uses locks to synchronise thread access, so whilst it is
thread-safe, it is not realtime-safe. Do not call this method from within
your audio processing code!
*/
ValueTree copyState();
/** Replaces the state value tree.
The AudioProcessorValueTreeState's ValueTree is updated internally on the
message thread, but there may be cases when you may want to modify the state
from a different thread (setStateInformation is a good example). This method
allows you to replace the state in a thread safe way.
Note: This method uses locks to synchronise thread access, so whilst it is
thread-safe, it is not realtime-safe. Do not call this method from within
your audio processing code!
*/
void replaceState (const ValueTree& newState);
/** A reference to the processor with which this state is associated. */
AudioProcessor& processor;
/** The state of the whole processor.
This must be initialised after all calls to createAndAddParameter().
You can replace this with your own ValueTree object, and can add properties and
children to the tree. This class will automatically add children for each of the
parameter objects that are created by createAndAddParameter().
*/
ValueTree state;
/** Provides access to the undo manager that this object is using. */
UndoManager* const undoManager;
//==============================================================================
/** An object of this class maintains a connection between a Slider and a parameter
in an AudioProcessorValueTreeState.
During the lifetime of this SliderAttachment object, it keeps the two things in
sync, making it easy to connect a slider to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
and Slider aren't deleted before this object!
*/
class JUCE_API SliderAttachment
{
public:
SliderAttachment (AudioProcessorValueTreeState& stateToControl,
const String& parameterID,
Slider& sliderToControl);
~SliderAttachment();
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SliderAttachment)
};
//==============================================================================
/** An object of this class maintains a connection between a ComboBox and a parameter
in an AudioProcessorValueTreeState.
During the lifetime of this ComboBoxAttachment object, it keeps the two things in
sync, making it easy to connect a combo box to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
and ComboBox aren't deleted before this object!
*/
class JUCE_API ComboBoxAttachment
{
public:
ComboBoxAttachment (AudioProcessorValueTreeState& stateToControl,
const String& parameterID,
ComboBox& comboBoxToControl);
~ComboBoxAttachment();
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComboBoxAttachment)
};
//==============================================================================
/** An object of this class maintains a connection between a Button and a parameter
in an AudioProcessorValueTreeState.
During the lifetime of this ButtonAttachment object, it keeps the two things in
sync, making it easy to connect a button to a parameter. When this object is
deleted, the connection is broken. Make sure that your AudioProcessorValueTreeState
and Button aren't deleted before this object!
*/
class JUCE_API ButtonAttachment
{
public:
ButtonAttachment (AudioProcessorValueTreeState& stateToControl,
const String& parameterID,
Button& buttonToControl);
~ButtonAttachment();
private:
struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
std::unique_ptr<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonAttachment)
};
private:
//==============================================================================
struct Parameter;
friend struct Parameter;
ValueTree getOrCreateChildValueTree (const String&);
bool flushParameterValuesToValueTree();
void timerCallback() override;
void valueTreePropertyChanged (ValueTree&, const Identifier&) override;
void valueTreeChildAdded (ValueTree&, ValueTree&) override;
void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override;
void valueTreeChildOrderChanged (ValueTree&, int, int) override;
void valueTreeParentChanged (ValueTree&) override;
void valueTreeRedirected (ValueTree&) override;
void updateParameterConnectionsToChildTrees();
Identifier valueType { "PARAM" },
valuePropertyID { "value" },
idPropertyID { "id" };
CriticalSection valueTreeChanging;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorValueTreeState)
};
} // namespace juce