#!/bin/sh

# ALSA configurator
# in 1998,1999 by SALSOFT, Jan ONDREJ <ondrejj@salstar.shadow.sk>
version=0.4.2

#  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.

# DEFINITIONS
if [ -e /etc/modules.conf ]; then
  export cfgfile="/etc/modules.conf"
elif [ -e /etc/conf.modules ]; then
  export cfgfile="/etc/conf.modules"
else
  export cfgfile="/etc/modules.conf"
  touch /etc/modules.conf
fi

# Example:
# export CARD_0x#="snd-module_name Nicnames_of_cards [...]\
#  @IOs IRQs DMAs ...\
#  @available_IOs avail_IRQs ...\
#  default_IO default_IRQ ..."
# Don't forget add to CARDS!

export CARD_0="nocard No_more_cards\
 @io_names\
 @available\
 @default"
export CARD_0x1="snd-card-gusclassic Gravis_UltraSound_Classic\
 @port irq dma1 dma1_size dma2 dma2_size joystick_dac\
 @0x220,0x230,0x240,0x250,0x260 3,5,9,11,12,15 1,3,5,6,7 4-128 1,3,5,6,7 4-128 0-31\
 @0x220 5 6 '' 6 '' ''"
export CARD_0x2="snd-card-gusextreme Gravis_UltraSound_Extreme\
 @port mpu_port irq mpu_irq irq1 dma8 dma8_size dma1 dma1_size joystick_dac\
 @0x220,0x230,0x240,0x250,0x260 0x300,0x310,0x320,0x330,-1 5,7,9,10 5,7,9,10 3,5,9,11,12,15 0,1,3 4-64 1,3,5,6,7 4-128 0-31\
 @0x220 0x300 5 7 11 1 '' 6 '' ''"
export CARD_0x3="snd-card-gusclassic Gravis_UltraSound_ACE\
 @port irq dma1 dma1_size dma2 dma2_size joystick_dac\
 @0x220,0x230,0x240,0x250,0x260 3,5,9,11,12,15 1,3,5,6,7 4-128 1,3,5,6,7 4-128 0-31\
 @0x220 5 6 '' 6 '' ''"
export CARD_0x4="snd-card-gusmax Gravis_UltraSound_MAX\
 @port irq dma1 dma1_size dma2 dma2_size joystick_dac\
 @0x220,0x230,0x240,0x250,0x260 3,5,9,11,12,15 1,3,5,6,7 4-128 1,3,5,6,7 4-128 0-31\
 @0x220 11 5 '' 6 '' ''"
export CARD_0x5="snd-card-interwave Gravis_UltraSound_PnP Dynasonic_3-D/Pro\
 @port irq dma1 dma1_size dma2 dma2_size joystick_dac midi\
 @0x210,0x220,0x230,0x240,0x250,0x260 3,5,9,11,12,15 0,1,3,5,6,7 4-128 0,1,3,5,6,7 4-128 0-31 0,1\
 @0x220 11 5 '' 6 '' '' 0"
export CARD_0x6="snd-card-sb8 SoundBlaster_1.0\
 @port irq dma8 dma8_size\
 @0x220,0x240,0x260 5,7,9,10 1,3 4-64\
 @0x220 5 1 ''"
export CARD_0x7="snd-card-sb8 SoundBlaster_2.0\
 @port irq dma8 dma8_size\
 @0x220,0x240,0x260 5,7,9,10 1,3 4-64\
 @0x220 5 1 ''"
export CARD_0x8="snd-card-sb8 SoundBlaster_Pro\
 @port irq dma8 dma8_size\
 @0x220,0x240,0x260 5,7,9,10 1,3 4-64\
 @0x220 5 1 ''"
export CARD_0x9="snd-card-sb16 SoundBlaster_16_(PnP)\
 @port mpu_port irq dma8 dma8_size dma16 dma16_size mic_agc\
 @0x220,0x240,0x260 0x300,0x330,-1 5,7,9,10 0,1,3 4-64 5,6,7 4-128 0,1\
 @0x220 0x300 5 1 '' 5 '' 0"
