Files

60 lines
1.9 KiB
QML

pragma Singleton
import Quickshell
import Quickshell.Services.Pipewire
import qs.config
// The default audio sink. Quickshell talks to pipewire directly, so there is no
// wpctl or pactl to shell out to and no polling: the properties below change as
// the graph does, whoever moved them.
//
// Everything is expressed against the default sink rather than a remembered
// one, so switching outputs — plugging in a headset, say — moves the panel with
// the sound.
Singleton {
id: root
readonly property PwNode sink: Pipewire.defaultAudioSink
// Pipewire objects only carry live properties while something is tracking
// them, so `audio` is null until the tracker below binds the node.
readonly property bool available: Config.showVolume && root.sink !== null && root.sink.ready && root.sink.audio !== null
// 0-1 for the usable range, though pipewire allows more and another client
// may well have set more. Reported as-is; the slider is what clamps.
readonly property real volume: root.available ? root.sink.audio.volume : 0
readonly property bool muted: root.available ? root.sink.audio.muted : false
function setVolume(value: real): void {
if (!root.available)
return;
root.sink.audio.volume = Math.max(0, Math.min(1, value));
}
// Raising the volume from silence unmutes: a volume key that appears to do
// nothing is worse than one that does slightly more than it said.
function step(delta: real): void {
if (!root.available)
return;
if (delta > 0 && root.muted)
root.setMuted(false);
root.setVolume(root.volume + delta);
}
function setMuted(muted: bool): void {
if (root.available)
root.sink.audio.muted = muted;
}
function toggleMute(): void {
root.setMuted(!root.muted);
}
PwObjectTracker {
objects: root.sink ? [root.sink] : []
}
}