99
1010#include " moc_VolumeMeter.cpp"
1111
12- // Size of the audio indicator in pixels
13- #define INDICATOR_THICKNESS 3
14-
1512QPointer<QTimer> VolumeMeter::updateTimer = nullptr ;
1613
14+ namespace {
15+ constexpr int INDICATOR_THICKNESS = 3 ;
16+ constexpr int CLIP_FLASH_DURATION_MS = 1000 ;
17+ constexpr int TICK_SIZE = 2 ;
18+ constexpr int TICK_DB_INTERVAL = 6 ;
19+ } // namespace
20+
1721static inline QColor color_from_int (long long val)
1822{
1923 QColor color (val & 0xff , (val >> 8 ) & 0xff , (val >> 16 ) & 0xff , (val >> 24 ) & 0xff );
@@ -274,17 +278,6 @@ void VolumeMeter::setPeakMeterType(enum obs_peak_meter_type peakMeterType)
274278 updateBackgroundCache ();
275279}
276280
277- void VolumeMeter::mousePressEvent (QMouseEvent *event)
278- {
279- setFocus (Qt::MouseFocusReason);
280- event->accept ();
281- }
282-
283- void VolumeMeter::wheelEvent (QWheelEvent *event)
284- {
285- QApplication::sendEvent (focusProxy (), event);
286- }
287-
288281VolumeMeter::VolumeMeter (QWidget *parent, obs_source_t *source)
289282 : QWidget(parent),
290283 weakSource(OBSGetWeakRef(source)),
@@ -348,7 +341,7 @@ VolumeMeter::VolumeMeter(QWidget *parent, obs_source_t *source)
348341 repaint ();
349342 });
350343
351- connect (App (), &OBSApp::StyleChanged, this , &VolumeMeter::updateBackgroundCache );
344+ connect (App (), &OBSApp::StyleChanged, this , &VolumeMeter::doLayout );
352345}
353346
354347VolumeMeter::~VolumeMeter ()
@@ -419,10 +412,10 @@ bool VolumeMeter::needLayoutChange()
419412
420413 if (displayNrAudioChannels != currentNrAudioChannels) {
421414 displayNrAudioChannels = currentNrAudioChannels;
422- recalculateLayout = true ;
415+ return true ;
423416 }
424417
425- return recalculateLayout ;
418+ return false ;
426419}
427420
428421void VolumeMeter::setVertical (bool vertical_)
@@ -465,6 +458,18 @@ void VolumeMeter::refreshColors()
465458 updateBackgroundCache ();
466459}
467460
461+ QRect VolumeMeter::getBarRect () const
462+ {
463+ QRect barRect = rect ();
464+ if (vertical) {
465+ barRect.setWidth (displayNrAudioChannels * (meterThickness + 1 ) - 1 );
466+ } else {
467+ barRect.setHeight (displayNrAudioChannels * (meterThickness + 1 ) - 1 );
468+ }
469+
470+ return barRect;
471+ }
472+
468473// When this is called from the constructor, obs_volmeter_get_nr_channels has not
469474// yet been called and Q_PROPERTY settings have not yet been read from the
470475// stylesheet.
@@ -476,28 +481,19 @@ inline void VolumeMeter::doLayout()
476481 int meterSize = std::floor (22 / displayNrAudioChannels);
477482 meterThickness = std::clamp (meterSize, 3 , 6 );
478483 }
479- recalculateLayout = false ;
480484
481485 tickFont = font ();
482486 QFontInfo info (tickFont);
483487 tickFont.setPointSizeF (info.pointSizeF () * meterFontScaling);
488+
484489 QFontMetrics metrics (tickFont);
485- if (vertical) {
486- // Each meter channel is meterThickness pixels wide, plus one pixel
487- // between channels, but not after the last.
488- // Add 4 pixels for ticks, space to hold our longest label in this font,
489- // and a few pixels before the fader.
490- QRect scaleBounds = metrics.boundingRect (" -88" );
491- setMinimumSize (displayNrAudioChannels * (meterThickness + 1 ) - 1 + 10 + scaleBounds.width () + 2 , 100 );
492- } else {
493- // Each meter channel is meterThickness pixels high, plus one pixel
494- // between channels, but not after the last.
495- // Add 4 pixels for ticks, and space high enough to hold our label in
496- // this font, presuming that digits don't have descenders.
497- setMinimumSize (100 , displayNrAudioChannels * (meterThickness + 1 ) - 1 + 4 + metrics.capHeight ());
498- }
490+ // This is a quick and naive assumption for widest potential tick label.
491+ tickTextTokenRect = metrics.boundingRect (" -88 " );
499492
493+ updateBackgroundCache ();
500494 resetLevels ();
495+
496+ updateGeometry ();
501497}
502498
503499inline bool VolumeMeter::detectIdle (uint64_t ts)
@@ -607,7 +603,7 @@ void VolumeMeter::paintHTicks(QPainter &painter, int x, int y, int width)
607603 painter.setPen (majorTickColor);
608604
609605 // Draw major tick lines and numeric indicators.
610- for (int i = 0 ; i >= minimumLevel; i -= 6 ) {
606+ for (int i = 0 ; i >= minimumLevel; i -= TICK_DB_INTERVAL ) {
611607 int position = int (x + width - (i * scale) - 1 );
612608 QString str = QString::number (i);
613609
@@ -624,7 +620,7 @@ void VolumeMeter::paintHTicks(QPainter &painter, int x, int y, int width)
624620 }
625621 painter.drawText (pos, y + 4 + metrics.capHeight (), str);
626622
627- painter.drawLine (position, y, position, y + 2 );
623+ painter.drawLine (position, y, position, y + TICK_SIZE );
628624 }
629625}
630626
@@ -637,7 +633,7 @@ void VolumeMeter::paintVTicks(QPainter &painter, int x, int y, int height)
637633 painter.setPen (majorTickColor);
638634
639635 // Draw major tick lines and numeric indicators.
640- for (int i = 0 ; i >= minimumLevel; i -= 6 ) {
636+ for (int i = 0 ; i >= minimumLevel; i -= TICK_DB_INTERVAL ) {
641637 int position = y + int (i * scale);
642638 QString str = QString::number (i);
643639
@@ -648,12 +644,24 @@ void VolumeMeter::paintVTicks(QPainter &painter, int x, int y, int height)
648644 painter.drawText (x + 8 , position + (metrics.capHeight () / 2 ), str);
649645 }
650646
651- painter.drawLine (x, position, x + 2 , position);
647+ painter.drawLine (x, position, x + TICK_SIZE , position);
652648 }
653649}
654650
655651void VolumeMeter::updateBackgroundCache ()
656652{
653+ if (!size ().isValid ()) {
654+ return ;
655+ }
656+
657+ if (backgroundCache.size () == size () && !backgroundCache.isNull ()) {
658+ return ;
659+ }
660+
661+ if (displayNrAudioChannels <= 0 ) {
662+ return ;
663+ }
664+
657665 QColor backgroundColor = palette ().color (QPalette::Window);
658666
659667 backgroundCache = QPixmap (size () * devicePixelRatioF ());
@@ -705,8 +713,6 @@ void VolumeMeter::updateBackgroundCache()
705713 }
706714}
707715
708- #define CLIP_FLASH_DURATION_MS 1000
709-
710716inline int VolumeMeter::convertToInt (float number)
711717{
712718 constexpr int min = std::numeric_limits<int >::min ();
@@ -743,9 +749,6 @@ void VolumeMeter::paintEvent(QPaintEvent *)
743749 const qreal scale = meterLength / minimumLevel;
744750
745751 // Paint cached background pixmap
746- if (backgroundCache.isNull () || backgroundCache.size () != size ()) {
747- updateBackgroundCache ();
748- }
749752 painter.drawPixmap (0 , 0 , backgroundCache);
750753
751754 // Draw dynamic audio meter bars
@@ -849,23 +852,42 @@ void VolumeMeter::paintEvent(QPaintEvent *)
849852 lastRedrawTime = ts;
850853}
851854
852- QRect VolumeMeter::getBarRect () const
855+ void VolumeMeter::resizeEvent (QResizeEvent *event)
853856{
854- QRect rec = rect ();
855- if (vertical) {
856- rec.setWidth (displayNrAudioChannels * (meterThickness + 1 ) - 1 );
857- } else {
858- rec.setHeight (displayNrAudioChannels * (meterThickness + 1 ) - 1 );
859- }
857+ updateBackgroundCache ();
858+ return QWidget::resizeEvent (event);
859+ }
860860
861- return rec;
861+ void VolumeMeter::mousePressEvent (QMouseEvent *event)
862+ {
863+ setFocus (Qt::MouseFocusReason);
864+ event->accept ();
862865}
863866
864- void VolumeMeter::changeEvent (QEvent *e )
867+ void VolumeMeter::wheelEvent (QWheelEvent *event )
865868{
866- if (e->type () == QEvent::StyleChange) {
867- recalculateLayout = true ;
868- }
869+ QApplication::sendEvent (focusProxy (), event);
870+ }
871+
872+ QSize VolumeMeter::minimumSizeHint () const
873+ {
874+ return sizeHint ();
875+ }
869876
870- QWidget::changeEvent (e);
877+ QSize VolumeMeter::sizeHint () const
878+ {
879+ QRect meterRect = getBarRect ();
880+ int labelTotal = std::abs (minimumLevel / TICK_DB_INTERVAL) + 1 ;
881+
882+ if (vertical) {
883+ int width = meterRect.width () + tickTextTokenRect.width () + TICK_SIZE + 10 ;
884+ int height = (labelTotal * tickTextTokenRect.height ()) + INDICATOR_THICKNESS;
885+
886+ return QSize (width, height * 1.1 );
887+ } else {
888+ int width = (labelTotal * tickTextTokenRect.width ()) + INDICATOR_THICKNESS;
889+ int height = meterRect.height () + tickTextTokenRect.height ();
890+
891+ return QSize (width * 1.1 , height);
892+ }
871893}
0 commit comments