Unresponsive GUI

Hey guys, ive finally added a GUI to my script but when the alarm is set off it freezes up the interface

Description : When alarmed it activated a alarm which is set off when the laptop is moved

http://swat.gotdns.com MultiAlarm

If you have a SMS enabled iBook/PowerBook you can try it and see what i mean

-- alarm.applescript
-- alarm

--  Created by Steven Halford on 08/04/2006.
-- Modified by semaja2 on 13/04/2006
--  Copyright 2006 Steven Halford. All rights reserved.

property appName : "MultiAlarm"
--machType is either powerbook or ibook
property machType : "hirespb"
property alarmActivated : "false"
property thisHere : ""
property theUpperX : ""
property theLowerX : ""
property theUpperY : ""
property theLowerY : ""
property get_password : false
property the_password : "Password"
property alarmVolumeOrignal : "50"
property alarmVolumeAlert : "100"

on launched theObject
	
	beep 1
	
end launched

on idle theObject
	
	if alarmActivated is false then
		
	end if
	if alarmActivated is true then
		
		
		repeat while alarmActivated is true
			
			
			--runs motion cmd to find x and y axis
			set theNewCoords to do shell script thisHere & "Contents/Resources/motion_" & machType & " " & machType
			if theNewCoords is not "" then
				set {theNewX, theNewY} to getXY(theNewCoords)
				set theNewX to theNewX + 1000
				set theNewY to theNewY + 1000
				--Checks the x and y axis for change if change is found it will start the process
				if theNewX is greater than theUpperX or theNewX is less than theLowerX or theNewY is greater than theUpperY or theNewY is less than theLowerY then
					alarmAlert(1)
				else
					--stops sound and reactivates systems
					stop (load sound "caralarm.aiff")
					--set alarmActivated to false
					
				end if
			end if
		end repeat
	end if
end idle


---------------Interface Functions---------------



--Menu Items

on choose menu item theObject
	set n to name of theObject
	if n is "Arm" then
		alarmActivate(1)
	end if
end choose menu item

--Text Fields

on end editing theObject
	set c to content of text field "secure" of window "main"
	if c is the_password then
		set visible of window "main" to false
		alarmDeactivate(1)
		beep 2
	end if
end end editing

--Clicked objects

on clicked theObject
	set n to name of theObject
	if n is "Disarm" then
		set c to content of text field "secure" of window "main"
		if c is the_password then
			set visible of window "main" to false
			alarmDeactivate(1)
			beep 1
		else
			display dialog "Incorrect Password"
			beep 5
		end if
	else if n is "Enable Alarm" then
		alarmActivate(1)
	else if n is "Disable Alarm" then
		alarmDeactivate(1)
	else if n is "Set" then
		set the_password to content of text field "secure" of window "setpass"
		set visible of window "main" to false
		display dialog "Password Set"
		set visible of window "main" to false
		beep 1
	end if
	
end clicked

----------------Functions------------

--Gets and organises coordinates
on getXY(theCoords)
	set oldTID to AppleScript's text item delimiters
	set text item delimiters to {" "}
	set theX to first text item of theCoords
	set theY to second text item of theCoords
	set text item delimiters to oldTID
	return {theX, theY}
end getXY

--Checks and controls growl
on GrowlNotify(myName, myTitle, myText)
	set myApp to ""
	
	tell application "System Events" to set GrowlRunning to ((application processes whose (name is equal to "GrowlHelperApp")) count)
	
	if GrowlRunning ≥ 1 then
		try
			set myApp to "GrowlHelperApp"
			
			set notifs to "{\"Alarm Activated\", \"Alarm Deactivated\",\"Theft in progress\"}"
			
			tell application myApp to run script "register as application \"" & appName & "\" all notifications " & notifs & " default notifications " & notifs & " icon of application \"" & appName & "\""
			
			tell application myApp to run script "notify with name \"" & myName & "\" title \"" & myTitle & "\" application name \"" & appName & "\" description \"" & myText & "\" icon of application \"" & appName & "\""
		end try
	end if
end GrowlNotify

---------------------Alarm Functions---------------------

