> ## Documentation Index
> Fetch the complete documentation index at: https://songbird.studiocollective.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# songbird-host-ffi

# songbird-host-ffi

FFI bridge for hosting C++ (JUCE) VST3/AU plugins from the Rust audio engine.

Rust owns the audio thread. Third-party plugins are loaded and processed via JUCE through a thin C ABI layer. The `JucePlugin` wrapper implements the Rust `Plugin` trait, so external plugins are interchangeable with stock Rust plugins in the audio graph.

## Architecture

```
Rust audio thread
  → JucePlugin.process()
    → extern "C" ffi_plugin_process(handle, input_ptrs, output_ptrs, num_samples, num_channels)
      → C++ JUCE wrapper
        → juce::AudioProcessor::processBlock()
```

## FFI Declarations (16 functions)

| Function                       | Purpose                                               |
| ------------------------------ | ----------------------------------------------------- |
| `ffi_plugin_load`              | Load a plugin by path/format (VST3, AU, etc.)         |
| `ffi_plugin_unload`            | Unload and free a plugin instance                     |
| `ffi_plugin_initialize`        | Set sample rate and block size                        |
| `ffi_plugin_reset`             | Reset plugin state                                    |
| `ffi_plugin_process`           | Process audio buffer (non-interleaved float pointers) |
| `ffi_plugin_get_param_count`   | Number of parameters                                  |
| `ffi_plugin_get_param_name`    | Parameter name by index                               |
| `ffi_plugin_get_param_value`   | Current parameter value (0.0–1.0)                     |
| `ffi_plugin_set_param_value`   | Set parameter value                                   |
| `ffi_plugin_get_param_default` | Default parameter value                               |
| `ffi_plugin_get_latency`       | Plugin latency in samples                             |
| `ffi_plugin_get_tail`          | Tail length in seconds                                |
| `ffi_plugin_save_state`        | Save binary plugin state                              |
| `ffi_plugin_load_state`        | Restore binary plugin state                           |
| `ffi_plugin_accepts_midi`      | Whether plugin processes MIDI                         |
| `ffi_plugin_send_midi`         | Send MIDI events to plugin                            |

## JucePlugin Wrapper

```rust theme={null}
pub struct JucePlugin {
    handle: *mut c_void,           // Opaque C++ plugin handle
    name: String,
    type_name: String,
    param_cache: Vec<PluginParam>, // Cached parameter metadata
    sample_rate: f64,
}

impl Plugin for JucePlugin {
    fn process(&mut self, buffer: &mut AudioBuffer, midi_events: &[MidiEvent]) {
        // Calls extern "C" ffi_plugin_process with raw buffer pointers
        // Buffer layout: non-interleaved, matching JUCE's AudioBuffer<float>
    }
    // ... all other Plugin trait methods delegate to FFI calls
}
```

## Buffer Layout

Both sides use **non-interleaved** (planar) float buffers:

```
Channel 0: [sample_0, sample_1, ..., sample_N]
Channel 1: [sample_0, sample_1, ..., sample_N]
```

This matches JUCE's `AudioBuffer<float>::getWritePointer()` layout, so no format conversion is needed at the boundary.

## Out-of-Process Hosting (Future)

The `Plugin` trait does not assume shared memory. The FFI bridge can be extended to host plugins in a separate process (like Ableton/Bitwig do) by:

1. Replacing `ffi_plugin_process` with IPC (shared memory ring buffer or pipe)
2. Running the JUCE host in a child process
3. Crashing plugin = child process dies, not the DAW

The `JucePlugin` wrapper's interface stays the same — only the transport layer changes.

## Status

* **Rust side**: Complete (16 `extern "C"` declarations, `JucePlugin` wrapper, 6 unit tests)
* **C++ side**: Stubs only (needs a thin JUCE wrapper implementing the 16 functions)

## Testing

```bash theme={null}
cargo test -p songbird-host-ffi  # Tests FFI struct layout and parameter caching
```