export CARD_0xA="snd-card-sbawe SoundBlaster_AWE_32_(PnP) SoundBlaster_AWE_64_PnP\
 @port mpu_port awe_port irq dma8 dma8_size dma16 dma16_size mic_agc\
 @0x220,0x240,0x260 0x300,0x330,-1 ? 5,7,9,10 0,1,3 4-64 5,6,7 4-128 0,1\
 @0x220 0x300 -1 5 1 '' 5 '' 0"
export CARD_0xB="snd-card-audiodrive1688 ESS_AudioDrive_ESx688\
 @port mpu_port irq mpu_irq dma8 dma8_size\
 @0x220,0x240,0x260 0x300,0x310,0x320,0x330,-1 5,7,9,10 5,7,9,10 0,1,3 4-64\
 @0x220 -1 5 7 1 ''"
export CARD_0xC="snd-card-opl3sa2 Yamaha_OPL3-SA2/SA3\
 @port sb_port wss_port midi_port fm_port irq dma1 dma1_size dma2 dma2_size\
 @0x??? 0x220 0x530,0xe80,0xf40,0x604 0x300,0x330,-1 0x388,-1 5,7,9,10 0,1,3 4-64 0,1,3,-1 4-64\
 @0x370 0x220 0x530 0x300 0x388 5 1 '' 3 ''"
export CARD_0xD="snd-card-mozart OAK_Mozart\
 @port irq dma1 dma1_size\
 @0x530,0xe80,0xf40,0x604 7,9,10,11 0,1,3 4-64\
 @0x530 7 1 ''"
export CARD_0xE="snd-card-sonicvibes S3_SonicVibes_PCI\
 @dmaa_size dmac_size reverb mge\
 @4-128 4-128 0,1 0,1\
 @'' '' 0 0"
export CARD_0xF="snd-card-ens1370 Ensoniq_AudioPCI_ES1370\
 @dac1_frame_size dac2_frame_size adc_frame_size\
 @4-128 4-128 4-128\
 @'' '' ''"
export CARD_0x10="snd-card-ens1371 Ensoniq_AudioPCI_ES1371 Sound_Blaster_PCI_64 Sound_Blaster_PCI_128 Sound_Blaster_Vibra_PCI\
 @dac1_frame_size dac2_frame_size adc_frame_size\
 @4-128 4-128 4-128\
 @'' '' ''"
export CARD_0x11="snd-card-cs4232 CS4232/CS4232A\
 @port cport mpu_port fm_port jport irq mpu_irq dma1 dma1_size dma2 dma2_size\
 @PnP_setup=0x534 PnP_setup=0x120 PnP_setup=0x300,-1 PnP_setup=0x388,-1 PnP_setup=0x200,-1 5,7,9,11,12,15 9,11,12,15 0,1,3 4-64 0,1,3,-1 4-64\
 @0x534 0x120 0x300 0x388 0x200 11 7 1 '' 3 ''"
export CARD_0x12="snd-card-cs4236 CS4235/CS4236B/CS4237B/CS4238B/CS4239\
 @port cport mpu_port fm_port irq mpu_irq dma1 dma1_size dma2 dma2_size\
 @PnP_setup=0x534 PnP_setup=0x120 PnP_setup=0x300,-1 PnP_setup=0x388,-1 5,7,9,11,12,15 9,11,12,15 0,1,3 4-64 0,1,3,-1 4-64\
 @0x534 0x120 0x300 0x388 11 7 1 '' 3 ''"
export CARD_0x13="snd-card-interwave-stb UltraSound_32-Pro\
 @port port_tc irq dma1 dma1_size dma2 dma2_size joystick_dac midi\
 @0x210,0x220,0x230,0x240,0x250,0x260 0x350,0x360,0x370,0x380 3,5,9,11,12,15 0,1,3,5,6,7 4-128 0,1,3,5,6,7 4-128 0-31 0,1\
 @0x220 0x350 11 5 '' 6 '' '' 0"
export CARD_0x14="snd-card-ess1938 ESS_Solo-1_ES1938/ES1946\
 @\
 @\
 @"
