Help with Snow Leopard and "conversational" scripts.

My friends and I are currently writing a “butler” script, simply because we just recently discovered applescript, and though it would be cool to be able to control the entire computer via speech commands. We’ve gotten a lot done so far, and have made some progress. However, there are still a lot details that need to be ironed out. We are also working collaboratively on the script through our shared dropbox folder. So pieces of it get added at a time. It’s a work in progress, but in order for it to work, the speech recognition server is vital. And, for some reason, we can’t get it to work!

This is the butler script we have so far, without my latest addition. Essentially what this does is tell the user the time, date, and current weather. It also notify’s the user of any new mail, and explains the user’s calendar events in great detail for events of that day and in the nearby future. At the end, it asks if it would like to open one of my three favorite websites via speech. (My addition that the others can change to what they want). This all works well. Now, see below this applescript.

tell application "Mail"
	check for new mail
end tell
--This starts the get weather script
--you will need to set the web address below for your city, I live in Bakersfield, CA, so it's currently set to the weather there.

set weather to "curl " & quote & "http://weather.yahooapis.com/forecastrss?w=12796826&u=f" & quote

set postWeather to "grep -E '(Current Conditions:|F<BR)'"

set forecast to do shell script weather & " | " & postWeather

set voiceweather to (characters 1 through -8 of paragraph 2 of forecast) as string

--This starts the get date script

set CalendarDate to date string of (current date)

set CurrentDateHours to hours of (current date)

if CurrentDateHours is greater than or equal to 0 and CurrentDateHours is less than 12 then
	set CurrentDateGreeting to "Good morning sir." as string
end if
if CurrentDateHours is greater than or equal to 12 and CurrentDateHours is less than 18 then
	set CurrentDateGreeting to "Good afternoon sir." as string
end if
if CurrentDateHours is greater than or equal to 18 and CurrentDateHours is less than 24 then
	set CurrentDateGreeting to "Good evening sir." as string
end if

if CurrentDateHours is greater than 12 then
	set CurrentDateHours to CurrentDateHours - 12 as string
	set CurrentDateAMPM to "PM" as string
else
	set CurrentDateAMPM to "AM" as string
end if

set CurrentDateMinutes to minutes of (current date) as string
if CurrentDateMinutes is less than 10 then
	set CurrentDateMinutes to "0" & CurrentDateMinutes as string
end if

if CurrentDateHours is equal to 0 then
	set CurrentDateHours to 12 as string
end if

--New Message Script

tell application "Mail"
	set UnreadCount to 0
	set res to {}
	set res to unread count of every mailbox
	repeat with i in res
		set UnreadCount to UnreadCount + i
	end repeat
	set alist to every account whose enabled is true
	repeat with af in alist
		set UnreadCount to UnreadCount + (unread count of mailbox "INBOX" of af)
	end repeat
end tell

set MessagesPlural to " new messages."
if UnreadCount is equal to 1 then
	set MessagesPlural to " new message."
end if

if UnreadCount is equal to 0 then
	set UnreadCount to "no" as string
	tell application "Mail"
		quit
	end tell
	--Matt added a quit if no new mail
end if

--And this is where the magic happens
say CurrentDateGreeting & " Today is " & CalendarDate & ". It is " & CurrentDateHours & ":" & CurrentDateMinutes & " " & CurrentDateAMPM & ". The weather currently is a " & voiceweather & "degrees. You have " & UnreadCount & MessagesPlural

if UnreadCount is not "no" then
	quit application "Mail"
	say "I will open your inbox for you now"
	try
		tell application "Mail"
			activate
			tell the front message viewer
				set unreadMessages to (the messages whose ¬
					read status is false) as list
				if (count of unreadMessages) is not 0 then
					set selected messages to {the first item of unreadMessages}
				else
					beep
				end if
			end tell
		end tell
	on error error_message
		beep
		display dialog "Error looking for next unread message: " & ¬
			return & return & error_message buttons {"OK"} default button 1
	end try
	
	
end if

--This is the iCal script
set Now to current date


