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.

287 lines
8.2KB

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