File size: 4,796 Bytes
644b727 590be7d 42bb859 fdc4e41 abf507a 4a72dce fdc4e41 644b727 fdc4e41 644b727 42bb859 644b727 590be7d 644b727 fdc4e41 590be7d 644b727 590be7d 4a72dce fdc4e41 42bb859 644b727 fdc4e41 42bb859 fdc4e41 abf507a 590be7d fdc4e41 42bb859 fdc4e41 42bb859 644b727 fdc4e41 590be7d 42bb859 fdc4e41 abf507a 42bb859 fdc4e41 590be7d 42bb859 590be7d 644b727 fdc4e41 644b727 | 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 | #pragma once
#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_dsp/juce_dsp.h>
#include "HelperConnection.h"
#include "McpServer.h"
#include "Blocklist.h"
#include "PluginSafetyDB.h"
#include "AudioAnalyser.h"
#include "Constants.h"
#include <map>
#include <mutex>
#include <set>
class PluginBridgeProcessor : public juce::AudioProcessor,
private juce::AudioProcessorListener
{
public:
PluginBridgeProcessor();
~PluginBridgeProcessor() override;
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
void releaseResources() override;
void processBlock(juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
juce::AudioProcessorEditor* createEditor() override;
bool hasEditor() const override { return true; }
const juce::String getName() const override { return "PluginBridge"; }
bool acceptsMidi() const override { return true; }
bool producesMidi() const override { return true; }
double getTailLengthSeconds() const override { return 0.0; }
int getNumPrograms() override { return 1; }
int getCurrentProgram() override { return 0; }
void setCurrentProgram(int) override {}
const juce::String getProgramName(int) override { return {}; }
void changeProgramName(int, const juce::String&) override {}
void getStateInformation(juce::MemoryBlock& destData) override;
void setStateInformation(const void* data, int sizeInBytes) override;
// MCP
bool isMcpServerRunning() const;
int getMcpServerPort() const;
HelperConnection& getHelperConnection() { return helper; }
// Plugin lifecycle
void loadPlugin(const juce::String& pluginPath);
void unloadPlugin();
bool isPluginLoaded() const { return pluginLoaded; }
juce::String getLoadedPluginName() const { return pluginName; }
int getLoadedPluginParamCount() const { return pluginParamCount; }
HelperConnection::State getConnectionState() const { return helper.getState(); }
juce::String getLastPluginPath() const { return pluginPath; }
// In-process plugin instance (GUI only — null when plugin is unsafe)
juce::AudioPluginInstance* getInProcessPlugin() const { return inProcessPlugin.get(); }
// Plugin list
juce::Array<juce::File> getInstalledPluginFiles() const;
// Manufacturer name for a plugin file (reads moduleinfo.json for VST3, heuristic for AU)
// Fast — no plugin loading. Results cached in memory.
juce::String getPluginManufacturer(const juce::File& pluginFile) const;
// Blocklist
bool isBlocked(const juce::String& path) const;
Blocklist& getBlocklist() { return blocklist; }
// Safety DB
PluginSafetyDB& getSafetyDB() { return safetyDB; }
void startBackgroundScan();
void stopBackgroundScan();
// Audio analysis (for MCP get_analysis)
std::string getAnalysis() const { return analyser.getCompactAnalysis(); }
// Callbacks for editor
std::function<void()> onPluginWillLoad; // fired BEFORE old plugin/editor torn down
std::function<void()> onPluginLoaded;
std::function<void()> onPluginUnloaded;
std::function<void(const juce::String&)> onLoadFailed;
std::function<void(const juce::String&, bool)> onScanProgress; // path, safe
private:
void loadInProcessPlugin(const juce::String& path);
void unloadInProcessPlugin();
// Spawns Helper with --scan <path>, waits up to 10s, returns true if safe.
// Safe to call from any thread. Never crashes Ableton on plugin crash.
bool runPluginScan(const juce::String& path);
// AudioProcessorListener — forwards in-process param changes to Helper
void audioProcessorParameterChanged(juce::AudioProcessor*, int paramIdx, float value) override;
void audioProcessorChanged(juce::AudioProcessor*, const ChangeDetails&) override {}
HelperConnection helper;
std::unique_ptr<McpServer> mcpServer;
Blocklist blocklist;
PluginSafetyDB safetyDB;
AudioAnalyser analyser;
// In-process plugin (GUI instance — nullptr for unsafe plugins)
juce::AudioPluginFormatManager inProcessFormatManager;
std::unique_ptr<juce::AudioPluginInstance> inProcessPlugin;
std::atomic<bool> suppressParamSync{false};
bool pluginLoaded = false;
juce::String pluginName;
juce::String pluginPath;
int pluginParamCount = 0;
double currentSampleRate = 44100.0;
int currentBlockSize = 512;
// Background scanner
std::thread scanThread;
std::atomic<bool> scanRunning{false};
// Manufacturer name cache (path → manufacturer)
mutable std::map<std::string, std::string> manufacturerCache;
mutable std::mutex manufacturerCacheMutex;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginBridgeProcessor)
};
|