feat: add Carla plugin host stubs and integration plan
This commit is contained in:
committed by
Loic Coenen (aider)
parent
5cffec86e7
commit
dafc7fe46b
110
breakup.md
110
breakup.md
@@ -0,0 +1,110 @@
|
||||
# Integration Plan: Carla Plugin Host (Client‑side)
|
||||
|
||||
## 1. Strategy
|
||||
|
||||
Carla lives in the **client** (the TUI), not the looper engine.
|
||||
The client becomes a lightweight JACK client itself, capable of loading plugins via the Carla host API and bridging audio/MIDI between the looper’s JACK ports and the plugin’s ports.
|
||||
|
||||
## 2. Client (TUI) – new modules
|
||||
|
||||
### 2.1 Carla dependency
|
||||
- Link the client binary with `libcarla_host` (C static/shared library).
|
||||
- Use the official `carla_standalone.h` API.
|
||||
|
||||
### 2.2 New files `client/src/plugins.c` / `plugins.h`
|
||||
Functions (same signatures as before, but run **inside the client**):
|
||||
|
||||
- `int plugin_load(const char *binary, const char *plugin_id, int *out_id)`
|
||||
- `int plugin_unload(int id)`
|
||||
- `int plugin_connect(int id, const char *port_name, const char *looper_port)`
|
||||
- `int plugin_disconnect(const char *from, const char *to)`
|
||||
- `void plugin_set_bypass(int id, bool bypass)`
|
||||
|
||||
The module owns the list of loaded plugins, their Carla‑native IDs, and the mapping between looper JACK ports and plugin ports.
|
||||
|
||||
### 2.3 JACK client for plugin I/O
|
||||
- In `client/src/tui.c` (or a new `client/src/jack_io.c`), open a JACK client with `jack_client_open()`.
|
||||
- Register input/output ports that will be connected to the looper’s ports (usually via `jack_connect` called once at start‑up).
|
||||
- In the process callback, copy audio between looper ports and plugin ports (using Carla’s `process()`‑like functions).
|
||||
- This keeps the engine completely unaware of plugins.
|
||||
|
||||
## 3. TUI commands (colon‑mode)
|
||||
|
||||
All already exist in the plan; only the implementation target changes:
|
||||
|
||||
- `:from <port>` → describe a looper output port (e.g., `looper:out_0`)
|
||||
- `:to <port>` → destination port (e.g., `plugin1:in_left`)
|
||||
- `:addplugin <path>` → loads the plugin and, if `from`/`to` are set, connects them automatically
|
||||
- `:connect` → creates a JACK‑connection between the stored `from` and `to` (or, if one side belongs to a plugin, uses Carla’s internal connect)
|
||||
- `:disconnect`
|
||||
- `:rack` → toggles rack view (list of plugins with ports and bypass status)
|
||||
- `:grid` → back to the original grid view
|
||||
|
||||
## 4. Rack view (TUI)
|
||||
|
||||
Identical to the original description, but the data comes from the **client’s internal Carla handle** instead of the status FIFO.
|
||||
|
||||
## 5. Integration Tests
|
||||
|
||||
### 5.1 Mock plugin (client‑side)
|
||||
- Create `client/tests/mock_plugin/mock_plugin.c`.
|
||||
- A trivial JACK client that copies input to output and adds a 1 kHz tone when the input is silent.
|
||||
- Compiled to `libmock_plugin.so` → the TUI’s plugin loader will load it.
|
||||
|
||||
### 5.2 Test infrastructure (client/tests)
|
||||
- Start the TUI in a headless test mode (or fork a child and feed it commands via stdin).
|
||||
- Observe the status output (sent to stdout or a temporary file) to verify plugin list and connections.
|
||||
|
||||
### 5.3 Test cases (new file `client/tests/test_plugin_client.c`)
|
||||
- `test_plugin_load_unload` – load mock plugin, confirm list shows 1 entry, unload, confirm list empty.
|
||||
- `test_plugin_connect_audio` – load plugin, connect to looper ports, inject audio from a test JACK client, verify plugin output reaches a monitor port.
|
||||
- `test_rack_view` – send `:rack` command, parse the printed lines, verify they match the expected layout.
|
||||
- (Later) `test_bypass` – load, bypass, verify audio passes unaltered.
|
||||
|
||||
## 6. Build System Changes
|
||||
|
||||
- **client/makefile**:
|
||||
- Add `-lcarla_host` to `LDFLAGS`.
|
||||
- Add `plugins.c` (and optionally `jack_io.c`) to `SRCS`.
|
||||
- Build mock plugin as a separate target.
|
||||
- **engine/makefile** – no changes (engine stays pure looper).
|
||||
- **top‑level makefile** – no changes.
|
||||
|
||||
## 7. Implementation Steps (ordered)
|
||||
|
||||
1. **Add Carla dependency & stub tests (client side)**
|
||||
- Link client binary with `-lcarla_host`.
|
||||
- Create `client/src/plugins.h` / `client/src/plugins.c` with stub implementations.
|
||||
- Create `client/tests/test_plugins.c` with failing (**Red**) unit tests for:
|
||||
- `plugin_load` returns -1 on NULL binary
|
||||
- `plugin_unload` returns -1 on invalid id
|
||||
- (optional) `plugin_connect` returns -1 on invalid id
|
||||
- Add a `test` target in `client/makefile` that builds and runs `test_plugins`.
|
||||
- Verify the tests compile and pass (**Green**).
|
||||
|
||||
2. **Implement real Carla integration (client side)**
|
||||
- Open a private JACK client inside the TUI using `jack_client_open()`.
|
||||
- Implement `plugin_load` / `plugin_unload` using Carla’s `carla_new_native` etc.
|
||||
- Write integration tests that load a mock plugin and verify it appears in the rack.
|
||||
|
||||
3. **Add `:addplugin` command parsing in TUI**
|
||||
- When colon mode is entered, parse `:addplugin <path>`.
|
||||
- Call the underlying `plugin_load` and update the internal plugin list.
|
||||
|
||||
4. **Implement rack view (TUI)**
|
||||
- Toggle between grid view and plugin‑list view.
|
||||
- Display plugin name, ID, bypass status.
|
||||
- Add `B`, `D`, `X` keybindings.
|
||||
|
||||
5. **Build mock plugin and write integration tests**
|
||||
- Create `client/tests/mock_plugin/mock_plugin.c`.
|
||||
- Target `libmock_plugin.so`.
|
||||
- Write tests in `client/tests/test_plugin_client.c`:
|
||||
- `test_plugin_load_unload`
|
||||
- `test_plugin_connect_audio`
|
||||
- `test_rack_view`
|
||||
|
||||
6. **Polish and document**
|
||||
- Clean up error messages, handle edge cases.
|
||||
- Add comments to new modules.
|
||||
- Update root `README` with Carla instructions.
|
||||
|
||||
Reference in New Issue
Block a user