File size: 4,485 Bytes
644b727
 
 
 
590be7d
 
42bb859
fdc4e41
abf507a
0a63fb2
4a72dce
fdc4e41
 
 
644b727
fdc4e41
 
644b727
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42bb859
644b727
 
590be7d
644b727
0a63fb2
 
 
 
fdc4e41
590be7d
644b727
590be7d
 
 
 
 
4a72dce
 
0a63fb2
fdc4e41
 
42bb859
644b727
 
0a63fb2
fdc4e41
 
42bb859
 
 
 
fdc4e41
 
 
 
 
0a63fb2
abf507a
 
590be7d
0a63fb2
42bb859
 
 
0a63fb2
42bb859
644b727
fdc4e41
 
 
 
 
 
 
590be7d
42bb859
fdc4e41
 
abf507a
42bb859
0a63fb2
fdc4e41
 
 
 
590be7d
 
42bb859
590be7d
 
0a63fb2
 
 
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
129
#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 "InstanceRegistry.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; }

    // Channel name (for multi-instance identification)
    void setChannelName(const juce::String& name);
    juce::String getChannelName() const { return channelName; }

    // 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 (null when plugin is unsafe)
    juce::AudioPluginInstance* getInProcessPlugin() const { return inProcessPlugin.get(); }

    // Plugin list
    juce::Array<juce::File> getInstalledPluginFiles() const;

    // Manufacturer name
    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
    std::string getAnalysis() const { return analyser.getCompactAnalysis(); }

    // Callbacks for editor
    std::function<void()> onPluginWillLoad;
    std::function<void()> onPluginLoaded;
    std::function<void()> onPluginUnloaded;
    std::function<void(const juce::String&)> onLoadFailed;
    std::function<void(const juce::String&, bool)> onScanProgress;

private:
    void loadInProcessPlugin(const juce::String& path);
    void unloadInProcessPlugin();
    bool runPluginScan(const juce::String& path);

    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
    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;

    // Channel identification
    juce::String channelName { "Unnamed" };

    double currentSampleRate = 44100.0;
    int currentBlockSize = 512;

    std::thread scanThread;
    std::atomic<bool> scanRunning{false};

    mutable std::map<std::string, std::string> manufacturerCache;
    mutable std::mutex manufacturerCacheMutex;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginBridgeProcessor)
};