ControlCenter: add volume controls

This commit is contained in:
lysec
2025-10-10 14:51:42 +02:00
parent 2d13e60fa5
commit 7a403bbdde
2 changed files with 197 additions and 1 deletions
+189
View File
@@ -0,0 +1,189 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Services
import qs.Widgets
// Audio controls card: output and input volume controls
NBox {
id: root
property real localOutputVolume: AudioService.volume
property real localInputVolume: AudioService.inputVolume
// Timer to debounce volume changes (similar to AudioTab)
Timer {
interval: 100
running: true
repeat: true
onTriggered: {
if (Math.abs(localOutputVolume - AudioService.volume) >= 0.01) {
AudioService.setVolume(localOutputVolume)
}
}
}
// Connections to update local volumes when AudioService changes
Connections {
target: AudioService.sink?.audio ? AudioService.sink?.audio : null
function onVolumeChanged() {
localOutputVolume = AudioService.volume
}
}
Connections {
target: AudioService.source?.audio ? AudioService.source?.audio : null
function onVolumeChanged() {
localInputVolume = AudioService.inputVolume
}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: Style.marginM * scaling
spacing: Style.marginM * scaling
// Output Volume Section
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
opacity: AudioService.sink ? 1.0 : 0.5
enabled: AudioService.sink
// Output Volume Header
RowLayout {
Layout.fillWidth: true
spacing: Style.marginXS * scaling
NIconButton {
icon: AudioService.muted ? "volume-off" : "volume-high"
baseSize: Style.baseWidgetSize * 0.5
colorFg: AudioService.muted ? Color.mError : Color.mOnSurfaceVariant
colorBg: Color.transparent
colorBgHover: Color.mTertiary
colorFgHover: Color.mOnTertiary
onClicked: {
if (AudioService.sink && AudioService.sink.audio) {
AudioService.sink.audio.muted = !AudioService.muted
}
}
}
RowLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: I18n.tr("settings.audio.volumes.output-volume.label")
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurface
font.weight: Style.fontWeightMedium
}
NText {
text: AudioService.sink ? AudioService.sink.description : "No output device"
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
font.weight: Style.fontWeightMedium
elide: Text.ElideRight
Layout.fillWidth: true
}
}
}
// Output Volume Slider
RowLayout {
Layout.fillWidth: true
spacing: Style.marginXS * scaling
NSlider {
Layout.fillWidth: true
from: 0
to: Settings.data.audio.volumeOverdrive ? 1.5 : 1.0
value: localOutputVolume
stepSize: 0.01
onMoved: value => localOutputVolume = value
}
NText {
text: Math.round(AudioService.volume * 100) + "%"
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
font.weight: Style.fontWeightMedium
verticalAlignment: Text.AlignVCenter
Layout.alignment: Qt.AlignVCenter
}
}
}
// Input Volume Section
ColumnLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
opacity: AudioService.source ? 1.0 : 0.5
enabled: AudioService.source
// Input Volume Header
RowLayout {
Layout.fillWidth: true
spacing: Style.marginXS * scaling
NIconButton {
icon: AudioService.inputMuted ? "microphone-off" : "microphone"
baseSize: Style.baseWidgetSize * 0.5
colorFg: AudioService.inputMuted ? Color.mError : Color.mOnSurfaceVariant
colorBg: Color.transparent
colorBgHover: Color.mTertiary
colorFgHover: Color.mOnTertiary
onClicked: AudioService.setInputMuted(!AudioService.inputMuted)
}
RowLayout {
spacing: Style.marginXXS * scaling
Layout.fillWidth: true
NText {
text: I18n.tr("settings.audio.volumes.input-volume.label")
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurface
font.weight: Style.fontWeightMedium
}
NText {
text: AudioService.source ? AudioService.source.description : "No input device"
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
font.weight: Style.fontWeightMedium
elide: Text.ElideRight
Layout.fillWidth: true
}
}
}
// Input Volume Slider
RowLayout {
Layout.fillWidth: true
spacing: Style.marginXS * scaling
NSlider {
Layout.fillWidth: true
from: 0
to: Settings.data.audio.volumeOverdrive ? 1.5 : 1.0
value: localInputVolume
stepSize: 0.01
onMoved: value => AudioService.setInputVolume(value)
}
NText {
text: Math.round(AudioService.inputVolume * 100) + "%"
pointSize: Style.fontSizeXS * scaling
color: Color.mOnSurfaceVariant
font.weight: Style.fontWeightMedium
verticalAlignment: Text.AlignVCenter
Layout.alignment: Qt.AlignVCenter
}
}
}
}
}
+8 -1
View File
@@ -11,7 +11,7 @@ NPanel {
id: root
preferredWidth: 400
preferredHeight: topHeight + midHeight + bottomHeight + Math.round(Style.marginL * 4)
preferredHeight: topHeight + midHeight + bottomHeight + audioHeight + Math.round(Style.marginL * 5)
panelKeyboardFocus: true
readonly property int topHeight: {
@@ -31,6 +31,7 @@ NPanel {
}
readonly property int midHeight: 220
readonly property int bottomHeight: 80
readonly property int audioHeight: 120
// Positioning
readonly property string controlCenterPosition: Settings.data.controlCenter.position
@@ -60,6 +61,12 @@ NPanel {
Layout.preferredHeight: topHeight * scaling
}
// Audio controls card
AudioCard {
Layout.fillWidth: true
Layout.preferredHeight: audioHeight * scaling
}
// Media card
MediaCard {
Layout.fillWidth: true