volume-control.hpp 12 KB

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