169 lines
5.1 KiB
QML
169 lines
5.1 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Services.Pipewire
|
|
import qs.config
|
|
import qs.widgets
|
|
import qs.services
|
|
import qs.modules.quicksettings
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
required property var node
|
|
property bool output: true
|
|
property bool selected: false
|
|
|
|
implicitHeight: root.output || !root.selected ? 88 : 105
|
|
radius: Theme.cardRadius
|
|
color: root.selected ? Theme.alpha(Theme.accent, 0.09) : Theme.alpha(Theme.fg, 0.025)
|
|
border.width: 1
|
|
border.color: root.selected ? Theme.alpha(Theme.accent, 0.34) : Theme.alpha(Theme.fg, 0.07)
|
|
|
|
PwObjectTracker {
|
|
objects: root.node ? [root.node] : []
|
|
}
|
|
|
|
PwNodePeakMonitor {
|
|
id: inputPeak
|
|
node: root.node
|
|
enabled: !root.output && root.selected
|
|
}
|
|
|
|
readonly property real volume: root.node?.audio?.volume ?? 0
|
|
readonly property bool muted: root.node?.audio?.muted ?? false
|
|
|
|
function iconName(): string {
|
|
if (!root.output)
|
|
return root.muted ? "microphone-sensitivity-muted-symbolic" : "audio-input-microphone-symbolic";
|
|
if (root.muted || root.volume <= 0.001)
|
|
return "audio-volume-muted-symbolic";
|
|
if (root.volume < 0.34)
|
|
return "audio-volume-low-symbolic";
|
|
if (root.volume < 0.67)
|
|
return "audio-volume-medium-symbolic";
|
|
return "audio-volume-high-symbolic";
|
|
}
|
|
|
|
Row {
|
|
id: heading
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.leftMargin: 12
|
|
anchors.rightMargin: 10
|
|
anchors.topMargin: 8
|
|
height: 28
|
|
spacing: 10
|
|
|
|
ThemedIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
size: 20
|
|
icon: root.output ? "audio-speakers-symbolic" : "audio-input-microphone-symbolic"
|
|
iconFallback: "audio-card-symbolic"
|
|
tint: root.selected ? Theme.accent : Theme.fg
|
|
}
|
|
|
|
Column {
|
|
width: Math.max(0, parent.width - 20 - useButton.width - parent.spacing * 2)
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 1
|
|
|
|
Text {
|
|
width: parent.width
|
|
text: AudioDevices.label(root.node)
|
|
color: Theme.fg
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSize
|
|
font.weight: root.selected ? Font.DemiBold : Font.Medium
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Text {
|
|
width: parent.width
|
|
visible: root.node.nickname && root.node.nickname !== AudioDevices.label(root.node)
|
|
text: root.node.nickname ?? ""
|
|
color: Theme.fgDim
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
|
|
SettingsButton {
|
|
id: useButton
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: root.selected ? 78 : 64
|
|
text: root.selected ? "Default" : "Use"
|
|
enabled: !root.selected
|
|
onClicked: AudioDevices.select(root.output, root.node)
|
|
}
|
|
}
|
|
|
|
IconButton {
|
|
id: muteButton
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 8
|
|
anchors.top: heading.bottom
|
|
anchors.topMargin: 7
|
|
size: 30
|
|
iconSize: 17
|
|
icon: root.iconName()
|
|
iconFallback: root.output ? "audio-volume-high-symbolic" : "audio-input-microphone-symbolic"
|
|
onClicked: {
|
|
if (root.node?.audio)
|
|
root.node.audio.muted = !root.node.audio.muted;
|
|
}
|
|
}
|
|
|
|
ValueSlider {
|
|
id: volumeSlider
|
|
anchors.left: muteButton.right
|
|
anchors.leftMargin: 7
|
|
anchors.right: volumeText.left
|
|
anchors.rightMargin: 10
|
|
anchors.verticalCenter: muteButton.verticalCenter
|
|
value: root.muted ? 0 : root.volume
|
|
onMoved: value => {
|
|
if (!root.node?.audio)
|
|
return;
|
|
root.node.audio.muted = false;
|
|
root.node.audio.volume = value;
|
|
}
|
|
}
|
|
|
|
Text {
|
|
id: volumeText
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 12
|
|
anchors.verticalCenter: muteButton.verticalCenter
|
|
width: 38
|
|
text: Math.round(root.volume * 100) + "%"
|
|
color: Theme.fgDim
|
|
font.family: Theme.fontMono
|
|
font.features: Theme.tabularFigures
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
horizontalAlignment: Text.AlignRight
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.left: volumeSlider.left
|
|
anchors.right: volumeText.right
|
|
anchors.top: muteButton.bottom
|
|
anchors.topMargin: 5
|
|
height: 5
|
|
radius: height / 2
|
|
visible: !root.output && root.selected
|
|
color: Theme.alpha(Theme.fg, 0.10)
|
|
|
|
Rectangle {
|
|
anchors.left: parent.left
|
|
anchors.top: parent.top
|
|
anchors.bottom: parent.bottom
|
|
width: parent.width * Math.max(0, Math.min(1, inputPeak.peak))
|
|
radius: parent.radius
|
|
color: inputPeak.peak > 0.88 ? Theme.danger : Theme.accentSecondary
|
|
|
|
}
|
|
}
|
|
}
|