Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
contract_editor_session.hpp
Go to the documentation of this file.
1#pragma once
2
3// One editor opened through the editor-host contract (editor_host.hpp), held
4// by a format adapter on the host's behalf.
5//
6// Every plug-in format turns its own editor callbacks (VST3 IPlugView, CLAP
7// clap_plugin_gui, an AU Cocoa view) into the same handful of contract calls.
8// This session owns what those adapters share, so each one is a thin mapping:
9//
10// - the editor itself, built from the processor's EditorFactory in the editor
11// role, with an EditorContext whose resize and host-action requests go to
12// hooks the adapter supplies;
13// - one StateStoreParamPort over the adapter's store, so edits reach the host
14// through the adapter's existing gesture path, and closing this editor never
15// ends a gesture another editor holds;
16// - attachment: `detach()` releases every gesture this session holds before
17// the editor detaches. When the adapter or its processor goes away,
18// `close_for_owner()` (the host's window still exists) releases them,
19// detaches the editor and destroys it, and `invalidate()` (the window is
20// already gone) releases them, invalidates the editor and destroys it; both
21// run while the processor that owns the editor's factory still exists;
22// - the idle tick: while attached, Editor::idle() runs from a cancellable
23// main-thread timer (detail::MainThreadTimer) unless the adapter drives
24// `tick()` itself from a host timer. Once the session detaches, closes,
25// invalidates or is destroyed, no tick runs;
26// - size negotiation shared by every format: the current size, a host resize
27// (keeping the scale the editor reports), a new content scale, whether the
28// editor is resizable, and a proposed size adjusted by the editor and clamped
29// to its hints.
30//
31// Main thread only. View-free: it names no view, canvas or render type, so it
32// compiles into pulp-format-core.
33
34#include <pulp/format/detail/main_thread_timer.hpp>
36
37#include <atomic>
38#include <cstdint>
39#include <functional>
40#include <memory>
41#include <mutex>
42#include <vector>
43
44namespace pulp::state {
45class StateStore;
46}
47
48namespace pulp::format {
49
51
74 public:
79
82 void close_all();
84 std::size_t size() const;
85
86 private:
88 mutable std::mutex mutex_;
89 std::vector<std::weak_ptr<ContractEditorSession>> sessions_;
90};
91
92class ContractEditorSession : public std::enable_shared_from_this<ContractEditorSession> {
93 public:
95 static constexpr int kIdleIntervalMs = 16;
96
98 struct HostHooks {
101 std::function<bool(const EditorSize&)> request_resize;
103 std::function<bool(const HostActionRequest&)> host_action;
104 };
105
107 enum class IdleSource : std::uint8_t {
110 };
111
114 static std::unique_ptr<ContractEditorSession> create(Processor& processor,
115 state::StateStore& store,
116 EditorFactory& factory, HostHooks hooks,
118
122
124 Editor* editor() const {
125 return editor_.get();
126 }
127
129 return port_.get();
130 }
131 bool is_attached() const {
132 return attached_;
133 }
134
138 bool attach(const NativeParent& parent);
141 void detach();
155 return idle_source_;
156 }
157
158 void tick();
159
168
174 bool set_size(std::uint32_t width, std::uint32_t height);
176 bool set_scale(double scale);
179 bool resizable() const;
182 bool constrain(std::uint32_t& width, std::uint32_t& height) const;
183
186 void focus_changed(bool focused);
187 void visibility_changed(bool visible);
188
189 private:
191 class Context;
192
194 IdleSource idle);
195 void start_idle();
196 void stop_idle();
197 void destroy_editor();
198
199 IdleSource idle_source_;
200 // Declared in dependency order so the editor is destroyed first, then the
201 // context it was created with, then the port the context hands out.
202 std::unique_ptr<StateStoreParamPort> port_;
203 std::unique_ptr<Context> context_;
204 std::unique_ptr<Editor> editor_;
205 bool attached_ = false;
206 detail::MainThreadTimer idle_timer_;
207 std::atomic<bool> owner_gone_{false};
208};
209
210} // namespace pulp::format
Definition contract_editor_session.hpp:92
bool resizable() const
False only for an editor whose hints fix its size (equal, non-zero minimum and maximum on both axes).
bool attach(const NativeParent &parent)
Attach the editor to parent and start the idle tick.
void visibility_changed(bool visible)
KeyDisposition offer_key(const EditorKeyEvent &event)
Offer a key. Forward when not attached.
StateStoreParamPort * param_port() const
This session's parameter port, or null after invalidate().
Definition contract_editor_session.hpp:128
IdleSource
Who calls tick() while attached.
Definition contract_editor_session.hpp:107
@ host_driven
the adapter, from a host timer
Definition contract_editor_session.hpp:109
@ self_paced
the session's own main-thread chain
Definition contract_editor_session.hpp:108
bool register_with(ContractSessionRegistry &registry)
Be closed by registry when its adapter instance goes away first.
IdleSource idle_source() const
Who calls tick() while attached.
Definition contract_editor_session.hpp:154
bool constrain(std::uint32_t &width, std::uint32_t &height) const
Adjust a proposed size through the editor, then clamp it to the hints.
void close_for_owner()
The processor is going away while the host's window still exists: stop the tick, release every gestur...
ContractEditorSession(const ContractEditorSession &)=delete
bool set_size(std::uint32_t width, std::uint32_t height)
A host resize, keeping the scale the editor reports.
ViewSize size_hints() const
The editor's size hints (defaults when the editor is gone).
void disconnect_owner()
The owner is going away on another thread: release every gesture, cut the port from the store and ref...
void invalidate()
The host's window is already gone: stop the tick, release every gesture, invalidate the editor and de...
void tick()
One idle tick: Editor::idle() while attached.
friend class ContractSessionRegistry
Definition contract_editor_session.hpp:190
Editor * editor() const
The editor, or null after invalidate().
Definition contract_editor_session.hpp:124
EditorSize size() const
The editor's size, or its preferred size while it reports none.
bool set_scale(double scale)
A new content scale at the current size.
static constexpr int kIdleIntervalMs
Interval of the session's own idle tick while attached (about 60 Hz).
Definition contract_editor_session.hpp:95
ContractEditorSession & operator=(const ContractEditorSession &)=delete
bool is_attached() const
Definition contract_editor_session.hpp:131
void detach()
Stop the tick, release every gesture this session holds, then detach the editor.
void use_self_paced_idle()
Tick from the session's own timer from now on, for an adapter whose host timer is unavailable.
static std::unique_ptr< ContractEditorSession > create(Processor &processor, state::StateStore &store, EditorFactory &factory, HostHooks hooks, IdleSource idle=IdleSource::self_paced)
A session over a new editor from factory, or null when the factory does not offer the editor role or ...
friend class ContractEditorSession
Definition contract_editor_session.hpp:87
ContractSessionRegistry(const ContractSessionRegistry &)=delete
std::size_t size() const
Registered sessions still alive.
ContractSessionRegistry & operator=(const ContractSessionRegistry &)=delete
void close_all()
Close every live registered session for its owner and forget them: at once on the main thread,...
Builds a processor's editors.
Definition editor_host.hpp:576
One editor instance in one native window.
Definition editor_host.hpp:429
Definition processor.hpp:174
The default ParamPort, over a processor's StateStore.
Definition editor_host.hpp:186
float get(state::ParamID id) const override
The current plain value (the host's automation included). Any thread.
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
The editor-host contract: how a host (a format adapter, the standalone app, a test) opens,...
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
KeyDisposition
The editor's answer to an offered key.
Definition editor_host.hpp:377
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
What the adapter does for the editor's context.
Definition contract_editor_session.hpp:98
std::function< bool(const EditorSize &)> request_resize
Ask the host to resize its window to size.
Definition contract_editor_session.hpp:101
std::function< bool(const HostActionRequest &)> host_action
Take a host action. Null declines every action.
Definition contract_editor_session.hpp:103
A key the host offers to the editor before acting on it itself.
Definition editor_host.hpp:368
An editor size in logical pixels, with the backing scale factor that maps them to physical pixels (2....
Definition editor_host.hpp:332
One host action and its arguments.
Definition editor_host.hpp:520
A native window to attach an editor to, owned by the host.
Definition editor_host.hpp:324
Editor size hints (in logical pixels).
Definition plugin_descriptor.hpp:27