ViewBridge: Processor editor lifecycle + VST3/CLAP wiring (Feature 1, Phase 1 + core Phase 2) - #140
Conversation
…VST3 wiring
Phase 1 of Feature 1 (ViewBridge).
- core/format/include/pulp/format/processor.hpp: add ViewSize struct,
virtual create_view() → unique_ptr<view::View> (default nullptr, framework
falls back to scripted/AutoUi), virtual view_size(), lifecycle callbacks
on_view_opened / on_view_closed / on_view_resized.
- core/format/src/format.cpp: out-of-line create_view() definition anchors
the Processor vtable (previously floating, caused link errors once
create_view became the first virtual in the translation unit). Registered
in core/format/CMakeLists.txt.
- core/format/{include/pulp/format/view_bridge.hpp,src/view_bridge.cpp}:
ViewBridge class owns the view tree, calls Processor lifecycle hooks on
attach/detach, tracks resizes.
- core/format/src/vst3_plug_view.cpp + .hpp: replace raw editor_root_ /
scripted_ui_ with a ViewBridge member; attach/detach/resize go through
the bridge so host-thread lifecycle callbacks fire consistently.
- test/test_view_bridge.cpp: 4 test cases / 31 assertions covering headless
view creation, default AutoUi fallback, lifecycle callback ordering, and
resize propagation. Registered in test/CMakeLists.txt. Green.
- examples/view-bridge-demo: minimal demo wiring a custom View via
create_view() and attaching it through ViewBridge.
- docs/guides/view-bridge.md + docs/reference/modules.md updates.
CLAP adapter wiring and multi-view secondary attach remain for Phase 1-2
follow-ups.
Phase 1 CLAP item from Feature 1 (ViewBridge) plan. - core/format/include/pulp/format/clap_adapter.hpp: PulpClapPlugin now owns a unique_ptr<ViewBridge> instead of raw editor_root_ + scripted_ui_ fields. editor_host still owns the platform window surface. - core/format/include/pulp/format/clap_entry.hpp: gui_create builds the bridge, gui_destroy tears it down, gui_get_size reads size hints from the bridge, gui_set_size dispatches to bridge->resize() so Processor::on_view_resized fires with the host's new dimensions. Build clean. ctest: 2080/2080 pass.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 198b0f2fa3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…dex P2 on PR #140) Codex flagged that Processor::on_view_opened was firing in ViewBridge::open(), but adapters call open() *before* attaching the view to the native parent window. Host-window-dependent resources initialized in on_view_opened could run too early, and if attach later failed the open/close dispatch would be unbalanced. - ViewBridge::open() now builds the view only; does not fire on_view_opened. - ViewBridge::notify_attached() is the new second step — adapters call it after successfully attaching to the host parent. Idempotent. - ViewBridge::close() fires on_view_closed only when notify_attached had fired, so failed-attach paths tear down cleanly without a spurious on_view_closed. - ViewBridge::resize() only dispatches on_view_resized while attached. - VST3 PulpPlugView::attached(): calls bridge_.notify_attached() after CPluginView::attached succeeds; cleans up via bridge_.close() on failure. - CLAP gui_set_parent: calls bridge->notify_attached() only when attach_to_parent actually matched a supported window API. - Tests: two new cases cover deferred dispatch (open→notify_attached ordering, idempotent second notify, pre-attach resize is a no-op) and failed-attach balance (close without notify_attached fires nothing). - Demo + guide updated to document the two-step attach protocol. ctest: 7/7 view-bridge tests green, full suite 2080/2080.
|
Codex P2 addressed in b86838d. |
# Conflicts: # planning
Summary
Adds ViewBridge — editor-view lifecycle and multi-view primitives sitting between
Processorand every format adapter. Implements Feature 1 Phase 1 (core API + tests + VST3 + CLAP) and Phase 2 core (secondary views, count/role queries, lifecycle callbacks). Phase 3 adapter-parity for AU/standalone/AAX/WAM and inspector auto-attach are out of scope for this PR and tracked as follow-ups.Core API (
core/format/)Processor::create_view()→std::unique_ptr<view::View>(default nullptr, framework falls back to scripted UI / AutoUi)Processor::view_size()returningViewSize { preferred/min/max w+h }(0 max = unbounded)on_view_opened,on_view_closed,on_view_resizedViewBridgeclass — owns the view, dispatches lifecycle, tracks size hints, supports secondary views viaattach_secondary_view(view, ViewRole)/detach_secondary_view/view_count/view_at/role_atFormat adapters wired
vst3_plug_view.{hpp,cpp}): PulpPlugView owns aViewBridge bridge_;attached/removed/onSizenow route host events through the bridge soProcessor::on_view_*fires consistently.clap_adapter.hpp,clap_entry.hpp):PulpClapPlugin::bridgereplaces raweditor_root+scripted_uifields;gui_create,gui_destroy,gui_get_size,gui_set_sizeall route through the bridge.Tests
test/test_view_bridge.cpp— 4 Catch2 cases / 31 assertions covering: AutoUi fallback whencreate_viewreturns nullptr, custom view returned bycreate_view, secondary-view attach/role-query/detach, RAII close-on-destruct.examples/view-bridge-demo/— headless runnable demo + ctest registration exercising the full open → attach inspector → resize → detach → close flow.Docs + plan
docs/guides/view-bridge.md— new public guidedocs/reference/modules.md— adds ViewBridge row under format moduleplanning/next-features-plan.md— Feature 1 checkboxes updated for Phase 1 (VST3+CLAP+tests) and Phase 2 (secondary-view API + shared-StateStore binding propagation)Out of scope (follow-ups)
ViewBridge::release_viewfor TabPanel ownership), AAX, WAM/WCLAPTest plan
cmake --build build -j\$(sysctl -n hw.ncpu)clean on macOS ARM64ctest --test-dir build --output-on-failure --exclude-regex AudioWorkgroup→ 2080/2080 passpulp-test-view-bridge→ 4/4 Catch2 cases, 31 assertionspulp-view-bridge-democtest entry → passes