Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
view_bridge.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <cstdlib>
5#include <functional>
6#include <memory>
10#include <pulp/view/view.hpp>
11#include <string>
12#include <string_view>
13#include <vector>
14
15namespace pulp::view {
17} // namespace pulp::view
18
19namespace pulp::format {
20
30 const char* v = std::getenv("PULP_DEV_HOT_RELOAD");
31 if (!v) return false;
32 switch (v[0]) {
33 case '1': case 't': case 'T': case 'y': case 'Y': return true;
34 default: return false;
35 }
36}
37
43 const char* v = std::getenv("PULP_EDITOR_OPEN");
44 return !(v && std::string_view(v) == "view-first");
45}
46
50enum class ViewRole {
53};
54
73std::uint32_t resolve_editor_background(const Processor& processor,
74 const view::View* root) noexcept;
75
77public:
78 struct Options {
79 bool enable_hot_reload = false;
87 bool defer_document_load = false;
88
98 bool content_first_open = false;
99
113 return Options{.enable_hot_reload = dev_editor_hot_reload_enabled(),
114 .role = ViewRole::Editor,
115 .defer_document_load = true,
116 .content_first_open = editor_content_first_open_enabled()};
117 }
118 };
119
121 ViewBridge(Processor& processor, state::StateStore& store, Options options);
123 runtime::AliveToken::Handle owner_alive);
125 runtime::AliveToken::Handle owner_alive, Options options);
127
128 ViewBridge(const ViewBridge&) = delete;
129 ViewBridge& operator=(const ViewBridge&) = delete;
130
139 bool open(std::string* error = nullptr);
140
164
165 static constexpr int kFirstFrameSettleRounds = 8;
166 static constexpr double kFirstFrameSettleBudgetMs = 120.0;
167
172
188 std::unique_ptr<view::View> release_view();
189
194 void close();
195
198 void resize(uint32_t width, uint32_t height);
199
208 if (owner_alive_) owner_alive_->store(false, std::memory_order_release);
210 }
211
222 bool notify_owner_released() noexcept;
223
227 bool owner_is_alive() const noexcept {
228 return runtime::AliveToken::is_alive(owner_alive_);
229 }
230
243 bool set_preferred_size(uint32_t width, uint32_t height);
244
256
266
267 bool is_open() const { return view_raw_ != nullptr; }
268 ViewRole role() const { return options_.role; }
269 view::View* view() { return view_raw_; }
270 const view::View* view() const { return view_raw_; }
271
272 bool uses_script_ui() const { return uses_script_ui_; }
273
291
298 view::HostActionSurface* host_actions() const { return host_actions_; }
299
306 const std::shared_ptr<std::atomic<bool>>& alive_token() const { return alive_; }
307
314
319 const std::function<void(view::ScriptedUiSession*)>& visitor);
321 const std::function<void(const view::ScriptedUiSession*)>& visitor) const;
322
323 uint32_t width() const { return width_; }
324 uint32_t height() const { return height_; }
325 const ViewSize& size_hints() const { return size_hints_; }
326
333 std::uint32_t editor_background_rgb() const { return editor_background_rgb_; }
334
335 const std::string& last_error() const { return last_error_; }
336
341 view::View* attach_secondary_view(std::unique_ptr<view::View> view, ViewRole role);
342
346
349 size_t view_count() const;
350
354 view::View* view_at(size_t index);
355
357 ViewRole role_at(size_t index) const;
358
359private:
364 bool poll_state_restore();
365
369 void pump_store_listeners();
370
392 std::size_t sync_design_frames_from_host();
393
395 friend std::function<void()> make_editor_idle_pump(ViewBridge&);
397 friend struct ViewBridgeTestAccess;
398 Processor& processor_;
399 state::StateStore& store_;
400 Options options_;
405 bool supports_editor_reload_ = false;
410 runtime::AliveToken local_owner_alive_;
411 runtime::AliveToken::Handle owner_alive_;
412
413 std::unique_ptr<view::View> view_;
414 view::View* view_raw_ = nullptr;
417 std::unique_ptr<view::StateStoreHostParamSurface> host_param_surface_;
418 view::HostActionSurface* host_actions_ = nullptr;
419 std::unique_ptr<view::ScriptedUiSession> scripted_ui_;
423 bool in_place_scripted_ui_reload_ = false;
424 bool uses_script_ui_ = false;
425 bool uses_auto_ui_ = false;
426 bool attached_ = false;
427 bool owner_release_notified_ = false;
428 bool released_ = false;
429 uint64_t last_reload_generation_ = 0;
430 uint64_t last_state_restore_revision_ = 0;
432 std::shared_ptr<std::atomic<bool>> alive_ =
433 std::make_shared<std::atomic<bool>>(true);
434
435 struct Secondary {
436 std::unique_ptr<view::View> view;
438 };
439 std::vector<Secondary> secondaries_;
440
441 ViewSize size_hints_;
442 std::uint32_t editor_background_rgb_ = view::kEditorHostClearRgb;
443 uint32_t width_ = 0;
444 uint32_t height_ = 0;
445 std::string last_error_;
446};
447
448namespace detail {
449
455template <typename HostRequest>
457 uint32_t width, uint32_t height,
458 HostRequest&& request) {
459 const auto previous = bridge.size_hints();
460 if (!bridge.set_preferred_size(width, height)) return false;
461 if (request(width, height)) return true;
462
463 // The declared bounds never change in set_preferred_size(), so a preferred
464 // size that was valid before the transaction remains valid for rollback.
465 bridge.set_preferred_size(previous.preferred_width,
466 previous.preferred_height);
467 return false;
468}
469
474
475} // namespace detail
476
477} // namespace pulp::format
A framework-agnostic host command channel.
Definition host_surfaces.hpp:180
A framework-agnostic, native-view-facing runtime parameter accessor.
Definition host_surfaces.hpp:40
One editor instance in one native window.
Definition editor_host.hpp:429
Definition processor.hpp:174
Definition view_bridge.hpp:76
void visit_scripted_ui(const std::function< void(view::ScriptedUiSession *)> &visitor)
Borrow the active scripted UI only for the duration of visitor.
const std::string & last_error() const
Definition view_bridge.hpp:335
void close()
Destroy the view.
view::View * attach_secondary_view(std::unique_ptr< view::View > view, ViewRole role)
Attach a secondary inspector view to this bridge.
bool open(std::string *error=nullptr)
Build the view.
view::ScriptedUiSession * scripted_ui()
Access the scripted UI session, if the primary view was built from a JS script.
view::HostParamSurface * host_params()
The runtime host-parameter surface installed on the open view tree.
uint32_t width() const
Definition view_bridge.hpp:323
ViewBridge(const ViewBridge &)=delete
void visit_scripted_ui(const std::function< void(const view::ScriptedUiSession *)> &visitor) const
size_t view_count() const
Total number of attached views (primary + secondary).
void resize(uint32_t width, uint32_t height)
Notify the bridge that the host resized the editor.
const ViewSize & size_hints() const
Definition view_bridge.hpp:325
std::uint32_t editor_background_rgb() const
The editor's background as 0xRRGGBB, resolved when open() builds the view: Processor::editor_backgrou...
Definition view_bridge.hpp:333
bool poll_editor_reload()
Live editor reload (live-swap 1.9).
uint32_t height() const
Definition view_bridge.hpp:324
friend struct ViewBridgeTestAccess
Test-only reach-in, mirroring StandaloneRenderTestAccess.
Definition view_bridge.hpp:397
std::unique_ptr< view::View > release_view()
Transfer ownership of the primary view to the caller while preserving the bridge's lifecycle dispatch...
ViewBridge & operator=(const ViewBridge &)=delete
bool uses_script_ui() const
Definition view_bridge.hpp:272
bool is_open() const
Definition view_bridge.hpp:267
bool set_preferred_size(uint32_t width, uint32_t height)
Update the editor's PREFERRED size (and derived aspect ratio) after the plugin requested an editor-in...
ViewBridge(Processor &processor, state::StateStore &store, runtime::AliveToken::Handle owner_alive, Options options)
bool notify_owner_released() noexcept
Tell every view in the editor tree that the plug-in instance owning it is gone, by calling EditorOwne...
bool owner_is_alive() const noexcept
Whether the adapter instance that owns both Processor and StateStore is still alive.
Definition view_bridge.hpp:227
const std::shared_ptr< std::atomic< bool > > & alive_token() const
Cross-thread liveness token.
Definition view_bridge.hpp:306
bool prepare_first_frame(view::PluginViewHost &host)
Content-first open: make host's first frame the settled document.
static constexpr double kFirstFrameSettleBudgetMs
Definition view_bridge.hpp:166
void set_host_actions(view::HostActionSurface *actions)
Install the command channel a routed view's Kind::action clicks reach (route_actions_to_host(true) → ...
ViewBridge(Processor &processor, state::StateStore &store, runtime::AliveToken::Handle owner_alive)
ViewRole role() const
Definition view_bridge.hpp:268
const view::View * view() const
Definition view_bridge.hpp:270
bool detach_secondary_view(view::View *view)
Detach and destroy a previously-attached secondary view.
view::View * view()
Definition view_bridge.hpp:269
void notify_attached()
Fire on_view_opened(view) — called by the adapter once the view has been attached to its native paren...
static constexpr int kFirstFrameSettleRounds
Definition view_bridge.hpp:165
view::HostActionSurface * host_actions() const
Definition view_bridge.hpp:298
void notify_processor_destroyed() noexcept
The owning adapter MUST call this before the referenced Processor is destroyed when the two have inde...
Definition view_bridge.hpp:207
view::View * view_at(size_t index)
Access an attached view by index.
ViewRole role_at(size_t index) const
Role of the view at index. Returns Editor when out of range.
ViewBridge(Processor &processor, state::StateStore &store, Options options)
const view::ScriptedUiSession * scripted_ui() const
ViewBridge(Processor &processor, state::StateStore &store)
friend std::function< void()> make_editor_idle_pump(ViewBridge &)
The editor idle pump — the sole production caller of the host pull.
Definition editor_idle_pump.hpp:18
bool rebuild_primary_view()
Force a rebuild of the open primary view from create_view() now, transplanting the fresh content (chi...
Shared, fail-closed lifetime signal for callbacks that may outlive an owner.
Definition alive_token.hpp:19
std::shared_ptr< State > Handle
Definition alive_token.hpp:53
static bool is_alive(const Handle &handle) noexcept
Definition alive_token.hpp:143
Centralized parameter storage with lock-free value access.
Definition store.hpp:164
Definition plugin_view_host.hpp:64
Definition scripted_ui.hpp:125
Definition view.hpp:73
bool negotiate_preferred_size(ViewBridge &bridge, uint32_t width, uint32_t height, HostRequest &&request)
Internal transaction shared by the CLAP and VST3 adapters.
Definition view_bridge.hpp:456
void view_editor_prewarm_scheduler(const Processor::EditorPrewarm &request)
The scheduler pulp-format-view installs for request_editor_prewarm() (see editor_prewarm....
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
@ error
Definition validation_harness.hpp:20
bool dev_editor_hot_reload_enabled()
Whether a DAW-hosted editor should enable scripted-UI + theme hot reload (item 1.3).
Definition view_bridge.hpp:29
bool editor_content_first_open_enabled()
Whether a DAW-hosted editor opens content-first (the default) or view-first.
Definition view_bridge.hpp:42
std::uint32_t resolve_editor_background(const Processor &processor, const view::View *root) noexcept
Manages editor-view lifecycle for a single Processor across all plugin formats.
ViewRole
Role of a view attached to a ViewBridge.
Definition view_bridge.hpp:50
@ Editor
Definition view_bridge.hpp:51
@ Inspector
Definition view_bridge.hpp:52
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
constexpr std::uint32_t kEditorHostClearRgb
The background a plug-in editor host paints when the plug-in has not declared its own (Processor::edi...
Definition plugin_view_host.hpp:48
What a scripted editor evaluates every time it opens and that does not depend on the instance: the te...
Definition processor.hpp:593
Definition view_bridge.hpp:78
static Options hosted_editor()
Options for a primary editor embedded in a host: hot reload follows the developer's PULP_DEV_HOT_RELO...
Definition view_bridge.hpp:112
ViewRole role
Definition view_bridge.hpp:80
bool content_first_open
Hand the host an editor whose first frame is already the settled document (see prepare_first_frame())...
Definition view_bridge.hpp:98
bool defer_document_load
Return the view before evaluating its scripted document (see view::ScopedDeferredDocumentLoad).
Definition view_bridge.hpp:87
bool enable_hot_reload
Poll scripted UI + theme.json for changes.
Definition view_bridge.hpp:79
Editor size hints (in logical pixels).
Definition plugin_descriptor.hpp:27