Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
editor_ui.hpp
Go to the documentation of this file.
1#pragma once
2
12#include <atomic>
13#include <filesystem>
14#include <memory>
15#include <optional>
16#include <string>
17#include <string_view>
18#include <system_error>
19#include <vector>
20
21namespace pulp::format {
22
30 Processor& processor, runtime::AliveToken::Handle owner_alive) {
31 return [processor = &processor, owner = std::move(owner_alive)](
32 const view::ValueChannelVisitor& visitor) {
34 visitor(nullptr);
35 return;
36 }
37 PULP_TRY { processor->visit_value_channels(visitor); }
38 PULP_CATCH_ALL { visitor(nullptr); }
39 };
40}
41
43 std::unique_ptr<view::View> root;
44 std::unique_ptr<view::ScriptedUiSession> scripted_ui;
45 bool uses_script_ui = false;
46};
47
50inline std::optional<std::filesystem::path> configured_ui_script_path(const EditorAssets& assets) {
51 if (assets.script_path == nullptr || assets.script_path[0] == '\0')
52 return std::nullopt;
53 return std::filesystem::path{assets.script_path};
54}
55
57inline std::optional<std::filesystem::path> configured_ui_theme_path(const EditorAssets& assets) {
58 if (assets.theme_path == nullptr || assets.theme_path[0] == '\0')
59 return std::nullopt;
60 return std::filesystem::path{assets.theme_path};
61}
62
64inline std::vector<std::filesystem::path> configured_ui_asset_roots(const EditorAssets& assets) {
65 std::vector<std::filesystem::path> roots;
66 if (assets.asset_roots == nullptr)
67 return roots;
68 std::string_view raw{assets.asset_roots};
69 while (!raw.empty()) {
70 const auto split = raw.find('|');
71 const auto item = raw.substr(0, split);
72 if (!item.empty()) roots.emplace_back(std::string(item));
73 if (split == std::string_view::npos) break;
74 raw.remove_prefix(split + 1);
75 }
76 return roots;
77}
78
80inline std::optional<std::filesystem::path> configured_ui_script_path() {
82}
83
85inline std::optional<std::filesystem::path> configured_ui_theme_path() {
87}
88
90inline std::vector<std::filesystem::path> configured_ui_asset_roots() {
92}
93
95inline std::vector<view::WidgetBridge::EmbeddedAsset>
97 std::vector<view::WidgetBridge::EmbeddedAsset> files;
98 if (assets.files == nullptr)
99 return files;
100 files.reserve(assets.file_count);
101 for (std::size_t i = 0; i < assets.file_count; ++i) {
102 const auto& file = assets.files[i];
103 if (file.name == nullptr || file.name[0] == '\0' || file.data == nullptr || file.size == 0)
104 continue;
105 files.push_back({file.name, file.data, file.size});
106 }
107 return files;
108}
109
114 std::filesystem::path script_path;
115 std::string script_source;
116 std::string theme_source;
117 std::string script_name;
119 std::vector<view::WidgetBridge::EmbeddedAsset> embedded_assets;
120 bool available() const noexcept {
121 return !script_path.empty() || !script_source.empty();
122 }
123 bool embedded() const noexcept {
124 return script_path.empty() && !script_source.empty();
125 }
126
127 std::string label() const {
128 return script_path.empty() ? script_name : script_path.string();
129 }
130};
131
140inline EditorUiSource select_editor_ui_source(const EditorAssets& assets, bool enable_hot_reload) {
141 EditorUiSource source;
142 const auto dev_script_path = configured_ui_script_path(assets);
143 const bool dev_file_present = [&] {
144 if (!dev_script_path)
145 return false;
146 std::error_code ec;
147 return std::filesystem::is_regular_file(*dev_script_path, ec) && !ec;
148 }();
149 if (embeds_editor_script(assets) && !(enable_hot_reload && dev_file_present)) {
150 source.script_source.assign(reinterpret_cast<const char*>(assets.script),
151 assets.script_size);
152 if (assets.theme != nullptr && assets.theme_size > 0)
153 source.theme_source.assign(reinterpret_cast<const char*>(assets.theme),
154 assets.theme_size);
155 source.script_name = assets.script_name != nullptr && assets.script_name[0] != '\0'
156 ? assets.script_name
157 : "ui.js";
158 source.embedded_assets = embedded_ui_assets(assets);
159 return source;
160 }
161 if (dev_script_path)
162 source.script_path = *dev_script_path;
163 return source;
164}
165
172 EditorUiSource source, state::StateStore& store,
173 bool enable_hot_reload, std::string* error,
174 view::ValueChannelAccess value_channel_access,
175 std::string_view storage_identity);
176
183inline std::atomic<ScriptedEditorBuilder>& scripted_editor_builder_slot() noexcept {
184 static std::atomic<ScriptedEditorBuilder> builder{nullptr};
185 return builder;
186}
187
196 state::StateStore& store, bool enable_hot_reload,
197 std::string* error,
198 view::ValueChannelAccess value_channel_access,
199 std::string_view storage_identity = {}) {
200 // Selected once here: choosing it stats the on-disk script, and the
201 // builder evaluates exactly the document this check found.
202 if (auto source = select_editor_ui_source(assets, enable_hot_reload); source.available()) {
203 if (auto builder = scripted_editor_builder_slot().load(std::memory_order_acquire)) {
204 auto instance = builder(assets, std::move(source), store, enable_hot_reload, error,
205 std::move(value_channel_access), storage_identity);
206 if (instance.root)
207 return instance;
208 } else {
209 const std::string missing =
210 "this binary declares a scripted editor but does not link the script runtime; "
211 "declare UI_SCRIPT on the plug-in target or call "
212 "pulp::format::install_scripted_editor_builder()";
213 runtime::log_error("Scripted editor UI not built: {}. Falling back to AutoUi.",
214 missing);
215 if (error && error->empty())
216 *error = missing;
217 }
218 }
219
220 auto root = view::AutoUi::build(store);
221 if (!root && error) {
222 *error = "AutoUi::build() returned nullptr";
223 }
224 return {std::move(root), nullptr, false};
225}
226
228inline EditorUiInstance
230 std::string* error,
231 view::ValueChannelAccess value_channel_access) {
232 return build_editor_ui_for_assets(registered_editor_assets(), store, enable_hot_reload, error,
233 std::move(value_channel_access));
234}
235
239 bool enable_hot_reload,
240 std::string* error = nullptr,
241 view::ValueChannelSet* value_channels = nullptr) {
243 if (value_channels != nullptr) {
244 access = [value_channels](const view::ValueChannelVisitor& visitor) {
245 visitor(value_channels);
246 };
247 }
249 store, enable_hot_reload, error, std::move(access));
250}
251
252} // namespace pulp::format
A processor's declared channels.
Definition value_channel_set.hpp:61
Definition processor.hpp:174
virtual void visit_value_channels(const std::function< void(view::ValueChannelSet *)> &visitor)
Synchronously visit the current value-channel set while the processor keeps it alive.
Definition processor.hpp:1123
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
static std::unique_ptr< View > build(state::StateStore &store)
Portable try/catch macros for source that must also compile with C++ exceptions disabled (-fno-except...
#define PULP_TRY
Definition exceptions.hpp:42
#define PULP_CATCH_ALL
Definition exceptions.hpp:43
std::function< void(ValueChannelSet *)> ValueChannelVisitor
Runs a value-channel operation while the hosting processor guarantees that the exposed set and all of...
Definition value_channel_set.hpp:52
std::function< void(const ValueChannelVisitor &)> ValueChannelAccess
Definition value_channel_set.hpp:53
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
@ file
Definition test_signal.hpp:14
EditorAssets registered_editor_assets() noexcept
The binary-wide record from register_editor_assets(), or an empty record.
EditorUiSource select_editor_ui_source(const EditorAssets &assets, bool enable_hot_reload)
Pick the document for a default scripted editor from the record the plug-in registered.
Definition editor_ui.hpp:140
@ error
Definition validation_harness.hpp:20
EditorUiInstance build_editor_ui(state::StateStore &store, bool enable_hot_reload, std::string *error=nullptr, view::ValueChannelSet *value_channels=nullptr)
Compatibility entry point for stable processors and callers without a processor.
Definition editor_ui.hpp:238
EditorUiInstance(*)(const EditorAssets &assets, EditorUiSource source, state::StateStore &store, bool enable_hot_reload, std::string *error, view::ValueChannelAccess value_channel_access, std::string_view storage_identity) ScriptedEditorBuilder
Builds the scripted editor from source, the document select_editor_ui_source() chose for assets (the ...
Definition editor_ui.hpp:171
EditorUiInstance build_editor_ui_for_assets(const EditorAssets &assets, state::StateStore &store, bool enable_hot_reload, std::string *error, view::ValueChannelAccess value_channel_access, std::string_view storage_identity={})
Build the editor assets declares: a scripted UI when it names or embeds a script and the binary links...
Definition editor_ui.hpp:195
EditorUiInstance build_editor_ui_with_value_channel_access(state::StateStore &store, bool enable_hot_reload, std::string *error, view::ValueChannelAccess value_channel_access)
The editor this binary declares (see register_editor_assets()).
Definition editor_ui.hpp:229
std::optional< std::filesystem::path > configured_ui_script_path()
This binary's on-disk scripted-UI entry file (see register_editor_assets()).
Definition editor_ui.hpp:80
std::vector< std::filesystem::path > configured_ui_asset_roots()
This binary's asset directories.
Definition editor_ui.hpp:90
std::vector< view::WidgetBridge::EmbeddedAsset > embedded_ui_assets(const EditorAssets &assets)
The files embedded beside assets' script, as the bridge consumes them.
Definition editor_ui.hpp:96
bool embeds_editor_script(const EditorAssets &assets) noexcept
True when assets carries an embedded entry script.
view::ValueChannelAccess processor_value_channel_access(Processor &processor, runtime::AliveToken::Handle owner_alive)
Build the UI-thread accessor used by scripted editors.
Definition editor_ui.hpp:29
std::optional< std::filesystem::path > configured_ui_theme_path()
This binary's on-disk theme / design-token file.
Definition editor_ui.hpp:85
std::atomic< ScriptedEditorBuilder > & scripted_editor_builder_slot() noexcept
The scripted editor builder this binary links, or null.
Definition editor_ui.hpp:183
void log_error(std::format_string< Args... > fmt, Args &&... args)
Definition log.hpp:195
Definition editor_assets.hpp:47
const char * theme_path
Absolute path of the theme / design-token file. Null or empty: none.
Definition editor_assets.hpp:51
const EmbeddedEditorFile * files
Files embedded beside the script, resolved by the embedded editor in place of its script directory.
Definition editor_assets.hpp:67
const char * asset_roots
'|'-separated absolute directories the script may load assets from.
Definition editor_assets.hpp:53
std::size_t file_count
Definition editor_assets.hpp:68
std::size_t script_size
Definition editor_assets.hpp:61
const char * script_path
Absolute path of the scripted-UI entry file. Null or empty: none.
Definition editor_assets.hpp:49
const unsigned char * theme
The embedded theme override (JSON), or null/0 when the build had none.
Definition editor_assets.hpp:63
const unsigned char * script
The embedded entry script's bytes.
Definition editor_assets.hpp:60
std::size_t theme_size
Definition editor_assets.hpp:64
const char * script_name
File name of the embedded entry script (main.js), for diagnostics.
Definition editor_assets.hpp:57
Definition editor_ui.hpp:42
std::unique_ptr< view::View > root
Definition editor_ui.hpp:43
bool uses_script_ui
Definition editor_ui.hpp:45
std::unique_ptr< view::ScriptedUiSession > scripted_ui
Definition editor_ui.hpp:44
Where the default scripted editor's document comes from.
Definition editor_ui.hpp:111
std::string label() const
What log lines call the document.
Definition editor_ui.hpp:127
std::string script_name
Definition editor_ui.hpp:117
std::string theme_source
Definition editor_ui.hpp:116
std::filesystem::path script_path
Set when the editor reads this file (and its sibling theme.json) from disk; empty when it evaluates s...
Definition editor_ui.hpp:114
bool embedded() const noexcept
Definition editor_ui.hpp:123
bool available() const noexcept
Definition editor_ui.hpp:120
std::vector< view::WidgetBridge::EmbeddedAsset > embedded_assets
Files embedded beside an embedded script; empty for an on-disk document.
Definition editor_ui.hpp:119
std::string script_source
Definition editor_ui.hpp:115
Source-compatible spelling of <pulp/dataplane/value_channel_set.hpp>.