#!/bin/bash
### BEGIN INIT INFO
# Provides:          alsa-autoconfig
# Required-Start:
# Required-Stop:
# Default-Start:     S
# Default-Stop:      0 6
# Short-Description: Auto configures ALSA.
### END INIT INFO


# if set, we need to setup /etc/modutils/1alsa to change /etc/modules.conf
# to include the new path.
# there alsa should be under $ALSAPATH/alsa

ALSAPATH="/lib/modules/extra"
DEBUG=1
#GAUGE=1

if [ -n "$ALSAPATH" ]; 
then
cat << EOF > /etc/modutils/1alsa
path[]=$ALSAPATH/alsa
depfile=$ALSAPATH/modules.dep
generic_stringfile=$ALSAPATH/modules.generic_string
pcimapfile=$ALSAPATH/modules.pcimap
isapnpmapfile=$ALSAPATH/modules.isapnpmap
usbmapfile=$ALSAPATH/modules.usbmap
parportmapfile=$ALSAPATH/modules.parportmap
ieee1394mapfile=$ALSAPATH/modules.ieee1394map
pnpbiosmapfile=$ALSAPATH/modules.pnpbiosmap
EOF
  # Delete symlink
  rm -f /etc/modules.conf
  
  # Setup new modules.conf to have modprobe know alsa
  [ -n "$DEBUG" ] && echo Preparing modules for alsa...
  [ -n "$GAUGE" ] && echo 10

  #update-modules 2>/dev/null
  if [ "$1" = "init-knx" ]; # first run on master knx, so lets create modules.dep & co
  then
    echo "Preparing master knoppix for alsa..."
    update-modules 2>/dev/null
    rm /etc/modutils/1alsa
    update-modules
    exit 0
  fi
  
  [ -n "$GAUGE" ] && echo 30
else
  ALSAPATH="/lib/modules/"`uname -r`
fi

#alsaconf dependent part : (we only support pnp-pci cards)
# FIXME: start /etc/init.d/alsa ?

version="0.9.0-knoppix"
cfgfile="/etc/modutils/alsa-0.9-knoppix"

do_legacy_only=0
use_modinfo_db=0
do_logging=0
alsa_uid=0
alsa_gid=29
alsa_mode=0660
legacy_probe_card=""
LOGFILE="/tmp/alsaconf.log"
TESTSOUND="/usr/share/sounds/alsa/test.wav"
try_all_combination=0

alsa_device_opts=""
if [ x"$alsa_uid" != x0 ]; then
    alsa_device_opts="$alsa_device_opts ${mpfx}device_uid=$alsa_uid"
fi
if [ x"$alsa_gid" != x0 ]; then
    alsa_device_opts="$alsa_device_opts ${mpfx}device_gid=$alsa_gid"
fi
if [ x"$alsa_mode" != x0 ]; then
    alsa_device_opts="$alsa_device_opts ${mpfx}device_mode=$alsa_mode"
fi

# build card database
# build_card_db filename
function build_card_db()
{
  PCIMAPFILE=$ALSAPATH/modules.pcimap
  last_driver=""
  echo -n > $1

    # list pci cards
   
    # speed up by using grep
    cat $PCIMAPFILE | grep "snd-" | (while read driver vendor device dummy; do
	if expr $driver : 'snd-.*' >/dev/null ; then
	    if [ "$last_driver" != "$driver" ]; then
		echo $driver.o
		last_driver=$driver
	    fi
	    id1=`printf '0x%04x' $vendor`
	    id2=`printf '0x%04x' $device`
	    echo "PCI: $id1=$id2"
	fi
    done) >> $1
}

#
# probe cards
#
probe_cards () {
    CARDID_DB=/var/tmp/alsaconf.cards
    DEPFILE=$ALSAPATH/modules.dep
    if [ ! -r $CARDID_DB ]; then
        use_modinfo_db=1
    fi
    if [ $use_modinfo_db != 1 ]; then
	if [ $CARDID_DB -ot $DEPFILE ]; then
	    use_modinfo_db=1
	fi
    fi
    if [ $use_modinfo_db = 1 ]; then
	[ -n "$GAUGE" ] && echo "50"
	[ -n "$DEBUG" ] && echo "Building card database.."
	build_card_db $CARDID_DB
	[ -n "$GAUGE" ] && echo "60"
    fi
    if [ ! -r $CARDID_DB ]; then
	echo "No card database is found.."
	exit 1
    fi
    ncards=`grep '^snd-.*\.o$' $CARDID_DB | wc -w`

    awk '
BEGIN {
	format="%-40s %s\n";
	ncards='"$ncards"';
	idx=0;
}
/^snd-.*\.o$/{
	sub(/.o$/, "");
	driver=$0;
	perc=(idx * 100) / (ncards + 1);
	print perc;
	idx++;
}
/^[<literal space><literal tab>]*PCI: /{
	gsub(/0x/, "");
	gsub(/=/, ":");
	x = sprintf ("/bin/lspci -n | grep '"'Class 0401'"' | grep %s", $2);
	if (system (x) == 0)
		printf "%s %s\n", $2, driver >>"'"$FOUND"'"
}
/^[<literal space><literal tab>]*ISAPNP: /{
	gsub(/=.*/, "");
	x = sprintf ("grep '\''^Card [0-9] .%s:'\'' '"$DUMP"'", $2);
	if (system (x) == 0)
		printf "%s %s\n", $2, driver >>"'"$FOUND"'"
}' < $CARDID_DB > /dev/null # |\
    # $DIALOG --gauge "Searching sound cards" 6 40 0
}

