Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
native_handle_visitor.hpp
Go to the documentation of this file.
1#pragma once
2
3// NativeHandleVisitor — typed plugin introspection.
4//
5// PluginSlot intentionally abstracts the format (VST3, AU, CLAP, LV2) so that
6// host code can drive any plugin through a single interface. Sometimes,
7// though, host code needs the underlying format-specific handle: a panel
8// might want to surface the `clap_plugin_id`, a debugger might want the
9// VST3 `IComponent*`, a CoreAudio-aware UI might want the `AudioComponent`.
10// Punching that out with a `void*` getter would leak the abstraction and
11// invite undefined behavior the moment a caller cast the wrong way.
12//
13// So the escape hatch is a double-dispatch visitor instead. Host code
14// subclasses `NativeHandleVisitor`, overrides only the `visit_*` methods for
15// the formats it can actually handle, and calls `slot.accept(visitor)`. The
16// slot — which is the only thing that knows its own format — calls back into
17// the matching `visit_*` with a populated handle struct. Two properties fall
18// out of that, and they are the whole reason for the indirection:
19//
20// * The cast is made by the code that knows the true type, so a caller can
21// never mis-cast a `void*` it was handed.
22// * A slot compiled WITHOUT a given format SDK simply never calls that
23// format's visitor method, so a visitor cannot be handed a stale or
24// half-initialized handle for a format that is not in the build.
25//
26// The format-specific handle structs deliberately avoid pulling in the
27// format SDK headers — handles are exposed as `void*` typedefs so that
28// callers that *do* link against the SDK can `static_cast<>` them back to
29// the concrete type (e.g. `static_cast<const clap_plugin_t*>(handle)`)
30// while non-SDK call sites can still link the header.
31//
32// Default `visit_*` implementations fall through to `visit_unknown(slot)`,
33// letting hosts opt-in to specific format dispatches without overriding
34// every method.
35
36#include <string>
37#include <string_view>
38
39namespace pulp::host {
40
41class PluginSlot;
42
43// Which plugin format a handle came from. Deliberately a separate enum from
44// scanner.hpp's PluginFormat (same members) so that a caller who only wants the
45// visitor does not have to pull the scanner in.
54
55// ── Per-format handle descriptors ───────────────────────────────────────
56//
57// All native handles are exposed as `void*` so this header is SDK-free.
58// Callers reinterpret_cast back to the documented concrete type. Each
59// struct carries a small handful of identifying metadata so that visitor
60// code can perform a sanity check (format / IID / category) before
61// reaching into the handle.
62
66 void* component = nullptr;
69 void* audio_processor = nullptr;
72 void* edit_controller = nullptr;
75 std::string class_id;
76};
77
80 void* component_instance = nullptr;
82 unsigned int type = 0;
83 unsigned int subtype = 0;
84 unsigned int manufacturer = 0;
85};
86
89 void* audio_unit = nullptr;
90};
91
94 void* plugin = nullptr;
97 void* host = nullptr;
99 std::string plugin_id;
100};
101
105 void* instance = nullptr;
107 std::string uri;
108};
109
110// ── Visitor base class ──────────────────────────────────────────────────
111//
112// Subclass and override only the visit_* methods relevant to your work.
113// The default fallthrough to `visit_unknown` means a visitor that only
114// cares about CLAP can ignore every other adapter without explicit
115// no-ops.
117public:
118 virtual ~NativeHandleVisitor() = default;
119
123 virtual void visit_unknown(const PluginSlot& /*slot*/,
124 NativeHandleFormat /*format*/) {}
125
126 virtual void visit_vst3(const PluginSlot& slot,
127 const Vst3NativeHandle& /*ext*/) {
129 }
130 virtual void visit_audio_unit(const PluginSlot& slot,
131 const AudioUnitNativeHandle& /*ext*/) {
133 }
134 virtual void visit_audio_unit_v3(const PluginSlot& slot,
135 const AudioUnitV3NativeHandle& /*ext*/) {
137 }
138 virtual void visit_clap(const PluginSlot& slot,
139 const ClapNativeHandle& /*ext*/) {
141 }
142 virtual void visit_lv2(const PluginSlot& slot,
143 const Lv2NativeHandle& /*ext*/) {
145 }
146};
147
148// ── Entry point ─────────────────────────────────────────────────────────
149//
150// PluginSlot::accept(visitor) is the canonical entry point. Its default
151// implementation in plugin_slot.hpp calls visit_unknown, so a slot that has
152// not (or cannot) identify itself still behaves sensibly. Each format-specific
153// slot overrides accept() to dispatch into the matching visit_* method with a
154// populated `*NativeHandle` struct.
155
156// ── Deprecated spellings ────────────────────────────────────────────────
157//
158// Kept so existing host code keeps compiling; every alias names the identical
159// type. The new names say what the values are — native, format-specific
160// handles — rather than the vaguer "extension".
161
162
163} // namespace pulp::host
Definition native_handle_visitor.hpp:116
virtual void visit_vst3(const PluginSlot &slot, const Vst3NativeHandle &)
Definition native_handle_visitor.hpp:126
virtual void visit_unknown(const PluginSlot &, NativeHandleFormat)
Called when the slot represents a format the visitor did not override, or when the slot itself does n...
Definition native_handle_visitor.hpp:123
virtual void visit_audio_unit(const PluginSlot &slot, const AudioUnitNativeHandle &)
Definition native_handle_visitor.hpp:130
virtual void visit_audio_unit_v3(const PluginSlot &slot, const AudioUnitV3NativeHandle &)
Definition native_handle_visitor.hpp:134
virtual void visit_lv2(const PluginSlot &slot, const Lv2NativeHandle &)
Definition native_handle_visitor.hpp:142
virtual ~NativeHandleVisitor()=default
virtual void visit_clap(const PluginSlot &slot, const ClapNativeHandle &)
Definition native_handle_visitor.hpp:138
Definition plugin_slot.hpp:94
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
NativeHandleFormat
Definition native_handle_visitor.hpp:46
@ VST3
Definition native_handle_visitor.hpp:48
@ LV2
Definition native_handle_visitor.hpp:52
@ CLAP
Definition native_handle_visitor.hpp:51
@ Unknown
Definition native_handle_visitor.hpp:47
@ AudioUnit
Definition native_handle_visitor.hpp:49
@ AudioUnitV3
Definition native_handle_visitor.hpp:50
Definition native_handle_visitor.hpp:78
unsigned int manufacturer
OSType (manufacturer code).
Definition native_handle_visitor.hpp:84
void * component_instance
AudioComponentInstance (a.k.a. AudioUnit). Owned by the slot.
Definition native_handle_visitor.hpp:80
unsigned int subtype
OSType (manufacturer-defined).
Definition native_handle_visitor.hpp:83
unsigned int type
AU component description fields, populated at load time.
Definition native_handle_visitor.hpp:82
Definition native_handle_visitor.hpp:87
void * audio_unit
AUAudioUnit*. Bridged-Objective-C pointer, owned by the slot.
Definition native_handle_visitor.hpp:89
Definition native_handle_visitor.hpp:92
void * plugin
const clap_plugin_t* — the plugin instance. Owned by the slot.
Definition native_handle_visitor.hpp:94
std::string plugin_id
CLAP plugin id, e.g. "com.pulp.gain".
Definition native_handle_visitor.hpp:99
void * host
const clap_host_t* — host-side struct the plugin was created against.
Definition native_handle_visitor.hpp:97
Definition native_handle_visitor.hpp:102
std::string uri
LV2 plugin URI, e.g. "https://example.com/plugins/gain".
Definition native_handle_visitor.hpp:107
void * instance
LilvInstance* if the loader uses lilv; otherwise opaque to the host (loader-specific).
Definition native_handle_visitor.hpp:105
Definition native_handle_visitor.hpp:63
void * edit_controller
Steinberg::Vst::IEditController* — non-null for plugins that expose a controller.
Definition native_handle_visitor.hpp:72
std::string class_id
FUID string of the plugin's processor class, e.g.
Definition native_handle_visitor.hpp:75
void * audio_processor
Steinberg::Vst::IAudioProcessor* — non-null when the plugin implements the audio-processor interface ...
Definition native_handle_visitor.hpp:69
void * component
Steinberg::Vst::IComponent* — the audio-processing side of the plugin.
Definition native_handle_visitor.hpp:66