omarchy-audio-output-sink follows a DSP sink to the physical sink through the DSP's playback stream. EasyEffects 8 has no such stream: its output node links its ports straight to the sink's playback ports, so the search found nothing and the volume keys, the bar's audio panel and the output switcher all acted on easyeffects_sink itself. That sink's volume is inert -- its monitor, which EasyEffects reads, does not follow it -- so the OSD moved while the speakers did not. Follow the port links to the alsa_output sink instead, and when EasyEffects is idle and has dropped them, use the output device its settings name, if that sink exists. Filter-chain tunings keep resolving through their stream as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
88 lines
3.2 KiB
Bash
Executable File
88 lines
3.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Print the sink whose volume and mute a given output really uses
|
|
# omarchy:args=[sink-name]
|
|
# omarchy:group=audio
|
|
# omarchy:examples=omarchy audio output sink | omarchy audio output sink omarchy_speaker_tuning
|
|
|
|
set -uo pipefail
|
|
|
|
# A DSP sink -- a speaker tuning filter-chain, or EasyEffects -- can be the
|
|
# selected output without being where loudness lives. Changing its volume alters
|
|
# the level going *into* the processing: the display moves while the speakers do
|
|
# not, and on a chain with a compressor or limiter the tone changes too. Resolve
|
|
# through it to the physical sink it feeds.
|
|
#
|
|
# With no argument this resolves the current default output, so when headphones or
|
|
# HDMI are selected it returns those, not the speakers a tuning happens to front.
|
|
# Callers that need to describe some *other* output -- an output switcher naming
|
|
# the next one in the rotation -- pass that sink explicitly.
|
|
|
|
sink="${1:-$(pactl get-default-sink 2>/dev/null)}"
|
|
|
|
if [[ -z $sink || $sink == alsa_output.* ]]; then
|
|
printf '%s\n' "$sink"
|
|
exit 0
|
|
fi
|
|
|
|
# A DSP sink feeds its physical output through a stream of its own; follow that
|
|
# stream down to the sink underneath.
|
|
downstream="$(pactl list sink-inputs 2>/dev/null |
|
|
awk -v virt="$sink" '
|
|
/^Sink Input #/ {target = ""}
|
|
/^[[:space:]]*Sink:/ {target = $2}
|
|
/node\.name = / {
|
|
name = $0
|
|
sub(/.*node\.name = "/, "", name)
|
|
sub(/"$/, "", name)
|
|
if (index(name, virt) == 1 && target != "") {print target; exit}
|
|
}
|
|
/application\.name = "EasyEffects"/ {
|
|
if (virt == "easyeffects_sink" && target != "") {print target; exit}
|
|
}')"
|
|
|
|
if [[ -n $downstream ]]; then
|
|
name="$(pactl list sinks short 2>/dev/null |
|
|
awk -v id="$downstream" '$1 == id {print $2; exit}')"
|
|
if [[ -n $name ]]; then
|
|
printf '%s\n' "$name"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# EasyEffects 8 does not play into the physical sink through a stream of its
|
|
# own: its output node links its ports straight to the sink's playback ports,
|
|
# so the sink-input search above finds nothing and the keys would move the
|
|
# EasyEffects sink -- whose volume its monitor, the input of the processing,
|
|
# does not follow. Follow the port links instead: the first alsa_output sink
|
|
# any EasyEffects output port is linked to.
|
|
if [[ $sink == "easyeffects_sink" ]]; then
|
|
linked="$(pw-link -l 2>/dev/null |
|
|
awk '
|
|
/^[^ ]/ {src = $0}
|
|
/^[[:space:]]*\|->/ {
|
|
if (src ~ /^ee_/ && $2 ~ /^alsa_output\..*:playback_/) {
|
|
sub(/:playback_.*$/, "", $2); print $2; exit
|
|
}
|
|
}')"
|
|
|
|
# Idle, EasyEffects drops those links: fall back to the output device it is
|
|
# configured to feed, when that sink exists.
|
|
if [[ -z $linked ]]; then
|
|
configured="$(sed -n 's/^outputDevice=//p' \
|
|
"${XDG_CONFIG_HOME:-$HOME/.config}/easyeffects/db/easyeffectsrc" 2>/dev/null)"
|
|
if [[ -n $configured ]] && pactl list sinks short 2>/dev/null | awk '{print $2}' | grep -qx "$configured"; then
|
|
linked="$configured"
|
|
fi
|
|
fi
|
|
|
|
if [[ -n $linked ]]; then
|
|
printf '%s\n' "$linked"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Nothing resolvable downstream -- the DSP sink may simply be idle and unlinked.
|
|
# Fall back to the sink itself so callers still have something to act on.
|
|
printf '%s\n' "$sink"
|