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.

179 lines
5.2KB

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