I have an alarm clock script that I built with a timer to make sure it doesn’t run all day. Unfortunately, once it’s done raising the volume for me, the script quits running instead of monitoring the time so it knows when to stop the music. I’m certain the problem lies in my understanding of the Idle handler, but I just can’t figure the problem out.
If anyone could proof my script for me, I’d really appreciate it.
dennis
p.s. The script is saved as ‘Stay Open,’ by the way.
-- Defining the common variables
--Time to wait for volume increases and snooze
property time_delay : 7
--how hot we'll eventually make iTunes volume
property dial_up : 80
property volume_dial : 0
--Our playlist full of wake-up music
property the_list : "Wake-Up Time"
property current_time : date
property start_time : date
--These settings capture the current volume of the system and iTunes and preps both to launch the alarm
on run
-- time delay for de-bugging
--delay 70
get volume settings
set old_volume to output volume of result
set volume_dial to 0 as number
set volume output volume 50
-- This tells us what time our script started running
set start_time to current date
-- Here, the alarm goes in to action.
my alarm_set()
end run
on alarm_set()
--This wakes up the display if it is asleep
(*tell application "System Events"
keystroke " "
end tell*)
--This section deals specifically with iTunes. Getting it in a 'ready' state.
tell application "iTunes"
stop
launch
set old_tunes_volume to sound volume of application "iTunes"
set sound volume of application "iTunes" to volume_dial
--This deletes all the tracks of the smart playlist 'Wake-Up Time' in order to make sure the playlist is fresh.
delete every track of playlist the_list
try
set visuals enabled to true
end try
--Let's get cracking!
delay 2
play track 1 of playlist the_list
end tell
idle
end alarm_set
on idle
-- Here, we perform the routine checks to determine what part of the script needs to take place
delay time_delay
tell application "iTunes"
-- This tells us what time it is right now so we know how long it's been running
set current_time to current date
--Let's wake someone up!
if volume_dial < dial_up then
my alarm_volume()
end if
--Did someone wake up and pause iTunes?
if player state ≠playing and volume_dial ≠0 then
my alarm_snooze()
end if
-- If the script has been running for 50 minutes, stop and return the system to a pre-launch state
if start_time + 50 * minutes ≤ current_time then
my alarm_stop()
end if
end tell
end idle
on alarm_volume()
-- Increase the volume at a slow and steady pace
tell application "iTunes"
set sound volume of application "iTunes" to volume_dial
set volume_dial to volume_dial + 1 as number
end tell
idle
end alarm_volume
on alarm_snooze()
-- If iTunes has been paused, don't do anything for a brief moment, then get going again. Snooze in other words.
tell application "iTunes"
if player state ≠playing then
delay (time_delay * 120)
play (next track)
end if
end tell
idle
end alarm_snooze
on alarm_stop()
--All the actions necessary to stop the script and re-set the settings to a pre-run state
tell application "iTunes"
stop
set volume output volume old_volume
set sound volume of application "iTunes" to old_tunes_volume
error number -128
end tell
end alarm_stop
An ‘idle’ handler is normally executed (in a running, stay-open script) immediately after the ‘run’ handler finishes. Thereafter, the script just sits there doing nothing until it gets a message from the operating system to execute the ‘idle’ handler again. The ‘idle’ handler itself must return a value which tells the system how long to wait before signalling the script to execute the handler again.
-- Any property declarations here.
on run
-- Do any preparatory work here.
end run
on idle
-- Do the periodical stuff here.
return time_delay -- Number of seconds to the next call of the 'idle' handler.
end idle
Thanks for the reply, Nigel. I touched up my script to reflect what I believed to be what you were telling me, but the script still quits after it has fulfilled its task of raising the volume instead of continuing to run and check the time. It’s driving me nuts! What am I missing?
dennis
-- Defining the common variables
--Time to wait for volume increases and snooze
property time_delay : 7
--how hot we'll eventually make iTunes volume
property dial_up : 80
property volume_dial : 0
--Our playlist full of wake-up music
property the_list : "Wake-Up Time"
property current_time : date
property start_time : date
--These settings capture the current volume of the system and iTunes and preps both to launch the alarm
on run
-- time delay for de-bugging
--delay 70
get volume settings
set old_volume to output volume of result
set volume_dial to 0 as number
set volume output volume 50
-- This tells us what time our script started running
set start_time to current date
-- Here, the alarm goes in to action.
my alarm_set()
end run
on idle
-- Here, we perform the routine checks to determine what part of the script needs to take place
return time_delay
tell application "iTunes"
-- This tells us what time it is right now so we know how long it's been running
set current_time to current date
--Let's wake someone up!
if volume_dial < dial_up then
my alarm_volume()
end if
--Did someone wake up and pause iTunes?
if player state ≠playing and volume_dial ≠0 then
my alarm_snooze()
end if
-- If the script has been running for 50 minutes, stop and return the system to a pre-launch state
if start_time + 50 * minutes ≤ current_time then
my alarm_stop()
end if
end tell
end idle
on alarm_set()
--This wakes up the display if it is asleep
(*tell application "System Events"
keystroke " "
end tell*)
--This section deals specifically with iTunes. Getting it in a 'ready' state.
tell application "iTunes"
stop
launch
set old_tunes_volume to sound volume of application "iTunes"
set sound volume of application "iTunes" to volume_dial
try
set visuals enabled to true
end try
--Let's get cracking!
delay 2
play track 1 of playlist the_list
end tell
--idle
end alarm_set
on alarm_volume()
-- Increase the volume at a slow and steady pace
tell application "iTunes"
set sound volume of application "iTunes" to volume_dial
set volume_dial to volume_dial + 1 as number
end tell
--idle
end alarm_volume
on alarm_snooze()
-- If iTunes has been paused, don't do anything for a brief moment, then get going again. Snooze in other words.
tell application "iTunes"
if player state ≠playing then
delay (time_delay * 120)
play (next track)
end if
end tell
--idle
end alarm_snooze
on alarm_stop()
--All the actions necessary to stop the script and re-set the settings to a pre-run state
tell application "iTunes"
stop
set volume output volume old_volume
set sound volume of application "iTunes" to old_tunes_volume
error number -128
end tell
end alarm_stop
I moved the line ‘return time_delay’ to the end of the Idle handler, plus I commented out the references to ‘idle’ at the end of all the other Idle handlers (because it should return to Idle on its own, yes?) and now the script runs through once and quits instead of behaving as it did prior and running until the volume had been suficiently increased.
Now I’m really confused…
dennis
-- Defining the common variables
--Time to wait for volume increases and snooze
property time_delay : 7
--how hot we'll eventually make iTunes volume
property dial_up : 80
property volume_dial : 0
--Our playlist full of wake-up music
property the_list : "Wake-Up Time"
property current_time : date
property start_time : date
--These settings capture the current volume of the system and iTunes and preps both to launch the alarm
on run
-- time delay for de-bugging
--delay 70
get volume settings
set old_volume to output volume of result
set volume_dial to 0 as number
set volume output volume 50
-- This tells us what time our script started running
set start_time to current date
-- Here, the alarm goes in to action.
my alarm_set()
end run
on alarm_set()
--This wakes up the display if it is asleep
(*tell application "System Events"
keystroke " "
end tell*)
--This section deals specifically with iTunes. Getting it in a 'ready' state.
tell application "iTunes"
stop
launch
set old_tunes_volume to sound volume of application "iTunes"
set sound volume of application "iTunes" to volume_dial
--This deletes all the tracks of the smart playlist 'Wake-Up Time' in order to make sure the playlist is fresh.
--delete every track of playlist the_list
try
set visuals enabled to true
end try
--Let's get cracking!
delay 2
play track 1 of playlist the_list
end tell
--idle
end alarm_set
on idle
-- Here, we perform the routine checks to determine what part of the script needs to take place
tell application "iTunes"
-- This tells us what time it is right now so we know how long it's been running
set current_time to current date
--Let's wake someone up!
if volume_dial < dial_up then
my alarm_volume()
end if
--Did someone wake up and pause iTunes?
if player state ≠playing and volume_dial ≠0 then
my alarm_snooze()
end if
-- If the script has been running for 50 minutes, stop and return the system to a pre-launch state
if start_time + 50 * minutes ≤ current_time then
my alarm_stop()
end if
end tell
return time_delay
end idle
on alarm_volume()
-- Increase the volume at a slow and steady pace
tell application "iTunes"
set sound volume of application "iTunes" to volume_dial
set volume_dial to volume_dial + 1 as number
end tell
--idle
end alarm_volume
on alarm_snooze()
-- If iTunes has been paused, don't do anything for a brief moment, then get going again. Snooze in other words.
tell application "iTunes"
if player state ≠playing then
delay (time_delay * 120)
play (next track)
end if
end tell
--idle
end alarm_snooze
on alarm_stop()
--All the actions necessary to stop the script and re-set the settings to a pre-run state
tell application "iTunes"
stop
set volume output volume old_volume
set sound volume of application "iTunes" to old_tunes_volume
error number -128
end tell
end alarm_stop
Sorry I didn’t reply to your earlier post. I’m afraid I lost touch with this thread.
Your script keeps going as expected on my machine. Are you still saving it as a stay-open application?
If I change “Wake-Up Time” to “Library” for testing here, I get iTunes’s volume being set to 0 and the tracks starting to play. I haven’t run the script through its complete course, but presumably, the volume’s gradually increased until the sound becomes audible. One thing I did notice is that you need to make the variables ‘old_volume’ and ‘old_tunes_volume’ into globals or properties. Otherwise they’re local to the handlers in which they’re set and aren’t visible in alarm_stop(), which tries to read them.
No luck, still. The script as shown in my most recent post above still quits almost immediately after starting. Here’s a log event I just now took (if it might help)
tell current application
get volume settings
{output volume:50, input volume:53, alert volume:100, output muted:false}
set volume output volume 50
current date
date "Friday, May 12, 2006 6:47:32 AM"
end tell
tell application "iTunes"
stop current application
launch
current application
get sound volume
0
set sound volume to 0
set visuals enabled to true
play track 1 of playlist "Wake-Up Time"
end tell
Needless to say, I’m dumbfounded. Especially if it works fine on other people’s machines.
Presumably you got the event log by running the script in Script Editor. The idle handler won’t be executed under those circumstances. The script has to be saved as a stay-open application and the file run as an application in its own right.
If you are running it as a stay-open application, what do you mean by “quits”? Does it merely stop doing anything, or does it disappear from the Dock altogether? I can’t see anything that would cause it to quit altogether, but if you haven’t corrected the scope of the variables I mentioned in my last post, or if there’s some inconsistency between the script and your system, it might just be erroring silently without appearing to do anything. It should be possible to trap that, but first we should make sure the script’s being run the right way.
Thanks for all your help and I apologize about not being more specific. If there’s one thing I’ve noticed from asking for (and giving) support, it’s that one must be as specific as possible and I sometimes forget just how specific I need to be.
Good to know about the event log. I’ll definitely have to find a new method of debugging as I continue to use the Idle handler (once I figure it out!).
As for the core problem, I did make the update to the variables you mentioned by making them global and I am saving as a ‘Stay Open’ application. However, the application does quit and dissapear from the dock once it has satisfied the requirements for the volume increase instead of waiting the required amount of time as specified in the Idle handler.
I imagine I could get better information if I had access to every step it took, but I don’t know how to get that information. You’d mentioned finding a way to capture it and I would be very excited to incorporate something like that in my script!
Thanks again for all your help.
dennis
p.s. I’ve included as much System Info as I could since I’m not at my home computer right now…
Model: 17" iMac Duo Core
AppleScript: ???
Browser: Firefox 1.5.0.3
Operating System: Mac OS X (10.4)
You seem to be doing everything right and I can’t find anything fatally wrong with your script. Have you tried pasting the text into a new Script Editor window and compiling a totally fresh copy it, in a new file? The old one might have become corrupted for some reason.
Otherwise, here’s a “debugging” version of the script. There’s a beep at the top of the idle handler. If it doesn’t sound every few seconds, the script isn’t idling. (Or the line that sets the computer’s sound volume to 50 isn’t working. ;)) There are also ‘try’ blocks in each handler which hopefully will catch any errors and tell you where they’re occurring.
-- Defining the common variables
--Time to wait for volume increases and snooze
property time_delay : 7
--how hot we'll eventually make iTunes volume
property dial_up : 80
property volume_dial : 0
property old_volume : missing value
property old_tunes_volume : missing value
--Our playlist full of wake-up music
property the_list : "Library" --"Wake-Up Time"
property current_time : missing value
property start_time : missing value
--These settings capture the current volume of the system and iTunes and preps both to launch the alarm
on run
try
get volume settings
set old_volume to output volume of result
set volume_dial to 0
set volume output volume 50
-- This tells us what time our script started running
set start_time to current date
on error msg
display dialog "Error in run handler:" & return & msg
quit
error number -128
end try
-- Here, the alarm goes in to action.
my alarm_set()
end run
on alarm_set()
try
--This section deals specifically with iTunes. Getting it in a 'ready' state.
tell application "iTunes"
stop
-- launch
set old_tunes_volume to its sound volume
set its sound volume to volume_dial
--This deletes all the tracks of the smart playlist 'Wake-Up Time' in order to make sure the playlist is fresh.
--delete every track of playlist the_list
try
set visuals enabled to true
end try
--Let's get cracking!
delay 2
play track 1 of playlist the_list
end tell
on error msg
display dialog "Error in alarm_set handler:" & return & msg
quit
error number -128
end try
end alarm_set
on idle
beep
try
-- This tells us what time it is right now so we know how long it's been running
set current_time to current date
-- Here, we perform the routine checks to determine what part of the script needs to take place
tell application "iTunes"
--Let's wake someone up!
if volume_dial < dial_up then
my alarm_volume()
end if
--Did someone wake up and pause iTunes?
if player state ≠playing and volume_dial ≠0 then
my alarm_snooze()
end if
-- If the script has been running for 50 minutes, stop and return the system to a pre-launch state
if start_time + 50 * minutes ≤ current_time then
my alarm_stop()
end if
end tell
on error msg
display dialog "Error in idle handler:" & return & msg
quit
error number -128
end try
return time_delay
end idle
on alarm_volume()
try
-- Increase the volume at a slow and steady pace
tell application "iTunes"
set its sound volume to volume_dial
set volume_dial to volume_dial + 1
end tell
on error msg
display dialog "Error in alarm_volume handler:" & return & msg
quit
error number -128
end try
end alarm_volume
on alarm_snooze()
try
-- If iTunes has been paused, don't do anything for a brief moment, then get going again. Snooze in other words.
tell application "iTunes"
if player state ≠playing then
delay (time_delay * 120)
play (next track)
end if
end tell
on error msg
display dialog "Error in alarm_snooze handler:" & return & msg
quit
error number -128
end try
end alarm_snooze
on alarm_stop()
try
--All the actions necessary to stop the script and re-set the settings to a pre-run state
tell application "iTunes"
stop
set its sound volume to old_tunes_volume
end tell
set volume output volume old_volume
on error msg
display dialog "Error in alarm_stop handler:" & return & msg
end try
quit -- Quit this script application when it stops.
error number -128 -- Stop it now
end alarm_stop
Sorry for the delay in my response. I had to be certain the script would pass the field test. It survived in my sand box and it woke me up this morning. More importantly, though, it is continuing to run! I tried running your error-proofing script and nothing went wrong so I copied mine to another document and, again, it worked just fine. It may very well have been just a corrupt document the whole time. Two observations, though:
My script did not show ‘Stay Open’ as being checked when I went to ‘Save As’ thought I had previously saved it as such. I then discovered that there seemed to be no way of verifying if a script had been saved as ‘Stay Open.’
In the ‘Get Info’ dialog box, all my script applications are listed as ‘Power PC.’ Not really a concern, just odd given that I’m on an Intel Mac and Script Editor is ‘Universal,’ thus I assumed that my scripts would be ‘Universal’ as well.
Long post short, it works! Thank you so very much for all of your help.
If I load my copy of the script into Script Editor and go to the “Save As” dialog, the “Stay Open” box is still checked. The obvious suspects in your case are an oversight while saving or a corruption of the file.
I don’t recall noticing “PowerPC” and “Universal” in info windows before you mentioned them. I only downloaded the 10.4.6 updater last night, but I see the Finder version’s still 10.4.4, so presumably they’ve been there since at least then.
In the minimal testing I’ve done so far, scripts saved as applications are shown as “PowerPC”, while those saved as application bundles are shown as “Universal”. I have a PowerPC machine anyway, so it doesn’t make any difference to me. But if script applications are being saved as PowerPC code on your machine, presumably it’s running them through some sort of translation software. It might be interesting to see if they run any faster or more reliably when saved as application bundles…