How to tell when iPod sync is complete via AppleScript - user-interface

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

Related

Why doesn't Automator AppleScript End?

OK, I realize the solution to this is probably something very simple, but I've wasted a lot of time trying to figure it out. As you'll likely be able to tell, I'm new to AppleScript.
I have an AppleScript being run by Automator. It clicks a button in Chrome. I have an action I need to repeat nearly 1000 times, so I'm trying to automate it. Here's what I have:
tell application "Google Chrome"
activate
set theTab to tab 1 of window 1
execute theTab javascript "document.querySelectorAll('[title=Archive]')[0].click()"
end tell
This works as I want: It activates Chrome and clicks a button on the active tab. Clicking the button brings up an alert box for which the default is an OK button. Next I need to click that button, so I have a second AppleScript:
tell application "Google Chrome" to activate
delay 2
tell application "System Events"
keystroke return
end tell
Let me be clear: I know ultimately I should have a single script, but I created two to diagnose the problem I'm having.
It appears the first script just never ends, so it never gets to the second script. If I run the first script, stop it, and then run the second, I get exactly what I want. But unless I stop the first script, it just churns and never moves on. While it's executing the javascript, it seems that it just stops there.
Like I said, this is probably incredibly simple... and I feel incredibly stupid for not seeing the solution. What am I missing?
It's not as easy as you might think, because alert box with the "OK" button is modal. This means: the script will wait for the "OK" button to be pressed, only then will it continue further.
I can't test, because I don't use Google Chrome, and I don't know webpage you test with. Try my suggestion yourself (it uses idea of throwing artefact interruption):
tell application "Google Chrome"
activate
set theTab to tab 1 of window 1
try
with timeout of 1 second
set theResult to (execute theTab javascript "document.querySelectorAll('[title=Archive]')[0].click()")
end timeout
theResult
on error
tell application "System Events" to keystroke return
end try
end tell
Here is fully tested by me closing modal alert box programatically:
try
with timeout of 1 second
set theResult to display alert "TEST"
end timeout
theResult
on error
tell application "System Events" to keystroke return
end try

How to quit Xcode with confirmation dialog box using apple script

I'm trying to do a script to quit Xcode with currently building application. My current script only cover to quit Xcode but I'm unable to handle the confirmation dialog box that pop-ups on the Xcode. On the confirmation box, there are two button options: Cancel or Stop Tasks. I wanted to click on Stop Tasks button. Please help.
Here's my current AppleScript so far:
set apps to {"Simulator","Xcode"}
repeat with thisApp in apps
tell application thisApp to quit
end repeat
tell application "System Events"
tell process "Xcode"
click button "Stop Tasks" of sheet 1 of window 1
end tell
end tell
This is my current applescript that didn't work.
I'm able to fix my issue regarding terminating Xcode with confirmation dialog box prompt. Here's my the applescript I've come up:
try
with timeout of 10 seconds
quit application "Simulator"
quit application "Xcode"
end timeout
on error number e
if e is -1712 then
activate application "Xcode"
tell application "System Events"
tell application process "Xcode"
keystroke return
end tell
end tell
end if
end try

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

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.

AppleScript: "set frontmost to true" does not work when the screensaver is running?

