Switch Audio Source

My impression is:

Toggle item A:

“Internal Speakers”/“Headphone port”

Toggle item B: ?

Thanks for asking, ccstone.

In your format, toggle item A can be one of either:…

“Internal Speakers" or "Headphones”

… in my System Preferences, depending on whether the headphones are physically plugged in or not. The System automatically detects whether they are plugged in, and changes its Preferences text accordingly, and…

Toggle item B: “C_Media USB Audio Device”

The wording of toggle item B doesn’t change, unless the device itself isn’t plugged into a USB port, in which case your code alerts me to the fact it’s not there.

In your code, which works fine as is, if the headphones happen to be plugged in, then the Preferences wording changes and the code fails.

After reading your KM variable settings steps and your code script that follows (I know little about the coding), I was thinking what was needed was that KM, maybe, should do an IF-THEN-ELSE test before invoking your script, something like:

IF the System Preferences is set to “Internal Speakers” OR “Headphones” THEN switch to “C_Media USB Audio Device”

But I don’t know how to query the System, by changing your KM steps or code, about the state of the Preferences’s current setting, whether it’s “Internal Speakers” or “Headphones”. I’m guessing that KM should do the IF-Then test and branch accordingly so that it sets up your script properly. But maybe it works better if the script wording is adjusted in some way.

Hey Peter,

That's @ComplexPoint's code rather than mine.  :slight_smile:

I suggest you download and install this command-line tool:

AudioSwitcher.zip (107.1 KB)

Install it here:

/usr/local/bin/

Open a window in the Finder and type G

Paste the path string in the resulting dialog, and hit the GO button.

Drag the executable from the archive into that folder – you will be required to enter your password to do so.

Then you can run this macro and avoid having to mess with System Events.

Toggle Audio Output.kmmacros (2.5 KB)

Although the display in the Sound Preferences changes to reflect whether headphones are connected the actual underlying “Built-in Output” doesn't change, so the shell script doesn't need to check for headphones.

If the macro doesn't work out-of-the-box then the wording for C_Media USB Audio Device may be off.

You can check by switching to that output and then running this in the Terminal.app:

AudioSwitcher -c

The output should look something like this:

C_Media USB Audio Device (output)

If that differs from what I have in the shell script then you'll need to change it:

Remove (output) from the end of what you got from the terminal and replace the relevant string in the shell script in the macro.

All of this may seem a bit intimidating, but it's really simple to get done step-by-step.

Message me if you need help.

TESTED: on OSX 10.11.5 with Keyboard Maestro 7.2

-Chris

1 Like

The link to AudioSwitcher.zip leads to : Oops! That page doesn’t exist or is private.

Hey Dimo,

That's odd. I'm looking into it.

In the meantime the direct link works – but ONLY if you paste it into your browser's address field – NOT if you click the link in the forum. (Tested only with Safari.)

Strange...

https://forum.keyboardmaestro.com/uploads/default/original/2X/3/3d208a21186eb96aefbc9f6c2ff093296c12722d.zip

-Chris

Another approach I found is based on the fact that if “Sound” appears in the System menu bar, you can hold the option key and click on the Sound icon. That displays all connected output options, including airplay speakers.

I created the following script - which would need to be adjusted based on where the icon appears on a specific monitor, and where the selected output item appears in the sub menu.

Holding the option key - Move and Click without dragging (click on Sound icon)
Duplicate the step and change the down position by a small number and test if you have hit the item. In my case, the number was 50 to hit the fourth item in the list.

Not overly elegant - but it works well. One point - if this is in the middle of other steps - put a Pause in front and after the two macro steps.

1 Like

Hey Folks,

I fixed the download link in post #11.

-Chris

Chris

Thanks for all of this - I followed your instructions and got it working fine. Can you, or someone, help me with 2 questions, as I’m not fluent completely at home with coding, even though the terms are explained in the AudioSwitch documentation.

Firstly, what would the code look like if I wanted it to alter the input device rather than the output device? The default is output, so that changed with F1, but my input isn’t changing. I would ultimately like to change both, so I’m assuming just make a second code and have it run too. I know that -t refers to type, and since the default is output, we don’t see it in the code. So how do you alter the code to work for input?

Secondly, I’d actually like to run these codes triggered by plugging in the usb device. I sort of got that working by changing the trigger, but it seems to go through three steps: Switched to USB, to internal, back to USB. I suspect that’s because the mac is responding anyway when I plug the device in, and that the way around it is to have the KM code simply always run in the one direction (IF) and not have an alternative (ELSE) letting KM do the work. Am I right? Or is this coming across as confusing?

Thanks for any help.

Phil

Hey Phil.

This will change the sound input to the source named in the variable “inputName”.

# REQUIRES: AudioSwitcher Unix Command Line Tool

inputName='Soundflower (2ch)'

export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:$PATH
currentInput=$(AudioSwitcher -t input -c)

if [ ! "$currentInput" = "$inputName" ]; then

   AudioSwitcher -t input -s "$inputName"
   
fi

You can get the available help for AudioSwitcher by inputting the following in the Terminal:

AudioSwitcher -h

This is one-way only.

As for the USB-trigger you’re on your own. I haven’t gone beyond briefly testing them.

-Chris

Chris. Thanks again. Brilliant and I seriously wouldn’t have been able to do it on my own. Because it’s a one-way script, I duplicated it and substituted output for input, so it works exactly as I hoped. Awesome.

1 Like

What would your AppleScript look like if I want it to select a specific audio output, not toggle between two different ones?

Thanks!

You have in mind the JavaScript for Automation in the post below (post 2 of this thread) ?

The variable f gets the name-string of the device to be chosen:

var f = -1 !== c.indexOf(strDeviceA) ? strDeviceB : strDeviceA;

So you should be able to comment out that line, and replace it with something on the pattern of:

var f = "nameStringOfMyPreferredDevice";

where "nameStringOfMyPreferredDevice" is replaced by the real (quoted) name of the device.

That is exactly what I meant! Thanks for a quick reply.

Could you please show me the full script?

I’m still new with programming :wink:

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)

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