Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
4.6KB

  1. /*
  2. * Fake juce event thread needed for juce_audio_processors
  3. * Copyright (C) 2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaJuceUtils.hpp"
  18. // -------------------------------------------------------------------------------------------------------------------
  19. #if ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
  20. #undef KeyPress
  21. #include "juce_audio_processors/juce_audio_processors.h"
  22. #include "juce_events/juce_events.h"
  23. namespace juce {
  24. #include "juce_events/broadcasters/juce_ActionBroadcaster.cpp"
  25. #include "juce_events/broadcasters/juce_AsyncUpdater.cpp"
  26. #include "juce_events/messages/juce_DeletedAtShutdown.cpp"
  27. #include "juce_events/messages/juce_MessageManager.cpp"
  28. #include "juce_audio_processors/processors/juce_AudioProcessor.cpp"
  29. #include "juce_audio_processors/processors/juce_AudioProcessorGraph.cpp"
  30. #include "juce_audio_processors/processors/AudioProcessorGraphMultiThreaded.cpp"
  31. #include "juce_audio_processors/utilities/juce_AudioProcessorParameters.cpp"
  32. class JuceEventsThread : public Thread
  33. {
  34. public:
  35. JuceEventsThread()
  36. : Thread("JuceEventsThread"),
  37. fInitializing(false),
  38. fLock(),
  39. fQueue() {}
  40. ~JuceEventsThread()
  41. {
  42. signalThreadShouldExit();
  43. stopThread(2000);
  44. const ScopedLock sl(fLock);
  45. CARLA_SAFE_ASSERT(fQueue.size() == 0);
  46. fQueue.clear();
  47. }
  48. bool postMessage(MessageManager::MessageBase* const msg)
  49. {
  50. const ScopedLock sl(fLock);
  51. fQueue.add(msg);
  52. return true;
  53. }
  54. bool isInitializing() const noexcept
  55. {
  56. return fInitializing;
  57. }
  58. protected:
  59. void run() override
  60. {
  61. /*
  62. * We need to know when we're initializing because MessageManager::setCurrentThreadAsMessageThread()
  63. * calls doPlatformSpecificInitialisation/Shutdown, in which we started this thread previously.
  64. * To avoid a deadlock we do not call start/stopThread if still initializing.
  65. */
  66. fInitializing = true;
  67. if (MessageManager* const msgMgr = MessageManager::getInstance())
  68. msgMgr->setCurrentThreadAsMessageThread();
  69. fInitializing = false;
  70. for (; ! threadShouldExit();)
  71. {
  72. // dispatch messages until no more present, then sleep
  73. for (; dispatchNextInternalMessage();) {}
  74. sleep(25);
  75. }
  76. }
  77. private:
  78. volatile bool fInitializing;
  79. CriticalSection fLock;
  80. ReferenceCountedArray<MessageManager::MessageBase> fQueue;
  81. MessageManager::MessageBase::Ptr popNextMessage()
  82. {
  83. const ScopedLock sl(fLock);
  84. return fQueue.removeAndReturn(0);
  85. }
  86. bool dispatchNextInternalMessage()
  87. {
  88. if (const MessageManager::MessageBase::Ptr msg = popNextMessage())
  89. {
  90. JUCE_TRY
  91. {
  92. msg->messageCallback();
  93. return true;
  94. }
  95. JUCE_CATCH_EXCEPTION
  96. }
  97. return false;
  98. }
  99. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JuceEventsThread)
  100. };
  101. static JuceEventsThread& getJuceEventsThreadInstance()
  102. {
  103. static JuceEventsThread sJuceEventsThread;
  104. return sJuceEventsThread;
  105. }
  106. JUCEApplicationBase::CreateInstanceFunction JUCEApplicationBase::createInstance = nullptr;
  107. void MessageManager::doPlatformSpecificInitialisation()
  108. {
  109. JuceEventsThread& juceEventsThread(getJuceEventsThreadInstance());
  110. if (! juceEventsThread.isInitializing())
  111. juceEventsThread.startThread();
  112. }
  113. void MessageManager::doPlatformSpecificShutdown()
  114. {
  115. JuceEventsThread& juceEventsThread(getJuceEventsThreadInstance());
  116. if (! juceEventsThread.isInitializing())
  117. juceEventsThread.stopThread(-1);
  118. }
  119. bool MessageManager::postMessageToSystemQueue(MessageManager::MessageBase* const message)
  120. {
  121. JuceEventsThread& juceEventsThread(getJuceEventsThreadInstance());
  122. return juceEventsThread.postMessage(message);
  123. }
  124. bool MessageManager::dispatchNextMessageOnSystemQueue(bool)
  125. {
  126. carla_stderr2("MessageManager::dispatchNextMessageOnSystemQueue() unsupported");
  127. return false;
  128. }
  129. } // namespace juce
  130. #endif // ! CARLA_OS_MAC || CARLA_OS_WIN