Cancel doesn't cancel

I’ve been scripting for a while, and I’m accustomed to scripts stopping in their tracks when the user clicks a “Cancel” button in a dialog or being able to use “tell me to quit” to stop a script elsewhere. I’m surprised I haven’t run into the problem I’m having now with other, more complicated scripts.

I am combining Doug Adams’ “Just Play This One” and “This is the Last Song” scripts for iTunes. (JPTO didn’t allow me to quit it from the Dock and stopped a song if it was already playing. TITLS didn’t work if iTunes wasn’t already playing.)

TITLS begins by checking to see if iTunes is running. But if it’s not, the script plunges ahead and runs into an error.

on run
	tell application "System Events"
		if (get name of every process) does not contain "iTunes" then
			display dialog "iTunes is not running." buttons {"Cancel"} default button 1 giving up after 10 with icon 0
		end if
	end tell
	get_fin()
end run

Clicking the Cancel button doesn’t stop it; letting it time out doesn’t stop it; adding

if gave up of (display dialog...) is true then tell me to quit

didn’t help. While searching the BBS I found the recommendation to “use error number -128” instead of “tell me to quit.” That didn’t work.

It runs into an error because it skips the get_fin() subroutine and enters idle(). But I don’t want it to idle, I want it to quit. Why doesn’t “tell me to quit” work?

Thank you!

‘Error number -128’ is a signal not to execute any more instructions after that point. ‘Tell me to quit’ tells the process running the script to quit, which it does only after it’s finished what it’s doing - ie. running the script.

In a stay-open script, the idle handler seems to be independent of the rest of the script. If you type ‘error number -128’ in the run handler, the rest of the ‘run’ script doesn’t execute, but the application itself - being stay-open - doesn’t quit. Presumably it then immediately gets its first prompt from the OS to execute the idle handler. If you type in ‘quit’ instead, the application runs the rest of the script and then quits before it can be told to execute the idle handler.

What you want to do can be achieved by using both commands - though obviously they have to be in the right order:

on run
  tell application "System Events" to set washout to (not (exists process "iTunes"))
  if washout then
    try
      -- An error trap's needed in case the "Cancel" button's clicked,
      -- which would stop the following 'quit' command from being executed.
      display dialog "iTunes is not running." buttons {"Cancel"} default button 1 giving up after 10 with icon 0
    end try
    quit -- quit when you've stopped running the script
    error number -128 -- stop running the script
  end if
  get_fin()
end run

on get_fin()
  beep
end get_fin

on idle
  beep 2
end idle

Well that’s annoying, but it works! I guess this is because each subroutine is a script unto itself as far as AS is concerned.

Well, thanks.
Cheers