Limiting your Mac’s Volume in 2020, an Update

Limiting volume only while on your Headphones

Lucas Andión
Trabe
4 min readNov 17, 2020

--

Photo by 9to5mac

Big Sur was released yesterday, and even with its new shiny UI for controlling volume, Apple has again failed to add an option to limit it.

Now that we know we are not getting native volume limit control anytime soon we can put some energy into improving the script a little.

My current solution, which I detailed in my previous post is far from perfect, but it has worked well for me and some other people.

It even has some uses I haven’t considered when I wrote the script. Chloé Chassany is taking advantage of it to be able to use a pair of broken EarPods.

Headphone detection

Ranhiru Jude Cooray improved the script to use SwitchAudioSource to detect whether your headphones are connected or not.

You can take a look at the full solution in his blog post. In short, you have to install SwitchAudioCore using homebrew and then run the installed program as a shell script. Here is that bit, extracted from Ranhiru’s code:

If the standard headphones are connected this should output “External Headphones”.

Sadly, this solution does not work for me. In my case, SwitchAudioSource is not returning different values when earphones are connected or internal speakers are being used. It just says “Built-in Output” all the time.

It appears there is an open issue related to this problem: SwitchAudioSource won’t work consistently over Mac OS versions.

Using system_profiler

The issue we talked about linked a StackOverflow thread where user jordan314 suggested using system_profiler to check for the audio source like this:

The script above just looks for the string “Headphones” using grep on the output ofsystem_profiler SPAudioDataType.

This works great if you only use wired headphones, but it does not work when using Bluetooth sets. In my case, when I have nothing connected the script returns:

And when I connect my wired headphones it just changes the “Built-in Output” like this:

Checking for all kinds of headphones

My first attempt was to use this regex that matches whatever Output Source name is on the entry containing the string “Default Output Device: Yes”.

But this does not work when I’m using my Bluetooth headphones. In this case, the output adds two extra devices (input and output) and moves Default Output Device: Yes to a new entry, with a useless Default under Output Source.

So, in the end, I decided to just detect when my Internal Speakers are not the Default Output Device, since I have no external Bluetooth Speakers this should work for me. You can check the regex I am using to do it here.

You may have different needs, maybe you have Bluetooth speakers or any other setup. If this is your case, you would need to adapt the script to your needs. Just play with the output of system_profiler and check for your desired conditions.

Adapting our PurrfectVolume script

Our original PurrfectVolume app was just an AppleScript written in Javascript. To perform the output device detection detailed in the previous section we just have to execute system_profiler as a shell script and match its output with the Regex we created. The code looks like this:

We were using AppleScript’s idle() handler to check for the volume every half a second. Now we will also check if our Headphones are connected or not every half a second.

Now our script will auto-limit the volume just when it’s necessary and will let us blast music on our speakers when we celebrate the end of the COVID era, hopefully.

Our final script looks like this:

Note that it won’t work unless you save the script as an app, since it’s the only scenario where our idle() handler works. If a stay-open script application includes an idle handler, Applescript sends the app periodic idle commands every X seconds, where X is the value returned by the handler itself (or 30 by default).

The script will also show a notification every time we connect or disconnect our Headphones, warning the user about the presence/absence of a volume-limit.

When you change sources (or plug your headphones) the script limits the volume automatically.

You can download the updated app here. For instructions on creating your own app or adapting it, you can check my previous post. You can find the code in the same repository.

Wrapping up

It’s sad that Apple does not offer an integrated solution for volume limiting yet. Even the recently released Big Sur’s revamped control center with volume settings does not seem to fix this.

You may have different needs, and just want to check when your specific device is connected or avoid some Bluetooth Speakers to be dimmed. In that case, you could just play with the output of system_profiler.

If after reading this post you still have trouble adapting the script, you can always post a comment, I’ll be happy to help you.

Kudos to Ranhiru for the initial Headphone check version, and for sharing it with everybody.

--

--

Lucas Andión
Trabe

Galician. Software developer @trabe. Bike lover, beer enthusiast, mad traveler, beagle friend, surfer wannabe — https://andion.github.io