From 8dd32e2632aec21ddd657869dc2beb7bb602c9d1 Mon Sep 17 00:00:00 2001 From: Sem Date: Sun, 31 May 2026 20:37:30 +0200 Subject: [PATCH] Add volume indicator --- hypr/autostart.lua | 10 ++++ hypr/colors.lua | 90 ++++++++++++++-------------- hypr/hyprland.lua | 10 +++- quickshell/services/AudioService.qml | 52 ++++++++++++++++ quickshell/ui/AudioIcon.qml | 53 ++++++++++++++++ quickshell/ui/TopBar.qml | 6 ++ 6 files changed, 175 insertions(+), 46 deletions(-) create mode 100644 quickshell/services/AudioService.qml create mode 100644 quickshell/ui/AudioIcon.qml diff --git a/hypr/autostart.lua b/hypr/autostart.lua index e69de29..5bac971 100644 --- a/hypr/autostart.lua +++ b/hypr/autostart.lua @@ -0,0 +1,10 @@ +-- exec-once = hyprpaper # wallpaper +-- exec-once = cava -p ~/.config/cava/config + +hl.on("hyprland.start", function() + hl.exec_cmd("/usr/lib/hyprpolkitagent/hyprpolkitagent") + hl.exec_cmd("/usr/bin/qs &") + hl.exec_cmd("awww-daemon") + hl.exec_cmd("hyprsunset") + hl.exec_cmd("qs -c overview") +end) diff --git a/hypr/colors.lua b/hypr/colors.lua index 8fe412a..8236e5c 100644 --- a/hypr/colors.lua +++ b/hypr/colors.lua @@ -1,104 +1,104 @@ return { - image = "/home/sem/Pictures/wallpapers/a_person_riding_a_bicycle_on_a_hill_with_sunflowers.jpeg", + image = "/home/sem/Pictures/wallpapers/DSC00789.jpg", - background = "0xff0f1510", + background = "0xff121318", error = "0xffff5449", error_container = "0xff7b0007", - inverse_on_surface = "0xff606660", + inverse_on_surface = "0xff64646a", - inverse_primary = "0xff508d65", + inverse_primary = "0xff737db7", - inverse_surface = "0xffdfe4dd", + inverse_surface = "0xffe3e1e9", - on_background = "0xff5e645e", + on_background = "0xff626268", on_error = "0xff5c0003", on_error_container = "0xffff7d70", - on_primary = "0xff0c4f2d", + on_primary = "0xff374176", - on_primary_container = "0xff73b286", + on_primary_container = "0xff97a0dd", - on_primary_fixed = "0xff93d2a5", + on_primary_fixed = "0xffb7c0ff", - on_primary_fixed_variant = "0xff6fad83", + on_primary_fixed_variant = "0xff939dd9", - on_secondary = "0xff1b2e21", + on_secondary = "0xff26293b", - on_secondary_container = "0xff94a997", + on_secondary_container = "0xffa0a2b9", - on_secondary_fixed = "0xffb3cab6", + on_secondary_fixed = "0xffc1c2da", - on_secondary_fixed_variant = "0xff90a593", + on_secondary_fixed_variant = "0xff9d9fb5", - on_surface = "0xff9fa49e", + on_surface = "0xffa3a2a9", - on_surface_variant = "0xff7d857d", + on_surface_variant = "0xff82828c", - on_tertiary = "0xff002e38", + on_tertiary = "0xff3d2037", - on_tertiary_container = "0xff80abb7", + on_tertiary_container = "0xffc198b5", - on_tertiary_fixed = "0xffa0cbd8", + on_tertiary_fixed = "0xffe3b7d5", - on_tertiary_fixed_variant = "0xff7da7b3", + on_tertiary_fixed_variant = "0xffbd94b1", - outline = "0xff4e564f", + outline = "0xff53535c", - outline_variant = "0xff343c35", + outline_variant = "0xff393942", - primary = "0xff609e74", + primary = "0xff838dc8", - primary_container = "0xff004424", + primary_container = "0xff2c366b", - primary_fixed = "0xff1e5c38", + primary_fixed = "0xff434d84", - primary_fixed_dim = "0xff004424", + primary_fixed_dim = "0xff2c366b", scrim = "0xff000000", - secondary = "0xff819684", + secondary = "0xff8d8fa6", - secondary_container = "0xff2b3e30", + secondary_container = "0xff36394c", - secondary_fixed = "0xff425647", + secondary_fixed = "0xff4d5064", - secondary_fixed_dim = "0xff2b3e30", + secondary_fixed_dim = "0xff36394c", shadow = "0xff000000", - source_color = "0xff52735b", + source_color = "0xff1c1d25", - surface = "0xff0f1510", + surface = "0xff121318", - surface_bright = "0xff353b36", + surface_bright = "0xff39393f", - surface_container = "0xff1c211c", + surface_container = "0xff1f1f25", - surface_container_high = "0xff262b27", + surface_container_high = "0xff29292f", - surface_container_highest = "0xff313631", + surface_container_highest = "0xff34343a", - surface_container_low = "0xff181d19", + surface_container_low = "0xff1b1b21", - surface_container_lowest = "0xff0a0f0b", + surface_container_lowest = "0xff0d0e13", - surface_dim = "0xff0f1510", + surface_dim = "0xff121318", - surface_tint = "0xff95d5a7", + surface_tint = "0xffbac3ff", - surface_variant = "0xff414942", + surface_variant = "0xff46464f", - tertiary = "0xff6d97a3", + tertiary = "0xffac85a1", - tertiary_container = "0xff11404a", + tertiary_container = "0xff4f3048", - tertiary_fixed = "0xff2c5762", + tertiary_fixed = "0xff684660", - tertiary_fixed_dim = "0xff11404a", + tertiary_fixed_dim = "0xff4f3048", } \ No newline at end of file diff --git a/hypr/hyprland.lua b/hypr/hyprland.lua index 0a06f87..1a55700 100644 --- a/hypr/hyprland.lua +++ b/hypr/hyprland.lua @@ -12,7 +12,7 @@ local mainMod = "SUPER" -- require("monitors") local colors = require("colors") -- require("programs") -require("autostart") +-- require("autostart") require("environment") require("look-and-feel") require("input") @@ -22,6 +22,14 @@ require("keybindings") -- exec-once = hyprpaper # wallpaper -- exec-once = cava -p ~/.config/cava/config +hl.on("hyprland.start", function() + hl.exec_cmd("/usr/lib/hyprpolkitagent/hyprpolkitagent") + hl.exec_cmd("/usr/bin/qs &") + hl.exec_cmd("awww-daemon") + hl.exec_cmd("hyprsunset") + hl.exec_cmd("qs -c overview") +end) + -- monitors --############### diff --git a/quickshell/services/AudioService.qml b/quickshell/services/AudioService.qml new file mode 100644 index 0000000..8beb199 --- /dev/null +++ b/quickshell/services/AudioService.qml @@ -0,0 +1,52 @@ +import QtQuick +import Quickshell.Io + +// service to get the current volume and handle volume changes +Item { + id: root + signal volumeChanged(int volume) + + // process to get the volume level: first active playback stream, falling back to the sink + Process { + id: audioVolumeProcess + command: ["sh", "-c", "pactl list sink-inputs | grep -m1 'Volume:' | grep -oP '\\d+(?=%)' | head -1 || wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk '{printf \"%d\", $2 * 100}'"] + stdout: StdioCollector { + onStreamFinished: { + if (this.text) { + const volume = parseInt(this.text.trim()); + root.volumeChanged(volume); + } + } + } + } + + Process { + id: volumeUpProcess + command: ["sh", "-c", "pactl list sink-inputs | awk '/^Sink Input #/{sub(/^Sink Input #/,x);id=$1;got=0} /^[[:space:]]+Volume:/ && id && !got{match($0,/[0-9]+%/);if(substr($0,RSTART,RLENGTH-1)+0<100)print id;got=1}' | xargs -r -I{} pactl set-sink-input-volume {} +1%"] + } + + Process { + id: volumeDownProcess + command: ["sh", "-c", "pactl list short sink-inputs | awk '{print $1}' | xargs -r -I{} pactl set-sink-input-volume {} -1%"] + } + + function volumeUp() { + volumeUpProcess.running = true; + audioVolumeProcess.running = true; + } + + function volumeDown() { + volumeDownProcess.running = true; + audioVolumeProcess.running = true; + } + + // timer to periodically check the volume level + Timer { + interval: 5000 + running: true + repeat: true + onTriggered: audioVolumeProcess.running = true + } + + Component.onCompleted: audioVolumeProcess.running = true +} \ No newline at end of file diff --git a/quickshell/ui/AudioIcon.qml b/quickshell/ui/AudioIcon.qml new file mode 100644 index 0000000..69c17e9 --- /dev/null +++ b/quickshell/ui/AudioIcon.qml @@ -0,0 +1,53 @@ +import Quickshell +import Quickshell.Io +import QtQuick +import QtQuick.Layouts + +import "../constants" +import "../services" + +Text { + id: root + required property TopBar parentWindow + + property string lowVolumeIconGlyph: "\uf027" + property string highVolumeIconGlyph: "\uf028" + property string iconGlyph: lowVolumeIconGlyph + property string volumeText: "" + property list volumeDudes: ["⸝(°-°)⸜","ヽ(°∘°)ノ","ヽ(°o°)ノ","ヽ(°O°)ノ","ヽ(°ᗜ°)ノ","ヽ(°〇°)ノ","ᕙ( ᗒᗣᗕ )ᕗ"] + property int volumeDudeIndex: 0 + property int dudeStep: 100 / volumeDudes.length + + property AudioService audioService: AudioService { + onVolumeChanged: function (volume) { + var dudeIndex = Math.min(Math.floor(volume / root.dudeStep), root.volumeDudes.length - 1); + root.text = volume + "% " + root.volumeDudes[dudeIndex]; + } + } + + text: iconGlyph + color: Colors.md3.on_primary_fixed + + font { + family: Constants.fontFamily + pixelSize: Constants.fontSize + bold: false + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + onClicked: { + // TODO open volume control panel + } + + onWheel: function (wheel) { + if (wheel.angleDelta.y > 0) { + root.audioService.volumeUp(); + } else { + root.audioService.volumeDown(); + } + } + } +} diff --git a/quickshell/ui/TopBar.qml b/quickshell/ui/TopBar.qml index 3231046..3c4334a 100644 --- a/quickshell/ui/TopBar.qml +++ b/quickshell/ui/TopBar.qml @@ -67,6 +67,12 @@ Item { parentWindow: root } + LineSeparator {} + + AudioIcon { + parentWindow: root + } + LineSeparator {} BarText {