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.

290 lines
8.8KB

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