// 04-pipewire-volume/Bar.qml // A bar showing the default audio sink volume. Drag the slider to change it. import QtQuick import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Services.Pipewire import Quickshell.Widgets PanelWindow { id: bar anchors { top: true; left: true; right: true } implicitHeight: 36 color: "#cc1e1e2e" readonly property var sinkAudio: Pipewire.defaultAudioSink ? Pipewire.defaultAudioSink.audio : null // Keep the default sink tracked so its audio object remains available. PwObjectTracker { objects: [ Pipewire.defaultAudioSink ] } RowLayout { anchors.fill: parent anchors.leftMargin: 12 anchors.rightMargin: 12 spacing: 12 // Icon. `Quickshell.iconPath` resolves against the system icon theme. IconImage { implicitSize: 18 source: Quickshell.iconPath( bar.sinkAudio && bar.sinkAudio.muted ? "audio-volume-muted-symbolic" : "audio-volume-high-symbolic" ) } // Mute toggle. The `Connections` watches the service for changes. Text { text: "Mute" color: "white" font.pointSize: 11 MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: if (bar.sinkAudio) bar.sinkAudio.muted = !bar.sinkAudio.muted } } Item { Layout.fillWidth: true; Layout.preferredWidth: 1 } // spacer // Service changes update the slider through the value binding. // User movement writes back through onMoved without reacting to initialization. Slider { Layout.preferredWidth: 240 from: 0 to: 1.5 value: bar.sinkAudio ? bar.sinkAudio.volume : 0 onMoved: if (bar.sinkAudio) bar.sinkAudio.volume = value } Text { text: `${Math.floor((bar.sinkAudio ? bar.sinkAudio.volume : 0) * 100)}%` color: "white" font.pointSize: 11 Layout.preferredWidth: 40 } } }