Add initial bits for Qt6 support
[carla.git] / source / modules / distrho / src / DistrhoUIInternal.hpp
blobb470224646e1d79cfb59e8b61f765a9b8ba078a4
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #ifndef DISTRHO_UI_INTERNAL_HPP_INCLUDED
18 #define DISTRHO_UI_INTERNAL_HPP_INCLUDED
20 #include "DistrhoUIPrivateData.hpp"
22 START_NAMESPACE_DISTRHO
24 // -----------------------------------------------------------------------
25 // Static data, see DistrhoUI.cpp
27 extern const char* g_nextBundlePath;
28 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
29 extern uintptr_t g_nextWindowId;
30 extern double g_nextScaleFactor;
31 #endif
33 // -----------------------------------------------------------------------
34 // UI exporter class
36 class UIExporter
38 // -------------------------------------------------------------------
39 // UI Widget and its private data
41 UI* ui;
42 UI::PrivateData* uiData;
44 // -------------------------------------------------------------------
46 public:
47 UIExporter(void* const callbacksPtr,
48 const uintptr_t winId,
49 const double sampleRate,
50 const editParamFunc editParamCall,
51 const setParamFunc setParamCall,
52 const setStateFunc setStateCall,
53 const sendNoteFunc sendNoteCall,
54 const setSizeFunc setSizeCall,
55 const fileRequestFunc fileRequestCall,
56 const char* const bundlePath = nullptr,
57 void* const dspPtr = nullptr,
58 const double scaleFactor = 0.0,
59 const uint32_t bgColor = 0,
60 const uint32_t fgColor = 0xffffffff)
61 : ui(nullptr),
62 uiData(new UI::PrivateData())
64 uiData->sampleRate = sampleRate;
65 uiData->bundlePath = bundlePath != nullptr ? strdup(bundlePath) : nullptr;
66 uiData->dspPtr = dspPtr;
68 uiData->bgColor = bgColor;
69 uiData->fgColor = fgColor;
70 uiData->scaleFactor = scaleFactor;
71 uiData->winId = winId;
73 uiData->callbacksPtr = callbacksPtr;
74 uiData->editParamCallbackFunc = editParamCall;
75 uiData->setParamCallbackFunc = setParamCall;
76 uiData->setStateCallbackFunc = setStateCall;
77 uiData->sendNoteCallbackFunc = sendNoteCall;
78 uiData->setSizeCallbackFunc = setSizeCall;
79 uiData->fileRequestCallbackFunc = fileRequestCall;
81 g_nextBundlePath = bundlePath;
82 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
83 g_nextWindowId = winId;
84 g_nextScaleFactor = scaleFactor;
85 #endif
86 UI::PrivateData::s_nextPrivateData = uiData;
88 UI* const uiPtr = createUI();
90 g_nextBundlePath = nullptr;
91 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
92 g_nextWindowId = 0;
93 g_nextScaleFactor = 0.0;
94 #else
95 // enter context called in the PluginWindow constructor, see DistrhoUIPrivateData.hpp
96 uiData->window->leaveContext();
97 #endif
98 UI::PrivateData::s_nextPrivateData = nullptr;
100 DISTRHO_SAFE_ASSERT_RETURN(uiPtr != nullptr,);
101 ui = uiPtr;
102 uiData->initializing = false;
104 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
105 // unused
106 (void)bundlePath;
107 #endif
110 ~UIExporter()
112 quit();
113 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
114 uiData->window->enterContextForDeletion();
115 #endif
116 delete ui;
117 delete uiData;
120 // -------------------------------------------------------------------
122 uint getWidth() const noexcept
124 return uiData->window->getWidth();
127 uint getHeight() const noexcept
129 return uiData->window->getHeight();
132 double getScaleFactor() const noexcept
134 return uiData->window->getScaleFactor();
137 bool getGeometryConstraints(uint& minimumWidth, uint& minimumHeight, bool& keepAspectRatio) const noexcept
139 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
140 uiData->window->getGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio);
141 #else
142 const DGL_NAMESPACE::Size<uint> size(uiData->window->getGeometryConstraints(keepAspectRatio));
143 minimumWidth = size.getWidth();
144 minimumHeight = size.getHeight();
145 #endif
146 return true;
149 bool isResizable() const noexcept
151 return uiData->window->isResizable();
154 bool isVisible() const noexcept
156 return uiData->window->isVisible();
159 uintptr_t getNativeWindowHandle() const noexcept
161 return uiData->window->getNativeWindowHandle();
164 uint getBackgroundColor() const noexcept
166 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0);
168 return uiData->bgColor;
171 uint getForegroundColor() const noexcept
173 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0xffffffff);
175 return uiData->fgColor;
178 // -------------------------------------------------------------------
180 uint32_t getParameterOffset() const noexcept
182 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0);
184 return uiData->parameterOffset;
187 // -------------------------------------------------------------------
189 void parameterChanged(const uint32_t index, const float value)
191 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
193 ui->parameterChanged(index, value);
196 #if DISTRHO_PLUGIN_WANT_PROGRAMS
197 void programLoaded(const uint32_t index)
199 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
201 ui->programLoaded(index);
203 #endif
205 #if DISTRHO_PLUGIN_WANT_STATE
206 void stateChanged(const char* const key, const char* const value)
208 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
209 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
210 DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
212 ui->stateChanged(key, value);
214 #endif
216 // -------------------------------------------------------------------
218 #if DISTRHO_UI_IS_STANDALONE
219 void exec(DGL_NAMESPACE::IdleCallback* const cb)
221 DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
223 uiData->window->show();
224 uiData->window->focus();
225 uiData->app.addIdleCallback(cb);
226 uiData->app.exec();
229 void exec_idle()
231 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, );
233 ui->uiIdle();
236 void showAndFocus()
238 uiData->window->show();
239 uiData->window->focus();
241 #endif
243 bool plugin_idle()
245 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false);
247 uiData->app.idle();
248 ui->uiIdle();
249 return ! uiData->app.isQuitting();
252 void focus()
254 uiData->window->focus();
257 void quit()
259 uiData->window->close();
260 uiData->app.quit();
263 // -------------------------------------------------------------------
265 #if defined(DISTRHO_PLUGIN_TARGET_VST3) && (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
266 void idleForVST3()
268 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
270 uiData->app.triggerIdleCallbacks();
271 ui->uiIdle();
274 # if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
275 void addIdleCallbackForVST3(IdleCallback* const cb, const uint timerFrequencyInMs)
277 uiData->window->addIdleCallback(cb, timerFrequencyInMs);
280 void removeIdleCallbackForVST3(IdleCallback* const cb)
282 uiData->window->removeIdleCallback(cb);
284 # endif
285 #endif
287 // -------------------------------------------------------------------
289 void setWindowOffset(const int x, const int y)
291 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
292 // TODO
293 (void)x; (void)y;
294 #else
295 uiData->window->setOffset(x, y);
296 #endif
299 #ifdef DISTRHO_PLUGIN_TARGET_VST3
300 void setWindowSizeForVST3(const uint width, const uint height)
302 # if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
303 ui->setSize(width, height);
304 # else
305 uiData->window->setSizeForVST3(width, height);
306 # endif
308 #endif
310 void setWindowTitle(const char* const uiTitle)
312 uiData->window->setTitle(uiTitle);
315 void setWindowTransientWinId(const uintptr_t transientParentWindowHandle)
317 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
318 ui->setTransientWindowId(transientParentWindowHandle);
319 #else
320 uiData->window->setTransientParent(transientParentWindowHandle);
321 #endif
324 bool setWindowVisible(const bool yesNo)
326 uiData->window->setVisible(yesNo);
328 return ! uiData->app.isQuitting();
331 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
332 bool handlePluginKeyboardVST(const bool press, const bool special, const uint keychar, const uint keycode, const uint16_t mods)
334 using namespace DGL_NAMESPACE;
336 Widget::KeyboardEvent ev;
337 ev.mod = mods;
338 ev.press = press;
339 ev.key = keychar;
340 ev.keycode = keycode;
342 // keyboard events must always be lowercase
343 if (ev.key >= 'A' && ev.key <= 'Z')
344 ev.key += 'a' - 'A'; // A-Z -> a-z
346 const bool ret = ui->onKeyboard(ev);
348 if (press && !special && (mods & (kModifierControl|kModifierAlt|kModifierSuper)) == 0)
350 Widget::CharacterInputEvent cev;
351 cev.mod = mods;
352 cev.character = keychar;
353 cev.keycode = keycode;
355 // if shift modifier is on, convert a-z -> A-Z for character input
356 if (cev.character >= 'a' && cev.character <= 'z' && (mods & kModifierShift) != 0)
357 cev.character -= 'a' - 'A';
359 ui->onCharacterInput(cev);
362 return ret;
364 #endif
366 // -------------------------------------------------------------------
368 void notifyScaleFactorChanged(const double scaleFactor)
370 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
372 ui->uiScaleFactorChanged(scaleFactor);
375 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
376 void notifyFocusChanged(const bool focus)
378 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
380 ui->uiFocus(focus, DGL_NAMESPACE::kCrossingNormal);
382 #endif
384 void setSampleRate(const double sampleRate, const bool doCallback = false)
386 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
387 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr,);
388 DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
390 if (d_isEqual(uiData->sampleRate, sampleRate))
391 return;
393 uiData->sampleRate = sampleRate;
395 if (doCallback)
396 ui->sampleRateChanged(sampleRate);
399 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter)
402 // -----------------------------------------------------------------------
404 END_NAMESPACE_DISTRHO
406 #endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED