#!/usr/bin/env bash # Kaisa pro-audio 基线门禁:检查 WirePlumber 片段、UCM Lua、卡 profile、sinks、IEC958。 # 退出码 0 = 通过,1 = 未满足(stdout 说明缺项)。 # # 须在图形/用户会话下执行(pactl 连接 PipeWire-Pulse);勿裸 root 占用普通用户 XDG_RUNTIME_DIR。 # 若用 sudo 调用本脚本,需带 SUDO_USER,脚本会经 sudo -u $SUDO_USER + XDG_RUNTIME_DIR 调用 pactl。 # # 用法:./scripts/verify-kaisa-pro-audio.sh set -uo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" PACTL_PREFIX=() WCONF_HOME="${HOME}" if [[ $EUID -eq 0 && -n "${SUDO_USER:-}" ]] && command -v sudo &>/dev/null && id -u "$SUDO_USER" &>/dev/null; then _VU="$(id -u "$SUDO_USER")" if [[ -d "/run/user/${_VU}" ]]; then _VH="$(getent passwd "$SUDO_USER" | cut -d: -f6)" _VH="${_VH:-/home/$SUDO_USER}" PACTL_PREFIX=(sudo -u "$SUDO_USER" env XDG_RUNTIME_DIR="/run/user/${_VU}" HOME="$_VH") WCONF_HOME="$_VH" fi fi if [[ $EUID -eq 0 && ${#PACTL_PREFIX[@]} -eq 0 ]]; then echo "verify-kaisa-pro-audio: 当前为 root 且无法解析 SUDO_USER/会话;请用登录用户执行,或: sudo -u <用户> $0" >&2 exit 1 fi fail() { echo "verify-kaisa-pro-audio: FAIL — $*" >&2; exit 1; } ok() { echo "verify-kaisa-pro-audio: OK — $*"; } if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//' exit 0 fi if ! command -v pactl &>/dev/null; then fail "未找到 pactl(建议安装 pulseaudio-utils)" fi if ! command -v amixer &>/dev/null; then fail "未找到 amixer(alsa-utils)" fi if ! grep -q 'sof-rt5682' /proc/asound/cards 2>/dev/null; then fail "/proc/asound/cards 中无 sof-rt5682" fi ok "ALSA 卡 sof-rt5682 存在" if [[ -f /usr/share/wireplumber/main.lua.d/60-kaisa-ucm.lua ]]; then fail "仍存在可加载的 /usr/share/wireplumber/main.lua.d/60-kaisa-ucm.lua(应改为 .disabled 或删除)" fi ok "60-kaisa-ucm.lua 未处于激活路径" conf="${WCONF_HOME}/.config/wireplumber/wireplumber.conf.d/50-kaisa-sof-rt5682-hdmi.conf" if [[ ! -f "$conf" ]]; then fail "缺少用户 WirePlumber 片段: $conf" fi ok "用户级 50-kaisa-sof-rt5682-hdmi.conf 存在" wp_state="${WCONF_HOME}/.local/state/wireplumber/default-profile" if [[ -f "$wp_state" ]] && grep 'cml_rt5682' "$wp_state" 2>/dev/null | grep -qF 'stereo-fallback'; then fail "WirePlumber 状态文件仍要求 cml_rt5682 使用 stereo-fallback(会在重启后顶掉 pro-audio)。请执行: ${REPO_ROOT}/scripts/strip-kaisa-default-profile-state.sh 后 systemctl --user restart wireplumber pipewire pipewire-pulse,或重新运行 apply-kaisa-pro-audio.sh" fi pactl_cards="$("${PACTL_PREFIX[@]}" pactl list cards 2>/dev/null)" || fail "pactl list cards 失败" if ! grep -qF 'cml_rt5682' <<< "$pactl_cards"; then fail "pactl list cards 中无 cml_rt5682(PCI/卡名是否与仓库 conf 一致?)" fi # 在「含 cml_rt5682 的卡」块内取第一条 活动配置 / Active Profile(避免匹配到「配置文件」里的 pro-audio 行) active_line="$(awk ' /^卡 #[0-9]+/ || /^Card #[0-9]+/ { in_c=0 } /cml_rt5682/ { in_c=1 } in_c && (/活动配置/ || /Active Profile/) { print; exit } ' <<< "$pactl_cards")" if [[ -z "$active_line" ]]; then fail "无法在 cml_rt5682 卡块内解析 活动配置/Active Profile 行" fi if [[ "$active_line" != *pro-audio* ]]; then _al="$(echo "$active_line" | tr -d '\t' | sed 's/^[[:space:]]*//')" fail "该卡活动配置不是 pro-audio(当前: ${_al})。请执行: ${REPO_ROOT}/scripts/apply-kaisa-pro-audio.sh(勿加 --verify-only)" fi ok "pactl 声卡活动配置为 pro-audio" sinks="$("${PACTL_PREFIX[@]}" pactl list short sinks 2>/dev/null)" || fail "pactl list short sinks 失败" for po in pro-output-0 pro-output-2 pro-output-3 pro-output-4; do if ! grep -F 'cml_rt5682' <<< "$sinks" | grep -qF "$po"; then fail "缺少 sink …${po}(pro-audio 下应暴露 Port1 + HDMI1/2/3)" fi done ok "pactl short sinks 含 pro-output-0/2/3/4(cml_rt5682)" def="$("${PACTL_PREFIX[@]}" pactl get-default-sink 2>/dev/null)" || fail "pactl get-default-sink 失败" if [[ "$def" != *pro-output-2* ]]; then fail "默认 sink 应为 …pro-output-2,当前: $def" fi ok "默认 sink 为 pro-output-2" for i in 0 1 2; do out="$(amixer -c0 sget "IEC958",$i 2>/dev/null || true)" if ! grep -qiE '\[on\]|\[开启\]' <<< "$out"; then fail "IEC958',$i' 非开启状态(需 amixer -c0 sset 'IEC958',$i on)" fi done ok "IEC958',0/1/2 均为 on" echo "verify-kaisa-pro-audio: 全部检查通过。" exit 0