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.

255 lines
7.1KB

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