Εύκολη εναλλαγή μεταξύ PulseAudio και PipeWire

Ένα μικρό script για την εγκατάσταση του PipeWire και την εύκολη εναλλαγή μεταξύ PulseAudio και PipeWire. Δοκιμάστηκε σε Linux Mint. Για περισσότερες λεπτομέρειες δείτε:

asfodelus@menta:~/Projects/PipeWire$ ./audio_switch 
audio_switch: Install pipewire and sound switcher source
   repos:       Enable PPAs
   install:     Install pipewire
   pipewire:    Use pipewire
   pulseaudio:  Use puleaudio
   check:       Check sound

O κώδικας

#!/bin/bash
# Save as /usr/local/bin/audio_switch and make it executable
# Info: https://pipewire-debian.github.io/pipewire-debian/

RESET='\e[0m'
RED='\e[31m'
GREEN='\e[32m'
OK="${GREEN}[OK]${RESET}"
ERROR="${RED}[ERROR]${RESET}"

function cmd_repos() {
    # For PipeWire
    sudo add-apt-repository ppa:pipewire-debian/pipewire-upstream -y
    # For WirePlumber 
    sudo add-apt-repository ppa:pipewire-debian/wireplumber-upstream
}

function cmd_install() {
    sudo apt-get update
    sudo apt install pipewire gstreamer1.0-pipewire pipewire-pulse libspa-0.2-bluetooth libspa-0.2-jack pipewire-media-session -y
    sudo cp -vRa /usr/share/pipewire /etc/ 
}

function enable_service() {
    service="$1"
    systemctl --user --quiet --now enable "${service}"
    state=$(systemctl show --user -p SubState "$service" | sed 's/SubState=//g')
    code="${ERROR}" && systemctl is-active --user --quiet "${service}" && code="${OK}"
    echo -e "    ${code} Service ${service} is ${state}"
}

function disable_service() {
    service="$1"
    systemctl --user --quiet --now disable "${service}" 
    state=$(systemctl show --user -p SubState "$service" | sed 's/SubState=//g')
    code="${ERROR}" && systemctl is-active --user --quiet "${service}" || code="${OK}"
    echo -e "    ${code} Service ${service} is ${state}"
}

function cmd_pulseaudio() {
    what="${1-on}"; shift
    case "$what" in
    "on")
        cmd_pipewire off
        echo "-- Enable PulseAudio"
        systemctl --quiet --user unmask pulseaudio
        enable_service pulseaudio.socket
        enable_service pulseaudio.service
        systemctl --user daemon-reload
        cmd_check
        ;;
    *)
        echo "-- Disable PulseAudio"
        disable_service pulseaudio.socket
        disable_service pulseaudio.service
        systemctl --quiet --user mask pulseaudio
        systemctl --user daemon-reload
        ;;
    esac
    shift
}

function cmd_pipewire() {
    what="${1-on}"; shift
    case "$what" in
    "on")
        echo "-- Enable pipewire"
        cmd_pulseaudio off
        enable_service pipewire.socket
        enable_service pipewire.service
        enable_service pipewire-pulse.socket
        enable_service pipewire-pulse.service
        enable_service wireplumber.service
        systemctl --user daemon-reload
        cmd_check
        ;;
    *)
        echo "-- Disable pipewire"
        disable_service wireplumber.service
        disable_service pipewire-pulse.socket
        disable_service pipewire-pulse.service
        disable_service pipewire.service
        disable_service pipewire.socket
        systemctl --user daemon-reload
        ;;
    esac
}

function cmd_check() {    
    pactl info | grep '^Server Name'
    aplay /usr/share/sounds/linuxmint-gdm.wav
}

function cmd_help() {
    echo "$(basename "${BASH_SOURCE[0]}"): Install pipewire and sound switcher source"
    echo "   repos:       Enable PPAs"
    echo "   install:     Install pipewire"
    echo "   pipewire:    Use pipewire"
    echo "   pulseaudio:  Use puleaudio"
    echo "   check:       Check sound"
}

### Run the command
command=${1-help}
shift
func=cmd_"${command}"
if [ "$(type -t "$func")" == "function" ]; then
	$func "$@"
else
	printf "Unknown command %s\n" "$command"
	cmd_help
fi

6 «Μου αρέσει»

Ο νέος κώδικάς είναι στο github

Δώστε σε ένα τερματικό:

wget -O - https://raw.githubusercontent.com/jtsagata/audio_switch/master/install.sh | sudo bash
2 «Μου αρέσει»

Συγχαρητήρια, θα ήθελα να το δω και στο Arch και ίσως προσπαθήσω για την αλλαγή!

Μία ερώτηση για την cmd_check function.

