Files
dotfiles/.config/quickshell/nucleus-shell/modules/interface/settings/AudioConfig.qml

356 lines
13 KiB
QML

import QtQuick
import QtQuick.Layouts
import Quickshell.Io
import qs.modules.functions
import qs.config
import qs.modules.components
import qs.services
ContentMenu {
title: "Sound"
description: "Volume and audio devices"
ContentCard {
ColumnLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(20)
RowLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(16)
Rectangle {
Layout.preferredWidth: 40
Layout.preferredHeight: 40
radius: Metrics.radius("large")
color: Appearance.m3colors.m3primaryContainer
MaterialSymbol {
anchors.centerIn: parent
icon: "volume_up"
color: Appearance.m3colors.m3onPrimaryContainer
iconSize: Metrics.iconSize(24)
}
}
ColumnLayout {
Layout.fillWidth: true
StyledText {
text: "Output"
font.pixelSize: Metrics.fontSize(16)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurface
}
StyledText {
text: Volume.defaultSink.description
font.pixelSize: Metrics.fontSize(13)
color: Appearance.m3colors.m3onSurfaceVariant
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Appearance.m3colors.m3outlineVariant
opacity: 0.4
}
ColumnLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(12)
RowLayout {
Layout.fillWidth: true
StyledText {
text: "Volume"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurface
}
Item { Layout.fillWidth: true }
StyledText {
animate: false
text: Math.round(Volume.defaultSink.audio.volume * 100) + "%"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit SemiBold")
color: Appearance.m3colors.m3primary
}
}
RowLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(16)
MaterialSymbol {
icon: Volume.defaultSink.audio.muted ? "volume_off"
: Volume.defaultSink.audio.volume < 0.33 ? "volume_mute"
: Volume.defaultSink.audio.volume < 0.66 ? "volume_down"
: "volume_up"
color: Appearance.m3colors.m3onSurfaceVariant
iconSize: Metrics.iconSize(24)
}
StyledSlider {
id: outputVolumeSlider
Layout.fillWidth: true
value: Volume.defaultSink.audio.volume * 100
onValueChanged: Volume.setVolume(value / 100)
}
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(8)
StyledText {
text: "Device"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurface
}
StyledDropDown {
Layout.fillWidth: true
label: "Output device"
model: Volume.sinks.map(d => d.description)
currentIndex: {
for (let i = 0; i < Volume.sinks.length; i++)
if (Volume.sinks[i].name === Volume.defaultSink.name) return i
return -1
}
onSelectedIndexChanged: index => {
if (index >= 0 && index < Volume.sinks.length)
Volume.setDefaultSink(Volume.sinks[index])
}
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 56
radius: Metrics.radius("small")
color: Appearance.m3colors.m3surfaceContainerHigh
RowLayout {
anchors.fill: parent
anchors.leftMargin: Metrics.margin(16)
anchors.rightMargin: Metrics.margin(16)
spacing: Metrics.spacing(12)
MaterialSymbol {
icon: Volume.defaultSink.audio.muted ? "volume_off" : "volume_up"
color: Volume.defaultSink.audio.muted ? Appearance.m3colors.m3error : Appearance.m3colors.m3onSurfaceVariant
iconSize: Metrics.iconSize(24)
}
StyledText {
Layout.fillWidth: true
text: "Mute output"
font.pixelSize: Metrics.fontSize(14)
color: Appearance.m3colors.m3onSurface
}
StyledSwitch {
checked: Volume.defaultSink.audio.muted
onToggled: Volume.toggleMuted(Volume.defaultSink)
}
}
}
}
}
ContentCard {
ColumnLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(20)
RowLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(16)
Rectangle {
Layout.preferredWidth: 40
Layout.preferredHeight: 40
radius: Metrics.radius("large")
color: Appearance.m3colors.m3secondaryContainer
MaterialSymbol {
anchors.centerIn: parent
icon: "mic"
color: Appearance.m3colors.m3onSecondaryContainer
iconSize: Metrics.iconSize(24)
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(2)
StyledText {
text: "Input"
font.pixelSize: Metrics.fontSize(16)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurface
}
StyledText {
visible: Volume.sources.length > 0
text: Volume.defaultSource.description
font.pixelSize: Metrics.fontSize(13)
color: Appearance.m3colors.m3onSurfaceVariant
}
}
}
Rectangle {
visible: Volume.sources.length === 0
Layout.fillWidth: true
Layout.preferredHeight: 120
radius: Metrics.radius("small")
color: Appearance.m3colors.m3surfaceContainerHigh
ColumnLayout {
anchors.centerIn: parent
spacing: Metrics.spacing(8)
MaterialSymbol {
icon: "mic_off"
iconSize: Metrics.iconSize(48)
color: ColorUtils.transparentize(Appearance.m3colors.m3onSurface, 0.3)
Layout.alignment: Qt.AlignHCenter
}
StyledText {
text: "No input devices"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurfaceVariant
Layout.alignment: Qt.AlignHCenter
}
}
}
Rectangle {
visible: Volume.sources.length > 0
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Appearance.m3colors.m3outlineVariant
opacity: 0.4
}
ColumnLayout {
visible: Volume.sources.length > 0
Layout.fillWidth: true
spacing: Metrics.spacing(12)
RowLayout {
Layout.fillWidth: true
StyledText {
text: "Volume"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurface
}
Item { Layout.fillWidth: true }
StyledText {
animate: false
text: Math.round(Volume.defaultSource.audio.volume * 100) + "%"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit SemiBold")
color: Appearance.m3colors.m3primary
}
}
RowLayout {
Layout.fillWidth: true
spacing: Metrics.spacing(16)
MaterialSymbol {
icon: Volume.defaultSource.audio.muted ? "mic_off" : "mic"
color: Appearance.m3colors.m3onSurfaceVariant
iconSize: Metrics.iconSize(24)
}
StyledSlider {
id: inputVolumeSlider
Layout.fillWidth: true
value: Volume.defaultSource.audio.volume * 100
onValueChanged: Volume.setSourceVolume(value / 100)
}
}
}
ColumnLayout {
visible: Volume.sources.length > 0
Layout.fillWidth: true
spacing: Metrics.spacing(8)
StyledText {
text: "Device"
font.pixelSize: Metrics.fontSize(14)
font.family: Metrics.fontFamily("Outfit Medium")
color: Appearance.m3colors.m3onSurface
}
StyledDropDown {
Layout.fillWidth: true
label: "Input device"
model: Volume.sources.map(d => d.description)
currentIndex: {
for (let i = 0; i < Volume.sources.length; i++)
if (Volume.sources[i].name === Volume.defaultSource.name) return i
return -1
}
onSelectedIndexChanged: index => {
if (index >= 0 && index < Volume.sources.length)
Volume.setDefaultSource(Volume.sources[index])
}
}
}
Rectangle {
visible: Volume.sources.length > 0
Layout.fillWidth: true
Layout.preferredHeight: 56
radius: Metrics.radius("small")
color: Appearance.m3colors.m3surfaceContainerHigh
RowLayout {
anchors.fill: parent
anchors.leftMargin: Metrics.margin(16)
anchors.rightMargin: Metrics.margin(16)
spacing: Metrics.spacing(12)
MaterialSymbol {
icon: Volume.defaultSource.audio.muted ? "mic_off" : "mic"
color: Volume.defaultSource.audio.muted ? Appearance.m3colors.m3error : Appearance.m3colors.m3onSurfaceVariant
iconSize: Metrics.iconSize(24)
}
StyledText {
Layout.fillWidth: true
text: "Mute input"
font.pixelSize: Metrics.fontSize(14)
color: Appearance.m3colors.m3onSurface
}
StyledSwitch {
checked: Volume.defaultSource.audio.muted
onToggled: Volume.toggleMuted(Volume.defaultSource)
}
}
}
}
}
}