Skip to content

Commit 9235e2d

Browse files
committed
Add CustomParameter
1 parent 60820b7 commit 9235e2d

File tree

2 files changed

+127
-2
lines changed

2 files changed

+127
-2
lines changed

WECore/CoreJUCEPlugin/CoreAudioProcessor.h

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "../JuceLibraryCode/JuceHeader.h"
2828
#include "General/ParameterDefinition.h"
2929
#include "ParameterUpdateHandler.h"
30+
#include "CustomParameter.h"
3031

3132
namespace WECore::JUCEPlugin {
3233

@@ -118,7 +119,6 @@ namespace WECore::JUCEPlugin {
118119
float defaultValue);
119120
/** @} */
120121

121-
// These methods allow custom setters if needed
122122
/**
123123
* Used to register private parameters that are not visible to the host. Used for parameters
124124
* that cause other parameter or state changes so make automation impractical, but should
@@ -133,7 +133,10 @@ namespace WECore::JUCEPlugin {
133133
*
134134
* Int parameters are created with their real (not normalised) ranges.
135135
*
136+
* Custom parameters don't have a range and can only ever be private.
137+
*
136138
* (Bool parameters don't have a meaningful range.)
139+
*
137140
*/
138141
/** @{ */
139142
inline void registerPrivateParameter(juce::AudioParameterFloat*& param,
@@ -148,6 +151,9 @@ namespace WECore::JUCEPlugin {
148151
const ParameterDefinition::BaseParameter<int>* range,
149152
int defaultValue,
150153
std::function<void(int)> setter);
154+
155+
template <typename PARAM_TYPE>
156+
inline void registerPrivateParameter(PARAM_TYPE*& param, const juce::String& name);
151157
/** @} */
152158

153159
/**
@@ -169,6 +175,7 @@ namespace WECore::JUCEPlugin {
169175
// We need to store pointers to all the private parameters that are registered so that they
170176
// can be deallocated by the destructor
171177
std::vector<juce::AudioProcessorParameter*> _privateParameters;
178+
std::vector<CustomParameter*> _customParameters;
172179

173180
/**
174181
* Stores a setter and getter for a parameter. Used when persisting parameter values to XML
@@ -180,6 +187,17 @@ namespace WECore::JUCEPlugin {
180187
std::function<void(float)> setter;
181188
};
182189

190+
/**
191+
* Stores a setter and getter for a custom parameter. Used when persisting parameter values
192+
* to XML and restoring values from XML. Access to the params XML element is provided since
193+
* custom parameters typically need to store complex data.
194+
*/
195+
struct CustomParameterInterface {
196+
juce::String name;
197+
std::function<void(juce::XmlElement*)> writeToXml;
198+
std::function<void(juce::XmlElement*)> restoreFromXml;
199+
};
200+
183201
/**
184202
* Listens for parameter changes and triggers the broadcaster so the changes can be handled
185203
* by another thread.
@@ -200,9 +218,10 @@ namespace WECore::JUCEPlugin {
200218
ParameterBroadcaster _parameterBroadcaster;
201219

202220
/**
203-
* List of parameters in the order they are registered and stored in XML.
221+
* List of parameters which will trigger updates and are stored in XML.
204222
*/
205223
std::vector<ParameterInterface> _paramsList;
224+
std::vector<CustomParameterInterface> _customParamsList;
206225

207226
inline std::vector<float> _stringToFloatVector(const juce::String sFloatCSV) const;
208227

@@ -224,6 +243,10 @@ namespace WECore::JUCEPlugin {
224243
for (juce::AudioProcessorParameter* parameter : _privateParameters) {
225244
delete parameter;
226245
}
246+
247+
for (CustomParameter* parameter : _customParameters) {
248+
delete parameter;
249+
}
227250
}
228251

229252
void CoreAudioProcessor::setParameterValueInternal(juce::AudioParameterFloat* param, float value) {
@@ -251,6 +274,11 @@ namespace WECore::JUCEPlugin {
251274
paramsElement->setAttribute(param.name, param.getter());
252275
}
253276

277+
for (const CustomParameterInterface& param : _customParamsList) {
278+
juce::XmlElement* thisParameterElement = paramsElement->createNewChildElement(param.name);
279+
param.writeToXml(thisParameterElement);
280+
}
281+
254282
copyXmlToBinary(rootElement, destData);
255283
}
256284

@@ -273,6 +301,14 @@ namespace WECore::JUCEPlugin {
273301
param.setter(paramsElement->getDoubleAttribute(param.name));
274302
}
275303
}
304+
305+
for (const CustomParameterInterface& param : _customParamsList) {
306+
juce::XmlElement* thisParameterElement = paramsElement->getChildByName(param.name);
307+
308+
if (thisParameterElement != nullptr) {
309+
param.restoreFromXml(thisParameterElement);
310+
}
311+
}
276312
}
277313
}
278314
}
@@ -371,6 +407,19 @@ namespace WECore::JUCEPlugin {
371407
_privateParameters.push_back(param);
372408
}
373409

