Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
parameter_binding.hpp
Go to the documentation of this file.
1#pragma once
2
40
41#include <optional>
43#include <pulp/state/store.hpp>
44#include <pulp/view/design_frame_view.hpp> // DesignStepper
45#include <pulp/view/ui_components.hpp> // ComboBox
46#include <pulp/view/widgets.hpp>
47#include <utility>
48
49namespace pulp::view {
50
54public:
55 ParameterBinding() = default;
56 explicit ParameterBinding(state::ListenerToken token) : token_(std::move(token)) {}
58 : token_(std::move(token)), watch_(std::move(watch)) {}
59
62 : token_(std::move(token)), watch_(std::move(watch)),
63 second_watch_(std::move(second_watch)) {}
64 ParameterBinding(ParameterBinding&&) noexcept = default;
65 ParameterBinding& operator=(ParameterBinding&&) noexcept = default;
67 ParameterBinding& operator=(const ParameterBinding&) = delete;
68
69private:
70 state::ListenerToken token_;
71 state::StateStore::ModulationWatch watch_;
72 state::StateStore::ModulationWatch second_watch_;
73};
74
75namespace detail {
82template <typename Control>
85 return store.watch_modulation(id, [&control](std::optional<float> played) {
86 if (played)
87 control.set_modulated_value(*played);
88 else
89 control.clear_modulated_value();
90 });
91}
92} // namespace detail
93
95[[nodiscard]] inline ParameterBinding
97 knob.set_value(store.get_normalized(id));
98 knob.on_gesture_begin = [&store, id] { store.begin_gesture(id); };
99 knob.on_change = [&store, id](float v) { store.set_normalized(id, v); };
100 knob.on_gesture_end = [&store, id] { store.end_gesture(id); };
101 return ParameterBinding(store.add_listener(
102 [&knob, &store, id](state::ParamID changed, float) {
103 if (changed == id)
104 knob.set_value(store.get_normalized(id));
105 },
109}
110
112[[nodiscard]] inline ParameterBinding
114 fader.set_value(store.get_normalized(id));
115 fader.on_gesture_begin = [&store, id] { store.begin_gesture(id); };
116 fader.on_change = [&store, id](float v) { store.set_normalized(id, v); };
117 fader.on_gesture_end = [&store, id] { store.end_gesture(id); };
118 return ParameterBinding(store.add_listener(
119 [&fader, &store, id](state::ParamID changed, float) {
120 if (changed == id)
121 fader.set_value(store.get_normalized(id));
122 },
126}
127
129[[nodiscard]] inline ParameterBinding
131 pad.on_gesture_begin = [&store, x_id, y_id] {
132 store.begin_gesture(x_id);
133 store.begin_gesture(y_id);
134 };
135 pad.on_change = [&store, x_id, y_id](float x, float y) {
136 store.set_normalized(x_id, x);
137 store.set_normalized(y_id, y);
138 };
139 pad.on_gesture_end = [&store, x_id, y_id] {
140 store.end_gesture(x_id);
141 store.end_gesture(y_id);
142 };
143 pad.set_x(store.get_normalized(x_id));
144 pad.set_y(store.get_normalized(y_id));
145 return ParameterBinding(store.add_listener(
146 [&pad, &store, x_id, y_id](state::ParamID changed, float) {
147 if (changed == x_id)
148 pad.set_x(store.get_normalized(x_id));
149 if (changed == y_id)
150 pad.set_y(store.get_normalized(y_id));
151 },
154 store.watch_modulation(x_id,
155 [&pad](std::optional<float> played) {
156 if (played)
157 pad.set_modulated_x(*played);
158 else
159 pad.clear_modulated_x();
160 }),
161 store.watch_modulation(y_id, [&pad](std::optional<float> played) {
162 if (played)
163 pad.set_modulated_y(*played);
164 else
165 pad.clear_modulated_y();
166 }));
167}
168
170[[nodiscard]] inline ParameterBinding
172 // Synced FROM the parameter without notifying, so playback never echoes
173 // a write back into the store.
174 slider.set_value(store.get_normalized(id), Notify::none);
175 slider.on_gesture_begin = [&store, id] { store.begin_gesture(id); };
176 slider.on_change = [&store, id](float v) { store.set_normalized(id, v); };
177 slider.on_gesture_end = [&store, id] { store.end_gesture(id); };
178 return ParameterBinding(store.add_listener(
179 [&slider, &store, id](state::ParamID changed, float) {
180 if (changed == id)
181 slider.set_value(store.get_normalized(id), Notify::none);
182 },
185 detail::watch_modulated_display(slider, store, id));
186}
187
191[[nodiscard]] inline ParameterBinding
193 combo.set_selected_silent(static_cast<int>(store.get_value(id)));
194 combo.on_change = [&store, id](int index) {
195 store.begin_gesture(id);
196 store.set_value(id, static_cast<float>(index));
197 store.end_gesture(id);
198 };
199 return ParameterBinding(store.add_listener(
200 [&combo, &store, id](state::ParamID changed, float) {
201 if (changed == id) combo.set_selected_silent(static_cast<int>(store.get_value(id)));
202 },
205}
206
210[[nodiscard]] inline ParameterBinding
212 stepper.set_selected_silent(static_cast<int>(store.get_value(id)));
213 stepper.on_select = [&store, id](int index) {
214 store.begin_gesture(id);
215 store.set_value(id, static_cast<float>(index));
216 store.end_gesture(id);
217 };
218 return ParameterBinding(store.add_listener(
219 [&stepper, &store, id](state::ParamID changed, float) {
220 if (changed == id) stepper.set_selected_silent(static_cast<int>(store.get_value(id)));
221 },
224}
225
227[[nodiscard]] inline ParameterBinding
229 toggle.set_on(store.get_value(id) >= 0.5f);
230 toggle.on_toggle = [&store, id](bool on) {
231 store.begin_gesture(id);
232 store.set_value(id, on ? 1.0f : 0.0f);
233 store.end_gesture(id);
234 };
235 return ParameterBinding(store.add_listener(
236 [&toggle, &store, id](state::ParamID changed, float) {
237 if (changed == id) toggle.set_on(store.get_value(id) >= 0.5f);
238 },
241}
242
244[[nodiscard]] inline ParameterBinding
246 box.set_checked(store.get_value(id) >= 0.5f);
247 box.on_change = [&store, id](bool on) {
248 store.begin_gesture(id);
249 store.set_value(id, on ? 1.0f : 0.0f);
250 store.end_gesture(id);
251 };
252 return ParameterBinding(store.add_listener(
253 [&box, &store, id](state::ParamID changed, float) {
254 if (changed == id) box.set_checked(store.get_value(id) >= 0.5f);
255 },
258}
259
262[[nodiscard]] inline ParameterBinding
264 button.set_on(store.get_value(id) >= 0.5f);
265 button.on_toggle = [&store, id](bool on) {
266 store.begin_gesture(id);
267 store.set_value(id, on ? 1.0f : 0.0f);
268 store.end_gesture(id);
269 };
270 return ParameterBinding(store.add_listener(
271 [&button, &store, id](state::ParamID changed, float) {
272 if (changed == id) button.set_on(store.get_value(id) >= 0.5f);
273 },
276}
277
278} // namespace pulp::view
RAII handle for a registered parameter-change listener.
Definition listener_token.hpp:47
RAII handle for watch_modulation(). Move-only; dropping it unwatches.
Definition store.hpp:742
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
float get_value(ParamID id) const
Read a parameter's base value (lock-free).
Definition store.hpp:186
ModulationWatch watch_modulation(ParamID id, std::function< void(std::optional< float >)> on_change)
Call on_change on the main thread, from pump_listeners(), whenever displayed_modulation(id) changes (...
void set_value(ParamID id, float value)
Write a parameter's base value (lock-free).
void set_normalized(ParamID id, float normalized)
Write a parameter from a normalized [0, 1] value (lock-free).
float get_normalized(ParamID id) const
Read a parameter's value mapped to [0, 1] (lock-free).
void end_gesture(ParamID id)
Signal the host that the current gesture has ended.
ListenerToken add_listener(ParamChangeCallback callback, ListenerThread thread)
Subscribe to parameter-value changes.
void begin_gesture(ParamID id)
Signal the host that a gesture (drag, click) has begun on a parameter.
Definition widgets.hpp:2111
std::function< void(bool)> on_change
Definition widgets.hpp:2262
void set_checked(bool v)
Definition widgets.hpp:2127
Drop-down selector for enumerated parameters.
Definition ui_components.hpp:43
std::function< void(int index)> on_change
Called when selection changes.
Definition ui_components.hpp:93
void set_selected_silent(int index)
Definition design_frame_view.hpp:1077
Definition widgets.hpp:1337
Definition widgets.hpp:901
ParameterBinding(state::ListenerToken token)
Definition parameter_binding.hpp:56
ParameterBinding(state::ListenerToken token, state::StateStore::ModulationWatch watch, state::StateStore::ModulationWatch second_watch)
A two-parameter control (XY pad): one watch per axis.
Definition parameter_binding.hpp:60
ParameterBinding(state::ListenerToken token, state::StateStore::ModulationWatch watch)
Definition parameter_binding.hpp:57
ParameterBinding(ParameterBinding &&) noexcept=default
Definition widgets.hpp:1750
std::function< void()> on_gesture_begin
Fired when an interactive drag begins / ends, so a binding can bracket the edit in a host automation ...
Definition widgets.hpp:1976
void set_value(float v, Notify notify=Notify::sync)
Set the current value.
Definition widgets.hpp:1818
std::function< void(float)> on_change
Fired when the value changes — from drag, click, or set_value().
Definition widgets.hpp:1972
std::function< void()> on_gesture_end
Definition widgets.hpp:1977
Definition widgets.hpp:2383
void set_on(bool v)
Definition widgets.hpp:2393
std::function< void(bool)> on_toggle
Definition widgets.hpp:2462
Definition widgets.hpp:2036
Definition widgets.hpp:2599
void set_y(float v)
Definition widgets.hpp:2604
void set_x(float v)
Definition widgets.hpp:2603
std::function< void(float, float)> on_change
Definition widgets.hpp:2640
std::function< void()> on_gesture_end
Definition widgets.hpp:2642
std::function< void()> on_gesture_begin
Definition widgets.hpp:2641
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
@ Main
Definition listener_token.hpp:24
@ Reconcile
Definition listener_token.hpp:36
uint32_t ParamID
Unique parameter identifier, stable across plugin versions.
Definition parameter.hpp:55
Definition accessibility_provider.hpp:65
state::StateStore::ModulationWatch watch_modulated_display(Control &control, state::StateStore &store, state::ParamID id)
The modulated-value half of a binding: whatever modulates the parameter – a host's CLAP modulation,...
Definition parameter_binding.hpp:84
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
@ fader
Definition design_ir.hpp:261
@ toggle
Definition design_ir.hpp:272
@ stepper
Definition design_ir.hpp:281
@ knob
Definition design_ir.hpp:260
ParameterBinding bind_parameter(Knob &knob, state::StateStore &store, state::ParamID id)
Knob ↔ parameter (normalized).
Definition parameter_binding.hpp:96
@ none
change the value silently
Definition slider_core.hpp:61
@ y
Definition input_events.hpp:42
@ x
Definition input_events.hpp:41
@ v
Definition input_events.hpp:41
@ changed
Definition gesture.hpp:17
@ on
Definition accessibility.hpp:132
STL namespace.
Additional UI components: ComboBox, Tooltip, ProgressBar, CallOutBox, TabPanel, ListBox,...