Ask RTKit directly for the speaker tuning's realtime priority (#12958)
The tuning host loaded module-rt with default arguments, so it asked for realtime through xdg-desktop-portal. A portal started before rtkit was installed reports a realtime budget of zero. module-rt applies that as a hard RLIMIT_RTTIME of 0, RTKit still makes the data thread SCHED_RR, and the kernel kills the host with SIGKILL as soon as audio plays; systemd restarts it every two seconds and the speakers stay silent until the next login. Set rtportal.enabled = false, as the stock pipewire.conf does. The host is a user service in the same session as the PipeWire daemon and has no reason to go through the portal. The host config is only copied by `omarchy-audio-tuning on`, so a migration replaces an installed copy that is still Omarchy's own with the old setting, and restarts the host if it runs. It does not call `on`, which would overwrite a tuning graph another tool wrote under the same name. Co-authored-by: Michael de By <contact@michaeldeby.nl>
This commit is contained in:
1 parent
245630786c
commit
baf0287138
3 files changed
+83
-2
No files matched your search
@@ -23,9 +23,12 @@ context.spa-libs = {
|
||||
}
|
||||
|
||||
context.modules = [
|
||||
# Boost the audio thread priority.
|
||||
# Boost the audio thread priority. Ask RTKit directly, as pipewire.conf
|
||||
# does: a portal started before rtkit existed reports a realtime budget of
|
||||
# zero, which becomes a hard RLIMIT_RTTIME of 0 while RTKit still makes the
|
||||
# data thread realtime, and the kernel then kills the host once audio plays.
|
||||
{ name = libpipewire-module-rt
|
||||
args = { }
|
||||
args = { rtportal.enabled = false }
|
||||
flags = [ ifexists nofail ]
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
echo "Ask RTKit directly for the speaker tuning's realtime priority"
|
||||
|
||||
# The tuning host asked for realtime through xdg-desktop-portal. A portal started
|
||||
# before rtkit was installed reports a realtime budget of zero; module-rt applies
|
||||
# it as a hard RLIMIT_RTTIME of 0, RTKit still makes the data thread realtime, and
|
||||
# the kernel kills the host as soon as audio plays. The host config is only copied
|
||||
# by `omarchy-audio-tuning on`, so an installed tuning keeps the old one until
|
||||
# replaced here.
|
||||
#
|
||||
# Only Omarchy's own copy with the old setting is replaced. A community
|
||||
# calibrator can host its graph under the same file name, and a tuning graph is
|
||||
# never touched: `omarchy-audio-tuning on` would overwrite one it did not write.
|
||||
host_config="${XDG_CONFIG_HOME:-$HOME/.config}/pipewire/omarchy-speaker-tuning.conf"
|
||||
host_source="$OMARCHY_PATH/default/audio/filter-chain-host.conf"
|
||||
|
||||
if [[ -f $host_config && ! -L $host_config ]] &&
|
||||
grep -qx '# Host config for the Omarchy speaker tuning.' "$host_config" &&
|
||||
grep -q 'args = { }' "$host_config"; then
|
||||
install -Dm644 "$host_source" "$host_config"
|
||||
# A restart ends playback for a moment, so only a running host is restarted.
|
||||
systemctl --user try-restart omarchy-speaker-tuning.service >/dev/null 2>&1 || true
|
||||
fi
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
tmp_dir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp_dir"' EXIT
|
||||
mkdir -p "$tmp_dir/bin"
|
||||
export XDG_CONFIG_HOME="$tmp_dir/config" OMARCHY_PATH="$ROOT" CALL_LOG="$tmp_dir/calls"
|
||||
export PATH="$tmp_dir/bin:$PATH"
|
||||
|
||||
cat > "$tmp_dir/bin/systemctl" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\n' "$*" >> "$CALL_LOG"
|
||||
SH
|
||||
chmod +x "$tmp_dir/bin/systemctl"
|
||||
|
||||
migration="$ROOT/migrations/1790114905.sh"
|
||||
host_source="$ROOT/default/audio/filter-chain-host.conf"
|
||||
host_config="$XDG_CONFIG_HOME/pipewire/omarchy-speaker-tuning.conf"
|
||||
mkdir -p "${host_config%/*}"
|
||||
|
||||
grep -q 'args = { rtportal.enabled = false }' "$host_source" ||
|
||||
fail "the shipped tuning host asks RTKit directly"
|
||||
pass "the shipped tuning host asks RTKit directly"
|
||||
|
||||
# The copy an earlier Omarchy installed: the same file with the old setting.
|
||||
sed 's/args = { rtportal.enabled = false }/args = { }/' "$host_source" > "$host_config"
|
||||
: > "$CALL_LOG"
|
||||
bash -euo pipefail "$migration" >/dev/null
|
||||
cmp -s "$host_source" "$host_config" || fail "an installed Omarchy host is replaced"
|
||||
grep -Fxq -- "--user try-restart omarchy-speaker-tuning.service" "$CALL_LOG" ||
|
||||
fail "a replaced host is restarted if it runs"
|
||||
pass "an installed Omarchy host is replaced and restarted"
|
||||
|
||||
: > "$CALL_LOG"
|
||||
bash -euo pipefail "$migration" >/dev/null
|
||||
[[ ! -s $CALL_LOG ]] || fail "the migration is idempotent"
|
||||
pass "the migration is idempotent"
|
||||
|
||||
# Another tool's host under the same name, as a community calibrator writes it.
|
||||
foreign='context.properties = { log.level = 0 }
|
||||
context.modules = [
|
||||
{ name = libpipewire-module-rt args = { } flags = [ ifexists nofail ] }
|
||||
]'
|
||||
printf '%s\n' "$foreign" > "$host_config"
|
||||
: > "$CALL_LOG"
|
||||
bash -euo pipefail "$migration" >/dev/null
|
||||
[[ $(cat "$host_config") == "$foreign" && ! -s $CALL_LOG ]] ||
|
||||
fail "a host another tool wrote is left alone"
|
||||
pass "a host another tool wrote is left alone"
|
||||
|
||||
rm -f "$host_config"
|
||||
bash -euo pipefail "$migration" >/dev/null
|
||||
[[ ! -e $host_config && ! -s $CALL_LOG ]] || fail "no tuning installed means nothing to do"
|
||||
pass "no tuning installed means nothing to do"
|
||||
Reference in new issue
Block a user