export CARD_0x15="snd-card-audiodrive18xx ESS_AudioDrive_ES18XX\
 @port mpu_port fm_port irq dma1 dma1_size dma2 dma2_size snd_isapnp\
 @0x220,0x240,0x260 0x300,0x310,0x320,0x330,-1 ??? 5,7,9,10 0,1,3 4-64 0,1,3 4-64 0,1\
 @0x220 0x300 -1 5 0 '' 1 '' 1"
export CARD_0x16="snd-card-cs4231 Soundcards_based_on_CS4231_chips\
 @port mpu_port jport irq mpu_irq dma1 dma1_size dma2 dma2_size\
 @??? ???,-1 ???,-1 ??? ??? ??? 4-128 ??? 4-128\
 @'' -1 -1 '' '' '' '' '' ''"
export CARD_0x17="snd-card-opti9xx OPTi_82C9xx_chips\
 @port mpu_port opl_port irq mpu_irq dma1 dma1_size dma2 dma2_size cd_if cd_port cd_irq cd_drq game\
 @0x530,0xe80,0xf40,0x604 0x300,0x310,0x320,0x330 0x388 5,7,9,10,11 5,7,9,10 0,1,3 4-64 0,1 4-64 disabled,ide1,ide2,mitsumi,panasonic,sony 0x320,0x330,0x340,0x360 5,7,9,10,11,-1 0,1,3,-1 enabled,disabled\
 @0x530 0x300 0x388 7 9 0 '' 1 '' disabled 0x320 -1 -1 disabled"
export CARD_0x18="snd-card-serial Serial_MIDI_driver\
 @\
 @\
 @"
export CARD_0x19="snd-card-card-ad1848 Soundcards_based_on_AD1848/AD1847/CS4248_chips\
 @port irq dma1 dma1_size\
 @??? ??? 0,1,3 4-64\
 @'' '' 1 ''"
export CARD_0x1A="snd-card-trid4dwave Trident_4DWave_DX\
 @dac_frame_size_dx adc_frame_size_dx dac_frame_size_nx adc_frame_size_nx pcm_channels wavetable_size\
 @4-64 4-64 4-64 4-64 ??? 4-?\
 @'' '' '' '' '' ''"
export CARD_0x1B="snd-card-trid4dwave Trident_4DWave_NX\
 @dac_frame_size_dx adc_frame_size_dx dac_frame_size_nx adc_frame_size_nx pcm_channels wavetable_size\
 @4-64 4-64 4-64 4-64 ??? 4-?\
 @'' '' '' '' '' ''"
export CARD_0x1C="snd-card-sgalaxy Aztech_Sound_Galaxy\
 @sbport wssport irq dma1 dma1_size\
 @0x220,0x240 0x530,0xe80,0xf40,0x604 7,9,10,11 0,1,3 8,16,32,64\
 @0x220 0x530 9 1 ''"
export CARD_0x1D="snd-card-cs461x Soundcards_based_on_CS4610/CS4612/CS4614/CS4615/CS4280 Turtle_Beach_WaveFront_series\
 @dac_frame_size adc_frame_size\
 @4-64 4-64\
 @'' ''"
export CARD_0x22="snd-card-cmi8330 Soundcards_based_on_C-Media_CMI8330_chips\
 @wssport wssirq wssdma wssdma_size sbport sbirq sbdma8 sbdma8_size sbdma16 sbdma16_size\
 @??? ??? ??? ??? ??? ??? ??? ??? ??? ???\
 @'' '' '' '' '' '' '' '' '' ''"
export CARD_0x23="snd-card-dummy Dummy_soundcard\
 @\
 @\
 @"
export CARD_0x24="snd-card-als100 Advance_Logic_ALS100\
 @\
 @\
 @"
export CARDS="0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF\
 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C\
 0x1D 0x22 0x23 0x24"

# Check for root privileges
if [ `id -u` -ne 0 ]; then
  echo "You must be root to use this script."
  exit 1
fi

# Check for dialog, whiptail, gdialog, awk, ... ?
if which dialog > /dev/null; then
  DIALOG=dialog
else
  if which whiptail > /dev/null; then
    function whiptail_wrapper() {
      X1="$1"
      X2="$2"
      if [ $1 = --yesno ]; then
        X3=`expr $3 + 2`
      else
        X3=$3
      fi
      shift 3
      whiptail "$X1" "$X2" $X3 "$@"
    }
    DIALOG=whiptail_wrapper
  else
    echo "Error, dialog or whiptail not found."
    exit 1
  fi
