Rebase volume control widgets to new OBS version

This commit is contained in:
WarmUpTill
2022-10-03 18:26:48 +02:00
committed by WarmUpTill
parent c9b5bbfc14
commit 66ddf3b4ef
2 changed files with 477 additions and 135 deletions

View File

@@ -5,23 +5,24 @@
#include <QPushButton>
#include <QLabel>
#include <QPainter>
#include <QStyle>
#include <QStyleFactory>
#include <QSlider>
#include <util/platform.h>
using namespace std;
#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
#define FADER_PRECISION 4096.0
#define FADER_PRECISION 100
// Size of the audio indicator in pixels
#define INDICATOR_THICKNESS 3
// Padding on top and bottom of vertical meters
#define METER_PADDING 1
QWeakPointer<VolumeMeterTimer> VolumeMeter::updateTimer;
void VolControl::OBSVolumeChanged(void *data, float db)
{
Q_UNUSED(db);
Q_UNUSED(data);
}
void VolControl::OBSVolumeChanged(void *, float) {}
void VolControl::OBSVolumeLevel(void *data,
const float magnitude[MAX_AUDIO_CHANNELS],
@@ -33,9 +34,19 @@ void VolControl::OBSVolumeLevel(void *data,
volControl->volMeter->setLevels(magnitude, peak, inputPeak);
}
void VolControl::SliderChanged(int vol)
void VolControl::VolumeChanged()
{
Q_UNUSED(vol);
slider->blockSignals(true);
slider->setValue(
(int)(obs_fader_get_deflection(obs_fader) * FADER_PRECISION));
slider->blockSignals(false);
updateText();
}
void VolControl::SliderChanged(int)
{
float prev = obs_source_get_volume(source);
updateText();
}
@@ -61,6 +72,12 @@ void VolControl::SetName(const QString &newName)
{
nameLabel->setText(newName);
}
void VolControl::EmitConfigClicked()
{
emit ConfigClicked();
}
void VolControl::SetMeterDecayRate(qreal q)
{
volMeter->setPeakDecayRate(q);
@@ -71,23 +88,46 @@ void VolControl::setPeakMeterType(enum obs_peak_meter_type peakMeterType)
volMeter->setPeakMeterType(peakMeterType);
}
VolControl::VolControl(OBSSource source_, bool vertical)
VolumeSlider::VolumeSlider(obs_fader_t *fader, QWidget *parent)
: QSlider(parent)
{
fad = fader;
}
VolumeSlider::VolumeSlider(obs_fader_t *fader, Qt::Orientation orientation,
QWidget *parent)
: QSlider(orientation, parent)
{
fad = fader;
}
VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
: source(std::move(source_)),
levelTotal(0.0f),
levelCount(0.0f),
obs_fader(obs_fader_create(OBS_FADER_LOG)),
obs_volmeter(obs_volmeter_create(OBS_FADER_LOG)),
vertical(vertical)
vertical(vertical),
contextMenu(nullptr)
{
nameLabel = new QLabel();
volLabel = new QLabel();
QString sourceName = "";
if (source) {
obs_source_get_name(source);
}
QString sourceName = obs_source_get_name(source);
setObjectName(sourceName);
if (showConfig) {
config = new QPushButton(this);
config->setProperty("themeID", "menuIconSmall");
config->setSizePolicy(QSizePolicy::Maximum,
QSizePolicy::Maximum);
config->setMaximumSize(22, 22);
config->setAutoDefault(false);
connect(config, &QAbstractButton::clicked, this,
&VolControl::EmitConfigClicked);
}
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(4, 4, 4, 4);
mainLayout->setSpacing(2);
@@ -99,7 +139,7 @@ VolControl::VolControl(OBSSource source_, bool vertical)
QHBoxLayout *meterLayout = new QHBoxLayout;
volMeter = new VolumeMeter(nullptr, obs_volmeter, true);
slider = new QSlider(Qt::Vertical);
slider = new VolumeSlider(obs_fader, Qt::Vertical);
nameLayout->setAlignment(Qt::AlignCenter);
meterLayout->setAlignment(Qt::AlignCenter);
@@ -113,7 +153,11 @@ VolControl::VolControl(OBSSource source_, bool vertical)
controlLayout->setContentsMargins(0, 0, 0, 0);
controlLayout->setSpacing(0);
if (showConfig)
controlLayout->addWidget(config);
controlLayout->addItem(new QSpacerItem(3, 0));
// Add Headphone (audio monitoring) widget here
meterLayout->setContentsMargins(0, 0, 0, 0);
meterLayout->setSpacing(0);
@@ -131,6 +175,12 @@ VolControl::VolControl(OBSSource source_, bool vertical)
volMeter->setFocusProxy(slider);
// Default size can cause clipping of long names in vertical layout.
QFont font = nameLabel->font();
QFontInfo info(font);
font.setPointSizeF(0.8 * info.pointSizeF());
nameLabel->setFont(font);
setMaximumWidth(110);
} else {
QHBoxLayout *volLayout = new QHBoxLayout;
@@ -138,7 +188,7 @@ VolControl::VolControl(OBSSource source_, bool vertical)
QHBoxLayout *botLayout = new QHBoxLayout;
volMeter = new VolumeMeter(nullptr, obs_volmeter, false);
slider = new QSlider(Qt::Horizontal);
slider = new VolumeSlider(obs_fader, Qt::Horizontal);
textLayout->setContentsMargins(0, 0, 0, 0);
textLayout->addWidget(nameLabel);
@@ -153,6 +203,9 @@ VolControl::VolControl(OBSSource source_, bool vertical)
botLayout->setSpacing(0);
botLayout->addLayout(volLayout);
if (showConfig)
botLayout->addWidget(config);
mainLayout->addItem(textLayout);
mainLayout->addWidget(volMeter);
mainLayout->addItem(botLayout);
@@ -162,15 +215,10 @@ VolControl::VolControl(OBSSource source_, bool vertical)
setLayout(mainLayout);
QFont font = nameLabel->font();
font.setPointSize(font.pointSize() - 1);
nameLabel->setText(sourceName);
nameLabel->setFont(font);
volLabel->setFont(font);
slider->setMinimum(0);
slider->setMaximum(100);
slider->setMaximum(int(FADER_PRECISION));
obs_fader_add_callback(obs_fader, OBSVolumeChanged, this);
obs_volmeter_add_callback(obs_volmeter, OBSVolumeLevel, this);
@@ -180,6 +228,9 @@ VolControl::VolControl(OBSSource source_, bool vertical)
obs_fader_attach_source(obs_fader, source);
obs_volmeter_attach_source(obs_volmeter, source);
/* Call volume changed once to init the slider position and label */
VolumeChanged();
}
void VolControl::EnableSlider(bool enable)
@@ -187,11 +238,6 @@ void VolControl::EnableSlider(bool enable)
slider->setEnabled(enable);
}
QSlider *VolControl::GetSlider() const
{
return slider;
}
VolControl::~VolControl()
{
obs_fader_remove_callback(obs_fader, OBSVolumeChanged, this);
@@ -199,66 +245,143 @@ VolControl::~VolControl()
obs_fader_destroy(obs_fader);
obs_volmeter_destroy(obs_volmeter);
if (contextMenu)
contextMenu->close();
}
static inline QColor color_from_int(long long val)
{
QColor color(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff,
(val >> 24) & 0xff);
color.setAlpha(255);
return color;
}
QColor VolumeMeter::getBackgroundNominalColor() const
{
return backgroundNominalColor;
return p_backgroundNominalColor;
}
QColor VolumeMeter::getBackgroundNominalColorDisabled() const
{
return backgroundNominalColorDisabled;
}
void VolumeMeter::setBackgroundNominalColor(QColor c)
{
backgroundNominalColor = std::move(c);
p_backgroundNominalColor = std::move(c);
backgroundNominalColor = p_backgroundNominalColor;
}
void VolumeMeter::setBackgroundNominalColorDisabled(QColor c)
{
backgroundNominalColorDisabled = std::move(c);
}
QColor VolumeMeter::getBackgroundWarningColor() const
{
return backgroundWarningColor;
return p_backgroundWarningColor;
}
QColor VolumeMeter::getBackgroundWarningColorDisabled() const
{
return backgroundWarningColorDisabled;
}
void VolumeMeter::setBackgroundWarningColor(QColor c)
{
backgroundWarningColor = std::move(c);
p_backgroundWarningColor = std::move(c);
backgroundWarningColor = p_backgroundWarningColor;
}
void VolumeMeter::setBackgroundWarningColorDisabled(QColor c)
{
backgroundWarningColorDisabled = std::move(c);
}
QColor VolumeMeter::getBackgroundErrorColor() const
{
return backgroundErrorColor;
return p_backgroundErrorColor;
}
QColor VolumeMeter::getBackgroundErrorColorDisabled() const
{
return backgroundErrorColorDisabled;
}
void VolumeMeter::setBackgroundErrorColor(QColor c)
{
backgroundErrorColor = std::move(c);
p_backgroundErrorColor = std::move(c);
backgroundErrorColor = p_backgroundErrorColor;
}
void VolumeMeter::setBackgroundErrorColorDisabled(QColor c)
{
backgroundErrorColorDisabled = std::move(c);
}
QColor VolumeMeter::getForegroundNominalColor() const
{
return foregroundNominalColor;
return p_foregroundNominalColor;
}
QColor VolumeMeter::getForegroundNominalColorDisabled() const
{
return foregroundNominalColorDisabled;
}
void VolumeMeter::setForegroundNominalColor(QColor c)
{
foregroundNominalColor = std::move(c);
p_foregroundNominalColor = std::move(c);
foregroundNominalColor = p_foregroundNominalColor;
}
void VolumeMeter::setForegroundNominalColorDisabled(QColor c)
{
foregroundNominalColorDisabled = std::move(c);
}
QColor VolumeMeter::getForegroundWarningColor() const
{
return foregroundWarningColor;
return p_foregroundWarningColor;
}
QColor VolumeMeter::getForegroundWarningColorDisabled() const
{
return foregroundWarningColorDisabled;
}
void VolumeMeter::setForegroundWarningColor(QColor c)
{
foregroundWarningColor = std::move(c);
p_foregroundWarningColor = std::move(c);
foregroundWarningColor = p_foregroundWarningColor;
}
void VolumeMeter::setForegroundWarningColorDisabled(QColor c)
{
foregroundWarningColorDisabled = std::move(c);
}
QColor VolumeMeter::getForegroundErrorColor() const
{
return foregroundErrorColor;
return p_foregroundErrorColor;
}
QColor VolumeMeter::getForegroundErrorColorDisabled() const
{
return foregroundErrorColorDisabled;
}
void VolumeMeter::setForegroundErrorColor(QColor c)
{
foregroundErrorColor = std::move(c);
p_foregroundErrorColor = std::move(c);
foregroundErrorColor = p_foregroundErrorColor;
}
void VolumeMeter::setForegroundErrorColorDisabled(QColor c)
{
foregroundErrorColorDisabled = std::move(c);
}
QColor VolumeMeter::getClipColor() const
@@ -301,6 +424,42 @@ void VolumeMeter::setMinorTickColor(QColor c)
minorTickColor = std::move(c);
}
int VolumeMeter::getMeterThickness() const
{
return meterThickness;
}
void VolumeMeter::setMeterThickness(int v)
{
meterThickness = v;
recalculateLayout = true;
}
qreal VolumeMeter::getMeterFontScaling() const
{
return meterFontScaling;
}
void VolumeMeter::setMeterFontScaling(qreal v)
{
meterFontScaling = v;
recalculateLayout = true;
}
void VolControl::refreshColors()
{
volMeter->setBackgroundNominalColor(
volMeter->getBackgroundNominalColor());
volMeter->setBackgroundWarningColor(
volMeter->getBackgroundWarningColor());
volMeter->setBackgroundErrorColor(volMeter->getBackgroundErrorColor());
volMeter->setForegroundNominalColor(
volMeter->getForegroundNominalColor());
volMeter->setForegroundWarningColor(
volMeter->getForegroundWarningColor());
volMeter->setForegroundErrorColor(volMeter->getForegroundErrorColor());
}
qreal VolumeMeter::getMinimumLevel() const
{
return minimumLevel;
@@ -434,10 +593,9 @@ VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
bool vertical)
: QWidget(parent), obs_volmeter(obs_volmeter), vertical(vertical)
{
// Use a font that can be rendered small.
tickFont = QFont("Arial");
tickFont.setPixelSize(7);
// Default meter color settings, they only show if
setAttribute(Qt::WA_OpaquePaintEvent, true);
// Default meter settings, they only show if
// there is no stylesheet, do not remove.
backgroundNominalColor.setRgb(0x26, 0x7f, 0x26); // Dark green
backgroundWarningColor.setRgb(0x7f, 0x7f, 0x26); // Dark yellow
@@ -445,27 +603,38 @@ VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
foregroundNominalColor.setRgb(0x4c, 0xff, 0x4c); // Bright green
foregroundWarningColor.setRgb(0xff, 0xff, 0x4c); // Bright yellow
foregroundErrorColor.setRgb(0xff, 0x4c, 0x4c); // Bright red
clipColor.setRgb(0xff, 0xff, 0xff); // Bright white
magnitudeColor.setRgb(0x00, 0x00, 0x00); // Black
majorTickColor.setRgb(0xff, 0xff, 0xff); // Black
minorTickColor.setRgb(0xcc, 0xcc, 0xcc); // Black
minimumLevel = -60.0; // -60 dB
warningLevel = -20.0; // -20 dB
errorLevel = -9.0; // -9 dB
clipLevel = -0.5; // -0.5 dB
minimumInputLevel = -50.0; // -50 dB
peakDecayRate = 11.76; // 20 dB / 1.7 sec
magnitudeIntegrationTime = 0.3; // 99% in 300 ms
peakHoldDuration = 20.0; // 20 seconds
inputPeakHoldDuration = 1.0; // 1 second
backgroundNominalColorDisabled.setRgb(90, 90, 90);
backgroundWarningColorDisabled.setRgb(117, 117, 117);
backgroundErrorColorDisabled.setRgb(65, 65, 65);
foregroundNominalColorDisabled.setRgb(163, 163, 163);
foregroundWarningColorDisabled.setRgb(217, 217, 217);
foregroundErrorColorDisabled.setRgb(113, 113, 113);
clipColor.setRgb(0xff, 0xff, 0xff); // Bright white
magnitudeColor.setRgb(0x00, 0x00, 0x00); // Black
majorTickColor.setRgb(0xff, 0xff, 0xff); // Black
minorTickColor.setRgb(0xcc, 0xcc, 0xcc); // Black
minimumLevel = -60.0; // -60 dB
warningLevel = -20.0; // -20 dB
errorLevel = -9.0; // -9 dB
clipLevel = -0.5; // -0.5 dB
minimumInputLevel = -50.0; // -50 dB
peakDecayRate = 11.76; // 20 dB / 1.7 sec
magnitudeIntegrationTime = 0.3; // 99% in 300 ms
peakHoldDuration = 20.0; // 20 seconds
inputPeakHoldDuration = 1.0; // 1 second
meterThickness = 3; // Bar thickness in pixels
meterFontScaling =
0.7; // Font size for numbers is 70% of Widget's font size
channels = (int)audio_output_get_channels(obs_get_audio());
handleChannelCofigurationChange();
doLayout();
updateTimerRef = updateTimer.toStrongRef();
if (!updateTimerRef) {
updateTimerRef = QSharedPointer<VolumeMeterTimer>::create();
updateTimerRef->start(34);
updateTimerRef->setTimerType(Qt::PreciseTimer);
updateTimerRef->start(16);
updateTimer = updateTimerRef;
}
@@ -475,7 +644,6 @@ VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
VolumeMeter::~VolumeMeter()
{
updateTimerRef->RemoveVolControl(this);
delete tickPaintCache;
}
void VolumeMeter::setLevels(const float magnitude[MAX_AUDIO_CHANNELS],
@@ -515,23 +683,58 @@ inline void VolumeMeter::resetLevels()
}
}
inline void VolumeMeter::handleChannelCofigurationChange()
bool VolumeMeter::needLayoutChange()
{
int currentNrAudioChannels = obs_volmeter_get_nr_channels(obs_volmeter);
if (!currentNrAudioChannels) {
struct obs_audio_info oai;
obs_get_audio_info(&oai);
currentNrAudioChannels = (oai.speakers == SPEAKERS_MONO) ? 1
: 2;
}
if (displayNrAudioChannels != currentNrAudioChannels) {
displayNrAudioChannels = currentNrAudioChannels;
recalculateLayout = true;
}
return recalculateLayout;
}
// When this is called from the constructor, obs_volmeter_get_nr_channels has not
// yet been called and Q_PROPERTY settings have not yet been read from the
// stylesheet.
inline void VolumeMeter::doLayout()
{
QMutexLocker locker(&dataMutex);
int currentNrAudioChannels = obs_volmeter_get_nr_channels(obs_volmeter);
if (displayNrAudioChannels != currentNrAudioChannels) {
displayNrAudioChannels = currentNrAudioChannels;
recalculateLayout = false;
// Make room for 3 pixels meter, with one pixel between each.
// Then 9/13 pixels for ticks and numbers.
if (vertical)
setMinimumSize(displayNrAudioChannels * 4 + 14, 130);
else
setMinimumSize(130, displayNrAudioChannels * 4 + 8);
resetLevels();
tickFont = font();
QFontInfo info(tickFont);
tickFont.setPointSizeF(info.pointSizeF() * meterFontScaling);
QFontMetrics metrics(tickFont);
if (vertical) {
// Each meter channel is meterThickness pixels wide, plus one pixel
// between channels, but not after the last.
// Add 4 pixels for ticks, space to hold our longest label in this font,
// and a few pixels before the fader.
QRect scaleBounds = metrics.boundingRect("-88");
setMinimumSize(displayNrAudioChannels * (meterThickness + 1) -
1 + 4 + scaleBounds.width() + 2,
130);
} else {
// Each meter channel is meterThickness pixels high, plus one pixel
// between channels, but not after the last.
// Add 4 pixels for ticks, and space high enough to hold our label in
// this font, presuming that digits don't have descenders.
setMinimumSize(130,
displayNrAudioChannels * (meterThickness + 1) -
1 + 4 + metrics.capHeight());
}
resetLevels();
}
inline bool VolumeMeter::detectIdle(uint64_t ts)
@@ -649,12 +852,12 @@ void VolumeMeter::paintInputMeter(QPainter &painter, int x, int y, int width,
painter.fillRect(x, y, width, height, color);
}
void VolumeMeter::paintHTicks(QPainter &painter, int x, int y, int width,
int height)
void VolumeMeter::paintHTicks(QPainter &painter, int x, int y, int width)
{
qreal scale = width / minimumLevel;
painter.setFont(tickFont);
QFontMetrics metrics(tickFont);
painter.setPen(majorTickColor);
// Draw major tick lines and numeric indicators.
@@ -662,10 +865,18 @@ void VolumeMeter::paintHTicks(QPainter &painter, int x, int y, int width,
int position = int(x + width - (i * scale) - 1);
QString str = QString::number(i);
if (i == 0 || i == -5)
painter.drawText(position - 3, height, str);
else
painter.drawText(position - 5, height, str);
// Center the number on the tick, but don't overflow
QRect textBounds = metrics.boundingRect(str);
int pos;
if (i == 0) {
pos = position - textBounds.width();
} else {
pos = position - (textBounds.width() / 2);
if (pos < 0)
pos = 0;
}
painter.drawText(pos, y + 4 + metrics.capHeight(), str);
painter.drawLine(position, y, position, y + 2);
}
@@ -683,26 +894,31 @@ void VolumeMeter::paintVTicks(QPainter &painter, int x, int y, int height)
qreal scale = height / minimumLevel;
painter.setFont(tickFont);
QFontMetrics metrics(tickFont);
painter.setPen(majorTickColor);
// Draw major tick lines and numeric indicators.
for (int i = 0; i >= minimumLevel; i -= 5) {
int position = y + int((i * scale) - 1);
int position = y + int(i * scale) + METER_PADDING;
QString str = QString::number(i);
if (i == 0)
painter.drawText(x + 5, position + 4, str);
else if (i == -60)
painter.drawText(x + 4, position, str);
else
painter.drawText(x + 4, position + 2, str);
// Center the number on the tick, but don't overflow
if (i == 0) {
painter.drawText(x + 6, position + metrics.capHeight(),
str);
} else {
painter.drawText(x + 4,
position + (metrics.capHeight() / 2),
str);
}
painter.drawLine(x, position, x + 2, position);
}
// Draw minor tick lines.
painter.setPen(minorTickColor);
for (int i = 0; i >= minimumLevel; i--) {
int position = y + int((i * scale) - 1);
int position = y + int(i * scale) + METER_PADDING;
if (i % 5 != 0)
painter.drawLine(x, position, x + 1, position);
}
@@ -777,7 +993,7 @@ void VolumeMeter::paintHMeter(QPainter &painter, int x, int y, int width,
painter.fillRect(peakPosition, y,
maximumPosition - peakPosition, height,
backgroundErrorColor);
} else {
} else if (int(magnitude) != 0) {
if (!clipping) {
QTimer::singleShot(CLIP_FLASH_DURATION_MS, this,
SLOT(ClipEnding()));
@@ -879,7 +1095,7 @@ void VolumeMeter::paintVMeter(QPainter &painter, int x, int y, int width,
int end = errorLength + warningLength + nominalLength;
painter.fillRect(x, minimumPosition, width, end,
QBrush(foregroundErrorColor));
foregroundErrorColor);
}
if (peakHoldPosition - 3 < minimumPosition)
@@ -903,53 +1119,48 @@ void VolumeMeter::paintEvent(QPaintEvent *event)
{
uint64_t ts = os_gettime_ns();
qreal timeSinceLastRedraw = (ts - lastRedrawTime) * 0.000000001;
const QRect rect = event->region().boundingRect();
int width = rect.width();
int height = rect.height();
handleChannelCofigurationChange();
calculateBallistics(ts, timeSinceLastRedraw);
bool idle = detectIdle(ts);
// Draw the ticks in a off-screen buffer when the widget changes size.
QSize tickPaintCacheSize;
QRect widgetRect = rect();
int width = widgetRect.width();
int height = widgetRect.height();
QPainter painter(this);
if (vertical)
tickPaintCacheSize = QSize(14, height);
else
tickPaintCacheSize = QSize(width, 9);
if (tickPaintCache == nullptr ||
tickPaintCache->size() != tickPaintCacheSize) {
delete tickPaintCache;
tickPaintCache = new QPixmap(tickPaintCacheSize);
height -= METER_PADDING * 2;
QColor clearColor(0, 0, 0, 0);
tickPaintCache->fill(clearColor);
// timerEvent requests update of the bar(s) only, so we can avoid the
// overhead of repainting the scale and labels.
if (event->region().boundingRect() != getBarRect()) {
if (needLayoutChange())
doLayout();
// Paint window background color (as widget is opaque)
QColor background =
palette().color(QPalette::ColorRole::Window);
painter.fillRect(widgetRect, background);
QPainter tickPainter(tickPaintCache);
if (vertical) {
tickPainter.translate(0, height);
tickPainter.scale(1, -1);
paintVTicks(tickPainter, 0, 11,
tickPaintCacheSize.height() - 11);
paintVTicks(painter,
displayNrAudioChannels *
(meterThickness + 1) -
1,
0, height - (INDICATOR_THICKNESS + 3));
} else {
paintHTicks(tickPainter, 6, 0,
tickPaintCacheSize.width() - 6,
tickPaintCacheSize.height());
paintHTicks(painter, INDICATOR_THICKNESS + 3,
displayNrAudioChannels *
(meterThickness + 1) -
1,
width - (INDICATOR_THICKNESS + 3));
}
tickPainter.end();
}
// Actual painting of the widget starts here.
QPainter painter(this);
if (vertical) {
// Invert the Y axis to ease the math
painter.translate(0, height);
painter.translate(0, height + METER_PADDING);
painter.scale(1, -1);
painter.drawPixmap(displayNrAudioChannels * 4 - 1, 7,
*tickPaintCache);
} else {
painter.drawPixmap(0, height - 9, *tickPaintCache);
}
for (int channelNr = 0; channelNr < displayNrAudioChannels;
@@ -961,12 +1172,17 @@ void VolumeMeter::paintEvent(QPaintEvent *event)
: channelNr;
if (vertical)
paintVMeter(painter, channelNr * 4, 8, 3, height - 10,
paintVMeter(painter, channelNr * (meterThickness + 1),
INDICATOR_THICKNESS + 2, meterThickness,
height - (INDICATOR_THICKNESS + 2),
displayMagnitude[channelNrFixed],
displayPeak[channelNrFixed],
displayPeakHold[channelNrFixed]);
else
paintHMeter(painter, 5, channelNr * 4, width - 5, 3,
paintHMeter(painter, INDICATOR_THICKNESS + 2,
channelNr * (meterThickness + 1),
width - (INDICATOR_THICKNESS + 2),
meterThickness,
displayMagnitude[channelNrFixed],
displayPeak[channelNrFixed],
displayPeakHold[channelNrFixed]);
@@ -978,16 +1194,40 @@ void VolumeMeter::paintEvent(QPaintEvent *event)
// see that the audio stream has been stopped, without
// having too much visual impact.
if (vertical)
paintInputMeter(painter, channelNr * 4, 3, 3, 3,
paintInputMeter(painter,
channelNr * (meterThickness + 1), 0,
meterThickness, INDICATOR_THICKNESS,
displayInputPeakHold[channelNrFixed]);
else
paintInputMeter(painter, 0, channelNr * 4, 3, 3,
paintInputMeter(painter, 0,
channelNr * (meterThickness + 1),
INDICATOR_THICKNESS, meterThickness,
displayInputPeakHold[channelNrFixed]);
}
lastRedrawTime = ts;
}
QRect VolumeMeter::getBarRect() const
{
QRect rec = rect();
if (vertical)
rec.setWidth(displayNrAudioChannels * (meterThickness + 1) - 1);
else
rec.setHeight(displayNrAudioChannels * (meterThickness + 1) -
1);
return rec;
}
void VolumeMeter::changeEvent(QEvent *e)
{
if (e->type() == QEvent::StyleChange)
recalculateLayout = true;
QWidget::changeEvent(e);
}
void VolumeMeterTimer::AddVolControl(VolumeMeter *meter)
{
volumeMeters.push_back(meter);
@@ -1000,6 +1240,13 @@ void VolumeMeterTimer::RemoveVolControl(VolumeMeter *meter)
void VolumeMeterTimer::timerEvent(QTimerEvent *)
{
for (VolumeMeter *meter : volumeMeters)
meter->update();
for (VolumeMeter *meter : volumeMeters) {
if (meter->needLayoutChange()) {
// Tell paintEvent to update layout and paint everything
meter->update();
} else {
// Tell paintEvent to paint only the bars
meter->update(meter->getBarRect());
}
}
}