#!/bin/bash # This script configures pipewire to work both in the graphical environment and in the console with root apps. # Supports both legacy WirePlumber (Lua) and modern WirePlumber (0.5+ config format) # Detect WirePlumber version detect_wireplumber_version() { if command -v wireplumber >/dev/null 2>&1; then local version version=$(wireplumber --version 2>/dev/null | grep -oP 'wireplumber \K[0-9]+\.[0-9]+' | head -n1) if [ -n "$version" ]; then echo "$version" return 0 fi fi # Default to legacy if detection fails echo "0.4" return 1 } # Compare versions (returns 0 if version1 >= version2) version_ge() { [ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$2" ] } if [[ $(whoami) != "root" ]]; then # Track overall success CONFIG_SUCCESS=true # Get the current user's XDG_HOME xdgPath="${XDG_CONFIG_HOME:-$HOME/.config}" mkdir -p "$xdgPath/pipewire" || CONFIG_SUCCESS=false # Detect WirePlumber version WP_VERSION=$(detect_wireplumber_version) echo "Detected WirePlumber version: $WP_VERSION" # Determine configuration format if version_ge "$WP_VERSION" "0.5"; then echo "Using modern WirePlumber configuration format (0.5+)" USE_MODERN_CONFIG=true mkdir -p "$xdgPath/wireplumber/wireplumber.conf.d" mkdir -p "$xdgPath/wireplumber/main.conf.d" mkdir -p "$xdgPath/wireplumber/bluetooth.conf.d" else echo "Using legacy WirePlumber Lua configuration format" USE_MODERN_CONFIG=false mkdir -p "$xdgPath/wireplumber/main.lua.d" mkdir -p "$xdgPath/wireplumber/bluetooth.lua.d" fi # Create drop-in configuration for PipeWire-Pulse console access mkdir -p "$xdgPath/pipewire/pipewire-pulse.conf.d" # Warn user if we are going to overwrite an existing fenrir console config if [ -f "$xdgPath/pipewire/pipewire-pulse.conf.d/50-fenrir-console.conf" ]; then read -r -p "This will replace the current file located at $xdgPath/pipewire/pipewire-pulse.conf.d/50-fenrir-console.conf, press enter to continue or control+c to abort. " fi cat << "EOF" > "$xdgPath/pipewire/pipewire-pulse.conf.d/50-fenrir-console.conf" || CONFIG_SUCCESS=false # Fenrir console audio support # Adds secondary socket for console applications like Fenrir pulse.properties = { # the addresses this server listens on server.address = [ "unix:native" "unix:/tmp/pulse.sock" # console access socket ] } # client/stream specific properties pulse.rules = [ { # speech dispatcher asks for too small latency and then underruns. matches = [ { application.name = "~speech-dispatcher*" } ] actions = { update-props = { pulse.min.req = 1024/48000 # 21ms pulse.min.quantum = 1024/48000 # 21ms } } } ] EOF # Create WirePlumber configuration to prevent audio device suspension on console switch if [ "$USE_MODERN_CONFIG" = true ]; then # Modern WirePlumber 0.5+ configuration format CONFIG_FILE="$xdgPath/wireplumber/main.conf.d/50-fenrir-no-suspend.conf" if [ -f "$CONFIG_FILE" ]; then read -r -p "This will replace the current file located at $CONFIG_FILE, press enter to continue or control+c to abort. " fi cat << "EOF" > "$CONFIG_FILE" || CONFIG_SUCCESS=false # Fenrir console audio support # Prevents audio device suspension when switching to TTY console monitor.alsa.rules = [ { matches = [ { device.name = "~alsa_card.*" } ] actions = { update-props = { api.alsa.use-acp = true api.acp.auto-profile = false api.acp.auto-port = false session.suspend-timeout-seconds = 0 } } } { matches = [ { node.name = "~alsa_input.*" } { node.name = "~alsa_output.*" } ] actions = { update-props = { session.suspend-timeout-seconds = 0 } } } ] EOF else # Legacy Lua configuration format CONFIG_FILE="$xdgPath/wireplumber/main.lua.d/50-fenrir-no-suspend.lua" if [ -f "$CONFIG_FILE" ]; then read -r -p "This will replace the current file located at $CONFIG_FILE, press enter to continue or control+c to abort. " fi cat << "EOF" > "$CONFIG_FILE" || CONFIG_SUCCESS=false -- Fenrir console audio support -- Prevents audio device suspension when switching to TTY console alsa_monitor.rules = { { matches = { { { "device.name", "matches", "alsa_card.*" }, }, }, apply_properties = { ["api.alsa.use-acp"] = true, ["api.acp.auto-profile"] = false, ["api.acp.auto-port"] = false, ["session.suspend-timeout-seconds"] = 0 }, }, { matches = { { { "node.name", "matches", "alsa_input.*" }, }, { { "node.name", "matches", "alsa_output.*" }, }, }, apply_properties = { ["session.suspend-timeout-seconds"] = 0 }, }, } EOF fi # Create WirePlumber bluetooth configuration to prevent disconnection on TTY switch if [ "$USE_MODERN_CONFIG" = true ]; then # Modern WirePlumber 0.5+ configuration format CONFIG_FILE="$xdgPath/wireplumber/bluetooth.conf.d/50-fenrir-bluez.conf" if [ -f "$CONFIG_FILE" ]; then read -r -p "This will replace the current file located at $CONFIG_FILE, press enter to continue or control+c to abort. " fi cat << "EOF" > "$CONFIG_FILE" || CONFIG_SUCCESS=false # Fenrir console audio support # Prevents bluetooth disconnection when switching TTY monitor.bluez.properties = { # Disable logind integration to prevent bluetooth device suspension on TTY switch bluez5.enable-sbc-xq = true bluez5.enable-msbc = true bluez5.enable-hw-volume = true } monitor.bluez.rules = [ { matches = [ { device.name = "~bluez_card.*" } ] actions = { update-props = { session.suspend-timeout-seconds = 0 } } } ] EOF else # Legacy Lua configuration format CONFIG_FILE="$xdgPath/wireplumber/bluetooth.lua.d/30-fenrir-bluez.lua" if [ -f "$CONFIG_FILE" ]; then read -r -p "This will replace the current file located at $CONFIG_FILE, press enter to continue or control+c to abort. " fi cat << "EOF" > "$CONFIG_FILE" || CONFIG_SUCCESS=false -- Fenrir console audio support -- Disables logind module to prevent bluetooth disconnection when switching TTY bluez_monitor = {} bluez_monitor.properties = {} bluez_monitor.rules = {} function bluez_monitor.enable() load_monitor("bluez", { properties = bluez_monitor.properties, rules = bluez_monitor.rules, }) end EOF fi echo "" echo "Configuration files created successfully." if [ "$USE_MODERN_CONFIG" = true ]; then echo "Using modern WirePlumber 0.5+ configuration format (.conf files)" else echo "Using legacy WirePlumber configuration format (.lua files)" fi echo "" echo "Please ensure that your user is added to the audio group." echo "If you have not yet done so, please run this script as root to write the client.conf file." else # This section does the root part: CONFIG_SUCCESS=true xdgPath="/root/.config" mkdir -p "$xdgPath/pulse" || CONFIG_SUCCESS=false # Warn user if we are going to overwrite an existing client.conf if [ -f "$xdgPath/pulse/client.conf" ]; then read -r -p "This will replace the current file located at $xdgPath/pulse/client.conf, press enter to continue or control+c to abort. " fi cat << "EOF" > "$xdgPath/pulse/client.conf" || CONFIG_SUCCESS=false # This file is part of PulseAudio. # # PulseAudio is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # PulseAudio is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with PulseAudio; if not, see . ## Configuration file for PulseAudio clients. See pulse-client.conf(5) for ## more information. Default values are commented out. Use either ; or # for ## commenting. ; default-sink = ; default-source = default-server = unix:/tmp/pulse.sock ; default-dbus-server = autospawn = no ; autospawn = yes ; daemon-binary = /usr/bin/pulseaudio ; extra-arguments = --log-target=syslog ; cookie-file = ; enable-shm = yes ; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB ; auto-connect-localhost = no ; auto-connect-display = no EOF echo "If you have not yet done so, run this script as your normal user to write the user configs" fi # If there were no errors tell user to restart, else warn them errors happened. if [ "$CONFIG_SUCCESS" = true ]; then echo "Configuration created successfully, please restart both Pipewire-pulseaudio and Wireplumber or your system, for changes to take affect." exit 0 else echo "Errors were encountered whilst writing the configuration, please correct them manually." exit 1 fi