Dusk Audio Framework
Loading...
Searching...
No Matches
DafUI.hpp
1/*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2024 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 DAF_UI_HPP_INCLUDED
18#define DAF_UI_HPP_INCLUDED
19
20#include "DafDetails.hpp"
21#include "extra/LeakDetector.hpp"
22#include "src/DafPluginChecks.h"
23
24#ifdef DGL_CAIRO
25# include "Cairo.hpp"
26#endif
27#ifdef DGL_OPENGL
28# include "OpenGL.hpp"
29#endif
30#ifdef DGL_VULKAN
31# include "Vulkan.hpp"
32#endif
33
34#if DAF_UI_USE_CUSTOM
35# include DAF_UI_CUSTOM_INCLUDE_PATH
36typedef DAF_UI_CUSTOM_WIDGET_TYPE UIWidget;
37#elif DAF_UI_USE_CAIRO
38# include "../dgl/Cairo.hpp"
39typedef DGL_NAMESPACE::CairoTopLevelWidget UIWidget;
40#elif DAF_UI_USE_NANOVG
41# include "../dgl/NanoVG.hpp"
42typedef DGL_NAMESPACE::NanoTopLevelWidget UIWidget;
43#else
44# include "../dgl/TopLevelWidget.hpp"
45typedef DGL_NAMESPACE::TopLevelWidget UIWidget;
46#endif
47
48#if DAF_UI_FILE_BROWSER
49# include "extra/FileBrowserDialog.hpp"
50#endif
51
52#include <vector>
53
55
56class PluginWindow;
57
58/* ------------------------------------------------------------------------------------------------------------
59 * DAF UI */
60
61/**
62 @addtogroup MainClasses
63 @{
64 */
65
66/**
67 DAF UI class from where UI instances are created.
68
69 @note You must call setSize during construction,
70 @TODO Detailed information about this class.
71 */
72class UI : public UIWidget
73{
74public:
75 /**
76 UI class constructor.
77 The UI should be initialized to a default state that matches the plugin side.
78
79 When @a automaticallyScale is set to true, DAF will automatically scale up the UI
80 to fit the host/desktop scale factor.@n
81 It assumes aspect ratio is meant to be kept.
82 Manually call setGeometryConstraints instead if keeping UI aspect ratio is not required.
83 */
84 UI(uint width = 0, uint height = 0, bool automaticallyScaleAndSetAsMinimumSize = false);
85
86 /**
87 Destructor.
88 */
89 ~UI() override;
90
91 /* --------------------------------------------------------------------------------------------------------
92 * Host state */
93
94 /**
95 Check if this UI window is resizable (by the user or window manager).
96 There are situations where an UI supports resizing but the plugin host does not, so this could return false.
97
98 You might want to add a resize handle for such cases, so the user is still allowed to resize the window.
99 (programmatically resizing a window is always possible, but the same is not true for the window manager)
100 */
101 bool isResizable() const noexcept;
102
103 /**
104 Get the color used for UI background (i.e. window color) in RGBA format.
105 Returns 0 by default, in case of error or lack of host support.
106
107 The following example code can be use to extract individual colors:
108 ```
109 int red = (bgColor >> 24) & 0xff;
110 int green = (bgColor >> 16) & 0xff;
111 int blue = (bgColor >> 8) & 0xff;
112 ```
113 @see Color::fromRGB
114 */
115 uint getBackgroundColor() const noexcept;
116
117 /**
118 Get the color used for UI foreground (i.e. text color) in RGBA format.
119 Returns 0xffffffff by default, in case of error or lack of host support.
120
121 The following example code can be use to extract individual colors:
122 ```
123 int red = (fgColor >> 24) & 0xff;
124 int green = (fgColor >> 16) & 0xff;
125 int blue = (fgColor >> 8) & 0xff;
126 ```
127 @see Color::fromRGB
128 */
129 uint getForegroundColor() const noexcept;
130
131 /**
132 Get the current sample rate used in plugin processing.
133 @see sampleRateChanged(double)
134 */
135 double getSampleRate() const noexcept;
136
137 /**
138 Get the bundle path where the UI resides.@n
139 Can return null if the UI is not available in a bundle (if it is a single binary).
140 @see getBinaryFilename
141 */
142 const char* getBundlePath() const noexcept;
143
144 /**
145 editParameter.
146
147 Touch/pressed-down event.
148 Lets the host know the user is tweaking a parameter.
149 Required in some hosts to record automation.
150 */
151 void editParameter(uint32_t index, bool started);
152
153 /**
154 setParameterValue.
155
156 Change a parameter value in the Plugin.
157 */
158 void setParameterValue(uint32_t index, float value);
159
160#if DAF_PLUGIN_WANT_STATE
161 /**
162 setState.
163 @TODO Document this.
164 */
165 void setState(const char* key, const char* value);
166
167 /**
168 Request a new file from the host, matching the properties of a state key.@n
169 This will use the native host file browser if available, otherwise a DAF built-in file browser is used.@n
170 Response will be sent asynchronously to stateChanged, with the matching key and the new file as the value.@n
171 It is not possible to know if the action was cancelled by the user.
172
173 @return Success if a file-browser was opened, otherwise false.
174 @note You cannot request more than one file at a time.
175 */
176 bool requestStateFile(const char* key);
177#endif
178
179#if DAF_PLUGIN_WANT_MIDI_INPUT
180 /**
181 Send a single MIDI note from the UI to the plugin DSP side.@n
182 A note with zero velocity will be sent as note-off (MIDI 0x80), otherwise note-on (MIDI 0x90).
183 */
184 void sendNote(uint8_t channel, uint8_t note, uint8_t velocity);
185#endif
186
187#if DAF_UI_FILE_BROWSER
188 /**
189 Open a file browser dialog with this window as transient parent.@n
190 A few options can be specified to setup the dialog.@n
191 The @a DAF_NAMESPACE::FileBrowserOptions::className variable is automatically set in this call.
192
193 If a path is selected, onFileSelected() will be called with the user chosen path.
194 If the user cancels or does not pick a file, onFileSelected() will be called with nullptr as filename.
195
196 This function does not block the event loop.
197
198 @note This is exactly the same API as provided by the Window class, but redeclared here for convenience.
199 */
200 bool openFileBrowser(const DAF_NAMESPACE::FileBrowserOptions& options = FileBrowserOptions());
201#endif
202
203#if DAF_PLUGIN_WANT_DIRECT_ACCESS
204 /* --------------------------------------------------------------------------------------------------------
205 * Direct DSP access - DO NOT USE THIS UNLESS STRICTLY NECESSARY!! */
206
207 /**
208 getPluginInstancePointer.
209 @TODO Document this.
210 */
211 void* getPluginInstancePointer() const noexcept;
212#endif
213
214protected:
215 /* --------------------------------------------------------------------------------------------------------
216 * DSP/Plugin Callbacks */
217
218 /**
219 A parameter has changed on the plugin side.@n
220 This is called by the host to inform the UI about parameter changes.
221 */
222 virtual void parameterChanged(uint32_t index, float value);
223
224#if DAF_PLUGIN_WANT_PROGRAMS
225 /**
226 A program has been loaded on the plugin side.@n
227 This is called by the host to inform the UI about program changes.
228 */
229 virtual void programLoaded(uint32_t index);
230#endif
231
232#if DAF_PLUGIN_WANT_STATE
233 /**
234 A state has changed on the plugin side.@n
235 This is called by the host to inform the UI about state changes.
236 */
237 virtual void stateChanged(const char* key, const char* value);
238#endif
239
240 /* --------------------------------------------------------------------------------------------------------
241 * DSP/Plugin Callbacks (optional) */
242
243 /**
244 Optional callback to inform the UI about a sample rate change on the plugin side.
245 @see getSampleRate()
246 */
247 virtual void sampleRateChanged(double newSampleRate);
248
249 /* --------------------------------------------------------------------------------------------------------
250 * UI Callbacks (optional) */
251
252 /**
253 UI idle function, called to give idle time to the plugin UI directly from the host.
254 This is called right after OS event handling and Window idle events (within the same cycle).
255 There are no guarantees in terms of timing.
256 @see addIdleCallback(IdleCallback*, uint).
257 */
258 virtual void uiIdle() {}
259
260 /**
261 Window scale factor function, called when the scale factor changes.
262 This function is for plugin UIs to be able to override Window::onScaleFactorChanged(double).
263
264 The default implementation does nothing.
265 WARNING function needs a proper name
266 */
267 virtual void uiScaleFactorChanged(double scaleFactor);
268
269 /**
270 Get the types available for the data in a clipboard.
271 Must only be called within the context of uiClipboardDataOffer.
272 */
273 std::vector<DGL_NAMESPACE::ClipboardDataOffer> getClipboardDataOfferTypes();
274
275 /**
276 Window clipboard data offer function, called when clipboard has data present, possibly with several datatypes.
277 While handling this event, the data types can be investigated with getClipboardDataOfferTypes() to decide whether to accept the offer.
278
279 Reimplement and return a non-zero id to accept the clipboard data offer for a particular type.
280 UIs must ignore any type they do not recognize.
281
282 The default implementation accepts the "text/plain" mimetype.
283 */
284 virtual uint32_t uiClipboardDataOffer();
285
286 /**
287 Windows focus function, called when the window gains or loses the keyboard focus.
288 This function is for plugin UIs to be able to override Window::onFocus(bool, CrossingMode).
289
290 The default implementation does nothing.
291 */
292 virtual void uiFocus(bool focus, DGL_NAMESPACE::CrossingMode mode);
293
294 /**
295 Window reshape function, called when the window is resized.
296 This function is for plugin UIs to be able to override Window::onReshape(uint, uint).
297
298 Called from the drawing path, with the graphics context current, before the first draw that
299 follows the resize. The plugin UI size has already been set by the time this runs.
300 The default implementation sets up the drawing context where necessary.
301
302 You should almost never need to override this function.
303 The most common exception is custom OpenGL setup, but only really needed for custom OpenGL drawing code.
304 */
305 virtual void uiReshape(uint width, uint height);
306
307#if DAF_UI_FILE_BROWSER
308 /**
309 Window file selected function, called when a path is selected by the user, as triggered by openFileBrowser().
310 This function is for plugin UIs to be able to override Window::onFileSelected(const char*).
311
312 This action happens after the user confirms the action, so the file browser dialog will be closed at this point.
313 The default implementation does nothing.
314
315 If you need to use files as plugin state, please setup and use states with kStateIsFilenamePath instead.
316 */
317 virtual void uiFileBrowserSelected(const char* filename);
318#endif
319
320 /* --------------------------------------------------------------------------------------------------------
321 * UI Resize Handling, internal */
322
323 /**
324 Widget resize function, called when the widget is resized.
325 This is overridden here so the host knows when the UI is resized by you.
326 @see Widget::onResize(const ResizeEvent&)
327 */
328 void onResize(const ResizeEvent& ev) override;
329
330 // -------------------------------------------------------------------------------------------------------
331
332private:
333 struct PrivateData;
334 PrivateData* const uiData;
335 friend class PluginWindow;
336 friend class UIExporter;
337 /** @internal */
338 void requestSizeChange(uint width, uint height) override;
339
340 DAF_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UI)
341};
342
343/** @} */
344
345/* ------------------------------------------------------------------------------------------------------------
346 * Create UI, entry point */
347
348/**
349 @addtogroup EntryPoints
350 @{
351 */
352
353/**
354 createUI.
355 @TODO Document this.
356 */
357extern UI* createUI();
358
359/** @} */
360
361// -----------------------------------------------------------------------------------------------------------
362
364
365#endif // DAF_UI_HPP_INCLUDED
Definition DafUI.hpp:73
const char * getBundlePath() const noexcept
void editParameter(uint32_t index, bool started)
virtual uint32_t uiClipboardDataOffer()
uint getBackgroundColor() const noexcept
bool requestStateFile(const char *key)
uint getForegroundColor() const noexcept
std::vector< DGL_NAMESPACE::ClipboardDataOffer > getClipboardDataOfferTypes()
virtual void programLoaded(uint32_t index)
UI(uint width=0, uint height=0, bool automaticallyScaleAndSetAsMinimumSize=false)
void onResize(const ResizeEvent &ev) override
bool isResizable() const noexcept
void setParameterValue(uint32_t index, float value)
double getSampleRate() const noexcept
virtual void parameterChanged(uint32_t index, float value)
~UI() override
void sendNote(uint8_t channel, uint8_t note, uint8_t velocity)
void * getPluginInstancePointer() const noexcept
virtual void uiReshape(uint width, uint height)
void setState(const char *key, const char *value)
virtual void sampleRateChanged(double newSampleRate)
virtual void uiScaleFactorChanged(double scaleFactor)
virtual void uiFocus(bool focus, DGL_NAMESPACE::CrossingMode mode)
virtual void stateChanged(const char *key, const char *value)
virtual void uiIdle()
Definition DafUI.hpp:258
UI * createUI()
#define END_NAMESPACE_DAF
Definition DafInfo.hpp:996
#define START_NAMESPACE_DAF
Definition DafInfo.hpp:990
#define DAF_UI_CUSTOM_WIDGET_TYPE
Definition DafInfo.hpp:651
FileBrowserOptions()
Definition FileBrowserDialogImpl.hpp:85