#!/bin/bash # Waybar power-profiles-daemon module. # default : print the current profile as JSON (empty -> Waybar hides the module) # toggle : cycle to the next available profile, then signal Waybar to refresh # # Wired as interval:"once" + signal in config.jsonc, so the script runs exactly # once at Waybar startup and thereafter only when we signal it on click. On a # desktop the single startup run hits an unavailable PPD, prints empty, and the # module stays hidden forever with no recurring cost. # # Availability keys off the systemd unit being *enabled* rather than # `powerprofilesctl get` succeeding: PPD is D-Bus-activatable and desktop CPUs # expose EPP too, so `get` would answer on a desktop as well. The repo only # enables the service on laptops (IS_DESKTOP=0), so `is-enabled` is the honest # "is this a laptop that uses PPD" signal. SERVICE=power-profiles-daemon.service available() { command -v powerprofilesctl >/dev/null 2>&1 || return 1 systemctl is-enabled "$SERVICE" >/dev/null 2>&1 } # Available profile names in the order PPD lists them (power-saver … performance). # Profile header lines are just "name:" (optionally "* name:" for the active one); # every other line (Driver:, Degraded:, …) has text after the colon. profiles() { powerprofilesctl list 2>/dev/null | sed -nE 's/^[[:space:]]*\*?[[:space:]]*([a-z-]+):[[:space:]]*$/\1/p' } # FontAwesome glyphs (Nerd Font): f0e7 bolt, f6ad yin-yang, f06c leaf, f011 power. icon() { case "$1" in performance) printf '' ;; balanced) printf '' ;; power-saver) printf '' ;; *) printf '' ;; # power symbol, fallback esac } cycle() { mapfile -t list < <(profiles) [ "${#list[@]}" -eq 0 ] && exit 0 cur=$(powerprofilesctl get 2>/dev/null) next=0 for i in "${!list[@]}"; do if [ "${list[$i]}" = "$cur" ]; then next=$(( (i + 1) % ${#list[@]} )) break fi done powerprofilesctl set "${list[$next]}" pkill -SIGRTMIN+9 waybar } output() { if ! available; then printf '{"text":""}\n' exit 0 fi cur=$(powerprofilesctl get 2>/dev/null) [ -z "$cur" ] && { printf '{"text":""}\n'; exit 0; } printf '{"text":"%s","tooltip":"Power profile: %s\\nClick to cycle","class":"%s"}\n' \ "$(icon "$cur")" "$cur" "$cur" } case "$1" in toggle|cycle) cycle ;; *) output ;; esac