USB sound in Ubuntu – automatically selecting a USB audio device when it is plugged in

Ubuntu has started to support USB audio.    When I plug in a USB speaker or headset, it gets recognized and installed automatically.  However there are some bugs:

  • The USB sound device does not get selected automatically.   This is especially annoying for headphones.  When you plug in analog headphones, the sound automatically switches to them and the main speakers turn off.
  • The volume settings are turned way up for the device.  Ideally it would remember the volume settings from the last time the device was plugged in.
  • When the computer goes to sleep, the volume of usb devices gets turned way up on wake.

I discovered that I could address these shortcomings by creating a script.

  • PulseAudio provides command line control through pacmd.  I can use that to Query for USB audio devices (both speakers and microphones) that got installed automatically
  • Select default devices (both speakers and microphones)
  • Set volumes for devices (both speakers and microphones)
    • The udev system provides a mechanism for running a script when a USB sound device is plugged in<
    • The pm-utils system provides a mechanism for running a script on wake.

I have included the text of the script below.  To start using it:

  1. Copy and paste the script to a file in a permanent location (for example into /opt/usb-audio-select.sh)
    • sudo editor /opt-usb-audio-select.sh
    • Copy, paste,  save, then exit
    • Make the script executable
    • sudo chmod a+rx /opt/usb-audio-select.sh
  2. As a super user, run the script with the --install flag.  This will install the play command if you don’t have it, setup the udev rule, restart the udev system, and install the pm-utils script.
    • sudo /opt/usb-audio-select.sh --install
  3. If you want to test the script without  fully installing  (or run it manually for any reason) you may do so.
    • /opt/usb-audio-select.sh
  4. The script sets volume levels that are appropriate for my headset.  You might need to edit the script to adjust the volume levels to your preferences.

#!/bin/bash

# Automatically select USB sound devices 
# Copyright (C) 2013 Stephen Ostermiller
# 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., 51 Franklin Street, Fifth Floor, 
# Boston, MA  02110-1301, USA.

if [ "$1" = "--install" ]
then
    if [ $EUID -ne 0 ]
    then
        echo "Error you are not the root user."
        echo "Run this install as root (or use sudo)"
        exit 1
    fi
    if [ ! `which play` ]
    then
         apt-get -y install sox
    fi
    script=`readlink -f $0`
    rulefile=/lib/udev/rules.d/99-usb-audio-auto-select.rules
    if [ -e $rulefile ]
    then
        echo "udev rule already exists: $rulefile"
    else
        echo "Creating udev rule: $rulefile"
        echo "ACTION==\"add\", SUBSYSTEM==\"usb\", DRIVERS==\"snd-usb-audio\", RUN+=\"$script\"" > $rulefile
        service udev restart
    fi
    rulefile=/usr/lib/pm-utils/sleep.d/99usbaudio    
    if [ -e $rulefile ]
    then
        echo "pm-utils sleep/wake rule already exists: $rulefile"
    else
        echo "Creating pm-utils sleep/wake rule: $rulefile"
        echo -e "#!/bin/sh \n case \"\$1\" in \n 'resume' | 'thaw') \n $script \n ;; \n esac" > $rulefile
        chmod a+x $rulefile
    fi
    exit 0
fi

if [ "$1" = "--sleep" ]
then
    sleep 1
fi

if [ "$UID" == "0" ]
then
    # Check process table for users running PulseAudio
    for user in `ps axc -o user,command | grep pulseaudio | cut -f1 -d' ' | sort | uniq`
    do
        # Fork and relaunch this script as each pulseaudio user
        # tell it to sleep for a second to let pulseaudio install the usb device
        su $user -c "bash $0 --sleep" &
    done
else
    # Use grep to figure out the name of the usb speaker
    speaker=`pacmd list-sinks | grep 'name:' | grep usb | sed 's/.*<//g;s/>.*//g;' | head -n 1`
    # Use grep to figure out the name of the usb microphone
    mic=`pacmd list-sources | grep 'name:' | grep input | grep usb | sed 's/.*<//g;s/>.*//g;' | head -n 1`

    if [ "z$speaker" != "z" ]
    then
        # use this speaker
        pacmd  set-default-sink "$speaker" | grep -vE 'Welcome|>>> $'
        # unmute
        pacmd  set-sink-mute "$speaker" 0 | grep -vE 'Welcome|>>> $'
        # Set the volume.  20000 is 20%
        pacmd  set-sink-volume "$speaker" 20000 | grep -vE 'Welcome|>>> $'
    fi

    if [ "z$mic" != "z" ]
    then
        # use this microphone
        pacmd  set-default-source "$mic" | grep -vE 'Welcome|>>> $'
        # unmute
        pacmd  set-source-mute "$mic" 0 | grep -vE 'Welcome|>>> $'
        # Set the volume.  80000 is 80%
        pacmd  set-source-volume "$mic" 80000 | grep -vE 'Welcome|>>> $'
    fi

    #play a sound to let you know that it was plugged in
    play /usr/share/sounds/speech-dispatcher/test.wav 2> /dev/null
fi

exit 0

This script is licensed under the GNU General Public License 2

Leave a comment

Your email address will not be published. Required fields are marked *

12 thoughts on “USB sound in Ubuntu – automatically selecting a USB audio device when it is plugged in”