249 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			6.8 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(){
 | 
						|
    { [ "$3" ] &&[ "$2" ] && [ "$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()
 | 
						|
{
 | 
						|
    { [ "$1" ] && [ "$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()
 | 
						|
{
 | 
						|
    { [ "$3" ] && [ "$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" -eq 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 [[  $# -eq 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
 |