File size: 10,542 Bytes
312ea17 dcfc9c9 312ea17 6f6ce59 47e9eca dcfc9c9 6f6ce59 dcfc9c9 6f6ce59 dcfc9c9 61c48cb 312ea17 dcfc9c9 312ea17 dcfc9c9 312ea17 dcfc9c9 47e9eca dcfc9c9 312ea17 2aa5050 dcfc9c9 312ea17 dcfc9c9 312ea17 dcfc9c9 2aa5050 dcfc9c9 2aa5050 dcfc9c9 2aa5050 dcfc9c9 29b4c18 dcfc9c9 312ea17 2aa5050 dcfc9c9 2aa5050 dcfc9c9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | # PluginBridge β Claude Code Context
## What This Is
A JUCE-based VST3/AU plugin that:
1. Hosts any third-party VST3/AU plugin with full GUI embedded in Ableton's window
2. Crash-isolates unsafe plugins by loading them in a separate Helper process (audio-only mode)
3. Exposes ALL hosted plugin parameters via a local MCP server (port 16620)
4. Audio routes through shared memory (zero added latency)
5. Any AI that speaks MCP (Claude Code, Codex CLI, Gemini CLI) can control any plugin
## Current Status (v0.6.0 β 2026-05-17)
- β
In-process GUI hosting (full GUI for safe plugins)
- β
Safety scanning system (Helper-based pre-test, results cached in safety_db.json)
- β
Audio-only mode for unsafe plugins (iZotope, etc.)
- β
Ableton-style plugin picker (manufacturer TreeView, search, safety badges)
- β
MCP server (port 16620, HTTP JSON-RPC 2.0)
- β
Live spectrum analyzer (LUFS / FFT bands / stereo width / centroid / true peak)
- β
Multi-instance support + channel dropdown (any PluginBridge track addressable by name)
- β
Verified working: Pro-Q 4, God Particle, Little MicroShift, LIMITER
- β οΈ Sprint 7 in progress β MCP param ops route through Helper (not in-process) β EQ changes invisible in GUI
## Architecture: HYBRID SAFETY-SCAN
```
ββ Ableton Process βββββββββββββββββββββββββββββββββββββββββββββββ
β β
β PluginBridge.vst3 β
β βββ PluginBridgeProcessor β
β β βββ getInstalledPluginFiles() β scans VST3+AU dirs β
β β βββ getPluginManufacturer() β reads Info.plist, cached β
β β βββ PluginSafetyDB β safe/unsafe/unknown JSON DB β
β β βββ startBackgroundScan() β pre-tests all unknown plugins β
β β βββ loadPlugin() β orchestrates load flow β
β β βββ McpServer β HTTP MCP port 16620 β
β β β
β βββ PluginBridgeEditor β
β β βββ PluginPickerComponent β manufacturer TreeView + searchβ
β β βββ pluginEditor β hosted plugin's own editor β
β β β
β βββ HelperConnection β IPC + shared memory to Helperβ
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Unix socket + shared memory
βΌ
ββ PluginBridgeHelper.app (separate process) ββββββββββββββββββββββ
β Bundled in PluginBridge.vst3/Contents/Resources/ β
β β
β Modes: β
β --load <path> Load plugin, route audio via shared memory β
β --scan <path> Test-load plugin, exit 0=safe / crash=unsafe β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Plugin Load Flow
```
User selects plugin in picker
β
βΌ
loadPlugin() checks PluginSafetyDB
β
ββββββ΄βββββββββββββββββββ
β β
Unknown Safe/Unsafe already known
β β
βΌ β
Wait for Helper to exit β
Spawn: Helper --scan β
β β
Crashed? β mark Unsafe β
Exit 0? β mark Safe β
β β
ββββββββββββββ¬βββββββββββ
β
βββββββββ΄βββββββββ
β β
Safe Unsafe
β β
βΌ βΌ
Helper --load Helper --load
(audio routing) (audio routing)
β β
βΌ βΌ
loadInProcess() showAudioOnlyUI()
createEditor() (MCP still works)
embed in window
```
**Key constraint:** Only ONE Helper process at a time. Scanner must wait for live Helper to finish before spawning a scan subprocess (same shared memory name β conflict).
## File Structure
```
pluginbridge/
βββ CMakeLists.txt
βββ JUCE/ (git submodule)
βββ libs/
β βββ httplib.h (MIT, header-only HTTP server)
β βββ json.hpp (MIT, header-only JSON)
βββ Source/
β βββ Plugin/ β VST3/AU (runs inside Ableton)
β β βββ PluginBridgeProcessor.h/.cpp β main logic
β β βββ PluginBridgeEditor.h/.mm β editor window
β β βββ PluginPickerComponent.h/.mm β plugin browser UI (new v0.5)
β β βββ HelperConnection.h/.cpp β IPC + shared memory
β β βββ McpServer.h/.cpp β HTTP MCP server
β β βββ PluginSafetyDB.h β safe/unsafe JSON DB
β β βββ Blocklist.h β persistent crash blocklist
β β βββ PBLog.h β timestamped logger
β βββ Helper/ β Standalone exe (separate process)
β β βββ main.cpp β --load and --scan modes
β β βββ HelperPluginHost.h/.mm
β β βββ HelperIPC.h/.cpp
β βββ Shared/
β βββ SharedAudioBuffer.h β shared memory layout
β βββ IPCProtocol.h β JSON message formats
β βββ Constants.h
βββ CLAUDE.md β this file
βββ MACHINE-CONTEXT.md β system paths, verified APIs, plugin behaviors
βββ SYNC.md β what was built/fixed and when
βββ FAILED-APPROACHES.md β what didn't work and why
βββ ROADMAP.md
```
## Build
```bash
cd "/Volumes/T7 Shield/Users/Aditya/Downloads/AI MUSIC PRODUCTION/pluginbridge/build"
cmake --build . --target PluginBridge_VST3 -- -j4
# Auto-installs to ~/Library/Audio/Plug-Ins/VST3/PluginBridge.vst3
```
**Two targets:**
- `PluginBridge_VST3` β builds + installs both plugin and Helper
- `PluginBridgeHelper` β Helper standalone only
**CMake 3.28 required** (system CMake 4.x incompatible with JUCE 8).
## Key Runtime Data
| File | Purpose |
|---|---|
| `~/Library/PluginBridge/safety_db.json` | Safe/unsafe status per plugin path+mtime |
| `~/Library/PluginBridge/debug.log` | Session-tagged timestamped log |
| `~/Library/PluginBridge/scan.log` | Background scan output |
| `~/Library/PluginBridge/blocklist.txt` | Plugins that crashed Helper during use |
## PluginPickerComponent (v0.5)
`Source/Plugin/PluginPickerComponent.h/.mm`
- `Entry` struct: `{ file, name, manufacturer, blocked, safety }`
- Callbacks: `onPluginSelected`, `onClose`, `onClearBlocklist`, `onClearSafetyCache`
- `static constexpr int kWidth = 420, kHeight = 500`
- Tree: `ManufacturerTreeItem` (folder) β `PluginTreeItem` (leaf, 24px height)
- Safety badges: `Safety::Safe` β `β` green; `Safety::Unsafe` β `audio only` orange; `blocked` β `β ` red
- Search: `addChildComponent(searchList)` β NOT `addAndMakeVisible` (see FAILED-APPROACHES)
- Custom `TreeLF` LookAndFeel overrides `drawTreeviewPlusMinusBox` for Ableton-style arrows
## JUCE 8 APIs β Verified
### Working
- `formatManager.addFormat(new juce::VST3PluginFormat())`
- `formatManager.addFormat(new juce::AudioUnitPluginFormat())`
- `plugin->createEditor()` β message thread only
- `plugin->hasEditor()`
- `plugin->getParameters()` β `Array<AudioProcessorParameter*>`
- `juce::MessageManager::callAsync(lambda)` β cross-thread UI updates
- `addChildComponent(comp)` β adds hidden; use instead of `addAndMakeVisible` when starting invisible
- `juce::TreeView` + `juce::TreeViewItem` with custom `LookAndFeel`
- `juce::File::findChildFiles(findDirectories, false, "*.vst3")`
### Broken β Do NOT Use
- β `addDefaultFormats()` β deleted in JUCE 8
- β `juce::Thread::setCurrentThreadPriority()` β removed, use native pthread
- β `getParameter(int)` / `setParameter(int, float)` β deprecated
- β `getStringWidth()` β use `getStringWidthFloat()`
- β `juce::Rectangle<float>::getTransformToFit()` β does not exist
- β `juce::Array<CustomStruct>` initializer list β use `std::vector<CustomStruct>`
## macOS Gotchas
- β `MSG_NOSIGNAL` β Linux only β `signal(SIGPIPE, SIG_IGN)` + `SO_NOSIGPIPE`
- β Two processes with same `shm_open` name β both crash β scanner must wait for Helper
- β `addAndMakeVisible(comp)` after `comp.setVisible(false)` β `addAndMakeVisible` forces visible, invisible comp sits on top intercepting all mouse events β use `addChildComponent(comp)` instead
- β `CAContext` + `CALayerHost` for cross-process GUI β doesn't work in Ableton (see FAILED-APPROACHES #10)
- β
`posix_spawn` β safe for spawning from plugin process
- β
`shm_open` / `mmap` β reliable cross-process shared memory
## MCP Protocol
- Endpoint: `POST http://127.0.0.1:16620/mcp`
- Health: `GET http://127.0.0.1:16620/health`
- Wire format: JSON-RPC 2.0
- Tools: `list_plugins`, `search_param`, `get_params`, `set_params`, `get_analysis`
## What NOT To Do
- Don't load plugins in-process without safety scan β crash-prone plugins (iZotope, some Waves) call `abort()` and kill Ableton
- Don't use `PluginDirectoryScanner` β triggers plugin code on scan β crash
- Don't spawn Helper --scan while live Helper is running β shared memory conflict β false UNSAFE results
- Don't use `addAndMakeVisible` on a component that should start hidden β use `addChildComponent`
- Don't try CAContext/CALayerHost for cross-process GUI β see FAILED-APPROACHES #10
|