// async_attach.cpp #include "async_attach.h" AsyncAttachmentSource::AsyncAttachmentSource (juce::AudioProcessorValueTreeState& state, const juce::String& id) : state_{ state }, paramID_{ id } { state.addParameterListener (id, this); lastValue_ = *state.getRawParameterValue (id); } void AsyncAttachmentSource::confirmValue (float value, bool setParameter) { lastValue_ = value; juce::ScopedValueSetter svs{ ignoreCallbacks_, true }; if (setParameter) if (auto p{ parameter() }) p->setValueNotifyingHost (p->convertTo0to1 (value)); for (auto att : attachments_) att->setLastValue(); } void AsyncAttachmentSource::confirmGesture (bool starting) { if (auto p{ parameter() }) { if (starting) { if (state_.undoManager) state_.undoManager->beginNewTransaction(); p->beginChangeGesture(); } else p->endChangeGesture(); } } void AsyncAttachmentSource::parameterChanged (const juce::String&, float value) { if (juce::MessageManager::getInstance()->isThisTheMessageThread() && ignoreCallbacks_) return; if (notifyValue) notifyValue (value, false); } AsyncAttachment::~AsyncAttachment() { auto& atts{ source.attachments_ }; atts.erase (std::remove (atts.begin(), atts.end(), this), atts.end()); } void AsyncAttachment::valueChanged (float newValue) { if (source.ignoreCallbacks_) return; { juce::ScopedValueSetter svs{ source.ignoreCallbacks_, true }; setLastValue(); } if (source.notifyValue) source.notifyValue (newValue, true); } AsyncSliderAttachment::AsyncSliderAttachment (AsyncAttachmentSource& src, juce::Slider& slider) : AsyncAttachment{ src }, slider_{ slider } { if (auto param{ src.parameter() }) { slider.valueFromTextFunction = [=](const juce::String& text) { return double (param->convertFrom0to1 (param->getValueForText (text))); }; slider.textFromValueFunction = [=](double value) { return param->getText (param->convertTo0to1 (float (value)), 0); }; slider.setDoubleClickReturnValue (true, param->convertFrom0to1 (param->getDefaultValue())); auto range{ param->getNormalisableRange() }; auto convertFrom0To1 = [=](double start, double end, double value) mutable { range.start = float (start); range.end = float (end); return double (range.convertFrom0to1 (float (value))); }; auto convertTo0To1 = [=](double start, double end, double value) mutable { range.start = float (start); range.end = float (end); return double (range.convertTo0to1 (float (value))); }; auto snapToLegalValue = [=](double start, double end, double value) mutable { range.start = float (start); range.end = float (end); return double (range.snapToLegalValue (float (value))); }; juce::NormalisableRange newRange{ range.start, range.end, std::move (convertFrom0To1), std::move (convertTo0To1), std::move (snapToLegalValue) }; newRange.interval = range.interval; newRange.skew = range.skew; newRange.symmetricSkew = range.symmetricSkew; slider.setNormalisableRange (newRange); } setLastValue(); slider.addListener (this); }