diff --git a/UI/volume-control.cpp b/UI/volume-control.cpp index f930c7da8..e098c0f9c 100644 --- a/UI/volume-control.cpp +++ b/UI/volume-control.cpp @@ -17,6 +17,8 @@ using namespace std; +QWeakPointer VolumeMeter::updateTimer; + void VolControl::OBSVolumeChanged(void *data, float db) { Q_UNUSED(db); @@ -30,11 +32,10 @@ void VolControl::OBSVolumeLevel(void *data, float level, float mag, { VolControl *volControl = static_cast(data); - QMetaObject::invokeMethod(volControl, "VolumeLevel", - Q_ARG(float, mag), - Q_ARG(float, level), - Q_ARG(float, peak), - Q_ARG(bool, muted)); + if (muted) + level = mag = peak = 0.0f; + + volControl->volMeter->setLevels(mag, level, peak); } void VolControl::OBSVolumeMuted(void *data, calldata_t *calldata) @@ -256,30 +257,51 @@ VolumeMeter::VolumeMeter(QWidget *parent) peakColor.setRgb(0x3E, 0xF1, 0x2B); peakHoldColor.setRgb(0x00, 0x00, 0x00); - resetTimer = new QTimer(this); - connect(resetTimer, SIGNAL(timeout()), this, SLOT(resetState())); + updateTimerRef = updateTimer.toStrongRef(); + if (!updateTimerRef) { + updateTimerRef = QSharedPointer::create(); + updateTimerRef->start(100); + updateTimer = updateTimerRef; + } - resetState(); + updateTimerRef->AddVolControl(this); } -void VolumeMeter::resetState(void) +VolumeMeter::~VolumeMeter() { - setLevels(0.0f, 0.0f, 0.0f); - if (resetTimer->isActive()) - resetTimer->stop(); + updateTimerRef->RemoveVolControl(this); } void VolumeMeter::setLevels(float nmag, float npeak, float npeakHold) { - mag = nmag; - peak = npeak; - peakHold = npeakHold; + uint64_t ts = os_gettime_ns(); + QMutexLocker locker(&dataMutex); - update(); + mag += nmag; + peak += npeak; + peakHold += npeakHold; + multiple += 1.0f; + lastUpdateTime = ts; +} - if (resetTimer->isActive()) - resetTimer->stop(); - resetTimer->start(1000); +inline void VolumeMeter::calcLevels() +{ + uint64_t ts = os_gettime_ns(); + QMutexLocker locker(&dataMutex); + + if (lastUpdateTime && ts - lastUpdateTime > 1000000000) { + mag = peak = peakHold = 0.0f; + multiple = 1.0f; + lastUpdateTime = 0; + } + + if (multiple > 0.0f) { + curMag = mag / multiple; + curPeak = peak / multiple; + curPeakHold = peakHold / multiple; + + mag = peak = peakHold = multiple = 0.0f; + } } void VolumeMeter::paintEvent(QPaintEvent *event) @@ -292,9 +314,11 @@ void VolumeMeter::paintEvent(QPaintEvent *event) int width = size().width(); int height = size().height(); - int scaledMag = int((float)width * mag); - int scaledPeak = int((float)width * peak); - int scaledPeakHold = int((float)width * peakHold); + calcLevels(); + + int scaledMag = int((float)width * curMag); + int scaledPeak = int((float)width * curPeak); + int scaledPeakHold = int((float)width * curPeakHold); gradient.setStart(qreal(scaledMag), 0); gradient.setFinalStop(qreal(scaledPeak), 0); @@ -325,3 +349,19 @@ void VolumeMeter::paintEvent(QPaintEvent *event) scaledPeakHold, height); } + +void VolumeMeterTimer::AddVolControl(VolumeMeter *meter) +{ + volumeMeters.push_back(meter); +} + +void VolumeMeterTimer::RemoveVolControl(VolumeMeter *meter) +{ + volumeMeters.removeOne(meter); +} + +void VolumeMeterTimer::timerEvent(QTimerEvent*) +{ + for (VolumeMeter *meter : volumeMeters) + meter->update(); +} diff --git a/UI/volume-control.hpp b/UI/volume-control.hpp index 27b52b207..9330af72a 100644 --- a/UI/volume-control.hpp +++ b/UI/volume-control.hpp @@ -2,8 +2,13 @@ #include #include +#include +#include +#include +#include class QPushButton; +class VolumeMeterTimer; class VolumeMeter : public QWidget { @@ -14,12 +19,23 @@ class VolumeMeter : public QWidget Q_PROPERTY(QColor peakHoldColor READ getPeakHoldColor WRITE setPeakHoldColor DESIGNABLE true) private: - float mag, peak, peakHold; + static QWeakPointer updateTimer; + QSharedPointer updateTimerRef; + float curMag = 0.0f, curPeak = 0.0f, curPeakHold = 0.0f; + + inline void calcLevels(); + + QMutex dataMutex; + float mag = 0.0f, peak = 0.0f, peakHold = 0.0f; + float multiple = 0.0f; + uint64_t lastUpdateTime = 0; + QColor bkColor, magColor, peakColor, peakHoldColor; - QTimer *resetTimer; public: explicit VolumeMeter(QWidget *parent = 0); + ~VolumeMeter(); + void setLevels(float nmag, float npeak, float npeakHold); QColor getBkColor() const; void setBkColor(QColor c); @@ -32,8 +48,20 @@ public: protected: void paintEvent(QPaintEvent *event); -private slots: - void resetState(); +}; + +class VolumeMeterTimer : public QTimer { + Q_OBJECT + +public: + inline VolumeMeterTimer() : QTimer() {} + + void AddVolControl(VolumeMeter *meter); + void RemoveVolControl(VolumeMeter *meter); + +protected: + virtual void timerEvent(QTimerEvent *event) override; + QList volumeMeters; }; class QLabel;