Browse Source

VST3: Handle UI on macOS and Windows

Signed-off-by: falkTX <falktx@falktx.com>
pull/338/head
falkTX 3 years ago
parent
commit
c22ecc6c57
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
6 changed files with 85 additions and 4 deletions
  1. +1
    -0
      dgl/Application.hpp
  2. +5
    -0
      dgl/src/ApplicationPrivateData.cpp
  3. +3
    -0
      dgl/src/ApplicationPrivateData.hpp
  4. +22
    -0
      distrho/src/DistrhoUIInternal.hpp
  5. +7
    -1
      distrho/src/DistrhoUIPrivateData.hpp
  6. +47
    -3
      distrho/src/DistrhoUIVST3.cpp

+ 1
- 0
dgl/Application.hpp View File

@@ -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)


+ 5
- 0
dgl/src/ApplicationPrivateData.cpp View File

@@ -118,6 +118,11 @@ void Application::PrivateData::idle(const uint timeoutInMs)
puglUpdate(world, timeoutInSeconds);
}

triggerIdleCallbacks();
}

void Application::PrivateData::triggerIdleCallbacks()
{
for (std::list<IdleCallback*>::iterator it = idleCallbacks.begin(), ite = idleCallbacks.end(); it != ite; ++it)
{
IdleCallback* const idleCallback(*it);


+ 3
- 0
dgl/src/ApplicationPrivateData.hpp View File

@@ -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();


+ 22
- 0
distrho/src/DistrhoUIInternal.hpp View File

@@ -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);


+ 7
- 1
distrho/src/DistrhoUIPrivateData.hpp View File

@@ -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


+ 47
- 3
distrho/src/DistrhoUIVST3.cpp View File

@@ -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<dpf_plugin_view>* self;
ScopedPointer<dpf_ui_connection_point> connection;
ScopedPointer<dpf_plugin_view_content_scale> scale;
#ifdef DPF_VST3_USING_HOST_RUN_LOOP
ScopedPointer<dpf_timer_handler> timer;
#endif
ScopedPointer<UIVst3> 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;


Loading…
Cancel
Save