KM's excellent GUI provides the best way to do most things, but if, in particular cases, you need to change the options settings of an action at run-time, you can do that by calling the action from a script.
Application("Keyboard Maestro Engine").doScript(strXML)
can directly execute the XML string for a particular action, and you can:
- Find the XML you need by saving a macro and inspecting the .kmMacros or .kmActions file
- Adjust the options in the XML before calling the
kme.doScript(strXML)
(or Applescriptdo script strXML
Here is an example which simply calls the 'Speak Text' action once for each voice available on the system, varying the text spoken and the speed, as well as the voice that is used.
Listen to all installed system voices.kmmacros (6.6 KB)
// EXECUTING KEYBOARD MAESTRO ACTIONS FROM SCRIPTS,
// WITH RUN-TIME ADJUSTMENTS TO THEIR OPTIONS.
// READING OUT MESSAGES IN THE FULL SET OF SYSTEM VOICES
// AT RANDOMLY VARYING SPEEDS
(function () {
"use strict";
// Rob Trew Twitter @ComplexPoint MIT License 2015
// Ver 0.1
ObjC.import('AppKit');
var jsoDoScript = function (g) {
var h = /&/g,
k = /</g,
l = />/g,
d = {
array: function (a) {
return a.length ? "<array>" + a.reduce(function (a, e) {
return a + d[typeof e](e)
}, "") + "</array>" : "<array/>"
},
"boolean": function (a) {
return a ? "<true/>" : "<false/>"
},
dict: function (a) {
var b = Object.keys(a);
return "<dict>" + (b.sort() && b).reduce(function (b, f) {
var c = a[f];
return b + "<key>" + f + "</key>" + d[typeof c](c)
}, "") + "</dict>"
},
number: function (a) {
return "<real>" + (a ? a : "0.0") + "</real>"
},
object: function (a) {
return d[a instanceof Array ? "array" : "dict"](a)
},
string: function (a) {
return "<string>" + a.replace(h, "&").replace(k, "<").replace(l,
">") + "</string>"
}
},
m = function (a) {
var b = typeof a;
return "object" === b ? a instanceof Array ? "array" : "dict" : b
},
c = function (a) {
var b = a ? m(a) : "";
return b && "dict" === b ? a.MacroActionType ? [a] : a.Actions || c(a.Macros) :
"array" === b ? a.reduce(function (a, b) {
return a.concat(c(b))
}, []) : []
},
n = Application("Keyboard Maestro Engine");
// EXECUTE EACH XML SNIPPET WITH THE KEYBOARD MAESTRO ENGINE
// kme.doScript(strActionXML)
return c(g).reduce(function (a, b) {
var c = d.dict(b);
return n.doScript(c), a.push(c), a
}, [])
},
a = Application.currentApplication(),
sa = (a.includeStandardAdditions = true && a),
rgxSample = /\s+\w{2}[_-]\w{2,}\s+\#\s/,
dctSpeeches = sa.doShellScript(
"say -v '?'"
).split(/[\n\r]+/).reduce(
function (dct, strLine) {
var lst = strLine.split(rgxSample);
dct[lst[0]] = lst[1];
return dct;
}, {}
),
lstVoices = ObjC.deepUnwrap($.NSSpeechSynthesizer.availableVoices),
lstLCVoices = lstVoices.map(function (v) {
return v.toLowerCase();
}),
voiceID = function (v) {
var l = v.toLowerCase(),
sl = "com.apple.speech.synthesis.voice." + l,
i = lstLCVoices.indexOf(sl),
j = (i === -1) ? lstLCVoices.indexOf(sl + '.premium') : i;
return lstVoices[j] || '';
},
lstRates = 'Default Moderate Normal Quick Fast'.split(' '),
lngRates = lstRates.length,
kmSpeak = {
"MacroActionType": "SpeakText",
"Rate": "Quick",
"Text": "Hello world !",
"Voice": ""
},
/************************* MAIN ******************************/
strVoiceList = Object.keys(dctSpeeches).reduce(
function (strList, strVoice, i) {
var strText = dctSpeeches[strVoice],
strVoiceID = voiceID(strVoice);
// MODIFY THE PARAMETERS OF THE KM SAY ACTION
kmSpeak.Voice = voiceID(strVoice);
kmSpeak.Text = strText;
kmSpeak.Rate = lstRates[Math.floor(
Math.random() * lngRates
)];
// CONVERT JS OBJECT TO .kmActions XML AND EXECUTE
jsoDoScript(kmSpeak);
return strList + strVoice + '\t' + strVoiceID + '\t' + strText + '\n';
}, ''
);
sa.setTheClipboardTo(strVoiceList);
// EXECUTE A FINAL SERIES OF KEYBOARD MAESTRO ACTIONS,
// WITH OR WITHOUT RUN-TIME ADJUSTMENTS TO THEIR OPTIONS
// KM 'Play Sound' action
jsoDoScript({
"Volume": 80,
"MacroActionType": "PlaySound",
"Path": "/System/Library/Sounds/Glass.aiff",
"DeviceID": "SOUNDEFFECTS"
});
// KM 'Speak Text' action
kmSpeak.Voice = ''; // Finally, at default voice and speed ...
kmSpeak.Rate = '';
kmSpeak.Text =
"A complete list of voices, with identifiers and text samples, is now in the clipboard";
jsoDoScript(kmSpeak);
// KM 'Notification' action
jsoDoScript({
"MacroActionType": "Notification",
"Title": "Voice list",
"Subtitle": "Now in clipboard",
"Text": "A complete list of system voices is now in the clipboard"
});
return strVoiceList;
})();