From 42073b289e5b4ff415e4d4b4e8104d795ccbbf28 Mon Sep 17 00:00:00 2001 From: quadbyte Date: Sun, 10 Aug 2025 19:12:44 -0400 Subject: [PATCH] Bar-Volume: everything working just missing the AudioDeviceSelector --- Modules/Bar/Volume.qml | 82 +++++++++++++++--------------------------- Services/Audio.qml | 33 +++++++++++++---- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/Modules/Bar/Volume.qml b/Modules/Bar/Volume.qml index c68e7a6..996ec03 100644 --- a/Modules/Bar/Volume.qml +++ b/Modules/Bar/Volume.qml @@ -6,10 +6,13 @@ import qs.Modules.Audio import qs.Widgets Item { - id: volumeDisplay + id: root - width: pillIndicator.width - height: pillIndicator.height + width: pill.width + height: pill.height + + // Used to avoid opening the pill on Quickshell startup + property bool firstVolumeReceived: false function getIcon() { if (Audio.muted) { @@ -19,7 +22,7 @@ Item { } function getIconColor() { - return (Audio.volume <= 1.0) ? Colors.textPrimary : getVolumeColor(); + return (Audio.volume <= 1.0) ? Colors.textPrimary : getVolumeColor() } function getVolumeColor() { @@ -38,7 +41,7 @@ Item { } NPill { - id: pillIndicator + id: pill icon: getIcon() iconCircleColor: getVolumeColor() collapsedIconColor: getIconColor() @@ -48,19 +51,32 @@ Item { Audio.volume * 100) + "%\nLeft click for advanced settings.\nScroll up/down to change volume." onClicked: function () { console.log("onClicked") - //if (ioSelector.visible) { - // ioSelector.dismiss(); - // } else { - // ioSelector.show(); - // } + // if (ioSelector.visible) { + // ioSelector.dismiss() + // } else { + // ioSelector.show() + // } + } + onWheel: function (angle) { + if (angle > 0) { + Audio.volumeIncrement() + } else if (angle < 0) { + Audio.volumeDecrement() + } } } + // Connection used to open the pill when volume changes Connections { - target: Pipewire.defaultAudioSink?.audio ? Pipewire.defaultAudioSink?.audio : null - + target: Audio.sink?.audio ? Audio.sink?.audio : null function onVolumeChanged() { - console.log("[Bar:Volume] onVolumeChanged") + // console.log("[Bar:Volume] onVolumeChanged") + if (!firstVolumeReceived) { + // Ignore the first volume change + firstVolumeReceived = true + } else { + pill.show() + } } } @@ -68,44 +84,4 @@ Item { id: ioSelector // onPanelClosed: ioSelector.dismiss() } - - // Connections { - // target: Audio - // function onVolumeChanged() { - // console.log("onVolumeChanged") - // } - - // function onSinkChanged() { - // console.log("onSinkChanged") - // } - - // } - - // MouseArea { - // anchors.fill: parent - // hoverEnabled: true - // acceptedButtons: Qt.NoButton - // propagateComposedEvents: true - // onEntered: { - // volumeDisplay.containsMouse = true - // pillIndicator.autoHide = false - // pillIndicator.showDelayed() - // } - // onExited: { - // volumeDisplay.containsMouse = false - // pillIndicator.autoHide = true - // pillIndicator.hide() - // } - // cursorShape: Qt.PointingHandCursor - // onWheel: wheel => { - // if (!shell) - // return - // let step = 5 - // if (wheel.angleDelta.y > 0) { - // shell.updateVolume(Math.min(200, shell.volume + step)) - // } else if (wheel.angleDelta.y < 0) { - // shell.updateVolume(Math.max(0, shell.volume - step)) - // } - // } - // } } diff --git a/Services/Audio.qml b/Services/Audio.qml index 1420a46..3c8bf02 100644 --- a/Services/Audio.qml +++ b/Services/Audio.qml @@ -8,27 +8,48 @@ import Quickshell.Services.Pipewire Singleton { id: root - // Ensure the volume is readonly from outside + readonly property PwNode sink: Pipewire.defaultAudioSink + readonly property PwNode source: Pipewire.defaultAudioSource + + // Volume [0..1] is readonly from outside readonly property alias volume: root._volume - property real _volume: 0 + property real _volume: sink?.audio?.volume ?? 0 readonly property alias muted: root._muted - property bool _muted: false + property bool _muted: !!sink?.audio?.muted + + readonly property real step: 0.05 + + function volumeIncrement() { + volumeSet(volume + step) + } + + function volumeDecrement() { + volumeSet(volume - step) + } + + function volumeSet(newVolume) { + // Clamp volume to 200% + if (sink?.ready && sink?.audio) { + sink.audio.muted = false + sink.audio.volume = Math.max(0, Math.min(2, newVolume)) + } + } PwObjectTracker { objects: [Pipewire.defaultAudioSink] } Connections { - target: Pipewire.defaultAudioSink?.audio ? Pipewire.defaultAudioSink?.audio : null + target: sink?.audio ? sink?.audio : null function onVolumeChanged() { - root._volume = (Pipewire.defaultAudioSink?.audio.volume ?? 0) + root._volume = (sink?.audio.volume ?? 0) console.log("[Audio] onVolumeChanged: " + volume) } function onMutedChanged() { - root._muted = (Pipewire.defaultAudioSink?.audio.muted ?? true) + root._muted = (sink?.audio.muted ?? true) console.log("[Audio] onMuteChanged " + muted) } }