#!/bin/sh

set -e

PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin

if [ "$(id -u)" != "0" -a "$1" != "--help" -a "$1" != "help" -a ! -z "$1" ]; then
    echo "$0: To $1 ALSA, you must be root."
    exit 1
fi

# Which version of the tools are we using?
rmmod=""
modfile=""
case "$(modprobe --version 2>&1)" in
	modprobe*)
		rmmod="rmmod -r"
		modfile="/etc/modules.conf"
	;;
	module-init-tools*)
		rmmod="modprobe -r"
		if [ -s /lib/modules/modprobe.conf ]; then
			modfile="/lib/modules/modprobe.conf"
		else
			modfile="/etc/modules.conf"
		fi
	;;
esac

# Auto detect starting OSS layer
if [ ! -f /proc/sys/kernel/modprobe -o -c /dev/.devfsd ]; then
	startosslayer="true"
else
	startosslayer="false"
fi
# Populate some defaults in case /etc/default/alsa goes for a wander.
force_stop_modules_before_suspend="false"
alsactl_store_on_shutdown="true"

[ -e /etc/default/alsa ] && . /etc/default/alsa
# $ALSA_KILL_OVERRIDE is only for use by this script, please don't set it
# yourself in /etc/default/alsa :)
if [ "$ALSA_KILL_OVERRIDE" = "force" ]; then
    export ALSA_KILL_OVERRIDE
    ALSA_KILL_MODE=force
elif [ ! -z "$ALSA_KILL_OVERRIDE" ]; then
    export ALSA_KILL_OVERRIDE
    ALSA_KILL_MODE=none
fi

case "$1" in
    start)
	if [ -f /proc/asound/version ]; then
	    alsa_version="$(head -1 /proc/asound/version | cut -f7 -d" " | sed 's/\(.*\)\.$/\1/')"
	elif modprobe snd > /dev/null 2>&1; then
	    if [ -f /proc/asound/version ]; then
		alsa_version="$(head -1 /proc/asound/version | cut -f7 -d" " | sed 's/\(.*\)\.$/\1/')"
	    else
		echo "Starting ALSA (unknown version): failed - internal error 1"
		exit 1
	    fi
	else
	    echo "Starting ALSA (unknown version): failed - ALSA modules not installed"
	    exit 1
	fi

	printf "Starting ALSA (version %s):" "$alsa_version"

	module_list="$(grep -E "^[[:space:]]*(alias|probe)[[:space:]]+snd-card-[0-9]+" \
		       $modfile | grep -Ev '\b(off|none)\b' | sort -u | awk '{print $3}')"
	cards_exist=false
	if [ -d /proc/asound/card0 ]; then
		printf " ALSA appears to be compiled statically"
		cards_exist=true
	elif [ -z "$module_list" ]; then
		printf " warning, no drivers defined in %s" "$modfile"
	else
	    for module in $module_list; do
		module_name="${module#*-}"
		if modprobe "$module" > /dev/null 2>&1; then
		    printf " %s" "$module_name"
		    cards_exist=true
		else
		    printf " %s-failed" "$module_name"
		fi
	    done
	fi
	if [ "$cards_exist" = "true" ]; then
	    echo "."
	else
	    echo " failed"
	    exit
	fi
	
	if [ ! -L /dev/sndstat ] && [ ! -e /dev/.devfsd ]; then
	    rm -f /dev/sndstat && ln -s /proc/asound/oss/sndstat /dev/sndstat
	fi

	if [ "$startosslayer" = "true" ]; then
	    for module in mixer pcm seq; do
		modprobe "snd-${module}-oss" > /dev/null 2>&1 || true
	    done
	fi

	if [ "$alsactl_store_on_shutdown" = "true" ]; then
	    printf "Restoring ALSA mixer settings ... "
	    if alsactl restore > /dev/null 2>&1; then
		echo "done."
	    else
		echo "failed"
		exit 1
	    fi
	fi
	;;
    stop)
	if [ -d /proc/asound ]; then
	    if [ "$alsactl_store_on_shutdown" = "true" ]; then
		printf "Storing ALSA mixer settings ... "
		if alsactl store > /dev/null 2>&1; then
		    sleep 1
		    echo "done."
		else
		    echo "failed"
		fi
	    fi

	    if [ -f /proc/asound/version ]; then
		alsa_version="$(head -1 /proc/asound/version | cut -f7 -d" " | sed 's/\(.*\)\.$/\1/')"
	    else
		echo "Shutting down ALSA (unknown version): failed - internal error 3"
		exit 1
	    fi

	    printf "Shutting down ALSA (version %s): " "$alsa_version"
	    procs_using_sound="$(lsof +D /dev -F rt | awk '/^p/ {pid=$1} /^t/ {type=$1} /^r0x(74|e)..$/ && type == "tCHR" {print pid}' | cut -c 2- | uniq)"
	    if [ ! -z "$procs_using_sound" ]; then
		if [ "$ALSA_KILL_MODE" = force ]; then
		    printf "(terminating processes) "
		    kill $procs_using_sound
		    sleep 2
		    kill -9 $procs_using_sound
		else
		    printf "aborting. (sound used by PIDs %s)\n" "$procs_using_sound"
		    exit 1
		fi
	    fi

	    for i in $(lsmod | awk '/^snd/ {print $1}'); do
			$rmmod $i >/dev/null 2>&1 || :
		done
	    echo "done."
	else
	    echo "Shutting down ALSA (unknown version): not running"
	fi
	;;
    restart|reload)
	$0 stop && $0 start
	;;
    force-*)
	ALSA_KILL_OVERRIDE="force" $0 "${1#*-}"
	;;
    *)
	echo "Usage: /etc/init.d/alsa {start|stop|restart|reload|force-stop|force-restart|force-reload}"
	exit 1
	;;
esac
