DPF Plugin examples
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.4KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 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. For simplicity this UI will be of constant size.
  20. */
  21. static const int kUIWidth = 512;
  22. static const int kUIHeight = 512;
  23. /**
  24. We need the rectangle class from DGL.
  25. */
  26. using DGL::Rectangle;
  27. /**
  28. Get key name from an index.
  29. */
  30. static const char* getStateKeyFromIndex(const uint32_t index)
  31. {
  32. switch (index)
  33. {
  34. case 0: return "top-left";
  35. case 1: return "top-center";
  36. case 2: return "top-right";
  37. case 3: return "middle-left";
  38. case 4: return "middle-center";
  39. case 5: return "middle-right";
  40. case 6: return "bottom-left";
  41. case 7: return "bottom-center";
  42. case 8: return "bottom-right";
  43. }
  44. return "unknown";
  45. }
  46. // -----------------------------------------------------------------------------------------------------------
  47. class ExampleUIParameters : public UI
  48. {
  49. public:
  50. ExampleUIParameters()
  51. : UI()
  52. {
  53. /**
  54. Initialize the grid to all off per default.
  55. */
  56. std::memset(fParamGrid, 0, sizeof(bool)*9);
  57. setSize(kUIWidth, kUIHeight);
  58. }
  59. protected:
  60. /* --------------------------------------------------------------------------------------------------------
  61. * DSP/Plugin Callbacks */
  62. /**
  63. This plugin has no parameters, so we can safely ignore this.
  64. */
  65. void d_parameterChanged(uint32_t, float) override {}
  66. /**
  67. A state has changed on the plugin side.
  68. This is called by the host to inform the UI about state changes.
  69. */
  70. void d_stateChanged(const char* key, const char* value)
  71. {
  72. // check which block changed, enable it if its value is "true"
  73. /**/ if (std::strcmp(key, "top-left") == 0)
  74. fParamGrid[0] = (std::strcmp(value, "true") == 0);
  75. else if (std::strcmp(key, "top-center") == 0)
  76. fParamGrid[1] = (std::strcmp(value, "true") == 0);
  77. else if (std::strcmp(key, "top-right") == 0)
  78. fParamGrid[2] = (std::strcmp(value, "true") == 0);
  79. else if (std::strcmp(key, "middle-left") == 0)
  80. fParamGrid[3] = (std::strcmp(value, "true") == 0);
  81. else if (std::strcmp(key, "middle-center") == 0)
  82. fParamGrid[4] = (std::strcmp(value, "true") == 0);
  83. else if (std::strcmp(key, "middle-right") == 0)
  84. fParamGrid[5] = (std::strcmp(value, "true") == 0);
  85. else if (std::strcmp(key, "bottom-left") == 0)
  86. fParamGrid[6] = (std::strcmp(value, "true") == 0);
  87. else if (std::strcmp(key, "bottom-center") == 0)
  88. fParamGrid[7] = (std::strcmp(value, "true") == 0);
  89. else if (std::strcmp(key, "bottom-right") == 0)
  90. fParamGrid[8] = (std::strcmp(value, "true") == 0);
  91. // trigger repaint
  92. repaint();
  93. }
  94. /* --------------------------------------------------------------------------------------------------------
  95. * Widget Callbacks */
  96. /**
  97. The OpenGL drawing function.
  98. This UI will draw a 3x3 grid, with on/off states according to plugin state.
  99. */
  100. void onDisplay() override
  101. {
  102. Rectangle<int> r;
  103. r.setWidth(kUIWidth/3 - 6);
  104. r.setHeight(kUIHeight/3 - 6);
  105. // draw left, center and right columns
  106. for (int i=0; i<3; ++i)
  107. {
  108. r.setX(3 + i*kUIWidth/3);
  109. // top
  110. r.setY(3);
  111. if (fParamGrid[0+i])
  112. glColor3f(0.8f, 0.5f, 0.3f);
  113. else
  114. glColor3f(0.3f, 0.5f, 0.8f);
  115. r.draw();
  116. // middle
  117. r.setY(3 + kUIHeight/3);
  118. if (fParamGrid[3+i])
  119. glColor3f(0.8f, 0.5f, 0.3f);
  120. else
  121. glColor3f(0.3f, 0.5f, 0.8f);
  122. r.draw();
  123. // bottom
  124. r.setY(3 + kUIHeight*2/3);
  125. if (fParamGrid[6+i])
  126. glColor3f(0.8f, 0.5f, 0.3f);
  127. else
  128. glColor3f(0.3f, 0.5f, 0.8f);
  129. r.draw();
  130. }
  131. }
  132. /**
  133. Mouse press event.
  134. This UI will de/activate blocks when you click them and reports it as a state change to the plugin.
  135. */
  136. bool onMouse(const MouseEvent& ev) override
  137. {
  138. // Test for left-clicked + pressed first.
  139. if (ev.button != 1 || ! ev.press)
  140. return false;
  141. Rectangle<int> r;
  142. r.setWidth(kUIWidth/3 - 6);
  143. r.setHeight(kUIHeight/3 - 6);
  144. // handle left, center and right columns
  145. for (int i=0; i<3; ++i)
  146. {
  147. r.setX(3 + i*kUIWidth/3);
  148. // top
  149. r.setY(3);
  150. if (r.contains(ev.pos))
  151. {
  152. // index that this block applies to
  153. const uint32_t index = 0+i;
  154. // invert block state
  155. fParamGrid[index] = !fParamGrid[index];
  156. // report change to host (and thus plugin)
  157. d_setState(getStateKeyFromIndex(index), fParamGrid[index] ? "true" : "false");
  158. // trigger repaint
  159. repaint();
  160. break;
  161. }
  162. // middle
  163. r.setY(3 + kUIHeight/3);
  164. if (r.contains(ev.pos))
  165. {
  166. // same as before
  167. const uint32_t index = 3+i;
  168. fParamGrid[index] = !fParamGrid[index];
  169. d_setState(getStateKeyFromIndex(index), fParamGrid[index] ? "true" : "false");
  170. repaint();
  171. break;
  172. }
  173. // bottom
  174. r.setY(3 + kUIHeight*2/3);
  175. if (r.contains(ev.pos))
  176. {
  177. // same as before
  178. const uint32_t index = 6+i;
  179. fParamGrid[index] = !fParamGrid[index];
  180. d_setState(getStateKeyFromIndex(index), fParamGrid[index] ? "true" : "false");
  181. repaint();
  182. break;
  183. }
  184. }
  185. return true;
  186. }
  187. // -------------------------------------------------------------------------------------------------------
  188. private:
  189. /**
  190. Our states used to display the grid.
  191. The host does not know about these.
  192. */
  193. bool fParamGrid[9];
  194. /**
  195. Set our UI class as non-copyable and add a leak detector just in case.
  196. */
  197. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIParameters)
  198. };
  199. /* ------------------------------------------------------------------------------------------------------------
  200. * UI entry point, called by DPF to create a new UI instance. */
  201. UI* createUI()
  202. {
  203. return new ExampleUIParameters();
  204. }
  205. // -----------------------------------------------------------------------------------------------------------
  206. END_NAMESPACE_DISTRHO