feat: add per-node Ableton Link Audio publishing #1

Merged
peterswimm merged 1 commit from feat/per-node-link-audio-publish into main 2026-08-28 15:33:03 +00:00
Owner

Any plugin/built-in effect node, plus the Audio Input and Audio Output
device nodes, can now be individually opted in to publish its own
rendered audio as a named Link Audio sink, alongside the existing
master-bus sink - mirroring how Ableton Live exposes per-track Link
Audio routing rather than only a master send.

  • AudioTapSource: shared mixin implemented by BypassableInstance (covers
    every VST3/AU plugin and built-in effect processor). Device I/O nodes
    can't implement it directly - JUCE's AudioProcessorGraph renders
    AudioGraphIOProcessor nodes via direct buffer copies (AudioInOp/
    AudioOutOp) rather than calling processBlock(), so they're tapped via
    two dedicated slots on LinkAudioService fed from
    MeteringProcessorPlayer's existing audio callback instead.
  • LinkAudioService: new per-node sink registry (registerNodeSink/
    unregisterNodeSink/publishNodeAudio), with teardown ordering that
    keeps the audio thread from ever touching a sink mid-destruction.
  • FilterGraph: setNodeLinkAudioPublish/isNodeLinkAudioPublishEnabled/
    canNodePublishToLinkAudio as the single dispatch point; persists the
    choice per-node in patch XML; cleans up on node deletion and graph
    clear/restore.
  • UI: a dedicated "LINK" footer button (left-click popup menu) on
    eligible nodes, shown only while Link Audio is enabled in
    Preferences.

Also fixes two bugs found while testing this interactively:

  • PluginField::deleteConnection() dereferenced a connection's source/
    destination pins unconditionally, but a connection being actively
    dragged from an output pin has a null destination until dropped on a
    pin - right-clicking that in-progress cable crashed.
  • The same function read a connection's getParameterConnection() after
    deleting it (use-after-free).
Any plugin/built-in effect node, plus the Audio Input and Audio Output device nodes, can now be individually opted in to publish its own rendered audio as a named Link Audio sink, alongside the existing master-bus sink - mirroring how Ableton Live exposes per-track Link Audio routing rather than only a master send. - AudioTapSource: shared mixin implemented by BypassableInstance (covers every VST3/AU plugin and built-in effect processor). Device I/O nodes can't implement it directly - JUCE's AudioProcessorGraph renders AudioGraphIOProcessor nodes via direct buffer copies (AudioInOp/ AudioOutOp) rather than calling processBlock(), so they're tapped via two dedicated slots on LinkAudioService fed from MeteringProcessorPlayer's existing audio callback instead. - LinkAudioService: new per-node sink registry (registerNodeSink/ unregisterNodeSink/publishNodeAudio), with teardown ordering that keeps the audio thread from ever touching a sink mid-destruction. - FilterGraph: setNodeLinkAudioPublish/isNodeLinkAudioPublishEnabled/ canNodePublishToLinkAudio as the single dispatch point; persists the choice per-node in patch XML; cleans up on node deletion and graph clear/restore. - UI: a dedicated "LINK" footer button (left-click popup menu) on eligible nodes, shown only while Link Audio is enabled in Preferences. Also fixes two bugs found while testing this interactively: - PluginField::deleteConnection() dereferenced a connection's source/ destination pins unconditionally, but a connection being actively dragged from an output pin has a null destination until dropped on a pin - right-clicking that in-progress cable crashed. - The same function read a connection's getParameterConnection() after deleting it (use-after-free).
Any plugin/built-in effect node, plus the Audio Input and Audio Output
device nodes, can now be individually opted in to publish its own
rendered audio as a named Link Audio sink, alongside the existing
master-bus sink - mirroring how Ableton Live exposes per-track Link
Audio routing rather than only a master send.

- AudioTapSource: shared mixin implemented by BypassableInstance (covers
  every VST3/AU plugin and built-in effect processor). Device I/O nodes
  can't implement it directly - JUCE's AudioProcessorGraph renders
  AudioGraphIOProcessor nodes via direct buffer copies (AudioInOp/
  AudioOutOp) rather than calling processBlock(), so they're tapped via
  two dedicated slots on LinkAudioService fed from
  MeteringProcessorPlayer's existing audio callback instead.
- LinkAudioService: new per-node sink registry (registerNodeSink/
  unregisterNodeSink/publishNodeAudio), with teardown ordering that
  keeps the audio thread from ever touching a sink mid-destruction.
- FilterGraph: setNodeLinkAudioPublish/isNodeLinkAudioPublishEnabled/
  canNodePublishToLinkAudio as the single dispatch point; persists the
  choice per-node in patch XML; cleans up on node deletion and graph
  clear/restore.
- UI: a dedicated "LINK" footer button (left-click popup menu) on
  eligible nodes, shown only while Link Audio is enabled in
  Preferences.

Also fixes two bugs found while testing this interactively:
- PluginField::deleteConnection() dereferenced a connection's source/
  destination pins unconditionally, but a connection being actively
  dragged from an output pin has a null destination until dropped on a
  pin - right-clicking that in-progress cable crashed.
- The same function read a connection's getParameterConnection() after
  deleting it (use-after-free).
peterswimm deleted branch feat/per-node-link-audio-publish 2026-08-28 15:33:04 +00:00
Sign in to join this conversation.
No reviewers
No labels
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
fux-capacity/Pedalboardx8!1
No description provided.