parameter.cpp (7826B)
1 #include "parameter.h" 2 3 #include "controller.h" 4 5 namespace pluginLib 6 { 7 Parameter::Parameter(Controller& _controller, const Description& _desc, const uint8_t _partNum, const int _uniqueId, const PartFormatter& _partFormatter) 8 : juce::RangedAudioParameter(genId(_desc, _partNum, _uniqueId), _partFormatter(_partNum, _desc.isNonPartSensitive()) + " " + _desc.displayName) 9 , m_controller(_controller) 10 , m_desc(_desc) 11 , m_part(_partNum) 12 , m_uniqueId(_uniqueId) 13 { 14 m_range.start = static_cast<float>(m_desc.range.getStart()); 15 m_range.end = static_cast<float>(m_desc.range.getEnd()); 16 m_range.interval = m_desc.step ? static_cast<float>(m_desc.step) : (m_desc.isDiscrete || m_desc.isBool ? 1.0f : 0.0f); 17 18 m_value.setValue(m_range.start); 19 m_value.addListener(this); 20 } 21 22 void Parameter::valueChanged(juce::Value&) 23 { 24 sendToSynth(); 25 onValueChanged(this); 26 } 27 28 void Parameter::setDerivedValue(const int _value) 29 { 30 const int newValue = clampValue(_value); 31 32 if (newValue == m_lastValue) 33 return; 34 35 m_lastValue = newValue; 36 m_lastValueOrigin = Origin::Derived; 37 38 m_value.setValue(newValue); 39 } 40 41 void Parameter::sendToSynth() 42 { 43 const float floatValue = m_value.getValue(); 44 const auto value = juce::roundToInt(floatValue); 45 46 jassert(m_range.getRange().contains(floatValue) || m_range.end == floatValue); 47 48 if (value == m_lastValue) 49 return; 50 51 // ignore initial update 52 if (m_lastValue != -1) 53 { 54 if(m_rateLimit) 55 { 56 sendParameterChangeDelayed(value, ++m_uniqueDelayCallbackId); 57 } 58 else 59 { 60 m_lastSendTime = milliseconds(); 61 m_controller.sendParameterChange(*this, value); 62 } 63 } 64 65 m_lastValue = value; 66 } 67 68 uint64_t Parameter::milliseconds() 69 { 70 const auto t = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()); 71 return t.count(); 72 } 73 74 void Parameter::sendParameterChangeDelayed(const ParamValue _value, uint32_t _uniqueId) 75 { 76 if(_uniqueId != m_uniqueDelayCallbackId) 77 return; 78 79 const auto ms = milliseconds(); 80 81 const auto elapsed = ms - m_lastSendTime; 82 if(elapsed >= m_rateLimit) 83 { 84 m_lastSendTime = ms; 85 m_controller.sendParameterChange(*this, _value); 86 } 87 else 88 { 89 juce::Timer::callAfterDelay(static_cast<int>(elapsed), [this, _value, _uniqueId] 90 { 91 sendParameterChangeDelayed(_value, _uniqueId); 92 }); 93 } 94 } 95 96 int Parameter::clampValue(const int _value) const 97 { 98 return juce::roundToInt(m_range.getRange().clipValue(static_cast<float>(_value))); 99 } 100 101 void Parameter::setValueNotifyingHost(const float _value, const Origin _origin) 102 { 103 ScopedChangeGesture g(*this); 104 setUnnormalizedValue(juce::roundToInt(convertFrom0to1(_value)), _origin); 105 notifyHost(_value); 106 } 107 108 void Parameter::setUnnormalizedValueNotifyingHost(const float _value, const Origin _origin) 109 { 110 ScopedChangeGesture g(*this); 111 setUnnormalizedValue(juce::roundToInt(_value), _origin); 112 notifyHost(convertTo0to1(_value)); 113 } 114 115 void Parameter::setUnnormalizedValueNotifyingHost(const int _value, const Origin _origin) 116 { 117 ScopedChangeGesture g(*this); 118 setUnnormalizedValue(_value, _origin); 119 notifyHost(convertTo0to1(static_cast<float>(_value))); 120 } 121 122 void Parameter::setRateLimitMilliseconds(const uint32_t _ms) 123 { 124 m_rateLimit = _ms; 125 } 126 127 void Parameter::setLinkState(const ParameterLinkType _type) 128 { 129 const auto prev = m_linkType; 130 m_linkType = static_cast<ParameterLinkType>(m_linkType | _type); 131 if(m_linkType != prev) 132 onLinkStateChanged(this, m_linkType); 133 } 134 135 void Parameter::clearLinkState(const ParameterLinkType _type) 136 { 137 const auto prev = m_linkType; 138 m_linkType = static_cast<ParameterLinkType>(m_linkType & ~_type); 139 if(m_linkType != prev) 140 onLinkStateChanged(this, m_linkType); 141 } 142 143 void Parameter::pushChangeGesture() 144 { 145 if(!m_changeGestureCount) 146 beginChangeGesture(); 147 ++m_changeGestureCount; 148 } 149 150 void Parameter::popChangeGesture() 151 { 152 assert(m_changeGestureCount > 0); 153 --m_changeGestureCount; 154 if(!m_changeGestureCount) 155 endChangeGesture(); 156 } 157 158 bool Parameter::isMetaParameter() const 159 { 160 return !m_derivedParameters.empty(); 161 } 162 163 void Parameter::setValue(const float _newValue) 164 { 165 // some plugin formats (VST3 for example) bounce back immediately, skip this, we don't 166 // want it and VST2 doesn't do it either so why does Juce for VST3? 167 // It's not the host, it's the Juce VST3 implementation 168 if(m_notifyingHost) 169 return; 170 171 setUnnormalizedValue(juce::roundToInt(convertFrom0to1(_newValue)), Origin::HostAutomation); 172 } 173 174 void Parameter::setUnnormalizedValue(const int _newValue, const Origin _origin) 175 { 176 if (m_changingDerivedValues) 177 return; 178 179 m_lastValueOrigin = _origin; 180 m_value.setValue(clampValue(_newValue)); 181 182 if(_origin != Origin::Derived) 183 sendToSynth(); 184 185 forwardToDerived(_newValue); 186 } 187 188 void Parameter::setValueFromSynth(const int _newValue, const Origin _origin) 189 { 190 const auto clampedValue = clampValue(_newValue); 191 192 // we do not want to send an excessive amount of value changes to the host if a preset is 193 // changed, we use updateHostDisplay() (see caller) to inform the host to read all 194 // parameters again instead 195 const auto notifyHost = _origin != Origin::PresetChange; 196 197 if (clampedValue != m_lastValue) 198 { 199 m_lastValue = clampedValue; 200 m_lastValueOrigin = _origin; 201 202 if (notifyHost && getDescription().isPublic) 203 { 204 setUnnormalizedValueNotifyingHost(clampedValue, _origin); 205 } 206 else 207 { 208 m_value.setValue(clampedValue); 209 } 210 } 211 212 forwardToDerived(_newValue); 213 } 214 215 void Parameter::forwardToDerived(const int _newValue) 216 { 217 if (m_changingDerivedValues) 218 return; 219 220 m_changingDerivedValues = true; 221 222 for (const auto& p : m_derivedParameters) 223 p->setDerivedValue(_newValue); 224 225 m_changingDerivedValues = false; 226 } 227 228 void Parameter::notifyHost(const float _value) 229 { 230 m_notifyingHost = true; 231 sendValueChangedMessageToListeners(_value); 232 m_notifyingHost = false; 233 } 234 235 juce::String Parameter::genId(const Description& d, const int part, const int uniqueId) 236 { 237 if(uniqueId > 0) 238 return juce::String::formatted("%d_%d_%d_%d", static_cast<int>(d.page), part, d.index, uniqueId); 239 return juce::String::formatted("%d_%d_%d", static_cast<int>(d.page), part, d.index); 240 } 241 242 float Parameter::getValueForText(const juce::String& _text) const 243 { 244 auto res = m_desc.valueList.textToValue(std::string(_text.getCharPointer())); 245 if(m_desc.range.getStart() < 0) 246 res += m_desc.range.getStart(); 247 return convertTo0to1(static_cast<float>(res)); 248 } 249 250 ParamValue Parameter::getDefault() const 251 { 252 if(m_desc.defaultValue != Description::NoDefaultValue) 253 return m_desc.defaultValue; 254 return 0; 255 } 256 257 juce::String Parameter::getText(const float _normalisedValue, int _i) const 258 { 259 const auto v = convertFrom0to1(_normalisedValue); 260 return m_desc.valueList.valueToText(juce::roundToInt(v) - std::min(0, m_desc.range.getStart())); 261 } 262 263 void Parameter::setLocked(const bool _locked) 264 { 265 if(m_isLocked == _locked) 266 return; 267 268 m_isLocked = _locked; 269 270 onLockedChanged(this, m_isLocked); 271 } 272 273 void Parameter::addDerivedParameter(Parameter* _param) 274 { 275 if (_param == this) 276 return; 277 278 for (auto* p : m_derivedParameters) 279 { 280 _param->m_derivedParameters.insert(p); 281 p->m_derivedParameters.insert(_param); 282 } 283 284 m_derivedParameters.insert(_param); 285 _param->m_derivedParameters.insert(this); 286 } 287 288 Parameter::ScopedChangeGesture::ScopedChangeGesture(Parameter& _p) : m_parameter(_p) 289 { 290 if(_p.getDescription().isPublic) 291 _p.pushChangeGesture(); 292 } 293 294 Parameter::ScopedChangeGesture::~ScopedChangeGesture() 295 { 296 if(m_parameter.getDescription().isPublic) 297 m_parameter.popChangeGesture(); 298 } 299 300 }