Mema
Memory Matrix — multi-channel audio matrix monitor and router
Loading...
Searching...
No Matches
MemaPluginParameterInfo.h
Go to the documentation of this file.
1/* Copyright (c) 2025, Christian Ahrens
2 *
3 * This file is part of Mema <https://github.com/ChristianAhrens/Mema>
4 *
5 * This tool is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License version 3.0 as published
7 * by the Free Software Foundation.
8 *
9 * This tool is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this tool; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18#pragma once
19
20#include <JuceHeader.h>
21
22namespace Mema
23{
24
26{
27 Toggle, // Two-state button/switch
28 Discrete, // Dropdown/ComboBox for discrete values
29 Continuous // Slider/Fader for continuous values
30};
31
34{
35 int index = 0;
36 juce::String id = "0";
37 juce::String name = "";
38 float defaultValue = 0.0f;
39 float currentValue = 0.0f;
40 juce::String label = "";
41 bool isAutomatable = false;
43 juce::AudioProcessorParameter::Category category = juce::AudioProcessorParameter::Category::genericParameter;
44 float minValue = 0.0f;
45 float maxValue = 1.0f;
46 float stepSize = 0.0f;
47 bool isDiscrete = false;
48 ParameterControlType type = ParameterControlType::Continuous;
49 int stepCount = 0;
50 std::vector<std::string> stepNames;
51
52 // Equality operator
53 bool operator==(const PluginParameterInfo& other) const
54 {
55 return index == other.index &&
56 id == other.id &&
57 name == other.name &&
58 defaultValue == other.defaultValue &&
59 currentValue == other.currentValue &&
60 label == other.label &&
63 category == other.category &&
64 minValue == other.minValue &&
65 maxValue == other.maxValue &&
66 stepSize == other.stepSize &&
67 isDiscrete == other.isDiscrete &&
68 type == other.type &&
69 stepCount == other.stepCount;
70 }
71
72 // Inequality operator
73 bool operator!=(const PluginParameterInfo& other) const
74 {
75 return !(*this == other);
76 }
77
78 // Less-than operator (primarily based on index, then id)
79 bool operator<(const PluginParameterInfo& other) const
80 {
81 if (index != other.index)
82 return index < other.index;
83 return id < other.id;
84 }
85
86 // Greater-than operator
87 bool operator>(const PluginParameterInfo& other) const
88 {
89 return other < *this;
90 }
91
92 // Less-than-or-equal operator
93 bool operator<=(const PluginParameterInfo& other) const
94 {
95 return !(other < *this);
96 }
97
98 // Greater-than-or-equal operator
99 bool operator>=(const PluginParameterInfo& other) const
100 {
101 return !(*this < other);
102 }
103
104 juce::String toString() const
105 {
106 return juce::String(index) + ";"
107 + id + ";"
108 + name + ";"
109 + juce::String(defaultValue) + ";"
110 + juce::String(currentValue) + ";"
111 + label + ";"
112 + juce::String(isAutomatable ? 1 : 0) + ";"
113 + juce::String(isRemoteControllable ? 1 : 0) + ";"
114 + juce::String(static_cast<int>(category)) + ";"
115 + juce::String(minValue) + ";"
116 + juce::String(maxValue) + ";"
117 + juce::String(stepSize) + ";"
118 + juce::String(isDiscrete ? 1 : 0) + ";"
119 + juce::String(int(type)) + ";"
120 + juce::String(stepCount) + ";"
121 + [&]() {
122 juce::StringArray sa;
123 for (const auto& s : stepNames)
124 sa.add(s);
125 return sa.joinIntoString(",");
126 }();
127 }
128 bool initializeFromString(const juce::String& parameterString)
129 {
130 juce::StringArray parameterStringArray;
131 auto paramCnt = parameterStringArray.addTokens(parameterString, ";", "");
132 if (16 == paramCnt)
133 {
134 index = parameterStringArray[0].getIntValue();
135 id = parameterStringArray[1];
136 name = parameterStringArray[2];
137 defaultValue = parameterStringArray[3].getFloatValue();
138 currentValue = parameterStringArray[4].getFloatValue();
139 label = parameterStringArray[5];
140 isAutomatable = parameterStringArray[6].getIntValue() == 1 ? true : false;
141 isRemoteControllable = parameterStringArray[7].getIntValue() == 1 ? true : false;
142 category = static_cast<juce::AudioProcessorParameter::Category>(parameterStringArray[8].getIntValue());
143 minValue = parameterStringArray[9].getFloatValue();
144 maxValue = parameterStringArray[10].getFloatValue();
145 stepSize = parameterStringArray[11].getFloatValue();
146 isDiscrete = parameterStringArray[12].getIntValue() == 1 ? true : false;
147 type = static_cast<ParameterControlType>(parameterStringArray[13].getIntValue());
148 stepCount = parameterStringArray[14].getIntValue();
149
150 juce::StringArray stepNamesArray;
151 stepNamesArray.addTokens(parameterStringArray[15], ",", "");
152 for (auto const& stepName : stepNamesArray)
153 stepNames.push_back(stepName.toStdString());
154 jassert(stepCount == stepNames.size());
155
156 return true;
157 }
158
159 return false;
160 }
161 static PluginParameterInfo fromString(const juce::String& parameterString)
162 {
163 PluginParameterInfo parameterInfo;
164 auto success = parameterInfo.initializeFromString(parameterString);
165 jassert(success);
166 return parameterInfo;
167 };
168 bool initializeFromAudioProcessorParameter(juce::AudioProcessorParameter& processorParameter)
169 {
170 index = processorParameter.getParameterIndex();
171 name = processorParameter.getName(100);
172 label = processorParameter.getLabel();
173 defaultValue = processorParameter.getDefaultValue();
174 currentValue = processorParameter.getValue();
175 isAutomatable = processorParameter.isAutomatable();
176 isRemoteControllable = false;
177 category = processorParameter.getCategory();
178
179 if (auto* paramWithID = dynamic_cast<juce::AudioProcessorParameterWithID*>(&processorParameter))
180 {
181 id = paramWithID->paramID;
182 }
183 else
184 {
185 id = "param_" + juce::String(index);
186 }
187
188 if (auto* rangedParam = dynamic_cast<juce::RangedAudioParameter*>(&processorParameter))
189 {
190 auto range = rangedParam->getNormalisableRange();
191 minValue = range.start;
192 maxValue = range.end;
193 stepSize = range.interval;
194 isDiscrete = range.interval > 0.0f;
195 }
196 else
197 {
198 minValue = 0.0f;
199 maxValue = 1.0f;
200 stepSize = 0.0f;
201 isDiscrete = false;
202 }
203
204 return true;
205 }
206 static PluginParameterInfo fromAudioProcessorParameter(juce::AudioProcessorParameter& processorParameter)
207 {
208 PluginParameterInfo parameterInfo;
209 auto success = parameterInfo.initializeFromAudioProcessorParameter(processorParameter);
210 jassert(success);
211 return parameterInfo;
212 };
213
214 static std::vector<PluginParameterInfo> parametersToInfos(juce::Array<juce::AudioProcessorParameter*> processorParameters)
215 {
216 std::vector<PluginParameterInfo> infos(processorParameters.size());
217 for (auto param : processorParameters)
218 infos.push_back(fromAudioProcessorParameter(*param));
219 return infos;
220 };
221};
222
223} // namespace Mema
Definition Mema.cpp:27
Metadata describing a single plugin parameter exposed for remote control.
std::vector< std::string > stepNames
Display names for each discrete step.
bool operator==(const PluginParameterInfo &other) const
bool operator<(const PluginParameterInfo &other) const
juce::String name
Human-readable parameter name.
bool isRemoteControllable
Whether this parameter is exposed for remote control.
int stepCount
Number of discrete steps (0 if continuous).
bool initializeFromString(const juce::String &parameterString)
bool isAutomatable
Whether the host can automate this parameter.
int index
Zero-based parameter index within the plugin.
ParameterControlType type
Control widget type (slider, combo, toggle).
static PluginParameterInfo fromString(const juce::String &parameterString)
bool initializeFromAudioProcessorParameter(juce::AudioProcessorParameter &processorParameter)
float defaultValue
Factory default value (normalised 0..1).
juce::String id
Unique string identifier of the parameter.
bool operator>(const PluginParameterInfo &other) const
bool operator>=(const PluginParameterInfo &other) const
float stepSize
Step interval for discrete parameters (0 = continuous).
static PluginParameterInfo fromAudioProcessorParameter(juce::AudioProcessorParameter &processorParameter)
float minValue
Minimum value in the parameter's native range.
float currentValue
Current parameter value (normalised 0..1).
float maxValue
Maximum value in the parameter's native range.
bool isDiscrete
True if the parameter has a finite set of steps.
static std::vector< PluginParameterInfo > parametersToInfos(juce::Array< juce::AudioProcessorParameter * > processorParameters)
juce::AudioProcessorParameter::Category category
JUCE parameter category.
bool operator!=(const PluginParameterInfo &other) const
bool operator<=(const PluginParameterInfo &other) const
juce::String label
Unit label (e.g. "dB", "Hz").