#!/bin/bash
#
#  ALSA Configurator
#
#  Copyright (c) 1999-2002  SuSE GmbH
#                           Jan ONDREJ
#
#  written by Takashi Iwai <tiwai@suse.de>
#             Bernd Kaindl <bk@suse.de>
#             Jan ONDREJ (SAL) <ondrejj@salstar.sk>
#
#  based on the original version of Jan ONDREJ's alsaconf for ALSA 0.4.
#
#  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.
#
#BK hacked for puppy linux 4.02, may 2008.
#v425 fix for busybox depmod.
#101015 BK various fixes. depmod now full version. config is now /etc/modprobe.d/alsa.conf
#101015, 101017 using Xdialog and gtkdialog-splash instead of dialog and echo.
#110102 shinobar: precaution, check if need to run depmod.
#110405 fix 'free' applet output format different in later versions of busybox.
#110506 /etc/init.d/10alsa name fix, but this fix might break alsaconf as option 'stop' then 'restart' might not be handled properly in 10alsa.
#110509 rerwin: take version from alsacctl.
#110509 rerwin: remove sound card entry in /etc/modprobe.d/alsa.conf before writing it.
#110519 warning msg that reboot may be required.
#120201 rodin.s: update internationalized.
#120329 Xdialog bug --yesno supposed to "yes" "No" buttons, but they are "OK" "Cancel".

#101015 check for low ram, warn full depmod may not work... 110405...
#FREEMEM=`free | tr -s ' ' | grep -o 'Total: [0-9]*' | cut -f 2 -d ' '`
memTOTALK=`free | grep -o 'Mem: .*' | tr -s ' ' | cut -f 2 -d ' '`
swapTOTALK=`free | grep -o 'Swap: .*' | tr -s ' ' | cut -f 2 -d ' '`
TOTALMEM=`expr $memTOTALK + $swapTOTALK`
#rodin.s: removed later in script for i18n
#if [ $TOTALMEM -lt 99000 ];then
# yaf-splash -placement center -bg pink -close box -text "This computer has very little RAM, perhaps not enough to run the 'depmod' utility (which the ALSA Wizard needs to run). Shutdown first, to create a save-file for the session, and you may then have enough working memory at the next boot. Click button to exit Wizard..."
# exit
#fi

cfgfile="/etc/modprobe.d/alsa.conf" #101014
touch /etc/modprobe.d/alsa.conf

MYLANG=$LANG
export LANG=C #to keep Xdialog happy. 120329 this should be removed, then remove all the LANG=$MYLANG prefixes.
export TEXTDOMAIN=alsaconf
export OUTPUT_CHARSET=UTF-8
#export XDIALOG_HIGH_DIALOG_COMPAT=1 #101015 # rodin.s: comment out for better layout in Russian
#DIALOG=dialog
DIALOG='Xdialog' #101015

Yes_lbl="$(LANG=$MYLANG gettext 'Yes')"
No_lbl="$(LANG=$MYLANG gettext 'No')"

prefix=/usr
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
sbindir=${exec_prefix}/sbin
#version=1.0.23 #
version="`alsactl --version | cut -f 3 -d ' '`" #110509 rerwin
USE_NLS=yes

# Useful for debugging
PROCFS="/proc"
SYSFS="/sys"

# i18n stuff
if test "$USE_NLS" = "yes" && which gettext > /dev/null; then
  xecho() {
    LANG=$MYLANG gettext -s "$*"
  }
else
  xecho() {
    echo "$*"
  }
  gettext() {
    echo -n "$*"
  }
fi
xmsg() {
  msg=$(LANG=$MYLANG  gettext "$1")
  shift
  printf "$msg" $*
}
# moved it here for gettext to work - rodin.s
if [ $TOTALMEM -lt 99000 ];then
 yaf-splash -placement center -bg pink -close box -text "$(xmsg 'This computer has very little RAM, perhaps not enough to run the "depmod" utility (which the ALSA Wizard needs to run). Shutdown first, to create a save-file for the session, and you may then have enough working memory at the next boot. Click button to exit Wizard...')"
 exit
fi

# Check for GNU/Linux distributions BK...
distribution="unknown"

for prog in lspci lsmod; do
	for path in /sbin /usr/sbin /bin /usr/bin;do
		test -x $path/$prog && eval $prog=$path/$prog
	done
done
unset prog path

usage() {
    xecho "ALSA configurator"
    echo "  version $version"
    xecho "usage: alsaconf [options]
  -l|--legacy    check only legacy non-isapnp cards
  -m|--modinfo   read module descriptions instead of reading card db
  -s|--sound wav-file
                 use the specified wav file as a test sound
  -u|--uid uid   set the uid for the ALSA devices (default = 0) [obsoleted]
  -g|--gid gid   set the gid for the ALSA devices (default = 0) [obsoleted]
  -d|--devmode mode
                 set the permission for ALSA devices (default = 0666) [obs.]
  -r|--strict    set strict device mode (equiv. with -g 17 -d 0660) [obsoleted]
  -L|--log file  logging on the specified file (for debugging purpose only)
  -p|--probe card-name
                 probe a legacy non-isapnp card and print module options
  -P|--listprobe list the supported legacy card modules
  -c|--config file
                 specify the module config file
  -R|--resources list available DMA and IRQ resources with debug for legacy
  -h|--help      what you're reading"
}

