home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / etc / init.d / alsa-utils < prev    next >
Encoding:
Text File  |  2006-07-30  |  9.1 KB  |  376 lines

  1. #!/bin/sh
  2. #
  3. # alsa-utils initscript
  4. #
  5. ### BEGIN INIT INFO
  6. # Provides:          alsa-utils
  7. # Required-Start:    mountall
  8. # Required-Stop:     mountall
  9. # Should-Start:
  10. # Should-Stop:
  11. # Default-Start:     S
  12. # Default-Stop:      0 6
  13. # Short-Description: Restore and store ALSA driver settings
  14. # Description:       This script stores and restores mixer levels on
  15. #                    shutdown and bootup.On sysv-rc systems: to
  16. #                    disable storing of mixer levels on shutdown,
  17. #                    remove /etc/rc[06].d/K50alsa-utils.  To disable
  18. #                    restoring of mixer levels on bootup, rename the
  19. #                    "S50alsa-utils" symbolic link in /etc/rcS.d/ to
  20. #                    "K50alsa-utils".
  21. ### END INIT INFO
  22.  
  23. # Don't use set -e; check exit status instead
  24.  
  25. # Exit silently if package is no longer installed
  26. [ -x /sbin/alsactl ] || exit 0
  27.  
  28. PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  29. MYNAME=/etc/init.d/alsa-utils
  30.  
  31. . /lib/lsb/init-functions
  32.  
  33. # $1 EXITSTATUS
  34. # [$2 MESSAGE]
  35. log_action_end_msg_and_exit()
  36. {
  37.     log_action_end_msg "$1" ${2:+"$2"}
  38.     exit $1
  39. }
  40.  
  41. # $1 PROGRAM
  42. executable()
  43. {
  44.     # If which is not available then we must be running before
  45.     # /usr is mounted on a system that has which in /usr/bin/.
  46.     # Conclude that $1 is not executable.
  47.     [ -x /bin/which ] || [ -x /usr/bin/which ] || return 1
  48.     which "$1" >/dev/null 2>&1
  49. }
  50.  
  51. # Wait for filesystems to show up
  52. while [ ! -d /usr/bin -o ! -d /var/lib/alsa ]; do
  53.     sleep 0.2
  54. done
  55.  
  56. executable amixer || { echo "${MYNAME}: Error: No amixer program available." >&2 ; exit 1 ; }
  57.  
  58. bugout() { echo "${MYNAME}: Programming error" >&2 ; exit 123 ; }
  59.  
  60. # $1 <card ID> | "all"
  61. restore_levels()
  62. {
  63.     [ -f /var/lib/alsa/asound.state ] || return 1
  64.     CARD="$1"
  65.     [ "$1" = all ] && CARD=""
  66.     # Assume that if alsactl prints a message on stderr
  67.     # then it failed somehow.  This works around the fact
  68.     # that alsactl doesn't return nonzero status when it
  69.     # can't restore settings for the card
  70.     if MSG="$(alsactl restore $CARD 2>&1 >/dev/null)" && [ ! "$MSG" ] ; then
  71.         return 0
  72.     else
  73.         # Retry with the "force" option.  This restores more levels
  74.         # but it results in much longer error messages.
  75.         alsactl -F restore $CARD >/dev/null 2>&1
  76.         [ -z "$CARD" ] && log_action_cont_msg "warning: 'alsactl restore' failed with error message '$MSG'"
  77.         return 1
  78.     fi
  79. }
  80.  
  81. # $1 <card ID> | "all"
  82. store_levels()
  83. {
  84.     CARD="$1"
  85.     [ "$1" = all ] && CARD=""
  86.     if MSG="$(alsactl store $CARD 2>&1)" ; then
  87.         sleep 1
  88.         return 0
  89.     else
  90.         [ -z "$CARD" ] && log_action_cont_msg "warning: 'alsactl store' failed with error message '$MSG'"
  91.         return 1
  92.     fi
  93. }
  94.  
  95. echo_card_indices()
  96. {
  97.     if [ -f /proc/asound/cards ] ; then
  98.         sed -n -e's/^[[:space:]]*\([0-7]\)[[:space:]].*/\1/p' /proc/asound/cards
  99.     fi
  100. }
  101.  
  102. filter_amixer_output()
  103. {
  104.     sed \
  105.         -e '/Unable to find simple control/d' \
  106.         -e '/Unknown playback setup/d' \
  107.         -e '/^$/d'
  108. }
  109.  
  110. # The following functions try to set many controls.
  111. # No card has all the controls and so some of the attempts are bound to fail.
  112. # Because of this, the functions can't return useful status values.
  113.  
  114. # $1 <control>
  115. # $2 <level>
  116. # $CARDOPT
  117. unmute_and_set_level()
  118. {
  119.     { [ "$2" ] && [ "$CARDOPT" ] ; } || bugout
  120.     amixer $CARDOPT -q set "$1" "$2" unmute 2>&1 | filter_amixer_output || :
  121.     return 0
  122. }
  123.  
  124. # $1 <control>
  125. # $CARDOPT
  126. mute_and_zero_level()
  127. {
  128.     { [ "$1" ] && [ "$CARDOPT" ] ; } || bugout
  129.     amixer $CARDOPT -q set "$1" "0%" mute 2>&1 | filter_amixer_output || :
  130.     return 0
  131. }
  132.  
  133. # $1 <control>
  134. # $2 "on" | "off"
  135. # $CARDOPT
  136. switch_control()
  137. {
  138.     { [ "$2" ] && [ "$CARDOPT" ] ; } || bugout
  139.     amixer $CARDOPT -q set "$1" "$2" 2>&1 | filter_amixer_output || :
  140.     return 0
  141. }
  142.  
  143. # $1 <card ID>
  144. sanify_levels_on_card()
  145. {
  146.     CARDOPT="-c $1"
  147.  
  148.     unmute_and_set_level "Master" "80%"
  149.     unmute_and_set_level "Master Digital" "80%"   # E.g., cs4237B
  150.     unmute_and_set_level "Playback" "80%"
  151.     unmute_and_set_level "Headphone" "70%"
  152.     unmute_and_set_level "PCM" "80%"
  153.     unmute_and_set_level "PCM,1" "80%"   # E.g., ess1969
  154.     unmute_and_set_level "DAC" "80%"     # E.g., envy24, cs46xx
  155.     unmute_and_set_level "DAC,0" "80%"   # E.g., envy24
  156.     unmute_and_set_level "DAC,1" "80%"   # E.g., envy24
  157.     unmute_and_set_level "Synth" "80%"
  158.     unmute_and_set_level "CD" "80%"
  159.  
  160.     mute_and_zero_level "Mic"
  161.  
  162.     # Intel P4P800-MX  (Ubuntu bug #5813)
  163.     switch_control "Master Playback Switch" on
  164.  
  165.     # Trident/YMFPCI/emu10k1:
  166.     unmute_and_set_level "Wave" "80%"
  167.     unmute_and_set_level "Music" "80%"
  168.     unmute_and_set_level "AC97" "80%"
  169.  
  170.     # DRC:
  171.     unmute_and_set_level "Dynamic Range Compression" "80%"
  172.  
  173.     # Required for HDA Intel (hda-intel):
  174.     unmute_and_set_level "Front" "80%"
  175.  
  176.     # Required for SB Live 7.1/24-bit (ca0106):
  177.     unmute_and_set_level "Analog Front" "80%"
  178.  
  179.     # Required at least for Via 823x hardware on DFI K8M800-MLVF Motherboard with kernels 2.6.10-3/4 (see ubuntu #7286):
  180.     switch_control "IEC958 Capture Monitor" off
  181.  
  182.     # Required for hardware allowing toggles for AC97 through IEC958,
  183.     #  valid values are 0, 1, 2, 3. Needs to be set to 0 for PCM1.
  184.     unmute_and_set_level "IEC958 Playback AC97-SPSA" "0"
  185.  
  186.     # Required for newer Via hardware (see Ubuntu #31784)
  187.     unmute_and_set_level "VIA DXS,0" "80%"
  188.     unmute_and_set_level "VIA DXS,1" "80%"
  189.     unmute_and_set_level "VIA DXS,2" "80%"
  190.     unmute_and_set_level "VIA DXS,3" "80%"
  191.  
  192.     # Required on some notebooks with ICH4:
  193.     switch_control "Headphone Jack Sense" off
  194.     switch_control "Line Jack Sense" off
  195.  
  196.     # Some machines need one or more of these to be on;
  197.     # others need one or more of these to be off:
  198.     #
  199.     # switch_control "External Amplifier" on
  200.     # switch_control "Audigy Analog/Digital Output Jack" on
  201.     # switch_control "SB Live Analog/Digital Output Jack" on
  202.  
  203.     return 0
  204. }
  205.  
  206. # $1 <card ID> | "all"
  207. sanify_levels()
  208. {
  209.     TTSDML_RETURNSTATUS=0
  210.     case "$1" in
  211.       all)
  212.         for CARD in $(echo_card_indices) ; do
  213.             sanify_levels_on_card "$CARD" || TTSDML_RETURNSTATUS=1
  214.         done
  215.         ;;
  216.       *)
  217.         sanify_levels_on_card "$1" || TTSDML_RETURNSTATUS=1
  218.         ;;
  219.     esac
  220.     return $TTSDML_RETURNSTATUS
  221. }
  222.  
  223. # $1 <card ID>
  224. preinit_levels_on_card()
  225. {
  226.     CARDOPT="-c $1"
  227.  
  228.     # Silly dance to activate internal speakers by default on PowerMac
  229.     # Snapper and Tumbler
  230.     id=`cat /proc/asound/card$1/id 2>/dev/null`
  231.     if [ "$id" = "Snapper" -o "$id" = "Tumbler" ]; then
  232.         switch_control "Auto Mute" off
  233.         switch_control "PC Speaker" off
  234.         switch_control "Auto Mute" on
  235.     fi
  236. }
  237.  
  238. # $1 <card ID> | "all"
  239. preinit_levels()
  240. {
  241.     TTSDML_RETURNSTATUS=0
  242.     case "$1" in
  243.       all)
  244.         for CARD in $(echo_card_indices) ; do
  245.             preinit_levels_on_card "$CARD" || TTSDML_RETURNSTATUS=1
  246.         done
  247.         ;;
  248.       *)
  249.         preinit_levels_on_card "$1" || TTSDML_RETURNSTATUS=1
  250.         ;;
  251.     esac
  252.     return $TTSDML_RETURNSTATUS
  253. }
  254.  
  255. # $1 <card ID>
  256. mute_and_zero_levels_on_card()
  257. {
  258.     CARDOPT="-c $1"
  259.     for CTL in \
  260.         Master \
  261.         PCM \
  262.         Synth \
  263.         CD \
  264.         Line \
  265.         Mic \
  266.         "PCM,1" \
  267.         Wave \
  268.         Music \
  269.         AC97 \
  270.         "Master Digital" \
  271.         DAC \
  272.         "DAC,0" \
  273.         "DAC,1" \
  274.         Headphone \
  275.         Playback
  276.     do
  277.         mute_and_zero_level "$CTL"
  278.     done
  279.     for CTL in \
  280.         "Audigy Analog/Digital Output Jack" \
  281.         "SB Live Analog/Digital Output Jack"
  282.     do
  283.         switch_control "$CTL" off
  284.     done
  285.     return 0
  286. }
  287.  
  288. # $1 <card ID> | "all"
  289. mute_and_zero_levels()
  290. {
  291.     TTZML_RETURNSTATUS=0
  292.     case "$1" in
  293.       all)
  294.         for CARD in $(echo_card_indices) ; do
  295.             mute_and_zero_levels_on_card "$CARD" || TTZML_RETURNSTATUS=1
  296.         done
  297.         ;;
  298.       *)
  299.         mute_and_zero_levels_on_card "$1" || TTZML_RETURNSTATUS=1
  300.         ;;
  301.     esac
  302.     return $TTZML_RETURNSTATUS
  303. }
  304.  
  305.  
  306. # $1 <card ID> | "all"
  307. card_OK()
  308. {
  309.     [ "$1" ] || bugout
  310.     if [ "$1" = all ] ; then
  311.         [ -d /proc/asound ]
  312.         return $?
  313.     else
  314.         [ -d "/proc/asound/card$1" ] || [ -d "/proc/asound/$1" ]
  315.         return $?
  316.     fi
  317. }
  318.  
  319. # If a card identifier is provided in $2 then regard it as an error
  320. # if that card is not present; otherwise don't regard it as an error.
  321.  
  322. case "$1" in
  323.   start)
  324.     EXITSTATUS=0
  325.     TARGET_CARD="$2"
  326.     case "$TARGET_CARD" in
  327.       ""|all) TARGET_CARD=all ; log_action_begin_msg "Setting up ALSA" ;;
  328.     esac
  329.     if ! card_OK "$TARGET_CARD"; then
  330.         [ "$TARGET_CARD" = "all" ] && log_action_end_msg "$( [ ! "$2" ] ; echo $? ; )" "none loaded"
  331.         exit $?
  332.     fi
  333.     preinit_levels "$TARGET_CARD" || EXITSTATUS=1
  334.     if ! restore_levels "$TARGET_CARD" ; then
  335.         sanify_levels "$TARGET_CARD" || EXITSTATUS=1
  336.         restore_levels "$TARGET_CARD" >/dev/null 2>&1 || :
  337.     fi
  338.     [ "$TARGET_CARD" = "all" ] && log_action_end_msg_and_exit "$EXITSTATUS"
  339.     exit $EXITSTATUS
  340.     ;;
  341.   stop)
  342.     EXITSTATUS=0
  343.     TARGET_CARD="$2"
  344.     case "$TARGET_CARD" in
  345.       ""|all) TARGET_CARD=all ; log_action_begin_msg "Shutting down ALSA" ;;
  346.       *) log_action_begin_msg "Shutting down ALSA card ${TARGET_CARD}" ;;
  347.     esac
  348.     card_OK "$TARGET_CARD" || log_action_end_msg_and_exit "$( [ ! "$2" ] ; echo $? ; )" "none loaded"
  349.     store_levels "$TARGET_CARD" || EXITSTATUS=1
  350.     mute_and_zero_levels "$TARGET_CARD" || EXITSTATUS=1
  351.     log_action_end_msg_and_exit "$EXITSTATUS"
  352.     ;;
  353.   restart|force-reload)
  354.     EXITSTATUS=0
  355.     $0 stop || EXITSTATUS=1
  356.     $0 start || EXITSTATUS=1
  357.     exit $EXITSTATUS
  358.     ;;
  359.   reset)
  360.     TARGET_CARD="$2"
  361.     case "$TARGET_CARD" in
  362.       ""|all) TARGET_CARD=all ; log_action_begin_msg "Resetting ALSA" ;;
  363.       *) log_action_begin_msg "Resetting ALSA card ${TARGET_CARD}" ;;
  364.     esac
  365.     card_OK "$TARGET_CARD" || log_action_end_msg_and_exit "$( [ ! "$2" ] ; echo $? ; )" "none loaded"
  366.     preinit_levels "$TARGET_CARD"
  367.     sanify_levels "$TARGET_CARD"
  368.     log_action_end_msg_and_exit "$?"
  369.     ;;
  370.   *)
  371.     echo "Usage: $MYNAME {start [CARD]|stop [CARD]|restart [CARD]|reset [CARD]}" >&2
  372.     exit 3
  373.     ;;
  374. esac
  375.  
  376.