#!/bin/sh # # alsa-utils initscript # ### BEGIN INIT INFO # Provides: alsa-utils # Required-Start: $local_fs $remote_fs # Required-Stop: $remote_fs # Default-Start: S # Default-Stop: 0 1 6 # Short-Description: Restore and store ALSA driver settings # Description: This script stores and restores mixer levels on # shutdown and bootup.On sysv-rc systems: to # disable storing of mixer levels on shutdown, # remove /etc/rc[06].d/K50alsa-utils. To disable # restoring of mixer levels on bootup, rename the # "S50alsa-utils" symbolic link in /etc/rcS.d/ to # "K50alsa-utils". ### END INIT INFO # Don't use set -e; check exit status instead # Exit silently if package is no longer installed test -x /usr/sbin/alsactl || exit 0 setglobal PATH = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' setglobal MYNAME = '/etc/init.d/alsa-utils' setglobal ALSACTLHOME = '/run/alsa' test -d $ALSACTLHOME || mkdir -p $ALSACTLHOME source /lib/lsb/init-functions source /usr/share/alsa/utils.sh # $1 EXITSTATUS # [$2 MESSAGE] proc log_action_end_msg_and_exit { log_action_end_msg $1 $(2:+"$2") exit $1 } # $1 PROGRAM proc executable { # If which is not available then we must be running before # /usr is mounted on a system that has which in /usr/bin/. # Conclude that $1 is not executable. test -x /bin/which || test -x /usr/bin/which || return 1 which $1 >/dev/null !2 > !1 } executable amixer || do { echo "$(MYNAME): Error: No amixer program available." > !2 ; exit 1 ; } # $1 | "all" proc restore_levels { test -f /var/lib/alsa/asound.state || return 1 setglobal CARD = $1 test $1 = all && setglobal CARD = ''"" # Assume that if alsactl prints a message on stderr # then it failed somehow. This works around the fact # that alsactl doesn't return nonzero status when it # can't restore settings for the card if setglobal MSG = $[alsactl -E HOME="$ALSACTLHOME" restore $CARD !2 > !1 >/dev/null] && test ! $MSG { return 0 } else { # Retry with the "force" option. This restores more levels # but it results in much longer error messages. alsactl -F restore $CARD >/dev/null !2 > !1 log_action_cont_msg "warning: 'alsactl -E HOME="$ALSACTLHOME" restore$(CARD:+ $CARD)' failed with error message '$MSG'" return 1 } } # $1 | "all" proc store_levels { setglobal CARD = $1 test $1 = all && setglobal CARD = ''"" if setglobal MSG = $[alsactl -E HOME="$ALSACTLHOME" store $CARD !2 > !1] { sleep 1 return 0 } else { log_action_cont_msg "warning: 'alsactl store$(CARD:+ $CARD)' failed with error message '$MSG'" return 1 } } # $1 proc mute_and_zero_levels_on_card { setglobal CARDOPT = ""-c $1"" for CTL in [\ Master \ PCM \ Synth \ CD \ Line \ Mic \ "PCM,1" \ Wave \ Music \ AC97 \ "Master Digital" \ DAC \ "DAC,0" \ "DAC,1" \ Headphone \ Speaker \ Playback] { mute_and_zero_level $CTL } # for CTL in \ # "Audigy Analog/Digital Output Jack" \ # "SB Live Analog/Digital Output Jack" # do # switch_control "$CTL" off # done return 0 } # $1 | "all" proc mute_and_zero_levels { setglobal TTZML_RETURNSTATUS = '0' match $1 { with all for CARD in [$[echo_card_indices]] { mute_and_zero_levels_on_card $CARD || setglobal TTZML_RETURNSTATUS = '1' } with * mute_and_zero_levels_on_card $1 || setglobal TTZML_RETURNSTATUS = '1' } return $TTZML_RETURNSTATUS } # $1 | "all" proc card_OK { test $1 || bugout if test $1 = all { test -d /proc/asound return $? } else { test -d "/proc/asound/card$1" || test -d "/proc/asound/$1" return $? } } # If a card identifier is provided in $2 then regard it as an error # if that card is not present; otherwise don't regard it as an error. match $1 { with start setglobal EXITSTATUS = '0' setglobal TARGET_CARD = $2 match $TARGET_CARD { with ""|all setglobal TARGET_CARD = 'all' ; log_action_begin_msg "Setting up ALSA" with * log_action_begin_msg "Setting up ALSA card $(TARGET_CARD)" } card_OK $TARGET_CARD || log_action_end_msg_and_exit $[ test ! $2 ; echo $Status] "none loaded" preinit_levels $TARGET_CARD || setglobal EXITSTATUS = '1' if ! restore_levels $TARGET_CARD { sanify_levels $TARGET_CARD || setglobal EXITSTATUS = '1' restore_levels $TARGET_CARD >/dev/null !2 > !1 || : } log_action_end_msg_and_exit $EXITSTATUS with stop setglobal EXITSTATUS = '0' setglobal TARGET_CARD = $2 match $TARGET_CARD { with ""|all setglobal TARGET_CARD = 'all' ; log_action_begin_msg "Shutting down ALSA" with * log_action_begin_msg "Shutting down ALSA card $(TARGET_CARD)" } card_OK $TARGET_CARD || log_action_end_msg_and_exit $[ test ! $2 ; echo $Status] "none loaded" store_levels $TARGET_CARD || setglobal EXITSTATUS = '1' #mute_and_zero_levels "$TARGET_CARD" || EXITSTATUS=1 log_action_end_msg_and_exit $EXITSTATUS with restart|force-reload setglobal EXITSTATUS = '0' $0 stop || setglobal EXITSTATUS = '1' $0 start || setglobal EXITSTATUS = '1' exit $EXITSTATUS with reset setglobal TARGET_CARD = $2 match $TARGET_CARD { with ""|all setglobal TARGET_CARD = 'all' ; log_action_begin_msg "Resetting ALSA" with * log_action_begin_msg "Resetting ALSA card $(TARGET_CARD)" } card_OK $TARGET_CARD || log_action_end_msg_and_exit $[ test ! $2 ; echo $Status] "none loaded" preinit_levels $TARGET_CARD sanify_levels $TARGET_CARD log_action_end_msg_and_exit "$Status" with * echo "Usage: $MYNAME {start [CARD]|stop [CARD]|restart [CARD]|reset [CARD]}" > !2 exit 3 }