AppleScript speakers

I recently bought a USB headset to make Skype calls, and wanted a quick way to switch the Mac’s audio output between the built-in line output (which feeds my speakers) and the headset. Rogue Amoeba’s free SoundSource provides a handy system-wide menu bar for doing that, but every time I switched to the headphones, they blasted my ears. So I cobbled together this AppleScript to switch between sound sources and adjust the volume with one click.

The code is based on a script I found at MacOS Hints.com. I substituted the name of my headset, added a line that changes the volume, and added a verbal confirmation of the change and some error checking. I also reformatted the dialog window and set it to disappear after three seconds.

To use this script, paste it into Script Editor, substitute the names of your output devices for mine, and then save it as an application or as a script. You can then double-click the application to run it, or assign the script to a keystroke with a program like Butler.

Note the line about enabling Assistive Devices. Because the script works by interacting with elements on the screen, it misbehaved when I unplugged the headset—there was no longer a headset item to select in the Output menu. I’m surprised that AppleScript doesn’t let you refer to screen elements by an ID, such as “Balance slider.” Instead, you have to use syntax like slider 1 of group 1 of tab group 1 of window 1. I couldn’t figure out where the volume slider was located in that hierarchy, so I ended up changing the volume through the Finder. Let me know if you suss it out.


(*
This script toggles between two audio outputs in the "Sound" pane in "System Preferences" and adjusts the volume. 
Modified from a script at http://forums.macosxhints.com/showthread.php?t=45384 
to add volume control and GUI scripting detection. --David Battino, www.batmosphere.com.

USES GUI SCRIPTING; "ENABLE ASSISTIVE DEVICES" OPTION MUST BE CHECKED IN THE "UNIVERSAL ACCESS" PREFERENCE PANE
*)

tell application "System Preferences"
	activate
	set current pane to pane "com.apple.preference.sound"
end tell
tell application "System Events"
	if UI elements enabled then
		try
			tell application process "System Preferences"
				tell tab group 1 of window "Sound"
					click radio button "Output"
					if (selected of row 3 of table 1 of scroll area 1) then --headset is selected
						set selected of row 1 of table 1 of scroll area 1 to true
						set deviceselected to "Line Out"
						set verbal_description to "Line out."
						tell application "Finder"
							set volume 7
						end tell
					else
						set selected of row 3 of table 1 of scroll area 1 to true
						set deviceselected to "Logitech USB Headset"
						set verbal_description to "Headset."
						tell application "Finder"
							set volume 2
						end tell
					end if
				end tell
			end tell
			tell application "System Preferences" to quit
			tell me to activate
			say verbal_description using "Trinoids"
			display dialog "Audio output is now..." & return & return & "* " & deviceselected buttons {"Rock on"} default button 1 giving up after 3
		on error
			tell me to activate
			display dialog "Please plug in the headset." buttons {"Whoops!"} default button 1
		end try
	else --GUI scripting is disabled
		tell application "System Preferences"
			activate
			set current pane to pane "com.apple.preference.universalaccess"
		end tell
		display dialog "Please check the box called \"Enable access for assistive devices.\"" buttons {"Okay"} with icon 1 default button 1
	end if
end tell
SoundSource Menu

Rogue Amoeba’s SoundSource offers a simple way to switch among inputs and outputs, but it doesn’t adjust levels.

Another thing I haven’t figured out is why the script will occasionally reverse the volume settings for the line out and the headset, or crank the latter all the way up. (The scale apparently goes from 0 to 7, though there may be a parameter to increase the resolution to 256 steps, as in the QuickTime Player.) Nevertheless, I find having one-key output switching is a treat.

Update, 2006-07-17: I inserted a backslash before the quotation marks in the GUI scripting dialog so the script will compile correctly. The O’Reilly blogging system changed the curly quotes I had in the original script to straight ones, breaking it.