Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
store.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cstdint>
6#include <functional>
7#include <memory>
8#include <mutex>
9#include <optional>
13#include <span>
14#include <unordered_map>
15#include <unordered_set>
16#include <utility>
17#include <vector>
18
19namespace pulp::events { class EventLoop; }
20
21namespace pulp::state {
22
27struct ParamGroup {
28 int id = 0;
29 std::string name;
30 int parent_id = 0;
31};
32
35 std::size_t size_approx = 0;
36 std::size_t capacity = 0;
37 std::uint64_t overflow_count = 0;
38};
39
49
54
55class StateStore;
56namespace test_support {
57struct StateWriterProbe;
58}
59
64 public:
66
67 bool valid() const noexcept {
68 return valid_;
69 }
70
71 ParamID id() const noexcept {
72 return id_;
73 }
74 std::uint64_t packed_identity() const noexcept {
75 return packed_identity_;
76 }
77
78 private:
79 friend class StateStore;
80 ParameterFeedbackBaseline(const StateStore* owner, ParamID id, std::uint64_t packed_identity)
81 : owner_(owner), id_(id), packed_identity_(packed_identity), valid_(true) {}
82
83 const StateStore* owner_ = nullptr;
84 ParamID id_ = 0;
85 std::uint64_t packed_identity_ = 0;
86 bool valid_ = false;
87};
88
94
99
125 public:
126 ParamReader() = default;
127
131 float get() const noexcept;
132
134 bool valid() const noexcept {
135 return store_ != nullptr;
136 }
137
138 private:
139 friend class StateStore;
140 ParamReader(const StateStore* store, std::size_t index) noexcept
141 : store_(store), index_(index) {}
142
143 const StateStore* store_ = nullptr;
144 std::size_t index_ = 0;
145};
146
165 // Tests drive a writer through its phases one at a time to reproduce
166 // reader/writer interleavings deterministically.
168
169 public:
172
173 StateStore(const StateStore&) = delete;
174 StateStore& operator=(const StateStore&) = delete;
175
179
181 void add_group(const ParamGroup& group);
182
186 [[gnu::always_inline]] float get_value(ParamID id) const {
187 const std::size_t i = index_of(id);
188 return i == kNoIndex ? 0.0f : values_[i].get();
189 }
190
196
199 float get_modulated(ParamID id) const;
200
203
206 void set_value(ParamID id, float value);
207
227 void set_value_rt(ParamID id, float value);
228
230 struct ParamWrite {
231 ParamID id = 0;
232 float value = 0.0f;
233 };
234
244 void set_values_rt(std::span<const ParamWrite> writes);
245
250 void set_normalized_rt(ParamID id, float normalized);
251
254 std::optional<ParameterFeedbackBaseline> capture_feedback_baseline(ParamID id) const noexcept;
255
264
266 void set_mod_offset(ParamID id, float offset);
267
269 void add_mod_offset(ParamID id, float delta);
270
273
274 // ── Modulated value for display ─────────────────────────────────────
275 //
276 // A control bound to a parameter shows two things: the BASE (what the
277 // user set or host automation plays; what gestures edit and the host
278 // records) and, when something modulates the parameter, the value
279 // PLAYING. Two sources feed the second, and neither is ever a host
280 // automation write:
281 //
282 // * host modulation -- a CLAP host's parameter modulation, which the
283 // adapter writes as the mod offset (set_mod_offset). Shown by every
284 // bound control with no plugin code.
285 // * the plugin's own modulation (an internal LFO) -- opt-in: the
286 // plugin publishes the value its DSP plays with
287 // set_display_modulation(), from any thread, real-time safe.
288 //
289 // A published display value wins over the host offset; nothing published
290 // and a zero offset means nothing is shown.
291
294 void set_display_modulation(ParamID id, float plain_value) noexcept;
299 std::optional<float> displayed_modulation(ParamID id) const noexcept;
300
301 class ModulationWatch;
305 [[nodiscard]] ModulationWatch
306 watch_modulation(ParamID id, std::function<void(std::optional<float>)> on_change);
307
309 float get_normalized(ParamID id) const;
310
312 void set_normalized(ParamID id, float normalized);
313
320 std::uint64_t state_generation() const noexcept {
321 return state_generation_.load(std::memory_order_acquire);
322 }
323
330 bool state_snapshot_is_current(std::uint64_t generation) const noexcept {
331 return active_state_writers_.load(std::memory_order_acquire) == 0 &&
332 state_generation() == generation;
333 }
334
343 std::uint64_t expected_generation, ParamID id, float normalized);
344
346 float get_default(ParamID id) const;
347
350
353
369
372 bool has_trigger_params() const { return !trigger_indices_.empty(); }
373
376 const ParamInfo* info(ParamID id) const;
377
391 bool set_parameter_display_name(ParamID id, std::string name);
392
397 std::string parameter_display_name(ParamID id) const;
398
400 std::uint64_t parameter_display_revision() const noexcept {
401 return parameter_display_revision_.load(std::memory_order_acquire);
402 }
403
426 template <std::size_t N>
427 [[nodiscard]] std::array<float, N> snapshot(
428 const std::array<ParamID, N>& ids) const noexcept;
429
434 template <std::size_t N>
435 [[nodiscard]] std::array<float, N> snapshot_modulated(
436 const std::array<ParamID, N>& ids) const noexcept;
437
439 std::span<const ParamInfo> all_params() const { return params_; }
440
442 std::span<const ParamGroup> all_groups() const { return groups_; }
443
445 std::size_t param_count() const { return params_.size(); }
446
462
466
477
490
493 std::size_t open_gesture_count() const noexcept { return open_gestures_.size(); }
494
507 void run_gesture_on_main(std::function<void()> gesture);
508
514 std::uint64_t gesture_thread_violation_count() const {
515 return gesture_thread_violations_.load(std::memory_order_relaxed);
516 }
517
525
556 [[nodiscard]]
558 ListenerThread thread);
559
561 [[nodiscard]]
563 ListenerThread thread,
564 ListenerRestoreBehavior restore_behavior);
565
568 [[nodiscard]]
570
574
581 std::size_t pump_listeners();
582
602
606
610
620
626 std::vector<uint8_t> serialize() const;
627
633 bool deserialize(std::span<const uint8_t> data);
634
650 std::uint64_t state_restore_revision() const noexcept {
651 return state_restore_revision_.load(std::memory_order_acquire);
652 }
653
656 void set_state_version(uint32_t version) { state_version_ = version; }
657
659 uint32_t state_version() const { return state_version_; }
660
666 bool register_state_migration(uint32_t from_version,
667 uint32_t to_version,
669
674
675 private:
676 friend class ParamReader;
677
679 float value_at_index_(std::size_t index) const noexcept {
680 return values_[index].get();
681 }
682
683 // Member ORDER is load-bearing for the RT->main listener path. The
684 // parameter storage (id_to_index_ + values_) MUST be declared before
685 // registry_ so that, on destruction (reverse declaration order),
686 // registry_ is torn down FIRST. registry_'s value_getter captures
687 // `this` and reads id_to_index_/values_ during drain_main_listeners;
688 // destroying registry_ before that storage guarantees the getter can
689 // never run after the storage it reads is gone. Do not reorder.
690 std::vector<ParamInfo> params_;
691 std::vector<ParamGroup> groups_;
692 std::unordered_map<ParamID, std::size_t> id_to_index_;
693 std::vector<ParamValue> values_;
694 // Direct ParamID -> index table for the audio-thread readers and writers.
695 // Parameter IDs are almost always small integers, so a vector beats a hash
696 // lookup. Every ID below kDenseIndexLimit is in the table; only IDs at or
697 // above it (a four-char code, an adapter's synthesized Bypass) are looked
698 // up in the map, so one such ID does not slow every other lookup.
699 static constexpr ParamID kDenseIndexLimit = 1u << 14;
700 static constexpr std::uint32_t kNoDenseIndex = 0xFFFF'FFFFu;
701 std::vector<std::uint32_t> dense_index_;
702 bool has_sparse_ids_ = false;
703 static constexpr std::size_t kNoIndex = static_cast<std::size_t>(-1);
704 // The dense-table hit is the whole inline path; the hash-map fallback is
705 // out of line so get_value() stays small enough to inline into a
706 // processor's per-block parameter reads.
707 [[gnu::always_inline]] std::size_t index_of(ParamID id) const noexcept {
708 if (id < dense_index_.size()) {
709 const std::uint32_t i = dense_index_[id];
710 return i == kNoDenseIndex ? kNoIndex : i;
711 }
712 return id >= kDenseIndexLimit && has_sparse_ids_ ? index_of_sparse(id) : kNoIndex;
713 }
714 [[gnu::noinline]] std::size_t index_of_sparse(ParamID id) const noexcept;
715 using ParameterDisplayNames =
716 std::unordered_map<ParamID, std::string>;
717 mutable std::mutex parameter_display_mutex_;
718 std::shared_ptr<const ParameterDisplayNames> parameter_display_names_;
719 std::atomic<std::uint64_t> parameter_display_revision_{0};
720 std::atomic<std::uint64_t> state_restore_revision_{0};
721 std::atomic<std::uint64_t> reconciled_state_restore_revision_{0};
722 std::atomic<std::uint64_t> state_generation_{0};
723 std::atomic<std::uint32_t> active_state_writers_{0};
724 // Indices (into values_/params_) of trigger / momentary parameters, cached
725 // at registration so reset_triggers_rt() is allocation-free on the audio
726 // thread. Empty for the overwhelmingly common no-trigger store.
727 std::vector<std::size_t> trigger_indices_;
728 std::shared_ptr<detail::ListenerRegistry> registry_;
729
730 public:
732 struct Entry {
733 std::uint64_t id = 0;
735 std::function<void(std::optional<float>)> on_change;
736 std::optional<float> last;
737 };
738 std::vector<Entry> entries;
739 std::uint64_t next_id = 1;
740 };
741
743 public:
744 ModulationWatch() = default;
745 ModulationWatch(std::weak_ptr<ModulationWatchers> owner, std::uint64_t id) noexcept
746 : owner_(std::move(owner)), id_(id) {}
748 : owner_(std::move(other.owner_)), id_(std::exchange(other.id_, 0)) {}
750 if (this != &other) {
751 reset();
752 owner_ = std::move(other.owner_);
753 id_ = std::exchange(other.id_, 0);
754 }
755 return *this;
756 }
760 reset();
761 }
762 void reset() noexcept {
763 if (id_ == 0)
764 return;
765 if (auto owner = owner_.lock()) {
766 auto& e = owner->entries;
767 e.erase(std::remove_if(e.begin(), e.end(),
768 [this](const auto& x) { return x.id == id_; }),
769 e.end());
770 }
771 id_ = 0;
772 }
773 explicit operator bool() const noexcept {
774 return id_ != 0;
775 }
776
777 private:
778 std::weak_ptr<ModulationWatchers> owner_;
779 std::uint64_t id_ = 0;
780 };
781
782 private:
783 std::shared_ptr<ModulationWatchers> modulation_watchers_ =
784 std::make_shared<ModulationWatchers>();
785 void service_modulation_watchers();
786 std::vector<ListenerToken> permanent_listener_tokens_;
787 StateMigrationRegistry migrations_;
788 uint32_t state_version_ = 1;
789
790 std::function<void(ParamID)> on_begin_gesture_;
791 std::function<void(ParamID)> on_end_gesture_;
792
793 // Parameters with an open gesture (begin without a matching end). Keeps
794 // begin/end balanced 1:1 toward the host and lets release_open_gestures()
795 // close everything still held on editor teardown. Main-thread-only, like
796 // the gesture entry points that mutate it.
797 std::unordered_set<ParamID> open_gestures_;
798 // Direct begin/end callers retain the historical duplicate-suppression
799 // contract independently of shared editor leases. open_gestures_ is the
800 // union that is actually open toward the host.
801 std::unordered_set<ParamID> direct_gestures_;
802 std::unordered_map<ParamID, std::size_t> gesture_leases_;
803 std::vector<ParamID> deferred_gesture_releases_;
804
805 // Close a retired owner's pending host bracket before a replacement owner
806 // is allowed to begin the same parameter again.
807 void flush_deferred_gesture_release(ParamID id) noexcept;
808 std::uint64_t advance_state_generation() noexcept;
809
810 // Off-main-thread gesture-misuse counter. Bumped (relaxed) by
811 // begin_gesture/end_gesture when a MainThreadDispatcher backend is live but
812 // the caller is not on the main thread. Observability only — never blocks
813 // the audio path (gestures are main-thread UI events, not audio).
814 std::atomic<std::uint64_t> gesture_thread_violations_{0};
815
816public:
821 std::function<void(ParamID)> begin_fn,
822 std::function<void(ParamID)> end_fn)
823 {
824 on_begin_gesture_ = std::move(begin_fn);
825 on_end_gesture_ = std::move(end_fn);
826 // A new callback set is a new host/editor session: any gesture tracked
827 // against the previous callbacks is stale. Reset so a re-opened editor
828 // (e.g. AU clears callbacks on teardown, then re-installs on reopen)
829 // does not have a lingering entry suppress a fresh begin_gesture.
830 open_gestures_.clear();
831 direct_gestures_.clear();
832 gesture_leases_.clear();
833 deferred_gesture_releases_.clear();
834 }
835};
836
837inline float ParamReader::get() const noexcept {
838 return store_ != nullptr ? store_->value_at_index_(index_) : 0.0f;
839}
840
841// ─── Template definitions ──────────────────────────────────────────────────
842
843template <std::size_t N>
844std::array<float, N> StateStore::snapshot(
845 const std::array<ParamID, N>& ids) const noexcept
846{
847 std::array<float, N> out{};
848 for (std::size_t i = 0; i < N; ++i) {
849 out[i] = get_value(ids[i]);
850 }
851 return out;
852}
853
854template <std::size_t N>
856 const std::array<ParamID, N>& ids) const noexcept
857{
858 std::array<float, N> out{};
859 for (std::size_t i = 0; i < N; ++i) {
860 out[i] = get_modulated(ids[i]);
861 }
862 return out;
863}
864
865} // namespace pulp::state
Definition event_loop.hpp:22
RAII handle for a registered parameter-change listener.
Definition listener_token.hpp:47
friend class StateStore
Definition store.hpp:139
bool valid() const noexcept
True if this handle refers to a registered parameter.
Definition store.hpp:134
float get() const noexcept
Current base value (lock-free, relaxed ordering), or 0.0f if unbound.
Definition store.hpp:837
Opaque exact identity captured when asynchronous work is ordered against a parameter.
Definition store.hpp:63
ParamID id() const noexcept
Definition store.hpp:71
std::uint64_t packed_identity() const noexcept
Definition store.hpp:74
friend class StateStore
Definition store.hpp:79
bool valid() const noexcept
Definition store.hpp:67
Offline migration support for serialized StateStore payloads.
Definition state_migration.hpp:16
std::function< bool(std::span< const uint8_t > source, std::vector< uint8_t > &destination)> MigrationFn
Definition state_migration.hpp:18
RAII handle for watch_modulation(). Move-only; dropping it unwatches.
Definition store.hpp:742
ModulationWatch(std::weak_ptr< ModulationWatchers > owner, std::uint64_t id) noexcept
Definition store.hpp:745
ModulationWatch(ModulationWatch &&other) noexcept
Definition store.hpp:747
ModulationWatch & operator=(const ModulationWatch &)=delete
ModulationWatch & operator=(ModulationWatch &&other) noexcept
Definition store.hpp:749
ModulationWatch(const ModulationWatch &)=delete
~ModulationWatch()
Definition store.hpp:759
void reset() noexcept
Definition store.hpp:762
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
void acquire_gesture(ParamID id)
Acquire/release a shared gesture lease.
StateStore & operator=(const StateStore &)=delete
std::uint64_t state_restore_revision() const noexcept
Monotonic reconciliation edge published after each successful deserialize().
Definition store.hpp:650
std::array< float, N > snapshot(const std::array< ParamID, N > &ids) const noexcept
Block-local snapshot of N parameter values.
Definition store.hpp:844
std::string parameter_display_name(ParamID id) const
Current host-facing name: overlay when present, otherwise ParamInfo::name.
friend struct test_support::StateWriterProbe
Definition store.hpp:167
void defer_gesture_release(ParamID id)
Release a lease without synchronously entering host code.
void set_gesture_callbacks(std::function< void(ParamID)> begin_fn, std::function< void(ParamID)> end_fn)
Install callbacks that forward gesture begin/end to the plugin host.
Definition store.hpp:820
float get_value(ParamID id) const
Read a parameter's base value (lock-free).
Definition store.hpp:186
void add_parameter(const ParamInfo &info)
Register a parameter.
void release_open_gestures()
Close every gesture still open and report each end to the host.
bool set_parameter_display_name(ParamID id, std::string name)
Override only the host-facing presentation name of a stable parameter.
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 reset_all_mod()
Clear all modulation offsets to zero.
std::span< const ParamGroup > all_groups() const
View of all registered groups (in registration order).
Definition store.hpp:442
void set_main_loop(pulp::events::EventLoop *loop)
Install an EventLoop used to marshal ListenerThread::Main listeners onto the main thread.
std::optional< ParameterFeedbackBaseline > capture_feedback_baseline(ParamID id) const noexcept
Capture an exact per-parameter identity at the caller's ordering point.
void set_normalized_rt(ParamID id, float normalized)
Real-time-safe normalized-value write.
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).
void add_group(const ParamGroup &group)
Register a parameter group. Call during initialization only.
ConditionalParameterApplyResult set_value_rt_if_baseline(const ParameterFeedbackBaseline &baseline, float value)
Publish asynchronous feedback only if the captured identity is still current.
BaseOffsetValue get_base_offset(ParamID id) const
Read the canonical base-vs-offset pair without collapsing its fields.
void run_gesture_on_main(std::function< void()> gesture)
Run a complete parameter gesture (begin_gesture → value writes → end_gesture) on the host's main thre...
void clear_display_modulation(ParamID id) noexcept
Stop showing a plugin-published modulated value for id.
float get_normalized(ParamID id) const
Read a parameter's value mapped to [0, 1] (lock-free).
std::array< float, N > snapshot_modulated(const std::array< ParamID, N > &ids) const noexcept
Modulated variant of snapshot — returns each parameter's base + per-buffer modulation offset (see set...
Definition store.hpp:855
const ParamInfo * info(ParamID id) const
Look up immutable metadata for a parameter.
uint32_t state_version() const
Get the current state schema version.
Definition store.hpp:659
std::optional< float > displayed_modulation(ParamID id) const noexcept
The modulated value a control should show, normalized to the parameter's range, or nullopt when nothi...
void end_gesture(ParamID id)
Signal the host that the current gesture has ended.
void reset_rt_listener_queue_overflow_count()
Reset only the RT listener queue overflow counter.
void set_display_modulation(ParamID id, float plain_value) noexcept
Publish the value (plain units) a plugin's own modulator plays for id.
StateStore(const StateStore &)=delete
std::span< const ParamInfo > all_params() const
View of all registered parameters (in registration order).
Definition store.hpp:439
void set_mod_offset(ParamID id, float offset)
Set the absolute modulation offset for a parameter.
std::size_t param_count() const
Number of registered parameters.
Definition store.hpp:445
void add_mod_offset(ParamID id, float delta)
Add a delta to a parameter's modulation offset.
void set_state_version(uint32_t version)
Set the schema version embedded in serialized state.
Definition store.hpp:656
ListenerToken add_audio_listener(ParamChangeCallback callback)
Convenience for opting into real-time-safe inline invocation.
friend class ParamReader
Definition store.hpp:676
ListenerToken add_listener(ParamChangeCallback callback, ListenerThread thread)
Subscribe to parameter-value changes.
ParamReader param_reader(ParamID id) const
Resolve a read handle for a parameter's base value.
ListenerToken add_listener(ParamChangeCallback callback, ListenerThread thread, ListenerRestoreBehavior restore_behavior)
Subscribe with explicit state-restore behavior.
void release_gesture(ParamID id)
void set_value_rt(ParamID id, float value)
Real-time-safe parameter write for use from the audio thread.
bool has_trigger_params() const
True when at least one registered parameter is a trigger / momentary control.
Definition store.hpp:372
void reset_to_default(ParamID id)
Reset a single parameter to its default value.
bool reset_triggers_rt()
Reset every trigger / momentary parameter to its range default.
ParameterGestureApplyResult apply_normalized_gesture_if_generation(std::uint64_t expected_generation, ParamID id, float normalized)
Atomically claim expected_generation and apply one complete host gesture if it is still current.
std::size_t pump_listeners()
Drain queued main-thread listener invocations posted by set_value_rt() / set_normalized_rt() from the...
bool state_snapshot_is_current(std::uint64_t generation) const noexcept
True when no writer is in flight and none has advanced the generation past generation.
Definition store.hpp:330
float get_default(ParamID id) const
Get the default value for a parameter (from its ParamRange).
std::uint64_t gesture_thread_violation_count() const
Number of times a gesture entry point (begin_gesture / end_gesture) was called off the host main thre...
Definition store.hpp:514
std::vector< uint8_t > serialize() const
Serialize all parameter values to a binary blob for preset/state save.
float get_modulated(ParamID id) const
Read a parameter's modulated value: base + mod_offset (lock-free).
std::size_t open_gesture_count() const noexcept
Number of parameters with an open gesture (begin without a matching end).
Definition store.hpp:493
void add_listener(ParamChangeCallback callback)
Legacy permanent-listener registration.
void flush_deferred_gesture_releases() noexcept
void copy_state_migrations_from(const StateStore &source)
Copy schema migrations from another store with the same registered parameters.
void set_values_rt(std::span< const ParamWrite > writes)
set_value_rt() for several parameters as one store write: one writer claim for the batch and one list...
void reset_all_to_defaults()
Reset all parameters to their default values.
bool register_state_migration(uint32_t from_version, uint32_t to_version, StateMigrationRegistry::MigrationFn migration)
Register a load-time migration for this store's parameter schema.
bool deserialize(std::span< const uint8_t > data)
Restore parameter values from a parameter-only binary blob.
void remove_listener(ListenerToken &token)
Remove a listener explicitly.
std::uint64_t state_generation() const noexcept
Current mutation generation for every parameter-state writer.
Definition store.hpp:320
std::size_t reconcile_restore_listeners()
Reconcile opted-in Main listeners with the current parameter snapshot.
RtListenerQueueTelemetry rt_listener_queue_telemetry() const
Latest telemetry for the RT-to-main listener queue used by set_value_rt() / pump_listeners().
std::uint64_t parameter_display_revision() const noexcept
Monotonic edge for format adapters that republish ParameterInfo.
Definition store.hpp:400
void begin_gesture(ParamID id)
Signal the host that a gesture (drag, click) has begun on a parameter.
Definition child_process_manager.hpp:18
Definition store.hpp:56
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
std::function< void(ParamID id, float new_value)> ParamChangeCallback
Callback signature for parameter change notifications.
Definition parameter.hpp:936
ParameterGestureApplyStatus
Outcome of a generation-bound complete parameter gesture.
Definition store.hpp:41
@ CallbackFailureRolledBack
Definition store.hpp:46
@ InvalidParameter
Definition store.hpp:44
@ CallbackFailureUnknown
Definition store.hpp:47
@ ConcurrentMutation
Definition store.hpp:45
@ GenerationConflict
Definition store.hpp:43
ListenerThread
Where a parameter-change listener runs.
Definition listener_token.hpp:23
ConditionalParameterApplyStatus
Definition store.hpp:89
ListenerRestoreBehavior
Whether a Main listener participates in the UI refresh that follows a successful state restore.
Definition listener_token.hpp:34
uint32_t ParamID
Unique parameter identifier, stable across plugin versions.
Definition parameter.hpp:55
STL namespace.
Canonical automation value shared by graph, Processor, and timeline delivery.
Definition parameter.hpp:22
ConditionalParameterApplyStatus status
Definition store.hpp:96
std::uint64_t current_identity
Definition store.hpp:97
Named parameter group for hierarchical UI organization.
Definition store.hpp:27
int parent_id
0 = root-level group.
Definition store.hpp:30
std::string name
Definition store.hpp:29
Immutable parameter metadata, registered once at plugin initialization.
Definition parameter.hpp:316
ParameterGestureApplyStatus status
Definition store.hpp:51
std::uint64_t generation
Definition store.hpp:52
Snapshot of StateStore's real-time listener queue.
Definition store.hpp:34
std::size_t size_approx
Definition store.hpp:35
std::uint64_t overflow_count
Definition store.hpp:37
std::size_t capacity
Definition store.hpp:36
std::optional< float > last
Definition store.hpp:736
std::function< void(std::optional< float >)> on_change
Definition store.hpp:735
std::uint64_t next_id
Definition store.hpp:739
std::vector< Entry > entries
Definition store.hpp:738
One parameter write in a set_values_rt() batch.
Definition store.hpp:230
float value
Definition store.hpp:232