You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
6.9 KiB
239 lines
6.9 KiB
#!/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
|
|
|