August 10, 2006

I'm briefly talking at WWDC Friday...

I'll be talking about Delicious Library's use of voice input and output in the Worldwide Developer's Conference at session 155, Let's Talk: Building Speech Technology into your UI, on Friday at 9AM. (That's in San Francisco, and if you don't have a ticket already you are boned.)

I know, 9AM... I won't be awake either, but I'm getting on stage, so you can at least show up and sleep in the audience. I'm kind of worried that, since it's the last day, there's going to be like three guys there. Seriously, the last day sucks.

My part will be brief, because, honestly, it was about three lines of code to integrate the speech stuff, which I think is the point. But if you want to say hi, that's where I'm at, dogg.


Here's the code I didn't have a chance to go over at the conference -- there really aren't any surprises here, but the point is that this is the actual, production code in a shipping app (Delicious Library v1.6):

Read Titles
- (void)speakTitle;
[self _vickiSay:title];
if (IsEmpty(title))

if ([title rangeOfString:@"Harry Potter"].location != NSNotFound)
[self performSelector:@selector(_whisper:) withObject:@"Voldemort"
else if ([title rangeOfString:@"Star Wars"].location != NSNotFound)
[self performSelector:@selector(_whisper:) withObject:
@"I AM YOUR FATHER!" afterDelay:7.0];


// Private speech

- (void)_whisper:(NSString *)speakString;
[self _say:(NSString *)speakString withVoice:@"Whisper"];
- (void)_fredSay:(NSString *)speakString;
[self _say:(NSString *)speakString withVoice:@"Fred"];
- (void)_vickiSay:(NSString *)speakString;
[self _say:(NSString *)speakString withVoice:@"Vicki"];
- (void)_say:(NSString *)speakString withVoice:(NSString *)voice;
if (!speechSynthesizer)
speechSynthesizer = [[NSSpeechSynthesizer alloc] initWithVoice:nil];
else if ([speechSynthesizer isSpeaking])

if (speakString == nil || [speakString length] == 0 || [[NSUserDefaults
standardUserDefaults] boolForKey:LILibraryDoNotSpeakPreferenceName])

[speechSynthesizer setVoice:[@""
[speechSynthesizer startSpeakingString:speakString];

Speak to Find Titles
- (void)_coalesceLibraryChanges:(NSNotification *)notification;
[NSObject cancelPreviousPerformRequestsWithTarget:self
selector:@selector(_setupSpeechRecognition) object:nil];
[self performSelector:@selector(_setupSpeechRecognition)
withObject:nil afterDelay:6.0];


// Private speech

- (void)_setupSpeechRecognition;
if ([[NSUserDefaults standardUserDefaults]
boolForKey:LISpeechRecognitionOffPreferenceName]) {
[speechRecognizer stopListening];
[speechRecognizer release];
speechRecognizer = nil;

if (!speechRecognizer) {
speechRecognizer = [[NSSpeechRecognizer alloc] init];
[speechRecognizer setDisplayedCommandsTitle:nil];
[speechRecognizer setListensInForegroundOnly:YES];
[speechRecognizer setDelegate:self];
[speechRecognizer startListening];

NSMutableArray *commands = [NSMutableArray array];
NSArray *items = [library items];
unsigned int itemIndex, itemCount = [items count];
for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {
LIMedia *item = [items objectAtIndex:itemIndex];
NSString *title = [item valueForKey:LIMediaTitleAttributeKey];
if (title != nil)
[commands addObject:title];
[speechRecognizer setCommands:commands];


// NSObject (NSSpeechRecognizerDelegate)

- (void)speechRecognizer:(NSSpeechRecognizer *)sender
NSMutableArray *matchingItems = [NSMutableArray array];
NSArray *items = [library items];
unsigned int itemIndex, itemCount = [items count];
for (itemIndex = 0; itemIndex < itemCount; itemIndex++) {
LIMedia *item = [items objectAtIndex:itemIndex];
NSString *title = [item valueForKey:LIMediaTitleAttributeKey];
if (title != nil && [title isEqualToString:command])
[matchingItems addObject:item];

[self showItems:matchingItems];

Thanks to Dr. Kim for letting me get up on stage (I'm an attention whore -- surprise!) and for giving me extra minutes to talk when I went super-long.



Anonymous Seth Willits said...

Well, shoot.... I wish I wasn't leaving...

August 10, 2006 10:25 PM

Blogger Patrick said...

I really enjoyed the Friday sessions I went to last year (heck the last session on Friday afternoon was probably the most valuable session of the week).

Having said that I didn't make a 9am session any day. I tried, I really did. Just didn't happen.

August 11, 2006 12:02 AM

Anonymous Derek said...

I was really expecting a more ground breaking technology than the new Leopard voice, so I'll be skipping it and going to the Ruby/Python session during the same time block.

For the record I don't like Python, but I may have to integrate it within my code thanks to certain people.

August 11, 2006 12:34 AM

Blogger Aaron Tait said...

I'll be there!

August 11, 2006 6:27 AM

Anonymous Justin Williams said...

I may show up. It's Friday though. Ive been trying to hunt you down and give you a MacZealots shirt all week, but your body guard keeps you well concealed.

August 11, 2006 7:40 AM

Anonymous Benjamin said...

The IB session at 9:00 surely will be more interesting. 

August 11, 2006 8:18 AM

Anonymous Anonymous said...

ill definately be there -Lemont

August 11, 2006 8:34 AM

Anonymous Anonymous said...

ill definately be there -Lemont

August 11, 2006 8:34 AM

Anonymous Lon Varscsak said...

I wish that had given you a little more time Wil! Good job though.

August 11, 2006 12:12 PM

Anonymous Oddy said...

I saw you talking! You're funny ;)

August 11, 2006 2:47 PM

Anonymous Julian Bennett Holmes said...

Haha, it's to bad I wasn't at WWDC.

I definetly would've come to your session.

August 12, 2006 7:06 PM

Anonymous Anonymous said...

I spy some easter eggs.

August 12, 2006 9:19 PM

Anonymous Michael James said...


You were an excellent addition to a surprisingly great session. I had never really considered Cocoa's speech abilities before, but I definitely will now!

I met you very briefly after the session. I was the one you gave that Lost Lakes book to. Sadly, US Airways had a problem locating my checked in bags and when they delivered them to me on Sunday all the paper items in the suitcase were moist (as if they sat outside all night and got morning dew on them) and the book was pretty much ruined.

On the other hand, if I had known you were an attention whore (your words), I would have thanked you for Delicious Library and this blog. But I didn't want to act like a total fanboy (but I am a fan of your work) and it looked like Len Case really wanted to talk to you, so I just went for the book.

August 14, 2006 7:27 AM

Anonymous Anonymous said...

What's wrong with being a fan?  I've been a fan of Wil's for quite some time.


August 18, 2006 2:28 AM

Anonymous michael james said...

Nothing wrong with being a fan, but I wasn't sure how it would go over.  Remember, I didn't know how much Wil appreciated attention.  I didn't want his first impression of me to be a negative one.

Well, now I know for next time.

August 19, 2006 12:37 AM

Blogger Evan Schoenberg said...

I'm curious.. why do you cast speakString, which is an NSString, to NSString? Is that part of your usual coding style or left over from a previous iteration of the code?

August 19, 2006 9:35 AM

Blogger Wil Shipley said...

Copy/paste error. Nice catch.

August 19, 2006 2:01 PM


Post a Comment

<< Home