Browse Source

Create a hidden HWND for timer

Do not rely on the passed parent window because the plugin does not own it.
pull/360/head
Luciano Iam 4 years ago
parent
commit
672f47e2c3
1 changed files with 36 additions and 8 deletions
  1. +36
    -8
      distrho/src/DistrhoUIVST3.cpp

+ 36
- 8
distrho/src/DistrhoUIVST3.cpp View File

@@ -36,6 +36,10 @@
# define DPF_VST3_USING_HOST_RUN_LOOP # define DPF_VST3_USING_HOST_RUN_LOOP
#endif #endif


#if defined(DISTRHO_OS_WINDOWS)
# define DPF_VST3_WIN32_TIMER_ID 1
#endif

#ifndef DPF_VST3_TIMER_INTERVAL #ifndef DPF_VST3_TIMER_INTERVAL
# define DPF_VST3_TIMER_INTERVAL 16 /* ~60 fps */ # define DPF_VST3_TIMER_INTERVAL 16 /* ~60 fps */
#endif #endif
@@ -135,7 +139,8 @@ public:
fTimerPtr(nullptr), fTimerPtr(nullptr),
#endif #endif
#if defined(DISTRHO_OS_WINDOWS) #if defined(DISTRHO_OS_WINDOWS)
fTimerHwnd(reinterpret_cast<HWND>(winId)),
fTimerHwnd(nullptr),
fTimerWindowClassName(nullptr),
#endif #endif
fUI(this, winId, sampleRate, fUI(this, winId, sampleRate,
editParameterCallback, editParameterCallback,
@@ -515,6 +520,7 @@ public:


void onTimer() void onTimer()
{ {
d_stdout("**** ON TIMER ****\n");
fUI.plugin_idle(); fUI.plugin_idle();
doIdleStuff(); doIdleStuff();
} }
@@ -562,6 +568,7 @@ private:
#endif #endif
#if defined(DISTRHO_OS_WINDOWS) #if defined(DISTRHO_OS_WINDOWS)
HWND fTimerHwnd; HWND fTimerHwnd;
LPSTR fTimerWindowClassName;
#endif #endif


// Plugin UI (after VST3 stuff so the UI can call into us during its constructor) // Plugin UI (after VST3 stuff so the UI can call into us during its constructor)
@@ -764,20 +771,41 @@ private:
# elif defined(DISTRHO_OS_WINDOWS) # elif defined(DISTRHO_OS_WINDOWS)
void nativeIdleTimerCreate(const uint timerFrequencyInMs) void nativeIdleTimerCreate(const uint timerFrequencyInMs)
{ {
// User data could be attached to the window but we do not own it.
// Let's abuse the nIDEvent parameter.
SetTimer(fTimerHwnd, reinterpret_cast<UINT_PTR>(this), timerFrequencyInMs,
UIVst3::nativeIdleTimerCallback);
// We cannot assume anything about the native parent window passed as a
// parameter (winId) to the UIVst3 constructor because we do not own it.
// These parent windows have class names like 'reaperPluginHostWrapProc'
// and 'JUCE_nnnnnn'. Create invisible window to handle a timer intstead.
// There is no need for implementing a window proc because DefWindowProc
// already calls the callback function when processing WM_TIMER messages.
constexpr size_t clsNameSz = 256;
fTimerWindowClassName = (LPSTR)std::malloc(clsNameSz);
snprintf(fTimerWindowClassName, clsNameSz, "DPF_timer_%x", std::rand());
WNDCLASSEX cls;
ZeroMemory(&cls, sizeof(cls));
cls.cbSize = sizeof(WNDCLASSEX);
cls.cbWndExtra = sizeof(LONG_PTR);
cls.lpszClassName = fTimerWindowClassName;
RegisterClassEx(&cls);
fTimerHwnd = CreateWindowEx(0, cls.lpszClassName, "DPF Timer Helper",
0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
SetWindowLongPtr(fTimerHwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
SetTimer(fTimerHwnd, DPF_VST3_WIN32_TIMER_ID, timerFrequencyInMs,
static_cast<TIMERPROC>(UIVst3::nativeIdleTimerCallback));
} }


void nativeIdleTimerDestroy() void nativeIdleTimerDestroy()
{ {
KillTimer(fTimerHwnd, reinterpret_cast<UINT_PTR>(this));
KillTimer(fTimerHwnd, DPF_VST3_WIN32_TIMER_ID);
DestroyWindow(fTimerHwnd);
UnregisterClass(fTimerWindowClassName, nullptr);
std::free(fTimerWindowClassName);
} }


static void nativeIdleTimerCallback(HWND /*hwnd*/, UINT /*uMsg*/, UINT_PTR timerId, DWORD /*dwTime*/)
static void nativeIdleTimerCallback(HWND hwnd, UINT /*uMsg*/, UINT_PTR /*timerId*/,
DWORD /*dwTime*/)
{ {
reinterpret_cast<UIVst3*>(timerId)->onTimer();
UIVst3* ui = reinterpret_cast<UIVst3*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
ui->onTimer();
} }
# endif # endif
#endif #endif


Loading…
Cancel
Save