fi
if which awk > /dev/null; then :
else
  echo "Error, awk not found. Can't continue."
  exit 1
fi

# Check for existence of group "audio".
if grep -q ^audio: /etc/group; then
  SND_MODE=0660
  SND_GID=`grep ^audio: /etc/group | cut -d: -f3`
  SND_UID=0
else
  SND_MODE=0666
  SND_GID=0
  SND_UID=0
fi

# Read mode, gid, uid from conf.modules
eval `grep "options snd " $cfgfile | cut -d " " -f3-`
if [ "$snd_device_mode" ]; then
  SND_MODE="$snd_device_mode"
fi
if [ "$snd_device_gid" ]; then
  SND_GID="$snd_device_gid"
fi
if [ "$snd_device_uid" ]; then
  SND_UID="$snd_device_uid"
fi

# Stripnum
function stripnum() {
  SEQ=":`seq -s : $1 $2`:"
  shift 2
  for i in $@; do
    SEQ=`echo $SEQ | sed s/:$i:/:/`
  done
  echo $SEQ
}

# Set variables
TMP=/tmp/alsaconf.$$
USED_IRQS=`grep "^ *[0-9]*:" /proc/interrupts | cut -d: -f1 | tr -d " "`
FREE_IRQS=`stripnum 0 15 $USED_IRQS`
USED_DMAS=`grep "^ *[0-9]*:" /proc/dma | cut -d: -f1 | tr -d " "`
FREE_DMAS=`stripnum 0 7 $USED_DMAS`
DETECTFILE=/usr/src/alsa/detect
if [ ! -e "$DETECTFILE" ]; then
  DETECTFILE=/proc/asound/detect
fi

# Exit function
function acex() {
  rm -f $TMP
  clear
  exit $1
}

# INTRO
function intro() {
$DIALOG --msgbox "
                  ALSA  CONFIGURATOR
                    version  $version

                (c) 1998,1999  SALSOFT
        Jan ONDREJ, <ondrejj@salstar.shadow.sk>

This script is a configurator for Advanced Linux Sound
Architecture driver.
" 16 60 || acex 0
}

# Set card variables from CARD_#.
function set_card_vars() {
  eval CARD_INFO=\$CARD_$1
  CARD_DRIVER=`echo $CARD_INFO | cut -d" " -f1`
  CARD_NAMES=`echo $CARD_INFO | cut -d"@" -f1 | cut -d" " -f2-`
  if [ "$2" ]; then
    CARD_GETOPT="id "`echo $CARD_INFO | cut -d"@" -f2`
    CARD_MAINOPT="_ "`echo $CARD_INFO | cut -d"@" -f3`
    CARD_DEFOPT="CARD_$2 "`echo $CARD_INFO | cut -d"@" -f4`
  fi
}

# Test card informations in CARD_# variables
function test_card_info() {
  for C in $CARDS; do
    set_card_vars $C X
    echo "-----------------------------------------------------------------"
    echo "DRIVER:  $CARD_DRIVER"
    echo "NAMES:   $CARD_NAMES"
    echo "-----------------------------------------------------------------"
    echo "Parameter      Default   Options"
    OPTNUM=0
    for OPT in $CARD_GETOPT; do
      OPTNUM=`expr $OPTNUM + 1`
      MAINOPT="(`echo \"$CARD_MAINOPT\" | cut -d" " -f$OPTNUM`)"
      DEFOPT=`echo "$CARD_DEFOPT" | cut -d" " -f$OPTNUM | tr -d "'"`
      echo "$OPT@$DEFOPT@$MAINOPT" \
        | awk -F@ '{ printf "%-15s%-10s%s\n",$1,$2,$3 }'
    done
  done
  exit 0
}

# Select card
function select_card() {
  $DIALOG --menu "Select card" 20 70 13 $MENU_CARDS 2> $TMP || acex 0
  SEL_CARD=`cat $TMP`
}

