# The routing model

FaustWave's audio + MIDI topology is a **single declarative routing table**, JACK-style. Every signal-producing entity is a **Source**, every signal-consuming entity is a **Sink**, and a **Connection** wires one Source's output port to one Sink's input port. The Patchbay is the matrix editor for that table; the rest of this book is about what you can do with it.

> 🟦 **NEW TO THIS?** "JACK-style" means the routing graph is **explicit, addressable, and observable**: every port has a stable id, every wire is a first-class object, and you can list / connect / disconnect with one call. The DAW you came from probably had implicit routing ("the synth's output goes to the master" — invisible). Here, every wire is in the Patchbay matrix and in `routing.list`.

## Three entity types

### Sources — things that PRODUCE

Anything that emits an audio buffer, a MIDI event, or a control value is a Source. From a fresh project you have:

- `keyboard-default` (MIDI) — the on-screen Keyboard.
- `sequencer-default` (MIDI) — the step grid.
- Hardware MIDI inputs (one Source per device, e.g. `midi-input-input-0`).
- `master` (audio) — the master bus's pre-fade tap, so you can route the mix into the Recorder or back into a Builder.
- Every Builder / Faust-DSP module you open registers itself: `builder-<id>` (audio).
- Every running instrument you've installed exposes its audio out (`<instrument-id>`, audio).
- Each **MixerTrack** is an audio Source too (`<track-id>`) — it routes the track's post-fader signal on to `master`.

Each Source has one or more **output ports**. Most have a single port called `out`; multi-output entities (a few specialised modules) carry more.

### Sinks — things that CONSUME

Anything that wants to receive audio, MIDI, or modulation values is a Sink:

- `master` (audio) — the master bus input.
- Each **MixerTrack** as an audio Sink (`<track-id>:in`) — Sources route INTO a track here; the track applies its fader / mute / solo / FX / sends, then routes on to `master`.
- `recorder-default` (audio) — the bundled Recorder.
- Hardware MIDI outputs (one Sink per device, e.g. `midi-output-output-1`).
- Every MIDI-accepting module's MIDI side — a Builder with a `midi_note` node (appears once the node binds), or an installed instrument's `<instrument-id>:midi-in`.
- An instrument's modulation side as `<instrument-id>` (kind `modulation`) — one **input port per exposed Faust param** (e.g. `<instrument-id>/cutoff`).

The modulation Sink is the special one: a single entity exposes a whole **bank of per-parameter ports**, and you wire modulator Sources (LFOs, envelope followers) to specific params.

### Connections — the wires

A Connection has:

- A `from` { sourceId, portId } pair (the producer side).
- A `to` { sinkId, portId } pair (the consumer side).
- A `kind` — `"audio"`, `"midi"`, or `"modulation"`.
- A `gain` (audio) or `amount` (modulation) or just an `enabled` flag (MIDI).
- An auto-generated `id` of the form `conn:<sourceId>:<sourcePort>-><sinkId>:<sinkPort>`.

The id is **deterministic** — calling `routing.connect` twice for the same endpoints doesn't create two wires, it returns the same id (idempotent).

## The three cable kinds

| Kind | Carries | Extra control | UI cell |
|---|---|---|---|
| `audio` | Sample buffers (stereo by default, channel count from the port). | `gain` (linear 0..1, 5 ms ramp on changes; `enabled` suspends with a ramp to 0). | Cyan cell in the matrix. |
| `midi` | MIDI events (note-on / note-off / CC / clock / sysex). | `enabled` only — a Boolean dispatch gate. No gain ("50 % MIDI" makes no sense). | Purple cell in the matrix. |
| `modulation` | Per-param control values (LFO output, envelope follower, slow CCs converted to param-rate). | `amount` (signed scalar; modulator output scaled before reaching the param). | Reachable via `routing.connect` + the Modulators panel; not in the matrix V1. |

**Kind-mismatch is rejected**: you can't wire an audio Source to a MIDI Sink. The matrix greys those cells out; `routing.connect` returns an error if you try via MCP.

## The audio path

A fresh project ships with **nothing pre-wired** — there's no bundled instrument and no seeded connections. You build the topology explicitly. The audio path for a DSP reads:

```
builder-<id> → <track>:in   (audio — created by the mixer's "+ ADD AUDIO")
<track> → master            (audio — the MixerTrack's own output)
```

i.e. a Source routes INTO a **MixerTrack** (which carries the fader / mute / solo / FX / sends), and the track routes on to `master`. Opening + running a Builder registers `builder-<id>` as a Source but does NOT wire it anywhere on its own — you add it to a track via the Master panel's **"+ ADD AUDIO"** picker (or `mixer.tracks.input.set`). The route then persists, so re-opening the DSP restores it.

MIDI is wired the same explicit way — `keyboard-default` / `sequencer-default → <your Builder's midi-in>`.

Multiple Sources can route into one track, and multiple tracks sum into `master`. The right-panel mixer shows one strip per **MixerTrack**, with the track's gain as the fader.

## Permanent vs ephemeral

Every entry in `routing.list` carries a `permanent` flag:

- `permanent: true` — the entity is built into FaustWave's posture (master, Keyboard, Sequencer, Recorder, hardware MIDI devices). Removing the underlying module is either impossible or auto-respawns.
- `permanent: false` — user-created entities (Builders + Faust DSPs you opened, MixerTracks you added). Closing the module / deleting the track unregisters its Source / Sink and disconnects its wires.

When you delete a Builder, its wires don't "leak" — the routing engine reconciles on the next diff cycle and tears down anything the closed module owned.

## What this gets you

Because routing is observable + addressable + MCP-driven, every routing decision is:

- **Visible** — the Patchbay matrix + the Activity log show every connect / disconnect.
- **Scriptable** — the AI assistant (or your own MCP client) can build complex wirings end-to-end. See § 4 in this pack.
- **Survives restart** — connections persist in the project. Re-opening the project re-binds them once each Source / Sink rebinds.

Next section: opening the Patchbay matrix and using it.