set TodaysDate to date string of Now
set MidnightToday to (date TodaysDate)
set MidnightTomorrow to (date TodaysDate) + (1 * days)
tell application "iCal"
	set AllCalendars to every calendar
	
	repeat with EachCalendar in AllCalendars
		set CalendarName to name of EachCalendar
		
		set TodaysEvents to (every event of EachCalendar ¬
			whose (start date is greater than MidnightToday and ¬
			start date is less than MidnightTomorrow) or ¬
			(start date is MidnightToday and allday event is true))
		repeat with EachEvent in TodaysEvents
			if contents of EachEvent is not missing value then
				set TheEvent to contents of EachEvent
				set EventProperties to properties of TheEvent
				set EventName to summary of EventProperties
				set EventLocation to location of EventProperties
				set EventDescription to description of EventProperties
				
				if not (allday event of EventProperties) then
					set EventTime to "at " & time string of start date of EventProperties
					if start date of EventProperties comes before Now then
						set EventStillToCome to false
					else
						set EventStillToCome to true
					end if
				else
					set EventTime to ", All Day"
					set EventStillToCome to true
				end if
				
				if EventStillToCome then
					set EventAttendees to attendees of TheEvent
					set AttendeeNames to ""
					repeat with EachAttendee in EventAttendees
						set AttendeeName to display name of EachAttendee
						set AttendeeNames to AttendeeNames & " ," & AttendeeName
					end repeat
					
					--Me trying to remove the seconds from the message (Success btw!)
					
					try
						set EventTime to (characters 1 thru 8 of EventTime) & " " & (characters 13 thru 14 of EventTime) as string
					on error
						set EventTime to (characters 1 thru 7 of EventTime) & " " & (characters 12 thru 13 of EventTime) as string
					end try
					
					
					
					--Start building message 
					set EventMsg to ""
					set EventMsg to EventMsg & EventTime & ", "
					set EventMsg to EventMsg & "is the " & EventName
					if EventLocation is not in {missing value, ""} then ¬
						set EventMsg to EventMsg & ", at " & EventLocation
					set EventMsg to EventMsg & ". "
					if EventDescription is not in {missing value, ""} then ¬
						set EventMsg to EventMsg & "The notes indicate: " & EventDescription & ". "
					if EventAttendees is not {} then ¬
						set EventMsg to EventMsg & "Expected attendees are " & AttendeeNames & ". "
					say EventMsg
					
				end if
			end if
		end repeat
	end repeat
end tell
--This is the goodbyes
--Inserted "Colors" script
set MyApp to {"Yes, Facebook", "Yes, Fox News", "Yes, Life Hacker", "No"}
--This is where Snow Leopard fails. There is no pause for it to listen here. And I can't figure out how to fix it -Scott.
try
	tell application "SpeechRecognitionServer"
		set YourApp to (listen for MyApp with prompt "Would you like me to open Facebook, Fox News, or Life Hacker?" displaying MyApp giving up after 30)
	end tell
on error
	delay 10
	say "Let me know if I can be of any further assistance. And have a wonderful rest of your day!"
end try
if YourApp is "Yes, Facebook" then
	tell application "Safari"
		open location "http://www.facebook.com/"
	end tell
end if
if YourApp is "Yes, Fox News" then
	tell application "Safari"
		open location "[url=http://www.foxnews.com]www.foxnews.com[/url]"
	end tell
end if
if YourApp is "Yes, Life Hacker" then
	tell application "Safari"
		open location "[url=http://www.lifehacker.com]www.lifehacker.com[/url]"
	end tell
end if

if YourApp is "No" then
	say "Alright then"
end if

say "Let me know if I can be of further assistance, and have a wonderful rest of your day!"

This is the latest addition that I’ve been trying to add to it. At the end, instead of simply saying “let me know if you can be of further assistance,” it will actually be a functional question “Do you require further assistance?” and from there the user can respond based on the currently few meager options I’ve put in. This script works fine by itself, but doesn’t work at all when I put it in the other one! Honestly, I have no idea where to put it to make it functional at the end.