OPTS=`getopt -o lmL:hp:Pu:g:d:rs:c:R --long legacy,modinfo,log:,help,probe:,listprobe,uid:,gid:,devmode:,strict,sound:,config:,resources -n alsaconf -- "$@"` || exit 1
eval set -- "$OPTS"

do_legacy_only=0
use_modinfo_db=0
alsa_uid=0
alsa_gid=0
alsa_mode=0666
legacy_probe_card=""
LOGFILE=""
TESTSOUND="/usr/share/audio/2barks.au" #BK
try_all_combination=0
resources="false"

# legacy support
LEGACY_CARDS="opl3sa2 cs4236 cs4232 cs4231 es18xx es1688 sb16 sb8"

while true ; do
    case "$1" in
    -l|--legacy)
	do_legacy_only=1; shift ;;
    -m|--modinfo)
	use_modinfo_db=1; shift ;;
    -s|--sound)
	TESTSOUND=$2; shift 2;;
    -h|--help)
	usage; exit 0 ;;
    -L|--log)
	LOGFILE="$2"; shift 2;;
    -p|--probe)
	legacy_probe_card="$2"; shift 2;;
    -P|--listprobe)
	echo "$LEGACY_CARDS"; exit 0;;
    -u|--uid)
	alsa_uid="$2"; shift 2;;
    -g|--gid)
	alsa_gid="$2"; shift 2;;
    -d|--devmode)
	alsa_mode="$2"; shift 2;;
    -r|--strict)
	alsa_uid=0; alsa_gid=17; alsa_mode=0660; shift;;
    -c|--config)
	cfgfile="$2"; shift 2;;
    -R|--resources)
        resources="true"; shift;;
    --) shift ; break ;;
    *) usage ; exit 1 ;;
    esac
done

#
# probe legacy ISA cards
#

check_dma_avail () {
    list=""
    if [ -d $SYSFS/bus/pnp/devices ]; then
      for dma in $*; do
        ok="true"
        for i in $SYSFS/bus/pnp/devices/??:* ; do
          if grep -q "state = active" $i/resources ; then
            if grep -q '^dma '$dma'$' $i/resources; then
              ok="false"
            fi
          fi
        done
        if [ -r $PROCFS/dma ]; then
	  if grep -q '^ *'$dma': ' $PROCFS/dma ; then
            ok="false"
          fi
	fi
        if [ "$ok" = "true" ]; then
          list="$list $dma"
        fi
      done
    else
      if [ -r $PROCFS/dma ]; then
  	for dma in $*; do
	    grep -q '^ *'$dma': ' $PROCFS/dma || list="$list $dma"
	done
      fi
    fi
    if [ ! -z "$list" ]; then
      echo $list
    fi
}

check_irq_avail () {
    list=""
    if [ -d $SYSFS/bus/pnp/devices ]; then
      for irq in $*; do
        ok="true"
        for i in $SYSFS/bus/pnp/devices/??:* ; do
          if grep -q "state = active" $i/resources ; then
            if grep -q '^irq '$irq'$' $i/resources; then
              ok="false"
            fi
          fi
        done
        if [ -r $PROCFS/interrupts ]; then
	  if grep -q '^ *'$irq': ' $PROCFS/interrupts ; then
            ok="false"
          fi
	fi
        if [ "$ok" = "true" ]; then
          list="$list $irq"
        fi
      done
    else
      if [ -r $PROCFS/interrupts ]; then
	for irq in $*; do
	    grep -q '^ *'$irq': ' $PROCFS/interrupts || list="$list $irq"
	done
      fi
    fi
    if [ ! -z "$list" ]; then
      echo $list
    fi
}

#
#
#

if [ "$resources" = "true" ]; then
  if [ -d $SYSFS/bus/pnp/devices ]; then
    for i in $SYSFS/bus/pnp/devices/??:* ; do
      if [ "$resources" = "true" ]; then
        echo ">>>>> PnP file: $i/resources"
        cat $i/resources
      fi
    done
  fi
  if [ -r $PROCFS/dma ]; then
    echo ">>>>> Allocated dma channels:"
    cat $PROCFS/dma
  fi
  if [ -r $PROCFS/interrupts ]; then
    echo ">>>>> Allocated interrupt channels:"
    cat $PROCFS/interrupts
  fi
  echo -n "Valid DMA channels: "
  check_dma_avail 0 1 2 3 4 5 6 7
  echo -n "Valid IRQ channels: "
  check_irq_avail 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  exit 0
fi

# Check for root privileges
if [ `id -u` -ne 0 ]; then
  xecho "You must be root to use this script."
  yaf-splash -placement center -bg pink -close box -text "$(xmsg 'You must be root to use this script.')"
  exit 1
fi

#
# check the snd_ prefix for ALSA module options
# snd_ prefix is obsoleted since 0.9.0rc4.
#
if /sbin/modinfo -p snd | grep -q snd_ ; then
  mpfx="snd_"
else
  mpfx=""
fi

alsa_device_opts=""
if /sbin/modinfo -p snd | grep -q uid ; then
  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
fi
if /sbin/modinfo -p snd | grep -q device_mode ; then
  if [ x"$alsa_mode" != x0 ]; then
    alsa_device_opts="$alsa_device_opts ${mpfx}device_mode=$alsa_mode"
  fi
