"Sound is not running for specific time" trigger?

Hello guys,

Do you have any genius idea for creating an “execute a specific macro when sound is not running for specific seconds/minutes”?

Currently, there is no trigger for running sound.

By “sound is not running” do you mean there is no sound output? I don’t know of any utilities that can do things based on if sound is being outputted. You might look into Rogue Amoeba’s software since they make a lot of great audio-related apps, of which I use several, but I don’t think even there’s can do things based on if sound is being outputted or not. I’m happy to be proven wrong however!

Thanks for sharing,

What I meant by "sound is not running" is when the Media Player or YouTube or whatever is playing sound on your computer has stopped and is not playing anymore, either by itself or manually by you.

I know this is a tough one,

Actually I have few softwares of Rogue Amoeba and I don't see how I can find the solution from them.

Not a trigger, but through this thread on stackoverflow I found way to check if the mac is currently outputting sound, and made it into a subroutine:

Is sound being outputted [SUBROUTINE].kmmacros (3.5 KB)
(v11.0.2)

Macro Image

The return from this subroutine can be used as input for conditions within the macro, e.g. IF Mac is (or is not) outputting sound do *your thing*, OTHERWISE do nothing (or cancel macro, or anything).

DEMONSTRAITNG Subroutine- Is sound being outputted.kmmacros (4.1 KB)
(v11.0.2)

Macro Image

On my system the pmset is prette much immediate at changing status after a sound output starts, but takes about 1–2 seconds to change status after the output stops, still useful for many situations I’d say.

EDIT: Fixed a couple of spelling errors in the uploaded macros

3 Likes

I like this method. You could perhaps simplify the subroutine by running your if/else/then via bash.

audioOutput=$(pmset -g | sed -En "/^ sleep /p" | grep -o "coreaudiod")
if [[ $audioOutput == *"coreaudiod"* ]]; then
  echo "1"
	  else
  echo "0"
fi

That will return 1 for audio outputting or 0 for no audio output. Your subroutine could then be as follows:

Subroutine Screenshot (click to expand/collapse)

You also don’t really need the macIsOutputtingSound variable parameter under the trigger, unless you need to pass information to the subroutine for processing before execution. Removing that will remove the variable field in the execute a subroutine action as seen below:

Actions Screenshot (click to expand/collapse)

3 Likes

Thank you so much for these pointers! I am a total novice when it comes to scripting, which is why I currently build my macros almost entirely using native KM operations. But satisfyingly I was able to follow or make sense of most of the steps you’ve done in your bash. Thank you also for the clarification helping me understand how better to use KM Subroutines!

Uploaded here are versions, of my macros above, following your ideas:

Is sound being outputted [SUBROUTINE] v2.kmmacros (2.4 KB)
(v11.0.2)

Macro Image

DEMONSTRAITNG Subroutine- Is sound being outputted v2.kmmacros (4.1 KB)
(v11.0.2)

Macro Image

3 Likes

I appreciate it a lot, guys,