--Alarm Activation Script
on alarmActivate(do)
	set alarmActivated to true
	---------------Sets paths---------------------
	set thisHere to path to me
	set thisHere to POSIX path of thisHere
	--------------Sound Configs-----------------
	--Sets the sound for alarm activation
	set theArming to load sound "armx2.wav"
	--------------------------------------------------
	--set alarmVolumeOrignal to volume
	--plays the arming sound
	beep
	play theArming
	
	--runs motion cmd to find x and y axis
	set theCoords to do shell script thisHere & "Contents/Resources/motion_" & machType & " " & machType
	if theCoords is not "" then
		set {theX, theY} to getXY(theCoords)
		set theUpperX to theX + 1002
		set theLowerX to theX + 998
		set theUpperY to theY + 1002
		set theLowerY to theY + 998
	end if
	
	GrowlNotify("Alarm Activated", "Alarm", "Warning : Alarm Primed")
	
	
end alarmActivate

--Alarm Deactivation Script
on alarmDeactivate(do)
	--Deactivates the check
	set alarmActivated to false
	--plays the arming sound
	beep 2
	play (load sound "arm.wav")
	--Displays growl notification
	GrowlNotify("Alarm Deactivated", "Alarm", "Warning : Alarm Disarmed")
	set volume alarmVolumeOrignal
end alarmDeactivate


on alarmAlert(do)
	--Play alarm sound
	play (load sound "caralarm.aiff")
	--Say
	say "Help! I am being stolen."
	beep 1
	--Set the volume to MAX
	set volume alarmVolumeAlert
	--Displays Growl Notification
	GrowlNotify("Theft in progress", "Alarm", "Warning : Theft in progress")
	
	return
	
	
end alarmAlert

Hi again semaja2,

Playing sounds take up a lot of cpu usage. If you notice in the examples with ‘beep’, using beeps interfeered with the ui responsiveness. I was thinking that maybe loading all the sounds first, using them, then releasing them at quit time might be a better way to do this, instead of constanly loading the sounds. Note that constantly loading sounds is bad, because they aren’t deleted automatically. See the ‘load’ command in the reference document.

I’ll do some testing when I have time also.

Edited: here’s an excerpt from my studio reference manual:

For information about freeing loaded objects, see the Discussion section of the load image (page 108) command.

gl,

Thanks for your reply, i get what you mean but playing that sound constantly is vital to the alarm, what else would suggest to make it play on loop when the alarm is activated?

If you work it out, it would be excellent

Hi semaja2,

Here’s a test script:

global basso_snd

on idle theObject
play basso_snd
–play (load sound “Glass”)
–say “Help! I am being stolen.”
return 2
end idle

on awake from nib theObject
set basso_snd to load sound “Basso”
end awake from nib

on will quit theObject
– not sure if loaded sounds are saved on quit
– no harm
delete basso_snd
end will quit

on clicked theObject
set x to count (every sound)
log x
end clicked

I have a window with a text field and a button. Every handler is connected to the application object, except the clicked handler which is connected to the button. I didn’t put the beep in there because we know that slows down the app considerably and shouldn’t be used here in the idle handler where it beeps continuously. As the script is now, it loads the sound in the ‘awake from nib’ handler, plays the sound in the ‘idle’ handler, and deletes the sound in the ‘quit’ handler. If the user presses the button, a count of the number of loaded sounds is logged. It should remain as 1.

On the other hand, uncomment and comment these lines:

play basso_snd
--play (load sound "Glass")

so it looks like this:

--play basso_snd
play (load sound "Glass")

Here, the sound is repeatedlly loaded, increasing the memory usage of the app each time the sound is loaded. If the user presses the button, the increasing count of loaded sounds is logged.

I tested the ‘say’ command and it didn’t seem to slow down typing in the text field, but did cause some interference. Maybe you can use a seperate app to speak the phrase. I still test that out.

In the short run of your alarm app, constantly loading sounds may not affect it. You probably want to do it this way anyway where you load each sound just once.

gl,

ive tried to implement what you posted but im getting a error

-- alarm.applescript
-- alarm

--  Created by Steven Halford on 08/04/2006.
-- Modified by semaja2 on 13/04/2006
--  Copyright 2006 Steven Halford. All rights reserved.

property appName : "MultiAlarm"
--machType is either powerbook or ibook
property machType : "powerbook"
property alarmActivated : "false"
property thisHere : ""
property theUpperX : ""
property theLowerX : ""
property theUpperY : ""
property theLowerY : ""
property get_password : "0"
property the_password : "Hello"
property new_password : ""
property theOldVolume : ""
property alarmVolumeAlert : "100"
property alarmVoice : false
property alarmGrowl : 0