fi

#
# remove the previous configuration by alsaconf
#
#remove_ac_block() {
#    awk '/^'"$ACB"'$/,/^'"$ACE"'$/ { next } { print }'
#}
remove_ac_block() {
    awk '/^'"$ACB"'$/,/^'"$ACE"'$/ { next }
    /^'"alias snd-card-0"'/ { next }
    /^'"alias sound-slot-0"'/ { next }
    { print }'
} #110509 rerwin: remove sound card entry in /etc/modprobe.d/alsa.conf before writing it.

#
# set default mixer volumes
#101015 BK had to add ,0 after Front...
set_mixers() {
    amixer -s -q <<EOF
set Master 75% unmute
set Master -12dB
set 'Master Mono' 75% unmute
set 'Master Mono' -12dB
set Front,0 75% unmute
set Front,0 -12dB
set PCM 90% unmute
set PCM 0dB
mixer Synth 90% unmute
mixer Synth 0dB
mixer CD 90% unmute
mixer CD 0dB
# mute mic
set Mic 0% mute
# ESS 1969 chipset has 2 PCM channels
set PCM,1 90% unmute
set PCM,1 0dB
# Trident/YMFPCI/emu10k1
set Wave 100% unmute
set Music 100% unmute
set AC97 100% unmute
# CS4237B chipset:
set 'Master Digital' 75% unmute
# Envy24 chips with analog outs
set DAC 90% unmute
set DAC -12dB
set DAC,0 90% unmute
set DAC,0 -12dB
set DAC,1 90% unmute
set DAC,1 -12dB
# some notebooks use headphone instead of master
set Headphone 75% unmute
set Headphone -12dB
set Playback 100% unmute
# turn off digital switches
set "SB Live Analog/Digital Output Jack" off
set "Audigy Analog/Digital Output Jack" off
EOF
}