#
# look for a descriptive device name from the given device id
#
find_device_name () {
    if expr "$1" : '[0-9a-f][0-9a-f][0-9a-f][0-9a-f]:[0-9a-f][0-9a-f][0-9a-f][0-9a-f]' >/dev/null; then
	/bin/lspci -d $1 | sed -e 's/^..:..\.. Multimedia audio controller: //g'
	return
    elif expr "$1" : '[A-Z@][A-Z@][A-Z@][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' >/dev/null; then
	cardname=`grep '^Card [0-9]\+ '\'$1':' $DUMP | head -1 | sed -e 's/^Card [0-9]\+ '\''.*:\(.*\)'\'' .*$/\1/'`
	echo $cardname
    else
	echo $1
    fi
}

#
# configure and try test sound
#
ac_config_card () {

    CARD_DRIVER=snd-$1
#    CARD_OPTS="${*:2}" # FIXME
    if [ -z "$CARD_OPTS" ]; then
	CARD_OPTS="${mpfx}index=0"
    else
	CARD_OPTS="${mpfx}index=0 $CARD_OPTS"
    fi

    # Configuration done

    # Copy conf.modules and make changes.
    ACB="# --- BEGIN: Generated by ALSACONF, do not edit. ---"
    ACE="# --- END: Generated by ALSACONF, do not edit. ---"

    # Detect 2.2.X kernel
    KVER=`uname -r | tr ".-" "  "`
    KVER1=`echo $KVER | cut -d" " -f1`
    KVER2=`echo $KVER | cut -d" " -f2`
    if [ $KVER1 -ge 2 ] && [ $KVER2 -ge 2 ]; then
	SOUND_CORE="soundcore"
    else
	SOUND_CORE="snd"
    fi

    echo "$ACB
# --- ALSACONF version $version ---
alias char-major-116 snd
alias snd-card-0 $CARD_DRIVER
alias char-major-14 $SOUND_CORE
alias sound-slot-0 snd-card-0
alias sound-service-0-0 snd-mixer-oss
alias sound-service-0-1 snd-seq-oss
alias sound-service-0-3 snd-pcm-oss
alias sound-service-0-8 snd-seq-oss
alias sound-service-0-12 snd-pcm-oss
options snd ${mpfx}major=116 ${mpfx}cards_limit=1$alsa_device_opts
options $CARD_DRIVER $CARD_OPTS
$ACE
" >> $TMP

#    if cp -f $cfgfile $cfgfile.old; then
#	:
#    else
#	echo "ERROR! $cfgfile could not be saved."
#	echo "Configured ALSA is in /tmp/alsaconf.saved."
#	cp $TMP /tmp/alsaconf.saved
#	exit 1
#    fi

    rm -f $cfgfile
    cp -f $TMP $cfgfile

    [ -n "$DEBUG" ] && echo Running update-modules...
    [ -n "$GAUGE" ] && echo 80
    update-modules 2>/dev/null
    touch -r $ALSAPATH/modules.dep /etc/modules.conf
    [ -n "$DEBUG" ] && echo "Creating snddevices..." 
    /usr/sbin/alsa_snddevices >/dev/null 2>/dev/null
    [ -n "$GAUGE" ] && echo 90
    
    #echo Loading driver...
    #/etc/init.d/alsa start

    # for kernel 2.6 we need to load the modules:
    KERNEL_26=""
    case $(uname -r) in 2.6.*) KERNEL_26="true" ;; esac
    if [ -n "$KERNEL_26" ]
    then
        echo Loading driver...
        modprobe snd
        modprobe $SOUND_CORE
        modprobe $CARD_DRIVER $CARD_OPTS
      
        for module in mixer pcm seq
        do
            modprobe "snd-${module}-oss" > /dev/null 2>&1
        done
    fi

    [ -n "$DEBUG" ] && echo Setting default volumes...
    if [ -x /usr/bin/set_default_volume ]; then
	/usr/bin/set_default_volume -f
    else
	#set_mixers
	aumix -m 0 -v 70 -w 70 # set pcm & master to 60, micro to 0
    fi
    [ -n "$GAUGE" ] && echo 100
}

# Make temp files
function alsaconf_init()
{
TMP=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	echo "$0: Can't create temp file, exiting..."
        exit 1
fi
FOUND=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	echo "$0: Can't create temp file, exiting..."
        exit 1
fi
DUMP=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	echo "$0: Can't create temp file, exiting..."
        exit 1
fi
}

cleanup () {
    rm -f "$TMP" "$FOUND" "$DUMP"
}
trap cleanup 0 
alsaconf_init

if [ -z "$ALSA_CARD" ]; 
then
probe_cards

devs_found=()

if [ -s "$FOUND" ]; then
    while read dev card ; do
	#/sbin/modprobe -a -l | grep $card'\.o' >/dev/null 2>&1 || continue
	#cardname=`find_device_name $dev | cut -c 1-64`
	#if [ -z "$cardname" ]; then
	#    cardname="$card"
	#fi
	card=${card##snd-}
        [ -n "$DEBUG" ] && echo "Configuring $card..."
        [ -n "$GAUGE" ] && echo 70
	ac_config_card $card
	# FIXME: we (and alsaconf) support just the first card atm.
	break
    done <"$FOUND"
fi
else
  echo "Configuring $ALSA_CARD (cmdline set)"
  ac_config_card $ALSA_CARD
fi
