105 lines
6.6 KiB
Markdown
105 lines
6.6 KiB
Markdown
# External plugin hosting evaluation
|
|
|
|
Historical Phase 9 decision: defer external hosting. The native source API is useful
|
|
for proving processor contracts without adding an SDK or scanning/loading code.
|
|
|
|
| Candidate | Benefits | Work required before adoption |
|
|
| --- | --- | --- |
|
|
| LV2 | Open specifications, established Linux hosts/plugins | RDF discovery and feature negotiation, URIDs, state, UI lifetime, worker requests and event mapping; likely additional discovery dependency |
|
|
| CLAP | C ABI, explicit lifecycle and event model | Extension negotiation, parameter/state persistence, host callbacks, main/audio-thread scheduling and UI integration |
|
|
| VST3 | Broad plugin availability | SDK/license review for the selected SDK release, C++ adapter outside the C core, component/controller and editor lifecycle, state and event translation |
|
|
|
|
No candidate was linked, scanned or loaded in this phase. API/SDK and plugin
|
|
licenses must be checked at the revision actually adopted; they are separate
|
|
from xtc's MIT license. Supporting a format does not grant redistribution rights
|
|
to individual plugins. Do not search user plugin directories from the callback.
|
|
|
|
Before implementation, require versioned module identity and state, a missing-
|
|
plugin recovery policy, preparation failure/partial cleanup tests, bounded events
|
|
and parameter publication, latency/tail handling, callback-safe unload after
|
|
retirement, a GUI/main-thread boundary and an explicit crash-containment decision.
|
|
Native ABI tests cover some ownership mechanics but do not prove third-party
|
|
code safe. Event graph ports and custom-instrument GUI selection remain gaps.
|
|
Choose one format with concrete user needs after those contracts are specified;
|
|
do not introduce a general multi-format framework now. See decision 0008.
|
|
|
|
## Phase 15 implementation (supersedes the Phase 9 deferral)
|
|
|
|
Decision [0009](decisions/0009-parameter-processors-and-ladspa.md) selects a bounded
|
|
LADSPA 1.1 host. `xtc_plugin.h` is the C API; no C++ engine or FLTK type is needed.
|
|
|
|
1. Choose **File → Load LADSPA plugin** and a trusted absolute `.so` path. Loading
|
|
executes native code immediately, including constructors during discovery.
|
|
2. The dialog lists compatible descriptor indices/labels. Select an index.
|
|
3. In the Modular Graph, connect the new source/effect output to an output or
|
|
other effect; effects have an optional mono input. Unconnected effect inputs
|
|
receive external input, as other graph processors do.
|
|
4. Select its node and use **Edit → Selected plugin control**. The dialog shows
|
|
actual port IDs, names, values and rate-adjusted ranges. Enter a port and value.
|
|
Toggled controls require 0/1 and integer controls require integral values.
|
|
5. Save normally, reopen, reconnect external JACK playback if needed, and Play.
|
|
Plugin changes stop/rebuild playback and participate in ordinary undo/redo.
|
|
|
|
The GUI uses only public graph/model/plugin APIs. Discovery probes explicit module
|
|
files by descriptor index, bounded to 1024 descriptors. It never recursively scans
|
|
system directories. The C API exposes probe, parameter metadata, instance
|
|
create/process/destroy, and add/get/set graph configuration. Missing header means
|
|
hosting returns UNSUPPORTED; metadata persistence continues to work.
|
|
|
|
Supported: 0/1 audio input, 1 output, <=64 total ports and <=16 input controls.
|
|
Stereo graph channels are two independent mono instances. Stereo/multichannel
|
|
LADSPA descriptors are rejected, rather than downmixed silently. Control output
|
|
ports have private storage; no output-control GUI is implemented. No plugin UI,
|
|
MIDI/events, sample automation, worker interface, latency compensation or opaque
|
|
state is supplied by this first format. Parameter configuration is persisted;
|
|
oscillator phase, held voices, delay history and tails are not. No smoothing is
|
|
added around plan replacement. Integer LADSPA sample rates are obtained from the
|
|
engine rate; practical backend rates are integral.
|
|
|
|
A new plan opens and owns its own modules and instances. Failed loading,
|
|
incompatible identity/range/layout, or instantiate returning NULL unwinds the
|
|
candidate and leaves active/pending plans intact. Only run and bounded host
|
|
buffer copies execute in audio. Destruction and unloading happen after callback
|
|
quiescence or retirement acknowledgement on the control thread. Transport reset
|
|
retains LADSPA history; compile/reopen starts fresh. A LADSPA run callback has no
|
|
error return. Nonfinite/subnormal samples become zero, but native crashes,
|
|
corruption, runaway CPU, allocations or I/O inside a plugin cannot be contained
|
|
or prevented. Use trusted plugins; hard-realtime properties are declarations,
|
|
not proof. This is an in-process host, not a crash-isolation service.
|
|
|
|
Project v5 stores absolute module path, index, label, LADSPA unique ID, mono input
|
|
count and ordered input-control port/value pairs. Restore verifies identity,
|
|
layout, parameter ports and ranges against the loaded module. No pointers are
|
|
serialized. Relocating a module requires restoring it at its saved absolute path
|
|
or deliberately modifying its metadata through a C client. GUI Open reports the
|
|
missing/incompatible identity/path and retains the current document. Metadata
|
|
load/save and `xtc-check --validate` do not execute plugin code and do not certify
|
|
module availability. LADSPA IDs are not cryptographic binary/version identities.
|
|
|
|
## Repeatable acceptance
|
|
|
|
```sh
|
|
make all test gui test-plugins test-gui-plugins analyze
|
|
make test-plugins-real
|
|
```
|
|
|
|
The first plugin target builds an original MIT shared-library fixture with gain,
|
|
source, unsupported stereo and failed-initialization descriptors. Tests exercise
|
|
identity/range errors, exact in-place gain, save/reopen/exact rendering, missing
|
|
module metadata preservation and 100 plan replacements with callback guards
|
|
against host allocation/free/dlopen/dlclose. GUI commands cover add, control edit,
|
|
invalid-value rollback, undo/redo and save/New/reopen. ASan/UBSan/leak checks cover
|
|
host/fixture lifetimes; plugin code from system packages is not instrumented.
|
|
|
|
`test-plugins-real` requires these separately installed modules (nothing is
|
|
bundled or installed by the target):
|
|
|
|
| Module / descriptor | Tested behavior |
|
|
| --- | --- |
|
|
| `/usr/lib/ladspa/amp.so`, 0 `amp_mono` | One input, gain control, finite nonzero render, exact save/reopen render |
|
|
| `/usr/lib/ladspa/inv_1429.so`, 0 `inv` | One input, no controls, exact save/reopen render |
|
|
| `/usr/lib/ladspa/sine.so`, 3 `sine_fcac` | No input, frequency/amplitude controls, exact save/reopen render |
|
|
|
|
Tested packages: ladspa 1.17-7 and swh-plugins 0.4.17-7. These zero-latency
|
|
processors define the initial compatible set; other plugins remain unqualified.
|
|
Physical listening and plugin CPU/endurance qualification remain pending.
|