NSTimer delay time as expression.

I must be doing something really dumb. I’m setting a timer and I want to use an expression. If I use:


set theTimer to current application's NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(60, me, "timerExpired:", "Closing time", false)

all is well. However if I use and expression to convert a variable delay in minutes I get an error:


set theTimer to current application's NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_((minutes * 60), me, "timerExpired:", "Closing time", false)

I’ve tried to coerce it to number, or integer to get the data passed. I’m just learning this stuff, so I’m probably missing something really basic.

TIA

That error message is telling you the problem is in the method sound:didFinishPlaying:. Is your timer being set up in that method?

There’s no reason I can see that you can’t use (minutes * 60) as you have there…

Yes, sound_didFinishPlaying_ is my main state change handler. I play a sound in a handler in response to a start button. As each of several sounds completes from NSSound, sound_didFinishPlaying_ is called. Here is the full Applescript below. When I put a constant seconds timer in the NSTimer method, everything works fine. It is only when I try to calculate the seconds wait time that I get the error, thanks:


script rs_MedTAppDelegate
	property parent : class "NSObject"
	property meditationTime : 20
	property callSound : "TibetanSakyaBell"
	property timerSound : "SoftStruckTibetanSingingBowl"
	property programState : 0
	property idleState : 0
	property callingState : 1
	property startingState : 2
	property timingState : 3
	property ending1State : 4
	property ending2State : 5
	property ending3State : 6
	property isIdle : true
	property theTimer : missing value
	property theSound : missing value
	
	
	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened 
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate_
	
	on startMeditation_(sender)
		set my isIdle to false
		set programState to callingState
		tell current application's NSSound to set theSound to soundNamed_(callSound)
		tell theSound
			setDelegate_(me)
			play()
		end tell
	end startMeditation_
	
	on sound_didFinishPlaying_(someSound, theResult)
		
		if theResult as boolean = true then
			
			if programState = callingState then
				set programState to startingState
				log "Playing start sound: " & programState
				tell current application's NSSound to set theSound to soundNamed_(timerSound)
				tell theSound
					setDelegate_(me)
					play()
				end tell
			else if programState = startingState then
				set programState to timingState
				log "starting timer: " & programState
				set secondsTimer to (meditationTime * 60)
				set theTimer to current application's NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(secondsTimer, me, "timerExpired:", "Closing time", false)
			else if programState = ending1State then
				set programState to ending2State
				log "Playing second end sound: " & programState
				tell theSound
					setDelegate_(me)
					play()
				end tell
			else if programState = ending2State then
				set programState to ending3State
				log "Playing third end sound: " & programState
				tell theSound
					setDelegate_(me)
					play()
				end tell
			else if programState = ending3State then
				set programState to idleState
				log "Finishing." & programState
				set my isIdle to true
			else
				log "sound_didFinishPlaying_: Invalid state" & programState
				set programState to idleState
				set my isIdle to true
			end if
			
		else
			display dialog "The sound was not played."
		end if
		
	end sound_didFinishPlaying_
	
	on timerExpired_(someTimer)
		if programState = timingState then
			-- theSound should already be set from startingState
			set programState to ending1State
			tell theSound
				setDelegate_(me)
				play()
			end tell
		else
			log "TimerExpired_: Invalid state " & programState
			set programState to idleState
			set my isIdle to true
		end if
	end timerExpired_
	
	on resetTimer_(sender)
		set programState to idleState
		set my isIdle to true
		
		try
			tell theTimer to invalidate()
		on error
			-- just to catch bad timer?
		end try
	end resetTimer_
	
	
end script

And the |play| went away when I cut and pasted.

Is meditationTime involved in some binding? If so, my guess is that it’s becoming an NSNumber, and the error is in fact happening when you try to use it in an AS multiplication. Have you tried:

 set secondsTimer to ((meditationTime as integer) * 60)

or:

 set secondsTimer to ((meditationTime as real) * 60)

Yes meditationTime is bound to a text box in the main window. I had originally used the expression:

(meditationTime * 60) as integer

for the elapsed seconds argument and that didn’t work. But I tried your suggestion and that works! Wonderful!

I am very grateful for your help!

Model: MacBook Pro
Browser: Safari 537.31
Operating System: Mac OS X (10.8)