# INTRO BK...
intro() {
  local msg=$(xmsg "
                   ALSA  WIZARD
                   version %s

            This Wizard is a configurator for
    Advanced Linux Sound Architecture (ALSA) driver.
       (with some modifications for Puppy Linux)

  If any are running, you should close all sound
  apps now (like Mplayer, mhWaveEdit, etc.).
  " $version)
  echo "Getting started..." #101017
  $DIALOG --title "ALSA Sound Wizard" --cr-wrap --msgbox "$msg" 20 63 || acex 0
}

# FAREWELL BK...
farewell() {
  local msg=$(xmsg "

     OK, sound driver is configured.

                  ALSA  WIZARD
          will prepare the card for playing now.

Technical: \"/etc/init.d/10alsa start\" will be used to
           initialise ALSA, amixer used to raise volume.

     You can change the volume later via a mixer
     program such as Retrovol (Multimedia menu), or
     click on speaker icon in tray for volume slider.
  ")
  echo "Sound driver configured." #101017
  $DIALOG --title "ALSA Sound Wizard" --cr-wrap --msgbox "$msg" 20 60 || acex 0
}

# Exit function
acex() {
  cleanup
  clear
  exit $1
}

#
# search for alsasound init script
#
    #BK...
    #rcalsasound="/etc/rc.d/rc.alsa"
    #w468...
    rcalsasound="/etc/init.d/10alsa" #110506
    
# MAIN
if [ -d $PROCFS/asound ]; then
  $rcalsasound stop >/dev/null 2>&1
  $rcalsasound unload >/dev/null 2>&1
  /sbin/rmmod dmasound dmasound_awacs 2>/dev/null
fi


cleanup () {
    killall -9 aplay arecord >/dev/null 2>&1
    /sbin/modprobe -r isapnp >/dev/null 2>&1
    /sbin/modprobe -r isa-pnp >/dev/null 2>&1
    rm -f "$TMP" "$addcfg" "$FOUND" "$DUMP"
}
trap cleanup 0 

TMP=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	xecho "Can't create temp file, exiting..."
        exit 1
fi
addcfg=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	xecho "Can't create temp file, exiting..."
        exit 1
fi
FOUND=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	xecho "Can't create temp file, exiting..."
        exit 1
fi
DUMP=`mktemp -q /tmp/alsaconf.XXXXXX`
if [ $? -ne 0 ]; then
	xecho "Can't create temp file, exiting..."
        exit 1
fi

# convert ISA PnP id number to string 'ABC'
convert_isapnp_id () {
    if [ -z "$1" ]; then
	echo "XXXX"
	return
    fi
    let a='('$1'>>2) & 0x3f'
    let b='(('$1' & 0x03) << 3) | (('$1' >> 13) & 0x07)'
    let c='('$1'>> 8) & 0x1f'
    strs='@ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    echo ${strs:$a:1}${strs:$b:1}${strs:$c:1}
}

# swap high & low bytes
swap_number () {
    if [ -z "$1" ]; then
	echo "0000"
	return
    fi
    let v='(('$1'>>8)&0xff)|(('$1'&0xff)<<8)'
    printf "%04x" $v
}

# build card database
# build_card_db filename
build_card_db () {
    MODDIR=/lib/modules/`uname -r`
    last_driver=""
    echo -n > $1

    [ -f $MODDIR/modules.pcimap ] || depmod  # 2jan2010 shinobar: precaution.

    # list pci cards
    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 < $MODDIR/modules.pcimap >> $1

    # list isapnp cards
    while read driver cardvendor carddevice data vendor func; do
	if expr $driver : 'snd-.*' >/dev/null ; then
	    if [ "$last_driver" != "$driver" ]; then
		echo $driver.o
		last_driver=$driver
	    fi
	    id1=`convert_isapnp_id $cardvendor`
	    dev1=`swap_number $carddevice`
	    id2=`convert_isapnp_id $vendor`
	    dev2=`swap_number $func`
	    echo "ISAPNP: $id1$dev1=$id2$dev2"
	fi
    done < $MODDIR/modules.isapnpmap >> $1
}

#
# probe cards
#
probe_cards () {
    found="0"
    test -r $PROCFS/isapnp || /sbin/modprobe isapnp >/dev/null 2>&1
    test -r $PROCFS/isapnp || /sbin/modprobe isa-pnp >/dev/null 2>&1
    if [ -r $PROCFS/isapnp ]; then
	cat $PROCFS/isapnp >"$DUMP"
	found="1"
    elif [ -d $SYSFS/bus/pnp/devices ]; then
	# use 2.6 kernel's sysfs output
	# fake the isapnp dump
	index=0
	bindex=0
	for d1 in $SYSFS/devices/pnp* ; do
	  for d2 in $d1/*:* ; do
	    if [ -r $d2/card_id ]; then
	      id=`cat $d2/card_id`
	      name=`cat $d2/name`
	      echo "Card $index '$id:$name' " >> "$DUMP"
	      index=$[$index+1]
	      found="1"
	    else if [ -r $d2/id ]; then
	      # FIXME: multiple id might be present (separated with new-line)
	      id=`head -n 1 $d2/id`
	      echo "BIOS $bindex '$id' " >> "$DUMP"
	      bindex=$[$bindex+1]
	      found="1"
	    fi
	    fi
	  done
	done
    fi
    if [ "$found" = "0" ]; then
      echo -n >"$DUMP"
    fi 
    CARDID_DB=/var/tmp/alsaconf.cards
    if [ ! -r $CARDID_DB ]; then
        use_modinfo_db=1
    fi
    if [ $use_modinfo_db != 1 ]; then
	if [ $CARDID_DB -ot /lib/modules/`uname -r`/modules.dep ]; then
	    use_modinfo_db=1
	fi
    fi
    if [ $use_modinfo_db = 1 ]; then
	    xecho "Building card database, please wait..."
	    #yaf-splash -placement center -bg orange -close never -text "Building card database, please wait..." &
	    #YAFPID=$!
	    build_card_db $CARDID_DB
	    #kill $YAFPID
    fi
    if [ ! -r $CARDID_DB ]; then
	xecho "No card database is found."
	yaf-splash -placement center -bg pink -close box -text "No card database is found."
	exit 1
    fi
    ncards=`grep '^snd-.*\.o$' $CARDID_DB | wc -w`

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

    #
    # PowerMac
    #
    if grep -q MacRISC $PROCFS/cpuinfo; then
	MODDIR=/lib/modules/`uname -r`
	find $MODDIR -name 'snd-powermac*' -print | \
	while read i; do
	    i=${i##*/}
	    i=${i%%.o}
	    i=${i%%.ko}
	    echo "PowerMac $i" >> $FOUND
	done
    fi

    #
    # Sparc
    #
    if grep -q Sparc $PROCFS/cpuinfo; then
	test -r $PROCFS/openprom/name || /bin/mount -t openpromfs none $PROCFS/openprom >/dev/null 2>&1
	# Check for an "audio" device
	audio=
	compat=
	if test -r $PROCFS/openprom; then
	    audio=`find $PROCFS/openprom -follow -type d -name "audio*" -print`
	fi
	if test -n "$audio"; then
	    compat=`cat $audio/compatible`
	    compat=${compat#\'}
	    compat=${compat%\'}
	    compat=${compat#SUNW,}
	fi
	# Go through all cards we have
	MODDIR=/lib/modules/`uname -r`
	find $MODDIR -name 'snd-sun-*' -print | \
	while read i; do
	    i=${i##*/}
	    i=${i%%.o}
	    i=${i%%.ko}
	    sdev=`echo ${i#snd-sun-} | tr "[a-z]" "[A-Z]"`

	    if test "$sdev" = "$compat"; then
		echo "$sdev $i" >> $FOUND
	    elif test -r $PROCFS/openprom; then
		find $PROCFS/openprom -follow -type d -name "SUNW,${sdev}*" \
		    -exec echo "$sdev $i" \; 2>/dev/null >> $FOUND
	    else
		echo "$sdev $i" >> $FOUND
	    fi
	done
    fi
}

#
# 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
	$lspci -d $1 2>/dev/null| sed -e 's/^.*:..\.. [^:]*: //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 -n 1 | sed -e 's/^Card [0-9]\+ '\''.*:\(.*\)'\'' .*$/\1/'`
	echo $cardname
    else
	echo $1
    fi
}

# get hwcfg file type from the given driver name
get_hwcfg_type () {
    while read dev driver; do
	if [ "$driver" = "$1" ]; then
	    case "$dev" in
	    *:*)
		# FIXME: need to look around /sys/bus/pci/* (or use vpid-* ?)
		devid=`$lspci -d "$dev" | head -n 1 | sed -e 's/ .*$//'`
		case "$devid" in
		*:*:*.*) ;;
		*) devid="0000:$devid" ;;
		esac
		echo bus-pci-$devid
		;;
	    *)
		echo $driver
		;;
	    esac
	    break
	fi
    done
}

