Plugin GUI Magic (PGM) is a JUCE module that supports easily creating, editing, saving, and loading JUCE GUIs at runtime.
PGM Demo Video: Plugin Gui Magic Equalizer Example (JUCE Audio Plugin)
Clone the main branch of plugin gui magic:
git clone https://github.com/ffAudio/foleys_gui_magic.git
For starters, look over the PGM distribution. It basically contains a single JUCE Module
named foleys_gui_magic that you will load into your
project using the JUCE Projucer
(or CMake with JUCE support added).
We cover using PGM in the videos linked below.
<Slider caption="Gain" parameter="gain"
min-width="20" min-height="10" max-height="80"/>
These become node types and properties in a
juce::ValueTree
,
which manages a
juce::NamedValueSet
containing child nodes and named
juce::var
properties.juce::var
is similar to a var
in JavaScript and wraps a
single int, bool, float, string, or array.juce::var
:
juce::ValueTree svt ("Slider"); // ValueTree Type set forever to "Slider"
svt.setProperty(/* const Identifier& */ "Gain", /* const var& */ 0.1, /* UndoManager* */ nullptr);
juce::ValueTree sbvt ("SliderBank");
sbvt.addChild(svt, /* index */ -1, /* undoMgr */ nullptr);
// ...
ValueTree
has a type (e.g., "Slider" above), which you can query
using getType()
and hasType()
.juce::AsyncUpdater
to do anything nontrivial.
juce::ReferenceCountedObject
.
toXmlString
and
fromXml
.
PGM, following JUCE-recommended best practice, requires us to create a
juce::AudioProcessorValueTreeState (APVTS) in our processor to hold all of our plugin parameter info in a hierarchically grouped
ParameterLayout:
processorToConnectTo
.AudioProcessor()
APVTS()
createParameterLayout()
create and return the parameters in a juce::AudioProcessorParameterGroup
MOVE the parameters into the parameters array OWNED BY THE APVTS
Later you can access the parameters via APVTS methods such as:
std::atomic* getRawParameterValue (StringRef parameterID)
RangedAudioParameter* getParameter (StringRef parameterID)
std::atomic
parameter pointers are used to prevent a
so-called "torn" read or write due to a collision of
two or more threads.
float
) is thread-safe for
reading and writing thanks to a built-in
memory
barrier for this purpose, and the Faust
compiler assumes this.
std::atomic
should
do nothing and cost nothing at run time. It is
therefore best practice to declare audio
processor parameters using std::atomic
and let the C++ compiler decide what is needed for
thread safety, if anything.
This is the most advanced C++ we will have to deal with in Music 320c, involving unique smart pointers and a rigid construction/initialization process.
Be aware that this APVTS-based method of handling plugin
parameters is relatively recent, so you'll find older JUCE
code, even in official JUCE tutorials, that uses the older
(deprecated) processor-based management of the plugin
parameters. In
particular, createAndAddParameter()
is
deprecated, so avoid examples using that.
createParameterLayout()
is genuinely useful, but arguably outside our scopeLecture Recordings (making of):
createParameterLayout()