Can I pause the Pause action's timer?

I have a macro that contains a 10 minute timer for each repeat/loop. What I want is for that 10 minute timer to pause when I switch to another application, and then resume when I come back to the target application.

Right now I'm using the action Pause for x minutes as the timer, but I don't think it can be paused. In other words, I want to pause the Pause action! (Or use another timing method.)

Is this possible in Keyboard Maestro? TIA!

Just to make sure I understand, you want nothing to happen at all while the timer is active, just counting off ten minutes? And if you switch to another app, that 10 minute timer should pause, then resume where it was when you go back to that application?

-rob.

1 Like

Interesting problem. I'm not sure if my solution is optimal, but I do have a solution.

My recommendation is that you create a variable called TimeReactivate which is assigned a value of TIME()+60*10, and then create a macro that triggers once per second, and in that macro, if the application isn't the one you are timing, then "add 1" to the value of TimeReactivate. Your pause statement would look like this: (starting with a 10 minute timer variable setup)...

Then your second macro would look something like this:

Any second that your application (in the example above, Mail) is not active, one second will be added to the time before the pausing macro can continue.

Most likely there are better solutions, but this one isn't too bad.

2 Likes

How accurate do you want your 10 minutes to be?

Instead of "Pause Until" you could post the value 600 into a variable then "While" the value is >0 you'd test to see if the app was frontmost, decrement the counter if it is, then "Pause" for one second.

Here's an example for TextEdit. Run it when TextEdit is frontmost and the dialog appears after 10 seconds. Run it when TextEdit is frontmost, wait 2 seconds, switch to Finder for however long you want, switch back to TextEdit and the dialog appears 8 seconds later.

Wait for 10 seconds of TextEdit Front-time.kmmacros (5.8 KB)

Image

This won't be 100% accurate, but should be near enough for most use-cases.

If it isn't -- what's so important about 10 minutes of front-time? There may be something better than a timed pause, especially if this is a "waiting for something to complete" style of thing.

3 Likes

Thanks for all the replies.

I was wondering if there was a way to do this without variables because I was concerned about running triggers constantly (for system performance and cluttering the console log), but I'm probably overthinking it.

Accuracy is actually extremely low-priority, in fact I could run this every 60 seconds, which mostly alleviates my concerns above.

I'll have to tinker with this concept quite a bit to integrate it, and I'll have to run it asynchronously with my main macro which is not ideal, but I'll let you know how that goes!

Cheers.

Personally, I don't worry about using up too many instructions, since modern Macs can process roughly 20,000,000,000,000 instructions per second (and have multiple processors.)

Now that you've modified your requirements, I would take a different approach. I would rewrite your macro to trigger every few minutes, and it should be in a group that allows it to trigger only when your preferred application is active (in front.) No "pause" is required if you do it this way.

I do this sort of thing all the time with many of my macros.

2 Likes
  1. You have to store something to do with time somewhere, and a local KM variable is probably the "cheapest" way of doing so
  2. Don't confuse variables with triggers

My macro above is just a demo. For your use you'd replace your "Pause for 10 minutes" action with the "Set Variable Local_theCounter..." action (changing the number to 600 for 10 minutes) followed by the "While..." action and its contents. So there's no trigger cluttering your logs, and the whole routine will use (in my testing) ~5% of one core of your processor -- you won't even know it's running.

Generally, KM actions themselves have an insignificant impact on your system. It's the activities of other programs that you're automating, or "external" scripts, that are noticeable -- subtracting 1 from an internal variable is nothing compared to even a simple "Activate Safari" and the resource cost of bringing Safari to the front, redrawing its windows, and so on.

2 Likes

Here's a take relying on Pause Untils instead of frequent looping.

With the Pause Untils setting for 'Reduce CPU Usage' enabled (the default setting), its tax on your system should be quite low. To prioritize accuracy over system load, making the pause/delay calculations closely match the time defined in the local_pauseMinutes, you'd disable this setting in the two Pause Untils.

For testing before implementation I'd set the multiplier of 60, in the two calculation conditions, to 1, effectively turning the local_pauseMinutes' unit into seconds instead.

Delay pause if app is not at the front.kmmacros (22 KB)

Macro image

1 Like

Interestingly, my "loop with a 1 second pause" grabs slightly less CPU than your "Pause Until" -- 10 concurrent instances of mine use ~5%, regardless of whether TextEdit is or isn't frontmost, yours takes ~7%.

The big difference is when switching to/from TextEdit -- mine chugs along with barely a flicker, yours briefly spikes to ~34% then drops back down again. Your macro is also triple the load on launch -- 18% vs 6%.

Measured by eyeballing the % CPU for the Keyboard Maestro Engine process in Activity Monitor, 1 second sample time, no other KM activity, on a 3.3GHz i5 2020 iMac.

Totally anecdotal and, more importantly, we have to keep those numbers in perspective -- that's 10 concurrent macros all reacting to the same events, and even then the maximum is 1/3 of 1 core of a creaky 6-core Intel machine, and for only a fraction of a second.

You'd never notice either method under "normal use" on any Apple Silicon.

Agreed!

My assumption (and reason for implying) was definitely that using a dedicated KM pause (until) action here, with the 'Reduce CPU Usage' Enabled, would be less demanding than a 'frequent' loop ran once per second.

But I guess a loop and re-evaluation every second, in this context, is not really at all frequent, (even when running 10 of them on top of each other). Also I guess there is in actuality some form of loop running there under the hood of the Pause Until, and my prior testing have indicated that it (over the corse of a few seconds) re-evaluates its condition(s) much more frequently than every second.

So as it takes some seconds for the Reduce CPU Usage to really kick in, it really does make sense that the actual Pause every second is the gentler approach here. (Although, as you say, neither of these puts any modern mac under any significant load.)

We're dealing with a lot of unknowns here.

How does "Pause for 1 second" register that delay and check whether it's time to resume? If the Engine is running a time-stamped "future events" list that it is checking anyway, adding an entry to that then doing nothing until it bubbles to "now" is next to zero overhead during the pause period. But if it action sits there going "Is it me? Is it me? Is it me?" every millisecond it's quite a lot more!

Similarly with the "Pause Until" -- we know it conserves resources after a time, but we don't know the baseline nor what's "a little" or "a lot". What we do know is that yours includes an API call to see if TextEdit is frontmost every time they evaluate, which will be more expensive resource-wise than a simple clock check.

There has to be. Remember that, unlike the similar triggers which are fired at KM by OS events, the "Pause" conditions are state checks made by KM -- the Engine is repeatedly asking the OS "Is TextEdit frontmost?" While the frequency of checking is decreased the longer the pause is maintained (assuming "Reduce CPU" is checked), it's still usually more work than a simple pause-for-time.

1 Like