volume-control.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #pragma once
  2. #include <obs.hpp>
  3. #include <QWidget>
  4. #include <QPaintEvent>
  5. #include <QSharedPointer>
  6. #include <QTimer>
  7. #include <QMutex>
  8. #include <QList>
  9. #include <QMenu>
  10. class QPushButton;
  11. class VolumeMeterTimer;
  12. class VolumeMeter : public QWidget {
  13. Q_OBJECT
  14. Q_PROPERTY(QColor backgroundNominalColor READ getBackgroundNominalColor
  15. WRITE setBackgroundNominalColor DESIGNABLE true)
  16. Q_PROPERTY(QColor backgroundWarningColor READ getBackgroundWarningColor
  17. WRITE setBackgroundWarningColor DESIGNABLE true)
  18. Q_PROPERTY(QColor backgroundErrorColor READ getBackgroundErrorColor
  19. WRITE setBackgroundErrorColor DESIGNABLE true)
  20. Q_PROPERTY(QColor foregroundNominalColor READ getForegroundNominalColor
  21. WRITE setForegroundNominalColor DESIGNABLE true)
  22. Q_PROPERTY(QColor foregroundWarningColor READ getForegroundWarningColor
  23. WRITE setForegroundWarningColor DESIGNABLE true)
  24. Q_PROPERTY(QColor foregroundErrorColor READ getForegroundErrorColor
  25. WRITE setForegroundErrorColor DESIGNABLE true)
  26. Q_PROPERTY(QColor backgroundNominalColorDisabled READ
  27. getBackgroundNominalColorDisabled WRITE
  28. setBackgroundNominalColorDisabled
  29. DESIGNABLE true)
  30. Q_PROPERTY(QColor backgroundWarningColorDisabled READ
  31. getBackgroundWarningColorDisabled WRITE
  32. setBackgroundWarningColorDisabled
  33. DESIGNABLE true)
  34. Q_PROPERTY(
  35. QColor backgroundErrorColorDisabled READ
  36. getBackgroundErrorColorDisabled WRITE
  37. setBackgroundErrorColorDisabled DESIGNABLE true)
  38. Q_PROPERTY(QColor foregroundNominalColorDisabled READ
  39. getForegroundNominalColorDisabled WRITE
  40. setForegroundNominalColorDisabled
  41. DESIGNABLE true)
  42. Q_PROPERTY(QColor foregroundWarningColorDisabled READ
  43. getForegroundWarningColorDisabled WRITE
  44. setForegroundWarningColorDisabled
  45. DESIGNABLE true)
  46. Q_PROPERTY(
  47. QColor foregroundErrorColorDisabled READ
  48. getForegroundErrorColorDisabled WRITE
  49. setForegroundErrorColorDisabled DESIGNABLE true)
  50. Q_PROPERTY(QColor clipColor READ getClipColor WRITE setClipColor
  51. DESIGNABLE true)
  52. Q_PROPERTY(QColor magnitudeColor READ getMagnitudeColor WRITE
  53. setMagnitudeColor DESIGNABLE true)
  54. Q_PROPERTY(QColor majorTickColor READ getMajorTickColor WRITE
  55. setMajorTickColor DESIGNABLE true)
  56. Q_PROPERTY(QColor minorTickColor READ getMinorTickColor WRITE
  57. setMinorTickColor DESIGNABLE true)
  58. // Levels are denoted in dBFS.
  59. Q_PROPERTY(qreal minimumLevel READ getMinimumLevel WRITE setMinimumLevel
  60. DESIGNABLE true)
  61. Q_PROPERTY(qreal warningLevel READ getWarningLevel WRITE setWarningLevel
  62. DESIGNABLE true)
  63. Q_PROPERTY(qreal errorLevel READ getErrorLevel WRITE setErrorLevel
  64. DESIGNABLE true)
  65. Q_PROPERTY(qreal clipLevel READ getClipLevel WRITE setClipLevel
  66. DESIGNABLE true)
  67. Q_PROPERTY(qreal minimumInputLevel READ getMinimumInputLevel WRITE
  68. setMinimumInputLevel DESIGNABLE true)
  69. // Rates are denoted in dB/second.
  70. Q_PROPERTY(qreal peakDecayRate READ getPeakDecayRate WRITE
  71. setPeakDecayRate DESIGNABLE true)
  72. // Time in seconds for the VU meter to integrate over.
  73. Q_PROPERTY(
  74. qreal magnitudeIntegrationTime READ getMagnitudeIntegrationTime
  75. WRITE setMagnitudeIntegrationTime DESIGNABLE true)
  76. // Duration is denoted in seconds.
  77. Q_PROPERTY(qreal peakHoldDuration READ getPeakHoldDuration WRITE
  78. setPeakHoldDuration DESIGNABLE true)
  79. Q_PROPERTY(qreal inputPeakHoldDuration READ getInputPeakHoldDuration
  80. WRITE setInputPeakHoldDuration DESIGNABLE true)
  81. friend class VolControl;
  82. private slots:
  83. void ClipEnding();
  84. private:
  85. obs_volmeter_t *obs_volmeter;
  86. static QWeakPointer<VolumeMeterTimer> updateTimer;
  87. QSharedPointer<VolumeMeterTimer> updateTimerRef;
  88. inline void resetLevels();
  89. inline void handleChannelCofigurationChange();
  90. inline bool detectIdle(uint64_t ts);
  91. inline void calculateBallistics(uint64_t ts,
  92. qreal timeSinceLastRedraw = 0.0);
  93. inline void calculateBallisticsForChannel(int channelNr, uint64_t ts,
  94. qreal timeSinceLastRedraw);
  95. void paintInputMeter(QPainter &painter, int x, int y, int width,
  96. int height, float peakHold);
  97. void paintHMeter(QPainter &painter, int x, int y, int width, int height,
  98. float magnitude, float peak, float peakHold);
  99. void paintHTicks(QPainter &painter, int x, int y, int width,
  100. int height);
  101. void paintVMeter(QPainter &painter, int x, int y, int width, int height,
  102. float magnitude, float peak, float peakHold);
  103. void paintVTicks(QPainter &painter, int x, int y, int height);
  104. QMutex dataMutex;
  105. uint64_t currentLastUpdateTime = 0;
  106. float currentMagnitude[MAX_AUDIO_CHANNELS];
  107. float currentPeak[MAX_AUDIO_CHANNELS];
  108. float currentInputPeak[MAX_AUDIO_CHANNELS];
  109. QPixmap *tickPaintCache = nullptr;
  110. int displayNrAudioChannels = 0;
  111. float displayMagnitude[MAX_AUDIO_CHANNELS];
  112. float displayPeak[MAX_AUDIO_CHANNELS];
  113. float displayPeakHold[MAX_AUDIO_CHANNELS];
  114. uint64_t displayPeakHoldLastUpdateTime[MAX_AUDIO_CHANNELS];
  115. float displayInputPeakHold[MAX_AUDIO_CHANNELS];
  116. uint64_t displayInputPeakHoldLastUpdateTime[MAX_AUDIO_CHANNELS];
  117. QFont tickFont;
  118. QColor backgroundNominalColor;
  119. QColor backgroundWarningColor;
  120. QColor backgroundErrorColor;
  121. QColor foregroundNominalColor;
  122. QColor foregroundWarningColor;
  123. QColor foregroundErrorColor;
  124. QColor backgroundNominalColorDisabled;
  125. QColor backgroundWarningColorDisabled;
  126. QColor backgroundErrorColorDisabled;
  127. QColor foregroundNominalColorDisabled;
  128. QColor foregroundWarningColorDisabled;
  129. QColor foregroundErrorColorDisabled;
  130. QColor clipColor;
  131. QColor magnitudeColor;
  132. QColor majorTickColor;
  133. QColor minorTickColor;
  134. qreal minimumLevel;
  135. qreal warningLevel;
  136. qreal errorLevel;
  137. qreal clipLevel;
  138. qreal minimumInputLevel;
  139. qreal peakDecayRate;
  140. qreal magnitudeIntegrationTime;
  141. qreal peakHoldDuration;
  142. qreal inputPeakHoldDuration;
  143. uint64_t lastRedrawTime = 0;
  144. int channels = 0;
  145. bool clipping = false;
  146. bool vertical;
  147. bool muted = false;
  148. public:
  149. explicit VolumeMeter(QWidget *parent = nullptr,
  150. obs_volmeter_t *obs_volmeter = nullptr,
  151. bool vertical = false);
  152. ~VolumeMeter();
  153. void setLevels(const float magnitude[MAX_AUDIO_CHANNELS],
  154. const float peak[MAX_AUDIO_CHANNELS],
  155. const float inputPeak[MAX_AUDIO_CHANNELS]);
  156. QColor getBackgroundNominalColor() const;
  157. void setBackgroundNominalColor(QColor c);
  158. QColor getBackgroundWarningColor() const;
  159. void setBackgroundWarningColor(QColor c);
  160. QColor getBackgroundErrorColor() const;
  161. void setBackgroundErrorColor(QColor c);
  162. QColor getForegroundNominalColor() const;
  163. void setForegroundNominalColor(QColor c);
  164. QColor getForegroundWarningColor() const;
  165. void setForegroundWarningColor(QColor c);
  166. QColor getForegroundErrorColor() const;
  167. void setForegroundErrorColor(QColor c);
  168. QColor getBackgroundNominalColorDisabled() const;
  169. void setBackgroundNominalColorDisabled(QColor c);
  170. QColor getBackgroundWarningColorDisabled() const;
  171. void setBackgroundWarningColorDisabled(QColor c);
  172. QColor getBackgroundErrorColorDisabled() const;
  173. void setBackgroundErrorColorDisabled(QColor c);
  174. QColor getForegroundNominalColorDisabled() const;
  175. void setForegroundNominalColorDisabled(QColor c);
  176. QColor getForegroundWarningColorDisabled() const;
  177. void setForegroundWarningColorDisabled(QColor c);
  178. QColor getForegroundErrorColorDisabled() const;
  179. void setForegroundErrorColorDisabled(QColor c);
  180. QColor getClipColor() const;
  181. void setClipColor(QColor c);
  182. QColor getMagnitudeColor() const;
  183. void setMagnitudeColor(QColor c);
  184. QColor getMajorTickColor() const;
  185. void setMajorTickColor(QColor c);
  186. QColor getMinorTickColor() const;
  187. void setMinorTickColor(QColor c);
  188. qreal getMinimumLevel() const;
  189. void setMinimumLevel(qreal v);
  190. qreal getWarningLevel() const;
  191. void setWarningLevel(qreal v);
  192. qreal getErrorLevel() const;
  193. void setErrorLevel(qreal v);
  194. qreal getClipLevel() const;
  195. void setClipLevel(qreal v);
  196. qreal getMinimumInputLevel() const;
  197. void setMinimumInputLevel(qreal v);
  198. qreal getPeakDecayRate() const;
  199. void setPeakDecayRate(qreal v);
  200. qreal getMagnitudeIntegrationTime() const;
  201. void setMagnitudeIntegrationTime(qreal v);
  202. qreal getPeakHoldDuration() const;
  203. void setPeakHoldDuration(qreal v);
  204. qreal getInputPeakHoldDuration() const;
  205. void setInputPeakHoldDuration(qreal v);
  206. void setPeakMeterType(enum obs_peak_meter_type peakMeterType);
  207. virtual void mousePressEvent(QMouseEvent *event) override;
  208. virtual void wheelEvent(QWheelEvent *event) override;
  209. protected:
  210. void paintEvent(QPaintEvent *event) override;
  211. };
  212. class VolumeMeterTimer : public QTimer {
  213. Q_OBJECT
  214. public:
  215. inline VolumeMeterTimer() : QTimer() {}
  216. void AddVolControl(VolumeMeter *meter);
  217. void RemoveVolControl(VolumeMeter *meter);
  218. protected:
  219. void timerEvent(QTimerEvent *event) override;
  220. QList<VolumeMeter *> volumeMeters;
  221. };
  222. class QLabel;
  223. class QSlider;
  224. class MuteCheckBox;
  225. class VolControl : public QWidget {
  226. Q_OBJECT
  227. private:
  228. OBSSource source;
  229. QLabel *nameLabel;
  230. QLabel *volLabel;
  231. VolumeMeter *volMeter;
  232. QSlider *slider;
  233. MuteCheckBox *mute;
  234. QPushButton *config = nullptr;
  235. float levelTotal;
  236. float levelCount;
  237. obs_fader_t *obs_fader;
  238. obs_volmeter_t *obs_volmeter;
  239. bool vertical;
  240. QMenu *contextMenu;
  241. static void OBSVolumeChanged(void *param, float db);
  242. static void OBSVolumeLevel(void *data,
  243. const float magnitude[MAX_AUDIO_CHANNELS],
  244. const float peak[MAX_AUDIO_CHANNELS],
  245. const float inputPeak[MAX_AUDIO_CHANNELS]);
  246. static void OBSVolumeMuted(void *data, calldata_t *calldata);
  247. void EmitConfigClicked();
  248. private slots:
  249. void VolumeChanged();
  250. void VolumeMuted(bool muted);
  251. void SetMuted(bool checked);
  252. void SliderChanged(int vol);
  253. void updateText();
  254. signals:
  255. void ConfigClicked();
  256. public:
  257. explicit VolControl(OBSSource source, bool showConfig = false,
  258. bool vertical = false);
  259. ~VolControl();
  260. inline obs_source_t *GetSource() const { return source; }
  261. QString GetName() const;
  262. void SetName(const QString &newName);
  263. void SetMeterDecayRate(qreal q);
  264. void setPeakMeterType(enum obs_peak_meter_type peakMeterType);
  265. void EnableSlider(bool enable);
  266. inline void SetContextMenu(QMenu *cm) { contextMenu = cm; }
  267. };