# Enter a number or text.
function enter_data() {
  $DIALOG --inputbox "$1\n$2" 9 50 "$DEFOPT" 2> $TMP || acex 0
  RETURN=`cat $TMP`
}

# Disabled or Enabled ?
function enter_dis_ena() {
  $DIALOG --menu "$1" 9 50 2 "0" "Disable" "1" "Enable" 2> $TMP || acex 0
  RETURN=`cat $TMP`
}

# Add option
function add_option() {
  if [ "$2" ]; then
    CARD_OPT="$CARD_OPT $1=$2"
  fi
}

# Get card options from conf.modules
function get_card_options() {
  # Clear all ALSACONF_snd_ variables
  ALSACONF_snd_temp=0
  `set | grep "^ALSACONF_snd_" | cut -d"=" -f1 \
    | sed -e 's/^/export /g' -e 's/$/=/g'`

  # Read conf.modules
  O=`grep "options * $1 * snd_index=$2 " $cfgfile`
  if [ "$O" ]; then
    # single card conf. detected
    `echo $O | cut -d" " -f3- | tr " " "\n" | sed 's/^/export ALSACONF_/g'`
  else
    O=`grep "options * $1 * snd_index=$2," $cfgfile`
    if [ -z "$O" ]; then
      O=`grep "options * $1 * snd_index=[0-9,]*,$2[, ]" $cfgfile`
    fi
    if [ "$O" ]; then
      # now is multicard conf. detected. Try, what card is it.
      X=`echo $O | cut -d" " -f3 | cut -d"=" -f2 | tr "," " "`
      I=2
      for x in $X; do
        [ $x -eq $2 ] && break
        I=`expr $I + 1`
      done
      export I
      # now $I-1 is number of card on options line, $O is options line
      `echo $O | cut -d" " -f3- | tr " " "\n" | sed 's/=/=,/g' \
         | awk 'BEGIN -F, {I=ENVIRON["I"]} {print $1$(I)}' \
         | sed 's/^/export ALSACONF_/g'`
    fi
  fi
}

# Read options for card
function read_card_options() {
  # Input options for this driver
  CARD_OPT="$CARD_DRIVER snd_index=$CARD_NUM"
  OPTNUM="0"
  for OPT in $CARD_GETOPT; do
    OPTNUM=`expr $OPTNUM + 1`
    MAINOPT="(`echo \"$CARD_MAINOPT\" | cut -d" " -f$OPTNUM`)"
    eval DEFOPT="\$ALSACONF_snd_$OPT"
    if [ -z "$DEFOPT" ]; then
      DEFOPT=`echo "$CARD_DEFOPT" | cut -d" " -f$OPTNUM | tr -d "'"`
    fi
    case $OPT in
      id)
        enter_data "Card identifier." ""
        ;;
      port|sbport)
        enter_data "IO port." "$MAINOPT"
        ;;
      mpu_port)
        enter_data "MPU IO port." "$MAINOPT"
        ;;
      awe_port)
        enter_data "EMU8000 synthesizer port." "$MAINOPT"
        ;;
      wss_port|wssport)
        enter_data "WSS IO port." "$MAINOPT"
        ;;
      midi_port)
        enter_data "MIDI (MPU-401 UART) port." "$MAINOPT"
        ;;
      fm_port)
        enter_data "FM port (-1 for disable)." "$MAINOPT"
        ;;
      cport)
        enter_data "Control port." "$MAINOPT"
        ;;
      jport)
        enter_data "Game port." "$MAINOPT"
        ;;
      irq|sbirq|wssirq)
        enter_data "IRQ." "$MAINOPT"
        ;;
      mpu_irq)
        enter_data "MPU IRQ." "$MAINOPT"
        ;;
      dma1|wssdma)
        enter_data "First DMA." "$MAINOPT"
        ;;
      dma1_size|waadma_size)
        enter_data "Max. first DMA size in kB." "$MAINOPT"
        ;;
      dma2)
        enter_data "Second DMA." "$MAINOPT"
        ;;
      dma2_size)
        enter_data "Max. second DMA size in kB." "$MAINOPT"
        ;;
      dma8|sbdma8)
        enter_data "8-bit DMA." "$MAINOPT"
        ;;
      dma8_size|sbdma8_size)
        enter_data "Max. 8-bit DMA size in kB." "$MAINOPT"
        ;;
      dma16|sbdma16)
        enter_data "16-bit DMA." "$MAINOPT"
        ;;
      dma16_size|sbdma16_size)
        enter_data "Max. 16-bit DMA size in kB." "$MAINOPT"
        ;;
      joystick_dac)
        enter_data "Joystick DAC." "$MAINOPT"
        ;;
      midi)
        enter_dis_ena "MIDI UART"
        ;;
      port_tc)
        enter_data "Tone control port." "$MAINOPT"
        ;;
      mic_agc)
        enter_dis_ena "Mic. Auto-Gain-Control"
        ;;
      dmaa_size)
        enter_data "Max. DDMA-A (playback) size in kB." "$MAINOPT"
        ;;
      dmac_size)
        enter_data "Max. DDMA-C (record) size in kB." "$MAINOPT"
        ;;
      dac1_frame_size)
	enter_data "Max. dac1 (playback1) frame size in kB." "$MAINOPT"
	;;
      dac2_frame_size)
        enter_data "Max. dac2 (playback2) frame size in kB." "$MAINOPT"
	;;
      dac_frame_size)
        enter_data "Max. dac (playback) frame size in kB." "$MAINOPT"
        ;;
      adc_frame_size)
        enter_data "Max. adc (record) frame size in kB." "$MAINOPT"
	;;
      reverb)
        enter_dis_ena "Reverb"
        ;;
      mge)
        enter_dis_ena "Microphone Gain"
        ;;
      dac_frame_size_dx)
	enter_data "Max. dac (playback) frame size in kB (DX)." "$MAINOPT"
	;;
      adc_frame_size_dx)
        enter_data "Max. adc (record) frame size in kB (DX)." "$MAINOPT"
	;;
      dac_frame_size_nx)
	enter_data "Max. dac (playback) frame size in kB (NX)." "$MAINOPT"
	;;
      adc_frame_size_nx)
        enter_data "Max. adc (record) frame size in kB (NX)." "$MAINOPT"
	;;
    esac
    add_option snd_$OPT $RETURN
  done
}