# clean up all hwcfg-* files containing ALSA modules
# alsaconf sets up exclusively
cleanup_hwcfg () {
    for i in /etc/sysconfig/hardware/hwcfg-*; do
	grep -q "MODULE='snd-" $i && rm -f $i
    done
}

#
# set up /etc/sysconfig/hardware/hwcfg-* stuff
#
setup_hwcfg () {
    card=$1
    cleanup_hwcfg
    cfg=`echo "$devs_olist" | get_hwcfg_type $card`
    echo "MODULE='$card'" > /etc/sysconfig/hardware/hwcfg-$cfg
    echo "STARTMODE='auto'" >> /etc/sysconfig/hardware/hwcfg-$cfg
}


#
# configure and try test sound
# BK inserted line, changed width from 50 to 70...
ac_config_card () {

    CARD_DRIVER=snd-$1
    CARD_OPTS="${*:2}"

	msg=$(xmsg "
Configuring %s
PLEASE ANSWER YES HERE SO PUPPY WILL USE DRIVER ON NEXT BOOT
Do you want to modify %s?" $CARD_DRIVER $cfgfile)
    echo "Configure driver ${CARD_DRIVER}..." #101017
        $DIALOG --title "ALSA Wizard" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 10 80 || acex 0
    clear

    # 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

    if [ -r $cfgfile ] ; then
        #remove_ac_block < $cfgfile | remove_sndconfig_block | uniq > $TMP
	    #remove_ac_block < $cfgfile | remove_y2_block | uniq > $TMP
	    remove_ac_block < $cfgfile | uniq > $TMP #101015
    fi

    if [ -z "$have_alias" ]; then
	    if grep -q char-major-116 /lib/modules/`uname -r`/modules.alias; then
	        have_alias="yes"
	    fi
    fi
    if [ -z "$have_alias" ]; then
echo "alias char-major-116 snd
alias char-major-14 $SOUND_CORE
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" >> $addcfg
    fi
    if [ -n "$alsa_device_opts" ]; then
	echo "options snd $alsa_device_opts" >> $addcfg
    fi
    echo "alias snd-card-0 $CARD_DRIVER
alias sound-slot-0 $CARD_DRIVER" >> $addcfg
    if [ -n "$CARD_OPTS" ]; then
        echo "options $CARD_DRIVER $CARD_OPTS" >> $addcfg
    fi

	echo "$ACB
# --- ALSACONF version $version ---" >> $TMP
        cat "$addcfg" >> "$TMP"
	echo "$ACE
" >> $TMP
        cmp -s "$TMP" "$cfgfile" || cat "$TMP" > "$cfgfile"

    /sbin/depmod -a 2>/dev/null

    farewell
    clear
    if [ -x $rcalsasound ] ; then
      echo Loading driver...
      $rcalsasound restart
    fi
    #101015 need to restart volume tray applet...
    if [ -f /root/Startup/obmixer_tray ];then
     [ "`pidof obmixer_tray`" = "" ] && nohup /root/Startup/obmixer_tray >/dev/null &
    fi
    if [ -f /root/Startup/retrovol_tray ];then
     [ "`pidof retrovol`" = "" ] && nohup /root/Startup/retrovol_tray >/dev/null &
    fi
    echo Setting default volumes...
    if [ -x $bindir/set_default_volume ]; then
	$bindir/set_default_volume -f
    else
	set_mixers
    fi
    if [ -f $TESTSOUND ]; then
    #BK...
      msg=$(xmsg "
       The mixer is set up now for for playing.
       Shall I try to play a sound sample now?

                           NOTE:
If you have a big amplifier, lower your volumes or say no.
    Otherwise check that your speaker volume is wound up,
         then select <Yes> to play test sound...
")
      if $DIALOG --title "ALSA Wizard" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 14 70 
      then
          clear
	      echo
	      #aplay -N $TESTSOUND
          #BK two-barks gets truncated, -N option causes it...
          aplay $TESTSOUND & #101015
          sleep 2            #101015
          killall aplay      #101015
      fi
    fi
    if [ ! -r /etc/asound.state ]; then
	xecho "Saving the mixer setup used for this in /etc/asound.state."
	$sbindir/alsactl store
    fi
    clear
    xecho "
===============================================================================

 Now ALSA is ready to use.
 For adjustment of volumes, use your favorite mixer.

 Have a lot of fun!

"
}

# check playback
# return 0 - OK, 1 - NG, 2 - not working (irq/dma problem)
ac_try_load () {
    test -n "$LOGFILE" && echo "$1 ${*:2}" >> "$LOGFILE"
    /sbin/modprobe snd-$1 ${*:2} >/dev/null 2>&1
    if $lsmod | grep -q -E '^(snd-|snd_)'$1' '; then
	: ;
    else
	/sbin/modprobe -r snd-$1 >/dev/null 2>&1
	return 1
    fi

    # mute mixers
    amixer set Master 0% mute >/dev/null 2>&1
    amixer set PCM 0% mute >/dev/null 2>&1
    
    # output 0.5 sec
    head -c 4000 < /dev/zero | aplay -N -r8000 -fS16_LE -traw -c1 > /dev/null 2>&1 &
    # remember pid
    pp=$!
    # sleep for 2 seconds (to be sure -- 1 sec would be enough)
    sleep 2
    # kill the child process if still exists.
    kill -9 $pp > /dev/null 2>&1
    st=$?
    ac_cardname=`head -n 1 $PROCFS/asound/cards | sed -e 's/^[0-9].* - \(.*\)$/\1/'`
    /sbin/modprobe -r snd-$1 >/dev/null 2>&1
    if [ $st = 0 ]; then
	# irq problem?
	test -n "$LOGFILE" && echo "no playback return" >> "$LOGFILE"
	return 2
    else
	# seems ok!
	test -n "$LOGFILE" && echo "playback OK" >> "$LOGFILE"
	return 0
    fi
}

# check capture
# return 0 - OK, 1 - NG, 2 - not working (irq/dma problem)
# ac_try_capture card duplex opts
ac_try_capture () {
    test -n "$LOGFILE" && echo "$1 ${*:2}" >> "$LOGFILE"
    /sbin/modprobe snd-$1 ${*:3} >/dev/null 2>&1
    if $lsmod | grep -q -E '^(snd-|snd_)'$1' '; then
	: ;
    else
	/sbin/modprobe -r snd-$1 >/dev/null 2>&1
	return 1
    fi

    # mute mixers
    amixer set Master 0% mute >/dev/null 2>&1
    amixer set PCM 0% mute >/dev/null 2>&1

    play_pid=0
    if [ $2 = yes ]; then
	# try duplex - start dummy playing
	aplay -N -r8000 -fS16_LE -traw -c1 < /dev/zero > /dev/null 2>&1 &
	play_pid=$!
    fi
    # record 1sec
    arecord -N -d1 > /dev/null 2>&1 &
    # remember pid
    pp=$!
    # sleep for 2 seconds
    sleep 2
    # kill the child process if still exists.
    kill -9 $pp > /dev/null 2>&1
    st=$?
    # kill playback process if any
    test $play_pid != 0 && kill -9 $play_pid
    /sbin/modprobe -r snd-$1 >/dev/null 2>&1
    if [ $st = 0 ]; then
	test -n "$LOGFILE" && echo "capture no return" >> "$LOGFILE"
	return 2
    else
	test -n "$LOGFILE" && echo "capture OK" >> "$LOGFILE"
	return 0
    fi
}

get_dma_pair () {
    case $1 in
    0)
	echo 1 3 5;;
    1)
	echo 0 3 5;;
    3)
	echo 1 0 5;;
    5)
	echo 3 1 0;;
    esac
}

