From c22ecc6c57bbb4a383b7aa6b0c9cb3e44bb0aca8 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 1 Oct 2021 23:11:37 +0100 Subject: [PATCH] VST3: Handle UI on macOS and Windows Signed-off-by: falkTX --- dgl/Application.hpp | 1 + dgl/src/ApplicationPrivateData.cpp | 5 +++ dgl/src/ApplicationPrivateData.hpp | 3 ++ distrho/src/DistrhoUIInternal.hpp | 22 ++++++++++++ distrho/src/DistrhoUIPrivateData.hpp | 8 ++++- distrho/src/DistrhoUIVST3.cpp | 50 ++++++++++++++++++++++++++-- 6 files changed, 85 insertions(+), 4 deletions(-) diff --git a/dgl/Application.hpp b/dgl/Application.hpp index 0979987a..87937cc7 100644 --- a/dgl/Application.hpp +++ b/dgl/Application.hpp @@ -107,6 +107,7 @@ public: private: struct PrivateData; PrivateData* const pData; + friend class PluginApplication; friend class Window; DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Application) diff --git a/dgl/src/ApplicationPrivateData.cpp b/dgl/src/ApplicationPrivateData.cpp index 1de1fc76..f573c2f7 100644 --- a/dgl/src/ApplicationPrivateData.cpp +++ b/dgl/src/ApplicationPrivateData.cpp @@ -118,6 +118,11 @@ void Application::PrivateData::idle(const uint timeoutInMs) puglUpdate(world, timeoutInSeconds); } + triggerIdleCallbacks(); +} + +void Application::PrivateData::triggerIdleCallbacks() +{ for (std::list::iterator it = idleCallbacks.begin(), ite = idleCallbacks.end(); it != ite; ++it) { IdleCallback* const idleCallback(*it); diff --git a/dgl/src/ApplicationPrivateData.hpp b/dgl/src/ApplicationPrivateData.hpp index e35328d3..0d2993c4 100644 --- a/dgl/src/ApplicationPrivateData.hpp +++ b/dgl/src/ApplicationPrivateData.hpp @@ -84,6 +84,9 @@ struct Application::PrivateData { /** Run Pugl world update for @a timeoutInMs, and then each idle callback in order of registration. */ void idle(uint timeoutInMs); + /** Run each idle callback without updating pugl world. */ + void triggerIdleCallbacks(); + /** Set flag indicating application is quitting, and close all windows in reverse order of registration. For standalone mode only. */ void quit(); diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp index 46de9858..35606a98 100644 --- a/distrho/src/DistrhoUIInternal.hpp +++ b/distrho/src/DistrhoUIInternal.hpp @@ -234,6 +234,28 @@ public: // ------------------------------------------------------------------- +#if defined(DISTRHO_PLUGIN_TARGET_VST3) && (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)) + void addIdleCallbackForVST3(IdleCallback* const cb, const uint timerFrequencyInMs) + { + uiData->window->addIdleCallback(cb, timerFrequencyInMs); + } + + void removeIdleCallbackForVST3(IdleCallback* const cb) + { + uiData->window->removeIdleCallback(cb); + } + + void idleForVST3() + { + DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,); + + uiData->app.triggerIdleCallbacks(); + ui->uiIdle(); + } +#endif + + // ------------------------------------------------------------------- + void setWindowTitle(const char* const uiTitle) { uiData->window->setTitle(uiTitle); diff --git a/distrho/src/DistrhoUIPrivateData.hpp b/distrho/src/DistrhoUIPrivateData.hpp index ca8a96f9..93a8a89a 100644 --- a/distrho/src/DistrhoUIPrivateData.hpp +++ b/distrho/src/DistrhoUIPrivateData.hpp @@ -22,7 +22,7 @@ #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI # include "../extra/Sleep.hpp" #else -# include "../../dgl/Application.hpp" +# include "../../dgl/src/ApplicationPrivateData.hpp" # include "../../dgl/src/WindowPrivateData.hpp" # include "../../dgl/src/pugl.hpp" #endif @@ -98,6 +98,7 @@ struct PluginApplication // these are not needed void idle() {} void quit() {} + void triggerIdleCallbacks() {} DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication) }; @@ -119,6 +120,11 @@ public: setClassName(className); } + void triggerIdleCallbacks() + { + pData->triggerIdleCallbacks(); + } + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginApplication) }; #endif diff --git a/distrho/src/DistrhoUIVST3.cpp b/distrho/src/DistrhoUIVST3.cpp index 281dd934..42a708de 100644 --- a/distrho/src/DistrhoUIVST3.cpp +++ b/distrho/src/DistrhoUIVST3.cpp @@ -28,9 +28,16 @@ * - size constraints * - host-side resize * - oddities with init and size callback (triggered too early?) - * - win/mac native idle loop */ +#if !(defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)) +# define DPF_VST3_USING_HOST_RUN_LOOP +#endif + +#ifndef DPF_VST3_TIMER_INTERVAL +# define DPF_VST3_TIMER_INTERVAL 16 /* ~60 fps */ +#endif + START_NAMESPACE_DISTRHO // -------------------------------------------------------------------------------------------------------------------- @@ -70,6 +77,9 @@ struct ScopedUTF16String { * The low-level VST3 stuff comes after. */ class UIVst3 +#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS) + : public IdleCallback +#endif { public: UIVst3(v3_plugin_view** const view, @@ -95,10 +105,16 @@ public: fReadyForPluginData(false), fScaleFactor(scaleFactor) { +#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS) + fUI.addIdleCallbackForVST3(this, DPF_VST3_TIMER_INTERVAL); +#endif } ~UIVst3() { +#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS) + fUI.removeIdleCallbackForVST3(this); +#endif if (fConnection != nullptr) disconnect(); } @@ -320,6 +336,21 @@ public: return V3_OK; } + // ---------------------------------------------------------------------------------------------------------------- + // special idle callback on macOS and Windows + +#if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS) + void idleCallback() override + { + if (fReadyForPluginData) + { + fReadyForPluginData = false; + requestMorePluginData(); + } + + fUI.idleForVST3(); + } +#else // ---------------------------------------------------------------------------------------------------------------- // v3_timer_handler interface calls @@ -333,6 +364,7 @@ public: fUI.plugin_idle(); } +#endif // ---------------------------------------------------------------------------------------------------------------- @@ -676,6 +708,7 @@ struct dpf_plugin_view_content_scale : v3_plugin_view_content_scale_cpp { } }; +#ifdef DPF_VST3_USING_HOST_RUN_LOOP // -------------------------------------------------------------------------------------------------------------------- // dpf_timer_handler @@ -732,6 +765,7 @@ struct dpf_timer_handler : v3_timer_handler_cpp { handler->uivst3->onTimer(); } }; +#endif // -------------------------------------------------------------------------------------------------------------------- // dpf_plugin_view @@ -741,7 +775,9 @@ struct dpf_plugin_view : v3_plugin_view_cpp { ScopedPointer* self; ScopedPointer connection; ScopedPointer scale; +#ifdef DPF_VST3_USING_HOST_RUN_LOOP ScopedPointer timer; +#endif ScopedPointer uivst3; // cached values v3_host_application** const host; @@ -869,12 +905,14 @@ struct dpf_plugin_view : v3_plugin_view_cpp { { if (std::strcmp(kSupportedPlatforms[i], platform_type) == 0) { - // find host run loop to plug ourselves into (required) + #ifdef DPF_VST3_USING_HOST_RUN_LOOP + // find host run loop to plug ourselves into (required on some systems) DISTRHO_SAFE_ASSERT_RETURN(view->frame != nullptr, V3_INVALID_ARG); v3_run_loop** runloop = nullptr; v3_cpp_obj_query_interface(view->frame, v3_run_loop_iid, &runloop); DISTRHO_SAFE_ASSERT_RETURN(runloop != nullptr, V3_INVALID_ARG); + #endif const float scaleFactor = view->scale != nullptr ? view->scale->scaleFactor : 0.0f; view->uivst3 = new UIVst3((v3_plugin_view**)view->self, @@ -890,9 +928,13 @@ struct dpf_plugin_view : v3_plugin_view_cpp { view->uivst3->setFrame(view->frame); + #ifdef DPF_VST3_USING_HOST_RUN_LOOP // register a timer host run loop stuff view->timer = new dpf_timer_handler(view->uivst3); - v3_cpp_obj(runloop)->register_timer(runloop, (v3_timer_handler**)&view->timer, 16); + v3_cpp_obj(runloop)->register_timer(runloop, + (v3_timer_handler**)&view->timer, + DPF_VST3_TIMER_INTERVAL); + #endif return V3_OK; } @@ -908,6 +950,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp { DISTRHO_SAFE_ASSERT_RETURN(view != nullptr, V3_NOT_INITIALISED); DISTRHO_SAFE_ASSERT_RETURN(view->uivst3 != nullptr, V3_INVALID_ARG); + #ifdef DPF_VST3_USING_HOST_RUN_LOOP // unregister our timer as needed if (view->timer != nullptr) { @@ -917,6 +960,7 @@ struct dpf_plugin_view : v3_plugin_view_cpp { view->timer = nullptr; } + #endif view->uivst3 = nullptr; return V3_OK;