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.

279 lines
8.4KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 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 "ResizeHandle.hpp"
  18. START_NAMESPACE_DISTRHO
  19. using DGL_NAMESPACE::ResizeHandle;
  20. // -----------------------------------------------------------------------------------------------------------
  21. class InfoExampleUI : public UI
  22. {
  23. static const uint kInitialWidth = 405;
  24. static const uint kInitialHeight = 256;
  25. public:
  26. InfoExampleUI()
  27. : UI(kInitialWidth, kInitialHeight),
  28. fSampleRate(getSampleRate()),
  29. fResizable(isResizable()),
  30. fScale(1.0f),
  31. fResizeHandle(this)
  32. {
  33. std::memset(fParameters, 0, sizeof(float)*kParameterCount);
  34. std::memset(fStrBuf, 0, sizeof(char)*(0xff+1));
  35. #ifdef DGL_NO_SHARED_RESOURCES
  36. createFontFromFile("sans", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf");
  37. #else
  38. loadSharedResources();
  39. #endif
  40. setGeometryConstraints(kInitialWidth, kInitialHeight, true);
  41. // no need to show resize handle if window is user-resizable
  42. if (fResizable)
  43. fResizeHandle.hide();
  44. }
  45. protected:
  46. /* --------------------------------------------------------------------------------------------------------
  47. * DSP/Plugin Callbacks */
  48. /**
  49. A parameter has changed on the plugin side.
  50. This is called by the host to inform the UI about parameter changes.
  51. */
  52. void parameterChanged(uint32_t index, float value) override
  53. {
  54. // some hosts send parameter change events for output parameters even when nothing changed
  55. // we catch that here in order to prevent excessive repaints
  56. if (d_isEqual(fParameters[index], value))
  57. return;
  58. fParameters[index] = value;
  59. repaint();
  60. }
  61. /* --------------------------------------------------------------------------------------------------------
  62. * DSP/Plugin Callbacks (optional) */
  63. /**
  64. Optional callback to inform the UI about a sample rate change on the plugin side.
  65. */
  66. void sampleRateChanged(double newSampleRate) override
  67. {
  68. fSampleRate = newSampleRate;
  69. repaint();
  70. }
  71. /* --------------------------------------------------------------------------------------------------------
  72. * Widget Callbacks */
  73. /**
  74. The NanoVG drawing function.
  75. */
  76. void onNanoDisplay() override
  77. {
  78. const float lineHeight = 20 * fScale;
  79. fontSize(15.0f * fScale);
  80. textLineHeight(lineHeight);
  81. float x = 0.0f * fScale;
  82. float y = 15.0f * fScale;
  83. // buffer size
  84. drawLeft(x, y, "Buffer Size:");
  85. drawRight(x, y, getTextBufInt(fParameters[kParameterBufferSize]));
  86. y+=lineHeight;
  87. // sample rate
  88. drawLeft(x, y, "Sample Rate:");
  89. drawRight(x, y, getTextBufFloat(fSampleRate));
  90. y+=lineHeight;
  91. // separator
  92. y+=lineHeight;
  93. // time stuff
  94. drawLeft(x, y, "Playing:");
  95. drawRight(x, y, (fParameters[kParameterTimePlaying] > 0.5f) ? "Yes" : "No");
  96. y+=lineHeight;
  97. drawLeft(x, y, "Frame:");
  98. drawRight(x, y, getTextBufInt(fParameters[kParameterTimeFrame]));
  99. y+=lineHeight;
  100. drawLeft(x, y, "Time:");
  101. drawRight(x, y, getTextBufTime(fParameters[kParameterTimeFrame]));
  102. y+=lineHeight;
  103. // separator
  104. y+=lineHeight;
  105. // param changes
  106. drawLeft(x, y, "Param Changes:", 20);
  107. drawRight(x, y, (fParameters[kParameterCanRequestParameterValueChanges] > 0.5f) ? "Yes" : "No", 40);
  108. y+=lineHeight;
  109. // resizable
  110. drawLeft(x, y, "Host resizable:", 20);
  111. drawRight(x, y, fResizable ? "Yes" : "No", 40);
  112. y+=lineHeight;
  113. // BBT
  114. x = 200.0f * fScale;
  115. y = 15.0f * fScale;
  116. const bool validBBT(fParameters[kParameterTimeValidBBT] > 0.5f);
  117. drawLeft(x, y, "BBT Valid:");
  118. drawRight(x, y, validBBT ? "Yes" : "No");
  119. y+=lineHeight;
  120. if (! validBBT)
  121. return;
  122. drawLeft(x, y, "Bar:");
  123. drawRight(x, y, getTextBufInt(fParameters[kParameterTimeBar]));
  124. y+=lineHeight;
  125. drawLeft(x, y, "Beat:");
  126. drawRight(x, y, getTextBufInt(fParameters[kParameterTimeBeat]));
  127. y+=lineHeight;
  128. drawLeft(x, y, "Tick:");
  129. drawRight(x, y, getTextBufFloatExtra(fParameters[kParameterTimeTick]));
  130. y+=lineHeight;
  131. drawLeft(x, y, "Bar Start Tick:");
  132. drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBarStartTick]));
  133. y+=lineHeight;
  134. drawLeft(x, y, "Beats Per Bar:");
  135. drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatsPerBar]));
  136. y+=lineHeight;
  137. drawLeft(x, y, "Beat Type:");
  138. drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatType]));
  139. y+=lineHeight;
  140. drawLeft(x, y, "Ticks Per Beat:");
  141. drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeTicksPerBeat]));
  142. y+=lineHeight;
  143. drawLeft(x, y, "BPM:");
  144. drawRight(x, y, getTextBufFloat(fParameters[kParameterTimeBeatsPerMinute]));
  145. y+=lineHeight;
  146. }
  147. void onResize(const ResizeEvent& ev) override
  148. {
  149. fScale = static_cast<float>(ev.size.getHeight())/static_cast<float>(kInitialHeight);
  150. UI::onResize(ev);
  151. }
  152. // -------------------------------------------------------------------------------------------------------
  153. private:
  154. // Parameters
  155. float fParameters[kParameterCount];
  156. double fSampleRate;
  157. // UI stuff
  158. bool fResizable;
  159. float fScale;
  160. ResizeHandle fResizeHandle;
  161. // temp buf for text
  162. char fStrBuf[0xff+1];
  163. // helpers for putting text into fStrBuf and returning it
  164. const char* getTextBufInt(const int value)
  165. {
  166. std::snprintf(fStrBuf, 0xff, "%i", value);
  167. return fStrBuf;
  168. }
  169. const char* getTextBufFloat(const float value)
  170. {
  171. std::snprintf(fStrBuf, 0xff, "%.1f", value);
  172. return fStrBuf;
  173. }
  174. const char* getTextBufFloatExtra(const float value)
  175. {
  176. std::snprintf(fStrBuf, 0xff, "%.2f", value + 0.001f);
  177. return fStrBuf;
  178. }
  179. const char* getTextBufTime(const uint64_t frame)
  180. {
  181. const uint32_t time = frame / uint64_t(fSampleRate);
  182. const uint32_t secs = time % 60;
  183. const uint32_t mins = (time / 60) % 60;
  184. const uint32_t hrs = (time / 3600) % 60;
  185. std::snprintf(fStrBuf, 0xff, "%02i:%02i:%02i", hrs, mins, secs);
  186. return fStrBuf;
  187. }
  188. // helpers for drawing text
  189. void drawLeft(float x, const float y, const char* const text, const int offset = 0)
  190. {
  191. const float width = (100.0f + offset) * fScale;
  192. x += offset * fScale;
  193. beginPath();
  194. fillColor(200, 200, 200);
  195. textAlign(ALIGN_RIGHT|ALIGN_TOP);
  196. textBox(x, y, width, text);
  197. closePath();
  198. }
  199. void drawRight(float x, const float y, const char* const text, const int offset = 0)
  200. {
  201. const float width = (100.0f + offset) * fScale;
  202. x += offset * fScale;
  203. beginPath();
  204. fillColor(255, 255, 255);
  205. textAlign(ALIGN_LEFT|ALIGN_TOP);
  206. textBox(x + (105 * fScale), y, width, text);
  207. closePath();
  208. }
  209. /**
  210. Set our UI class as non-copyable and add a leak detector just in case.
  211. */
  212. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(InfoExampleUI)
  213. };
  214. /* ------------------------------------------------------------------------------------------------------------
  215. * UI entry point, called by DPF to create a new UI instance. */
  216. UI* createUI()
  217. {
  218. return new InfoExampleUI();
  219. }
  220. // -----------------------------------------------------------------------------------------------------------
  221. END_NAMESPACE_DISTRHO