#
# check playback on specified irqs
#
# ac_try_irq card opts irqs...
# return 0 - OK, 1 - NG, 2 - not working (dma problem?)
#
ac_try_irq () {
    card=$1
    opts="$2 ${mpfx}irq=$3"
    ac_try_load $card $opts >/dev/null 2>&1
    result=$?
    case $result in
    0)
	ac_opts="$opts"
	return 0
	;;
    2)
	for irq in ${*:4}; do
	    opts="$2 ${mpfx}irq=$irq"
	    ac_try_load $card $opts >/dev/null 2>&1
	    if [ $? = 0 ]; then
		ac_opts="$opts"
		return 0
	    fi
	done
	return 2
	;;
    esac
    return 1
}

#
# check playback/capture on dma1 & dma2 & specified irqs
#
# ac_try_dmas card opts irqs...
# return 0 - OK, 1 - NG
#
ac_try_dmas () {
    dma_list=`check_dma_avail 1 0 3 5`
    for irq in ${*:3}; do
	for dma1 in $dma_list; do
	    for dma2 in `get_dma_pair $dma1`; do
		opts="$2 ${mpfx}dma1=$dma1 ${mpfx}dma2=$dma2 ${mpfx}irq=$irq"
		ac_try_load $1 $opts >/dev/null 2>&1
		result=$?
		if [ $result = 1 ]; then
		    if [ $try_all_combination = 1 ]; then
			continue
		    else
			return 1
		    fi
		elif [ $result = 0 ]; then
		    test -n "$LOGFILE" && echo "Now checking capture..." >> "$LOGFILE"
		    ac_opts="$opts"
		    ac_try_capture $1 yes $opts >/dev/null 2>&1 && return 0
		    for d in yes no; do
			for dma2 in $dma_list; do
			    if [ $dma1 != $dma2 ]; then
				opts="$2 ${mpfx}dma1=$dma1 ${mpfx}dma2=$dma2 ${mpfx}irq=$irq"
				ac_opts="$opts"
				ac_try_capture $1 $d $opts >/dev/null 2>&1 && return 0
			    fi
			done
		    done
		    return 0
		fi
	    done
	done
    done
    return 1
}

# check if the option $2 exists in card $1: set value $3
ac_check_option () {
    if /sbin/modinfo -p snd-$1 | grep -q $2; then
      echo "$2=$3"
    fi
}

ac_try_card_sb8 () {
    card=sb8
    irq_list=`check_irq_avail 5 3 9 10 7`
    for dma8 in `check_dma_avail 1 3`; do
	opts="${mpfx}dma8=$dma8"
	ac_try_irq $card "$opts" $irq_list && return 0
    done
    return 1
}

