How to close / cancel a pop-up modal / dialog window in Applescript - macos

I'm trying to fix a particular problem in this Applescript I made: https://gist.github.com/jwmann/08daed8a905cfbf4ff96
Context:
It's an Applescript where you select a song in a VLC playlist, run the Applescript and it will trash the song from the original location.
The Problem:
The problem occurs when a user attempts to delete a currently playing, single song where the VLC playlist is the size of just the single song.
Now VLC will explode if you try to delete a song that it's currently playing. To workaround this I've made the script stop VLC from playing and trying again to delete it.
Now if this workaround happens, VLC will no longer be playing. In a multi-song playlist, this can't be annoying. So the script will continue playing VLC at the end of the script. However, after deleting the song from a single song playlist, it will remove the song from the playlist, leaving no songs and therefore no playlist.
So when the script tries to play, it'll open a new window / dialog / modal to allow the user to find something to play. This is something I don't want to happen.
What I'm trying to do:
I need a way to:
Detect the correct Window
Tell that window to Close
Information I've gathered:
This is the window I'm trying to Cancel
This is the data that Accessibility Inspector shows me about the window.
<AXApplication: “VLC”>
<AXWindow: “Open Source”>
Attributes:
AXFocused: “0”
AXFullScreen: “0”
AXTitle: “Open Source”
AXPosition (W): “x=993 y=276”
AXGrowArea: “(null)”
AXMinimizeButton: “(null)”
AXDocument: “(null)”
AXSections (W): “<array of size 1>”
AXCloseButton: “(null)”
AXMain: “0”
AXFullScreenButton: “(null)”
AXProxy: “(null)”
AXDefaultButton: “<AXButton: “Open”>”
AXMinimized: “0”
AXChildren: “<array of size 8>”
AXRole: “AXWindow”
AXParent: “<AXApplication: “VLC”>”
AXTitleUIElement: “<AXStaticText>”
AXCancelButton: “<AXButton: “Cancel”>”
AXModal: “1”
AXSubrole: “AXDialog”
AXZoomButton: “(null)”
AXRoleDescription: “dialog”
AXSize: “w=574 h=402”
AXToolbarButton: “(null)”
AXFrame: “x=993 y=276 w=574 h=402”
AXIdentifier: “_NS:40”
Actions:
AXRaise - raise
Things I've tried:
tell application "System Events"
close window "Open Source" of application "VLC"
end tell
tell application "System Events"
click button "Cancel" of window "Open Source" of application "VLC"
end tell
tell application "System Events"
cancel window "Open Source" of application "VLC"
end tell
tell application "System Events" to tell (window 1 of application "VLC" whose subrole is "AXDialog") to close
In every example, System Events or VLC (I tried both) can't seem to find the window "Open Source" even though it's clearly called "Open Source" in the inspector. It's not a sheet, it's a window. I don't understand why I can't find this window.

Thanks to #l'L'l for recommending me Script Debugger 5, it allowed to view the data of the windows in a readable way and even provide code on calling specific elements.
How I found out was I ran this code:
tell application "VLC" to activate
tell application "System Events"
tell process "VLC"
set myUI to every UI element
end tell
end tell
The reason being is that even though I knew the window's name, Applescript couldn't ever find it, so I needed a way to see everything.
Within that, I found this:
If you look at the metadata of this window, you'll see that it's SUPER broken.
No wonder Applescript could never find it, it's barely a window.
From that list, it provides the exact code to reference parts of the window, including, the "Cancel" button.
This is the code that cancels my window:
tell application "System Events"
tell its application process "VLC"
tell its window "Open Source"
click button "Cancel"
end tell
end tell
end tell
So searching every UI Element was definitely useful and Script Debugger 5 definitely helped.

Related

AppleScript plays playlist in Music.app on macOS Monterey

I'm working on this Alfred Workflow: https://github.com/gustavosaez/Alfred-Workflow-Apple-Music-Playlist
And today I'm looking for a day to "automate" the play music in background or hidden (to avoid open the application and click PLAY).
I found a way to set the mouse click on a screen position (specific on the play button), but it works only if the app is visible and if the resolution of screen is the same of mine.
I search about UI Elements for Music.app and didn't find anything.
The problem is:
When Alfred opens the chosen link, Music.app take a few seconds to open and load the playlist selected;
After this, space/play command is inactive, so I think to create a script that gets the current page and play the playlist in shuffle mode.
Any idea?
some ideas:
tell application "Music"
-- tell application "System Events" to tell process "Music" to click at {620, 374}
play current playlist
end tell
|
tell application "Music"
-- tell application "System Events" to tell process "Music" to click at {620, 374}
play {workflowPlaylistName}
end tell
tell application "System Events"
keystroke "h" using command down
end tell
I'm confused why you are trying to use mouse clicks or keystrokes, instead of just using
tell application "Music"
play
end tell
or
tell application "Music"
play the playlist named "{query}"
end tell
and pass the name of the playlist as query

How to close a floating window using AppleScript?

One of my application processes occasionally creates a floating window that I'd like to programmatically auto-close.
I have no problem checking for the existence of this window through its name, but then I am unable to close it with neither close window "windowname" nor tell window "windowname" to close.
E.g.:
tell application "System Events" to tell process "processname"
if exists window "windowname" then
close window "windowname"
end if
end tell
This result in:
error "System Events got an error: window "windowname" of process "processname" doesn’t understand the “close” message."
How can I close this window, then?
I can close a Finder window like this. Maybe you can do the same.
tell application "System Events"
tell process "Finder"
click button 1 of window 1
end tell
end tell
If "Command-W" closes the floating window, which it usually does, this will work:
tell application "System Events"
if exists window "<window name>" of process "<application name>" then
keystroke "w" using command down
end if
end tell
You can also use Automator instead of AppleScript proper to do this. Record yourself clicking the close button.
When I do this, Automator records the action as, I kid you not, Click the "<fill in title>" button.

