DPF

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

ExampleUIMeters.cpp (7347B)


      1 /*
      2  * DISTRHO Plugin Framework (DPF)
      3  * Copyright (C) 2012-2019 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 #include "DistrhoUI.hpp"
     18 
     19 START_NAMESPACE_DISTRHO
     20 
     21 /**
     22   We need the Color class from DGL.
     23  */
     24 using DGL_NAMESPACE::Color;
     25 
     26 /**
     27   Smooth meters a bit.
     28  */
     29 static const float kSmoothMultiplier = 3.0f;
     30 
     31 // -----------------------------------------------------------------------------------------------------------
     32 
     33 class ExampleUIMeters : public UI
     34 {
     35 public:
     36     ExampleUIMeters()
     37         : UI(128, 512),
     38           // default color is green
     39           fColor(93, 231, 61),
     40           // which is value 0
     41           fColorValue(0),
     42           // init meter values to 0
     43           fOutLeft(0.0f),
     44           fOutRight(0.0f)
     45     {
     46         setGeometryConstraints(32, 128, false);
     47     }
     48 
     49 protected:
     50    /* --------------------------------------------------------------------------------------------------------
     51     * DSP/Plugin Callbacks */
     52 
     53    /**
     54       A parameter has changed on the plugin side.
     55       This is called by the host to inform the UI about parameter changes.
     56     */
     57     void parameterChanged(uint32_t index, float value) override
     58     {
     59         switch (index)
     60         {
     61         case 0: // color
     62             updateColor(std::round(value));
     63             break;
     64 
     65         case 1: // out-left
     66             value = (fOutLeft * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f);
     67 
     68             /**/ if (value < 0.001f) value = 0.0f;
     69             else if (value > 0.999f) value = 1.0f;
     70 
     71             if (fOutLeft != value)
     72             {
     73                 fOutLeft = value;
     74                 repaint();
     75             }
     76             break;
     77 
     78         case 2: // out-right
     79             value = (fOutRight * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f);
     80 
     81             /**/ if (value < 0.001f) value = 0.0f;
     82             else if (value > 0.999f) value = 1.0f;
     83 
     84             if (fOutRight != value)
     85             {
     86                 fOutRight = value;
     87                 repaint();
     88             }
     89             break;
     90         }
     91     }
     92 
     93    /**
     94       A state has changed on the plugin side.
     95       This is called by the host to inform the UI about state changes.
     96     */
     97     void stateChanged(const char*, const char*) override
     98     {
     99         // nothing here
    100     }
    101 
    102    /* --------------------------------------------------------------------------------------------------------
    103     * Widget Callbacks */
    104 
    105    /**
    106       The NanoVG drawing function.
    107     */
    108     void onNanoDisplay() override
    109     {
    110         static const Color kColorBlack(0, 0, 0);
    111         static const Color kColorRed(255, 0, 0);
    112         static const Color kColorYellow(255, 255, 0);
    113 
    114         // get meter values
    115         const float outLeft(fOutLeft);
    116         const float outRight(fOutRight);
    117 
    118         // tell DSP side to reset meter values
    119         setState("reset", "");
    120 
    121         // useful vars
    122         const float halfWidth        = static_cast<float>(getWidth())/2;
    123         const float redYellowHeight  = static_cast<float>(getHeight())*0.2f;
    124         const float yellowBaseHeight = static_cast<float>(getHeight())*0.4f;
    125         const float baseBaseHeight   = static_cast<float>(getHeight())*0.6f;
    126 
    127         // create gradients
    128         Paint fGradient1 = linearGradient(0.0f, 0.0f,            0.0f, redYellowHeight,  kColorRed,    kColorYellow);
    129         Paint fGradient2 = linearGradient(0.0f, redYellowHeight, 0.0f, yellowBaseHeight, kColorYellow, fColor);
    130 
    131         // paint left meter
    132         beginPath();
    133         rect(0.0f, 0.0f, halfWidth-1.0f, redYellowHeight);
    134         fillPaint(fGradient1);
    135         fill();
    136         closePath();
    137 
    138         beginPath();
    139         rect(0.0f, redYellowHeight-0.5f, halfWidth-1.0f, yellowBaseHeight);
    140         fillPaint(fGradient2);
    141         fill();
    142         closePath();
    143 
    144         beginPath();
    145         rect(0.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-1.0f, baseBaseHeight);
    146         fillColor(fColor);
    147         fill();
    148         closePath();
    149 
    150         // paint left black matching output level
    151         beginPath();
    152         rect(0.0f, 0.0f, halfWidth-1.0f, (1.0f-outLeft)*getHeight());
    153         fillColor(kColorBlack);
    154         fill();
    155         closePath();
    156 
    157         // paint right meter
    158         beginPath();
    159         rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, redYellowHeight);
    160         fillPaint(fGradient1);
    161         fill();
    162         closePath();
    163 
    164         beginPath();
    165         rect(halfWidth+1.0f, redYellowHeight-0.5f, halfWidth-2.0f, yellowBaseHeight);
    166         fillPaint(fGradient2);
    167         fill();
    168         closePath();
    169 
    170         beginPath();
    171         rect(halfWidth+1.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-2.0f, baseBaseHeight);
    172         fillColor(fColor);
    173         fill();
    174         closePath();
    175 
    176         // paint right black matching output level
    177         beginPath();
    178         rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, (1.0f-outRight)*getHeight());
    179         fillColor(kColorBlack);
    180         fill();
    181         closePath();
    182     }
    183 
    184    /**
    185       Mouse press event.
    186       This UI will change color when clicked.
    187     */
    188     bool onMouse(const MouseEvent& ev) override
    189     {
    190         // Test for left-clicked + pressed first.
    191         if (ev.button != 1 || ! ev.press)
    192             return false;
    193 
    194         const int newColor(fColorValue == 0 ? 1 : 0);
    195         updateColor(newColor);
    196         setParameterValue(0, newColor);
    197 
    198         return true;
    199     }
    200 
    201     // -------------------------------------------------------------------------------------------------------
    202 
    203 private:
    204    /**
    205       Color and its matching parameter value.
    206     */
    207     Color fColor;
    208     int   fColorValue;
    209 
    210    /**
    211       Meter values.
    212       These are the parameter outputs from the DSP side.
    213     */
    214     float fOutLeft, fOutRight;
    215 
    216    /**
    217       Update color if needed.
    218     */
    219     void updateColor(const int color)
    220     {
    221         if (fColorValue == color)
    222             return;
    223 
    224         fColorValue = color;
    225 
    226         switch (color)
    227         {
    228         case METER_COLOR_GREEN:
    229             fColor = Color(93, 231, 61);
    230             break;
    231         case METER_COLOR_BLUE:
    232             fColor = Color(82, 238, 248);
    233             break;
    234         }
    235 
    236         repaint();
    237     }
    238 
    239    /**
    240       Set our UI class as non-copyable and add a leak detector just in case.
    241     */
    242     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIMeters)
    243 };
    244 
    245 /* ------------------------------------------------------------------------------------------------------------
    246  * UI entry point, called by DPF to create a new UI instance. */
    247 
    248 UI* createUI()
    249 {
    250     return new ExampleUIMeters();
    251 }
    252 
    253 // -----------------------------------------------------------------------------------------------------------
    254 
    255 END_NAMESPACE_DISTRHO