#!/bin/sh
#
# alsasound     This shell script takes care of starting and stopping
#               the ALSA sound driver.
#
# This script requires /usr/sbin/alsactl program from alsa-utils package.
#
# Copyright (c) by Jaroslav Kysela <perex@suse.cz> 
#
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
# For RedHat 5.0+:
# chkconfig: 2345 87 14
# description: ALSA driver
#
# modified to visually fit into SuSE 6.0+ by Philipp Thomas <pthomas@suse.de>
# further improvements by Bernd Kaindl, Olaf Hering and Takashi Iwai.
# 
### BEGIN INIT INFO
# Provides:       alsasound
# Required-Start: $local_fs
# Should-Start: $remote_fs resmgr
# Required-Stop: $local_fs
# Should-Stop: $remote_fs resmgr
# Default-Start:  2 3 5
# Default-Stop:
# Short-Description: Set up ALSA sound system
# Description:    Loading ALSA drivers and store/restore the current setting
### END INIT INFO

. /etc/rc.status
. /etc/sysconfig/sound

# Shell functions sourced from /etc/rc.status:
#      rc_check         check and set local and overall rc status
#      rc_status        check and set local and overall rc status
#      rc_status -v     ditto but be verbose in local rc status
#      rc_status -v -r  ditto and clear the local rc status
#      rc_failed        set local and overall rc status to failed
#      rc_reset         clear local rc status (overall remains)
#      rc_exit          exit appropriate to overall rc status

# First reset status of this service
rc_reset

alsactl=/usr/sbin/alsactl
asoundcfg=/var/lib/alsa/asound.state
aconnect=/usr/bin/aconnect

get_drivers() {
  /sbin/modprobe -c | \
    grep -E "^[[:space:]]*alias[[:space:]]+snd-card-[[:digit:]]" | sort -u | \
    while read a b card; do
	echo $card
    done
}

#
# insert all sound modules
#
load_modules() {
  module_loaded=0
  c=""
  drivers=`get_drivers`
  for i in $drivers; do
    if [ $i != off ]; then
      if [ x$c = x ]; then
        echo -n ": "
	c=1
      fi
      echo -n " ${i##snd-}"
      /sbin/modprobe $i && module_loaded=1
    fi
  done
  rc_status -v -r
  test $module_loaded -eq 0 && return 1
  return 0
}

#
# rest of start action
#

# manual load and force to store the status
start_all() {
    echo -n "Starting sound driver"
    load_modules
    rc_status -r
}

do_kill() {
  fuser $* /dev/admmidi* /dev/adsp* /dev/amidi* /dev/audio* /dev/dmfm* \
     /dev/dmmidi* /dev/dsp* /dev/dspW* /dev/midi* /dev/mixer* /dev/music \
     /dev/patmgr* /dev/sequencer* /dev/sndstat >/dev/null 2>&1
  if [ -d /dev/snd ]; then
    fuser $* /dev/snd/* >/dev/null 2>&1
  fi
}

terminate() {
  #
  # Kill processes holding open sound devices
  #
  do_kill -TERM -k
  sleep 1
  do_kill -k

  #
  # remove all sequencer connections if any
  #
  if [ -f /proc/asound/seq/clients -a -x $aconnect ]; then
    $aconnect --removeall
  fi
}

# mute master to avoid clicks at unload/shutdown
mute_system() {
  /usr/bin/amixer set Master mute >/dev/null 2>&1
}

#
# remove all sound modules
#
unload_modules() {
  mute_system
  mod=$(grep -m1 -E '^(snd[^ ]*|ac97_bus) [0-9]+ 0' /proc/modules)
  while [ -n "$mod" ]; do
      mod=${mod%% *}
      /sbin/modprobe -r $mod
      mod=$(grep -m1 -E '^(snd[^ ]*|ac97_bus) [0-9]+ 0' /proc/modules)
  done
  rc_failed 0
}

unload_all() {
    echo -n "Shutting down sound driver"
    terminate
    unload_modules
    rc_status -v
}

stop_all() {
    if [ -d /proc/asound ]; then
	$alsactl -g -f $asoundcfg store
        unload_all
    fi
}

# See how we were called.
case "$1" in
  start)
	if test "$PREVLEVEL" = "N" -a -d /proc/asound ; then
	    # re-run alsactl when /var is a seprate partition (bnc#700781)
	    case $asoundcfg in
		/var/*)
		    grep -q " /var " /proc/mounts && \
			$alsactl -F -f $asoundcfg restore >/dev/null 2>&1
		    ;;
	    esac
	else
	    start_all
	fi
        ;;
  stop)
	if [ "$RUNLEVEL" = "6" -o "$RUNLEVEL" = "0" ]; then
	    if [ -d /proc/asound ]; then
		$alsactl -f $asoundcfg store
		# kill pulseaudio before muting the system (bnc#499445)
		if killall -q -TERM pulseaudio; then
		    usleep 200
		fi
		mute_system
	    fi
	else
	    stop_all
	fi
        ;;
  unload)
	test -d /proc/asound && unload_all
	;;
  reload|restart)
	stop_all
	start_all
	;;
  status)
        if [ -d /proc/asound ]; then
          echo -n "ALSA sound driver loaded."
          rc_status -v
        else
          echo -n "ALSA sound driver not loaded."
	  rc_status -u
        fi
        ;;
  *)
	echo "Usage: $0 {start|stop|restart|reload|unload|status}"
        exit 1
	;;
esac

rc_exit