I have a shell script foo.sh which would keep running in a Terminal window. When some condition is true foo.sh would call an AppleScript bar.osa to make Thunderbird go offline. Following is the bar.osa script (my first applescript):
tell application "System Events" to tell process "Thunderbird"
set frontmost to true
tell menu bar item "File" of menu bar 1
tell menu "File"
tell menu item "Offline"
tell menu "Offline"
set v to (value of attribute "AXMenuItemMarkChar" of menu item "Work Offline") as string
if (v is not equal to "✓") then
click menu item "Work Offline"
end if
end tell
end tell
end tell
end tell
end tell
This works fine for most of the time but when the screensaver is running it does not work. Seems like set frontmost to true does not work when the screen is locked. So how can I make it work even when the screensaver is running?
I am on mavericks, and there is no way I can figure out if the screen saver is running, all I can recommend you to do, is to check the status afterwards of the frontmost property of "Thunderbird".
I have actually spent a good hour on this, and I hope that someone else comes up with a solution, that works! :)
Edit
Actually it was my bad, I thought that launching the ScreenSaver from the System Preferences Preview pane would do it.
When I run the screen saver started from a script, then the running property of it works.
tell application id "sevs" -- "System Events"
set itsRunning to false
if (running of screen saver preferences) then
set itsRunning to true
end if
end tell
if itsRunning then
tell application id "com.apple.ScreenSaver.Engine" to quit
end if
So the solution I propose, is to check if frontmost is true after you have set it frontmost, if the screen saver is running, then turn off the screen saver (requires that you have no password on the screen saver, then rerun the code that sets your app frontmost, and then finally launches the screen saver again.
try
tell application id "com.apple.ScreenSaver.Engine" to launch
end try
You can make this to work in a repeat loop, of course you don't have to use a repeat loop.
Edit+ I was really tired last night: you can really just start out by testing if the screensaver is running, and then either drop going forward, or turn the screen saver off, do your stuff, and turn it on again.

AppleScript works in Script Editor but not as application

I am pretty new to programming, especially with AppleScript. I wrote a simple script for Valentine's Day to play a song from iTunes and then open a flash animation file in Safari. When I run the script in ScriptEditor, everything works as desired, but when I export as a standalone application, it fails at the command to enable full-screen mode. I am assuming it is an issue with System Events. To be clear, the application functions to the end, but at the keystroke command I hear an alert sound and the window remains as-is.
I am running Yosemite, and am fully updated.
Ideally, I would like to open the file in Google Chrome to utilize Presentation Mode, but I can't even get Chrome to open the file.
Thanks for any advice! Here is the code:
tell application "Finder"
set visible of every process whose visible is true and name is not "Finder" to false
close every window
end tell
set volume output volume 75
tell application "iTunes"
set currentVolume to sound volume
if player state is playing then
stop
back track
end if
play track "The Promise"
set player position to 6
end tell
delay 4
tell application "Safari"
activate
if (count of windows) is 0 then -- Remove "if" statement if you don't want to make a new window if there is none
make new window at front
end if
open (POSIX path of (path to home folder)) & "/Desktop/beMine/beMine.swf"
tell application "System Events"
tell process "Safari" to keystroke "f" using {command down, control down}
end tell
end tell
I agree with Jerry Stratton's comment that it could be an accessibility issue. However it also could be that you are issuing the keystroke command before Safari is ready to accept it. If it's opening a file then it could be busy and miss the keystroke command.
Also, I would move the system events code outside the Safari code and also just tell system events, rather than the Safari process, to perform the keystroke command. Try this as the Safari and System Events parts.
NOTE: I can't get Chrome to open a file either.
tell application "Safari"
activate
if (count of windows) is 0 then -- Remove "if" statement if you don't want to make a new window if there is none
make new window at front
end if
open (POSIX path of (path to home folder)) & "/Desktop/beMine/beMine.swf"
end tell
tell application "Safari" to activate
delay 1
tell application "System Events"
keystroke "f" using {command down, control down}
end tell
Most likely you’ll need to allow your standalone application to use System Events. At some point you needed to do that for Script Editor; you’ll need to do the same for your standalone app.
You’ll find the option in System Preferences under Security & Privacy, then Privacy, and then Accessibility. There’ll be a list of apps, and your app is probably listed there without a check for “Allow the apps below to control your computer.”
You may need to use the “+” button to add your app to the list.
I have verified that I can use this simple script to make Safari full-screen; it will work if the app is given permission under Accessibility, and it will silently fail if not.
tell application "Safari"
activate
end tell
tell application "System Events"
tell process "Safari" to keystroke "f" using {command down, control down}
end tell
This is Yosemite, Mac OS X 10.10; it may be different in other versions of Mac OS X.

Resources