DISTRHO Plugin Framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
5.0KB

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