I’ve been seeing this for a few weeks on my macOS Tahoe laptop, but I thought nothing of it for being a pre-release OS until this morning I updated BTT to the most recent version on my macOS Sequoia workstation and started seeing the same symptom.
I have been running with my own tuned screen reader Real JavaScript for ages, which I have embedded bellow. Normally, I can fire these scripts off in rapid succession without issue, but then at some unpredictable point BTT turns non-responsive when I try to fire off this script - my TTS never starts, mouse clicks become unreliable (and my trackpad stops ticking back), and I cannot trigger any other BTT automation.
Since I run BTT headless, I have to use Activity Monitor to kill off the red task, at which point my mouse pointer jumps to where it was when the lockup started and begins to click normally again. From here, I can manually start BTT from spotlight. Since this began biting on my workstation, I found that killall -KILL BetterTouchTool is a better solution - BTT automagically restarts itself this way.
For troubleshooting purposes, is there a way to determine which version of BTT I upgraded from?
My screen reader script follows. While I don’t have the proof, my gut says this is likely unrelated to my symptom, but I’m including it on this report for completeness.
(async ()=> {
// Preserve original clipboard content as a workaround - get_selection() sometimes replaces clipboard content
let originalClipboard = await get_clipboard_content();
let selectedText = await get_selection({ format: 'NSPasteboardTypeString' });
// Restore original clipboard content only if it was valid text
if (typeof originalClipboard === 'string' && originalClipboard.length > 0) {
await set_clipboard_content(originalClipboard);
}
const escapedSelectedText = selectedText
.replace(/\\n/g, ' ') // don't verbalize "new line" characters
.replace(/'/g, "'\\''") // we use quotes when dispatching our shell command
.replace(/\$/g, '\\$') // dollar signs create chaos
.replace(/\`/g, ' ') // we use ticks in our command as well
.replace(/-/g, '...') // for some reason a hyphen beaks things
.replace(/â\(TM\)/g, '\'') // stupid slashdot
.replace(/</g, '') // < also breaks things
// some pronouncification tuning
.replace(/feat/g, 'feet') // for some reason, TTS says "featuring" every time
.replace(/mW/g, 'milliwatts') // not megawatts!
.replace(/\[\d+\]/g, '') // wikipedia references [99]
// determine if we are on tahoe or sequoia and set appropriate text speed
const majorOSVersion = await runShellScript({
script: "sw_vers -productVersion | awk -F. '{print $1}'"
});
let textSpeed = 250;
if (majorOSVersion > 15) {
textSpeed = 400;
}
// put the shell script into a string (single backticks are great for multiline strings)
const sayResult = await runShellScript({
script: `killall say; say '${escapedSelectedText}' -r ${textSpeed}`
});
returnToBTT(sayResult)
})();