| |||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||
Print This Article REALbasic University: Column 101
OOP Intermission: iConversation Part TwoLast time we started a cool new project called iConversation. With it you'll be able to have a conversation with your Mac! We didn't quite finish it last time, so today we'll get it working.
iConversationAt the end of the last lesson we added a method, respond, but we didn't put any code in it. Let's add that now:
All this does is step through each command in theCommands array and see if it matches the command that was spoken. If it was, it saves the response into s and the stop state. The reponse is then spoken and if we're not supposed to stop, we push the "Start Listening" button again to restart the listening mode. Of course our array of commands, theCommands, is initially empty. We need some way to fill it. To make this iConversation flexible, I decided to store the commands in a simple text file. The file's format is easy: each line consists of a command, a tab character, and a response. If the response includes two equals signs ("==") that's a sign that it's a "stop" command (the command's stop property is set to true). So add a loadCommands method to Window1 (Edit menu, "New Method..."). It takes no parameters and returns nothing, so all you need is the name. Then put in this code for the routine:
While this looks long and complex, it's very simple. First we look for a file called "speech phrases.text" that's in the same folder as iConversation. Once we find it, we open it as a text file and read the contents into variable s. Next, we step through each line of s. For each line we enlarge our theCommands array and initialize a new speechCommandClass object. Since each line is divided into two items separated by a tab character, we use nthField to break theLine into the two parts. The first part is assigned to the current speechCommandClass object's command property, the second to the response property. We finish by examining the response property for the "==" text. If we find it, we set the stop property to true and we delete the "==" from the response text. Finally, we add the speech command to our phraseList listbox. If you run iConversation now, it still won't do much -- that's because we haven't called loadCommands! Open startButton and go its Open event and put in this code:
This first loads the speech commands, then checks to see make sure the theCommands array has stuff in it. If so, it greets the user, enables the "Start Listening" button, and begins the conversation. Otherwise it speaks an error message. Speaking of the error message -- you'll need the speech phrases file for this to work. You can download that here.
Running iConversationOnce you've got everything, you should be able to run the program and have a conversation with your computer. Here's what iConversation looks like while it's running. The listbox contains the commands it recognizes. If you tell Speech Recognition to show its command window (use the menu beneath the round speech recognition window), you'll see its list of commands matches iConversation's list, as well as a list of commands it has successfully recognized. ![]() As you can see, iConversation knows how to talk about the weather, among other topics. You can easily add more phrases and responses to its vocabulary simply by editing the "speech phrases.text" text file. Just remember to put only one command/response per line, and separate the command and the response with a tab character. Currently the responses are fixed, so you couldn't have the computer respond with the current time, for instance. But you could easily extend the program by adding in variables for dynamic information. For example, "#time#" could represent the time. Thus the computer's response could be:
Then, in the respond method, you'd just need to add some find/replace routines to search s for "#time#" and replace it with the current time. You could do this with all kinds of dynamic data, of course. Also, while iConversation's more of a demonstration project, there's no reason the same techniques couldn't be used to give your application true voice recognition capabilities. Perhaps the AppleScript approach wouldn't be appropriate for that, or possibly you could call the AppleScript via a thread to let your program continue to do other things while waiting for speech input. If you would like the complete REALbasic project file for this week's tutorial (including resources), you may download it here.
Next WeekBack to our OOP progress bar project!
LettersToday's letter is from David Jessup, who has a question about interapplication communication:
Are both of these apps ones you're writing in REALbasic? If so, this is fairly easy. You need to enable the receiving app to accept an Apple Event that lets you specify the text to put in the editField. Doing that isn't difficult, but it does require several steps. To summarize them:
To demonstrate this, I've created two REALbasic projects, receiver.rb and sender.rb. In Sender, we've got an editField and a pushButton. In the Action event of pushButton1 we put this code:
This creates a new Apple Event and loads it with the text of editField1. Note that the parameters for the newAppleEvent function are three strings which correspond to the event class, event ID, and the Creator code of the receiving application. In Receiver, I open the App object and in the HandleAppleEvent event I put in this code:
This checks to see what kind of Apple Event was sent. If the class and ID match what we're looking for, we then stick whatever text was passed into editField1. Easy! Note that for this example to work both projects must be compiled to built applications. This won't work if you just choose "Run" from the Debug menu. When you launch both apps, whatever text is in the editField of Sender gets sent to Receiver when you click the Send button. It looks like this: ![]() You can grab these two project files here. For more on this, you can check out Matt Neuburg's book (see link above) or issue 1.5 and 1.6 of REALbasic Developer magazine. Oh, and if you're trying to do this with a receiving app you didn't write, that would be more difficult. You'd be best off using an AppleScript to do it. Either way, the receiving app would have to have included support for modifying its editField: you can't script an unscriptable action. About the Column REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers. Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.) About the Author See the REALbasic University Archives
REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.
|
. |
| |||||||||||||||||||||||||