Updated: Control PulseAudio With a Command-Line Ruby Script

technology.pngAh, PulseAudio. A brief description for those unfamiliar with it:

As described on the PulseAudio page:

PulseAudio is a sound system for POSIX OSes, meaning that it is a proxy for your sound applications. It allows you to do advanced operations on your sound data as it passes between your application and your hardware. Things like transferring the audio to a different machine, changing the sample format or channel count and mixing several sounds into one are easily achieved using a sound server.

PulseAudio is designed for Linux systems. It has also been ported to and tested on Solaris, FreeBSD, NetBSD, MacOS X, Windows 2000 and Windows XP.

There’s pretty good GUI tools for configuring PulseAudio, but sometimes (like in my case) you have to (or want to) control it from the command line.  While I modified a Ruby script about nine months ago, it had some shortcomings – you couldn’t switch outputs with it, for one thing.

In a bout of productive procrastination, I taught myself some more Ruby and cleaned up and improved the script.  So I present to you my updated and improved Ruby script to control PulseAudio from the commandline. It’s primarily of use to people who are command-line focused or use keybindings to control their sound (or if your media keys are being wonky).

To the best of my knowledge (despite my dated version of PulseAudio) the commandline syntax is unchanged through the current version. If I’m wrong, please let me know!

Here’s the changelog:

  • Added usage instructions when no arguments given
  • Added quiet (no output) option
  • Added explicit percentage setting of volume
  • Added explicit muting/unmuting instead of just toggling mute
  • Formatted output to be somewhat more human-readable, including padding & volume percentages
  • Added function to allow changing default sink
  • Added code to switch playing streams to new sink.Added introduction/description into the script
  • Standardized indentations
  • Rewrote if/else statements into case statements (improving efficiency)
  • Rewrote array; arranged by sink id instead of name

So for example, here’s what the output looks like on my machine:

Usage:
ruby volume.rb [0-100|up|down|toggle|mute|unmute|default] [q]
[0-100] – set percentage of max volume for all sinks
up|down – Changes volume on all sinks
toggle|mute|unmute – Sets mute on all sinks
default – Select default sink from commandline
q – quiet; no status output

##Current status##########################################
ID Sink Name Mute Vol Default
0. pci-0000_00_1b.0 no 62%
1. usb-Logitech_Logitech_Z305-00-default no 62% *
##########################################################

Even though the names are still a bit arcane, it’s pretty obvious which one is the USB speakers. And now that it’ll switch my playing music player to the new output source without hassle, it’s pretty sweet. It does its job in the background and lets me get on with my day.

You can get the script from github or clone it:

git clone git://gist.github.com/1791270.git

Hope this helps someone as much as it helps me!