Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
editor_host.hpp
Go to the documentation of this file.
1#pragma once
2
38
42
43#include <cstddef>
44#include <cstdint>
45#include <functional>
46#include <memory>
47#include <optional>
48#include <span>
49#include <string>
50#include <string_view>
51#include <unordered_map>
52#include <utility>
53#include <vector>
54
55namespace pulp::state {
56class StateStore;
57}
58
59namespace pulp::format {
60
61class Processor;
62
63// ── Parameters ───────────────────────────────────────────────────────────────
64
68 public:
69 ParamSubscription() = default;
72 explicit ParamSubscription(std::function<void()> cancel) noexcept
73 : cancel_(std::move(cancel)) {}
75 : cancel_(std::exchange(other.cancel_, {})) {}
77 if (this != &other) {
78 reset();
79 cancel_ = std::exchange(other.cancel_, {});
80 }
81 return *this;
82 }
86 reset();
87 }
88
90 void reset() noexcept {
91 if (auto cancel = std::exchange(cancel_, {}))
92 cancel();
93 }
94
95 explicit operator bool() const noexcept {
96 return static_cast<bool>(cancel_);
97 }
98
99 private:
100 std::function<void()> cancel_;
101};
102
120 public:
121 using Listener = std::function<void(state::ParamID id, float plain_value)>;
122
123 virtual ~ParamPort() = default;
124
126 virtual std::span<const state::ParamInfo> params() const = 0;
128 virtual const state::ParamInfo* info(state::ParamID id) const = 0;
130 virtual float get(state::ParamID id) const = 0;
131
133 virtual void begin(state::ParamID id) = 0;
136 virtual void set(state::ParamID id, float plain_value) = 0;
139 virtual void end(state::ParamID id) = 0;
140
145 [[nodiscard]] virtual ParamSubscription add_listener(Listener listener) = 0;
146
150 const auto* i = info(id);
151 return i ? i->range.normalize(get(id)) : 0.0f;
152 }
153
155 void set_normalized(state::ParamID id, float normalized) {
156 if (const auto* i = info(id))
157 set(id, i->range.denormalize(normalized));
158 }
159};
160
186class StateStoreParamPort final : public ParamPort {
187 public:
190
193
194 std::span<const state::ParamInfo> params() const override;
195 const state::ParamInfo* info(state::ParamID id) const override;
196 float get(state::ParamID id) const override;
197 void begin(state::ParamID id) override;
198 void set(state::ParamID id, float plain_value) override;
199 void end(state::ParamID id) override;
200 [[nodiscard]] ParamSubscription add_listener(Listener listener) override;
201
206
221 bool connected() const;
222
225
226 private:
227 struct Link;
228 std::shared_ptr<Link> link_;
229};
230
231// ── Visual data ──────────────────────────────────────────────────────────────
232
234enum class VisualChannelShape : std::uint8_t {
235 scalar = 0,
236 meter = 1,
237 vector = 2,
238 events = 3,
239};
240
243 std::string_view name;
244 std::string_view unit;
247 float neutral = 0.0f;
248};
249
252 std::uint32_t frame_index = 0;
253 float value = 0.0f;
254};
255
266 public:
267 virtual ~VisualPort() = default;
268
269 virtual std::size_t channel_count() const noexcept = 0;
271 virtual VisualChannelInfo channel(std::size_t index) const noexcept = 0;
272
275 virtual bool read_scalar(std::size_t index, float& value) noexcept = 0;
280 virtual std::size_t read_meter(std::size_t index, std::span<float> rms,
281 std::span<float> peak) noexcept = 0;
284 virtual std::size_t read_vector(std::size_t index, std::span<float> samples) noexcept = 0;
287 virtual std::size_t read_events(std::size_t index, std::span<VisualEvent> events) noexcept = 0;
290 virtual std::uint32_t publish_count(std::size_t index) const noexcept = 0;
291
293 std::optional<std::size_t> find(std::string_view name,
294 VisualChannelShape shape) const noexcept {
295 for (std::size_t i = 0, n = channel_count(); i < n; ++i) {
296 const auto c = channel(i);
297 if (c.shape == shape && c.name == name)
298 return i;
299 }
300 return std::nullopt;
301 }
302};
303
304// ── Native windows, sizes and keys ───────────────────────────────────────────
305
307enum class EditorRole : std::uint8_t {
308 editor = 0,
311};
312
315enum class NativeParentKind : std::uint8_t {
316 none = 0,
321};
322
326 void* handle = nullptr;
327 std::uint64_t window_id = 0;
328};
329
333 std::uint32_t width = 0;
334 std::uint32_t height = 0;
335 double scale = 1.0;
336};
337
341enum class EditorKey : std::uint16_t {
342 none = 0,
343 space = 1,
344 enter = 2,
345 tab = 3,
349 left = 7,
350 right = 8,
351 up = 9,
352 down = 10,
353 home = 11,
354 end = 12,
357};
358
366
370 char32_t character = 0;
371 std::uint8_t modifiers = 0;
372 bool is_down = true;
373 bool is_repeat = false;
374};
375
377enum class KeyDisposition : std::uint8_t {
380};
381
382// ── Editor ───────────────────────────────────────────────────────────────────
383
389 public:
390 virtual ~EditorAutomation() = default;
391
393 virtual bool capture_png(std::vector<std::uint8_t>& /*png*/) {
394 return false;
395 }
396
398 virtual bool inject_input(std::string_view /*request_json*/, std::string& error) {
399 error = "input injection is not supported by this editor";
400 return false;
401 }
402
404 virtual bool observe(std::string_view /*query_json*/, std::string& /*reply_json*/) {
405 return false;
406 }
407};
408
429class Editor {
430 public:
431 virtual ~Editor() = default;
432
435 virtual bool supports_parent(NativeParentKind kind) const = 0;
436
439 virtual bool attach(const NativeParent& parent) = 0;
440
443 virtual void detach() = 0;
444
449 virtual void invalidate() = 0;
450
452 virtual EditorSize size() const = 0;
453
456 virtual bool set_size(const EditorSize& size) = 0;
457
461 virtual ViewSize size_hints() const {
462 const auto s = size();
463 ViewSize hints;
464 hints.preferred_width = s.width;
465 hints.preferred_height = s.height;
466 return hints;
467 }
468
471 virtual EditorSize adjust_size(const EditorSize& proposed) const {
472 return proposed;
473 }
474
476 virtual void idle() {}
477
479 virtual void visibility_changed(bool /*visible*/) {}
480
482 virtual void focus_changed(bool /*focused*/) {}
483
488 virtual KeyDisposition offer_key(const EditorKeyEvent& /*event*/) {
490 }
491
494 virtual void parameter_highlight(state::ParamID /*id*/, bool /*highlighted*/,
495 std::uint32_t /*color_rgb*/) {}
496
500 return nullptr;
501 }
502};
503
504// ── Host context ─────────────────────────────────────────────────────────────
505
508enum class HostAction : std::uint16_t {
517};
518
526
530 public:
531 virtual ~EditorContext() = default;
532
534 virtual ParamPort& params() = 0;
535
538 virtual VisualPort* visuals() = 0;
539
543 virtual bool request_resize(const EditorSize& size) = 0;
544
547 virtual bool host_action(const HostActionRequest& request) = 0;
548
550 virtual EditorHostKind host_kind() const = 0;
551
567 virtual void* query_extension(std::string_view /*id*/) {
568 return nullptr;
569 }
570};
571
572// ── Factory ──────────────────────────────────────────────────────────────────
573
577 public:
578 virtual ~EditorFactory() = default;
579
581 virtual bool supports(EditorRole role) const = 0;
582
589 virtual std::unique_ptr<Editor> create(Processor& processor, EditorContext& context,
590 EditorRole role) = 0;
591
598 virtual void prewarm() {}
599};
600
601} // namespace pulp::format
Optional automation surface of an editor, so tooling (the pulp control UI tools, tests) can see and d...
Definition editor_host.hpp:388
virtual bool observe(std::string_view, std::string &)
Answer an observation query (for example the element tree, or one element's state) with a JSON snapsh...
Definition editor_host.hpp:404
virtual bool capture_png(std::vector< std::uint8_t > &)
Encode the editor's current frame as PNG into png.
Definition editor_host.hpp:393
virtual ~EditorAutomation()=default
virtual bool inject_input(std::string_view, std::string &error)
Apply one synthetic input request (a click, drag, key or text entry described as JSON).
Definition editor_host.hpp:398
What the host gives an editor.
Definition editor_host.hpp:529
virtual EditorHostKind host_kind() const =0
Whether the editor runs inside a plug-in host or the standalone app.
virtual bool request_resize(const EditorSize &size)=0
Ask the host to resize the editor's window to size.
virtual ~EditorContext()=default
virtual bool host_action(const HostActionRequest &request)=0
Ask the host to take request.
virtual void * query_extension(std::string_view)
A host capability beyond the members above, by stable string id, or null when this host does not offe...
Definition editor_host.hpp:567
virtual VisualPort * visuals()=0
The processor's published values and meters, or null when it declares none.
virtual ParamPort & params()=0
Parameter access. Several editors may share one port.
Builds a processor's editors.
Definition editor_host.hpp:576
virtual ~EditorFactory()=default
virtual bool supports(EditorRole role) const =0
Whether this factory builds editors for role.
virtual std::unique_ptr< Editor > create(Processor &processor, EditorContext &context, EditorRole role)=0
A new, unattached editor for processor in role, or null when the role is not supported.
virtual void prewarm()
Warm process-wide caches (compiled scripts, parsed documents, fonts) so the first create() does not d...
Definition editor_host.hpp:598
One editor instance in one native window.
Definition editor_host.hpp:429
virtual void invalidate()=0
The host's window is already gone or about to be destroyed by the host itself.
virtual bool set_size(const EditorSize &size)=0
The host resized the window (or changed its scale).
virtual void focus_changed(bool)
The editor's window gained or lost keyboard focus.
Definition editor_host.hpp:482
virtual ViewSize size_hints() const
Preferred, minimum and maximum size and the aspect ratio to hold.
Definition editor_host.hpp:461
virtual EditorSize adjust_size(const EditorSize &proposed) const
The nearest size to proposed this editor accepts, for a host that negotiates during an interactive re...
Definition editor_host.hpp:471
virtual bool attach(const NativeParent &parent)=0
Attach to and start drawing into parent.
virtual EditorAutomation * automation()
The editor's automation surface, or null when it has none.
Definition editor_host.hpp:499
virtual void visibility_changed(bool)
The editor's window became visible or hidden without being detached.
Definition editor_host.hpp:479
virtual bool supports_parent(NativeParentKind kind) const =0
Whether this editor can attach to a parent of kind.
virtual KeyDisposition offer_key(const EditorKeyEvent &)
A key the host would otherwise act on itself, offered synchronously before it does.
Definition editor_host.hpp:488
virtual void idle()
Main-thread tick from the host (a timer or the window's frame clock).
Definition editor_host.hpp:476
virtual void detach()=0
Stop drawing and remove everything the editor added to its parent.
virtual EditorSize size() const =0
The editor's current size.
virtual void parameter_highlight(state::ParamID, bool, std::uint32_t)
The host highlights or un-highlights a parameter's control (for example while it is automation-enable...
Definition editor_host.hpp:494
virtual ~Editor()=default
Parameter access for an editor.
Definition editor_host.hpp:119
float get_normalized(state::ParamID id) const
get(id) mapped to [0, 1] through the parameter's range (0 for an unknown id).
Definition editor_host.hpp:149
virtual void begin(state::ParamID id)=0
Open a gesture on id.
virtual ParamSubscription add_listener(Listener listener)=0
Be told about every change to any parameter, whoever made it (this editor, another editor,...
std::function< void(state::ParamID id, float plain_value)> Listener
Definition editor_host.hpp:121
virtual void end(state::ParamID id)=0
Close a gesture this caller opened.
virtual const state::ParamInfo * info(state::ParamID id) const =0
One parameter's description, or null for an unknown id. Any thread.
void set_normalized(state::ParamID id, float normalized)
set(id, …) from a [0, 1] value through the parameter's range.
Definition editor_host.hpp:155
virtual std::span< const state::ParamInfo > params() const =0
Every parameter, in declaration order.
virtual ~ParamPort()=default
virtual void set(state::ParamID id, float plain_value)=0
Write a plain value.
virtual float get(state::ParamID id) const =0
The current plain value (the host's automation included). Any thread.
Owns one ParamPort listener registration.
Definition editor_host.hpp:67
ParamSubscription(ParamSubscription &&other) noexcept
Definition editor_host.hpp:74
ParamSubscription & operator=(const ParamSubscription &)=delete
ParamSubscription & operator=(ParamSubscription &&other) noexcept
Definition editor_host.hpp:76
ParamSubscription(std::function< void()> cancel) noexcept
Adopt a registration; cancel runs exactly once, on reset or destruction.
Definition editor_host.hpp:72
~ParamSubscription()
Definition editor_host.hpp:85
void reset() noexcept
Remove the listener now. Idempotent.
Definition editor_host.hpp:90
ParamSubscription(const ParamSubscription &)=delete
Definition processor.hpp:174
void begin(state::ParamID id) override
Open a gesture on id.
void release_all()
Close every gesture this port still holds, reporting each end to the host.
float get(state::ParamID id) const override
The current plain value (the host's automation included). Any thread.
bool connected() const
False after disconnect().
std::span< const state::ParamInfo > params() const override
Every parameter, in declaration order.
void end(state::ParamID id) override
Close a gesture this caller opened.
int open_gestures(state::ParamID id) const
Gestures this port currently holds open on id (0 when none).
ParamSubscription add_listener(Listener listener) override
Be told about every change to any parameter, whoever made it (this editor, another editor,...
StateStoreParamPort(state::StateStore &store)
const state::ParamInfo * info(state::ParamID id) const override
One parameter's description, or null for an unknown id. Any thread.
void disconnect()
Release every gesture, remove every listener this port registered, and let go of the store,...
void set(state::ParamID id, float plain_value) override
Write a plain value.
StateStoreParamPort(const StateStoreParamPort &)=delete
StateStoreParamPort & operator=(const StateStoreParamPort &)=delete
Read access to the values and meters a processor publishes for its UI.
Definition editor_host.hpp:265
virtual std::size_t channel_count() const noexcept=0
virtual std::uint32_t publish_count(std::size_t index) const noexcept=0
Monotonic publish count of channel index.
virtual bool read_scalar(std::size_t index, float &value) noexcept=0
Latest value of a scalar channel.
virtual ~VisualPort()=default
virtual std::size_t read_events(std::size_t index, std::span< VisualEvent > events) noexcept=0
Occurrences of the latest published block of an events channel.
virtual std::size_t read_meter(std::size_t index, std::span< float > rms, std::span< float > peak) noexcept=0
Latest frame of a meter channel into rms and peak.
virtual std::size_t read_vector(std::size_t index, std::span< float > samples) noexcept=0
Latest block of a vector channel into samples.
std::optional< std::size_t > find(std::string_view name, VisualChannelShape shape) const noexcept
Index of the channel called name with shape shape, or nullopt.
Definition editor_host.hpp:293
virtual VisualChannelInfo channel(std::size_t index) const noexcept=0
Description of channel index (< channel_count()).
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
Definition child_process_manager.hpp:18
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
VisualChannelShape
The shape of one visual channel.
Definition editor_host.hpp:234
@ meter
per-channel RMS and peak levels
Definition editor_host.hpp:236
@ vector
a block of samples for a scope-style display
Definition editor_host.hpp:237
@ scalar
one number per publish (gain reduction, an envelope level)
Definition editor_host.hpp:235
@ error
Definition validation_harness.hpp:20
EditorRole
The UI role an editor plays. A processor may offer several at once.
Definition editor_host.hpp:307
@ settings
the processor's own settings content
Definition editor_host.hpp:310
@ editor
the main plug-in or app editor
Definition editor_host.hpp:308
@ inspector
a secondary window over the same processor
Definition editor_host.hpp:309
EditorKeyModifier
Modifier bits in EditorKeyEvent::modifiers.
Definition editor_host.hpp:360
@ editor_modifier_command
Command on macOS, Windows key elsewhere.
Definition editor_host.hpp:364
@ editor_modifier_control
Definition editor_host.hpp:362
@ editor_modifier_alt
Option on macOS.
Definition editor_host.hpp:363
@ editor_modifier_shift
Definition editor_host.hpp:361
EditorKey
A non-character key.
Definition editor_host.hpp:341
@ home
Definition editor_host.hpp:353
@ none
Definition editor_host.hpp:342
@ up
Definition editor_host.hpp:351
@ backspace
Definition editor_host.hpp:346
@ down
Definition editor_host.hpp:352
@ right
Definition editor_host.hpp:350
@ end
Definition editor_host.hpp:354
@ left
Definition editor_host.hpp:349
@ delete_forward
Definition editor_host.hpp:348
@ page_down
Definition editor_host.hpp:356
@ escape
Definition editor_host.hpp:347
@ enter
Definition editor_host.hpp:344
@ tab
Definition editor_host.hpp:345
@ page_up
Definition editor_host.hpp:355
@ space
Definition editor_host.hpp:343
NativeParentKind
The kind of native window handle an editor is attached to.
Definition editor_host.hpp:315
@ win32_window
Windows HWND in handle.
Definition editor_host.hpp:319
@ none
no window: an offscreen or headless editor
Definition editor_host.hpp:316
@ cocoa_view
macOS NSView* in handle
Definition editor_host.hpp:317
@ uikit_view
iOS UIView* in handle
Definition editor_host.hpp:318
@ x11_window
X11 Window id in window_id.
Definition editor_host.hpp:320
KeyDisposition
The editor's answer to an offered key.
Definition editor_host.hpp:377
@ consumed
the editor handled it; the host must not act on it
Definition editor_host.hpp:379
@ forward
not the editor's: the host acts on it (Space → transport)
Definition editor_host.hpp:378
HostAction
Actions an editor can ask its host to take.
Definition editor_host.hpp:508
@ parameter_context_menu
Show the host's context menu for parameter param at (x, y) in the editor's logical coordinates.
Definition editor_host.hpp:514
@ close_editor
Ask the host to close this editor's window.
Definition editor_host.hpp:516
@ mark_state_dirty
State outside the parameters changed (a loaded sample, an editor setting); the host should treat the ...
Definition editor_host.hpp:511
EditorHostKind
Where a processor's editor lives, as far as the keyboard is concerned.
Definition editor_host_kind.hpp:15
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
uint32_t ParamID
Unique parameter identifier, stable across plugin versions.
Definition parameter.hpp:55
STL namespace.
A key the host offers to the editor before acting on it itself.
Definition editor_host.hpp:368
bool is_repeat
an auto-repeat of a held key
Definition editor_host.hpp:373
EditorKey key
Definition editor_host.hpp:369
char32_t character
composed Unicode scalar, 0 when none
Definition editor_host.hpp:370
bool is_down
false for a key release
Definition editor_host.hpp:372
std::uint8_t modifiers
EditorKeyModifier bits
Definition editor_host.hpp:371
An editor size in logical pixels, with the backing scale factor that maps them to physical pixels (2....
Definition editor_host.hpp:332
double scale
Definition editor_host.hpp:335
std::uint32_t height
Definition editor_host.hpp:334
std::uint32_t width
Definition editor_host.hpp:333
One host action and its arguments.
Definition editor_host.hpp:520
float y
Definition editor_host.hpp:524
state::ParamID param
Definition editor_host.hpp:522
float x
Definition editor_host.hpp:523
HostAction action
Definition editor_host.hpp:521
A native window to attach an editor to, owned by the host.
Definition editor_host.hpp:324
NativeParentKind kind
Definition editor_host.hpp:325
void * handle
pointer handle (NSView*, UIView*, HWND)
Definition editor_host.hpp:326
std::uint64_t window_id
integer handle (an X11 Window)
Definition editor_host.hpp:327
Editor size hints (in logical pixels).
Definition plugin_descriptor.hpp:27
uint32_t preferred_height
Definition plugin_descriptor.hpp:29
uint32_t preferred_width
Definition plugin_descriptor.hpp:28
What a visual channel is. The strings stay valid for the life of the port.
Definition editor_host.hpp:242
VisualChannelShape shape
Definition editor_host.hpp:245
std::string_view name
verbatim lookup key
Definition editor_host.hpp:243
std::string_view unit
display only ("dB", "Hz"); may be empty
Definition editor_host.hpp:244
float neutral
The value a reader falls back to when the channel goes stale.
Definition editor_host.hpp:247
One occurrence on an events channel.
Definition editor_host.hpp:251
float value
payload; a zero value is still an event
Definition editor_host.hpp:253
std::uint32_t frame_index
sample offset inside its audio block
Definition editor_host.hpp:252
Immutable parameter metadata, registered once at plugin initialization.
Definition parameter.hpp:316