DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

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