DPF

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

SendNoteExampleUI.cpp (5114B)


      1 /*
      2  * DISTRHO Plugin Framework (DPF)
      3  * Copyright (C) 2012-2021 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 #include "Color.hpp"
     20 
     21 #include <cstring>
     22 
     23 START_NAMESPACE_DISTRHO
     24 
     25 /**
     26   We need a few classes from DGL.
     27  */
     28 using DGL_NAMESPACE::Color;
     29 using DGL_NAMESPACE::GraphicsContext;
     30 using DGL_NAMESPACE::Rectangle;
     31 
     32 // -----------------------------------------------------------------------------------------------------------
     33 
     34 class SendNoteExampleUI : public UI
     35 {
     36 public:
     37     SendNoteExampleUI()
     38         : UI(64*12+8, 64+8),
     39           fLastKey(-1)
     40     {
     41         std::memset(fKeyState, 0, sizeof(fKeyState));
     42     }
     43 
     44 protected:
     45    /* --------------------------------------------------------------------------------------------------------
     46     * DSP/Plugin Callbacks */
     47 
     48    /**
     49       A parameter has changed on the plugin side.
     50       This is called by the host to inform the UI about parameter changes.
     51     */
     52     void parameterChanged(uint32_t index, float value) override
     53     {
     54         (void)index;
     55         (void)value;
     56     }
     57 
     58    /* --------------------------------------------------------------------------------------------------------
     59     * Widget Callbacks */
     60 
     61    /**
     62       The OpenGL drawing function.
     63       This UI will draw a row of 12 keys, with on/off states according to pressed status.
     64     */
     65     void onDisplay() override
     66     {
     67         const GraphicsContext& context(getGraphicsContext());
     68 
     69         for (int key = 0; key < 12; ++key)
     70         {
     71             bool pressed = fKeyState[key];
     72             Rectangle<int> bounds = getKeyBounds(key);
     73 
     74             if (pressed)
     75                 Color(0.8f, 0.5f, 0.3f).setFor(context);
     76             else
     77                 Color(0.3f, 0.5f, 0.8f).setFor(context);
     78 
     79             bounds.draw(context);
     80         }
     81     }
     82 
     83    /**
     84       Mouse press event.
     85       This UI will de/activate keys when you click them and reports it as MIDI note events to the plugin.
     86     */
     87     bool onMouse(const MouseEvent& ev) override
     88     {
     89         // Test for last key release first
     90         if (fLastKey != -1 && ! ev.press)
     91         {
     92             // Send a note event. Velocity=0 means off
     93             sendNote(0, kNoteOctaveStart+fLastKey, 0);
     94             // Unset key state
     95             fKeyState[fLastKey] = false;
     96             fLastKey = -1;
     97             repaint();
     98             return true;
     99         }
    100 
    101         // Test for left-clicked first.
    102         if (ev.button != 1)
    103             return false;
    104 
    105         // Find the key which is pressed, if any
    106         int whichKey = -1;
    107         for (int key = 0; key < 12 && whichKey == -1; ++key)
    108         {
    109             Rectangle<int> bounds = getKeyBounds(key);
    110 
    111             if (bounds.contains(ev.pos))
    112                 whichKey = key;
    113         }
    114 
    115         if (whichKey == -1)
    116             return false;
    117         if (fKeyState[whichKey] == ev.press)
    118             return false;
    119 
    120         // Send a note event. Velocity=0 means off
    121         sendNote(0, kNoteOctaveStart+whichKey, ev.press ? kNoteVelocity : 0);
    122 
    123         // Set pressed state of this key, and update display
    124         fLastKey = whichKey;
    125         fKeyState[whichKey] = ev.press;
    126         repaint();
    127 
    128         return true;
    129     }
    130 
    131    /**
    132       Set our UI class as non-copyable and add a leak detector just in case.
    133     */
    134     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SendNoteExampleUI)
    135 
    136 private:
    137     /**
    138        Get the bounds of a particular key of the virtual MIDI keyboard.
    139      */
    140     Rectangle<int> getKeyBounds(unsigned index) const
    141     {
    142         Rectangle<int> bounds;
    143         int padding = 8;
    144         bounds.setX(64 * index + padding);
    145         bounds.setY(padding);
    146         bounds.setWidth(64 - padding);
    147         bounds.setHeight(64 - padding);
    148         return bounds;
    149     }
    150 
    151     /**
    152        The pressed state of one octave of a virtual MIDI keyboard.
    153      */
    154     bool fKeyState[12];
    155     int8_t fLastKey;
    156 
    157     enum
    158     {
    159         kNoteVelocity = 100, // velocity of sent Note-On events
    160         kNoteOctaveStart = 60, // starting note of the virtual MIDI keyboard
    161     };
    162 };
    163 
    164 /* ------------------------------------------------------------------------------------------------------------
    165  * UI entry point, called by DPF to create a new UI instance. */
    166 
    167 UI* createUI()
    168 {
    169     return new SendNoteExampleUI();
    170 }
    171 
    172 // -----------------------------------------------------------------------------------------------------------
    173 
    174 END_NAMESPACE_DISTRHO