ac_try_card_sb16 () {
    card=sb16
    isapnp=`ac_check_option $card ${mpfx}isapnp 0`
    opts="$isapnp"
    irq_list=`check_irq_avail 5 9 10 7 3`
    dma_list=`check_dma_avail 0 1 3`
    dma16_list=`check_dma_avail 5 6 7`
    # at first try auto-probing by driver itself
    ac_try_load $card $opts >/dev/null 2>&1
    result=$?
    case $result in
    0)
	ac_opts="$opts"
	ac_try_capture $card yes $opts >/dev/null 2>&1 && return 0
	for d in yes no; do
	    for dma8 in $dma_list; do
		for irq in $irq_list; do
		    opts="${mpfx}dma8=$dma8 ${mpfx}irq=$irq $isapnp"
		    ac_try_capture $card $d $opts >/dev/null 2>&1 && return 0
		done
	    done
	done
	return 0
	;;
    2)
	for dma16 in $dma16_list; do
	    opts="${mpfx}dma16=$dma16 $isapnp"
	    if ac_try_irq $card "$opts" $irq_list ; then
		ac_try_capture $card yes $ac_opts >/dev/null 2>&1 && return 0
		ac_opts_saved="$ac_opts"
		for d in yes no; do
		    for dma8 in $dma_list; do
			ac_opts="$ac_opts_saved ${mpfx}dma8=$dma8"
			ac_try_capture $card $d $ac_opts >/dev/null 2>&1 && return 0
		    done
		done
		# return anyway here..
		return 0
	    fi
	done
	;;
    esac
    return 1
}

ac_try_card_es1688 () {
    card=es1688
    opts=""
    irq_list=`check_irq_avail 5 9 10 7`
    for dma8 in `check_dma_avail 1 3 0`; do
	opts="${mpfx}dma8=$dma8 ${mpfx}mpu_irq=-1"
	ac_try_irq $card "$opts" $irq_list && return 0
    done
    return 1
}

ac_try_card_es18xx () {
    card=es18xx
    opts=`ac_check_option $card ${mpfx}isapnp 0`
    ac_try_dmas $card "$opts" `check_irq_avail 5 9 10 7` && return 0
    return 1
}

ac_try_card_cs4236 () {
    card=cs4236
    irq_list=`check_irq_avail 5 7 9 11 12 15`
    isapnp=`ac_check_option $card ${mpfx}isapnp 0`
    for cport in 0x538 0x210 0xf00; do
	for port in 0x530 0x534; do
	    opts="${mpfx}port=$port ${mpfx}cport=$cport $isapnp"
	    ac_try_dmas $card "$opts" $irq_list && return 0
	done
    done
    return 1
}

ac_try_card_cs4232 () {
    card=cs4232
    irq_list=`check_irq_avail 5 7 9 11 12 15`
    isapnp=`ac_check_option $card ${mpfx}isapnp 0`
    for cport in 0x538 0x210 0xf00; do
	for port in 0x530 0x534; do
	    opts="${mpfx}port=$port ${mpfx}cport=$cport $isapnp"
	    ac_try_dmas $card "$opts" $irq_list && return 0
	done
    done
    return 1
}

ac_try_card_cs4231 () {
    card=cs4231
    irq_list=`check_irq_avail 5 7 9 11 12 15`
    for port in 0x530 0x534; do
	opts="${mpfx}port=$port"
	ac_try_dmas $card "$opts" $irq_list && return 0
    done
    return 1
}

ac_try_card_opl3sa2 () {
    card=opl3sa2
    irq_list=`check_irq_avail 5 9 3 1 11 12 15 0`
    isapnp=`ac_check_option $card ${mpfx}isapnp 0`
    for port in 0x370 0x538 0xf86 0x100; do
	for wss_port in 0x530 0xe80 0xf40 0x604; do
	    opts="${mpfx}fm_port=-1 ${mpfx}midi_port=-1 ${mpfx}port=$port ${mpfx}wss_port=$wss_port $isapnp"
	    ac_try_dmas $card "$opts" $irq_list && return 0
	done
    done
    return 1
}

