Remove the CLAP plugin: the workstation and the fabric are the product, and the shell is a convenience every stage pays for #147

Closed
opened 2026-10-06 00:49:15 +00:00 by bcox · 0 comments
Owner

bcox said on 2026-10-05 that the plugin is a vague convenience only and he is considering dropping it, and asked for this proposal. Tree claims are from reading cd68bd3e on main; counts are from grep over the BUILD files and sources on that day. Nothing here is done.

Two things called plugin/

The directory holds the engine's host-side core and the CLAP shell over it, and only the shell is this ticket's subject.

The core is what the rest of the tree builds on: Instrument (a program's notes routed to one channel of a pool, "with no CLAP types anywhere in it", as its header says), Program (the patch authority a channel loads), RegionHost and PageAllocator, EditSlot (which fabric/fabric.h includes), preset_location.h, particle_atmosphere.h, va_ports.h (stage F8b's words for the RTL), the goldens, the engine tests and the benches. Outside plugin/, BUILD files depend on //plugin:instrument 74 times, :program 62, :region_host 9, :preset_location 6, :particle_atmosphere 5, :page_allocator 3, :va_ports 1 and :edit_slot 1. All of that stays.

The shell is plugin.cc (the CLAP ABI translation, the factory, the parameter and state extensions, preset load), gui.h/gui.cc and gui_window.h/gui_window.cc (the editor's views in a host-supplied X11 child window), edit_bridge.h (the plugin's EditSink), editor_hook.h, plugin_descriptor.h, preset_provider.h and preset_invalidation.h (clap.preset-discovery), midi_pitch.h (the CLAP note dialect's bend state), macro_requests.h (the GUI-to-audio macro crossing), clap_entry.map, and their tests: host_smoke_test.cc (sixty cases through the ABI), preset_race_test.cc, edit_bridge_test.cc, macro_requests_test.cc, midi_pitch_test.cc, preset_invalidation_test.cc, glibc_floor_test.cc. No header of the shell is included anywhere outside plugin/. About 7,900 lines with third_party/glibc_floor.h.

Around the shell, and existing for it alone: the clap and clap_helpers pins in MODULE.bazel with third_party/clap.BUILD.bazel and clap_helpers.BUILD.bazel; third_party/glibc_floor.h, which editor/ and raster/ also carry so that the bundle loads into a Flatpak DAW's older glibc; the -U_FORTIFY_SOURCE on libX11 in .bazelrc, there because Flatpak Bitwig's runtime lacks the fortified wrappers; //plugin:preset_race_test in CLAUDE.md's scoped TSan list and the "belt, not the braces" paragraph; the first sentence of CLAUDE.md and README's "State of the Union", which still says the plugin has no UI and eight macros.

The position this reverses, and why it moved

The north star design (2026-09-10, "The reference posture") says: "The CLAP plugin does not go away either. It is the development vehicle, the place the goldens live, and the thing the fabric is checked against." Each of the three has since moved off the shell:

  • The goldens render through playground::Instrument: render_golden_test.cc, partial_golden_test.cc, va_shape_golden_test.cc and the rest include plugin/instrument.h and never the ABI.
  • The fabric is checked against fabric::Fabric and Instrument: tools/fabric_pool_oracle_test, //tools:engine_replay, and the F8 benches that drive the C++ instrument over the 200-voice pool.
  • The development vehicle is the workstation (//tools:workstation, stages 4a through 6c, and the HPS port in flight) and the patch editor, each with an EditSink of its own (app/patch_sink.h's PatchSink, editor/patch_document.h's PatchDocument).

What the shell alone offers today is a DAW as host: sixteen macros as automatable parameters, presets in the host's browser, per-note CLAP expressions, and the editor inside the DAW's window. The instrument's own posture is hardware: midi/ reaches all sixty-four channels from a DAW over MIDI as it would any synth, MPE included, and the song's automation lanes are where automation lives.

What it costs to keep

Every new layer kind registers in plugin.cc beside the other LayerKind switch sites (the phaser did, as the eleventh); every host-side seam grows a plugin arm (the region binding landed as "the link, the plugin, the audition engine"); the TSan lane, the glibc floor, the fortify workaround and a 2,800-line ABI test are maintained for a path nobody ships. The cost recurs per stage. The benefit is a path the workstation replaces.

What must not be lost

host_smoke_test.cc holds some engine properties through the ABI, and those need a home before the file goes. The first task is an inventory of its sixty cases, each marked CLAP-only or engine-property, with the latter either named as already held elsewhere or rewritten against Instrument or fabric::Fabric. Candidates from the names alone:

  • RestoredStateProducesIdenticalAudio: the format's exactness claim, which format/ tests hold for a .tymp and which should be stated once against Instrument.
  • StateLoadedWhileActiveIsInstalledBetweenBlocks, AStateSaveAnswersAnUncollectedEdit, SavesTheHandedOverPatchBeforeTheAudioThreadTakesIt: the edit seam. EditSlot has edit_slot_test.cc; the fabric's program_slot.h is the same handover on the product path, and //fabric:lanes_race_test and //control:threads_race_test are its race tests.
  • ALongDelayLoadedWhileActiveRendersItsEcho, AWaveguideLoadedWhileActiveSounds, TwoWaveguidesAtTheWholePoolSound, ARateThatNoLongerFitsUnbindsTheLongDelays, AnOverHalfRegionPatchIsRefused: region_host_test.cc and region_binding_test.cc exist; check each case has a twin.
  • DrainsEveryStolenNoteInOneNoteOnStorm, WildcardNoteOffReleasesEverything, ANoteStartedUnderAStandingBendIsBornBent, RpnZeroWidensTheWheel: allocator and router properties; voice_allocator_test.cc and midi/router_test.cc are where they belong.
  • ATuningExpressionDetunesOneNoteAudibly: the per-note kTuning event, which the fabric's lanes carry; hold it there.
  • ReportsDecimatorLatency: the decimator's latency figure, which the console needs for alignment anyway.

preset_race_test.cc's one property (the main thread never reads the audio thread's copy) is the plugin's own macro_names_/macro_values_; the workstation's equivalent is control/'s read model, already under //control:threads_race_test.

What is lost for real

A DAW hosting the engine in-process, with sample-accurate macro automation and the CLAP note dialect's per-note expressions. The MIDI path gives a DAW the instrument as hardware instead, and MPE gives it per-note pitch and pressure; polyphonic timbre expression (CC 74) is #48's subject either way. A person who wants the engine inside a DAW session loses that; the instrument the north star describes never had it.

Order of work

  1. The inventory above, with each engine property's new or existing test named, before anything is deleted.
  2. Delete the shell, its tests, the two pins and their BUILD files, glibc_floor.h and its uses in editor/ and raster/, and the fortify line in .bazelrc. One commit, not a deprecation: F7's own ruling is that a dead path is a defect, not an option.
  3. Rename the directory. playground is the namespace already (playground::Instrument, playground::Program); engine/ is the other candidate. The rename touches about 190 includes of instrument.h and 80 of program.h, all mechanical.
  4. Docs: CLAUDE.md's first sentence, binaries list, TSan list and the belt-and-braces paragraph; README's "State of the Union"; an addendum to the north star saying the three roles moved and where. The plugin-edit-seam, plugin-gui-window and macro-request-path designs stay as history with a one-line status note each.

Decisions for bcox

  • Go, or not.
  • The directory's new name.
  • Whether //patches:install's default directory, "the preset directory a host indexes", stays as the editor's library location once no host indexes it.
  • Whether the tymbal.clap bundle is kept buildable for one release while the workstation's install story settles, or goes in the same commit. Recommended: the same commit.
bcox said on 2026-10-05 that the plugin is a vague convenience only and he is considering dropping it, and asked for this proposal. Tree claims are from reading `cd68bd3e` on `main`; counts are from grep over the BUILD files and sources on that day. **Nothing here is done.** ## Two things called `plugin/` The directory holds the engine's host-side core and the CLAP shell over it, and only the shell is this ticket's subject. The core is what the rest of the tree builds on: `Instrument` (a program's notes routed to one channel of a pool, "with no CLAP types anywhere in it", as its header says), `Program` (the patch authority a channel loads), `RegionHost` and `PageAllocator`, `EditSlot` (which `fabric/fabric.h` includes), `preset_location.h`, `particle_atmosphere.h`, `va_ports.h` (stage F8b's words for the RTL), the goldens, the engine tests and the benches. Outside `plugin/`, BUILD files depend on `//plugin:instrument` 74 times, `:program` 62, `:region_host` 9, `:preset_location` 6, `:particle_atmosphere` 5, `:page_allocator` 3, `:va_ports` 1 and `:edit_slot` 1. All of that stays. The shell is `plugin.cc` (the CLAP ABI translation, the factory, the parameter and state extensions, preset load), `gui.h`/`gui.cc` and `gui_window.h`/`gui_window.cc` (the editor's views in a host-supplied X11 child window), `edit_bridge.h` (the plugin's `EditSink`), `editor_hook.h`, `plugin_descriptor.h`, `preset_provider.h` and `preset_invalidation.h` (clap.preset-discovery), `midi_pitch.h` (the CLAP note dialect's bend state), `macro_requests.h` (the GUI-to-audio macro crossing), `clap_entry.map`, and their tests: `host_smoke_test.cc` (sixty cases through the ABI), `preset_race_test.cc`, `edit_bridge_test.cc`, `macro_requests_test.cc`, `midi_pitch_test.cc`, `preset_invalidation_test.cc`, `glibc_floor_test.cc`. No header of the shell is included anywhere outside `plugin/`. About 7,900 lines with `third_party/glibc_floor.h`. Around the shell, and existing for it alone: the `clap` and `clap_helpers` pins in `MODULE.bazel` with `third_party/clap.BUILD.bazel` and `clap_helpers.BUILD.bazel`; `third_party/glibc_floor.h`, which `editor/` and `raster/` also carry so that the bundle loads into a Flatpak DAW's older glibc; the `-U_FORTIFY_SOURCE` on libX11 in `.bazelrc`, there because Flatpak Bitwig's runtime lacks the fortified wrappers; `//plugin:preset_race_test` in CLAUDE.md's scoped TSan list and the "belt, not the braces" paragraph; the first sentence of CLAUDE.md and README's "State of the Union", which still says the plugin has no UI and eight macros. ## The position this reverses, and why it moved The north star design (2026-09-10, "The reference posture") says: "The CLAP plugin does not go away either. It is the development vehicle, the place the goldens live, and the thing the fabric is checked against." Each of the three has since moved off the shell: - The goldens render through `playground::Instrument`: `render_golden_test.cc`, `partial_golden_test.cc`, `va_shape_golden_test.cc` and the rest include `plugin/instrument.h` and never the ABI. - The fabric is checked against `fabric::Fabric` and `Instrument`: `tools/fabric_pool_oracle_test`, `//tools:engine_replay`, and the F8 benches that drive the C++ instrument over the 200-voice pool. - The development vehicle is the workstation (`//tools:workstation`, stages 4a through 6c, and the HPS port in flight) and the patch editor, each with an `EditSink` of its own (`app/patch_sink.h`'s `PatchSink`, `editor/patch_document.h`'s `PatchDocument`). What the shell alone offers today is a DAW as host: sixteen macros as automatable parameters, presets in the host's browser, per-note CLAP expressions, and the editor inside the DAW's window. The instrument's own posture is hardware: `midi/` reaches all sixty-four channels from a DAW over MIDI as it would any synth, MPE included, and the song's automation lanes are where automation lives. ## What it costs to keep Every new layer kind registers in `plugin.cc` beside the other `LayerKind` switch sites (the phaser did, as the eleventh); every host-side seam grows a plugin arm (the region binding landed as "the link, the plugin, the audition engine"); the TSan lane, the glibc floor, the fortify workaround and a 2,800-line ABI test are maintained for a path nobody ships. The cost recurs per stage. The benefit is a path the workstation replaces. ## What must not be lost `host_smoke_test.cc` holds some engine properties through the ABI, and those need a home before the file goes. The first task is an inventory of its sixty cases, each marked CLAP-only or engine-property, with the latter either named as already held elsewhere or rewritten against `Instrument` or `fabric::Fabric`. Candidates from the names alone: - `RestoredStateProducesIdenticalAudio`: the format's exactness claim, which `format/` tests hold for a `.tymp` and which should be stated once against `Instrument`. - `StateLoadedWhileActiveIsInstalledBetweenBlocks`, `AStateSaveAnswersAnUncollectedEdit`, `SavesTheHandedOverPatchBeforeTheAudioThreadTakesIt`: the edit seam. `EditSlot` has `edit_slot_test.cc`; the fabric's `program_slot.h` is the same handover on the product path, and `//fabric:lanes_race_test` and `//control:threads_race_test` are its race tests. - `ALongDelayLoadedWhileActiveRendersItsEcho`, `AWaveguideLoadedWhileActiveSounds`, `TwoWaveguidesAtTheWholePoolSound`, `ARateThatNoLongerFitsUnbindsTheLongDelays`, `AnOverHalfRegionPatchIsRefused`: `region_host_test.cc` and `region_binding_test.cc` exist; check each case has a twin. - `DrainsEveryStolenNoteInOneNoteOnStorm`, `WildcardNoteOffReleasesEverything`, `ANoteStartedUnderAStandingBendIsBornBent`, `RpnZeroWidensTheWheel`: allocator and router properties; `voice_allocator_test.cc` and `midi/router_test.cc` are where they belong. - `ATuningExpressionDetunesOneNoteAudibly`: the per-note `kTuning` event, which the fabric's lanes carry; hold it there. - `ReportsDecimatorLatency`: the decimator's latency figure, which the console needs for alignment anyway. `preset_race_test.cc`'s one property (the main thread never reads the audio thread's copy) is the plugin's own `macro_names_`/`macro_values_`; the workstation's equivalent is `control/`'s read model, already under `//control:threads_race_test`. ## What is lost for real A DAW hosting the engine in-process, with sample-accurate macro automation and the CLAP note dialect's per-note expressions. The MIDI path gives a DAW the instrument as hardware instead, and MPE gives it per-note pitch and pressure; polyphonic timbre expression (CC 74) is #48's subject either way. A person who wants the engine inside a DAW session loses that; the instrument the north star describes never had it. ## Order of work 1. The inventory above, with each engine property's new or existing test named, before anything is deleted. 2. Delete the shell, its tests, the two pins and their BUILD files, `glibc_floor.h` and its uses in `editor/` and `raster/`, and the fortify line in `.bazelrc`. One commit, not a deprecation: F7's own ruling is that a dead path is a defect, not an option. 3. Rename the directory. `playground` is the namespace already (`playground::Instrument`, `playground::Program`); `engine/` is the other candidate. The rename touches about 190 includes of `instrument.h` and 80 of `program.h`, all mechanical. 4. Docs: CLAUDE.md's first sentence, binaries list, TSan list and the belt-and-braces paragraph; README's "State of the Union"; an addendum to the north star saying the three roles moved and where. The plugin-edit-seam, plugin-gui-window and macro-request-path designs stay as history with a one-line status note each. ## Decisions for bcox - Go, or not. - The directory's new name. - Whether `//patches:install`'s default directory, "the preset directory a host indexes", stays as the editor's library location once no host indexes it. - Whether the `tymbal.clap` bundle is kept buildable for one release while the workstation's install story settles, or goes in the same commit. Recommended: the same commit.
bcox referenced this issue from a commit 2026-10-07 00:51:24 +00:00
bcox closed this issue 2026-10-07 00:51:24 +00:00
bcox referenced this issue from a commit 2026-10-07 00:51:24 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/tymbal#147
No description provided.