Mercurial > hg > pub > prymula > com
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 |