--Sounds
global alert_snd


to getPW(KeyName)
	tell application "Keychain Scripting"
		launch
		tell current keychain to tell (some generic key whose name is KeyName) to set PWD to password
	end tell
end getPW

on launched theObject
	
	--load sound "caralarm.aiff"
	
	set theMachine to do shell script "/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/grep 'Machine Name' | /usr/bin/colrm 1 20"
	if theMachine is not "" then
		set {theModel} to getSystem(theMachine)
	end if
	
	if theModel contains "powerbook" then
		--beep 1
		set visible of window "about" to true
	else if theModel contains "ibook" then
		if machType contains "hirespb" then
			set visible of window "nosupport" to true
			--beep 10
		else
			--beep 1
			set visible of window "about" to true
		end if
	else
		set visible of window "nosupport" to true
		--beep 10
	end if
	
	
end launched

on awake from nib theObject
	set alert_snd to load sound "caralarm"
end awake from nib

--on will quit theObject
-- not sure if loaded sounds are saved on quit
-- no harm
--	delete alert_snd
--end will quit

on idle theObject
	play alert_snd
	if alarmActivated is false then
		
	end if
	if alarmActivated is true then
		
		
		repeat while alarmActivated is true
			
			
			--runs motion cmd to find x and y axis
			do shell script thisHere & "Contents/Resources/AMSTracker"
			set theNewCoords to last paragraph of result
			if theNewCoords is not "" then
				set {theNewX, theNewY} to getXY(theNewCoords)
				set theNewX to theNewX + 1000
				set theNewY to theNewY + 1000
				--Checks the x and y axis for change if change is found it will start the process
				if theNewX is greater than theUpperX or theNewX is less than theLowerX or theNewY is greater than theUpperY or theNewY is less than theLowerY then
					alarmAlert(1)
				else
					--stops sound and reactivates systems
					--stop (load sound "caralarm.aiff")
					set alarmGrowl to 0
					
				end if
			end if
		end repeat
	end if
end idle


---------------Interface Functions---------------



--Menu Items

on choose menu item theObject
	set n to name of theObject
	if n is "Arm" then
		alarmActivate(1)
	else if n is "Disarm" then
		if alarmActivated is true then
			set visible of window "main" to true
		end if
	end if
end choose menu item

--Text Fields

on end editing theObject
	set n to name of theObject
	if n is "secureDisarm" then
		set c to content of text field "secureDisarm" of window "main"
		set the_password to c
		set the content of text field "secureDisarm" of window "main" to ""
		if the_password = getPW("MultiAlarm") then
			set visible of window "main" to false
			alarmDeactivate(1)
		else
			display dialog "Incorrect Password"
			--beep 5
		end if
		--beep 2
	else if n is "secureExit" then
		set c to content of text field "secureExit" of window "quitCheck"
		set the_password to c
		set the content of text field "secureExit" of window "quitCheck" to ""
		if the_password = getPW("MultiAlarm") then
			quit
		else
			display dialog "Incorrect Password"
			--beep 5
		end if
		--beep 2
	else if n is "secureSet" then
		set the_password to content of text field "secureSet" of window "setpass"
		set visible of window "setpass" to false
		keychain(newPWD)
		--beep 1
	end if
end end editing

--Clicked objects

on clicked theObject
	set n to name of theObject
	if n is "Disarm" then
		
		--		if n is "secureDisarm" then
		set c to content of text field "secureDisarm" of window "main"
		set the_password to c
		set the content of text field "secureDisarm" of window "main" to ""
		if the_password = getPW("MultiAlarm") then
			set visible of window "main" to false
			alarmDeactivate(1)
		else
			display dialog "Incorrect Password"
			--beep 5
		end if
		--beep 2
		
		--	end if
	else if n is "exit" then
		
		set c to content of text field "secureExit" of window "quitCheck"
		set the_password to c
		set the content of text field "secureExit" of window "quiteCheck" to ""
		if the_password = getPW("MultiAlarm") then
			quit
		else
			display dialog "Incorrect Password"
			--	beep 5
		end if
		--beep 2
		
	else if n is "Enable Alarm" then
		alarmActivate(1)
	else if n is "Disarm Alarm" then
		if alarmActivated is true then
			set visible of window "main" to true
		end if
	else if n is "Set" then
		set newPWD to content of text field "secureSet" of window "setpass"
		keychain(newPWD)
		set visible of window "setpass" to false
		--beep 1
	else if n is "voice" then
		if alarmVoice is true then
			set alarmVoice to false
		else if alarmVoice is false then
			set alarmVoice to true
		end if
	end if
	