How to tell when iPod sync is complete via AppleScript

I am trying to make an AppleScript that will sync and eject my iPod without me having to provide any input after the script starts. The basic script is:
set ipodList to {}
tell application "iTunes"
try
set ipodList to (name of every source whose kind is iPod)
end try
repeat with ipodName in ipodList
update ipodName
eject ipodName
end repeat
end tell
The problem with this script is that it causes iTunes to immediately try to eject the iPod after the sync'ing begins, so the sync'ing is not finished yet. This causes sometimes one and sometimes two dialog windows to appear. One window says that "iTunes is syncing the iPod. Are you sure you want to eject it?" and has two buttons, "Cancel" and "Eject." The other window says "The iPod “nanoBot” cannot be ejected because it contains files that are in use by another application." and has only an "OK" button. Just clicking "Eject" and "OK" causes iTunes to finish sync'ing the iPod and then to eject it.
I would like to use UI scripting to click these two buttons so that iTunes will do what I want. In fact, the following script seems to do what I want:
tell application "System Events"
tell process "iTunes"
try
click button "Eject" of window 1
end try
try
click button "OK" of window 1
end try
end tell
end tell
However, I tested that second bit of code by running it from a second AppleScript. The first AppleScript's execution hangs on the eject command until I click through the two dialogs (if only it hung on the update command, all of this annoyance would be solved...).
Is there any way to click through the dialogs in the same script as the eject command? Or some way of launching a second Applescript from the first and having it keep checking for these dialog windows to come up and then click through them? Or is there just some simpler solution to this problem?
[Edit: I should add that what I currently do is just sync the iPod with the update command, pause for a few seconds, and then eject the iPod with Finder (I have it set up as a disk drive). The problem with this method is that there is no way to tell when the sync'ing is complete and if it is not then the script does not eject the iPod and raises an error.]
Try this ...
set ipodList to {}
tell application "iTunes"
try
set ipodList to (name of every source whose kind is iPod)
end try
repeat with ipodName in ipodList
update ipodName
tell me to wait_for_sync()
eject ipodName
end repeat
end tell
on wait_for_sync()
tell application "System Events" to tell application process "iTunes"
set theStatusText to ""
repeat until theStatusText is "iPod sync is complete."
set theStatusText to value of static text 1 of scroll area 1 of window "iTunes"
delay 1
end repeat
end tell
end wait_for_sync

How to reload a Safari Extension from the command line?

I need to "Reload" a Safari extension from the command line (and also build the package later).
How can this be done?
Why?
I'd like to build in one step - my code is in CoffeeScript and thus I'm compiling it anyway.
What have I tried?
Apart from googling hopelessly I tried using this AppleScript:
tell application "System Events"
tell process "Safari"
click the button "Reload" of window "Extension Builder"
end tell
end tell
Which errors out with:
System Events got an error: Can’t get button "Reload" of window "Extension Builder" of process "Safari".
And this variation:
tell application "System Events"
tell process "Safari"
tell button "Reload" of window "Extension Builder" to perform action
end tell
end tell
Which doesn't give an error but also doesn't actually do anything.
It may be that the button isn't "named" as you expect. Check out UI Browser in order to view an application's interface hierarchy for use with GUI scripting.
The "Reload" button is accessible with:
click button "Reload" of UI element "ReloadUninstall[NAME OF EXTENSION HERE]" \
of UI element 1 of scroll area 1 of window "Extension Builder"
Extension Browser's view hierarchy seems to have changed since the accepted answer was written. This script works for me:
tell application "System Events"
tell process "Safari"
click button "Reload" of UI element 0 of window "Extension Builder"
end tell
end tell
Note that Safari and the Extension Builder window need to be open for this to work

AppleScript: How do I launch an application and then execute a menu command

I am trying to create a small applescript which will launch the DVD Player application and then resize it to its Actual Size. The code is listed below. When I run the code the DVD Player launches but it does not resize the window. What am I missing to get this to work?
Thanks,
Rob
do_menu("DVD Player", "View", "Actual Size")
on do_menu(app_name, menu_name, menu_item)
try
-- bring the target application to the front
tell application app_name
activate
end tell
delay 3
tell application "System Events"
tell process app_name
tell menu bar 1
tell menu bar item menu_name
tell menu menu_name
click menu item menu_item
end tell
end tell
end tell
end tell
end tell
return true
on error error_message
return false
end try
end do_menu
Have you looked at the dictionary for DVD Player?
There are properties for adjusting the size.
This will open it and go full screen:
tell application "DVD Player"
open
delay 2
set viewer full screen to true
end tell
Or there is the viewer size property which states:
viewer size (half/normal/double/max) : To set the the viewer size
So you could use this to go to Actual Size:
tell application "DVD Player"
open
delay 2
set viewer size to normal
end tell
Is that what you wanted to do?
I'm not in front of a Mac so I can't really test your code, but my suggestion is to try an existing and proven implementation of the same functionality, which uses recursion rather than nesting:
http://hints.macworld.com/article.php?story=20060921045743404
It's also possible that your delay 3 is not long enough for the DVD Player application to completely load before you start trying to script menu events. You could try debugging this by running two separate scripts and see if your menu-activation code works once the DVD Player app is loaded.

Resources