diff options
| author | Petri Hienonen <petri.hienonen@gmail.com> | 2024-05-23 13:56:00 +0300 |
|---|---|---|
| committer | Petri Hienonen <petri.hienonen@gmail.com> | 2025-11-30 12:29:57 +0200 |
| commit | 08297376a85a1719518507e54fca9de954d2376a (patch) | |
| tree | 3b9c58304b40248533bbb2bb5b7bad2da9da1ff0 /home/quickshell/bar/blocks/Sound.qml | |
| parent | 75c2af4aedd2ac5c2cfc74b346625fa4b265541d (diff) | |
| download | nixos-08297376a85a1719518507e54fca9de954d2376a.tar.zst | |
Agenix configuration
Diffstat (limited to 'home/quickshell/bar/blocks/Sound.qml')
| -rw-r--r-- | home/quickshell/bar/blocks/Sound.qml | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/home/quickshell/bar/blocks/Sound.qml b/home/quickshell/bar/blocks/Sound.qml new file mode 100644 index 0000000..e8be70b --- /dev/null +++ b/home/quickshell/bar/blocks/Sound.qml @@ -0,0 +1,176 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Services.Pipewire +import Quickshell.Io +import "../" +import "root:/" + +BarBlock { + id: root + property var sink: Pipewire.defaultAudioSink + + PwObjectTracker { + objects: [Pipewire.defaultAudioSink] + onObjectsChanged: { + sink = Pipewire.defaultAudioSink + if (sink?.audio) { + sink.audio.volumeChanged.connect(updateVolume) + } + } + } + + function updateVolume() { + if (sink?.audio) { + const icon = sink.audio.muted ? "" : "" + content.symbolText = `${icon} ${Math.round(sink.audio.volume * 100)}%` + } + } + + content: BarText { symbolText: `${sink?.audio?.muted ? "" : ""} ${Math.round(sink?.audio?.volume * 100)}%` } + + MouseArea { + anchors.fill: parent + onClicked: toggleMenu() + onWheel: function(event) { + if (sink?.audio) { + sink.audio.volume = Math.max(0, Math.min(1, sink.audio.volume + (event.angleDelta.y / 120) * 0.05)) + } + } + } + + Process { + id: pavucontrol + command: ["pavucontrol"] + running: false + } + + PopupWindow { + id: menuWindow + width: 200 + height: 150 + visible: false + + anchor { + window: root.QsWindow?.window + edges: Edges.Bottom + gravity: Edges.Top + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onExited: { + if (!containsMouse) { + closeTimer.start() + } + } + onEntered: closeTimer.stop() + + Timer { + id: closeTimer + interval: 500 + onTriggered: menuWindow.visible = false + } + + Rectangle { + anchors.fill: parent + color: "#2c2c2c" + border.color: "#3c3c3c" + border.width: 1 + radius: 4 + + Column { + anchors.fill: parent + anchors.margins: 10 + spacing: 10 + + // Volume Slider + Rectangle { + width: parent.width + height: 35 + color: "transparent" + + Slider { + id: volumeSlider + anchors.fill: parent + from: 0 + to: 1 + value: sink?.audio?.volume || 0 + onValueChanged: { + if (sink?.audio) { + sink.audio.volume = value + } + } + + background: Rectangle { + x: volumeSlider.leftPadding + y: volumeSlider.topPadding + volumeSlider.availableHeight / 2 - height / 2 + width: volumeSlider.availableWidth + height: 4 + radius: 2 + color: "#3c3c3c" + + Rectangle { + width: volumeSlider.visualPosition * parent.width + height: parent.height + color: "#4a9eff" + radius: 2 + } + } + + handle: Rectangle { + x: volumeSlider.leftPadding + volumeSlider.visualPosition * (volumeSlider.availableWidth - width) + y: volumeSlider.topPadding + volumeSlider.availableHeight / 2 - height / 2 + width: 16 + height: 16 + radius: 8 + color: volumeSlider.pressed ? "#4a9eff" : "#ffffff" + border.color: "#3c3c3c" + } + } + } + + Repeater { + model: [ + { text: sink?.audio?.muted ? "Unmute" : "Mute", action: () => sink?.audio && (sink.audio.muted = !sink.audio.muted) }, + { text: "Pavucontrol", action: () => { pavucontrol.running = true; menuWindow.visible = false } } + ] + + Rectangle { + width: parent.width + height: 35 + color: mouseArea.containsMouse ? "#3c3c3c" : "transparent" + radius: 4 + + Text { + anchors.fill: parent + anchors.leftMargin: 10 + text: modelData.text + color: "white" + font.pixelSize: 12 + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + onClicked: { + modelData.action() + } + } + } + } + } + } + } + } + + function toggleMenu() { + if (root.QsWindow?.window?.contentItem) { + menuWindow.anchor.rect = root.QsWindow.window.contentItem.mapFromItem(root, 0, -menuWindow.height - 5, root.width, root.height) + menuWindow.visible = !menuWindow.visible + } + } +}
\ No newline at end of file |