end clicked

----------------Functions------------

--Gets and organises coordinates
on getXY(theCoords)
	set oldTID to AppleScript's text item delimiters
	set text item delimiters to {"   "}
	set theX to second text item of theCoords
	set theY to third text item of theCoords
	set text item delimiters to oldTID
	return {theX, theY}
end getXY

--gets machine name
on getSystem(theMachine)
	set oldTID to AppleScript's text item delimiters
	set text item delimiters to {" "}
	set theName to first text item of theMachine
	set text item delimiters to oldTID
	return {theName}
end getSystem

--Checks and controls growl
on GrowlNotify(myName, myTitle, myText)
	set myApp to ""
	
	tell application "System Events" to set GrowlRunning to ((application processes whose (name is equal to "GrowlHelperApp")) count)
	
	if GrowlRunning ≥ 1 then
		try
			set myApp to "GrowlHelperApp"
			
			set notifs to "{\"Alarm Activated\", \"Alarm Deactivated\",\"Theft in progress\"}"
			
			tell application myApp to run script "register as application \"" & appName & "\" all notifications " & notifs & " default notifications " & notifs & " icon of application \"" & appName & "\""
			
			tell application myApp to run script "notify with name \"" & myName & "\" title \"" & myTitle & "\" application name \"" & appName & "\" description \"" & myText & "\" icon of application \"" & appName & "\""
		end try
	end if
end GrowlNotify

on keychain(newPWD)
	tell application "Keychain Scripting"
		tell keychain 1
			unlock -- gotta unlock it.
			--set theKey to (first key whose name is "Some Key") -- then find it
			set password of (first generic key whose name is "MultiAlarm") to newPWD
		end tell
	end tell
end keychain

---------------------Alarm Functions---------------------

--Alarm Activation Script
on alarmActivate(do)
	set theOldVolume to get output volume of (get volume settings)
	set alarmActivated to true
	---------------Sets paths---------------------
	set thisHere to path to me
	set thisHere to POSIX path of thisHere
	--------------Sound Configs-----------------
	--Sets the sound for alarm activation
	set theArming to load sound "armx2.wav"
	--------------------------------------------------
	--set alarmVolumeOrignal to volume
	--plays the arming sound
	--beep
	play theArming
	
	--runs motion cmd to find x and y axis
	do shell script thisHere & "Contents/Resources/AMSTracker"
	set theCoords to last paragraph of result
	if theCoords is not "" then
		set {theX, theY} to getXY(theCoords)
		set theUpperX to theX + 1002
		set theLowerX to theX + 998
		set theUpperY to theY + 1002
		set theLowerY to theY + 998
	end if
	
	GrowlNotify("Alarm Activated", "Alarm", "Warning : Alarm Primed")
	
	
end alarmActivate

--Alarm Deactivation Script
on alarmDeactivate(do)
	--Deactivates the check
	set alarmActivated to false
	--plays the arming sound
	--beep 2
	play (load sound "arm.wav")
	--Displays growl notification
	GrowlNotify("Alarm Deactivated", "Alarm", "Warning : Alarm Disarmed")
	set volume output volume theOldVolume
end alarmDeactivate



on alarmAlert(do)
	--Play alarm sound
	play alert_snd
	--Say
	if alarmVoice is true then
		say "Help! I am being stolen."
	end if
	--beep 1
	--Set the volume to MAX
	set volume alarmVolumeAlert
	--Displays Growl Notification
	if alarmGrowl is equal to 0 then
		set alarmGrowl to 1
		GrowlNotify("Theft in progress", "Alarm", "Warning : Theft in progress")
	end if
	return
	
	
end alarmAlert

I notice that you used caralarm.aiff earlier, but now you’re using just caralarm.

thanks for pointing that out, but it still leaves me with a variable not defined error

Hi semaja2,

That’s very strange. A bug in xcode? Maybe somebody can confirm this?

gl,