From 33f37847bc003ac17c80f30b24e2b83575c758da Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 2 Apr 2021 14:37:17 +0100 Subject: [PATCH] VST: Use RAII initialisation for JUCE GUI and SharedResourcePointer for MessageThread --- .../VST/juce_VST_Wrapper.cpp | 59 ++++++++-------- .../utility/juce_LinuxMessageThread.h | 67 +++++++++++++------ 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp index 4a01ec0b01..6c22a2918e 100644 --- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp +++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp @@ -185,13 +185,12 @@ namespace return w; } + static int numActivePlugins = 0; static bool messageThreadIsDefinitelyCorrect = false; } #endif -static Array activePlugins; - //============================================================================== // Ableton Live host specific commands struct AbletonLiveHostSpecific @@ -316,44 +315,35 @@ public: vstEffect.flags |= Vst2::effFlagsNoSoundInStop; #endif - activePlugins.add (this); + #if JUCE_WINDOWS + ++numActivePlugins; + #endif } ~JuceVSTWrapper() override { JUCE_AUTORELEASEPOOL { - { - #if JUCE_LINUX || JUCE_BSD - MessageManagerLock mmLock; - #endif - stopTimer(); - deleteEditor (false); + #if JUCE_LINUX || JUCE_BSD + MessageManagerLock mmLock; + #endif - hasShutdown = true; + stopTimer(); + deleteEditor (false); - delete processor; - processor = nullptr; + hasShutdown = true; - jassert (editorComp == nullptr); + delete processor; + processor = nullptr; - deleteTempChannels(); + jassert (editorComp == nullptr); - jassert (activePlugins.contains (this)); - activePlugins.removeFirstMatchingValue (this); - } + deleteTempChannels(); - if (activePlugins.size() == 0) - { - #if JUCE_LINUX || JUCE_BSD - SharedMessageThread::deleteInstance(); - #endif - shutdownJuce_GUI(); - - #if JUCE_WINDOWS + #if JUCE_WINDOWS + if (--numActivePlugins == 0) messageThreadIsDefinitelyCorrect = false; - #endif - } + #endif } } @@ -394,8 +384,6 @@ public: const int numMidiEventsComingIn = midiEvents.getNumEvents(); #endif - jassert (activePlugins.contains (this)); - { const int numIn = processor->getTotalNumInputChannels(); const int numOut = processor->getTotalNumOutputChannels(); @@ -2044,6 +2032,12 @@ private: } //============================================================================== + ScopedJuceInitialiser_GUI libraryInitialiser; + + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer messageThread; + #endif + Vst2::audioMasterCallback hostCallback; AudioProcessor* processor = {}; double sampleRate = 44100.0; @@ -2096,7 +2090,11 @@ namespace { JUCE_AUTORELEASEPOOL { - initialiseJuce_GUI(); + ScopedJuceInitialiser_GUI libraryInitialiser; + + #if JUCE_LINUX || JUCE_BSD + SharedResourcePointer messageThread; + #endif try { @@ -2164,7 +2162,6 @@ namespace { PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST; - SharedMessageThread::getInstance(); return pluginEntryPoint (audioMaster); } diff --git a/modules/juce_audio_plugin_client/utility/juce_LinuxMessageThread.h b/modules/juce_audio_plugin_client/utility/juce_LinuxMessageThread.h index 327c0f4854..e0e2bc5f3d 100644 --- a/modules/juce_audio_plugin_client/utility/juce_LinuxMessageThread.h +++ b/modules/juce_audio_plugin_client/utility/juce_LinuxMessageThread.h @@ -25,47 +25,70 @@ #if JUCE_LINUX || JUCE_BSD +#include + namespace juce { -struct SharedMessageThread : public Thread +class MessageThread { - SharedMessageThread() : Thread ("VstMessageThread") +public: + MessageThread() { - startThread (7); - - while (! initialised) - sleep (1); + startThread(); } - ~SharedMessageThread() override + ~MessageThread() { - signalThreadShouldExit(); - JUCEApplicationBase::quit(); - waitForThreadToExit (5000); - clearSingletonInstance(); + MessageManager::getInstance()->stopDispatchLoop(); + stopThread(); } - void run() override + void startThread() { - initialiseJuce_GUI(); - initialised = true; + shouldExit = false; - MessageManager::getInstance()->setCurrentThreadAsMessageThread(); + thread = std::thread { [this] + { + Thread::setCurrentThreadPriority (7); + Thread::setCurrentThreadName ("JUCE Plugin Message Thread"); - XWindowSystem::getInstance(); + MessageManager::getInstance()->setCurrentThreadAsMessageThread(); + XWindowSystem::getInstance(); - while ((! threadShouldExit()) && MessageManager::getInstance()->runDispatchLoopUntil (250)) - {} + threadInitialised.signal(); + + for (;;) + { + if (shouldExit + || ! MessageManager::getInstance()->runDispatchLoopUntil (250)) + { + break; + } + } + } }; + + threadInitialised.wait(); } - JUCE_DECLARE_SINGLETON (SharedMessageThread, false) + void stopThread() + { + shouldExit = true; + thread.join(); + } - bool initialised = false; + bool isThreadRunning() const noexcept { return thread.joinable(); } + +private: + WaitableEvent threadInitialised; + std::thread thread; + + std::atomic shouldExit { false }; + + JUCE_DECLARE_NON_MOVEABLE (MessageThread) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageThread) }; -JUCE_IMPLEMENT_SINGLETON (SharedMessageThread) - } // namespace juce #endif