0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-19 20:32:15 +02:00

UI: Update volume meter appearance

This commit is contained in:
Warchamp7 2024-04-20 19:58:20 -04:00
parent 17d654fcfc
commit 52ae5fc4bd
5 changed files with 237 additions and 48 deletions

View File

@ -129,6 +129,10 @@
--spinbox_button_height: calc(var(--input_height) - 2px);
--volume_slider: calc(calc(6px + var(--font_base_value)) / 2);
--volume_slider_box: calc(var(--volume_slider) * 4);
--volume_slider_label: calc(var(--volume_slider) * 6);
--scrollbar_size: 12px;
/* Inputs / Controls */
@ -295,15 +299,10 @@ SourceTree QWidget {
/* Misc */
QAbstractItemView,
QStackedWidget#stackedMixerArea QWidget {
QAbstractItemView {
background-color: var(--bg_base);
}
QStackedWidget#stackedMixerArea QScrollBar {
background-color: var(--grey6);
}
QToolTip {
background-color: var(--bg_base);
color: var(--text);
@ -1210,6 +1209,89 @@ QSlider::handle:disabled {
background-color: var(--button_bg_down);
}
#stackedMixerArea {
border: none;
padding: 0px;
border-bottom: 1px solid #3c404b;
}
VolControl #volLabel {
padding: var(--padding_base) 0px var(--padding_base);
text-align: center;
font-size: var(--font_base);
color: var(--text_muted);
}
/* Horizontal Mixer */
#hMixerScrollArea VolControl {
padding: 0px var(--padding_large);
border-bottom: 1px solid var(--border_color);
}
#hMixerScrollArea VolControl QSlider {
margin: 0px 0px;
}
#hMixerScrollArea VolControl QSlider::groove:horizontal {
background: var(--bg_window);
height: var(--volume_slider);
}
#hMixerScrollArea VolControl QPushButton {
margin-right: var(--padding_xlarge);
}
/* Vertical Mixer */
#stackedMixerArea QScrollBar:vertical {
border-left: 1px solid var(--border_color);
}
#vMixerScrollArea VolControl {
padding: var(--padding_large) 0px var(--padding_base);
border-right: 1px solid var(--border_color);
}
#vMixerScrollArea VolControl QSlider {
width: var(--volume_slider_box);
}
#vMixerScrollArea VolControl #volLabel {
padding: var(--padding_base) 0px var(--padding_base);
min-width: var(--volume_slider_label);
max-width: var(--volume_slider_label);
margin-right: 0;
text-align: center;
}
#vMixerScrollArea VolControl QSlider::groove:vertical {
background: var(--bg_window);
width: var(--volume_slider);
}
#vMixerScrollArea VolControl #volMeterFrame {
padding: var(--padding_large) var(--padding_xlarge);
}
#vMixerScrollArea VolControl QLabel {
padding: 0px var(--padding_large);
}
#vMixerScrollArea VolControl QPushButton {
margin-right: var(--padding_xlarge);
}
#vMixerScrollArea VolControl MuteCheckBox {
margin-left: var(--padding_xlarge);
}
VolControl {
background: var(--bg_base);
}
VolumeMeter {
background: transparent;
}
VolumeMeter {
qproperty-backgroundNominalColor: var(--green5);
qproperty-backgroundWarningColor: var(--yellow5);

View File

@ -246,6 +246,9 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
volLabel = new QLabel();
mute = new MuteCheckBox();
volLabel->setObjectName("volLabel");
volLabel->setAlignment(Qt::AlignCenter);
QString sourceName = obs_source_get_name(source);
setObjectName(sourceName);
@ -262,24 +265,28 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
}
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(4, 4, 4, 4);
mainLayout->setSpacing(2);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);
if (vertical) {
QHBoxLayout *nameLayout = new QHBoxLayout;
QHBoxLayout *controlLayout = new QHBoxLayout;
QHBoxLayout *volLayout = new QHBoxLayout;
QFrame *meterFrame = new QFrame;
QHBoxLayout *meterLayout = new QHBoxLayout;
volMeter = new VolumeMeter(nullptr, obs_volmeter, true);
slider = new VolumeSlider(obs_fader, Qt::Vertical);
slider->setLayoutDirection(Qt::LeftToRight);
slider->setDisplayTicks(true);
nameLayout->setAlignment(Qt::AlignCenter);
meterLayout->setAlignment(Qt::AlignCenter);
controlLayout->setAlignment(Qt::AlignCenter);
volLayout->setAlignment(Qt::AlignCenter);
meterFrame->setObjectName("volMeterFrame");
nameLayout->setContentsMargins(0, 0, 0, 0);
nameLayout->setSpacing(0);
nameLayout->addWidget(nameLabel);
@ -287,28 +294,38 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
controlLayout->setContentsMargins(0, 0, 0, 0);
controlLayout->setSpacing(0);
controlLayout->setAlignment(mute, Qt::AlignVCenter);
// Add Headphone (audio monitoring) widget here
controlLayout->addWidget(mute);
controlLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding,
QSizePolicy::Minimum));
if (showConfig) {
controlLayout->addWidget(config);
controlLayout->setAlignment(config, Qt::AlignVCenter);
}
controlLayout->addItem(new QSpacerItem(3, 0));
// Add Headphone (audio monitoring) widget here
controlLayout->addWidget(mute);
controlLayout->setAlignment(mute, Qt::AlignVCenter);
meterLayout->setContentsMargins(0, 0, 0, 0);
meterLayout->setSpacing(0);
meterLayout->addWidget(volMeter);
meterLayout->addWidget(slider);
meterLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding,
QSizePolicy::Minimum));
meterLayout->addWidget(volMeter);
meterFrame->setLayout(meterLayout);
volLayout->setContentsMargins(0, 0, 0, 0);
volLayout->setSpacing(0);
volLayout->addWidget(volLabel);
volLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding,
QSizePolicy::Minimum));
mainLayout->addItem(nameLayout);
mainLayout->addItem(volLayout);
mainLayout->addItem(meterLayout);
mainLayout->addWidget(meterFrame);
mainLayout->addItem(controlLayout);
volMeter->setFocusProxy(slider);
@ -316,17 +333,22 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
// 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 *textLayout = new QHBoxLayout;
QFrame *meterFrame = new QFrame;
QHBoxLayout *meterLayout = new QHBoxLayout;
QHBoxLayout *botLayout = new QHBoxLayout;
volMeter = new VolumeMeter(nullptr, obs_volmeter, false);
volMeter->setSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::Preferred);
slider = new VolumeSlider(obs_fader, Qt::Horizontal);
slider->setLayoutDirection(Qt::LeftToRight);
slider->setDisplayTicks(true);
textLayout->setContentsMargins(0, 0, 0, 0);
textLayout->addWidget(nameLabel);
@ -334,20 +356,28 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
textLayout->setAlignment(nameLabel, Qt::AlignLeft);
textLayout->setAlignment(volLabel, Qt::AlignRight);
meterFrame->setObjectName("volMeterFrame");
meterFrame->setLayout(meterLayout);
meterLayout->setContentsMargins(0, 0, 0, 0);
meterLayout->setSpacing(0);
if (showConfig) {
meterLayout->addWidget(config);
meterLayout->setAlignment(config, Qt::AlignVCenter);
}
meterLayout->addWidget(volMeter);
botLayout->setContentsMargins(0, 0, 0, 0);
botLayout->setSpacing(5);
botLayout->addWidget(slider);
botLayout->setSpacing(0);
botLayout->addWidget(mute);
botLayout->addWidget(slider);
botLayout->setAlignment(slider, Qt::AlignVCenter);
botLayout->setAlignment(mute, Qt::AlignVCenter);
if (showConfig) {
botLayout->addWidget(config);
botLayout->setAlignment(config, Qt::AlignVCenter);
}
mainLayout->addItem(textLayout);
mainLayout->addWidget(volMeter);
mainLayout->addWidget(meterFrame);
mainLayout->addItem(botLayout);
volMeter->setFocusProxy(slider);
@ -915,6 +945,10 @@ inline void VolumeMeter::doLayout()
{
QMutexLocker locker(&dataMutex);
if (displayNrAudioChannels) {
int meterSize = std::floor(22 / displayNrAudioChannels);
setMeterThickness(std::clamp(meterSize, 3, 7));
}
recalculateLayout = false;
tickFont = font();
@ -928,14 +962,14 @@ inline void VolumeMeter::doLayout()
// and a few pixels before the fader.
QRect scaleBounds = metrics.boundingRect("-88");
setMinimumSize(displayNrAudioChannels * (meterThickness + 1) -
1 + 4 + scaleBounds.width() + 2,
130);
1 + 10 + scaleBounds.width() + 2,
100);
} 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,
setMinimumSize(100,
displayNrAudioChannels * (meterThickness + 1) -
1 + 4 + metrics.capHeight());
}
@ -1085,14 +1119,6 @@ void VolumeMeter::paintHTicks(QPainter &painter, int x, int y, int width)
painter.drawLine(position, y, position, y + 2);
}
// Draw minor tick lines.
painter.setPen(minorTickColor);
for (int i = 0; i >= minimumLevel; i--) {
int position = int(x + width - (i * scale) - 1);
if (i % 5 != 0)
painter.drawLine(position, y, position, y + 1);
}
}
void VolumeMeter::paintVTicks(QPainter &painter, int x, int y, int height)
@ -1110,24 +1136,16 @@ void VolumeMeter::paintVTicks(QPainter &painter, int x, int y, int height)
// Center the number on the tick, but don't overflow
if (i == 0) {
painter.drawText(x + 6, position + metrics.capHeight(),
painter.drawText(x + 10, position + metrics.capHeight(),
str);
} else {
painter.drawText(x + 4,
painter.drawText(x + 8,
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) + METER_PADDING;
if (i % 5 != 0)
painter.drawLine(x, position, x + 1, position);
}
}
#define CLIP_FLASH_DURATION_MS 1000
@ -1518,6 +1536,77 @@ VolumeSlider::VolumeSlider(obs_fader_t *fader, Qt::Orientation orientation,
fad = fader;
}
bool VolumeSlider::getDisplayTicks() const
{
return displayTicks;
}
void VolumeSlider::setDisplayTicks(bool display)
{
displayTicks = display;
}
void VolumeSlider::paintEvent(QPaintEvent *event)
{
if (!getDisplayTicks()) {
QSlider::paintEvent(event);
return;
}
QPainter painter(this);
QColor *tickColor = new QColor;
tickColor->setRgb(91, 98, 115, 255);
obs_fader_conversion_t fader_db_to_def = obs_fader_db_to_def(fad);
QStyleOptionSlider opt;
initStyleOption(&opt);
QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt,
QStyle::SC_SliderGroove, this);
QRect handle = style()->subControlRect(QStyle::CC_Slider, &opt,
QStyle::SC_SliderHandle, this);
if (orientation() == Qt::Horizontal) {
const int sliderWidth = groove.width() - handle.width();
float tickLength = groove.height() * 1.5;
tickLength = std::max((int)tickLength + groove.height(),
8 + groove.height());
float yPos = groove.center().y() - (tickLength / 2) + 1;
for (int db = -10; db >= -90; db -= 10) {
float tickValue = fader_db_to_def(db);
float xPos = groove.left() + (tickValue * sliderWidth) +
(handle.width() / 2);
painter.fillRect(xPos, yPos, 1, tickLength, *tickColor);
}
}
if (orientation() == Qt::Vertical) {
const int sliderHeight = groove.height() - handle.height();
float tickLength = groove.width() * 1.5;
tickLength = std::max((int)tickLength + groove.width(),
8 + groove.width());
float xPos = groove.center().x() - (tickLength / 2) + 1;
for (int db = -10; db >= -96; db -= 10) {
float tickValue = fader_db_to_def(db);
float yPos = groove.height() + groove.top() -
(tickValue * sliderHeight) -
(handle.height() / 2);
painter.fillRect(xPos, yPos, tickLength, 1, *tickColor);
}
}
QSlider::paintEvent(event);
}
VolumeAccessibleInterface::VolumeAccessibleInterface(QWidget *w)
: QAccessibleWidget(w)
{

View File

@ -12,6 +12,7 @@
class QPushButton;
class VolumeMeterTimer;
class VolumeSlider;
class VolumeMeter : public QWidget {
Q_OBJECT
@ -276,7 +277,7 @@ class VolumeSlider;
class MuteCheckBox;
class OBSSourceLabel;
class VolControl : public QWidget {
class VolControl : public QFrame {
Q_OBJECT
private:
@ -342,6 +343,16 @@ public:
VolumeSlider(obs_fader_t *fader, QWidget *parent = nullptr);
VolumeSlider(obs_fader_t *fader, Qt::Orientation orientation,
QWidget *parent = nullptr);
bool getDisplayTicks() const;
void setDisplayTicks(bool display);
private:
bool displayTicks = false;
QColor tickColor;
protected:
virtual void paintEvent(QPaintEvent *event) override;
};
class VolumeAccessibleInterface : public QAccessibleWidget {

View File

@ -36,8 +36,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define CLAMP(x, min, max) ((x) < min ? min : ((x) > max ? max : (x)))
typedef float (*obs_fader_conversion_t)(const float val);
struct fader_cb {
obs_fader_changed_t callback;
void *param;
@ -943,3 +941,8 @@ float obs_db_to_mul(float db)
{
return db_to_mul(db);
}
obs_fader_conversion_t obs_fader_db_to_def(obs_fader_t *fader)
{
return fader->db_to_def;
}

View File

@ -282,6 +282,10 @@ EXPORT void obs_volmeter_remove_callback(obs_volmeter_t *volmeter,
EXPORT float obs_mul_to_db(float mul);
EXPORT float obs_db_to_mul(float db);
typedef float (*obs_fader_conversion_t)(const float val);
EXPORT obs_fader_conversion_t obs_fader_db_to_def(obs_fader_t *fader);
#ifdef __cplusplus
}
#endif