GUI Scripting
Can't Believe I'm Posting About GUI Scripting
It is a fact universally acknowledged—in my house—that GUI Scripting stinks. But the flip side of that is that sometimes it can be the only way to automate something with AppleScript. Especially so if the developers of the app you are 'scripting have long been ignoring your suggestions. Again, my house.
GUI Scripting is a way to write AppleScript that works by simulating mouse clicks, selections, key presses and other "touches" of the GUI elements of an app in order to get the app to do what those clicks and presses do. For instance, you can simulate a mouseclick on a menu item in a menu and whatever happens when you usually click that menu item will happen. GUI Scripting is clunky to work with for a number of reasons, but the two most discouraging are that it's tough to know what and how and where to click and press for the Thing you want to do; and that if the developer changes an app's layout in the future the scripts could break because something isn't where it was before.
Despite all that, I've been playing with GUI Scripting lately. It's what I use to change playlist views in Playlist Manager and how Needle Drop clicks the "Clear" button in the Playing Next panel. If you've used those scripts, you've had to give permission in "Accessibility" to allow those scripts to use the "System Events" app. System Events is what enables AppleScript to target GUI elements.
Here's a little scripting project that uses some GUI Scripting to do three things that I like to do somewhat regularly in the Music app: open the selected playlist in its own window; change the playlist View to "as Songs"; reposition the playlist window to a standard place, rather than BANG right over the main browser window. (Note that I could only get it to work on the latest version of Big Sur with the latest version of Music, which bears out my thoughts above about clunkiness.)
Updated Mono-Stereo Toggling
Apple changed a few things in System Preferences under Mojave which broke this script to toggle between Mono and Stereo output.
Here is the fix. You will note that it is a simple change to the line targeting the System Preferences' Accessibility window.
tell application "System Preferences"
reveal anchor "Hearing" of pane id "com.apple.preference.universalaccess"
end tell
tell application "System Events"
tell application process "System Preferences"
set frontmost to true
tell group 1 of window "Accessibility"
# pre-Mojave - replace the line above with the one below
# tell window "Accessibility"
set monoStereoCheckbox to checkbox "Play stereo audio as mono"
if (get value of monoStereoCheckbox) as boolean is true then
set ddMessage to "Switch to STEREO output?"
else
set ddMessage to "Switch to MONO output?"
end if
if button returned of (display dialog ddMessage buttons {"No", "Yes"} default button 2) is "Yes" then
tell monoStereoCheckbox to click
end if
end tell
end tell
end tell
if application "System Preferences" is running then
tell application "System Preferences" to quit
end if
For more details, read the original post.
Toggle Stereo/Mono Audio Output
Correspondent Simon Crosbie has set up an amp and pair of speakers in his workshop which is connected to an Airport Express. Unfortunately, the speakers are some distance apart, so that he may be near one speaker or another at any time, and will only hear that channel's output. Simon wanted to know if there's a way to toggle between stereo and mono output so he can hear more than just half of a stereo recording.
Yes, there is a way. Go to System Preferences > Accessibility. Choose "Audio" in the left-hand list and in the panel that appears click the checkbox next to "Play stereo audio as mono".
Goodnight everybody!
Wait a minute. I almost forgot I wrote this script to do it:
tell application "System Preferences"
reveal anchor "Hearing" of pane id "com.apple.preference.universalaccess"
end tell
tell application "System Events"
tell application process "System Preferences"
set frontmost to true
tell window "Accessibility"
##--> pre 10.9 set monoStereoCheckbox to checkbox 2 of group 1
set monoStereoCheckbox to checkbox "Play stereo audio as mono"
if (get value of monoStereoCheckbox) as boolean is true then
set ddMessage to "Switch to STEREO output?"
else
set ddMessage to "Switch to MONO output?"
end if
if button returned of (display dialog ddMessage buttons {"No", "Yes"} default button 2) is "Yes" then
tell monoStereoCheckbox to click
end if
end tell
end tell
end tell
if application "System Preferences" is running then
tell application "System Preferences" to quit
end if
[UPDATE November 13, 2013: The original script has been updated for Mavericks. Note the commented line for pre-10.9 systems and the line that follows it. Set the monoStereoCheckbox variable using one or the other depending on the OS.]
[UPDATE October 17, 2014: Another change for compatibility with Yosemite. The line "set frontmost to true" is inserted right after the first tell application process "System Preferences" line near the beginning.]
I would save this script in the system wide Scripts menu (install it in ~/Library/Scripts/). Because the script uses (gulp) GUI scripting you must make sure that "Enable access for assitive devices" is checked in the Accessibility System Preferences panel.
Smarties among you can figure out how to switch mono/stereo when using AppleScript to change AirPlay speakers.
And bear in mind that while the script works with the current OS (and probably an OS that may be released this Fall), Apple may change the layout of the System Preferences panels in a future update, in which case the GUI scripting will have to be updated.
[UPDATE December 28, 2018: Mojave made some changes and the updated version of the script can be seen here.
I Hate GUI Scripting Except When I Don't
Sometimes the only way to script anything that isn't explicitly in an app's scripting definition is to use GUI Scripting. I always look for some other way before resorting to GUI Scripting since it can get pretty oogly and is dependent on the app's GUI; if the developer changes the GUI then the script can be rendered useless. With that said, a Correspondent writes:
"In iTunes, I utilize checkboxes to determine what songs are synced to my iPhone. I do not utilize playlists because I want to keep complete playlists in my iTunes library while still syncing them to my iPhone, minus any unchecked songs. The problem is that iTunes will not play unchecked songs continuously, which annoys me. I recently discovered, however, a preference called "Show list checkboxes". Unchecking this will hide the checkboxes column and allow me to play my songs uninterrupted, but when I want to sync my iPhone I have to show the checkboxes again so that it won't try to sync my entire huge library.
I was wondering if there was any way that you could create a script that toggles this preference on & off, in order to reduce the number of clicks required to switch between playing all of my music and syncing my iPhone. This would be much appreciated."
There's no explicit command to toggle this behavior, but this bit of GUI Scripting'll do it:
tell application "iTunes" to activate
tell application "System Events"
tell process "iTunes"
click menu item 3 of menu 2 of menu bar 1
click button 1 of UI element 5 of window 1
click UI element 25 of group 1 of window 1
click UI element 1 of window 1
end tell
end tell
You must have set up GUI Scripting using the instructions found here. And be warned that if the Preferences panel of iTunes changes in the future this script may no longer work.
As usual, works best with a keyboard shortcut.