Switch Audio Source

Assuming that you have set a Keyboard Maestro variable called soundDevice to the name of your preferred device (or some distinct part of its name that appears in the System Preferences sound section), then I think a quick patch might look like this:

(For an Execute JavaScript for Automation action, or for prior testing in Script Editor, with the Language tab at top left set to JavaScript rather than AppleScript

(function (strDevice) {
    'use strict';

    var e = Application("System Preferences"),
            b = !1,
            d;
        e.panes["com.apple.preference.sound"].anchors.output.reveal();
        var a = Application("System Events")
            .processes["System Preferences"].windows[
                0].tabGroups[0].scrollAreas[0].tables[0].rows,
            c = a.where({
                selected: !0
            }),
            c = c.length ? c[0].textFields[0].value() : null;
        if (!c) return null;
        var f = strDevice;
        a()
            .forEach(function (a) {
                b || (d = a.textFields[0].value(), -1 !== d.indexOf(f) &&
                    (a.select(), b = !0));
            });
        a = Application.currentApplication();
        a.includeStandardAdditions = !0;
        a.activate();
        a.displayNotification(b ? "->  " + d :
            "Couldn't find a sound device containing this string: \"" + f + '"', {
                withTitle: "Sound Output Device " + (b ? "" : "NOT ") + "Changed"
            });
        e.quit();
        return b;

    })(Application("Keyboard Maestro Engine")
        .getvariable(
            'soundDevice'
        )
    );

I was looking for a way to cycle through audio devices and found many topics in KM forums. After testing some of the solutions, I chose the executable file solution AudioSwitcher.zip (107.1 KB) from @ccstone's reply.

  • Drag the executable file and drop it onto Applications folder, unless you want to keep it somewhere else then you would also need to change the default path of the executable file in the AppleScript below from "/Applications/AudioSwitcher" to your favorite path.

I made a few changes to this AppleScript StackExchange - SwitchAudioSource. The dialogue box seems unnecessary in my opinion so I deleted its line. I replaced it with a notification to know which output device is the current one. Also replaced " -c" with "-n".

Swtich Audio Source

on run
    set theSwitch to "/Applications/AudioSwitcher"
    do shell script theSwitch & "-n"
end run

Swtich Audio Source.kmmacros (1.6 KB)

1 Like

Hey Ali,

The typical place to install 3rd party Unix executables is here:

/usr/local/bin/

Open a window in the Finder, type Cmd-Shift-G, and paste the path into the “Go to the folder” field.

The system will require you to authenticate the move, and that's fine.

Also – there is no point in running a shell script from an AppleScript, unless it's part of a larger AppleScript.

Keyboard Maestro has a Execute a Shell Script action for pure shell scripts.

image

See this topic on the wiki for more information:

https://wiki.keyboardmaestro.com/action/Execute_a_Shell_Script

By using the export command, with the PATH variable, you won't have to use the full path to the executable.

export PATH=/usr/local/bin:$PATH;
AudioSwitcher -a

See brief discussion here: Path to excutables in shell scripts

You can also set a variable in Keyboard Maestro's variable preferences that will globally affect the PATH environment variable in the KM context.

The following link is to a macro that will do that for you.

Create a PATH Environment Variable for Keyboard Maestro and Add /usr/local/bin to the Default Path

This allows you to call your shell executable very simply:

AudioSwitcher -a

-Chris

These are valuable tips, Chris. Thanks

1 Like

These tips helped me a lot, as well. Thank you all! Not sure if this justifies opening up a new thread, so I'll try a reply here first:

While the macros discussed here change the audio output source, I would like to have something similar changing the input. So, whether I want to use the internal Mac microphone or the one attached to my USB headset. Ideally of course, this is combined with the output - so when I switch output to the headset, the input/mic should switch as well and vice versa.

Since you use the external shell script for the audio output, I guess I need something like this for the input as well?

Thanks,
Axel

Nevermind, just saw that you can change from output to input with the -t parameter.

I wonder if anyone can help me with an issue I'm having with this.

I'm trying to make a macro to cycle through my audio outputs and I found this thread. I installed AudioSwitcher and have this script in KM image

I have 3x audio outputs showing in system preferences on my mac - MacBook Pro Speaker, My Airpods Pro, BenQ LCD.

When I run the script in KM it works temporarily (depending on which audio output was selected last) but then gets stuck on zoomaudiodevice.

Any help would be much appreciated.

Hey @asonofdob,

Run this in the terminal:

/usr/local/bin/audioswitcher -a | pbcopy

It will copy a list of your 'puts to the clipboard like so:

Built-in Microphone (input)
Built-in Input (input)
Soundflower (2ch) (input)
Soundflower (16ch) (input)
Built-in Output (output)
Soundflower (2ch) (output)
Soundflower (16ch) (output)

Post yours to the forum, and we'll see if there's a work-around.

-Chris

Hey Chris,

Appreciate you taking a look at this. Here is my list:

HD Pro Webcam C920 (input)
MacBook Pro Microphone (input)
EpocCam Microphone (input)
ZoomAudioDevice (input)
BenQ LCD (output)
MacBook Pro Speakers (output)
EpocCam Microphone (output)
ZoomAudioDevice (output)

Cheers

What are you switching?

Input, Output, or both?

What version of macOS are you using?

-Chris

Hi Chris,

Apologies I didn't have everything plugged in before. You can see my updated list below:

AirPods Pro (input)
HD Pro Webcam C920 (input)
MacBook Pro Microphone (input)
EpocCam Microphone (input)
ZoomAudioDevice (input)
AirPods Pro (output)
BenQ LCD (output)
External Headphones (output)
MacBook Pro Speakers (output)
EpocCam Microphone (output)
ZoomAudioDevice (output)

I'd like to switch my output between Macbook Pro Speakers, External Headphones (wired) and Airpods when they are connected.

I am running Catalina 10.15.7

Thanks

Okay, run each of these lines separately:

audioswitcher -s 'MacBook Pro Speakers'

audioswitcher -s 'AirPods Pro'

audioswitcher -s 'External Headphones'

Make sure they do in fact switch the ouput appropriately.

If they do, then we'll move forward from there.

-Chris

1 Like

Perhaps it helps someone, so I described how I got it to work:
I've tried the instructions from Jun 2016 from @ccstone
But I was always told AudioSwitcher not found.

But installing https://github.com/deweller/switchaudio-osx via homebrew and then using this shell script (modified from @ccstone to use SwitchAudioSource and my own Sources) as a KM action worked:

export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:$PATH;

currentOutput=$(SwitchAudioSource -c); echo $currentOutput

if [ "$currentOutput" = 'MacBook Air Lautsprecher' ]; then

	SwitchAudioSource -s 'Externe Kopfhörer'

else

	SwitchAudioSource -s 'MacBook Air Lautsprecher'

fi

BTW – I've also tried the following script to switch between all available outputs, but that also comes with an annoying message that I have to close.

export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:$PATH;

SwitchAudioSource -n

Hey Johannes,

What version of macOS are you using?

-Chris

Big Sur 11.2.2
on an M1

What message?

Can you provide a screenshot?

-Chris

That's what it looks like.

Also:

How might I add an if else statement that checks whether the output I want to switch to is available / in the -c list?

You have the Execute a Shell Script action set to display the result in a window.

There is no list generated by the -c switch – that only displays the current device.

Run:

SwitchAudioSource -h

In the Terminal.app to see SwitchAudioSource's help.

To list all available devices:

SwitchAudioSource -a

To discover if a certain device exists in Bash:

deviceExists=$(SwitchAudioSource -a | awk '/Soundflower \(2ch\) \(output\)/ { print }')

if [ "$deviceExists" != '' ]; then

   echo "Device $deviceExists Exists!"

else

   echo "Device $deviceExists Does NOT Exist!"

fi

You could also do this by:

  • Running SwitchAudioSource -a and capturing the output to a variable.
  • Then use Keyboard Maestro's own search to look for your device.
  • Then use Keyboard Maestro's If Then Else or Switch or Case action to branch as desired.

I prefer to keep the whole bit in one Execute a Shell Script action for simplicity and speed, but then I know how to use Bash for such things.

-Chris

Thanks for the help Chris.

My goal is the following:
In my office I want to switch between A/B.
At home I want to switch between A/C
(B always exists because it's the internal speaker, C is only connected at home)

Here is the script, that makes sense to me (but doesn't work):

export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:$PATH;

currentOutput=$(SwitchAudioSource -c); echo $currentOutput

deviceExists=$(SwitchAudioSource -a | awk '/C \(output\)/ { print }')

if [ "$currentOutput" = 'C' || "$currentOutput" = 'B' ]; then
	
	SwitchAudioSource -s 'A'
			
else
	if [ "$deviceExists" != '' ]; then
		SwitchAudioSource -s 'C'
	else
		SwitchAudioSource -s 'B'

fi