volume-control.hpp 11 KB

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