From 9aeefd209f6f35f8ee41156bc1dde65f55216408 Mon Sep 17 00:00:00 2001 From: Kajus Naujokaitis Date: Fri, 14 Feb 2025 13:18:41 +0200 Subject: [PATCH] Desktop: Taskbar per-vm volume mixer Signed-off-by: Kajus Naujokaitis --- modules/desktop/graphics/ewwbar.nix | 3 +++ .../ewwbar/config/scripts/default.nix | 18 +++++++++++++----- .../ewwbar/config/variables/default.nix | 2 +- .../ewwbar/config/widgets/default.nix | 19 +++++++++++++------ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/modules/desktop/graphics/ewwbar.nix b/modules/desktop/graphics/ewwbar.nix index bb50994b7..127ed09cf 100644 --- a/modules/desktop/graphics/ewwbar.nix +++ b/modules/desktop/graphics/ewwbar.nix @@ -117,6 +117,9 @@ in Type = "forking"; ExecStart = "${ewwScripts.ewwbar-ctrl}/bin/ewwbar-ctrl start"; ExecReload = "${ewwScripts.ewwbar-ctrl}/bin/ewwbar-ctrl reload"; + ExecStopPost = '' + bash -c "dbus-send --session --dest=org.ghaf.Audio --type=method_call --print-reply /org/ghaf/Audio org.ghaf.Audio.UnsubscribeFromDeviceUpdatedSignal" + ''; Restart = "always"; RestartSec = "100ms"; }; diff --git a/modules/desktop/graphics/ewwbar/config/scripts/default.nix b/modules/desktop/graphics/ewwbar/config/scripts/default.nix index 49af402ab..1be33c88f 100644 --- a/modules/desktop/graphics/ewwbar/config/scripts/default.nix +++ b/modules/desktop/graphics/ewwbar/config/scripts/default.nix @@ -412,7 +412,9 @@ let esac } - listen_sink_inputs() { + listen_vms() { + # Subscribing should send an initial list of available resources, so we start listening before subscribing is done + (sleep 1; dbus-send --session --dest=org.ghaf.Audio --type=method_call --print-reply /org/ghaf/Audio org.ghaf.Audio.SubscribeToDeviceUpdatedSignal > /dev/null 2>&1) & dbus-monitor --session "type='signal',interface='org.ghaf.Audio',member='DeviceUpdated'" | \ awk ' /^signal/ { @@ -439,7 +441,7 @@ let else if (isDefault == "") isDefault = $2; } !capture { - if (type == 2) print id, type, name, volume, isMuted, isDefault, event; fflush(stdout); + if (type == 4) print id, type, name, volume, isMuted, isDefault, event; fflush(stdout); } ' | while read -r id type name volume isMuted isDefault event; do # Update the JSON array based on the extracted values @@ -475,6 +477,9 @@ let pactl set-sink-input-mute "$2" 0 pactl set-sink-input-volume "$2" "$3"% ;; + set_vm_volume) + dbus-send --session --dest=org.ghaf.Audio --type=method_call /org/ghaf/Audio org.ghaf.Audio.SetDeviceVolume int32:"$2" int32:4 int32:"$3" + ;; set_source_volume) pamixer --source "$2" --unmute --set-volume "$3" ;; @@ -487,6 +492,9 @@ let mute) pamixer --toggle-mute ;; + mute_vm) + dbus-send --session --dest=org.ghaf.Audio --type=method_call /org/ghaf/Audio org.ghaf.Audio.SetDeviceMute int32:"$2" int32:4 boolean:"$3" + ;; mute_source) pamixer --source "$2" --toggle-mute ;; @@ -518,11 +526,11 @@ let get_inputs done ;; - listen_sink_inputs) - listen_sink_inputs + listen_vms) + listen_vms ;; *) - echo "Usage: $0 {get|get_output|get_input|get_outputs|get_inputs|set_volume|set_sink_input_volume|set_source_volume|set_default_source|set_default_sink|mute|mute_source|mute_sink_input|listen_output|listen_input|listen_outputs|listen_inputs|listen_sink_inputs} [args...]" + echo "Usage: $0 {get|get_output|get_input|get_outputs|get_inputs|set_volume|set_sink_input_volume|set_source_volume|set_default_source|set_default_sink|mute|mute_source|mute_sink_input|listen_output|listen_input|listen_outputs|listen_inputs|listen_vms} [args...]" ;; esac ''; diff --git a/modules/desktop/graphics/ewwbar/config/variables/default.nix b/modules/desktop/graphics/ewwbar/config/variables/default.nix index 0c83c5b58..e5b723541 100644 --- a/modules/desktop/graphics/ewwbar/config/variables/default.nix +++ b/modules/desktop/graphics/ewwbar/config/variables/default.nix @@ -20,7 +20,7 @@ writeText "variables.yuck" '' (deflisten audio_input :initial "{}" "${ewwScripts.eww-audio}/bin/eww-audio listen_input") (defpoll audio_outputs :interval "1s" "${ewwScripts.eww-audio}/bin/eww-audio get_outputs") (defpoll audio_inputs :interval "1s" "${ewwScripts.eww-audio}/bin/eww-audio get_inputs") - (defvar audio_streams "[]") + (deflisten audio_streams :initial "[]" "${ewwScripts.eww-audio}/bin/eww-audio listen_vms") (deflisten workspace :initial "1" "${ghaf-workspace}/bin/ghaf-workspace subscribe") (deflisten windows :initial "[]" "${ewwScripts.eww-windows}/bin/eww-windows listen") diff --git a/modules/desktop/graphics/ewwbar/config/widgets/default.nix b/modules/desktop/graphics/ewwbar/config/widgets/default.nix index 2386a632f..d2c2b2efd 100644 --- a/modules/desktop/graphics/ewwbar/config/widgets/default.nix +++ b/modules/desktop/graphics/ewwbar/config/widgets/default.nix @@ -24,10 +24,11 @@ writeText "widgets.yuck" '' :style "background-image: url(\"${pkgs.ghaf-artwork}/icons/launcher.svg\")"))) ;; Generic slider widget ;; - (defwidget slider [?visible ?header-left ?header-onclick ?header-right ?icon ?image ?app_icon ?settings_icon level ?onchange ?settings-onclick ?icon-onclick ?class ?min ?slider-active] + (defwidget slider [?visible ?header-left ?header-onclick ?header-right ?icon ?image ?app_icon ?settings_icon level ?onchange ?settings-onclick ?icon-onclick ?class ?min ?slider-active ?style] (box :orientation "v" :visible { visible ?: "true"} :class "''${class}" + :style "''${style}" :spacing 10 :space-evenly false (box @@ -244,11 +245,12 @@ writeText "widgets.yuck" '' audio_output.volume_percentage <= 75 ? "${pkgs.ghaf-artwork}/icons/volume-2.svg" : "${pkgs.ghaf-artwork}/icons/volume-3.svg" } :icon-onclick "${ewwScripts.eww-audio}/bin/eww-audio mute &" :settings_icon "adjustlevels" + :settings-onclick "''${EWW_CMD} update volume-mixer-visible=''${!volume-mixer-visible} &" :level { audio_output.is_muted == "true" ? "0" : audio_output.volume_percentage } :onchange "${ewwScripts.eww-audio}/bin/eww-audio set_volume {} &" (audio_output_selector) (box :orientation "v" - (label :text "No audio streams" :visible {arraylength(audio_streams) == 0} :halign "center" :valign "center") + (label :text "No active VM audio streams" :style "margin: 10px 0;" :visible {arraylength(audio_streams) == 0} :halign "center" :valign "center") (volume_mixer :visible {arraylength(audio_streams) > 0}) )) (slider_with_children @@ -336,20 +338,25 @@ writeText "widgets.yuck" '' (scroll :hscroll "false" :vscroll "true" + :style "margin: 20px 0;" + :height { arraylength(audio_streams) <= 3 ? 80 * arraylength(audio_streams) : 240 } :visible { visible ?: "true" } - :height { 50 * min(4,arraylength(audio_streams)) } - (box :orientation "v" :space-evenly true :spacing 10 + (box + :orientation "v" + :space-evenly true + :spacing 10 (for entry in {audio_streams} (slider :class "qs-slider" + :style "padding: 0 15px 0 0;" :header-left {entry.name} :level {entry.muted == "true" ? "0" : entry.level} :app_icon {entry.icon_name != "" ? entry.icon_name : "icon-missing"} :image { entry.muted == "true" || entry.level == 0 ? "${pkgs.ghaf-artwork}/icons/volume-0.svg" : entry.level <= 25 ? "${pkgs.ghaf-artwork}/icons/volume-1.svg" : entry.level <= 75 ? "${pkgs.ghaf-artwork}/icons/volume-2.svg" : "${pkgs.ghaf-artwork}/icons/volume-3.svg" } - :onchange "${ewwScripts.eww-audio}/bin/eww-audio set_sink_input_volume ''${entry.id} {} &" - :icon-onclick "${ewwScripts.eww-audio}/bin/eww-audio mute_sink_input ''${entry.id} {} &") + :onchange "${ewwScripts.eww-audio}/bin/eww-audio set_vm_volume ''${entry.id} {} &" + :icon-onclick "${ewwScripts.eww-audio}/bin/eww-audio mute_vm ''${entry.id} ''${!entry.muted} &") ) ) )