Files
dotfiles/roles/quickshell/files/bar/VolumeControl.qml
2026-04-14 18:13:39 +02:00

75 lines
2.2 KiB
QML

import Quickshell.Services.Pipewire
import QtQuick
import QtQuick.Layouts
import "../components"
Item {
id: root
implicitWidth: chip.implicitWidth + 10
implicitHeight: 24
signal clickedLeft
PwObjectTracker {
objects: Pipewire.nodes.values
}
function safeVolume(node) {
if (!node || !node.ready || !node.audio) return 0
const v = node.audio.volume
return (v !== undefined && !isNaN(v)) ? v : 0
}
function setVolume(node, v) {
if (!node || !node.ready || !node.audio) return
node.audio.volume = Math.max(0, Math.min(1, v))
}
function volIcon(vol, muted) {
if (muted) return "\uf6a9"
if (vol > 0.6) return "\uf028"
if (vol > 0.2) return "\uf027"
return "\uf026"
}
readonly property var defaultSink: Pipewire.defaultAudioSink
readonly property real defaultVolume: safeVolume(defaultSink)
readonly property bool defaultMuted: defaultSink?.audio?.muted ?? false
Row {
id: chip
anchors.centerIn: parent
spacing: 5
Text {
anchors.verticalCenter: parent.verticalCenter
text: root.volIcon(root.defaultVolume, root.defaultMuted)
font.family: "JetBrainsMono Nerd Font Mono"
font.pixelSize: 14
color: root.defaultMuted ? Theme.textDim : Theme.text
}
Text {
anchors.verticalCenter: parent.verticalCenter
text: root.defaultMuted ? "mute" : Math.round(root.defaultVolume * 100) + "%"
font.pixelSize: 11
color: Theme.textDim
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.PointingHandCursor
onClicked: mouse => {
if (mouse.button === Qt.RightButton) {
if (root.defaultSink?.ready && root.defaultSink?.audio)
root.defaultSink.audio.muted = !root.defaultSink.audio.muted
} else {
root.clickedLeft()
}
}
onWheel: wheel => {
if (!root.defaultSink?.ready) return
root.setVolume(root.defaultSink, root.defaultVolume + wheel.angleDelta.y / 120 * 0.05)
}
}
}