Can't make Semaphore Lock to break loop when Stream Deck profile switching

I change Photoshop Stream Deck profiles with a macro that stores the name of the selected profile as a variable, "PSPreviousProfile" and then switches to that profile by activating a blank app.

Because several profiles may link to the same profile (for example, the "Brushes" profile) the "Back" button in the Brushes profile runs a macro that switches to the profile specified by the PSPreviousProfile variable.

When I switch back to Photoshop after using a different app, I need to load the profile that was open when I left Photoshop. I’m trying to use this PSPreviousProfile variable to do this, but I’m stuck in the "infinite loop" described by @noisneil and others.

In several posts, they mention using a Semaphore Lock action to break this loop, but I’m not grasping how to make it do that. I understand the lock prevents macros from executing simultaneously, but don’t see what that has to do with these two macros that appear to be executing sequentially.

Here's my switching macro:

Here's my macro that loads PSPreviousProfile when Photoshop activates:

Of course, when I activate Photoshop, the dummy app runs to switch the profile, then quits, then Photoshop activates and runs the dummy app again, etc.

How would I use Semaphore Lock in these macros to stop the looping?

I’ve been using UI scripting for a year and am ready to go the dummy app route to stop all the Stream Deck menu flashing!


Sounds like you're aware of all the steps but one thing to confirm is that you have disassociated your main Photoshop profile from the Photoshop app and are instead using a blank app for that too. If you don't, there's no way to avoid the infinite loop.

I'm sure you have that covered, as it sounds like it's working until you switch away and back.

As regards the lock, it's necessary because when the blank app activates, it takes focus in order to trigger the profile. Subsequently, Photoshop takes focus, but we don't want that to trigger the main profile right now; we want that to that instance to be ignored.

Of course, this only works if all switches are carried out by the same macro. Therefore, you might want to consider consolidating your switching into a single macro with some conditions.

For example, you could have a separate macro that sets a variable when PS is deactivated (no longer the frontmost app), and that variable can be used in your switcher macro to determine whether you should return to the most recent profile or go straight to the primary PS profile.

Also, you shouldn't need to programmatically quit blank apps if you have them set to quit after running when you make them. I can walk you through that if you don't know how.

What triggers this?

None of my Photoshop profiles have the "Make this my default profile" checked. (Actually, I haven't ticked this box for any of my applications.)

If I switch to Safari, my Stream Deck Safari profile loads. And then when I switch back to Photoshop, the Safari buttons are still there. When Photoshop takes focus, I think I always want to return to the profile that was loaded when I left it. (Every Photoshop profile has a "PS Home" button in the lower right corner that takes me to my home Photoshop profile.)

Right now, I have a separate blank-app-activating macro for each profile. That's the "Switching macro" that you asked about. It's triggered when I press a Stream Deck button via the KM-Link plug-in. For instance, when I want to see masking commands, I press a "Masking" button that runs the macro that opens/activates the blank PS-Mask app.

To consolidate these 12 macros, would I use a switch/case action like this?:

  • If the PSPreviousProfile variable is PS-Mask, activate the blank PS-Mask app
  • If the PSPreviousProfile variable is PS-Brushes, activate the blank PS-Brushes app
  • etc.

And this macro would be triggered when Photoshop activates?

If so, where do I put the Semaphore Lock action to stop the looping when the dummy app gives focus back to Photoshop?

Thanks for you help,

P.S. How do I create blank apps that quit after running? Would that be part of the AppleScript code, instead of just using "--this app does nothing"?

Sorry if I wasn't clear. I'm not talking about default profiles. I meant that you must not do this:

I'm trying to cover all bases here, but by the sound of it, I don't think you've fallen into this common trap.

Presumably, being able to return to the last profile is important to you, but if you could jettison that idea, then useing SD folders, pages or profile switching button actions would be a lot simpler and can all be done without Keyboard Maestro. Worth saying.

Seems like a separate thing. Unless I've misunderstood it seems there are two things you're trying to do:

  1. Switch SD profiles while PS is at the front. This can be done within the SD itself, but then you can't log which profile is current at the time you switch away from PS, so you're using KM to do it.
  2. Reopen the last PS profile you were in before you switched away from PS and back again.

Regarding point 1, you could use the same macro for all your PS profile triggers, and use the KM Link parameter box to send the blank app name to the macro (accessible as %TriggerValue%). You could store this as a global variable and use a shell script (as you have shown above) to open it.

Regarding point 2, you could add an application trigger (activates) to the same macro and use a text condition that determines whether %Trigger% contains activates. If it does, it means that the macro is being triggered by PS being made front-most. In this case, you could open the most recently chosen profile (remember, it's been stored as a global variable), again with a shell script.

Add a Semaphore Lock action to the front of the Photoshop activate macro with a very short timeout, and no notification on timeout, and then add a Pause action to pause 5 seconds at the end of the macro. So then the action will run, and then when it runs a second time, the Lock will still be in place and so the macro will abort.

The pause needs to be as long as it takes for Photoshop to launch and your profile switch to change and Photoshop to reactivate.

It's really important that I return to the last profile, because I frequently pause photo editing to research procedures in Safari or make notes in Obsidian. Every time I do that, I don't want to return to the Photoshop home profile and have to drill back in to pick up where I left off.

At your suggestion, I'm trying to use the KM Link parameter box to send the blank app name to the macro.

The actions below are in the macro "SD Profile: PS-Switcher." I’ve tried the two red actions and the green one (disabling the ones I’m not trying), and while the first red action does put PS-HSL Editing in the SDTrigger variable, the shell script doesn’t result in opening the blank app (also named PS-HSL Editing). I know nothing about shell scripting or its syntax, and tried a few approaches I saw in the KM Wiki pages with no luck.

I’m hoping I’m close with either the red pair or the single green action.


Try changing the shell script to:

open -a "$KMVAR_SDTrigger".app

That worked! Thank you so much!

You mentioned that I shouldn't need to programmatically quit blank apps if I have them set to quit after running when I make them.

Would that be part of the AppleScript app code, instead of just using "--this app does nothing"?


It's a checkbox when you save it as an application from Script Editor.


It looks like to auto-quit, I should uncheck "stay open after run handler," right?



I just read through this quickly so I may not have it right, but I think if you allow the blank app to auto-quit then the previous app will activate and so will its profile (if any)

The way I approached this in the past was to allow the blank app to keep running, which preserves the associated profile. Then—and this is such a hack—each of the buttons on the "blank app profile" would include an extra action to call a KBM macro that would at last kill the running "blank app"

Sorry, that's a little convoluted. But it worked.

This problem is solved by using the Semaphore Lock as described by Peter above, as long as the switching is all done in one macro.

If you had to keep it as separate macros for some reason you could programmatically disable the main switching macro at the start of the previous profile macro and then re-enable it after a short pause at the end.

Thanks for explaining, Peter. That worked!

1 Like