Changing the default sound card automatically in Linux

2008-04-20 02:23

Many people including me usually use a USB sound card or a USB speaker to enjoy noise-free high-fidelity sound. I simply don’t understand why all the main board manufacturers ship with a built-in sound chipset which just sucks. It’s not an exception for all laptops.

In a non-portable system such as a desktop PC, you usually don’t need to change your default sound card because your USB sound card is always connected. However, it’s a whole different story for a laptop computer. USB sound card is often disconnected and connected again. For example, I connected my USB speaker to the docking station. The expected behaviour is that the default sound card is chosen automatically – the sound system should be reconfigured so that my USB speaker becomes the default sound card when I dock to the docking station.

Currently, there’s no desktop environment that addresses this problem AFAIK, so I wrote a quick and dirty script file that reconfigures the sound system automatically when a new sound card is detected. The script assumes that you are running HAL and DBUS, which are very common in modern Linux distributions.

#!/bin/sh
# Path: /usr/local/bin/alsa-watch

# Exit if running already.
if [ "x`pgrep -of 'alsa-watch'`" != "x$$" ]; then
    exit 1
fi

# Configure the sound card to the default.
/usr/local/bin/alsa-reconfigure

# Begin monitering.
{
dbus-monitor --system --monitor "type='signal',path='/org/freedesktop/Hal/Manager',interface='org.freedesktop.Hal.Manager'" | while read -r EVT; do
  echo "$EVT" | egrep -qi "(DeviceAdded|DeviceRemoved)"
  if [ "$?" = '0' ]; then
    read -r EVT_VAL
    echo "$EVT_VAL" | egrep -qi '(alsa_playback|sound_card)_[0-9]+"'
    if [ "$?" = '0' ]; then
      # Reconfigure the sound card if a sound card is plugged in or out.
      /usr/local/bin/alsa-reconfigure
    fi
  fi
done
} &

Another required script is alsa-reconfigure. The following is what I put into the alsa-reconfigure script. I reset the volume level here:

#!/bin/sh
# Path: /usr/local/bin/alsa-reconfigure
# Exit if there's no sound card.
[ -f /proc/asound/cards ] || exit 0
cat /proc/asound/cards | grep -qi 'no soundcard' && exit 0

# Prefer USB audio device to other sound cards.
cat /proc/asound/cards | grep -qi USB-Audio
if [ "$?" == "0" ]; then
    CARD=`cat /proc/asound/cards | grep USB-Audio | head -1 | perl -pi -e "s/\\s*([0-9])+.*/\\1/"`
    USB='y'
else
    CARD=`cat /proc/asound/cards | head -1 | perl -pi -e "s/\\s*([0-9])+.*/\\1/"`
    USB='n'
fi

# Update ALSA settings.
echo \
"pcm.foo {
    type dmix
    slave.pcm \"hw:$CARD\"
    ipc_key 1024
}

pcm.!default {
    type plug
    slave.pcm \"foo\"
}

ctl.!default {
    type hw
    card $CARD
}
" > /etc/asound.conf

# Reset the volume. (optional)
if [ "$USB" == 'y' ]; then
    amixer sset 'PCM' 70% > /dev/null 2>&1
else
    amixer sset 'Master' 30% > /dev/null 2>&1
fi

You could also do something different such as restarting PulseAudio daemon:

#!/bin/sh
# Path: /usr/local/bin/alsa-reconfigure
# Exit if there's no sound card.
[ -f /proc/asound/cards ] || exit 0
cat /proc/asound/cards | grep -qi 'no soundcard' && exit 0

# Prefer USB audio device to other sound cards.
cat /proc/asound/cards | grep -qi USB-Audio
if [ "$?" == "0" ]; then
    CARD=`cat /proc/asound/cards | grep USB-Audio | head -1 | perl -pi -e "s/\\s*([0-9])+.*/\\1/"`
else
    CARD=`cat /proc/asound/cards | head -1 | perl -pi -e "s/\\s*([0-9])+.*/\\1/"`
fi

# Update ALSA settings. (optional if your Linux distribution uses PulseAudio by default)
echo \
"pcm.!default {
    type pulse
}

ctl.!default {
    type pulse
}
" > /etc/asound.conf

pkill -f '(^|/)pulseaudio( |$)' > /dev/null 2>&1
sleep 1
pkill -9 -f '(^|/)pulseaudio( |$)' > /dev/null 2>&1

# Restart PulseAudio daemon
pulseaudio \
  --system --daemonize --high-priority --realtime --log-target=syslog \
  --disallow-module-loading --disallow-exit \
  --resample-method=src-sinc-best-quality --no-cpu-limit -n \
  -L "module-native-protocol-unix auth-anonymous=1" \
  -L "module-native-protocol-tcp auth-ip-acl=192.168.0.0/16;127.0.0.0/8" \
  -L "module-rescue-streams" \
  -L "module-alsa-sink device=hw:$CARD"

I execute alsa-watch in my /etc/rc.local file and it works perfectly for me. :)

---

Comment

3 Comments

Silly question: which USB sound adapters work well with linux, and for full 6+1 optical out signals? Is there a list?

steve_l · 2008-04-20 20:58 · # · Reply

@steve_l: Most Logitech USB speakers and headsets worked perfectly for me. If you are looking for a USB sound card, I'd recommend you one from AUDIOTRAK - http://www.audiotrak.net/products/mayaex5ce/

Trustin Lee · 2008-04-21 00:59 · # · Reply

@steve_l: For the full list of supported USB sound cards, you'd better visit the official ALSA web site. I think most USB sound cards are supported basically because they all use the same protocol.

Trustin Lee · 2008-04-21 01:00 · # · Reply

 
  • Preview 버튼 누르고 reCAPTCHA 입력 후 Submit 버튼까지 눌러야 실제로 게시됩니다.
  • Make sure to answer the reCAPTCHA and click the Submit button to get your comment posted. It's not enough to click the Preview button only! -- See why.
---