changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > infra > box / airootfs/usr/local/bin/livecd-sound

changeset 2: 2fafbe22bd34
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 31 May 2024 17:30:09 -0400
permissions: -rwxr-xr-x
description: init releng
1 #!/usr/bin/env bash
2 #
3 # SPDX-License-Identifier: GPL-3.0-or-later
4 
5 usage() {
6  cat <<-_EOF_
7  live cd sound helper script.
8  Usage: livecdsound [OPTION]
9  OPTIONS
10  -u, --unmute unmute all sound cards
11  -p, --pick select a card for speetch output
12  -h, --help Show this usage message
13 
14 _EOF_
15 }
16 
17 bugout() {
18  printf "/usr/local/bin/livecdsound: programming error"
19  stat_fail
20 }
21 
22 echo_card_indices() {
23  if [[ -f /proc/asound/cards ]]; then
24  sed -n -e's/^[[:space:]]*\([0-7]\)[[:space:]].*/\1/p' /proc/asound/cards
25  fi
26 }
27 
28 # The following functions try to set many controls.
29 # No card has all the controls and so some of the attempts are bound to fail.
30 # Because of this, the functions can't return useful status values.
31 
32 # $1 <card id>
33 # $2 <control>
34 # $3 <level>
35 unmute_and_set_level() {
36  [[ -n "$3" && -n "$2" && -n "$1" ]] || bugout
37  systemd-cat -t "livecdsound" printf "Setting: %s on card: %s to %s\n" "$2" "$1" "$3"
38  systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "$3" unmute
39  return 0
40 }
41 
42 # $1 <card id>
43 # $2 <control>
44 mute_and_zero_level() {
45  [[ -n "$1" && -n "$2" ]] || bugout
46  systemd-cat -t "livecdsound" printf "Muting control: %s on card: %s\n" "$2" "$1"
47  systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "0%" mute
48  return 0
49 }
50 
51 # $1 <card ID>
52 # $2 <control>
53 # $3 "on" | "off"
54 switch_control() {
55  [[ -n "$3" && -n "$1" ]] || bugout
56  systemd-cat -t "livecdsound" printf "Switching control: %s on card: %s to %s\n" "$2" "$1" "$3"
57  systemd-cat -t "livecdsound" amixer -c "$1" set "$2" "$3"
58  return 0
59 }
60 
61 # $1 <card ID>
62 sanify_levels_on_card() {
63  unmute_and_set_level "$1" "Front" "80%"
64  unmute_and_set_level "$1" "Master" "80%"
65  unmute_and_set_level "$1" "Master Mono" "80%"
66  unmute_and_set_level "$1" "Master Digital" "80%" # E.g., cs4237B
67  unmute_and_set_level "$1" "Playback" "80%"
68  unmute_and_set_level "$1" "Headphone" "100%"
69  unmute_and_set_level "$1" "PCM" "80%"
70  unmute_and_set_level "$1" "PCM,1" "80%" # E.g., ess1969
71  unmute_and_set_level "$1" "DAC" "80%" # E.g., envy24, cs46xx
72  unmute_and_set_level "$1" "DAC,0" "80%" # E.g., envy24
73  unmute_and_set_level "$1" "DAC,1" "80%" # E.g., envy24
74  unmute_and_set_level "$1" "Synth" "80%"
75  unmute_and_set_level "$1" "CD" "80%"
76  unmute_and_set_level "$1" "PC Speaker" "100%"
77 
78  mute_and_zero_level "$1" "Mic"
79  mute_and_zero_level "$1" "IEC958" # Ubuntu #19648
80 
81  # Intel P4P800-MX
82  switch_control "$1" "Master Playback Switch" on
83  switch_control "$1" "Master Surround" on
84 
85  # Trident/YMFPCI/emu10k1:
86  unmute_and_set_level "$1" "Wave" "80%"
87  unmute_and_set_level "$1" "Music" "80%"
88  unmute_and_set_level "$1" "AC97" "80%"
89 
90  # DRC:
91  unmute_and_set_level "$1" "Dynamic Range Compression" "80%"
92 
93  # Required for HDA Intel (hda-intel):
94  unmute_and_set_level "$1" "Front" "80%"
95 
96  # Required for SB Live 7.1/24-bit (ca0106):
97  unmute_and_set_level "$1" "Analog Front" "80%"
98 
99  # Required at least for Via 823x hardware on DFI K8M800-MLVF Motherboard
100  switch_control "$1" "IEC958 Capture Monitor" off
101 
102  # Required for hardware allowing toggles for AC97 through IEC958,
103  # valid values are 0, 1, 2, 3. Needs to be set to 0 for PCM1.
104  unmute_and_set_level "$1" "IEC958 Playback AC97-SPSA" "0"
105 
106  # Required for newer Via hardware
107  unmute_and_set_level "$1" "VIA DXS,0" "80%"
108  unmute_and_set_level "$1" "VIA DXS,1" "80%"
109  unmute_and_set_level "$1" "VIA DXS,2" "80%"
110  unmute_and_set_level "$1" "VIA DXS,3" "80%"
111 
112  # Required on some notebooks with ICH4:
113  switch_control "$1" "Headphone Jack Sense" off
114  switch_control "$1" "Line Jack Sense" off
115 
116  # Some machines need one or more of these to be on;
117  # others need one or more of these to be off:
118 
119  switch_control "$1" "Audigy Analog/Digital Output Jack" on
120  switch_control "$1" "SB Live Analog/Digital Output Jack" on
121 
122  # D1984 -- Thinkpad T61/X61
123  switch_control "$1" "Speaker" on
124  switch_control "$1" "Headphone" on
125 
126  # HDA-Intel w/ "Digital" capture mixer (See Ubuntu #193823)
127  unmute_and_set_level "$1" "Digital" "80%"
128 
129  return 0
130 }
131 
132 # $1 <card ID> | "all"
133 sanify_levels() {
134  local ttsdml_returnstatus=0
135  local card
136  case "$1" in
137  all)
138  for card in $(echo_card_indices); do
139  sanify_levels_on_card "$card" || ttsdml_returnstatus=1
140  done
141  ;;
142  *)
143  sanify_levels_on_card "$1" || ttsdml_returnstatus=1
144  ;;
145  esac
146  return "$ttsdml_returnstatus"
147 }
148 
149 # List all cards that *should* be usable for PCM audio. In my experience,
150 # the console speaker (handled by the pcsp driver) isn't a suitable playback
151 # device, so we'll exclude it.
152 list_non_pcsp_cards() {
153  for card in $(echo_card_indices); do
154  local cardfile="/proc/asound/card${card}/id"
155  if [[ -r "$cardfile" && -f "$cardfile" && "$(cat "$cardfile")" != pcsp ]]; then
156  echo "$card"
157  fi
158  done
159 }
160 
161 # Properly initialize the sound card so that we have audio at boot.
162 unmute_all_cards() {
163  sanify_levels all
164 }
165 
166 is_numeric() {
167  local str="$1"
168  [[ "$str" =~ ^[0-9]+$ ]]
169 }
170 
171 set_default_card() {
172  local card="$1"
173  sed -e "s/%card%/$card/g" </usr/local/share/livecd-sound/asound.conf.in \
174  >/etc/asound.conf
175 }
176 
177 play_on_card() {
178  local card="$1" file="$2"
179  aplay -q "-Dplughw:$card,0" "$file"
180 }
181 
182 # If there are multiple usable sound cards, prompt the user to choose one,
183 # using auditory feedback.
184 pick_a_card() {
185  set -f
186  usable_cards="$(list_non_pcsp_cards)"
187  num_usable_cards="$(wc -w <<<"$usable_cards")"
188 
189  if (( num_usable_cards == 1 )); then
190  systemd-cat -t "livecdsound" printf "Only one sound card is detected\n"
191  exit 0
192  fi
193  systemd-cat -t "livecdsound" printf "multiple sound cards detected\n"
194  for card in "${usable_cards[@]}"; do
195  if ! is_numeric "$card"; then
196  continue
197  fi
198  play_on_card "$card" /usr/share/livecd-sounds/pick-a-card.wav &
199  done
200  wait
201  sleep 1
202  for card in "${usable_cards[@]}"; do
203  if ! is_numeric "$card"; then
204  continue
205  fi
206  play_on_card "$card" /usr/share/livecd-sounds/beep.wav
207  if read -r -t 10; then
208  systemd-cat -t "livecdsound" printf "Selecting %s sound card as default\n" "$card"
209  set_default_card "$card"
210  break
211  fi
212  done
213 }
214 
215 if (( $# == 0 )); then
216  echo "error: No argument passed."
217  exit 1
218 fi
219 while [[ "${1}" != "" ]]; do
220  case ${1} in
221  -h|--help)
222  usage
223  exit
224  ;;
225  -u|--unmute)
226  systemd-cat -t "livecdsound" printf "Unmuting all cards"
227  unmute_all_cards
228  ;;
229  -p|--pick)
230  pick_a_card
231  ;;
232  *)
233  echo "error: Unsupported argument"
234  usage
235  exit 1
236  ;;
237  esac
238  shift
239 done