# Autodetection
function autodetect() {
  modprobe snd-detect
  AUTODET=false
  DD=`grep -v ^Version $DETECTFILE | tr " " "_"`
  [ "$DD" ] && AUTODET=true
  for i in $DD; do
    DET_B=`echo $i | cut -d# -f1`
    DET_N=`echo $i | cut -d# -f2`
    DET_C=`echo $i | cut -d# -f3`
    DET_1=`echo $i | cut -d# -f4`
    CTC=no
    $DIALOG --yesno "`echo -e "I have detected $DET_B card named\n\n$DET_C
      \nDo you want to configure it?"`" 9 50 && CTC=yes
    if [ "$CTC" = "yes" ]; then
      SEL_CARD="$DET_N"
      CARD_NUM=`expr $CARD_NUM + 1`
      set_card_vars $SEL_CARD $CARD_NUM
      get_card_options $CARD_DRIVER $CARD_NUM
      if [ "$DET_B" = "ISA" ]; then
        ALSACONF_snd_port="$DET_1"
      fi
      read_card_options
      eval CARD_OPT_$CARD_NUM="\$CARD_OPT"
    fi
  done
  modprobe -r snd-detect 2> /dev/null
  modprobe -r snd 2> /dev/null
}

# MAIN
if [ "$1" = "-test" ]; then
  test_card_info
fi
MENU_CARDS=""
for N in $CARDS; do
  set_card_vars $N
  for CARD_NAME in $CARD_NAMES; do
    MENU_CARDS="$MENU_CARDS $N $CARD_NAME"
  done
done
intro
CARD_NUM=0
autodetect
while true; do
  select_card
  if [ "$SEL_CARD" = "0" ]; then
    break
  fi
  CARD_NUM=`expr $CARD_NUM + 1`
  set_card_vars $SEL_CARD $CARD_NUM
  get_card_options $CARD_DRIVER $CARD_NUM
  read_card_options

  eval CARD_OPT_$CARD_NUM="\$CARD_OPT"
done

# If no cards configured, then exit
if [ "$CARD_NUM" = "0" ]; then
  clear
  echo "No cards configured."
  exit 0
fi

# Configuration done
$DIALOG --yesno "Do you want to modify ${cfgfile}?" 5 50 || acex 0
rm -f $TMP
clear

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

function add_to_conf_modules() {
  awk '
    BEGIN {
      ACB=ENVIRON["ACB"]
      ACE=ENVIRON["ACE"]
      WOAC=0
      do {
        EOF=getline CMF <ENVIRON["cfgfile"]
        if (EOF <= 0) {
          print ""
          print ACB
          WOAC=1
          break
        }
        print CMF
      } while (CMF != ACB);
    }
    // {
      print
    }
    END {
      if (WOAC == 1) {
        print ACE
      } else {
        do {
          EOF=getline CMF <ENVIRON["cfgfile"]
        } while ((CMF != ACE) && (EOF > 0));
        print CMF
        while (EOF > 0) {
          EOF=getline CMF <ENVIRON["cfgfile"]
          if (EOF>0)
            print CMF
        }
      }
    }
  '
}

function join_cards() {
  # Join cards with same driver to one line.
  N1=0
  while [ $N1 -lt $CARD_NUM ]; do
    N1=`expr $N1 + 1`
    CO1=`eval echo \\$CARD_OPT_$N1 | cut -d" " -f1`
    N2=1
    while [ $N2 -lt $N1 ]; do
      CO2=`eval echo \\$CARD_OPT_$N2 | cut -d" " -f1`
      if [ "$CO1" = "$CO2" ]; then
        O1=`eval echo \\$CARD_OPT_$N1`
        O2=`eval echo \\$CARD_OPT_$N2`
        OO=`echo "$O2 $O1" | tr " " "\n" | awk -F= '
          BEGIN {
            x=0
          }
          /.*=.*/ {
            if (A[$1]=="") {
              N[x++]=$1
              A[$1]=$2
            } else {
              A[$1]=A[$1]","$2
            }
            next
          }
          {
            drv=$1
          }
          END {
            printf drv
            for(i=0;i<x;i++) {
              n=N[i]
              printf " %s=%s",n,A[n]
            }
          }
        '`
        eval CARD_OPT_$N2=\"$OO\"
        unset CARD_OPT_$N1
        break
      fi
      N2=`expr $N2 + 1`
    done
  done
}

# 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 [ "$CARD_NUM" = "1" ]; then
# Single card.
echo "# --- ALSACONF verion $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-pcm1-oss
alias sound-service-0-12 snd-pcm1-oss
options snd snd_major=116 snd_cards_limit=1\
 snd_device_mode=$SND_MODE snd_device_gid=$SND_GID snd_device_uid=$SND_UID
options $CARD_OPT" | add_to_conf_modules > $TMP
else
# More cards.
(echo "# --- ALSACONF verion $version ---
alias char-major-116 snd
alias char-major-14 $SOUND_CORE"
N=0
while [ $N -lt $CARD_NUM ]; do
  N=`expr $N + 1`
  echo -n "alias snd-card-$N "
  eval echo \$CARD_OPT_$N | cut -d" " -f1
  echo "alias sound-slot-$N snd-card-$N"
  echo "alias sound-service-$N-0 snd-mixer-oss"
  echo "alias sound-service-$N-1 snd-seq-oss"
  echo "alias sound-service-$N-3 snd-pcm1-oss"
  echo "alias sound-service-$N-12 snd-pcm1-oss"
done
echo "options snd snd_major=116 snd_cards_limit=$CARD_NUM\
 snd_device_mode=$SND_MODE snd_device_gid=$SND_GID snd_device_uid=$SND_UID"
join_cards
N=0
while [ $N -lt $CARD_NUM ]; do
  N=`expr $N + 1`
  echo -n "options "
  eval echo \$CARD_OPT_$N
done
) | add_to_conf_modules > $TMP
fi

if cp -f $cfgfile $cfgfile~; then
  mv -f $TMP $cfgfile
  echo "OK, $CARD_NUM card(s) configured."
else
  echo "ERROR! $cfgfile could not be saved."
  echo "Configured ALSA is in $TMP."
fi
