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
;
33 // -----------------------------------------------------------------------
38 // -------------------------------------------------------------------
39 // UI Widget and its private data
42 UI::PrivateData
* uiData
;
44 // -------------------------------------------------------------------
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)
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
;
86 UI::PrivateData::s_nextPrivateData
= uiData
;
88 UI
* const uiPtr
= createUI();
90 g_nextBundlePath
= nullptr;
91 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
93 g_nextScaleFactor
= 0.0;
95 // enter context called in the PluginWindow constructor, see DistrhoUIPrivateData.hpp
96 uiData
->window
->leaveContext();
98 UI::PrivateData::s_nextPrivateData
= nullptr;
100 DISTRHO_SAFE_ASSERT_RETURN(uiPtr
!= nullptr,);
102 uiData
->initializing
= false;
104 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
113 #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI
114 uiData
->window
->enterContextForDeletion();
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
);
142 const DGL_NAMESPACE::Size
<uint
> size(uiData
->window
->getGeometryConstraints(keepAspectRatio
));
143 minimumWidth
= size
.getWidth();
144 minimumHeight
= size
.getHeight();
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
);
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
);
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
);
231 DISTRHO_SAFE_ASSERT_RETURN(ui
!= nullptr, );
238 uiData
->window
->show();
239 uiData
->window
->focus();
245 DISTRHO_SAFE_ASSERT_RETURN(ui
!= nullptr, false);
249 return ! uiData
->app
.isQuitting();
254 uiData
->window
->focus();
259 uiData
->window
->close();
263 // -------------------------------------------------------------------
265 #if defined(DISTRHO_PLUGIN_TARGET_VST3) && (defined(DISTRHO_OS_MAC) || defined(DISTRHO_OS_WINDOWS))
268 DISTRHO_SAFE_ASSERT_RETURN(ui
!= nullptr,);
270 uiData
->app
.triggerIdleCallbacks();
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
);
287 // -------------------------------------------------------------------
289 void setWindowOffset(const int x
, const int y
)
291 #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI
295 uiData
->window
->setOffset(x
, y
);
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
);
305 uiData
->window
->setSizeForVST3(width
, height
);
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
);
320 uiData
->window
->setTransientParent(transientParentWindowHandle
);
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
;
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
;
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
);
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
);
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
))
393 uiData
->sampleRate
= sampleRate
;
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