239 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
	
		
			6.9 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env bash
 | |
| #
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| usage() {
 | |
|     cat <<-_EOF_
 | |
|     live cd sound helper script.
 | |
|     Usage: livecdsound [OPTION]
 | |
|     OPTIONS
 | |
|         -u, --unmute      unmute all sound cards
 | |
|         -p, --pick        select a card for  speetch output
 | |
|         -h, --help        Show this usage message
 | |
| 
 | |
| _EOF_
 | |
| }
 | |
| 
 | |
| bugout() {
 | |
|     printf "/usr/local/bin/livecdsound: programming error"
 | |
|     stat_fail
 | |
| }
 | |
| 
 | |
| echo_card_indices() {
 | |
|     if [[ -f /proc/asound/cards ]]; then
 | |
|         sed -n -e's/^[[:space:]]*\([0-7]\)[[:space:]].*/\1/p' /proc/asound/cards
 | |
|     fi
 | |
| }
 | |
| 
 | |
| # The following functions try to set many controls.
 | |
| # No card has all the controls and so some of the attempts are bound to fail.
 | |
| # Because of this, the functions can't return useful status values.
 | |
| 
 | |
| # $1 <card id>
 | |
| # $2 <control>
 | |
| # $3 <level>
 | |
| unmute_and_set_level() {
 | |
|     [[ -n "$3" && -n "$2" && -n "$1" ]] || bugout
 | |
|     systemd-cat -t "livecdsound" printf "Setting: %s on card: %s to %s\n" "$2" "$1" "$3"
 | |
|     systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "$3" unmute
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| # $1 <card id>
 | |
| # $2 <control>
 | |
| mute_and_zero_level() {
 | |
|     [[ -n "$1" && -n "$2" ]] || bugout
 | |
|     systemd-cat -t "livecdsound" printf "Muting control: %s on card: %s\n" "$2" "$1"
 | |
|     systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "0%" mute
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| # $1 <card ID>
 | |
| # $2 <control>
 | |
| # $3 "on" | "off"
 | |
| switch_control() {
 | |
|     [[ -n "$3" && -n "$1" ]] || bugout
 | |
|     systemd-cat -t "livecdsound" printf "Switching control: %s on card: %s to %s\n" "$2" "$1" "$3"
 | |
|     systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "$3"
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| # $1 <card ID>
 | |
| sanify_levels_on_card() {
 | |
|     unmute_and_set_level "$1" "Front" "80%"
 | |
|     unmute_and_set_level "$1" "Master" "80%"
 | |
|     unmute_and_set_level "$1" "Master Mono" "80%"
 | |
|     unmute_and_set_level "$1" "Master Digital" "80%"   # E.g., cs4237B
 | |
|     unmute_and_set_level "$1" "Playback" "80%"
 | |
|     unmute_and_set_level "$1" "Headphone" "100%"
 | |
|     unmute_and_set_level "$1" "PCM" "80%"
 | |
|     unmute_and_set_level "$1" "PCM,1" "80%"   # E.g., ess1969
 | |
|     unmute_and_set_level "$1" "DAC" "80%"     # E.g., envy24, cs46xx
 | |
|     unmute_and_set_level "$1" "DAC,0" "80%"   # E.g., envy24
 | |
|     unmute_and_set_level "$1" "DAC,1" "80%"   # E.g., envy24
 | |
|     unmute_and_set_level "$1" "Synth" "80%"
 | |
|     unmute_and_set_level "$1" "CD" "80%"
 | |
|     unmute_and_set_level "$1" "PC Speaker" "100%"
 | |
| 
 | |
|     mute_and_zero_level "$1" "Mic"
 | |
|     mute_and_zero_level "$1" "IEC958"         # Ubuntu #19648
 | |
| 
 | |
|     # Intel P4P800-MX
 | |
|     switch_control "$1" "Master Playback Switch" on
 | |
|     switch_control "$1" "Master Surround" on
 | |
| 
 | |
|     # Trident/YMFPCI/emu10k1:
 | |
|     unmute_and_set_level "$1" "Wave" "80%"
 | |
|     unmute_and_set_level "$1" "Music" "80%"
 | |
|     unmute_and_set_level "$1" "AC97" "80%"
 | |
| 
 | |
|     # DRC:
 | |
|     unmute_and_set_level "$1" "Dynamic Range Compression" "80%"
 | |
| 
 | |
|     # Required for HDA Intel (hda-intel):
 | |
|     unmute_and_set_level "$1" "Front" "80%"
 | |
| 
 | |
|     # Required for SB Live 7.1/24-bit (ca0106):
 | |
|     unmute_and_set_level "$1" "Analog Front" "80%"
 | |
| 
 | |
|     # Required at least for Via 823x hardware on DFI K8M800-MLVF Motherboard
 | |
|     switch_control "$1" "IEC958 Capture Monitor" off
 | |
| 
 | |
|     # Required for hardware allowing toggles for AC97 through IEC958,
 | |
|     #  valid values are 0, 1, 2, 3. Needs to be set to 0 for PCM1.
 | |
|     unmute_and_set_level "$1" "IEC958 Playback AC97-SPSA" "0"
 | |
| 
 | |
|     # Required for newer Via hardware
 | |
|     unmute_and_set_level "$1" "VIA DXS,0" "80%"
 | |
|     unmute_and_set_level "$1" "VIA DXS,1" "80%"
 | |
|     unmute_and_set_level "$1" "VIA DXS,2" "80%"
 | |
|     unmute_and_set_level "$1" "VIA DXS,3" "80%"
 | |
| 
 | |
|     # Required on some notebooks with ICH4:
 | |
|     switch_control "$1" "Headphone Jack Sense" off
 | |
|     switch_control "$1" "Line Jack Sense" off
 | |
| 
 | |
|     # Some machines need one or more of these to be on;
 | |
|     # others need one or more of these to be off:
 | |
| 
 | |
|     switch_control "$1" "Audigy Analog/Digital Output Jack" on
 | |
|     switch_control "$1" "SB Live Analog/Digital Output Jack" on
 | |
| 
 | |
|     # D1984 -- Thinkpad T61/X61
 | |
|     switch_control "$1" "Speaker" on
 | |
|     switch_control "$1" "Headphone" on
 | |
| 
 | |
|     # HDA-Intel w/ "Digital" capture mixer (See Ubuntu #193823)
 | |
|     unmute_and_set_level "$1" "Digital" "80%"
 | |
| 
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| # $1 <card ID> | "all"
 | |
| sanify_levels() {
 | |
|     local ttsdml_returnstatus=0
 | |
|     local card
 | |
|     case "$1" in
 | |
|         all)
 | |
|             for card in $(echo_card_indices); do
 | |
|                 sanify_levels_on_card "$card" || ttsdml_returnstatus=1
 | |
|             done
 | |
|             ;;
 | |
|         *)
 | |
|             sanify_levels_on_card "$1" || ttsdml_returnstatus=1
 | |
|             ;;
 | |
|     esac
 | |
|     return "$ttsdml_returnstatus"
 | |
| }
 | |
| 
 | |
| # List all cards that *should* be usable for PCM audio.  In my experience,
 | |
| # the console speaker (handled by the pcsp driver) isn't a suitable playback
 | |
| # device, so we'll exclude it.
 | |
| list_non_pcsp_cards() {
 | |
|     for card in $(echo_card_indices); do
 | |
|         local cardfile="/proc/asound/card${card}/id"
 | |
|         if [[ -r "$cardfile" && -f "$cardfile" && "$(cat "$cardfile")" != pcsp ]]; then
 | |
|             echo "$card"
 | |
|         fi
 | |
|     done
 | |
| }
 | |
| 
 | |
| # Properly initialize the sound card so that we have audio at boot.
 | |
| unmute_all_cards() {
 | |
|     sanify_levels all
 | |
| }
 | |
| 
 | |
| is_numeric() {
 | |
|     local str="$1"
 | |
|     [[ "$str" =~ ^[0-9]+$ ]]
 | |
| }
 | |
| 
 | |
| set_default_card() {
 | |
|     local card="$1"
 | |
|     sed -e "s/%card%/$card/g" </usr/local/share/livecd-sound/asound.conf.in \
 | |
|         >/etc/asound.conf
 | |
| }
 | |
| 
 | |
| play_on_card() {
 | |
|     local card="$1" file="$2"
 | |
|     aplay -q "-Dplughw:$card,0" "$file"
 | |
| }
 | |
| 
 | |
| # If there are multiple usable sound cards, prompt the user to choose one,
 | |
| # using auditory feedback.
 | |
| pick_a_card() {
 | |
|     set -f
 | |
|     usable_cards="$(list_non_pcsp_cards)"
 | |
|     num_usable_cards="$(wc -w <<<"$usable_cards")"
 | |
| 
 | |
|     if (( num_usable_cards == 1 )); then
 | |
|         systemd-cat -t "livecdsound" printf "Only one sound card is detected\n"
 | |
|         exit 0
 | |
|     fi
 | |
|     systemd-cat -t "livecdsound" printf "multiple sound cards detected\n"
 | |
|     for card in "${usable_cards[@]}"; do
 | |
|         if ! is_numeric "$card"; then
 | |
|             continue
 | |
|         fi
 | |
|         play_on_card "$card" /usr/share/livecd-sounds/pick-a-card.wav &
 | |
|     done
 | |
|     wait
 | |
|     sleep 1
 | |
|     for card in "${usable_cards[@]}"; do
 | |
|         if ! is_numeric "$card"; then
 | |
|             continue
 | |
|         fi
 | |
|         play_on_card "$card" /usr/share/livecd-sounds/beep.wav
 | |
|         if read -r -t 10; then
 | |
|             systemd-cat -t "livecdsound" printf "Selecting %s sound card as default\n" "$card"
 | |
|             set_default_card "$card"
 | |
|             break
 | |
|         fi
 | |
|     done
 | |
| }
 | |
| 
 | |
| if (( $# == 0 )); then
 | |
|     echo "error: No argument passed."
 | |
|     exit 1
 | |
| fi
 | |
| while [[ "${1}" != "" ]]; do
 | |
|     case ${1} in
 | |
|         -h|--help)
 | |
|             usage
 | |
|             exit
 | |
|             ;;
 | |
|         -u|--unmute)
 | |
|             systemd-cat -t "livecdsound" printf "Unmuting all cards"
 | |
|             unmute_all_cards
 | |
|             ;;
 | |
|         -p|--pick)
 | |
|             pick_a_card
 | |
|             ;;
 | |
|         *)
 | |
|             echo "error: Unsupported argument"
 | |
|             usage
 | |
|             exit 1
 | |
|             ;;
 | |
|     esac
 | |
|     shift
 | |
| done
 |