set Response1 to {"Yes", "No"}
set Response2 to {"Applications", "Logging out"}
try
	tell application "SpeechRecognitionServer"
		set chosenanswer to (listen for Response1 with prompt "Do you require further assistance?" displaying Response1 giving up after 15)
	end tell
	
	-- if's --
	if chosenanswer is "Yes" then
		say "Options are: Help opening applications, or Help logging out?"
		tell application "SpeechRecognitionServer"
			set Chosenanswer2 to (listen for Response2 displaying Response2 giving up after 15)
		end tell
		-- if's 2.0 --
		if Chosenanswer2 is "Applications" then
			tell application "SpeechRecognitionServer"
				set chosenanswer3 to (listen for Response1 with prompt "to open an application, simply say open, and then the application name. Would you like me to list a few of the applications available via speech launch?" displaying Response1 giving up after 15)
				if chosenanswer3 is "yes" then
					say "Safari, Mail, Finder, Ichat, and Itunes are all good examples of programs that can be opened via speech."
				end if
			end tell
		end if
		if Chosenanswer2 is "Logging out" then
			say "this applescript has the potential for functionality!"
		end if
	end if
	if chosenanswer is "No" then
		say "Have a wonderful day"
	end if
	
on error
	say "Hmm, it appears as if Snow Leopard is sucking at life again."
end try

Also the main problem I’m having with this script is that it doesn’t work in snow leopard! If you answer “yes” to this question, it lists the two options, applications and logging out. But then the speech input bubble disappears and doesn’t let you speak anymore!!! I was frustrated, so I sent it to my friend who has leopard who is working on this with me, and on his computer it worked fine! It didn’t work on my cousin’s snow leopard machine either. So I guess my main questions are: 1) Where should I put this script to make it work, even if it’s just in leopard? & 2) How can I get this script to work in snow leopard like it’s supposed to without the speech bubble shutting down?

Just a tip: My cousin and I found a way to make it work, but it’s ineffective and slow. If you run a shell script to force quit speechrecognitionserver right before you need it to work, and then you tell the application to activate and then you have it listen for a response with a prompt, it works okay. But it’s unreliable and slooooowwww.

Please Help! And thankyou in advance for any responses!

Model: Macbook Pro 15"
Browser: Safari 533.17.8
Operating System: Mac OS X (10.6)

I fixed your script… it works now in 10.6. It seems there’s a known bug with this in 10.6. The fix seems to be just keep killing the SpeechRecognitionServer process every time you want to say something. As such I added a couple handlers to the bottom of the script and a global variable to work with the handler. This will ensure the handler only runs in snow leopard so your friends on 10.5 won’t mind having the handler in the script.

Note: I also fixed a few of the if statements too. You should use the if/else if/else format so that 2 if statements aren’t evaluated when only 1 statement is needed… just for efficiency.

global sysVersion

set sysVersion to system version of (get system info)
set Response1 to {"Yes", "No"}
set Response2 to {"Applications", "Logging out"}

-- we do this so we can restart it if it was running at the end of the script
set speechIsRunning to isSpeakableItemsRunning()

try
	tell application "SpeechRecognitionServer"
		my tensixSpeechBugFix()
		set chosenanswer to (listen for Response1 with prompt "Do you require further assistance?" displaying Response1 giving up after 15)
	end tell
	
	-- if's --
	if chosenanswer is "Yes" then
		my tensixSpeechBugFix()
		say "Options are: Help opening applications, or Help logging out?"
		tell application "SpeechRecognitionServer"
			set Chosenanswer2 to (listen for Response2 displaying Response2 giving up after 15)
		end tell
		-- if's 2.0 --
		if Chosenanswer2 is "Applications" then
			tell application "SpeechRecognitionServer"
				my tensixSpeechBugFix()
				set chosenanswer3 to (listen for Response1 with prompt "to open an application, simply say open, and then the application name. Would you like me to list a few of the applications available via speech launch?" displaying Response1 giving up after 15)
				if chosenanswer3 is "yes" then
					my tensixSpeechBugFix()
					say "Safari, Mail, Finder, Ichat, and Itunes are all good examples of programs that can be opened via speech."
				end if
			end tell
		else if Chosenanswer2 is "Logging out" then
			my tensixSpeechBugFix()
			say "this applescript has the potential for functionality!"
		else
			my tensixSpeechBugFix()
			say "that is not a valid response!"
		end if
	else
		my tensixSpeechBugFix()
		say "Have a wonderful day"
	end if
