aboutsummaryrefslogtreecommitdiffstats
path: root/home/quickshell/bar/blocks/Sound.qml
diff options
context:
space:
mode:
authorPetri Hienonen <petri.hienonen@gmail.com>2024-05-23 13:56:00 +0300
committerPetri Hienonen <petri.hienonen@gmail.com>2025-11-30 12:29:57 +0200
commit08297376a85a1719518507e54fca9de954d2376a (patch)
tree3b9c58304b40248533bbb2bb5b7bad2da9da1ff0 /home/quickshell/bar/blocks/Sound.qml
parent75c2af4aedd2ac5c2cfc74b346625fa4b265541d (diff)
downloadnixos-08297376a85a1719518507e54fca9de954d2376a.tar.zst
Agenix configuration
Diffstat (limited to 'home/quickshell/bar/blocks/Sound.qml')
-rw-r--r--home/quickshell/bar/blocks/Sound.qml176
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