How to use a MIDI Controller slider to control system volume?

Hi, great keyboard macro/modifier/all around genius keyboard app.

I have a question, I have a MIDI Controller: KORG nanoKONTROL Studio that I currently use to control LOGIC Pro X. Is there a way for me to assign one of the sliders (out of 8, when it’s not being controller by LOGIC) to control my Mac’s System Volume? I’ve been able to control the Volume using a button, but not with sliders and haven’t had the time to research for it. Since then, I think all I can do is to ask in the forums, see if anyone has done it before. I’ve searched the forums, and I haven’t found anyone doing it.

Thanks in advance,


Keyboard Maestro does not currently(!) support MIDI control change triggers.

Version 8 will, which will hopefully be released soonish.

Can't wait!

1 Like

Until then, take a look at ControllerMate. I think it was originally written for MIDI devices and has expanded to support other devices too.

@peternlewis - I see, I shall wait for version 8 then.
@Onan - Really? I have a copy of ControllerMate for my DualShock4 controller config. I shall try it out then.

Hey there,

Newbie here. I want to do this as well. I can see how I can hook into a cc change, but the Set System Output Volume action only lets me set it to a specific level.

Like I say, total newbie here. Should I be using AppleScript or the like?



Yep, you’ll need to use AppleScript to set the volume to a varying value.

The AppleScript is simply:

set volume output volume 57

So you can do something like:

tell app "Keyboard Maestro Engine"
   set v to getvariable "Sound Volume"
end tell
set volume output volume v

Now with KMv8, can we use some of the control sliders from midi controllers such as the NanoKontrol to tell something to KM? I only find “packages” as new addition, which i haven’t figured out how to work with that.

In theory yes.

Create a new macro in the Global Macro group, and add the MIDI trigger, change to controller change, make sure the Allow recording checkbox is checked, and the controller text field is selected, and then move the slider and see if Keyboard Maestro can see the MIDI packets.

@peternlewis what do I need to do to set this up, to use apple script I mean. I’ve tried copying your commands to the KM window, but it doesn’t do anything, and I don’t understand at all how this script works. I’m confused as how do I get the slider value, then as your example, I should be able to apply the number (mapped from max 127 down to 100 with simple math) to the system volume variable. But where do I get the slider value off KM in Apple script?

Thank you.

Going back to your original question, there are several steps of the process.

First, you have to detect the MIDI Control Change packet. You do that using the MIDI trigger. The TriggerValue token will include the details for the control change. So start off with a macro that does the MIDI trigger, and displays the TriggerValue token (since there will probably be lots of them, perhaps use the Log action and open the Engine.log file in the Console (or tail -f in the Terminal). The Engine.log file can be found in the Keyboard Maestro Logs folder (Help ➤ Open Logs Folder).

%TriggerValue[3]% will be just the control change value, which is probably the part you want.

The next part is setting the volume. So you need to set a variable (eg “Sound Volume”) to text %TriggerValue[3]%, and then use the AppleScript command to read the Keyboard Maestro variable and set the volume.

Put them all together, and if it still does not work, post your macro to the forum so we can see it and explain where it is not working - is it triggering, are you getting the right control change value, is it just the volume not being set.

Hi Peter,

Thank you for the reply, here is the screenshot of my setup

I got this setup from another thread, here in the forums. I finally get the "idea" of how this works. My question would be, how to make all of this run in "real time", as in respond as fast as it can. Currently, it lags a bit (maybe around 500ms or so, as in, the value changes once every ~500ms). If I scroll my jog dial slowly, the macro can keep up with the changes, but if I scroll it about 3 clicks per second, it will jump all over the place (the value). How do I make it respond in real time?

Thank you.

The issue is that the MIDI controller will be sending lots of controller change packets, each of which trigger the macro.

If Keyboard Maestro responds to all of them, then the macro can’t keep up, and so you will get a lag (and since Keyboard Maestro by default cancels everything if it gets to 50 macros running simultaneously, that might happen too to further mess up the situation).

So what you really want is:

  • If you get the trigger, and you’re not currently processing a trigger, set the volume
  • If you get the trigger and you are currently processing a trigger, note the new value, but wait a bit.
  • After the previous one finishes, then set it to the last trigger value (but don’t attempt to set it to each intervening trigger value as that is pointless).

This is probably doable, but somewhat tricky.

  • Set Variable “JogValue” to “%TiggerValue[3]%”
  • Semaphore Lock “JogLock”, timeout after 20 hundredths of a second, cancel macro, don’t notify
  • Until
    • Set Variable “Local JogValue” to calculation “JogValue”
    • Execute AppleScript to set volume to JogValue
    • Until calculation Local JogValue = JogValue

So you only have one instance of the macro setting the volume, and it keeps running as long as the volume keeps changing, setting the volume to the current selection in a simple loop.

See if that works.

Hi Peter, thank you for the reply. Here is the updated config, and it is faster to some degree.

I find that the problem of my latency, is that Keyboard Maestro's [Set Variable "JogValue" to Text "%TriggerValue[3]%"] action does not run in "real time", as in then I twist my jog dial, this value doesn't change as fast as my JogDial spins 

As for your suggestions:

  1. I understand how to do the first one (as seen in my updated config).
  2. The second one, I think this is what you meant by it (refer to my config, the Semaphore Lock panel).
  3. The third one "Until" is where I lost you. I know there's an "Until" Semaphore, but I don't understand the logic.What I understand about repetition logic are, there are 3 types:
  4. Finite type (do this for X times).
  5. Check the repetition on top type (while {this} do {that}).
  6. Check the repetition on the bottom type (do {this} until {that}).
    Looking at your suggestion, this is the third repetition type, but I don't see any action that can do the "repeat this part" part of the repetition, which confuses me. There is an "Until" Semaphore as I mentioned earlier...

Here is the "Try" config:

And this doesn't work, and I have no idea how to debug this.

Thank you, Peter.

You cannot base that on the editor update you circled - that value is only updated once per second, macros can trigger much faster than that.

Instead of "The variable matches" condition, use The calculation condition:

What you have will never loop, because the JogValue variable will never regex match "LocalJogValue".

You could do this:

"matches" would never work, even if you expanded the LocalJogValue variable as shown, becuase if it was "3" it would "match" "13" and "23" and "30" and "31", etc.

What you have should be producing an update roughly 5 times a second.

The AppleScript needs to always use JogValue, not LocalJogValue, since:

  1. JogValue is more up to date than LocalJogValue, which is what you want
  2. AppleScript cannot access local variables without more work, which you haven't done.

Hi Peter, I appreciated the reply, slowly I'm starting to understand how Keyboard Maestro works. I've been reading the manual, and I've seen somewhere in there - that there is a debugger that I can use. I've been searching for this debugger for few days, and haven't been able to find it.

Got it.

I tried "The Calculation: JogBalue = LocalJogValue", it doesn't work. Is there a way to monitor what variable contains what value at all times, maybe like Google Chrome Web Inspector, so I know what is happening. Even better if I can debug my macro using "step into".

Thank you in advance.

There is a debugger, select Start Debugging from the Keyboard Maestro status menu.

But it only shows you where in the macro you are, it cannot view variables.

You can watch variables in the Keyboard Maestro Preferences, but it wont see Local variables.

The only way to see Local variables is to report them from the macro (perhaps with a Log command in the Engine.log file, or perhaps using Display Text, but since there is a lot of them, the Log command is probably best).

Post your whole macro and I can take a look.

Here is the updated macro:

The notifications are for me to monitor the variables, and it's not helping...