NEW ARCHITECTURE: In-process hosting + Helper as safety tester + embedded GUI
Browse filesCOMPLETE REWRITE — new approach:
- Plugin loads IN-PROCESS (inside Ableton) like SnappySnap
- GUI shows inside PluginBridge's own editor (no separate window)
- Helper process ONLY used to test if a plugin is safe before loading
- Blocklist persists to disk — unsafe plugins greyed out
- Shared memory / semaphores / audio routing via IPC all removed
Files changed:
- Source/Plugin/PluginBridgeProcessor.h (new: in-process hosting)
- Source/Plugin/PluginBridgeProcessor.cpp (new: direct processBlock)
- Source/Plugin/PluginBridgeEditor.h (new: embeds plugin GUI)
- Source/Plugin/PluginBridgeEditor.cpp (new: resizable, embedded editor)
- Source/Plugin/McpServer.h (simplified: talks to processor directly)
- Source/Plugin/McpServer.cpp (simplified: no helper dependency)
- Source/Plugin/Blocklist.h (NEW: persistent blocklist)
- Source/Plugin/PluginTestRunner.h (NEW: spawns helper to test-load)
- Source/Plugin/PluginTestRunner.cpp (NEW)
- Source/Helper/main.cpp (simplified: test mode only)
- Source/Helper/HelperPluginHost.cpp (simplified: load + report + quit)
- Source/Shared/Constants.h (updated)
- CMakeLists.txt (removed HelperConnection, added new files)
- CLAUDE.md (updated architecture)
- SYNC.md (updated)"
|
@@ -2,10 +2,11 @@
|
|
| 2 |
|
| 3 |
#include <juce_audio_processors/juce_audio_processors.h>
|
| 4 |
#include <juce_dsp/juce_dsp.h>
|
| 5 |
-
#include "
|
| 6 |
-
#include "McpServer.h"
|
| 7 |
#include "Constants.h"
|
| 8 |
|
|
|
|
|
|
|
| 9 |
class PluginBridgeProcessor : public juce::AudioProcessor
|
| 10 |
{
|
| 11 |
public:
|
|
@@ -33,32 +34,59 @@ public:
|
|
| 33 |
void getStateInformation(juce::MemoryBlock& destData) override;
|
| 34 |
void setStateInformation(const void* data, int sizeInBytes) override;
|
| 35 |
|
|
|
|
| 36 |
bool isMcpServerRunning() const;
|
| 37 |
int getMcpServerPort() const;
|
| 38 |
-
HelperConnection& getHelperConnection() { return helper; }
|
| 39 |
|
| 40 |
-
|
|
|
|
| 41 |
void unloadPlugin();
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
bool isPluginLoaded() const { return pluginLoaded; }
|
| 46 |
-
juce::String getLoadedPluginName() const { return pluginName; }
|
| 47 |
-
int getLoadedPluginParamCount() const { return pluginParamCount; }
|
| 48 |
-
HelperConnection::State getConnectionState() const { return helper.getState(); }
|
| 49 |
juce::String getLastPluginPath() const { return pluginPath; }
|
| 50 |
|
|
|
|
| 51 |
juce::Array<juce::File> getInstalledPluginFiles() const;
|
| 52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
private:
|
| 54 |
-
|
| 55 |
-
|
|
|
|
|
|
|
| 56 |
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
juce::String pluginPath;
|
| 60 |
-
int pluginParamCount = 0;
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
double currentSampleRate = 44100.0;
|
| 63 |
int currentBlockSize = 512;
|
| 64 |
|
|
|
|
| 2 |
|
| 3 |
#include <juce_audio_processors/juce_audio_processors.h>
|
| 4 |
#include <juce_dsp/juce_dsp.h>
|
| 5 |
+
#include "Blocklist.h"
|
|
|
|
| 6 |
#include "Constants.h"
|
| 7 |
|
| 8 |
+
class McpServer;
|
| 9 |
+
|
| 10 |
class PluginBridgeProcessor : public juce::AudioProcessor
|
| 11 |
{
|
| 12 |
public:
|
|
|
|
| 34 |
void getStateInformation(juce::MemoryBlock& destData) override;
|
| 35 |
void setStateInformation(const void* data, int sizeInBytes) override;
|
| 36 |
|
| 37 |
+
// MCP
|
| 38 |
bool isMcpServerRunning() const;
|
| 39 |
int getMcpServerPort() const;
|
|
|
|
| 40 |
|
| 41 |
+
// Plugin hosting (IN-PROCESS — plugin runs inside Ableton)
|
| 42 |
+
void loadPlugin(const juce::String& path);
|
| 43 |
void unloadPlugin();
|
| 44 |
+
bool isPluginLoaded() const { return hostedPlugin != nullptr; }
|
| 45 |
+
juce::String getLoadedPluginName() const;
|
| 46 |
+
int getLoadedPluginParamCount() const;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
juce::String getLastPluginPath() const { return pluginPath; }
|
| 48 |
|
| 49 |
+
// Plugin list
|
| 50 |
juce::Array<juce::File> getInstalledPluginFiles() const;
|
| 51 |
|
| 52 |
+
// Blocklist
|
| 53 |
+
bool isBlocked(const juce::String& path) const;
|
| 54 |
+
Blocklist& getBlocklist() { return blocklist; }
|
| 55 |
+
|
| 56 |
+
// Parameter access (for MCP server)
|
| 57 |
+
struct ParamInfo {
|
| 58 |
+
int index;
|
| 59 |
+
juce::String id;
|
| 60 |
+
juce::String name;
|
| 61 |
+
float value;
|
| 62 |
+
juce::String displayText;
|
| 63 |
+
};
|
| 64 |
+
std::vector<ParamInfo> searchParams(const juce::String& keyword) const;
|
| 65 |
+
std::vector<std::pair<int, float>> getParams(const std::vector<int>& ids) const;
|
| 66 |
+
bool setParams(const std::map<int, float>& values);
|
| 67 |
+
|
| 68 |
+
// For editor: get hosted plugin's editor component
|
| 69 |
+
juce::AudioProcessorEditor* createHostedPluginEditor();
|
| 70 |
+
|
| 71 |
+
// Notify editor that plugin changed
|
| 72 |
+
std::function<void()> onPluginLoaded;
|
| 73 |
+
std::function<void()> onPluginUnloaded;
|
| 74 |
+
std::function<void(const juce::String&)> onLoadFailed;
|
| 75 |
+
|
| 76 |
private:
|
| 77 |
+
// In-process hosted plugin
|
| 78 |
+
juce::AudioPluginFormatManager formatManager;
|
| 79 |
+
std::unique_ptr<juce::AudioPluginInstance> hostedPlugin;
|
| 80 |
+
juce::CriticalSection pluginLock;
|
| 81 |
|
| 82 |
+
// MCP server
|
| 83 |
+
std::unique_ptr<McpServer> mcpServer;
|
|
|
|
|
|
|
| 84 |
|
| 85 |
+
// Blocklist (persisted to disk)
|
| 86 |
+
Blocklist blocklist;
|
| 87 |
+
|
| 88 |
+
// State
|
| 89 |
+
juce::String pluginPath;
|
| 90 |
double currentSampleRate = 44100.0;
|
| 91 |
int currentBlockSize = 512;
|
| 92 |
|