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)
udevsystem 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:
- Copy and paste the script to a file in a permanent location (for example into
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
- As a super user, run the script with the
--installflag. This will install the
playcommand if you don’t have it, setup the
udevrule, restart the
udevsystem, and install the pm-utils script.
sudo /opt/usb-audio-select.sh --install
- If you want to test the script without fully installing (or run it manually for any reason) you may do so.
- 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