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:
parent
17d654fcfc
commit
52ae5fc4bd
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user