I forgot to say I know nothing about scripting (:

So I just imported the last two macros, but nothing happens when I pause the sound, either by your action or by my new action; the action does not fire.

Also, on my Mac, it shows that sleep is prevented even when there is no sound playing.


The «Is sound being outputted» Subroutine is sadly no substitute for a trigger, and the demonstration I uploaded is not set up with a trigger. You can of course try it by pressing Run (the play-button towards the top of your editor window), but you would have to choose a method of triggering the macro in your real world use case. Using a periodic trigger to periodically poll for the sound outputting status, could be one way of doing it, periodically checking if sound is not outputting, but as emphasised in the wiki about the Periodic Trigger:

Caution: Generally it is recommended to not use very frequent intervals (like seconds), except as a last resort.

Usually it can be possible to find something else happening just before or at the moment you want it triggered, something you or your computer does, that can be used to set up a somewhat precise trigger.

As there really is no no sound is outputting trigger, and running the script is no direct substitute for that, it'd be much better, I think, if you could elaborate on what the task is, that you are trying to achieve with your macro. There might be other ways to solve your task not relying on something emulating a no sound is outputting trigger.


Butu yes, from your screen shots it does seem like there is something very different with how the coreaudiod is showing up in your Power Management Settings, preventing the script from returning the correct state. The script is simply checking if that sleep line is containing 'coreaudio' so as it seems it will always return a 1 on your system. I have no idea why coreaudiod is showing up numerous times there, but hopefully someone else might have an idea, as there might in any case be something weird going on there that you should look into.


Since the script is not returning as intended on your system this might not be relevant to you, but heres a hot key triggered demonstration of how it can be set up so that a macro first continues on passed the teal While engrouping action, only after the submacro returns a 0, (usually indicating that sound is not being outputted):

DEMONSTRAITON #2 — If triggered while playing sound the macro should not reach the green group until after mac have stopped playing sound.kmmacros (4.2 KB)
(v11.0.2)

Macro Image

The While here is running a tight loop, if the submacro is returning a 1 it will immediately run it again, until it returns a 0. If you cannot find a precise way of triggering your macro, having to leave this macro running for more than say a minute, I'd definitely enable the pause action I've added within the While, setting it to an appropriate time intervall to re-run the Submacro

1 Like

Hello @Elad :wave:

Here is another suggestion maybe - if you don’t want to use a Subroutine - you know there is a Script Condition ?
You could then use this in with the Bash script.

Tagging Chris (@cdthomer) & Alex (@Alexander) here - maybe you two have forgotten about this option ?

Greetings from Germany

Tobias

1 Like

When you point it out, I also see how the subroutine approach is not really beneficial in the context of this thread. I only set it up, and shared it in this way, as I wanted to have it available in my KM as a nifty little subroutine for implementing into different macros.

Thank you so much for steering me towards this script condition! I have known about it, but not actually forgotten about it though, as I do not think I’ve ever really tried it.

It is a really nice way of doing it! Or mostly for scripts where the return is somewhat predictable, I guess. But many times that is the case, and I can definitely see myself having this method as my go to for many cases of simple script implementation coming forward! And the same situation as set up in my last demonstration can be set up really cleanly using it!

DEMONSTRAITON #2 A1 — If triggered while playing sound the macro should not reach the green group until after mac have stopped playing sound.kmmacros (4.0 KB)
(v11.0.2)

Macro Image

Implementing the script into a macro in this neat and simplistic way also have some downsides of course: First of which is monitoring what the script is actually returning. Especially important when testing scripts and commands where the output is unknown, and when modifying scripts.

Secondly the biggest drawback for this method, the way I see it, is that this condition is not implemented in the Switch/case action. Making it difficult to set up different outcomes based on different outputs. I, at least, do not see here now how this script condition could be set up to do one thing if it returns 0, and another if it actually returns 1, (or the other way around). Otherwise/else would not really differentiate between 1 and ‘no return’ if used within an If then. And it could only be checked by running the script again, either within the same action, or in a separate If then, neither of witch would be tru differentiation, the way I see it. Or I guess in this particular use case the macro would abort, if the script failed, which is the only way it could not return either 0 or 1 making the OTHERWISE condition actually stating that the return was 0 if initial condition is set to IF script text “is” (returning) 1. But in my eyes this condition would be much more complete, as an approach, if the Switch/Case would also have the option of using it. But still very nice, and thanks again for pointing me towards it!

EDIT: Uploaded a new version of the macro where the Untils Action timeout is set to 1 minute, as it'd not be great running this script in such a tight loop for longer periods

2 Likes

Thank you all, guys!

As I see it, unfortunately, in my condition, there is no option for triggering if the sound is playing or not, as you saw in the images I shared.

So, to whom it may help, my workaround was to separate play and pause into shortcuts (instead of the default spacebar), which you can do inside the Apple Shortcuts app.

Then create a Keyboard Maestro triggers (with a keystroke) for that shortcuts with "execute shortcut",

So now, after that, I have the "Pause" shortcut on my keyboard and the "Play" shortcut on my keyboard as two separate shortcuts. Instead of the toggle shortcut (spacebar), which prevents you from doing it (to execute an action when sound is not playing).

Then I put whatever I wanted after the "Execute Shortcut"; in my case, it was "Quit a specific app."

KM Keystroke -> Execute Pause Shortcut (Only in Mac) -> Whatever Actions You Want.

Hope it helps.

Cheers.

1 Like