|
| virtual | ~HostParamSurface ()=default |
| bool | has_param (std::string_view key) |
| | Live membership test — the single source of truth for "is this key
bound right now".
|
| double | get_param (std::string_view key) |
| | Current normalized [0, 1] value of key.
|
| void | set_param (std::string_view key, double normalized) |
| | Write a normalized [0, 1] value.
|
| void | begin_gesture (std::string_view key) |
| void | end_gesture (std::string_view key) |
| std::string | param_display_text (std::string_view key, double normalized) |
| | Host-formatted display of a normalized value, e.g.
|
| int | param_step_count (std::string_view key) |
| | Number of distinct values the HOST's parameter exposes for key — the authoritative cardinality of a discrete/choice/toggle parameter.
|
A framework-agnostic, native-view-facing runtime parameter accessor.
This is the SINGLE host surface a view binds against — defined once in the SDK, so the same view can be driven by whichever parameter system its host happens to own, and never knows which: (a) embedded in a third-party plug-in framework — backed by that framework's own parameter tree over the pulp-view-embed C ABI, (b) native Pulp — backed by StateStore (see StateStoreHostParamSurface in host_param_surface.hpp).
Unlike the bind-once path (NativeImportBindingContext / DesignFrameView's element_for_param_key push), this resolves keys LIVE, so dynamic/paged controls (effect racks, tabs) can rebind without a remount. Bind-once remains the fast path for static top-level controls; this surface is the fallthrough for keys a static registry does not carry.
Threading / call-context contract (hard rule). On macOS the embed's paint/idle is already marshaled to the main thread, so "which thread" is not the hazard; the hazards are re-entrancy and inverting the push-at-tick architecture. Therefore:
- These calls are legal ONLY from tick/update, NEVER from paint(). The embed facade snapshots values + display text once per tick into local state; views paint from the snapshot. Calling from paint would let a plugin-authored getText() override (arbitrary code, possibly holding locks shared with processBlock) run mid-render-traversal.
- The non-virtual public methods assert !is_in_no_alloc_scope() in debug builds — paint_all runs inside a ScopedNoAlloc, so a call from paint trips the assert. This is a best-effort guard, not a correctness guarantee; the audio thread must never touch this surface either.
- Host callbacks must not hold locks shared with the audio thread, and display-text results should be memoized per (key, normalized) pair.
| int pulp::dataplane::HostParamSurface::param_step_count |
( |
std::string_view | key | ) |
|
|
inline |
Number of distinct values the HOST's parameter exposes for key — the authoritative cardinality of a discrete/choice/toggle parameter.
Returns 0 for a continuous parameter and for an unknown key. 0 is deliberately unambiguous: it means "this parameter has no index domain", so a caller must never treat it as a denominator and must never divide by it. Use param_index_to_normalized(), which encodes that guard.
This counts VALUES, not intervals — a 6-way waveform selector returns 6, a toggle returns 2. It matches ParamKind/value_labels cardinality (state::param_value_count), which is what the AU and AAX adapters advertise directly. It is NOT VST3's stepCount field, which counts intervals and is therefore this value minus one; the VST3 adapter applies that -1 at its own boundary. "Step count" is overloaded across plug-in APIs — this accessor is values, always.
The count comes from the PARAMETER, never from a view's option list. A control that renders 3 visible positions may be bound to a 6-value parameter; the divisor is this count, not the number of things drawn. A view whose option count disagrees with this is mis-scaled — that mismatch is worth asserting on loudly rather than silently emitting wrong normalized values.