#ifndef ConnectionWorker_hpp #define ConnectionWorker_hpp #include #include "common.h" #include #include #include #include #include #include "StateIntegrity.hpp" class PluginWindow; class WavtoolPlayhead; class WavtoolKeyListener; class ConnectionWorker final : private juce::AsyncUpdater, public juce::AudioProcessorListener, private juce::Timer { public: ConnectionWorker(const juce::PluginDescription& desc, int bufferSize, int sampleRate, std::string&& bridgeKeySeed, std::function&& loadedHandler, std::function&& errorHandler, std::function&& saveHandler, std::function&& parameterGestureHandler, std::function&& keyHandler, std::function&& editorClosedHandler, std::function)>&& editorMovedHandler, std::function&& trustHandler, std::function&& latencyChangedHandler, std::function&& launchingChangedHandler, std::function&& keyboardEnabledHandler); ~ConnectionWorker(); void handleAsyncUpdate() override; void handleBlock(ShmData & block); void loadState(const std::string_view & data); void requestSaveState(bool periodic); void openPluginWindow(std::optional> pos); void closePluginWindow(); void setPluginWindowAlwaysOnTop(bool onTop); void setKeyboardEnabled(bool isEnabled); void keyboardActivity(); void trustResolution(const juce::XmlElement & elem); virtual void audioProcessorParameterChanged(juce::AudioProcessor *processor, int parameterIndex, float newValue) override; virtual void audioProcessorChanged(juce::AudioProcessor *processor, const ChangeDetails &details) override; virtual void audioProcessorParameterChangeGestureBegin(juce::AudioProcessor *processor, int parameterIndex) override; virtual void audioProcessorParameterChangeGestureEnd(juce::AudioProcessor *processor, int parameterIndex) override; virtual void timerCallback() override; private: friend class PluginWindow; using clock_t = std::chrono::high_resolution_clock; void loadPlugin(); void addPluginCallback(std::unique_ptr instance, const juce::String& error); void setTransport(ShmSetTransportData & data); void processBlock(ShmProcessBlockData & data, bool shouldReset); void enqueueThunk(uWS::MoveOnlyFunction && thunk); void stateUpdateCallbackFired(); void alwaysOnTopEdgeTrigger(); bool loadStateOnMessageThread(const std::string_view & data); bool parametersDidChange(); void doBusLayoutUpdate(); juce::MidiBuffer getClearMidiBuffer(); const int bufferSize; const int sampleRate; std::function loadedHandler; std::function errorHandler; std::function saveHandler; std::function parameterGestureHandler; std::function editorClosedHandler; std::function)> editorMovedHandler; std::function trustHandler; std::function latencyChangedHandler; std::function launchingChangedHandler; std::function keyboardEnabledHandler; std::unique_ptr plugin; std::unique_ptr formatManager; std::unique_ptr keyListener; std::unique_ptr pluginWindow; std::unique_ptr pluginToLoad; std::unique_ptr playhead; bool isLoadingState; rigtorp::MPMCQueue> thunkQ; std::atomic lastStateUpdateCallbackTime; std::atomic hasUncommittedStateUpdate; std::atomic gesturesActive; std::string lastSavedState; std::vector pluginParameters; std::vector pluginParameterValues; bool alwaysOnTop; juce::AudioBuffer audioBuffer; std::counting_semaphore<100> triggerAsyncUpdateSema; std::atomic triggerAsyncUpdateShouldExit; std::unique_ptr triggerAsyncUpdateThread; StateIntegrity stateIntegrity; bool waitingForTrustResolution; std::deque pendingStateChanges; std::atomic sendLatencyChangedNextBlock; std::atomic lastPeriodicSaveTime; std::atomic hasWindowPositionChange; std::atomic lastWindowPositionChangeTime; std::pair currentWindowPosition; std::atomic pluginLoadTime; std::atomic unsetLaunchingArmed; bool keyboardEnabled; std::atomic previousInputBuses; std::atomic previousOutputBuses; std::atomic desiredInputBuses; std::atomic desiredOutputBuses; std::atomic wantsBusLayoutUpdate; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionWorker) }; #endif /* ConnectionWorker_hpp */