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.

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