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