comparison DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoUIInternal.hpp @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
4 *
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.
8 *
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.
15 */
16
17 #ifndef DISTRHO_UI_INTERNAL_HPP_INCLUDED
18 #define DISTRHO_UI_INTERNAL_HPP_INCLUDED
19
20 #include "DistrhoUIPrivateData.hpp"
21
22 START_NAMESPACE_DISTRHO
23
24 // -----------------------------------------------------------------------
25 // Static data, see DistrhoUI.cpp
26
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
32
33 // -----------------------------------------------------------------------
34 // UI exporter class
35
36 class UIExporter
37 {
38 // -------------------------------------------------------------------
39 // UI Widget and its private data
40
41 UI* ui;
42 UI::PrivateData* uiData;
43
44 // -------------------------------------------------------------------
45
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 const char* const appClassName = nullptr)
62 : ui(nullptr),
63 uiData(new UI::PrivateData(appClassName))
64 {
65 uiData->sampleRate = sampleRate;
66 uiData->bundlePath = bundlePath != nullptr ? strdup(bundlePath) : nullptr;
67 uiData->dspPtr = dspPtr;
68
69 uiData->bgColor = bgColor;
70 uiData->fgColor = fgColor;
71 uiData->scaleFactor = scaleFactor;
72 uiData->winId = winId;
73
74 uiData->callbacksPtr = callbacksPtr;
75 uiData->editParamCallbackFunc = editParamCall;
76 uiData->setParamCallbackFunc = setParamCall;
77 uiData->setStateCallbackFunc = setStateCall;
78 uiData->sendNoteCallbackFunc = sendNoteCall;
79 uiData->setSizeCallbackFunc = setSizeCall;
80 uiData->fileRequestCallbackFunc = fileRequestCall;
81
82 g_nextBundlePath = bundlePath;
83 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
84 g_nextWindowId = winId;
85 g_nextScaleFactor = scaleFactor;
86 #endif
87 UI::PrivateData::s_nextPrivateData = uiData;
88
89 UI* const uiPtr = createUI();
90
91 g_nextBundlePath = nullptr;
92 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
93 g_nextWindowId = 0;
94 g_nextScaleFactor = 0.0;
95 #else
96 // enter context called in the PluginWindow constructor, see DistrhoUIPrivateData.hpp
97 uiData->window->leaveContext();
98 #endif
99 UI::PrivateData::s_nextPrivateData = nullptr;
100
101 DISTRHO_SAFE_ASSERT_RETURN(uiPtr != nullptr,);
102 ui = uiPtr;
103 uiData->initializing = false;
104
105 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
106 // unused
107 (void)bundlePath;
108 #endif
109 }
110
111 ~UIExporter()
112 {
113 quit();
114 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
115 uiData->window->enterContextForDeletion();
116 #endif
117 delete ui;
118 delete uiData;
119 }
120
121 // -------------------------------------------------------------------
122
123 uint getWidth() const noexcept
124 {
125 return uiData->window->getWidth();
126 }
127
128 uint getHeight() const noexcept
129 {
130 return uiData->window->getHeight();
131 }
132
133 double getScaleFactor() const noexcept
134 {
135 return uiData->window->getScaleFactor();
136 }
137
138 bool getGeometryConstraints(uint& minimumWidth, uint& minimumHeight, bool& keepAspectRatio) const noexcept
139 {
140 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
141 uiData->window->getGeometryConstraints(minimumWidth, minimumHeight, keepAspectRatio);
142 #else
143 const DGL_NAMESPACE::Size<uint> size(uiData->window->getGeometryConstraints(keepAspectRatio));
144 minimumWidth = size.getWidth();
145 minimumHeight = size.getHeight();
146 #endif
147 return true;
148 }
149
150 bool isResizable() const noexcept
151 {
152 return uiData->window->isResizable();
153 }
154
155 bool isVisible() const noexcept
156 {
157 return uiData->window->isVisible();
158 }
159
160 uintptr_t getNativeWindowHandle() const noexcept
161 {
162 return uiData->window->getNativeWindowHandle();
163 }
164
165 uint getBackgroundColor() const noexcept
166 {
167 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0);
168
169 return uiData->bgColor;
170 }
171
172 uint getForegroundColor() const noexcept
173 {
174 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0xffffffff);
175
176 return uiData->fgColor;
177 }
178
179 // -------------------------------------------------------------------
180
181 uint32_t getParameterOffset() const noexcept
182 {
183 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr, 0);
184
185 return uiData->parameterOffset;
186 }
187
188 // -------------------------------------------------------------------
189
190 void parameterChanged(const uint32_t index, const float value)
191 {
192 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
193
194 ui->parameterChanged(index, value);
195 }
196
197 #if DISTRHO_PLUGIN_WANT_PROGRAMS
198 void programLoaded(const uint32_t index)
199 {
200 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
201
202 ui->programLoaded(index);
203 }
204 #endif
205
206 #if DISTRHO_PLUGIN_WANT_STATE
207 void stateChanged(const char* const key, const char* const value)
208 {
209 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
210 DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
211 DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
212
213 ui->stateChanged(key, value);
214 }
215 #endif
216
217 // -------------------------------------------------------------------
218
219 #if DISTRHO_UI_IS_STANDALONE
220 void exec(DGL_NAMESPACE::IdleCallback* const cb)
221 {
222 DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
223
224 uiData->window->show();
225 uiData->window->focus();
226 uiData->app.addIdleCallback(cb);
227 uiData->app.exec();
228 }
229
230 void exec_idle()
231 {
232 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, );
233
234 ui->uiIdle();
235 }
236
237 void showAndFocus()
238 {
239 uiData->window->show();
240 uiData->window->focus();
241 }
242 #endif
243
244 bool plugin_idle()
245 {
246 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false);
247
248 uiData->app.idle();
249 ui->uiIdle();
250 return ! uiData->app.isQuitting();
251 }
252
253 void focus()
254 {
255 uiData->window->focus();
256 }
257
258 void quit()
259 {
260 uiData->window->close();
261 uiData->app.quit();
262 }
263
264 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
265 void repaint()
266 {
267 uiData->window->repaint();
268 }
269 #endif
270
271 // -------------------------------------------------------------------
272
273 #if defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS)
274 void idleFromNativeIdle()
275 {
276 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
277
278 uiData->app.triggerIdleCallbacks();
279 ui->uiIdle();
280 }
281
282 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
283 void addIdleCallbackForNativeIdle(IdleCallback* const cb, const uint timerFrequencyInMs)
284 {
285 uiData->window->addIdleCallback(cb, timerFrequencyInMs);
286 }
287
288 void removeIdleCallbackForNativeIdle(IdleCallback* const cb)
289 {
290 uiData->window->removeIdleCallback(cb);
291 }
292 #endif
293 #endif
294
295 // -------------------------------------------------------------------
296
297 void setWindowOffset(const int x, const int y)
298 {
299 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
300 // TODO
301 (void)x; (void)y;
302 #else
303 uiData->window->setOffset(x, y);
304 #endif
305 }
306
307 #if defined(DISTRHO_PLUGIN_TARGET_VST3) || defined(DISTRHO_PLUGIN_TARGET_CLAP)
308 void setWindowSizeFromHost(const uint width, const uint height)
309 {
310 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
311 ui->setSize(width, height);
312 #else
313 uiData->window->setSizeFromHost(width, height);
314 #endif
315 }
316 #endif
317
318 void setWindowTitle(const char* const uiTitle)
319 {
320 uiData->window->setTitle(uiTitle);
321 }
322
323 void setWindowTransientWinId(const uintptr_t transientParentWindowHandle)
324 {
325 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
326 ui->setTransientWindowId(transientParentWindowHandle);
327 #else
328 uiData->window->setTransientParent(transientParentWindowHandle);
329 #endif
330 }
331
332 bool setWindowVisible(const bool yesNo)
333 {
334 uiData->window->setVisible(yesNo);
335
336 return ! uiData->app.isQuitting();
337 }
338
339 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
340 bool handlePluginKeyboardVST(const bool press, const bool special, const uint keychar, const uint keycode, const uint16_t mods)
341 {
342 using namespace DGL_NAMESPACE;
343
344 Widget::KeyboardEvent ev;
345 ev.mod = mods;
346 ev.press = press;
347 ev.key = keychar;
348 ev.keycode = keycode;
349
350 // keyboard events must always be lowercase
351 if (ev.key >= 'A' && ev.key <= 'Z')
352 ev.key += 'a' - 'A'; // A-Z -> a-z
353
354 const bool ret = ui->onKeyboard(ev);
355
356 if (press && !special && (mods & (kModifierControl|kModifierAlt|kModifierSuper)) == 0)
357 {
358 Widget::CharacterInputEvent cev;
359 cev.mod = mods;
360 cev.character = keychar;
361 cev.keycode = keycode;
362
363 // if shift modifier is on, convert a-z -> A-Z for character input
364 if (cev.character >= 'a' && cev.character <= 'z' && (mods & kModifierShift) != 0)
365 cev.character -= 'a' - 'A';
366
367 ui->onCharacterInput(cev);
368 }
369
370 return ret;
371 }
372 #endif
373
374 // -------------------------------------------------------------------
375
376 void notifyScaleFactorChanged(const double scaleFactor)
377 {
378 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
379
380 ui->uiScaleFactorChanged(scaleFactor);
381 }
382
383 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
384 void notifyFocusChanged(const bool focus)
385 {
386 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
387
388 ui->uiFocus(focus, DGL_NAMESPACE::kCrossingNormal);
389 }
390 #endif
391
392 void setSampleRate(const double sampleRate, const bool doCallback = false)
393 {
394 DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr,);
395 DISTRHO_SAFE_ASSERT_RETURN(uiData != nullptr,);
396 DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
397
398 if (d_isEqual(uiData->sampleRate, sampleRate))
399 return;
400
401 uiData->sampleRate = sampleRate;
402
403 if (doCallback)
404 ui->sampleRateChanged(sampleRate);
405 }
406
407 DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter)
408 };
409
410 // -----------------------------------------------------------------------
411
412 END_NAMESPACE_DISTRHO
413
414 #endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED