Rogue Amoeba just released Audio Hijack 4!
I've made some .ahcommand files and they work great! Is there a way of running these scripts directly from KM? I think the bit I don't understand is how to tell KM which app it's automating.
The four things I want to be able to do are:
- Toggle
Code
var sessionName = "Cans & ARC"; //Set me to the target session
var session = app.sessionWithName( sessionName )
if( session.running )
session.stop()
else
session.start()
- Start
Code
var sessionName = "Cans & ARC"; //Set me to the target session
var session = app.sessionWithName( sessionName )
session.start()
- Stop
Code
var sessionName = "Cans & ARC"; //Set me to the target session
var session = app.sessionWithName( sessionName )
session.stop()
- Determine whether the AH session is running or not (I don't have a code for this).
The codes above work when run in AH4's script window, or when saved as UTF-8 files with the extension .ahcommand and opened by AH. I'd like to be able to run them as Javascript directly from KM if possible.
1 Like
Two steps:
- Make sure that you have checked
Audio Hijack 4 > Preferences > Advanced > Allow execution of external scripts
- Run the
.ahcommand
file with a command line in a KM Execute Shell Script action.
(Audio Hijack 4 is using its own internal instance of a JSContext – like TaskPaper and the the Omni Apps – but unlike them it doesn't have any osascript
interface at all, so you can't trigger it from Script Editor or a KM Execute JavaScript for Automation action, except by running a shell process)
Assuming that SomeScript.ahcommand
is in the current directory, or that you supply the full path to it:
open -b com.rogueamoeba.audiohijack SomeScript.ahcommand
See:
Rogue Amoeba | Running Audio Hijack scripts via external triggers
1 Like
Thanks for the detailed reply.
Yes, I've already done this, and am able to run the files using an open file action. Is there any advantage to running them via a Shell Script?
Presumably, this means that I'll be unable to detect whether or not the current session is running. I could use applescript to get the value of the run button, but I was all excited to be able to control AH in the background. Darn.
Thanks again for the info.
I haven't experiment much, and some of their early JS examples look as if they may need editing, but it looks as if they have implemented a console.log, and if that's working, a KM Execute Shell Script action should be able to capture the return value (console.log string) and pass it on to a KM If_then_else.
1 Like
Crikey! I wouldn't know where to start with that. If it's not too much trouble, could you point me in the right direction?
I'll try to sit down with it and experiment a little, if no one has beaten me to it, this (EU) evening.
1 Like
Well, early days, and scope for requests to the developer, I think.
From an .ahcommand
file run at the command line with something like
open -b com.rogueamoeba.audiohijack ~/Desktop/toggleSession.ahcommand
- Standard output of the calling shell doesn't get
console.log
strings
- Standard output in the calling shell doesn't get
echo
output from app.runShellCommand
- Environment variable name bindings made by
app.runShellCommand
are not seen by the calling shell instance.
but, pending something better, we can write something to a file and then read the file contents afterwards to find out what the new session status is.
So for example, given a ~/Desktop/ToggleSession.ahcommand
with the following JavaScript contents:
ToggleSession.ahcommand.zip (838 Bytes)
Expand disclosure triangle to view JS Source
(() => {
"use strict";
const
session = app.sessionWithName(
"Safari Audio"
);
if (session.running) {
session.stop();
app.runShellCommand(
"echo 'Stopped' > ~/Desktop/sessionStatus.txt"
);
} else {
session.start();
app.runShellCommand(
"echo 'Started' > ~/Desktop/sessionStatus.txt"
);
}
console.log("OK");
})();
We can capture the updated session status to a KM variable in this kind of pattern:
Toggle named Audio Hijack 4 session and report status.kmmacros (3.3 KB)
But it's hacky, so I would ask the developer to look at the feasibility of:
- sending
console.log
output to the calling shell's standard output
- sending
app.runShellCommand
output to the calling shell's standard output.
- emulating the pattern (used by TaskPaper and the Omni apps) of providing a minimal
osascript
interface which mainly consists of an evaluateJavaScript
method for:
- passing JS source in to Audio Hijack's own JSContext for evaluation, and
- returning result strings back to
osascript
.
(The existing evaluation of .ahcommand
files at the command line mainly lacks the provision of any kind of return string)
Amazing. If it works, I don't mind it being hacky!
I've emailed support with a link to this thread.
Meanwhile, can you see anything obviously wrong with this? I've tried to adapt what you provided to use my file locations and session name, but Session Status.txt is coming up blank every time.
Toggle.ahcommand - Code
(() => {
"use strict";
const
session = app.sessionWithName(
"Cans & ARC"
);
if (session.running) {
session.stop();
app.runShellCommand(
"echo 'Stopped' > /Users/noisyneil/Documents/- MY DOCUMENTS/Keyboard Maestro Stuff/Audio Hijack Scripts/Session Status.txt"
);
} else {
session.start();
app.runShellCommand(
"echo 'Started' > /Users/noisyneil/Documents/- MY DOCUMENTS/Keyboard Maestro Stuff/Audio Hijack Scripts/Session Status.txt"
);
}
console.log("OK");
})();
Macro Screenshot
At first glance I think the issue is probably that (in the JS of the .ahcommand
) you are:
- using a file path containing gaps, but
- leaving the file path unquoted
The shell needs a way of knowing that the string beyond Documents/-
is also to be interpreted as part of a file path.
(It relies on white space to segment the parts of a command)
Experiment, for example, with adding a single quote at both start and end of the file path:
"echo 'Stopped' > '/Users/noisyneil/Documents/- MY DOCUMENTS/Keyboard Maestro Stuff/Audio Hijack Scripts/Session Status.txt'"
1 Like
Ahhhh....
I had tried double quotes, which broke it. Didn't think to try single. Once I added a pause to give the file time to write, it worked!!
Brilliant! Thankyou so much!
I'll wait to see if the devs have any thoughts on this, but even if they're not interested, this is great!
1 Like
"Double quotes within \"double quotes\" would need to be escaped"
1 Like
Just got this response from Paul at Rogue Amoeba:
"Hi Neil,
We've taken a quick look at that thread, and the sample script provided is certainly along the right track. You can extract the state from Audio Hijack and use runShellCommand() to save it to a file, then read that back where needed.
It's true, that's not elegant, but for the initial scripting implementation, it's sufficient. We're working on more for the future, though we haven't decided exactly what route to take. Better stdout/stdin support as the thread mentions is one idea. Easier ways to read/write files directly, another.
I don't know if Keyboard Maestro supports Shortcuts on MacOS 12 yet, but it's a fair bit easier there. See the attached screenshot for an example of determining session state with Shortcuts.
I hope that helps - watch for more updates over time."
3 Likes
More generally, we can control Audio Hijack 4 from Keyboard Maestro using the pattern below.
(Here, for example, switching on a named session)
2 Likes
That's really nifty! I was expecting it to be a bit slower than with pre-existing files, but it's just as fast! Nice to have it all self-contained.
1 Like