410+
template <typename PARAM_TYPE>
411+
void CoreAudioProcessor::registerPrivateParameter(PARAM_TYPE*& param, const juce::String& name) {
412+
param = new PARAM_TYPE();
413+
414+
CustomParameterInterface interface = {name,
415+
[&param](juce::XmlElement* element) { param->writeToXml(element); },
416+
[&param](juce::XmlElement* element) { param->restoreFromXml(element); }};
417+
_customParamsList.push_back(interface);
418+
419+
param->setListener(&_parameterBroadcaster);
420+
_customParameters.push_back(param);
421+
}
422+
374423
std::vector<float> CoreAudioProcessor::_stringToFloatVector(const juce::String sFloatCSV) const {
375424
juce::StringArray tokenizer;
376425
tokenizer.addTokens(sFloatCSV, ",","");
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* File: CustomParameter.h
3+
*
4+
* Version: 1.0.0
5+
*
6+
* Created: 18/08/2021
7+
*
8+
* This file is part of WECore.
9+
*
10+
* WECore is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation, either version 3 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* WECore is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with WECore. If not, see <http://www.gnu.org/licenses/>.
22+
*
23+
*/
24+
25+
#pragma once
26+
27+
#include "../JuceLibraryCode/JuceHeader.h"
28+
29+
/**
30+
* Used to store state that shouldn't be exposed to the host, but would benefit from using the
31+
* save/restore and update mechanism used by conventional parameters.
32+
*
33+
* Derive from this class and add your own setter/getter methods as needed, just call
34+
* _updateListener() to trigger an update.
35+
*
36+
* Provide an implementation for restoreFromXml and writeToXml to enable saving and restoring
37+
* parameter state.
38+
*/
39+
class CustomParameter {
40+
public:
41+
inline CustomParameter();
42+
virtual ~CustomParameter() = default;
43+
44+
inline void setListener(juce::AudioProcessorParameter::Listener* listener);
45+
inline void removeListener();
46+
47+
virtual void restoreFromXml(juce::XmlElement* element) = 0;
48+
virtual void writeToXml(juce::XmlElement* element) = 0;
49+
50+
protected:
51+
inline void _updateListener();
52+
53+
private:
54+
std::mutex _listenerMutex;
55+
juce::AudioProcessorParameter::Listener* _listener;
56+
};
57+
58+
CustomParameter::CustomParameter() : _listener(nullptr) {
59+
}
60+
61+
void CustomParameter::setListener(juce::AudioProcessorParameter::Listener* listener) {
62+
std::scoped_lock lock(_listenerMutex);
63+
_listener = listener;
64+
}
65+
66+
void CustomParameter::removeListener() {
67+
std::scoped_lock lock(_listenerMutex);
68+
_listener = nullptr;
69+
}
70+
71+
void CustomParameter::_updateListener() {
72+
std::scoped_lock lock(_listenerMutex);
73+
if (_listener != nullptr) {
74+
_listener->parameterValueChanged(0, 0);
75+
}
76+
}

0 commit comments

Comments
 (0)