Βλέπω χρησιμοποιείς την aplay που είναι εντολή του alsa. Από μεριάς Arch η συγκεκριμένη εντολή είναι ενσωματωμένη στο alsa-utils το οποίο δεν είναι core package. Θα μπορούσε αν αντί της aplay το script να ελέγχει τον Sound Server και να χρησιμοποιεί την αντίστοιχη εντολή; Πχ. pw-play και pactl

2 «Μου αρέσει»

Δες το τελευταίο commit στο github.

function cmd_check() {    
    server=$(pactl info | grep '^Server Name')
    if [[ "$server" =~ "PipeWire" ]]; then 
        echo -ne "*** Running on ${GREEN}Pipewire${RESET}... "
    else 
        echo -ne "*** Running on ${GREEN}PulseAudio${RESET}..."
    fi
    aplay /usr/share/sounds/linuxmint-gdm.wav 2> /dev/null
    echo "Did you hear the sound?"
}

Πλέον είναι εύκολο να έχεις διαφορετική συμπεριφορά. Ίσως θα πρέπει να μπει και κάποιος έλεγχος για το αν υπάρχει το αρχείου ήχου και να επιλέξει κάποιο άλλο. Περιμένω pull request :sunglasses:

Μπορείς να προσθέσεις κάποια συνάρτηση cmd_arch_inst για εγκατάσταση στο arch. Θα την δει αυτόματα.

Fun Fact: Τα PPAs που χρησιμοποιούνται είναι φτιαγμένα και συντηρούνται από χρήστη του Arch :face_with_spiral_eyes:

2 «Μου αρέσει»

για το αν υπάρχει το αρχείου ήχου

Ή χωρίς τέτοιο αρχείο

cat /dev/urandom | pacat

και πιο απλά, αφού το pacat μπορεί να διαβάσει κάποια τοποθεσία κατευθείαν

pacat /dev/urandom

Και γιατί όχι αντί για ήχο λίγη μουσική (πηγή με εξήγηση της εντολής);

cat /dev/urandom | hexdump -v -e '/1 "%u\n"' | awk '{ split("0,2,4,5,7,9,11,12",a,","); for (i = 0; i < 1; i+= 0.0001) printf("%08X\n", 100*sin(1382*exp((a[$1%8+1]/12)*log(2))*i)) }' | xxd -r -p | pacat

Ενδιαφέρον πως κάποτε (προ ALSA, επί OSS) γινόταν κάποιος να κάνει

cat /dev/urandom > /dev/audio

που με τον OSS wrapper του PA γίνεται

cat /dev/urandom | padsp tee /dev/audio >/dev/null

αλλά δεν έχει νόημα αφού μπορεί να χρησιμοποιηθεί το πρώτο.

1 «Μου αρέσει»

Στην τελευταία έκδοση στο github γίνετε χρήση του αρχείου /usr/share/sounds/alsa/Front_Center.wav λογικά υπάρχει παντού. Επίσης διορθώθηκαν κάποια σφάλματα και δοκιμάστηκε και σε καινούργια εγκατάσταση Pop OS!.

Τώρα αν αντί για για κάποιον ήχο βάλεις θόρυβο, τότε υπάρχει φόβος σύγχυσης: “Δεν δουλεύει και αντί για ήχο κάνει θόρυβο”.

Trivia: Δεν υπάρχει κάτι το παράξενο στην εντολή padsp είναι ένα απλό αρχείο bash (δείτε το) που χρησιμοποιεί τον μηχανισμό του LD_PRELOAD και φορτώνει την βιβλιοθήκη libpulsedsp.so. Αυτό που κάνει είναι να κρύβει τις κλήσεις συστήματος του ALSA και να τις αντικαθιστά με αντίστοιχες του Pulse. Έχω στην αποθήκη ένα άρθρο που τα εξηγεί σε κάποιο βάθος τον Linker τις δυναμικές βιβλιοθήκες και τον μηχανισμό του LD_PRELOAD, πρέπει κάποια στιγμή να το τελειώσω :innocent:

ΥΓ: Ωραίο το κόλπο για παραγωγή μουσικής με bash, ίσως το βάλω, αν και θέλει κάποιες αλλαγές ώστε κάποια στιγμή να σταματάει. Αλλά θα κάνει το script αρκετά “μαγικό”, ένας που μας διαβάζει μπορεί να δει το πρόγραμμα και ίσως να αρπάξει κάποιες τεχνικές για τα δικά του.

Changelog:

  • Παίζει και μουσική όπως πρότεινε ο @konfou
  • Restart command
  • vinfo command: Δείχνει αν τρέχει σε 5.1 η 2.0 καθώς και την ένταση του ήχου
$ audio_switch vinfo
-- Default Sink: analog-surround-51
-- Volumes
      front-left: 56% 
     front-right: 56% 
       rear-left: 56% 
      rear-right: 56% 
    front-center: 56% 
             lfe: 56%