ac_config_legacy () {
   title=$(xmsg "WARNING")
   msg=$(xmsg "
   Probing legacy ISA cards might make
   your system unstable.

        Do you want to proceed?

")
    $DIALOG --title "$title" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 10 50 || acex 0

    if [ x"$1" = x ]; then
	probe_list="$LEGACY_CARDS"
    else
	probe_list=$*
    fi
    menu_args=()

    for card in $probe_list; do
	cardname=`/sbin/modinfo -d snd-$card | sed -e 's/^\"\(.*\)\"$/\1/g'`
	if [ x"$cardname" != x ]; then
	    menu_args=("${menu_args[@]}" "$card" "$cardname" "on")
	fi
    done
    if [ x$menu_args = x ]; then
	msg=$(xmsg "No legacy drivers are available
   for your machine")
	$DIALOG --title "ALSA Wizard" --msgbox "$msg" 5 50
	return 1
    fi
    title=$(xmsg "Driver Selection")
    msg=$(xmsg "           Probing legacy ISA cards

        Please select the drivers to probe:")
    $DIALOG --title "$title" --cr-wrap --checklist "$msg" \
	17 64 8 "${menu_args[@]}" 2> $FOUND || acex 0

    if [ $try_all_combination != 1 ]; then
	msg=$(xmsg "
 Shall I try all possible DMA and IRQ combinations?
 With this option, some unconventional configuration
 might be found, but it will take much longer time.")
	if $DIALOG --title "ALSA Wizard" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 10 60
	    then
	    try_all_combination=1
	fi
    fi

    xecho "Probing legacy cards..   This may take a few minutes.."
    echo -n $(xmsg "Probing: ")
    cards=`cat $FOUND | tr -d \"`
    for card in $cards; do
	echo -n " $card"
	ac_opts=""
	if eval ac_try_card_$card ; then
	    xecho " : FOUND!!"
	    ac_config_card $card $ac_opts
	    return 0
	fi
    done
    echo
    title=$(xmsg "Result")
    msg=$(xmsg "No legacy cards found")
    $DIALOG --title "$title" --msgbox "$msg" 5 50
    return 1
}

#
# main part continued..
#

if test -n "$LOGFILE" ; then
    touch "$LOGFILE"
    echo -n "Starting alsaconf: " >> "$LOGFILE"
    date >> "$LOGFILE"
fi

if [ x"$legacy_probe_card" != x ]; then
    ac_opts=""
    if eval ac_try_card_$legacy_probe_card >/dev/null 2>&1; then
	echo "$ac_opts"
	echo "$ac_cardname"
	exit 0
    else
	echo "FAILED"
	exit 1
    fi
fi

#script execution starts here...
#110519 warning msg that reboot may be required...
msg0=''$(xmsg 'The ALSA Wizard unloads any sound drivers and then starts again.
This causes a problem if you decide to exit anywhere before the
Wizard has gone right to the end -- if you previously had working
sound, it will then not be working -- but a reboot will fix it.
Also, unloading of the audio drivers may affect some dialup modems,
and they may not work after running this Wizard -- again, a reboot
will fix it.')'

'$(xmsg 'Do you want to continue and run the Wizard?...')''
$DIALOG --title "$(xmsg 'ALSA Sound Wizard: NOTICE')" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg0" 0 0 || exit 0

#welcome window...
intro

if [ $do_legacy_only = 1 ]; then
    ac_config_legacy
    exit 0
fi
    
probe_cards

devs_found=()
devs_olist=""

if [ -s "$FOUND" ]; then
    while read dev card ; do
	MODDIR=/lib/modules/`uname -r`
	find $MODDIR -type f | grep -q -E $card'\.(o|ko)' || continue
	cardname=`find_device_name $dev | cut -c 1-64`
	if [ -z "$cardname" ]; then
	    cardname="$card"
	fi
	card=${card##snd-}
	devs_found=("${devs_found[@]}" "$card" "$cardname")
	devs_devs=("${devs_devs[@]}" "$card" "$dev")
    done <"$FOUND"
    devs_olist=`cat $FOUND`
fi
if [ x$devs_found != x ]; then
    echo "...device found" #101017
    #
    # check for TP600E
    #
    if [ ${devs_found[0]} = cs46xx ]; then
	if $lspci -nv 2>/dev/null| grep -q "Subsystem: 1014:1010"; then
	    msg=$(xmsg "
 Looks like you having a Thinkpad 600E or 770 notebook.
 On this notebook, CS4236 driver should be used
 although CS46xx chip is detected.

 Shall I try to snd-cs4236 driver and probe
 the legacy ISA configuration?")
	    if $DIALOG --title "ALSA Wizard" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 13 60
	    then
		try_all_combination=1
		ac_config_legacy cs4236
		exit 0
	    fi
	elif $lspci -nv 2>/dev/null| grep -q "Subsystem: 8086:8080"; then
	    msg=$(xmsg "
 Looks like you having a Dell Dimension machine.
 On this machine, CS4232 driver should be used
 although CS46xx chip is detected.

 Shall I try to snd-cs4232 driver and probe
 the legacy ISA configuration?")
	    if $DIALOG --title "ALSA Wizard" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 13 60
	    then
		try_all_combination=1
		ac_config_legacy cs4232
		exit 0
	    fi
        fi	
    fi
   
    #BK john doe submitted this...
    #devs_found=("${devs_found[@]}" "legacy" "Probe legacy ISA (non-PnP) chips")
    devs_found=("${devs_found[@]}" "legacy" "Probe: legacy ISA (non-PnP) chips" "usb-audio" "Override: USB Sound Device" "aoa" "Override: Apple Onboard Audio")
    title=$(xmsg "Soundcard Selection")
    msg=$(xmsg "
         Following card(s) are found on your system.
         Choose a soundcard to configure:
")
    $DIALOG --title "$title" --cr-wrap --menu "$msg" 17 76 8 "${devs_found[@]}" 2> $FOUND || acex 0
    card=`head -n 1 $FOUND`
    if [ "$card" = "legacy" ]; then
	ac_config_legacy
    else
	ac_config_card "$card"
    fi
    exit 0
else
    echo "...no device found" #101017
    msg=$(xmsg "
        No supported PnP or PCI card found.

 Would you like to probe legacy ISA sound cards/chips?

")
    if $DIALOG --title "ALSA Wizard" --cr-wrap --ok-label "$Yes_lbl" --cancel-label "$No_lbl" --yesno "$msg" 9 60 ; then
	ac_config_legacy
	exit 0
    fi
fi

rm -f "$FOUND" "$DUMP"
exit 0