on error
	my tensixSpeechBugFix()
	say "Hmm, it appears as if Snow Leopard is sucking at life again."
end try

-- restart it if it was running
restartSpeakableItems(speechIsRunning)

(*================= SUBROUTINES =================*)
on isSpeakableItemsRunning()
	tell application "System Events"
		try
			first process whose name is "SpeakableItems"
			return true
		on error
			return false
		end try
	end tell
end isSpeakableItemsRunning

on restartSpeakableItems(speechIsRunning)
	if sysVersion is greater than or equal to "10.6" and speechIsRunning then
		my tensixSpeechBugFix()
		tell application "SpeakableItems" to quit
		delay 0.5
		tell application "SpeakableItems" to activate
	end if
end restartSpeakableItems

on tensixSpeechBugFix()
	if sysVersion is greater than or equal to "10.6" then
		try
			do shell script "killall SpeechRecognitionServer"
			delay 0.5
		end try
	end if
end tensixSpeechBugFix

Thanks so much! I actually just found that shell script yesterday and got it working too, but you’ve ironed out a lot of the issues iwth the script! You can probably tell I didn’t write the whole top part. Lol. ThankyouThankyouThankyou!:lol:

I have another question!! Sorry if this is not the way you’re supposed to do things around here… but I just figured I might as well ask you because you obviously seem to know what you’re doing! :slight_smile:

So when you corrected my script, you completely enlightened me about running subroutines in the script. After a bit of thought, I realized that subroutines have the possibiltiy to make everything infinitely easier. So I set out to write one that worked just as an experiment to see how they work and to figure out how I can implement them, and I ended up with the script below. It incorperates your 106 speech bug fix, but doesn’t work when I try to use handlers to say the date and time (correct me if I’m wrong, but for some reason I think handlers are the things in green text that you make with “set blahblahblah to whatever”). If I take out those handlers, then everything works fine! I’m betting it’s a simple mistake, but here’s the script anyways.

global sysVersion


my WhatCanIDo()

on WhatCanIDo()
	try
		my tensixSpeechBugFix()
		tell application "SpeechRecognitionServer"
			my tensixSpeechBugFix
			set chosenanswer1 to listen for {"Yes", "No"} with prompt "Would you like me to run through information relating to today?" giving up after 15
		end tell
		if chosenanswer1 is "yes" then
			my tensixSpeechBugFix()
			get saytime
			tell application "SpeechRecognitionServer"
				my tensixSpeechBugFix()
				set Chosenanswer2 to listen for {"Yes", "No"} with prompt "would you like more information?" giving up after 7
			end tell
		else if chosenanswer1 is "no" then
			my tensixSpeechBugFix()
			say "Alright then."
		end if
		if Chosenanswer2 is "yes" then
			say currentdate & currenthours
		else if Chosenanswer2 is "no" then
			say "Good. I didn't have any more anyways"
			
		end if
	on error
		beep 1
	end try
	
end WhatCanIDo
------subscripts------


on tensixSpeechBugFix()
	if sysVersion is greater than or equal to "10.6" then
		try
			do shell script "killall SpeechRecognitionServer"
			delay 0.5
		end try
	end if
end tensixSpeechBugFix

set currentdate to date string of (current date)
set currenthours to hours of (current date)
set saytime to say "The time is" & currenthours & "The date is" & currentdate

I’m glad to see you experimenting. You don’t quite have the concept of handlers and of the scope of variables. As such I’ll point you to this article which explains those things.
http://macscripter.net/viewtopic.php?id=24727

And here’s a list of tutorials (which is where I got the above link) which can be found on this website. I suggest you start with the ones called “AppleScript Tutorial for Beginners”. That’s the set of tutorials I did when I first started learning applescript. They’re short so it doesn’t take long to work through one and they’ll help you build a solid foundation. Anyway, I hope it helps.
http://macscripter.net/viewtopic.php?id=25631

Thanks again! You rock! hahaha :smiley: