#!/bin/ash
#Barry Kauler april 2009, puppylinux.com
#called from /etc/rc.d/rc.services at bootup, with 'start' param.
#called from /etc/rc.d/rc.shutdown at shutdown, with 'stop' param.
#101120, 101121 simplification.
#110111 shinobar: for reliable sound detection on HP Compac nc4010.
#110113 tweak delay. 110216 tweak delay.
#110506 /usr/sbin/alsaconf has 'restart' option, might need to reprobe modules. for now, just 'start|restart'.
#111229 add test file /etc/asound.state exists.
#120103 karl godt: fix unloading modules. refer: http://www.murga-linux.com/puppy/viewtopic.php?t=71767&start=390
#120222 revert 111229. 120223 shinobar: better fix.
#120226 01micko: added 'Master Front' entries. 120318 bumped it up, 75% to 100%.
#141103 weird, seems need change 'set' to 'sset' http://murga-linux.com/puppy/viewtopic.php?t=90784&start=795
#170527 easy linux, kernel does not have oss support.
#180410 increase time sound wait loop, extra tests sound working.
#191014 increase time sound wait loop.
#200113 introducing hardware-profile for sound. see also /usr/sbin/mscw
#200115 improve sound hardware-profiling.
#200116 /etc/asound.conf will always exist, even if empty.
#200121 add usb hardware-profile. rewrite.
#200523 1st bootup asound.stsate doesn't exist, hide error msg.
#201008 oe dunfell, have pulseaudio, do not load *oss modules. ref: https://wiki.archlinux.org/index.php/PulseAudio
#201013 oe gatesgarth, have removed pulseaudio, bring back oss modules.
#20201102 test if using pulseaudio, then not load *oss modules.
#20211109 simplify. note: 5.10.78 kernel built without OSS compatibility layer for ALSA.
#20211111 set all output volumes to 100%
#20211113 for pulseaudio, do not set volumes here. 20211118 fix syntax error.

case "$1" in
 start|restart)
  echo "running /etc/init.d/10alsa start"
  echo -n "${$}" > /tmp/10alsa-PID #20211109 /root/Startup/pulseaudio will wait.
  rm -f /var/lock/subsys/alsasound 2> /dev/null #or alsa will not start.
   
  #20211109 on my acer aspire 1 laptop have to wait up to 8 seconds!
  echo -n '' > /tmp/10alsa-CARD_PATHS
  for CNT in 1 2 3 4 5 6 7 8 9 10
  do
   sleep 1
   if [ -d /sys/class/sound/card0 ];then #20211118 [0-9] causes syntax err if more than one card.
    sleep 2 #just in case another tardy card.
    readlink /sys/class/sound/card[0-9] > /tmp/10alsa-CARD_PATHS
    #ex: ../../devices/pci0000:00/0000:00:1b.0/sound/card0
    break
   fi
  done
  echo "10alsa: waited for /sys/class/sound/card[0-9] ${CNT} seconds"
  if [ ! -s /tmp/10alsa-CARD_PATHS ];then
   echo "10alsa: no audio interfaces found, quiting."
   exit
  fi
   
  ###hardware profiling###
  #200113 hardware-profile... 200115 improve... (see also /usr/sbin/mscw)
  FNDflg=0
  if [ ! -f /etc/asound.conf ];then touch /etc/asound.conf; fi #200116
  echo -n '' > /tmp/10alsa-AudioCardHardwareProfiles
  CURR_SND_HW_PROFILE="$(grep '^#SND_HW_PROFILE' /etc/asound.conf | cut -f 2 -d "'")"
  #...ex: 0+8086:1c20 (card#+PCIID)
  if [ ! "$CURR_SND_HW_PROFILE" ];then CURR_SND_HW_PROFILE='0+'; fi #precaution
   
  #200121 separate out the usb paths...
  grep '/usb[0-9]/' /tmp/10alsa-CARD_PATHS > /tmp/10alsa-CARD_PATHS-usb
  grep -v '/usb[0-9]/' /tmp/10alsa-CARD_PATHS > /tmp/10alsa-CARD_PATHS-pci
  #200121 usb audio devices...
  if [ -s /tmp/10alsa-CARD_PATHS-usb ];then
   for aUSB in `cat /tmp/10alsa-CARD_PATHS-usb | tr '\n' ' '`
   do
    #...ex: ../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/usb3/3-2/3-2:1.0/sound/card1
    USB_SUBPATH="$(echo -n "${aUSB}" | grep -o '/usb[0-9]/[0-9.:-]*/[0-9.:-]*/')"
    #...ex: /usb3/3-2/3-2:1.0/
    if [ -e /sys/bus/usb/devices${USB_SUBPATH}modalias ];then
     aID="$(cut -c 6-14 /sys/bus/usb/devices${USB_SUBPATH}modalias)" #ex: 8086p0808
     aID="${aID/p/:}"
     aCARD="$(echo -n "$aUSB" | rev | cut -c 1 | rev)"
     SND_HW_PROFILE="${card}+usb+${aID}"
     echo "${aCARD}+usb+${aID}" >> /tmp/10alsa-AudioCardHardwareProfiles
    fi
   done
  fi
  #pci audio devices...
  if [ -s /tmp/10alsa-CARD_PATHS-pci ];then
   AUDIO_IDS="$(lspci -d ::0403 -n | cut -f 1,3 -d ' ' | tr ' ' '|' | tr '\n' ' ')"
   #...ex: 00:1b.0|8086:1c20
   for aAID in $AUDIO_IDS
   do
    aPTH=":${aAID/|*/}/sound" #ex: :00:1b.0/sound
    aID="${aAID/*|/}"         #ex: 8086:1c20
    aCDS="$(grep "${aPTH}" /tmp/10alsa-CARD_PATHS-pci | rev | cut -c 1 | rev)"
    #...ex: 0 (card#)
    for aCARD in $aCDS
    do
     if [ ! "$aCARD" ];then continue; fi
     echo "${aCARD}+pci+${aID}" >> /tmp/10alsa-AudioCardHardwareProfiles
    done
   done
  fi
  #try fix profile...
  if [ "$CURR_SND_HW_PROFILE" == "0+" ];then
   CURR_CARD="$(grep '^defaults.pcm.card' /etc/asound.conf | tr -s ' ' | cut -f 2 -d ' ')"
   [ ! "$CURR_CARD" ] && CURR_CARD='0'
   CURR_PROF="$(grep "^${CURR_CARD}+" /tmp/10alsa-AudioCardHardwareProfiles | head -n 1)"
   if [ "$CURR_PROF" ];then
    grep -v '^#SND_HW_PROFILE' /etc/asound.conf > /tmp/10alsa-asound.conf-temp
    echo "#SND_HW_PROFILE='${CURR_PROF}'" >> /tmp/10alsa-asound.conf-temp
    mv -f /tmp/10alsa-asound.conf-temp /etc/asound.conf
    cp -f /etc/asound.conf /etc/asound.conf.${CURR_PROF}
    CURR_SND_HW_PROFILE="${CURR_PROF}"
   fi
  fi
  #backup and restore...
  for aHP in `cat /tmp/10alsa-AudioCardHardwareProfiles | tr '\n' ' '`
  do
   if [ "$CURR_SND_HW_PROFILE" == "$aHP" ];then
    cp -af /etc/asound.conf /etc/asound.conf.${CURR_SND_HW_PROFILE}
     #200523 1st bootup doesn't exist, hide error msg...
    cp -af /etc/asound.state /etc/asound.state.${CURR_SND_HW_PROFILE} 2>/dev/null
    SND_HW_PROFILE="$CURR_SND_HW_PROFILE"
    FNDflg=1
    break
   fi
  done
  #restore...
  if [ $FNDflg -eq 0 ];then
   for aHP in `cat /tmp/10alsa-AudioCardHardwareProfiles | tr '\n' ' '`
   do
    if [ -f /etc/asound.conf.${aHP} ];then
     cp -af /etc/asound.conf.${aHP} /etc/asound.conf
     if [ -f /etc/asound.state.${aHP} ];then
      cp -af /etc/asound.state.${aHP} /etc/asound.state
     fi
     SND_HW_PROFILE="$aHP"
     FNDflg=1
     break
    fi
   done
  fi
  if [ $FNDflg -eq 0 ];then
   SND_HW_PROFILE="$(grep '^0+' /tmp/10alsa-AudioCardHardwareProfiles | head -n 1)"
   #go back to automatic detection...
   echo "#SND_HW_PROFILE='${SND_HW_PROFILE}'" > /etc/asound.conf
   cp -af /etc/asound.conf /etc/asound.conf.${SND_HW_PROFILE}
   if [ -f /etc/asound.state ];then rm -f /etc/asound.state; fi
  fi
  ###end hardware profiling###
   
  ###set sound levels###
  #20211113 only set sound level if pure alsa system...
  # note: for pa, delayedrun will call set-max-snd-levels
  # note: pa is also responsible for restoring levels at future bootup.
  if [ ! -e /root/Startup/pulseaudio ];then
   if [ ! -f /etc/asound.state ];then
    #set all snd outputs to max...
    /usr/sbin/set-max-snd-levels
    if [ $? -eq 0 ];then
     alsactl -f /etc/asound.state store #120223 shinobar.
    fi
   else
    alsactl -f /etc/asound.state restore #from /etc/asound.state.
   fi
  fi
 ;;
 stop)
  if [ ! -e /proc/asound/card0 ];then exit; fi #180410
  if [ -f /etc/asound.state ];then
   alsactl -f /etc/asound.state store #saves to /etc/asound.state. 111229 add test file exists. 120222 revert. 120223 restore.
  fi
  # Kill processes holding open sound devices...
  fuser -k /dev/admmidi? /dev/adsp? /dev/amidi? /dev/audio* /dev/dmfm* /dev/dmmidi? /dev/dsp* /dev/dspW* /dev/midi0? /dev/mixer? /dev/music /dev/patmgr? /dev/sequencer* /dev/sndstat >/dev/null 2>&1
  if [ -d /proc/asound/dev ];then
   fuser -k /proc/asound/dev/* >/dev/null 2>&1
  fi
  if [ -d /dev/snd ];then
   fuser -k /dev/snd/* >/dev/null 2>&1
  fi
  # 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
  amixer set Master mute >/dev/null 2>&1
  # remove all sound modules... 120103...
  #lsmod | grep "^snd" | grep -Ev "(snd-page-alloc|snd_page_alloc)" |
  c=0
  while [ "`lsmod | grep 'snd_'`" ];do
   lsmod | grep "^snd" | grep '0 $' | grep -Ev "(snd-page-alloc|snd_page_alloc)" |
   while read line
   do
    #rmmod `echo $line | cut -d ' ' -f 1`
    modprobe -rv `echo $line | cut -d ' ' -f 1`
   done
   c=$((c+1))
   if [ "$c" = '6' ];then break; fi #precaution if neverending loop
  done
  # remove the 2.2 soundcore module (if possible)
  rmmod soundcore 2> /dev/null
  rmmod gameport 2> /dev/null
  # remove lockfile if lockdir exists
  if [ -d /var/lock/subsys ];then rm -f /var/lock/subsys/alsasound; fi
 ;;
esac

###end###
