/*** This file is part of pavucontrol. Copyright 2006-2008 Lennart Poettering Copyright 2009 Colin Guthrie pavucontrol is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. pavucontrol is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with pavucontrol. If not, see . ***/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "channel.h" #include "minimalstreamwidget.h" constexpr int SLIDER_SNAP = 2; static inline int paVolume2Percent(pa_volume_t vol) { if (vol > PA_VOLUME_UI_MAX) vol = PA_VOLUME_UI_MAX; return qRound(static_cast(vol - PA_VOLUME_MUTED) / PA_VOLUME_NORM * 100); } static inline pa_volume_t percent2PaVolume(int percent) { return PA_VOLUME_MUTED + qRound(static_cast(percent) / 100 * PA_VOLUME_NORM); } /*** ChannelWidget ***/ Channel::Channel(QGridLayout* parent) : QObject(parent), can_decibel(false), volumeScaleEnabled(true), last(false) { channelLabel = new QLabel(nullptr); volumeScale = new QSlider(Qt::Horizontal, nullptr); volumeLabel = new QLabel(nullptr); const int row = parent->rowCount(); parent->addWidget(channelLabel, row, 0); parent->addWidget(volumeScale, row, 1); parent->addWidget(volumeLabel, row, 2); // make the info font smaller QFont label_font = volumeLabel->font(); if (label_font.pixelSize() == -1) label_font.setPointSizeF(label_font.pointSizeF() * 0.8); else label_font.setPixelSize(qRound(static_cast(label_font.pixelSize()) * 0.8)); volumeLabel->setFont(label_font); volumeLabel->setFixedWidth(QFontMetrics{volumeLabel->font()}.size(Qt::TextSingleLine, QStringLiteral("100%(-99.99dB)")).width()); volumeLabel->setAlignment(Qt::AlignHCenter); volumeLabel->setTextFormat(Qt::RichText); volumeScale->setRange(paVolume2Percent(PA_VOLUME_MUTED), paVolume2Percent(PA_VOLUME_UI_MAX)); volumeScale->setValue(paVolume2Percent(PA_VOLUME_NORM)); volumeScale->setPageStep(5); volumeScale->setTickInterval(paVolume2Percent(PA_VOLUME_NORM)); volumeScale->setTickPosition(QSlider::TicksBelow); volumeScale->setTracking(false); setBaseVolume(PA_VOLUME_NORM); connect(volumeScale, &QSlider::valueChanged, this, &Channel::onVolumeScaleValueChanged); connect(volumeScale, &QSlider::sliderMoved, this, &Channel::onVolumeScaleSliderMoved); } void Channel::setVolume(pa_volume_t volume) { const int v = paVolume2Percent(volume); if (can_decibel) { const double dB = pa_sw_volume_to_dB(volume); volumeLabel->setText(tr("%1% (%2dB)", "volume slider label [X% (YdB)]").arg(v) .arg(dB > PA_DECIBEL_MININFTY ? QString::asprintf("%0.2f", dB) : QStringLiteral("-∞"))); } else volumeLabel->setText(tr("%1%", "volume slider label [X%]").arg(v)); volumeScaleEnabled = false; volumeScale->setValue(v); volumeScaleEnabled = true; } void Channel::setVisible(bool visible) { channelLabel->setVisible(visible); volumeScale->setVisible(visible); volumeLabel->setVisible(visible); } void Channel::setEnabled(bool enabled) { channelLabel->setEnabled(enabled); volumeScale->setEnabled(enabled); volumeLabel->setEnabled(enabled); } void Channel::onVolumeScaleValueChanged(int value) { if (!volumeScaleEnabled) return; if (minimalStreamWidget->updating) return; minimalStreamWidget->updateChannelVolume(channel, percent2PaVolume(value)); } void Channel::onVolumeScaleSliderMoved(int value) { if (!volumeScaleEnabled) return; if (minimalStreamWidget->updating) return; const int current_value = volumeScale->value(); if (current_value == 100 && qAbs(value - current_value) <= SLIDER_SNAP) { volumeScale->blockSignals(true); volumeScale->setSliderPosition(current_value); volumeScale->blockSignals(false); return; } volumeScale->setValue(value); } /* void Channel::set_sensitive(bool enabled) { setEnabled(enabled); channelLabel->setEnabled(enabled); volumeLabel->setEnabled(enabled); volumeScale->setEnabled(enabled); } */ void Channel::setBaseVolume(pa_volume_t /*v*/) { #if 0 // FIXME: Qt does not support this functionality gtk_scale_clear_marks(GTK_SCALE(volumeScale->gobj())); gtk_scale_add_mark(GTK_SCALE(volumeScale->gobj()), (double)PA_VOLUME_MUTED, (GtkPositionType) GTK_POS_BOTTOM, last ? (can_decibel ? tr("Silence").toUtf8().constData() : tr("Min").toUtf8().constData()) : NULL); gtk_scale_add_mark(GTK_SCALE(volumeScale->gobj()), (double)PA_VOLUME_NORM, (GtkPositionType) GTK_POS_BOTTOM, last ? tr("100% (0dB)").toUtf8().constData() : NULL); if (v > PA_VOLUME_MUTED && v < PA_VOLUME_NORM) { gtk_scale_add_mark(GTK_SCALE(volumeScale->gobj()), (double)v, (GtkPositionType) GTK_POS_BOTTOM, last ? tr("Base").toUtf8().constData() : NULL); } #endif }