Audio plugin host https://kx.studio/carla
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.

373 lines
10KB

  1. /*
  2. * Digital Peak Meter, a custom Qt widget
  3. * Copyright (C) 2011-2015 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef DIGITALPEAKMETER_HPP_INCLUDED
  18. #define DIGITALPEAKMETER_HPP_INCLUDED
  19. #include "CarlaJuceUtils.hpp"
  20. #include <QtGui/QPainter>
  21. #include <QtGui/QPaintEvent>
  22. #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
  23. # include <QtWidgets/QWidget>
  24. #else
  25. # include <QtGui/QWidget>
  26. #endif
  27. // ------------------------------------------------------------------------------------------------------------
  28. class DigitalPeakMeter : public QWidget
  29. {
  30. public:
  31. enum Color {
  32. COLOR_GREEN = 1,
  33. COLOR_BLUE = 2
  34. };
  35. enum Orientation {
  36. HORIZONTAL = 1,
  37. VERTICAL = 2
  38. };
  39. enum Style {
  40. STYLE_DEFAULT = 1,
  41. STYLE_OPENAV = 2,
  42. STYLE_RNCBC = 3
  43. };
  44. // --------------------------------------------------------------------------------------------------------
  45. DigitalPeakMeter(QWidget* const p)
  46. : QWidget(p),
  47. fChannelCount(0),
  48. fChannelData(nullptr),
  49. fLastChannelData(nullptr),
  50. fMeterColor(COLOR_GREEN),
  51. fMeterColorBase(93, 231, 61),
  52. fMeterColorBaseAlt(15, 110, 15, 100),
  53. fMeterLinesEnabled(true),
  54. fMeterOrientation(VERTICAL),
  55. fMeterStyle(STYLE_DEFAULT),
  56. fMeterBackground("#111111"),
  57. fMeterGradient(0, 0, 0, 0),
  58. fSmoothMultiplier(1)
  59. {
  60. updateGrandient();
  61. }
  62. ~DigitalPeakMeter() override
  63. {
  64. if (fChannelData != nullptr)
  65. {
  66. delete[] fChannelData;
  67. fChannelData = nullptr;
  68. }
  69. if (fLastChannelData != nullptr)
  70. {
  71. delete[] fLastChannelData;
  72. fLastChannelData = nullptr;
  73. }
  74. }
  75. // --------------------------------------------------------------------------------------------------------
  76. int channelCount() const noexcept
  77. {
  78. return fChannelCount;
  79. }
  80. void setChannelCount(const int count)
  81. {
  82. if (fChannelCount == count)
  83. return;
  84. if (count < 0)
  85. return qCritical("DigitalPeakMeter::setChannelCount(%i) - channel count must be a positive integer or zero", count);
  86. fChannelCount = count;
  87. fChannelData = new float[count];
  88. fLastChannelData = new float[count];
  89. for (int i=count; --i >= 0;)
  90. {
  91. /**/fChannelData[i] = 0.0f;
  92. fLastChannelData[i] = 0.0f;
  93. }
  94. }
  95. // --------------------------------------------------------------------------------------------------------
  96. Color meterColor() const noexcept
  97. {
  98. return fMeterColor;
  99. }
  100. void setMeterColor(const Color color)
  101. {
  102. if (fMeterColor == color)
  103. return;
  104. if (! QList<Color>({COLOR_GREEN, COLOR_BLUE}).contains(color))
  105. return qCritical("DigitalPeakMeter::setMeterColor(%i) - invalid color", color);
  106. switch (color)
  107. {
  108. case COLOR_GREEN:
  109. fMeterColorBase = QColor(93, 231, 61);
  110. fMeterColorBaseAlt = QColor(15, 110, 15, 100);
  111. break;
  112. case COLOR_BLUE:
  113. fMeterColorBase = QColor(82, 238, 248);
  114. fMeterColorBaseAlt = QColor(15, 15, 110, 100);
  115. break;
  116. }
  117. fMeterColor = color;
  118. updateGrandient();
  119. }
  120. // --------------------------------------------------------------------------------------------------------
  121. bool meterLinesEnabled() const noexcept
  122. {
  123. return fMeterLinesEnabled;
  124. }
  125. void setMeterLinesEnabled(const bool yesNo)
  126. {
  127. if (fMeterLinesEnabled == yesNo)
  128. return;
  129. fMeterLinesEnabled = yesNo;
  130. }
  131. // --------------------------------------------------------------------------------------------------------
  132. Orientation meterOrientation() const noexcept
  133. {
  134. return fMeterOrientation;
  135. }
  136. void setMeterOrientation(const Orientation orientation)
  137. {
  138. if (fMeterOrientation == orientation)
  139. return;
  140. if (! QList<Orientation>({HORIZONTAL, VERTICAL}).contains(orientation))
  141. return qCritical("DigitalPeakMeter::setMeterOrientation(%i) - invalid orientation", orientation);
  142. fMeterOrientation = orientation;
  143. updateGrandient();
  144. }
  145. // --------------------------------------------------------------------------------------------------------
  146. Style meterStyle() const noexcept
  147. {
  148. return fMeterStyle;
  149. }
  150. void setMeterStyle(const Style style)
  151. {
  152. if (fMeterStyle == style)
  153. return;
  154. if (! QList<Style>({STYLE_DEFAULT, STYLE_OPENAV, STYLE_RNCBC}).contains(style))
  155. return qCritical("DigitalPeakMeter::setMeterStyle(%i) - invalid style", style);
  156. switch (style)
  157. {
  158. case STYLE_DEFAULT:
  159. fMeterBackground = QColor("#111111");
  160. break;
  161. case STYLE_OPENAV:
  162. fMeterBackground = QColor("#1A1A1A");
  163. break;
  164. case STYLE_RNCBC:
  165. fMeterBackground = QColor("#111111");
  166. break;
  167. }
  168. fMeterStyle = style;
  169. updateGrandient();
  170. }
  171. // --------------------------------------------------------------------------------------------------------
  172. int smoothMultiplier() const noexcept
  173. {
  174. return fSmoothMultiplier;
  175. }
  176. void setSmoothMultiplier(const int value)
  177. {
  178. if (fSmoothMultiplier == value)
  179. return;
  180. if (value < 0)
  181. return qCritical("DigitalPeakMeter::setSmoothMultiplier(%i) - value must be >= 0", value);
  182. if (value > 5)
  183. return qCritical("DigitalPeakMeter::setSmoothMultiplier(%i) - value must be < 5", value);
  184. fSmoothMultiplier = value;
  185. }
  186. // --------------------------------------------------------------------------------------------------------
  187. void displayMeter(const int meter, float level, bool forced = false)
  188. {
  189. if (meter <= 0 or meter > fChannelCount)
  190. return qCritical("DigitalPeakMeter::displayMeter(%i, %f) - invalid meter number", meter, level);
  191. const int i = meter - 1;
  192. if (fSmoothMultiplier > 0 && ! forced)
  193. level = (fLastChannelData[i] * float(fSmoothMultiplier) + level) / float(fSmoothMultiplier + 1);
  194. if (level < 0.001f)
  195. level = 0.0f;
  196. else if (level > 0.999f)
  197. level = 1.0f;
  198. if (fChannelData[i] != level)
  199. {
  200. fChannelData[i] = level;
  201. update();
  202. }
  203. fLastChannelData[i] = level;
  204. }
  205. // --------------------------------------------------------------------------------------------------------
  206. protected:
  207. void updateGrandient()
  208. {
  209. fMeterGradient = QLinearGradient(0, 0, 1, 1);
  210. if (fMeterStyle == STYLE_OPENAV)
  211. {
  212. fMeterGradient.setColorAt(0.0, fMeterColorBase);
  213. fMeterGradient.setColorAt(1.0, fMeterColorBase);
  214. }
  215. else
  216. {
  217. switch (fMeterOrientation)
  218. {
  219. case HORIZONTAL:
  220. fMeterGradient.setColorAt(0.0, fMeterColorBase);
  221. fMeterGradient.setColorAt(0.2, fMeterColorBase);
  222. fMeterGradient.setColorAt(0.4, fMeterColorBase);
  223. fMeterGradient.setColorAt(0.6, fMeterColorBase);
  224. fMeterGradient.setColorAt(0.8, Qt::yellow);
  225. fMeterGradient.setColorAt(1.0, Qt::red);
  226. break;
  227. case VERTICAL:
  228. fMeterGradient.setColorAt(0.0, Qt::red);
  229. fMeterGradient.setColorAt(0.2, Qt::yellow);
  230. fMeterGradient.setColorAt(0.4, fMeterColorBase);
  231. fMeterGradient.setColorAt(0.6, fMeterColorBase);
  232. fMeterGradient.setColorAt(0.8, fMeterColorBase);
  233. fMeterGradient.setColorAt(1.0, fMeterColorBase);
  234. break;
  235. }
  236. }
  237. updateGrandientFinalStop();
  238. }
  239. void updateGrandientFinalStop()
  240. {
  241. switch (fMeterOrientation)
  242. {
  243. case HORIZONTAL:
  244. fMeterGradient.setFinalStop(width(), 0);
  245. break;
  246. case VERTICAL:
  247. fMeterGradient.setFinalStop(0, height());
  248. break;
  249. }
  250. }
  251. // --------------------------------------------------------------------------------------------------------
  252. QSize minimumSizeHint() const override
  253. {
  254. return QSize(10, 10);
  255. }
  256. QSize sizeHint() const override
  257. {
  258. return QSize(width(), height());
  259. }
  260. // --------------------------------------------------------------------------------------------------------
  261. void paintEvent(QPaintEvent* const ev) override
  262. {
  263. QPainter painter(this);
  264. ev->accept();
  265. const int width_ = width();
  266. const int height_ = height();
  267. // draw background
  268. painter.setPen(QPen(fMeterBackground, 2));
  269. painter.setBrush(fMeterBackground);
  270. painter.drawRect(0, 0, width_, height_);
  271. }
  272. // --------------------------------------------------------------------------------------------------------
  273. void resizeEvent(QResizeEvent* const ev) override
  274. {
  275. QWidget::resizeEvent(ev);
  276. updateGrandientFinalStop();
  277. }
  278. // --------------------------------------------------------------------------------------------------------
  279. private:
  280. int fChannelCount;
  281. float* fChannelData;
  282. float* fLastChannelData;
  283. Color fMeterColor;
  284. QColor fMeterColorBase;
  285. QColor fMeterColorBaseAlt;
  286. bool fMeterLinesEnabled;
  287. Orientation fMeterOrientation;
  288. Style fMeterStyle;
  289. QColor fMeterBackground;
  290. QLinearGradient fMeterGradient;
  291. int fSmoothMultiplier;
  292. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DigitalPeakMeter)
  293. };
  294. // ------------------------------------------------------------------------------------------------------------
  295. #endif // DIGITALPEAKMETER_HPP_INCLUDED