diff --git a/source/backend/CarlaHostImpl.hpp b/source/backend/CarlaHostImpl.hpp index fcd698697..7859526e0 100644 --- a/source/backend/CarlaHostImpl.hpp +++ b/source/backend/CarlaHostImpl.hpp @@ -19,6 +19,7 @@ #define CARLA_HOST_IMPL_HPP_INCLUDED #include "CarlaHost.h" +#include "CarlaUtils.h" #include "CarlaEngine.hpp" #ifdef BUILD_BRIDGE diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp index 53d5c5b52..16f92a633 100644 --- a/source/backend/CarlaStandalone.cpp +++ b/source/backend/CarlaStandalone.cpp @@ -34,23 +34,6 @@ # include "CarlaLogThread.hpp" #endif -#ifdef USING_JUCE -# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Weffc++" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wundef" -# endif - -# include "AppConfig.h" -# include "juce_events/juce_events.h" - -# if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -# pragma GCC diagnostic pop -# endif -#endif - #define CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(cond, msg, ret) \ if (! (cond)) { \ carla_stderr2("%s: " msg, __FUNCTION__); \ @@ -66,6 +49,13 @@ #include "CarlaHostCommon.cpp" #undef CARLA_COMMON_NEED_CHECKSTRINGPTR +#ifdef USING_JUCE +static void carla_juce_init(); +static void carla_juce_idle(); +static void carla_juce_cleanup(); +# include "utils/JUCE.cpp" +#endif + // -------------------------------------------------------------------------------------------------------------------- uint carla_get_engine_driver_count() @@ -321,10 +311,7 @@ bool carla_engine_init(CarlaHostHandle handle, const char* driverName, const cha #endif #ifdef USING_JUCE - juce::initialiseJuce_GUI(); -#if !(defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) - juce::MessageManager::getInstance()->setCurrentThreadAsMessageThread(); -#endif + carla_juce_init(); #endif CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle); @@ -374,7 +361,7 @@ bool carla_engine_init(CarlaHostHandle handle, const char* driverName, const cha shandle.engine = nullptr; delete engine; #ifdef USING_JUCE - juce::shutdownJuce_GUI(); + carla_juce_cleanup(); #endif return false; } @@ -454,7 +441,7 @@ bool carla_engine_close(CarlaHostHandle handle) delete engine; #ifdef USING_JUCE - juce::shutdownJuce_GUI(); + carla_juce_cleanup(); #endif return closed; } @@ -465,11 +452,9 @@ void carla_engine_idle(CarlaHostHandle handle) handle->engine->idle(); -#if defined(USING_JUCE) && !(defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) - const juce::MessageManager* const msgMgr(juce::MessageManager::getInstanceWithoutCreating()); - CARLA_SAFE_ASSERT_RETURN(msgMgr != nullptr,); - - for (; msgMgr->dispatchNextMessageOnSystemQueue(true);) {} +#ifdef USING_JUCE + if (handle->isStandalone) + carla_juce_idle(); #endif } diff --git a/source/backend/CarlaUtils.h b/source/backend/CarlaUtils.h index ce095ac66..7cc6f06dc 100644 --- a/source/backend/CarlaUtils.h +++ b/source/backend/CarlaUtils.h @@ -166,11 +166,15 @@ CARLA_EXPORT const char* const* carla_get_supported_features(void); * Get how many cached plugins are available. * Internal and LV2 plugin formats are cached and need to be discovered via this function. * Do not call this for any other plugin formats. + * + * @note if this carla build uses JUCE, then you must call carla_juce_init beforehand */ CARLA_EXPORT uint carla_get_cached_plugin_count(PluginType ptype, const char* pluginPath); /*! * Get information about a cached plugin. + * + * @note if this carla build uses JUCE, then you must call carla_juce_init beforehand */ CARLA_EXPORT const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index); @@ -271,6 +275,30 @@ CARLA_EXPORT const char* carla_get_library_filename(void); * Get the folder where this carla library resides. */ CARLA_EXPORT const char* carla_get_library_folder(void); + +/* -------------------------------------------------------------------------------------------------------------------- + * JUCE */ + +/*! + * Initialize data structures and GUI support for JUCE. + * This is only needed when carla builds use JUCE and you call cached-plugin related APIs. + * + * Idle must then be called at somewhat regular intervals, though in practice there is no reason for it yet. + * + * Make sure to call carla_juce_cleanup after you are done with APIs that need JUCE. + */ +CARLA_EXPORT void carla_juce_init(); + +/*! + * Give idle time to JUCE stuff. + * Currently only used for Linux. + */ +CARLA_EXPORT void carla_juce_idle(); + +/*! + * Cleanup the JUCE stuff that was initialized by carla_juce_init. + */ +CARLA_EXPORT void carla_juce_cleanup(); #endif /* -------------------------------------------------------------------------------------------------------------------- diff --git a/source/backend/utils/JUCE.cpp b/source/backend/utils/JUCE.cpp new file mode 100644 index 000000000..8e9a3517a --- /dev/null +++ b/source/backend/utils/JUCE.cpp @@ -0,0 +1,77 @@ +/* + * Carla Plugin Host + * Copyright (C) 2011-2020 Filipe Coelho + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaUtils.h" +#include "CarlaUtils.hpp" + +#ifdef USING_JUCE + +// ------------------------------------------------------------------------------------------------------------------- + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wconversion" +# pragma GCC diagnostic ignored "-Weffc++" +# pragma GCC diagnostic ignored "-Wsign-conversion" +# pragma GCC diagnostic ignored "-Wundef" +#endif + +#include "AppConfig.h" +#include "juce_events/juce_events.h" + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +# pragma GCC diagnostic pop +#endif + +// ------------------------------------------------------------------------------------------------------------------- + +void carla_juce_init() +{ + juce::initialiseJuce_GUI(); +#if !(defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) + juce::MessageManager::getInstance()->setCurrentThreadAsMessageThread(); +#endif +} + +void carla_juce_idle() +{ +#if !(defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) + const juce::MessageManager* const msgMgr(juce::MessageManager::getInstanceWithoutCreating()); + CARLA_SAFE_ASSERT_RETURN(msgMgr != nullptr,); + + for (; msgMgr->dispatchNextMessageOnSystemQueue(true);) {} +#endif +} + +void carla_juce_cleanup() +{ + juce::shutdownJuce_GUI(); +} + +// ------------------------------------------------------------------------------------------------------------------- + +#else // USING_JUCE + +// ------------------------------------------------------------------------------------------------------------------- + +void carla_juce_init() {} +void carla_juce_idle() {} +void carla_juce_cleanup() {} + +// ------------------------------------------------------------------------------------------------------------------- + +#endif // USING_JUCE diff --git a/source/backend/utils/Makefile b/source/backend/utils/Makefile index 42752f243..f816e9f78 100644 --- a/source/backend/utils/Makefile +++ b/source/backend/utils/Makefile @@ -16,6 +16,7 @@ BUILD_CXX_FLAGS += $(FLUIDSYNTH_FLAGS) OBJS = \ $(OBJDIR)/CachedPlugins.cpp.o \ $(OBJDIR)/Information.cpp.o \ + $(OBJDIR)/JUCE.cpp.o \ $(OBJDIR)/PipeClient.cpp.o \ $(OBJDIR)/System.cpp.o \ $(OBJDIR)/Windows.cpp.o diff --git a/source/frontend/carla_database.py b/source/frontend/carla_database.py index 8fa7ee2e4..affd91c4f 100755 --- a/source/frontend/carla_database.py +++ b/source/frontend/carla_database.py @@ -931,6 +931,9 @@ class SearchPluginsThread(QThread): plugins = [] self._pluginLook(self.fLastCheckValue, "{} plugins...".format(PLUG_TEXT)) + if not isLV2: + gCarla.utils.juce_init() + count = gCarla.utils.get_cached_plugin_count(PLUG_TYPE, PLUG_PATH) if not self.fContinueChecking: @@ -950,6 +953,9 @@ class SearchPluginsThread(QThread): if not self.fContinueChecking: break + if not isLV2: + gCarla.utils.juce_cleanup() + self.fLastCheckValue += self.fCurPercentValue return plugins @@ -1903,6 +1909,9 @@ class PluginDatabaseW(QDialog): plugins = settingsDB.value("Plugins/" + ptypeStr, [], list) pluginCount = settingsDB.value("PluginCount/" + ptypeStr, 0, int) + if ptype == PLUGIN_AU: + gCarla.utils.juce_init() + pluginCountNew = gCarla.utils.get_cached_plugin_count(ptype, path) if pluginCountNew != pluginCount or len(plugins) != pluginCount or (len(plugins) > 0 and plugins[0]['API'] != PLUGIN_QUERY_API_VERSION): @@ -1910,6 +1919,8 @@ class PluginDatabaseW(QDialog): pluginCount = pluginCountNew QApplication.processEvents(QEventLoop.ExcludeUserInputEvents, 50) + if ptype == PLUGIN_AU: + gCarla.utils.juce_idle() for i in range(pluginCountNew): descInfo = gCarla.utils.get_cached_plugin_info(ptype, i) @@ -1923,10 +1934,15 @@ class PluginDatabaseW(QDialog): if i % 50 == 0: QApplication.processEvents(QEventLoop.ExcludeUserInputEvents, 50) + if ptype == PLUGIN_AU: + gCarla.utils.juce_idle() settingsDB.setValue("Plugins/" + ptypeStr, plugins) settingsDB.setValue("PluginCount/" + ptypeStr, pluginCount) + if ptype == PLUGIN_AU: + gCarla.utils.juce_cleanup() + # prepare rows in advance self.ui.tableWidget.setRowCount(self.fLastTableIndex + len(plugins)) diff --git a/source/frontend/carla_utils.py b/source/frontend/carla_utils.py index 42ee0c4fa..454cd475c 100644 --- a/source/frontend/carla_utils.py +++ b/source/frontend/carla_utils.py @@ -249,6 +249,15 @@ class CarlaUtils(object): self.lib.carla_pipe_client_destroy.argtypes = [CarlaPipeClientHandle] self.lib.carla_pipe_client_destroy.restype = None + self.lib.carla_juce_init.argtypes = None + self.lib.carla_juce_init.restype = None + + self.lib.carla_juce_idle.argtypes = None + self.lib.carla_juce_idle.restype = None + + self.lib.carla_juce_cleanup.argtypes = None + self.lib.carla_juce_cleanup.restype = None + self.lib.carla_cocoa_get_window.argtypes = [c_uintptr] self.lib.carla_cocoa_get_window.restype = c_int @@ -388,6 +397,15 @@ class CarlaUtils(object): def pipe_client_destroy(self, handle): self.lib.carla_pipe_client_destroy(handle) + def juce_init(self): + self.lib.carla_juce_init() + + def juce_idle(self): + self.lib.carla_juce_idle() + + def juce_cleanup(self): + self.lib.carla_juce_cleanup() + def cocoa_get_window(self, winId): return self.lib.carla_cocoa_get_window(winId)