From d5af82bb9bae08a058a87df8bd416b32da91f29b Mon Sep 17 00:00:00 2001 From: zack Date: Mon, 7 Apr 2025 15:36:47 -0400 Subject: [PATCH] waybar updates --- homes/x86_64-linux/zoey@earth/default.nix | 4 +- modules/home/apps/helpers/waybar/bar.sh | 79 +++++++ modules/home/apps/helpers/waybar/default.nix | 211 +++++++------------ modules/home/apps/helpers/waybar/style.css | 194 +++++++++++++++++ modules/nixos/hardware/audio/default.nix | 37 ++++ 5 files changed, 394 insertions(+), 131 deletions(-) create mode 100644 modules/home/apps/helpers/waybar/bar.sh create mode 100644 modules/home/apps/helpers/waybar/style.css diff --git a/homes/x86_64-linux/zoey@earth/default.nix b/homes/x86_64-linux/zoey@earth/default.nix index 61c204c..ba70869 100644 --- a/homes/x86_64-linux/zoey@earth/default.nix +++ b/homes/x86_64-linux/zoey@earth/default.nix @@ -246,8 +246,8 @@ # falloff = 0.0; }; input = { - method = "pipewire"; - source = "497"; + method = "pulse"; + source = "alsa_output.usb-MOTU_M4_M4MA03F7DV-00.HiFi__Line1__sink.monitor"; }; # output = { # method = "ncurses"; diff --git a/modules/home/apps/helpers/waybar/bar.sh b/modules/home/apps/helpers/waybar/bar.sh new file mode 100644 index 0000000..3c567d8 --- /dev/null +++ b/modules/home/apps/helpers/waybar/bar.sh @@ -0,0 +1,79 @@ +#! /bin/bash + +# --- Configuration --- +bar="▁▂▃▄▅▆▇█" +# Number of bars Cava should output +num_bars=8 +# Max height for ASCII output (should match length of bar string - 1) +ascii_max_range=$((${#bar} - 1)) +# Temporary config file path (using PID $$ for uniqueness) +config_file="/tmp/polybar_cava_config_$$" + +# --- Argument Handling --- +if [ $# -lt 1 ]; then + # Print error message to stderr + echo "Error: Please provide the PulseAudio source name as an argument." >&2 + echo "Usage: $0 " >&2 + echo "Example: $0 alsa_output.pci-0000_00_1f.3.analog-stereo.monitor" >&2 + echo "You can find source names using: pactl list sources | grep 'Name:'" >&2 + exit 1 +fi + +# Assign the first argument to the pulse_source variable +pulse_source="$1" + +# --- Functions --- + +# Function to clean up the temporary config file on exit +cleanup() { + rm -f "$config_file" +} + +# --- Main Script --- + +# Set trap to call cleanup function on script exit (including Ctrl+C) +trap cleanup EXIT + +# Build the sed dictionary string to replace numbers with bar characters +dict="s/;//g;" +i=0 +# Use modern arithmetic expansion and loop condition +while ((i < ${#bar})); do + # Safely append to the dictionary string + dict="${dict}s/$i/${bar:$i:1}/g;" + # Use modern arithmetic increment + ((i++)) +done + +# Create the Cava configuration file using printf for safety +# Note: Using the pulse_source variable passed as an argument +printf '%s\n' " +[general] +bars = $num_bars + +[input] +method = pulse +source = \"$pulse_source\" + +[output] +method = raw +raw_target = /dev/stdout +data_format = ascii +channels = mono +mono_option = average +ascii_max_range = $ascii_max_range +" >"$config_file" || { + echo "Error: Failed to write Cava config." >&2 + exit 1 +} # Exit if write fails + +# Run Cava with the generated config and process its output +# Use 'exec cava' if you don't need the script to do anything after cava finishes +cava -p "$config_file" | while IFS= read -r line; do + # Translate numbers to bars using sed + echo "$line" | sed "$dict" +done + +# The trap will handle cleanup automatically here +# If 'exec cava' was used above, this part is unreachable +exit 0 diff --git a/modules/home/apps/helpers/waybar/default.nix b/modules/home/apps/helpers/waybar/default.nix index afe4848..b30cb86 100644 --- a/modules/home/apps/helpers/waybar/default.nix +++ b/modules/home/apps/helpers/waybar/default.nix @@ -368,126 +368,11 @@ in { systemd.enable = true; systemd.target = "graphical-session.target"; style = '' - * { - min-height: 0; - min-width: 0; - font-family: Cantarell; - font-size: 16px; - font-weight: 600; - } - - window#waybar { - transition-property: background-color; - transition-duration: 0.5s; - /* background-color: #1e1e2e; */ - /* background-color: #181825; */ - background-color: #11111b; - /* background-color: rgba(24, 24, 37, 0.6); */ - } - - #workspaces button { - padding: 0.3rem 0.6rem; - margin: 0.4rem 0.25rem; - border-radius: 6px; - /* background-color: #181825; */ - background-color: #1e1e2e; - color: #cdd6f4; - } - - #workspaces button:hover { - color: #1e1e2e; - background-color: #cdd6f4; - } - - #workspaces button.active { - background-color: #1e1e2e; - color: #89b4fa; - } - - #workspaces button.urgent { - background-color: #1e1e2e; - color: #f38ba8; - } - - #clock, - #pulseaudio, - #custom-logo, - #custom-power, - #custom-spotify, - #custom-notification, - #cpu, - #tray, - #memory, - #window, - #mpd - #mpris { - padding: 0.3rem 0.6rem; - margin: 0.4rem 0.25rem; - border-radius: 6px; - /* background-color: #181825; */ - background-color: #1e1e2e; - } - - #mpris.playing { - color: #a6e3a1; - } - - #mpris.paused { - color: #9399b2; - } - - #custom-sep { - padding: 0px; - color: #585b70; - } - - window#waybar.empty #window { - background-color: transparent; - } - - #cpu { - color: #94e2d5; - } - - #memory { - color: #cba6f7; - } - - #clock { - color: #74c7ec; - } - - #clock.simpleclock { - color: #89b4fa; - } - - #window { - color: #cdd6f4; - } - - #pulseaudio { - color: #b4befe; - } - - #pulseaudio.muted { - color: #a6adc8; - } - - #custom-logo { - color: #89b4fa; - } - - #custom-power { - color: #f38ba8; - } - - tooltip { - background-color: #181825; - border: 2px solid #89b4fa; - } + ${builtins.readFile ./style.css} ''; - - settings = { + settings = let + cava = pkgs.writeShellScriptBin "cava" "${builtins.readFile ./bar.sh}"; + in { mainBar = { layer = "bottom"; position = "top"; @@ -497,12 +382,17 @@ in { "gtk-layer-shell" = true; passthrough = false; "fixed-center" = true; - "modules-left" = ["hyprland/workspaces" "hyprland/window" "niri/workspaces" "niri/window"]; + "modules-left" = ["hyprland/workspaces" "hyprland/window" "niri/workspaces" "niri/window" "network#speed" "custom/cava-system" "custom/cava-tt"]; "modules-center" = ["mpris"]; "modules-right" = [ "cpu" "memory" + "temperature" + "custom/gpu-usage" + "custom/gpu-mem" + "custom/gpu-temp" "pulseaudio" + "custom/weather" "clock" "clock#simpleclock" "tray" @@ -511,7 +401,7 @@ in { ]; "custom/spotify" = { - format = " {}"; + format = "{}"; "return-type" = "json"; "on-click" = "playerctl -p spotify play-pause"; "on-click-right" = "spotifatius toggle-liked"; @@ -558,6 +448,60 @@ in { }; }; + "custom/cava-system" = { + format = "{}"; + exec = "${cava}/bin/cava alsa_output.usb-MOTU_M4_M4MA03F7DV-00.HiFi__Line1__sink.monitor"; + }; + + "custom/cava-tt" = { + format = "{}"; + exec = "${cava}/bin/cava cava-line-in.monitor"; + }; + + "custom/weather" = { + "format" = "{}°F"; + interval = 3600; + exec = "${lib.getExe pkgs.wttrbar} --location 'Holland,MI' --fahrenheit --mph"; + return-type = "json"; + }; + + "custom/gpu-temp" = { + interval = 10; + exec = "nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits"; + format = "{}°C "; + tooltip = false; + }; + + "custom/gpu-mem" = { + interval = 10; + exec = "nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits | awk '{printf \"%.1f\", $1/1024}'"; + format = "{}Gi"; + tooltip = false; + }; + + "custom/gpu-usage" = { + interval = 2; + exec = "nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits"; + format = "{}%"; + tooltip = false; + }; + + "network#speed" = { + interval = 1; + format = "{ifname}%%"; + format-wifi = " {bandwidthDownBytes}  {bandwidthUpBytes}"; + format-ethernet = " {bandwidthDownBytes}  {bandwidthUpBytes} "; + format-disconnected = "󰌙"; + tooltip-format = "{ipaddr}"; + format-linked = "󰈁 {ifname} (No IP)"; + tooltip-format-wifi = "{essid} {icon} {signalStrength}%"; + tooltip-format-ethernet = "{ifname} 󰌘"; + tooltip-format-disconnected = "󰌙 Disconnected"; + max-length = 22; + min-length = 20; + format-icons = ["󰤯" "󰤟" "󰤢" "󰤥" "󰤨"]; + }; + "hyprland/workspaces" = { "on-click" = "activate"; format = "{id}"; @@ -577,11 +521,19 @@ in { "clock#simpleclock" = { tooltip = false; - format = " {:%H:%M}"; + format = "{:%H:%M}"; + }; + + "temperature" = { + hwmon-path-abs = "/sys/devices/platform/asus-ec-sensors/hwmon/hwmon3"; + input_filename = "temp2_input"; + critical-threshold = 70; + format = "{temperatureC}°C "; + format-critical = "󰸁 {temperatureC}°C"; }; clock = { - format = " {:L%a %d %b}"; + format = "{:L%a %d %b}"; calendar = { format = { days = "{}"; @@ -598,21 +550,22 @@ in { }; cpu = { - format = " {usage}%"; + format = "{usage}%"; tooltip = true; interval = 1; }; memory = { - format = " {used:0.1f}Gi"; + interval = 1; + format = "{used:0.1f}Gi"; }; pulseaudio = { - format = "{icon} {volume}%"; - "format-muted" = " muted"; + format = "{icon} {volume}%"; + "format-muted" = ""; "format-icons" = { - headphone = ""; - default = [" " " " " "]; + headphone = ""; + default = ["" ""]; }; "on-click" = "pavucontrol"; }; diff --git a/modules/home/apps/helpers/waybar/style.css b/modules/home/apps/helpers/waybar/style.css new file mode 100644 index 0000000..8c7c75f --- /dev/null +++ b/modules/home/apps/helpers/waybar/style.css @@ -0,0 +1,194 @@ +* { + font-family: Iosevka Nerd Font; + min-height: 14px; + font-size: 14px; + border: none; + border-radius: 6px; + padding: 4px; + margin: 0; + box-shadow: none; + text-shadow: none; + background-color: transparent; +} + +window#waybar { + padding: 8px; + background-color: @crust; +} + +#custom-cava-system, #custom-cava-tt { + color: #cba6f7; + border-left: 0px; + border-right: 0px; + padding: 6px; + font-family: 'bargraph'; + background: @base; + margin: 0px 2px; +} + +#window { + padding: 0px 8px 0px 8px; + background-color: @base; +} + +#cpu { + color: @green; + padding: 0px 12px; + background: @base; + margin-left: 1px; + border-radius: 6px 0 0 6px; +} + +#memory { + color: @green; + padding: 0px 12px; + background: @base; + margin: 0; + border-radius: 0; +} + +#temperature { + color: @green; + padding: 0px 12px; + background: @base; + margin-right: 1px; + border-radius: 0 6px 6px 0; +} + +#custom-gpu-temp { + padding: 0px 12px; + margin-right: 2px; + color: @blue; + background: @base; + border-radius: 0 6px 6px 0; +} + +#custom-gpu-mem { + padding: 0px 12px; + margin: 0; + color: @blue; + background: @base; + border-radius: 0; +} + +#custom-gpu-usage { + padding: 0px 12px; + margin-left: 1px; + color: @blue; + background: @base; + border-radius: 6px 0 0 6px; +} + +#tray { + background: @base; + padding: 4px; +} + +/* General Styling */ +tooltip, +menu, +#workspaces, +#clock, +#pulseaudio, +#backlight, +#bluetooth, +#network, +#battery, +#custom-notification, #custom-power, +#custom-weather { + background: @base; + padding: 8px 8px; + min-width: 28px; + margin-left: 1px; + margin-right: 1px; + border-radius: 6px; +} + +#custom-power { + color: @red; +} + +#workspaces { + background: @base; + margin: 0; + margin-left: 3px; + padding: 0; + font-weight: bold; + font-style: normal; + opacity: 1; + font-size: 16px; + color: #1e1; + border-radius: 6px; +} + +#workspaces button { + padding: 0px 5px; + margin: 3px; + border-radius: 6px; + border: none; + color: #f5e0dc; + /* background-color: #1e1e2e; */ + transition: all 0.3s ease-in-out; + opacity: 0.4; +} + +#workspaces button.active { + color: #1e1e2e; + background: #cba6f7; + min-width: 20px; + opacity: 1; +} + +#workspaces button:hover { + color: #c3dee5; + background: #1e1e2e; + opacity: 1; + animation: none; +} + +#clock { + padding: 0 15px; + color: @lavender; + border-radius: 6px; +} + +#custom-launcher { + font-size: 18px; + transition: none; + padding: 0px 10px; + margin-right: 2px; + background: @base; + color: rgba(137, 220, 235, 1); + border-radius: 0 6px 6px 0; +} + +#pulseaudio { + padding: 0 8px; + margin-right: 1px; + color: @beige; + border-radius: 6px 6px; +} + +#bluetooth, +#network { + color: #cba6f7; + border-radius: 6px; + margin: 0 1px; +} + +#network.speed { + background: @base; + padding: 0px 6px; + min-width: 10px; + color: @teal; + border-radius: 6px; +} + +#network { + min-width: 30px; + padding: 0 7px 0 2px; + /* margin: 0 2px; */ + border-radius: 6px; + /* border-radius: 0 6px 6px 0; */ +} + diff --git a/modules/nixos/hardware/audio/default.nix b/modules/nixos/hardware/audio/default.nix index 043a134..ec1a650 100644 --- a/modules/nixos/hardware/audio/default.nix +++ b/modules/nixos/hardware/audio/default.nix @@ -23,5 +23,42 @@ in { wireplumber.enable = true; jack.enable = true; }; + + systemd.user.services.cava-combine-inputs = { + description = "Combine MOTU M4 Line Inputs L/R for Cava"; + + # Ensure this runs after pipewire-pulse is started + after = ["pipewire-pulse.service"]; + wants = ["pipewire-pulse.service"]; # Start pipewire-pulse if not already running + + # Make it part of the default user session target + wantedBy = ["default.target"]; + + # Service configuration details + serviceConfig = { + Type = "oneshot"; # Run the command once and exit + # Use RemainAfterExit if you want the service to show as 'active' after running + # RemainAfterExit = true; + + # Command to execute. Use full paths for robustness. + # We use sh -c to run multiple commands sequentially. + # pactl is provided by the pulseaudio package. + ExecStart = '' + ${pkgs.runtimeShell} -c ' + echo "Attempting to load Cava combine modules..." + # Load null sink (returns non-zero if it fails AND module doesn't exist) + ${pkgs.pulseaudio}/bin/pactl load-module module-null-sink sink_name=cava-line-in sink_properties=device.description="Cava_Combined_LineIn" + # Load loopbacks (returns non-zero on failure) + ${pkgs.pulseaudio}/bin/pactl load-module module-loopback source="alsa_input.usb-MOTU_M4_M4MA03F7DV-00.HiFi__Line3__source" sink=cava-line-in latency_msec=10 + ${pkgs.pulseaudio}/bin/pactl load-module module-loopback source="alsa_input.usb-MOTU_M4_M4MA03F7DV-00.HiFi__Line4__source" sink=cava-line-in latency_msec=10 + echo "Finished loading Cava combine modules (ignore errors if already loaded)." + # Exit successfully even if modules were already loaded (pactl might return 0) + exit 0 + ''; + + # Prevent service from restarting automatically + Restart = "no"; + }; + }; }; }