#pragma once #include #include #include #include #include "SharedAudioBuffer.h" class HelperPluginHost { public: HelperPluginHost(); ~HelperPluginHost(); // Plugin lifecycle bool loadPlugin(const juce::String& path, double sampleRate, int blockSize); void unloadPlugin(); bool isLoaded() const { return plugin != nullptr; } juce::String getPluginName() const; int getParameterCount() const; // Audio processing (shared memory) void setSharedAudio(SharedAudioBuffer* shm, SharedSemaphore* inSem, SharedSemaphore* outSem); void startProcessing(); void stopProcessing(); // Parameters struct ParamInfo { int index; juce::String id; juce::String name; float value; juce::String displayText; }; std::vector searchParams(const juce::String& keyword) const; std::vector> getParams(const std::vector& ids) const; bool setParams(const std::map& values); // GUI via CARemoteLayerServer void showGui(); void hideGui(); int getGuiWidth() const { return guiWidth; } int getGuiHeight() const { return guiHeight; } void setLayerPortName(const juce::String& name) { layerPortName = name; } juce::String getLayerPortName() const { return layerPortName; } // Event injection (from host process) void injectMouseDown(float x, float y, int button); void injectMouseUp(float x, float y, int button); void injectMouseMove(float x, float y); void injectMouseDrag(float x, float y, int button); void injectMouseScroll(float x, float y, float dx, float dy); void injectKeyDown(int keyCode, const juce::String& chars, int modifiers); void injectKeyUp(int keyCode, const juce::String& chars, int modifiers); // State juce::String getStateBase64() const; bool setStateBase64(const juce::String& base64State); void configure(double sampleRate, int blockSize, int channels); // Callbacks std::function onGuiCreated; std::function onGuiResized; private: void audioProcessingLoop(); juce::AudioPluginFormatManager formatManager; std::unique_ptr plugin; std::unique_ptr editor; std::thread audioThread; std::atomic processing{false}; SharedAudioBuffer* sharedAudio = nullptr; SharedSemaphore* inputSem = nullptr; SharedSemaphore* outputSem = nullptr; double currentSampleRate = 44100.0; int currentBlockSize = 512; int currentChannels = 2; // GUI int guiWidth = 0; int guiHeight = 0; juce::String layerPortName; // ObjC objects (stored as void* to avoid ObjC in header) void* caContext = nullptr; // CAContext* — cross-process layer server void* guiWindow = nullptr; // NSWindow* — off-screen, ordered-front for compositing };