<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-350232640321685673</id><updated>2012-02-12T09:37:44.192-08:00</updated><title type='text'>The SpeakRight Framework</title><subtitle type='html'>Building VoiceXML apps faster using reusable Java components.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-7867901215527399573</id><published>2008-02-01T08:52:00.000-08:00</published><updated>2008-02-01T09:16:28.444-08:00</updated><title type='text'>Bottom-up Programming</title><content type='html'>Peter Bell's &lt;a href="http://www.pbell.com/"&gt;blog&lt;/a&gt; is a great guide to domain-specific programming,  application frameworks, and DSLs.  His article &lt;a href="http://www.pbell.com/index.cfm/2007/1/24/Bottom-Up-Programming"&gt;Bottom-Up Programming&lt;/a&gt; really captures a style of programming I like.  It refers to Paul Graham article that contrasts the old top-down programming style of Structure Programming, and the bottom-up programming often used in LISP.  LISP, like Smalltalk, allows you to extend the language itself.  LISP programmers would simply add to the language as they needed new features or mechanisms.  The resulting solution grew from the bottom up until it could express cleanly and concisely what the domain problem required.&lt;br /&gt;&lt;br /&gt;This ties in to the Agile notion of "listening to the code".  Code a solution normally and then look at the code for common patterns.  Extract those into re-usable classes and components.  Repeat.  You end up with a framework for building a family of related programs.  Most programmers work on related products in a particular area (telephony, graphics, web commerce, whatever), so this framework-building is rarely wasted effort.  &lt;br /&gt;&lt;br /&gt;Bottom-up programming also ties into Dijkstra's notion that programmers produce about the same number of lines of code regardless of the language.  So the higher a level at which you can work, the more productive you can be.&lt;br /&gt;&lt;br /&gt;Speakright shares this philosophy.  Make a framework which lets programmers write speech apps at a higher level.  And able to extend the framework themselves.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-7867901215527399573?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/7867901215527399573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=7867901215527399573' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7867901215527399573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7867901215527399573'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2008/02/bottom-up-programming.html' title='Bottom-up Programming'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-8496967791601601809</id><published>2007-12-04T15:46:00.000-08:00</published><updated>2007-12-04T16:00:40.723-08:00</updated><title type='text'>The StringTemplate Template Engine</title><content type='html'>The &lt;a href="http://www.stringtemplate.org/"&gt;StringTemplate&lt;/a&gt; template engine is a popular choice for generating markup text in Java.  It comes from Terrence Parr, the inventor of ANTLR.&lt;br /&gt;&lt;br /&gt;SpeakRight uses StringTemplate (ST) for all its VoiceXML generation.  When a flow object is rendered, it is first converted into a SpeechPage object.  A SpeechPage is not VoiceXML-specific, and allows SpeakRight to output other formats such as SALT,  or whatever you want.   It's also the glue that ST requires. SpeechPages are rendered using one of the ISpeechPageWriter classes.  For testing, an HTML page writer is available.  The main page writer though is VoiceXMLPageWriter.&lt;br /&gt;&lt;br /&gt;VoiceXMLPageWriter into VoiceXML.  A StringTemplate file defines the format for prompts, grammars, fields, forms and other VoiceXML tags.  This gives a lot of flexibility.  If your VoiceXML platform has special requirements, simply modify the &lt;span style="font-weight: bold;"&gt;speakright.stg&lt;/span&gt; template file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-8496967791601601809?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/8496967791601601809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=8496967791601601809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8496967791601601809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8496967791601601809'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/12/stringtemplate-template-engine.html' title='The StringTemplate Template Engine'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2794106717839375091</id><published>2007-12-04T12:42:00.000-08:00</published><updated>2007-12-04T15:40:49.231-08:00</updated><title type='text'>Matt Raible on web frameworks</title><content type='html'>Matt Raible has a fascinating &lt;a href="http://parleys.com/display/PARLEYS/Comparing+Java+Web+Frameworks?showComments=true"&gt;video &lt;/a&gt;comparing web frameworks.  Comparisons are tricky since frameworks are changing rapidly, with multiple releases per year.  However, he makes an interesting aside about the (lack of) value of visual IDEs.  JSF comes with a drag-and-drop IDE that is "appealing to managers", but "if one wants to develop anything substantial,  we're going to have to get down and dirty with the code."&lt;br /&gt;&lt;br /&gt;I've been espousing a &lt;a href="http://speakrightframework.blogspot.com/2007/05/benefits-of-code-based-approach.html"&gt;code-based&lt;/a&gt; approach for speech applications for while.  Indeed that's the whole premise of the SpeakRight framework.  Any substantial app will use dynamically generated code, and not be pages of handwritten markup text.&lt;br /&gt;&lt;br /&gt;Things are a bit simpler for speech applications.  The following criteria for comparing web frameworks don't apply&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Bookmarkable URLs.&lt;/li&gt;&lt;li&gt;Avoiding the double-POST problem&lt;/li&gt;&lt;li&gt;AJAX&lt;/li&gt;&lt;li&gt;Massive scalability.  Web applications may involve millions of users but speech apps are still orders of magnitude smaller.&lt;/li&gt;&lt;li&gt;Page decoration.  The vast topic of graphical design doesn't exist in a speech app.  Persona is as close as one gets to "decoration".&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2794106717839375091?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2794106717839375091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2794106717839375091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2794106717839375091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2794106717839375091'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/12/matt-raible-has-fascinating-video.html' title='Matt Raible on web frameworks'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-3148638099809180369</id><published>2007-12-03T14:00:00.000-08:00</published><updated>2007-12-06T06:28:43.929-08:00</updated><title type='text'>NBest</title><content type='html'>NBest is a very useful feature for handling similar sounding words.  Normally a speech rec engine finds the grammar rule that is the best match for the user's speech utterance.  Large grammars can suffer from substitution errors where the wrong rule is matched: caller says "Boston" but the engine selects "Austin".  NBest helps the application sort out this type of ambiguity.&lt;br /&gt;&lt;br /&gt;When enabled, NBest is a request to the speech rec engine to return the top N matches, sorted in order of decreasing confidence level. N is usually a small number, such as 4.  Remember that the NBest value is a maximum; fewer results may be returned.&lt;br /&gt;&lt;br /&gt;In SpeakRight, NBest is enabled using the &lt;span style="font-weight: bold;"&gt;QuestionFlow &lt;/span&gt;method &lt;span style="font-weight: bold;"&gt;enableNBest.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;flow.enableNBest(4); //up to 4 results&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When the &lt;span style="font-weight: bold;"&gt;SRResults &lt;/span&gt;come back for that question, you can check for NBest results.  The &lt;span style="font-weight: bold;"&gt;SRResults &lt;/span&gt; method &lt;span style="font-weight: bold;"&gt;hasNBest &lt;/span&gt;which indicates that more than one result was returned.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;NBest Pruning&lt;/span&gt;&lt;br /&gt;The simplest thing an application can do, is check the NBest results in &lt;span style="font-weight: bold;"&gt;validateInput&lt;/span&gt;, and use additional application logic to select the most likely result.  This is called NBest pruning.  For example, if the user is asked for her account number, each result can be checked against the database.  If only one result is a valid account number, the application could assume that's what the caller said.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;String probableAccountNumber = "";&lt;br /&gt;int matches = 0;&lt;br /&gt;for (int i = 0; i &lt;&gt;&lt;br /&gt;String value = results.getNBestValue(i);&lt;br /&gt;if (CheckAccountNumber(value)) {   //check against the database&lt;br /&gt;probableAccountNumber = value;&lt;br /&gt;matches++;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;if (matches == 1) {&lt;br /&gt;results.replaceInput(probableAccountNumber); //let's use it!&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;NBest Confirmation&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;A more common use for NBest is to do confirmation.  When NBest results are returned, the application confirms each NBest result, stopping as soon as the user says "yes".&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: What city?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: Boston&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: &lt;span style="font-style: italic;"&gt;(returns 'Austin' and 'Boston' as NBest results)&lt;/span&gt; Do you want Austin?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: No&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: Do you want Boston?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: Yes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: Great. Flying to Boston on what date?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The application may still want to prune the NBest results, re-ordering the results according to the most likely answers.  This way the first confirmation question is more likely to be the correct one.  This is an important part of NBest -- using additional context information and application logic to improve on the speech rec engine's results.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Pass an &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;NBestConfirmerFlow &lt;/span&gt;&lt;span style="font-family:arial;"&gt;and the question flow object to a &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;ConfirmationWrapper &lt;/span&gt;&lt;span style="font-family:arial;"&gt;object that will manage the confirmation process.  It will ask the user to confirm values until the caller accepts one (by saying "yes" or whatever your confirmation grammar uses for acceptance).  If the caller says "no" to all NBest values, then the question is asked again, and the process repeats.  You can override &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;NBestConfirmerFlow &lt;/span&gt;&lt;span style="font-family:arial;"&gt;to adjust this behaviour.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Note that NBest confirmation is an extension of basic confirmation.  A &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;YesNoConfirmerFlow &lt;/span&gt;&lt;span style="font-family:arial;"&gt;confirms a single result, while a &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;NBestConfirmerFlow &lt;/span&gt;&lt;span style="font-family:arial;"&gt;confirms multiple results.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  ConfirmationWrapper cw = new ConfirmationWrapper(new AskCity(),&lt;br /&gt;               new NBestConfirmer("yesno.grxml"));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;Skip Lists&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;A skip list is a list of words that the application will not confirm because the caller has already rejected them.  This is an optional feature of &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;NBestConfirmerFlow&lt;/span&gt;&lt;span style="font-family:arial;"&gt;.  Enable it with the &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;enableSkipList &lt;/span&gt;&lt;span style="font-family:arial;"&gt;method.  If the caller says "no" to all NBest values, then the question is &lt;/span&gt;&lt;span style="font-family:arial;"&gt;asked again.  Before beginning confirmation, &lt;/span&gt;&lt;span style="font-weight: bold;font-family:arial;" &gt;NBestConfirmerFlow &lt;/span&gt;&lt;span style="font-family:arial;"&gt;will remove from the new NBest results any values that were rejected during the previous round of confirmation questions.  If this results in only a single NBest result, then there is no need for confirmation.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: What city?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: Crosston&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: (returns 'Austin' and 'Boston' as NBest results) Do you want Austin?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: No&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: Do you want Boston?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: No&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: (asking the question again) Let's try again. What city?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: Crosston&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: (returns 'Austin' and 'Crosston' and 'Aulston' as NBest results.  Austin is removed.)Do you want Crosston?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;H: yes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;C: Got it. Flying to Crosston on what date?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;...&lt;br /&gt;&lt;br /&gt;If you don't use a skip list, the application can infuriatingly confirm the same wrong result again and again.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;NBest With SROs&lt;/span&gt;&lt;br /&gt;SpeakRight Reusable Objects (SROs) are pre-built flow objects for gathering common data such as numbers, dates, etc.&lt;br /&gt;&lt;br /&gt;To enable NBest for an SRO, use its &lt;span style="font-weight: bold;"&gt;enableNBest &lt;/span&gt;method.  This will use an &lt;span style="font-weight: bold;"&gt;SROConfirmNBest &lt;/span&gt;confirmer object.  If you need to use a custom confirmer, call &lt;span style="font-weight: bold;"&gt;enableNBest &lt;/span&gt;followed by &lt;span style="font-weight: bold;"&gt;setConfirmer &lt;/span&gt;to pass in your custom confirmer.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SRONumber flow = new SRONumber("tickets", 1, 10);&lt;br /&gt;flow.enableNBest(4); //up to 4 results&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-3148638099809180369?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/3148638099809180369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=3148638099809180369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/3148638099809180369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/3148638099809180369'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/12/nbest.html' title='NBest'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2477396030361668974</id><published>2007-11-30T15:24:00.001-08:00</published><updated>2007-11-30T15:30:26.175-08:00</updated><title type='text'>Version 0.1.4 now available</title><content type='html'>The latest release is available &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=189014"&gt;here.&lt;/a&gt;  Transfer and Record are now supported.  There are several new flow object classes, including RawContentFlow (roll your own VoiceXML), and GotoUrlFlow (transfer to another VoiceXML application).&lt;br /&gt;&lt;br /&gt;Content-logging is a new feature that's helpful during development -- vxml content is dumped to text files so you can see what the rendered VoiceXML looks like. &lt;br /&gt;&lt;br /&gt;Some code refactoring has also been done.  Flow object classes are now in the package org.speakright.core.flows.&lt;br /&gt;&lt;br /&gt;Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2477396030361668974?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2477396030361668974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2477396030361668974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2477396030361668974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2477396030361668974'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/11/version-014-now-available.html' title='Version 0.1.4 now available'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-8640665686257116712</id><published>2007-06-14T10:20:00.000-07:00</published><updated>2007-12-06T06:45:02.019-08:00</updated><title type='text'>Initialization</title><content type='html'>SpeakRight apps normally run in three different environments: in a JUnit test, in the interactive tester, and most importantly in a servlet.  You can avoid problems by creating a single piece of initialization code that is used across all environments.   This pace is called the &lt;span style="font-style: italic;"&gt;app factory.  &lt;/span&gt;&lt;span&gt;It should be &lt;/span&gt;derived from &lt;span style="font-weight: bold;"&gt;SRFactory&lt;/span&gt;, which performs standard initialization.&lt;br /&gt;&lt;br /&gt;Your class should override &lt;span style="font-weight: bold;"&gt;onCreateRunner &lt;/span&gt;and &lt;span style="font-weight: bold;"&gt;onInitRunner &lt;/span&gt;to do additional initialization, such as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; create and attach a model object&lt;br /&gt;&lt;/li&gt;&lt;li&gt; register prompt file(s)&lt;/li&gt;&lt;li&gt; set the extension point factory&lt;/li&gt;&lt;li&gt;other things.   For example, the SimpsonsDemo app records votes in a text file, and its Voting object needs to be initialized with the path&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Initialization is done using the &lt;span style="font-weight: bold;"&gt;createRunner &lt;/span&gt;method of &lt;span style="font-weight: bold;"&gt;SRFactory&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;   public SRRunner createRunner(String &lt;span style="font-style: italic;"&gt;projectDir&lt;/span&gt;, String &lt;span style="font-style: italic;"&gt;returnUrl&lt;/span&gt;, String &lt;span style="font-style: italic;"&gt;baseUrl&lt;/span&gt;, ISRServlet &lt;span style="font-style: italic;"&gt;servlet&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-style: italic;"&gt;projectDir &lt;/span&gt;is a path to the application's base directory, which usually has sub-directories audio, grammar, and sro.&lt;br /&gt;&lt;br /&gt;The two URLs are only needed in a servlet environment.  &lt;span style="font-style: italic;"&gt;returnUrl &lt;/span&gt;is the URL that the VoiceXML page should postback to.  &lt;span style="font-style: italic;"&gt;baseUrl &lt;/span&gt;is used to generate URLs for audio and grammars.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;servlet &lt;/span&gt;can be null.  It's an extension point that allows the servlet to do extra initialization.&lt;br /&gt;&lt;br /&gt;Now let's look at each environment in turn.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;JUnit&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;In a unit test, the dependencies can be visualized like this, from top to bottom:&lt;br /&gt;&lt;br /&gt;JUnit test class&lt;br /&gt;App (your callflow)&lt;br /&gt;SRRunner&lt;br /&gt;SRFactory or your derived class&lt;br /&gt;SRConfig&lt;br /&gt;&lt;br /&gt;Use your app factory to create a runner&lt;br /&gt;&lt;blockquote&gt;        AppFactory factory = new AppFactory();&lt;br /&gt;    SRRunner run = factory.createRunner();&lt;br /&gt;&lt;/blockquote&gt;Then run your application using the &lt;span style="font-weight: bold;"&gt;start &lt;/span&gt;and &lt;span style="font-weight: bold;"&gt;proceed&lt;/span&gt; methods of &lt;span style="font-weight: bold;"&gt;SRRunner&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;If your app uses properties in the srf.properties file, you need to initialize &lt;span style="font-weight: bold;"&gt;SRConfig&lt;/span&gt; first.  JUnit 4 has a per-class initializer called @BeforeClass&lt;br /&gt;&lt;br /&gt;@BeforeClass static public void redirectStderr() {&lt;br /&gt;    SRConfig.init("C:\\source\\app2\\", "srf.properties");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Interactive tester&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The interactive tester is a console app.  It's The dependencies can be visualized like this, from top to bottom:&lt;br /&gt;&lt;br /&gt;App (your callflow)&lt;br /&gt;SRInteractiveTester&lt;br /&gt;SRRunner&lt;br /&gt;SRFactory or your derived class&lt;br /&gt;SRConfig&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SRInteractiveTester &lt;/span&gt;inits &lt;span style="font-weight: bold;"&gt;SRConfig &lt;/span&gt;for you.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;        SRInteractiveTester tester = new SRInteractiveTester();&lt;br /&gt;&lt;br /&gt;    AppFactory factory = new AppFactory();&lt;br /&gt;    SRRunner runner = factory.createRunner(appDir, "http://def.com", "", null);&lt;br /&gt;&lt;br /&gt;App app = new App();&lt;br /&gt;    tester.init(app, run);&lt;br /&gt;tester.run();&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Servlet&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;In a servlet, the dependencies can be visualized like this, from top to bottom:&lt;br /&gt;&lt;br /&gt;Servlet&lt;br /&gt;App (your callflow)&lt;br /&gt;SRRunner&lt;br /&gt;SRServletRunner&lt;br /&gt;SRFactory or your derived class&lt;br /&gt;SRConfig&lt;br /&gt;&lt;br /&gt;In a servlet the &lt;span style="font-weight: bold;"&gt;SRServletRunner &lt;/span&gt;class is used.  You pass your app factory and it does initialization, including &lt;span style="font-weight: bold;"&gt;SRConfig&lt;/span&gt;.  The &lt;span style="font-weight: bold;"&gt;SRRunner&lt;/span&gt;'s project directory is set to the directory corresponding to the web apps' "/" url.&lt;br /&gt;&lt;br /&gt;The code in &lt;span style="font-weight: bold;"&gt;doGet &lt;/span&gt;should be&lt;br /&gt;&lt;blockquote&gt;        SRServletRunner runner = new SRServletRunner(new AppFactory(), null, request, response, "GET");&lt;br /&gt;&lt;br /&gt;    if (runner.isNewSession()) {&lt;br /&gt; SRRunner run = runner.createNewSRRunner(this);&lt;br /&gt;   &lt;br /&gt;            IFlow flow = new App();&lt;br /&gt;            runner.startApp(flow);&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt; runner.continueApp();&lt;br /&gt;    }&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The code in &lt;span style="font-weight: bold;"&gt;doPost &lt;/span&gt;should be&lt;br /&gt;&lt;blockquote&gt;        SRServletRunner runner = new SRServletRunner(new AppFactory(), null, request, response, "POST");&lt;br /&gt;&lt;br /&gt;    if (runner.isNewSession()) {&lt;br /&gt; //err!!&lt;br /&gt;            runner.log("can't get new session in a POST!!");&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt; runner.continueApp();&lt;br /&gt;    }&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;SRConfig&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SRConfig &lt;/span&gt;provides access to an srf.properties file.  Properties are often used by the constructors of flow objects.  Therefore it's important to initialize &lt;span style="font-weight: bold;"&gt;SRConfig &lt;/span&gt;early:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;SRConfig.init(path, "srf.properties");&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;For console apps or JUnit, a hard-coded path is used.  For servlets, this is done for you by SRServletRunner, which uses the directory corresponding to the web app's "/" base url.&lt;br /&gt;&lt;br /&gt;Currently the SpeakRight framework itself does not use any properties, but applications are free to.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-8640665686257116712?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/8640665686257116712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=8640665686257116712' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8640665686257116712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8640665686257116712'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/06/initialization.html' title='Initialization'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-4458942859258384809</id><published>2007-05-24T09:49:00.001-07:00</published><updated>2007-12-03T14:45:37.980-08:00</updated><title type='text'>List of Flow Objects</title><content type='html'>Flow objects are the building blocks of SpeakRight applications.  Here is the list of available objects:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;BranchFlow  &lt;/span&gt;Performs branching in the callflow based on an application-defined condition&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;ChoiceFlow  &lt;/span&gt;Branches based on user input, such as in a menu&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;DisconnectFlow  &lt;/span&gt;Hangs up the call&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;FlowList  &lt;/span&gt;a sequence of flow objects, optionally ending with an AppEvent&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;GotoUrlFlow  &lt;/span&gt;Redirects to an external URL&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;LoopFlow  &lt;/span&gt;Iterates over a sequence of sub-flows&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;NBestConfirmerFlow &lt;/span&gt;confirms NBest results&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;PromptFlow &lt;/span&gt;Plays one or more prompts&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;QuestionFlow  &lt;/span&gt;Asks the user a question.  Has built-in error retries for silence and nomatch.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;RawContentFlow  &lt;/span&gt;Ouput raw VoiceXML&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;RecordAudioFlow  &lt;/span&gt;record the caller's voice to an audio file.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;SRApp  &lt;/span&gt;The root flow object&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;TransferFlow  &lt;/span&gt;Transfer the call&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;YesNoConfirmerFlow &lt;/span&gt;used to confirm a single result&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Additional flow objects can be created by implementing the &lt;span style="font-weight: bold;"&gt;IFlow &lt;/span&gt;interface.&lt;br /&gt;&lt;br /&gt;There are also &lt;a href="http://speakrightframework.blogspot.com/2007/04/speakright-reusable-objects-sros.html"&gt;SROs &lt;/a&gt;(SpeakRight Reusable Objects) which you can use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-4458942859258384809?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/4458942859258384809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=4458942859258384809' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4458942859258384809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4458942859258384809'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/list-of-flow-objects.html' title='List of Flow Objects'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-4787241389033199545</id><published>2007-05-24T08:47:00.001-07:00</published><updated>2007-05-24T09:08:42.663-07:00</updated><title type='text'>Call Control</title><content type='html'>The focus of SpeakRight is to be a framework for voice user interfaces.  As such, it's support for call control is fairly limited.  Consider using CCXML for applications with heavy use of call control.  Or the RawContentFlow to generate platform-specific transfer and conferencing features.&lt;br /&gt;&lt;br /&gt;SpeakRight catches the disconnect event (usually &lt;span style="font-style: italic;"&gt;connection.disconnect&lt;/span&gt;) in order to do a final postback.  This results in the DISCONNECT event being thrown and &lt;span style="font-weight: bold;"&gt;onDisconnect &lt;/span&gt;being invoked.  SRApp provides a default handler for this.&lt;br /&gt;&lt;br /&gt;There are a number of call control flow objects.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;DisconnectFlow&lt;br /&gt;&lt;/span&gt;This flow object plays a final prompt and hangs up.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;SROTransferCall&lt;/span&gt;&lt;br /&gt;This flow object transfers the call using one of the VoiceXML 2.1 transfer types: Blind, Bridged, or Consultation.   The specified destination parameter is a string, such as&lt;br /&gt;&lt;blockquote&gt;"tel:+2560001112222"&lt;br /&gt;&lt;/blockquote&gt;The format of the dial string is often platform specific.&lt;br /&gt;&lt;br /&gt;TransferFlow has two prompts.  An initial prompt called &lt;span style="font-style: italic;"&gt;main&lt;/span&gt; is played before the transfer is initiated.  A &lt;span style="font-style: italic;"&gt;transferFailed&lt;/span&gt; prompt is played if the transfer fails to complete.  Both these prompts can be overriden in an app-specific prompt XML file.&lt;br /&gt;&lt;br /&gt;If the transfer fails because, for example, the destination is busy, then &lt;span style="font-weight: bold;"&gt;onTransferFailed &lt;/span&gt;is invoked. It plays the &lt;span style="font-style: italic;"&gt;transferFailed&lt;/span&gt; prompt.  Or you can override &lt;span style="font-weight: bold;"&gt;onTransferFailed &lt;/span&gt;and provide your own behaviour.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;TransferFlow&lt;br /&gt;&lt;/span&gt;This flow object is a low-level object.  We recommend the use of SROTransferCall instead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;RawContentFlow&lt;br /&gt;&lt;/span&gt;This flow object is an escape hatch.  The application can supply any VoiceXML it likes.  RawContentFlow may be useful for invoking platform-specific call control features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-4787241389033199545?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/4787241389033199545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=4787241389033199545' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4787241389033199545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4787241389033199545'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/call-control.html' title='Call Control'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-1968747481358803421</id><published>2007-05-17T08:26:00.000-07:00</published><updated>2007-11-30T15:37:01.116-08:00</updated><title type='text'>Optional Sub-Flow Objects</title><content type='html'>It's common in a speech application for some sections of the callflow to be optional.  &lt;span style="font-style: italic;"&gt;if the user is a preferred customer do X.  &lt;/span&gt;Or &lt;span style="font-style: italic;"&gt;if the app has forceLogin enabled then do Y.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Applications can simply create or not create certain flow objects based on the required logic.  However, an alternative solution is provided called &lt;span style="font-style: italic;"&gt;optional sub-flows.  &lt;/span&gt;The BasicFlow and LoopFlow classes have been enhanced.  The flow objects they contain (called sub-flows) can indicate that they don't wish to run by returning false from &lt;span style="font-weight: bold;"&gt;shouldExecute&lt;/span&gt;.  When this occurs, the sub-flow is skipped and the next sub-flow is executed.&lt;br /&gt;&lt;br /&gt;The advantage of optional sub-flows is that the decision on whether to run or not can be deferred until a sub-flow is executed.  The initialization code doesn't need to handle this.&lt;br /&gt;&lt;br /&gt;However there are a restrictions: &lt;span style="font-style: italic;"&gt;the final sub-flow cannot be optional.  &lt;/span&gt;Because if the final sub-flow returns null from its &lt;span style="font-weight: bold;"&gt;getFirst&lt;/span&gt;, there's nothing to execute.&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Example code that creates the callflow using a BasicFlow object:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;//callflow creation..&lt;br /&gt;BasicFlow flow = new BasicFlow();&lt;br /&gt;              flow.add(new PromptFlow("Welcome"));&lt;br /&gt;          flow.add(new RegisterUser());&lt;br /&gt;          flow.add(new MainMenu());&lt;br /&gt;              app.add(flow);&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;And the class definition for the optional sub-flow looks like this:&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;class RegisterUser extends BaseSROQuestion {&lt;br /&gt;                  public Model M;&lt;br /&gt;&lt;br /&gt;@Override public boolean shouldExecute() {&lt;br /&gt;return M.userHasRegistered;&lt;br /&gt;}&lt;br /&gt;//..rest of class definition omitted..&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;Note&lt;/span&gt;.  I'm not completely happy with this feature.  It's handy but the cant-be-last restriction will be easy to forget and will only fail at runtime.  Full test coverage is required!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-1968747481358803421?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/1968747481358803421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=1968747481358803421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/1968747481358803421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/1968747481358803421'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/optional-sub-flow-objects.html' title='Optional Sub-Flow Objects'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-8786308707553585524</id><published>2007-05-16T07:23:00.000-07:00</published><updated>2007-12-04T16:08:29.239-08:00</updated><title type='text'>Supported Platforms</title><content type='html'>SpeakRight has been tested on these platforms:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Voxeo Evolution (free hosting site http://community.voxeo.com/). VoiceCenter 5.5&lt;/li&gt;&lt;li&gt;Voxeo Prophecy platform version 8.0 beta&lt;/li&gt;&lt;/ul&gt;The main mechanism for porting to a new framework is to customize the template file; see &lt;a href="http://speakrightframework.blogspot.com/2007/12/stringtemplate-template-engine.html"&gt;StringTemplate template engine&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-8786308707553585524?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/8786308707553585524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=8786308707553585524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8786308707553585524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8786308707553585524'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/supported-platforms.html' title='Supported Platforms'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-8380625423331600968</id><published>2007-05-16T07:12:00.000-07:00</published><updated>2007-12-04T16:06:04.440-08:00</updated><title type='text'>VoiceXML Tags Supported</title><content type='html'>Here's an alphabetical list of VoiceXML tags supported by SpeakRight&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;assign &lt;/span&gt;&lt;span style="font-style: italic;"&gt;name expr     &lt;/span&gt;used to track dialog state&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;audio &lt;/span&gt;&lt;span style="font-style: italic;"&gt;src                   &lt;/span&gt;play audio file&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;block&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;break &lt;/span&gt;&lt;span style="font-style: italic;"&gt;time                 &lt;/span&gt;time is in msec&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;catch &lt;/span&gt;&lt;span style="font-style: italic;"&gt;connection.disconnect  &lt;/span&gt;So app gets a final postback&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;disconnect&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;exit&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;field &lt;/span&gt;&lt;span style="font-style: italic;"&gt;name&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;filled&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;form&lt;/span&gt;                            one per page&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;goto &lt;/span&gt;&lt;span style="font-style: italic;"&gt;next  &lt;/span&gt;To goto an external URL&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;grammar &lt;/span&gt;&lt;span style="font-style: italic;"&gt;type src    &lt;/span&gt;type can be "text/gsl", "application/srgs+xml", or"application/srgs".&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;noinput &lt;/span&gt;&lt;span style="font-style: italic;"&gt;count bargein &lt;/span&gt;main prompt(s), one per escalation&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;nomatch &lt;/span&gt;&lt;span style="font-style: italic;"&gt;count bargein &lt;/span&gt;main prompt(s), one per escalation&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;prompt &lt;/span&gt;&lt;span style="font-style: italic;"&gt;count bargein &lt;/span&gt;main prompt(s), one per escalation&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;submit &lt;/span&gt;&lt;span style="font-style: italic;"&gt;next namelist method&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;transfer&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;type dest connecttimeout&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;var &lt;/span&gt;&lt;span style="font-style: italic;"&gt;name expr     &lt;/span&gt;used to track dialog state&lt;/li&gt;&lt;/ul&gt;In addition, the RawContentFlow can be used by an app to output custom VoiceXML.  It's useful for features not yet supported by SpeakRight.&lt;br /&gt;&lt;br /&gt;You can customize the VoiceXML; see the &lt;a href="http://speakrightframework.blogspot.com/2007/12/stringtemplate-template-engine.html"&gt;StringTemplate template engine&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-8380625423331600968?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/8380625423331600968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=8380625423331600968' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8380625423331600968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8380625423331600968'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/voicexml-tags-supported.html' title='VoiceXML Tags Supported'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-7609569896818970549</id><published>2007-05-10T10:42:00.000-07:00</published><updated>2007-05-10T10:44:10.387-07:00</updated><title type='text'>Version 0.0.3 Released</title><content type='html'>Latest code drop is available at SourceForge (see Download link on the left).  The project has been elevated to alpha status and can be used to build some real apps.  The SimpsonsDemo app is an example of this, and is included as part of the release.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-7609569896818970549?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/7609569896818970549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=7609569896818970549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7609569896818970549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7609569896818970549'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/version-003-released.html' title='Version 0.0.3 Released'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-6217765756108129159</id><published>2007-05-03T08:43:00.000-07:00</published><updated>2007-05-03T09:02:35.554-07:00</updated><title type='text'>Automated Testing</title><content type='html'>Computers are good at doing repetitive work.  Few things are more repetitive than testing software -- so let the computer do it!&lt;br /&gt;&lt;br /&gt;SpeakRight provides an automated tester SRAutoTester.  It runs your callflow in a test harness where user input comes from strings that you provide.  It checks the progress through the callflow to validate the application logic.  Tests can be run directly on a developer's machine, no VoiceXML platform is needed.&lt;br /&gt;&lt;br /&gt;SRAutoTester uses the same test harness as SRInteractiveTester, so you can test manually (using the keyboard) and auto-test, and vice versa.&lt;br /&gt;&lt;br /&gt;The format of the string you give is a set of commands separated by semi-colons, where each command's format is: &lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;"&gt;cmd[~ExpectedCurrentFlowObject]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The commands are&lt;br /&gt;&lt;ul&gt;&lt;li&gt;    "e"  echo. toggle echo to log of VoiceXML on/off&lt;/li&gt;&lt;li&gt;"g" go. simulate the current VoiceXML page ending and posting back.  Causes SpeakRight to proceed to the next flow object.  Can contain user input, such as "go chicago" or if a slot is set use ":" like this "go city:chicago"&lt;/li&gt;&lt;li&gt;"q" quit&lt;/li&gt;&lt;/ul&gt;Let's do a quick example.  An app begins with a welcome prompt then asks for user id and password.  If the user input is a valid login then the app proceeds to "MainMenu" otherwise it plays "LoginFailed".&lt;br /&gt;&lt;br /&gt;The commands for testing a good login are: &lt;span style="font-style: italic;"&gt;g;g 4552;g 1234;g~MainMenu;q&lt;/span&gt;&lt;br /&gt;Let's break that down:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"g" means run the first flow object, which is the welcome prompt&lt;/li&gt;&lt;li&gt;"g 4552" is the user id&lt;/li&gt;&lt;li&gt;"g 1234" is the password&lt;/li&gt;&lt;li&gt;"g~MainMenu" validates that we're at the MainMenu flow object&lt;/li&gt;&lt;/ul&gt;To test a bad login: &lt;span style="font-style: italic;"&gt;g;g 9999;g 9999;g~LoginFailed;q&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;Note that these tests are high-level tests of the callflow.  They allow requirements such as "A bad login does not proceed to the Main Menu".  Testing the details of the VUI prompts and grammars need to be done as well; either with another SpeakRight tester (TBD) or on the VoiceXML platform itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-6217765756108129159?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/6217765756108129159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=6217765756108129159' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/6217765756108129159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/6217765756108129159'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/automated-testing.html' title='Automated Testing'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-5213455773297883841</id><published>2007-05-02T17:36:00.000-07:00</published><updated>2007-12-04T12:59:29.348-08:00</updated><title type='text'>Benefits of a Code-Based Approach</title><content type='html'>Sometime in the 1980s, voice applications (called &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;IVRs&lt;/span&gt;) appeared.  And &lt;span style="font-style: italic;"&gt;drag-and-drop&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;toolkits&lt;/span&gt; followed.  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;IVR&lt;/span&gt; apps were structured much like a flowchart since the user navigated the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;callflow&lt;/span&gt; using one of 12 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;DTMF&lt;/span&gt; keys.  A visual programming model seemed appropriate for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;IVR&lt;/span&gt; development.  The tools work well on small projects of up to fifty nodes or so.  On larger apps the visual approach breaks down.  It become hard to navigate an app with hundreds or thousands of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;nodes&lt;/span&gt;.  Code changes become tedious; try changing the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;MaxRetries&lt;/span&gt; value from 3 to 4 in all &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;GetDigits&lt;/span&gt; nodes in a 200 node app!  Also, the architectural weakness of visual programming becomes more apparent as size increases.  It's programming model is really a 1960s FORTRAN model based on &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;GOTOs&lt;/span&gt; and global variables.  Structured programming features, let alone object-oriented features are simply not supported.&lt;br /&gt;&lt;br /&gt;Drag-and-drop &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;toolkits&lt;/span&gt; remain viable for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;DTMF&lt;/span&gt; apps because the apps are simple.  Speech applications are much more complicated that the equivalent &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;DTMF&lt;/span&gt; app.  There are roughly nine times as many prompts (escalated versions of the main prompt and silence and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;nomatch&lt;/span&gt; prompts).  Confirmation needs to be done since speech recognition is never 100% accurate.  Lastly, speech apps are more complicated because, released from the limitations of 12 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;DTMF&lt;/span&gt; keys, they try to do more.   This complexity means that speech apps need a more powerful development environment, such as the Java programming language.&lt;br /&gt;&lt;br /&gt;The first wave of speech applications were written directly in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;VoiceXML&lt;/span&gt;.  Again this is simple for small apps but doesn't scale.  A large app has many &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;voicexml&lt;/span&gt; files, and the relationship between them is not clearly shown.  A &lt;span style="font-style: italic;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;login&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;vxml&lt;/span&gt;&lt;/span&gt; file may submit its results to &lt;span style="font-style: italic;"&gt;main_menu.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;vxml&lt;/span&gt;&lt;/span&gt;, but that is not apparent in looking at a list of files.  Raw &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;VoiceXML&lt;/span&gt; does not have any modern programming constructs such as inheritance or design patterns.  Lastly, unit testing and debugging are difficult.&lt;br /&gt;&lt;br /&gt;This brings us to the final option: a code-based approach.  &lt;span style="font-style: italic;"&gt;Write the application in Java&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;IDEs&lt;/span&gt; are powerful&lt;/span&gt;&lt;br /&gt;Use the full power of a good &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;IDE&lt;/span&gt; with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;refactoring&lt;/span&gt; support, code assist (AKA &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;Intellisense&lt;/span&gt;), unit testing, debugging, and integrated source control.  The Eclipse &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;IDE&lt;/span&gt;, for example, is used by millions of programmers.  It will be improved and extended at a far faster rate than any proprietary toolkit.  And Eclipse is free.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Better Debugging&lt;/span&gt;&lt;br /&gt;Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;IDEs&lt;/span&gt; have real debuggers.  Enough said.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Better Testing&lt;/span&gt;&lt;br /&gt;Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;IDEs&lt;/span&gt; have excellent unit testing.  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;SpeakRight&lt;/span&gt; provides a keyboard-based interactive tester, and an HTML mode for executing an app using an ordinary web browser (HTML is generated instead of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;VXML&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;More tools&lt;/span&gt;&lt;br /&gt;There are source code tools for code coverage, profiling, generating documentation and design diagrams.  Source code control tools allow important questions such as 'what's changed since last week' to be answered.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Code is flexible&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Source code is extremely flexible.  Unlike drag-and-drop tools that offer only a few levels of granularity, code can be organized and combined in many ways.  Let's look at the ways code can be used.&lt;br /&gt;&lt;br /&gt;See also &lt;a href="http://speakrightframework.blogspot.com/2007/12/matt-raible-has-fascinating-video.html"&gt;Matt Raible On Web Frameworks&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Configuration&lt;/span&gt;&lt;br /&gt;An object can be configured by settings its properties.  This allows re-usable objects to be customized for each use.  The customization can be done in code&lt;br /&gt;&lt;br /&gt;flow.m_&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;maxAttempts&lt;/span&gt; = 4;&lt;br /&gt;&lt;br /&gt;or it can come from external configuration files.  &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;SpeakRight&lt;/span&gt; allows prompts and grammars to reside in XML files that can be changed post-deployment without having to rebuild the app.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sub-classing&lt;/span&gt;&lt;br /&gt;The DRY principle is Don't Repeat Yourself.  DRY reduces the amount of source code and makes modifications simpler.  Java inheritance is one way of centralizing common code.  Any class deriving from a base class gets the base classes' behaviour automatically.  In our example concerning &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;GetDigit&lt;/span&gt; nodes, the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;MaxRetries&lt;/span&gt; value can be defined a single place (in the base class).  Changing the value in the base class causes the change to ripple down to all derived classes.&lt;br /&gt;&lt;br /&gt;Java inheritance is flexible because values or behaviour can be overridden at any point in the class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;heirarchy&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Composition&lt;/span&gt;&lt;br /&gt;Composition is the process of assembling together objects into useful components.  Modern frameworks make much use of interfaces and &lt;span style="font-style: italic;"&gt;extension points&lt;/span&gt;.  An extension point allows behaviour to be changed by plugging in different implementations of it.  In &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;SpeakRight&lt;/span&gt;, confirmation is an extension point where different types of confirmation can be plugged-in: yes-no confirmation, confirm-and-correct confirmation, and implicit &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;confimation&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Extension points increase re-use because the number of options multiply.  If you have four types of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;GetNumber&lt;/span&gt; objects and three types of confirmation, you have twelve types of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;GetNumber-And-Confirm&lt;/span&gt; behaviour to choose from.&lt;br /&gt;&lt;br /&gt;A menu is another example of an extension point.  A menu is basically a question followed by a switch statement.  Both are extension points that allow flexible menus to be created that still share the common base code.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;" class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;Refactoring&lt;/span&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;Refactoring&lt;/span&gt; is the process of improving code quality without changing the external behaviour.  Common code can be pulled into methods or classes.  Interfaces and extension points can be added to increase the flexibility of a class. Code can be packaged into &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;namespaces&lt;/span&gt; and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;libraries&lt;/span&gt;. Inherited behaviour can be overridden.&lt;br /&gt;&lt;br /&gt;A code-based approach allows all these modern software development techniques to be applied to speech apps.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Changing The Framework&lt;/span&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;SpeakRight&lt;/span&gt; is open-source so everything is available to you for modification.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Everything is a Flow Object&lt;/span&gt;&lt;br /&gt;In &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;SpeakRight&lt;/span&gt;, the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;callflow&lt;/span&gt; is built out of flow objects.  Everything from a low-level "yes-no" question, to a form with multiple fields, up to the app itself are flow objects.&lt;br /&gt;&lt;br /&gt;Flow objects participate in generating content (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;VoiceXML&lt;/span&gt;).  A flow object is notified of each prompt being rendered, and allowed to modify it.  Flow objects can control which &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;VoiceXML&lt;/span&gt; is generated, and if needed, the entire &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;VoiceXML&lt;/span&gt; rendering can be replaced (it's another extension point).&lt;br /&gt;&lt;br /&gt;Flow objects participate in deciding the execution path through the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;callflow&lt;/span&gt;.  Because they return an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;IFlow&lt;/span&gt; object to be run next, it's easy to inject additional behaviour when needed.  Confirmation is done this way.&lt;br /&gt;&lt;br /&gt;Consider a VUI dialog for traversing a list of items.  The common behaviour is the commands "next" and "previous" (and possibly "first" and "last").  These move to a new item and say its value, or play an error message if the end of the list has been reached.  List traversal is a common VUI feature, but difficult to make into a re-usable artifact in a non-code-based approach.  With code however, this is a standard sort of OO design task.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Prompts and grammars are made into fields.  Default values are provided but can be overridden or configured using getter and setter methods.&lt;/li&gt;&lt;li&gt;The list is a generic Java Collection, allowing it to be a list of anything.  An IItemFormatter interface is created so the rendering of a Java object (string, integer, XML, whatever) into a prompt becomes an extension point.  The default formatter just uses toString.&lt;/li&gt;&lt;li&gt;SpeakRight's flow objects are pause-able.  This means that a list traverser can pause while another VUI dialog runs, and resume when it finishes.  A list traverser can now be a main menu for an app that works on a list of items (such as flights to select from).  Additional commands can be added, so that in addition to the traversal commands, the menu can accept additional commands such as "details", "accept", and "search".  All of this is built on top of the existing list traversal class; no code duplication is required.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;And unlike a drag-and-drop toolkit where a list traversal node has a fixed set of features, there are no restrictions in a code-based approach.  You want "next" to wrap-around when it reaches the end of the list?  No problem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Less Code, Less Testing&lt;/span&gt;&lt;br /&gt;A code-based approach, by promoting re-use and the DRY principle, reduces the size of the application.  This has many benefits:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Faster development.  Less time spent in tedious repetitive work.&lt;/li&gt;&lt;li&gt;Easier to change.  A class hierarchy is like the paragraph styles in a word processor.  Rather than sprinkling formatting all over the document, it's kept in a few styles (base classes) where it's easily managed and changed.&lt;/li&gt;&lt;li&gt;Consistent Voice User Interface.  Shared code leads to shared behaviour, which leads to a consistent user interface.&lt;/li&gt;&lt;li&gt;Reduced testing.  This is a huge gain.  When common code is used, it only needs to be tested once, even though its used multiple times in the app.  For example, yes-no confirmation can be plugged in to the confirmation extension point of a flow object.  Once you've validated that it works in one flow object, there's no need to test all other flow objects since they share the same (base class) code.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Flexible Development&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;A code-based approach lacks the artificial boundaries of drag-and-drop &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;toolkits&lt;/span&gt;.  Development can begin by using existing classes and configuring them as needed.  When you find the same &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;VUI&lt;/span&gt; dialogs appearing in multiple places, sub-classing can be used to centralize a common configuration, such as a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;MyGetPassword&lt;/span&gt; class.  As more new classes are created they can be combined into a class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;heirarchy&lt;/span&gt; in order to share common code, with extension points added where variability is needed.  When classes are re-used in other projects they can be packaged as a library.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-5213455773297883841?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/5213455773297883841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=5213455773297883841' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5213455773297883841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5213455773297883841'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/benefits-of-code-based-approach.html' title='Benefits of a Code-Based Approach'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2029158781982696505</id><published>2007-05-02T06:21:00.000-07:00</published><updated>2007-12-06T06:47:14.353-08:00</updated><title type='text'>Prompt Ids and Prompt XML Files</title><content type='html'>Tuning a speech application often involves changing prompts, to re-word a question or improve an error message.  This should be possible without having to rebuild the app.  Speakright uses &lt;span style="font-style: italic;"&gt;prompt ids &lt;/span&gt;to provide this feature.&lt;br /&gt;&lt;br /&gt;A prompt id is a ptext item beginning with "id:", such as "id:outOfRange".  When the prompt is rendered, a set of XML files are searched to find an entry for that id.  The entry looks like this:&lt;br /&gt;&lt;blockquote&gt;  &amp;lt;prompt name="outOfRange" def="true"&amp;gt;That value is out of range. &amp;lt;/prompt&amp;gt;&lt;br /&gt;&lt;/blockquote&gt; The prompt text for the id is a full PText; it can contain references to other ids, for example.  It's an error if a prompt id cannot be found in any of the XML files.&lt;br /&gt;&lt;br /&gt;Which set of XML files? Well you get to define them using SRRunner.registerPromptFile, usually one per app.  The framework itself may register some; each SRO has its own prompt XML.  The registration may be permanent (for the life of the app), or temporary (for the current flow object execution).  The list of XML files is searched in reverse order so that your XML files are searched first, and framework XML files searched last.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Prompt Groups&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another useful feature is the ability to build an app using rough prompts, and then finalize the prompts later without having to do any code changes.  &lt;span style="font-style: italic;"&gt;Prompt Groups &lt;/span&gt;does this.  Each flow object has a prompt group.  The default value is the flow object's name.  Prompt ids are looked up twice.  First the prefix is added, so for an id "id:outOfRange" in a flow object "MyMenu" the first lookup is "id:MyMenu.outOfRange".  If this prompt id is found,  the value in the XML file is used.  If not, then a second lookup without the prefix is done, which for our example would be "id:outOfRange".&lt;br /&gt;&lt;br /&gt;All SROs use prompt ids with default values (see &lt;a href="http://speakrightframework.blogspot.com/2007/03/prompts-in-sros.html"&gt;Prompts in SROs&lt;/a&gt;).  The default prompts are usually good enough to get your app logic up and tested.  Then you can create an app-specific prompt XML file and register it (using SRRunner.registerPromptFile).  Now you can define the prompt text for all the flow objects at your leisure.  No code changes needed!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2029158781982696505?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2029158781982696505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2029158781982696505' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2029158781982696505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2029158781982696505'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/05/prompt-ids-and-prompt-xml-files.html' title='Prompt Ids and Prompt XML Files'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2201932925323349425</id><published>2007-04-26T08:55:00.000-07:00</published><updated>2007-12-06T07:56:25.438-08:00</updated><title type='text'>Simpsons Demo</title><content type='html'>SimpsonsDemo is a simple voting application.  It's a working speech application that demonstrates the use of SpeakRight in a non-trivial app.   In SimpsonsDemo, users can call in and vote for a character from the Simpsons TV show, one vote per phone call.  After voting they can hear the current standings and other information about the application.  In order to make the application more complex, each character is assumed to have a &lt;span style="font-style: italic;"&gt;related&lt;/span&gt; character who they are closest to.  For Mister Burns this might be Smithers (and vice versa!).&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Development Process&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Productivity of developers is important.  When code is quick to create, it's quick to change (and test!).  This encourages an agile development process.&lt;br /&gt;&lt;br /&gt;A SpeakRight application is developed in stages.&lt;br /&gt;&lt;br /&gt;Stage 1.  The application flow objects are created and wired together.  Concentrate on the Model and the overall callflow.  Don't worry about grammars and prompts at this point.  Use inline grammars and default prompts.  Do all testing using the keyboard-based interactive tester (and unit tests).  The goal at this stage is to get the callflow logic working.  External data access can be done at this stage, or mocked out, and done later in parallel with other stages.&lt;br /&gt;&lt;br /&gt;Stage 2. Define the grammars and prompts.  Use external grammars that take into consideration pre-amble, post-amble, and various ways of saying things ("LA" and "Los Angeles").  An application prompt XML file should be created that defines the main and error prompts for your flow objects.  Deploy the app as a servlet and test using the HTML mode, where the app can be executed using a web browser.  This will flush out missing files and other errors.&lt;br /&gt;&lt;br /&gt;Stage 3. Deploy the app to the VoiceXML platform.  At this point the callflow logic should be already complete and well tested, and the prompts and grammars defined.  All that remains is to listen for mis-pronounciations, poor prosody, and other VUI-level errors.&lt;br /&gt;&lt;br /&gt;The idea is to get as much testing done before deploying to the VoiceXML platform, where testing becomes much slower and more difficult (especially automated testing).  Of course, it's not a fixed waterfall approach; you may, for example, need to prototype some VUI design issues on the VoiceXML platform before tackling stage 1.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Description of the Call Flow&lt;/span&gt;&lt;br /&gt;When a user calls in they choose a character by saying the character's name, such as "Mister Burns".  The application plays a short description of the character and asks if the user wishes to vote for this character.  If yes, the vote is recorded and the user is taken to the main menu.  Otherwise the user is asked if they want to hear about the related character.  If the user says yes, the related character's description is played and the user has the opportunity to vote for the&lt;br /&gt;character as before.  If the user chooses not to hear about the related character then they are asked to choose another character.&lt;br /&gt;&lt;br /&gt;The main menu has four options.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;choose character&lt;/span&gt;  select a Simpsons character and vote.  described above.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;voting results&lt;/span&gt;.  Hear the voting results.  Results are played in sets of three.  The top three characters are listed. If the user says 'next', then the next three characters are listed.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;call statistics&lt;/span&gt;.  Lists # of calls, average call duration, and other statistics.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;speakright&lt;/span&gt;. Plays a description of the SpeakRight framework.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Sample Call&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;(For brevity we've left off examples of error handling for silence and no-input errors)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Computer:&lt;/span&gt; Welcome to the Simpsons Demo where you can vote for your favorite Simpson's character.  {pause} Please say the name of a character, such as "Mister Burns".&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Human:&lt;/span&gt; Homer&lt;br /&gt;&lt;span style="font-style: italic;"&gt;C: &lt;/span&gt;Homer Simpson is the show's main character.  His signature annoyed grunt "D'oh!" has been included in the Oxford English Dictionary.  Do you want to vote for Homer?&lt;br /&gt;&lt;span style="font-style: italic;"&gt;H: &lt;/span&gt;No&lt;br /&gt;C: Do you want to hear about Marge, Homer's wife?&lt;br /&gt;&lt;span style="font-style: italic;"&gt;H: &lt;/span&gt;Yes&lt;br /&gt;&lt;span style="font-style: italic;"&gt;C: &lt;/span&gt;Marge Simpson is the well-meaning and patient wife of Homer.  Do you want to vote for Marge?&lt;br /&gt;&lt;span style="font-style: italic;"&gt;H: &lt;/span&gt;Yes.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;C: &lt;/span&gt;Vote recorded. {pause} Main Menu.  You can say 'choose character', 'voting results', 'call statistics', or 'hear about speakright'.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;H&lt;/span&gt;: call statistics&lt;br /&gt;&lt;span style="font-style: italic;"&gt;C: &lt;/span&gt;There have been 413 calls with average length of 65 seconds.  The average completion is...&lt;br /&gt;&lt;span style="font-style: italic;"&gt;H: Hangup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Pseudo-Code for the Call Flow&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Let's write the call flow logic as a series of actions with some basic pseudo-code to represent branching and looping.  Labels are marked in &lt;span style="font-weight: bold;"&gt;bold&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Welcome&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A:&lt;/span&gt; ChooseCharacter&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;B:&lt;/span&gt; SayCharacterInfo&lt;br /&gt;VoteForCharacterYesNo&lt;br /&gt;&lt;span style="font-style: italic;"&gt;if yes then goto &lt;span style="font-weight: bold;"&gt;MainMenu&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;HearAboutRelatedCharacterYesNo&lt;br /&gt;&lt;span style="font-style: italic;"&gt;if yes then goto &lt;span style="font-weight: bold;"&gt;B&lt;/span&gt; else goto &lt;span style="font-weight: bold;"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MainMenu:&lt;/span&gt; MainMenu&lt;br /&gt;&lt;span style="font-style: italic;"&gt;if 'character' then goto &lt;span style="font-weight: bold;"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     else if 'results' then SayVotingResults&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     else if 'statistics' then SayCallStatistics&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;     else if 'speakright' then SaySpeakRightInfo&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Writing the Call Flow in Java&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;In SpeakRight, the pseudo-code for a callflow can be converted into Java code in a fairly simple way.  Each action becomes a &lt;span style="font-style: italic;"&gt;flow object, &lt;/span&gt;and is represented by a class derived from one of the SpeakRight base classes, such as a PromptFlow that plays some audio output.   A series of flow objects are executed in sequence.&lt;br /&gt;&lt;br /&gt;Where branching is required, the &lt;span style="font-style: italic;"&gt;getNext &lt;/span&gt;method of a flow object can be overridden to add the branching logic.  &lt;span style="font-style: italic;"&gt;getNext &lt;/span&gt;returns either a flow object to be executed, or an &lt;span style="font-style: italic;"&gt;event object &lt;/span&gt;which causes execution to jump to a previous point.  Event objects and event handlers act like "throw" and "catch" respectively.&lt;br /&gt;&lt;br /&gt;The application's data is stored in the &lt;span style="font-style: italic;"&gt;model, &lt;/span&gt;a special class generated by the SpeakRight tool MGen.  The model can be used to hold user input (such as the currently selected Simpson's character) and retrieved data (eg. from a database).  It can also hold control data that is used to control the execution path.&lt;br /&gt;&lt;br /&gt;Let's get started.  The outermost flow object represents the entire callflow, and is always derived from SRApp.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public static class SimpsonsDemo extends SRApp&lt;br /&gt;{&lt;br /&gt;public SimpsonsDemo()&lt;br /&gt;{&lt;br /&gt;   addPromptFlow("Welcome");&lt;br /&gt;   add(new MainLoop());&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The constructor adds two sub-flows: a welcome prompt and a loop flow object.  The welcome is only played once and the remainder of the callflow is done in a loop since the user can go back and forth from selecting a character to the main menu as many times as he or she likes.&lt;br /&gt;&lt;br /&gt;The MainLoop class defines a model variable M.  By convention, SpeakRight will inject a value for M at runtime automatically.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;public static class MainLoop extends BranchFlow&lt;br /&gt;{&lt;br /&gt; public Model M;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The first method called in a flow object is its &lt;span style="font-style: italic;"&gt;onBegin &lt;/span&gt;method.  Here we initialize the two main model values.  &lt;span style="font-style: italic;"&gt;nextAction &lt;/span&gt;is used to control what MainLoop does next, and &lt;span style="font-style: italic;"&gt;currentCharacterId &lt;/span&gt;is the currently chosen Simpsons' character.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;@Override&lt;br /&gt;public void onBegin() {&lt;br /&gt;M.nextAction().set("A");&lt;br /&gt;M.CurrentCharacterId().clear();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The next method to be called is &lt;span style="font-style: italic;"&gt;getFirst.  &lt;/span&gt;If &lt;span style="font-style: italic;"&gt;nextAction &lt;/span&gt;is set to choose a character then we build a sequence of sub-flows for selecting and voting for a character.  Otherwise we return the main menu flow object.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt; &lt;br /&gt;@Override&lt;br /&gt;public IFlow branch() {&lt;br /&gt;if (M.nextAction().get() == "A") {&lt;br /&gt;               BasicFlow flow = new BasicFlow();&lt;br /&gt;               if (M.getCurrentCharacterId() == 0) { //no char selected?&lt;br /&gt;                       flow.add(new AskCharacter());&lt;br /&gt;               }&lt;br /&gt;               flow.add(new new PromptFlow("{$M.CurrentCharacterId}"));&lt;br /&gt;               flow.add(new VoteYesNo());&lt;br /&gt;               flow.add(new RelatedCharacterYesNo());&lt;br /&gt;               return flow;&lt;br /&gt;       }&lt;br /&gt;       else {&lt;br /&gt;              MainMenu menu = new MainMenu();&lt;br /&gt;              return menu;&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;AskCharacter is a flow object that asks the user to enter a character name.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;br /&gt;public static class AskCharacter extends BaseSROQuestion {&lt;br /&gt;&lt;br /&gt;public AskCharacter() {&lt;br /&gt; super("character");&lt;br /&gt;&lt;br /&gt; m_main1Prompt = "Say the name of a Simpson's character";&lt;br /&gt; m_slotName = "x";&lt;br /&gt; m_modelVar = "currentCharacterId";&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The voting flow object is a yes/no question.  The VoteYesNo class asks the question and then it's &lt;span style="font-style: italic;"&gt;getNext &lt;/span&gt;method handles the result.  If 'yes' is input then record the vote and jump to the main menu.  The GotoMainLoopEvent event object is used to do this.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;public static class VoteYesNo extends SROYesNo {&lt;br /&gt;public VoteYesNo()&lt;br /&gt;{&lt;br /&gt; m_main1Prompt = "Do you want to vote for {$M.CharacterName}";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public IFlow onYes() {&lt;br /&gt; return new MainLoop.GotoEvent(MainLoop.BRANCH_MAIN_MENU);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The GotoMainLoopEvent is caught by MainLoop in its &lt;span style="font-style: italic;"&gt;onCatchGotoBranchEvent&lt;/span&gt;method.  Here we set the branching condition M.nextAction.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;protected void onCatchGotoBranchEvent(GotoBranchEvent ev)&lt;br /&gt;{&lt;br /&gt; log("branch. action: " + ev.m_action);&lt;br /&gt; M.nextAction().set(ev.m_action);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;MainLoop is a BranchFlow with it's loop-forever set.  MainLoop will be executed again,  and depending on &lt;span style="font-style: italic;"&gt;nextAction &lt;/span&gt;do either the main menu or choose-a-character.&lt;br /&gt;&lt;br /&gt;SimpsonsDemo has an interactive tester (for keyboard testing), and an auto-tester (see &lt;a href="http://speakrightframework.blogspot.com/2007/05/automated-testing.html"&gt;Automated Testing&lt;/a&gt;).&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2201932925323349425?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2201932925323349425/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2201932925323349425' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2201932925323349425'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2201932925323349425'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/04/simpsons-demo.html' title='Simpsons Demo'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-5017757559565239669</id><published>2007-04-19T11:06:00.000-07:00</published><updated>2007-05-24T09:48:09.518-07:00</updated><title type='text'>SpeakRight Reusable Objects (SROs)</title><content type='html'>One of the biggest challenges for a speech app framework is to maximise the reuse of common VUI dialogs.  Collection of comon data elements should be reusable.  This includes as time, date, currency, numbers, phone numbers, and zip code. Another area of commonality is user interface elements: login, main menu, "hot word" commands, list traversal, the enter-or-cancel pattern, and confirmation.&lt;br /&gt;&lt;br /&gt;SpeakRight provides a set of reusable speech objects called SROs.  They are configurable and extensible.  Here is a list of the ways SROs can be "tweaked":&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;SROs have a full set of prompts, with main, silence, no-reco, and help prompts.  Up to four escalations of each can be defined.&lt;/li&gt;&lt;li&gt;any or all prompts can be replaced.  Each SRO has a subject, a word such as "flights", which is used to build prompts. Changing the subject word is the simplest way to adjust the prompts.  There is an extension point for handling the plurality of subject words ("flight", "flights").  Or the entire prompt can be replaced.&lt;/li&gt;&lt;li&gt;prompts can be conditional, such as a prompt that only plays the first time an SRO is executed.&lt;/li&gt;&lt;li&gt;prompts can be defined at compile time, at runtime in code, or in external XML files.&lt;/li&gt;&lt;li&gt;grammars are replaceable.  Inline grammars or grammar files can be used.  The only restriction on a grammar is that it uses the slot names required by the SRO.&lt;/li&gt;&lt;li&gt;validation code can be added.  This server-side code inspects use input and either accepts it or causes the SRO to re-execute.&lt;/li&gt;&lt;li&gt;Model binding.  An SRO has a model variable name.  When set, the user input results are bound to the model (i.e. stored in the model for later use by the app)&lt;/li&gt;&lt;li&gt;Command phrases can be added to an SRO.  A common data entry pattern is the enter-data-or-say-cancel pattern.  SROs have a list of command phrases that you can add to.  &lt;/li&gt;&lt;li&gt;confirmation can be added.  An SRO has a confirmation plug-in that can be used to add various forms of confirmation (explicit, implicit, or confirm-and-correct).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;The current list of SROs is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;SROCancelCommand&lt;/li&gt;&lt;li&gt;SROChoice&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SROConfirmYesNo&lt;/li&gt;&lt;li&gt;SRODigitString&lt;/li&gt;&lt;li&gt;SROListNavigator&lt;/li&gt;&lt;li&gt;SRONumber&lt;/li&gt;&lt;li&gt;SROOrdinalItem&lt;/li&gt;&lt;li&gt;SROTransferCall&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SROYesNo&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Adding new SROs is simple.  Code-generation (using StringTemplate) generates a base class (eg. genSRONumber) that manages prompts and grammars.  You only need derive the actual SRO class to add specific logic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-5017757559565239669?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/5017757559565239669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=5017757559565239669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5017757559565239669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5017757559565239669'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/04/speakright-reusable-objects-sros.html' title='SpeakRight Reusable Objects (SROs)'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2558797865386756905</id><published>2007-03-29T13:16:00.000-07:00</published><updated>2007-03-29T13:56:50.824-07:00</updated><title type='text'>Prompts in SROs</title><content type='html'>SpeakRight speech objects (SROs) offer a highly-reusable approach to prompts.   Recall that SRO classes are generated by the SROGen tool.  Each SRO has an XML file that defines what code will be generated.  The XML file contains the grammars and prompts for the SRO. You can modify this file and regenerate an SRO.&lt;br /&gt;&lt;br /&gt;SROGen also generates an XML file holding the default prompts.  This file is deployed and is read at runtime to load the SRO prompt fields.  You can modify this file on a production system to modify the default prompts for an SRO; no re-compile (or restart) is necessary.&lt;br /&gt;&lt;br /&gt;Here's what a prompt definition in the XML file looks like:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;  &amp;lt;prompt name="main1" def="no"&amp;gt;What {%subject%} would you like?&amp;lt;/prompt&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The prompt id &lt;span style="font-style: italic;"&gt;main1, &lt;/span&gt;has a corresponding field in the SRO class called &lt;span style="font-weight: bold;"&gt;m_main1Prompt&lt;/span&gt;.  A derived class, or a SR app, can modify the field using get/set methods.&lt;br /&gt;&lt;br /&gt;This works fairly well with the PText feature {%&lt;span style="font-style: italic;"&gt;fieldName%}&lt;/span&gt; for extracting values from a field.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sub-Prompts&lt;br /&gt;&lt;/span&gt;The one thing missing so far is the ability to define conditional prompts, such as a play-once prompt.  You can do it in code of course, but that's not very flexible&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;if (executionCount() == 1) {&lt;br /&gt; m_main1Prompt = "Let's get started. " + m_main1Prompt;&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;To remedy this, SROs support multiple sub-prompts to be defined for a single prompt, such as the MAIN prompt.&lt;br /&gt;&lt;br /&gt;&amp;lt;prompt name="main1welc" group="MAIN" cond="once_ever"&amp;gt;Let's get started.&amp;lt;/prompt&amp;gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;  &amp;lt;prompt name="main1" group="MAIN" def="no"&amp;gt;What {%subject%} would you like?&amp;lt;/prompt&amp;gt;&lt;br /&gt;&lt;br /&gt;Each prompt tag results in a field being created.  Multiple prompts in the same group are rendered as a single VoiceXML prompt, in the order they occur in the XML file.  The neat thing is that conditions can now be applied to individual sub-prompts.  The &lt;span style="font-weight: bold;"&gt;cond &lt;/span&gt;attribute defines a condition.  Here, "once_ever" means a play-once-ever condition.   The first time the SRO is executed, the prompt will be:  "Let's get started.  What flight would you like?".  On subsequent executions, the prompt is "What flight would you like?".&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Implementation note:  Sub-prompts are implemented using the m_subIndex field of Prompt.  When prompts are rendered (in a PromptSet), all the rendered items are gathered together in the first sub-prompt.  But since each sub-prompt is an independent Prompt object, its rendering can be enabled or disabled by its condition.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2558797865386756905?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2558797865386756905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2558797865386756905' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2558797865386756905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2558797865386756905'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/03/prompts-in-sros.html' title='Prompts in SROs'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-6327909228100772822</id><published>2007-03-06T08:05:00.000-08:00</published><updated>2007-03-06T08:14:13.201-08:00</updated><title type='text'>Release 0.0.2 is out</title><content type='html'>This second &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=189014"&gt;release &lt;/a&gt;is a bit more real.  First two SROs (SRONumber and SROConfirmYesNo) are available.  And confirmation and validation are working.&lt;br /&gt;&lt;br /&gt;Here's a simple app to ask for the number of tickets in a travel application&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;SRApp flow = new SRApp();&lt;br /&gt;&lt;br /&gt;SRONumber sro = new SRONumber("tickets", 1, 10);&lt;br /&gt;sro.setConfirmer(new SROConfirmYesNo("tickets"));&lt;br /&gt;&lt;br /&gt;flow.add(sro);&lt;br /&gt;flow.addPrompt("You said {$INPUT}");&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;From this, the following dialog is possible&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Computer: How many tickets&lt;/span&gt; would you like?&lt;br /&gt;Human: &lt;silence&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Computer: I didn't hear you.  How many tickets would you like?&lt;br /&gt;&lt;/span&gt;Human: &lt;more&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Computer: I still didn't hear you.  How many tickets would you like?&lt;br /&gt;&lt;/span&gt;Human: twelve&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Computer: Sorry, I'm looking for a number between one and ten.  How many tickets would you like?&lt;br /&gt;&lt;/span&gt;Human: two  &lt;slightly&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Computer: Do you want two?&lt;br /&gt;&lt;/span&gt;Human: yes&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;Computer: You said two.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;As you can see, escalating error prompts are given and user input is validated against the range given to the SRONumber flow object.  Utterances below 80% confidence are confirmed, and finally the user's input is played back to them.&lt;br /&gt;&lt;br /&gt;This release uses extremely simple grammar in SRONumber (a built-in grammar for one to nine).  You're free to replace it with your own, and of course the next release will improve on this.&lt;br /&gt;&lt;br /&gt;Enjoy :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-6327909228100772822?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/6327909228100772822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=6327909228100772822' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/6327909228100772822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/6327909228100772822'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/03/release-002-is-out.html' title='Release 0.0.2 is out'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-5772436473651343622</id><published>2007-03-03T08:10:00.000-08:00</published><updated>2007-06-14T10:42:11.754-07:00</updated><title type='text'>Testing</title><content type='html'>Testing is an important part of SpeakRight.  Running applications on an VoiceXML platform is not easy or quick to do.  It's essential to be able to test your app under more programmer-friendly conditions.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Unit Tests&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Both JUnit and XMLUnit are supported.  Here is a basic test that creates an app and runs it, feeding the required user input.  Notice the use of TrailWrapper, a flow object that tracks execution in a trail of flow object names.  The test shown below is in org.speakright.sro.tests and uses the MockSpeechPageWriter.  This mock object remembers the rendered SpeechPage object which can then be checked to see if the expected grammars and prompts are there.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;    @Test public void testConfirmNo()&lt;br /&gt;{&lt;br /&gt; log("--------testConfirmNo--------");&lt;br /&gt; SRApp flow = createApp(true);&lt;br /&gt; TrailWrapper wrap1 = new TrailWrapper(flow);&lt;br /&gt;&lt;br /&gt; SRInstance run = StartIt(wrap1);&lt;br /&gt; Proceed(run, "2", "num", 40); //question with low confidence&lt;br /&gt; Proceed(run, "no"); //reject the confirmation&lt;br /&gt; Proceed(run, "8", "num"); //question again&lt;br /&gt; Proceed(run, ""); //you said...&lt;br /&gt;&lt;br /&gt; assertEquals("fail", false, run.isFailed());&lt;br /&gt; assertEquals("fin", true, run.isFinished());&lt;br /&gt; assertEquals("start", true, run.isStarted());&lt;br /&gt;&lt;br /&gt; ChkTrail(run, "SROQuantity;ConfYNFlow;SROQuantity;PFlow");&lt;br /&gt; assertEquals("city", "8", M.city().get());&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;XMLUnit can also be used.  See the TestRender.java file in org.speakright.core.tests.  XML comparison is more fussy (and slower), but you can check the actual VoiceXML.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;ISRInteractiveTester&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next up is the ISRInteractiveTester class.  Use it in a console-app for executing a SpeakRight app interactively from the keyboard.  See InteractiveTester.java in org.speakright.core.tests for an example.  Run this file as a Java application.&lt;br /&gt;&lt;br /&gt;Here are the commands it uses:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;SpeakRight ITester..&lt;br /&gt;RUNNING App2.........&lt;br /&gt;1&gt; ???&lt;br /&gt;available cmds:&lt;br /&gt;q -- quit&lt;br /&gt;go -- run or proceed&lt;br /&gt;bye -- simulate a DISCONNECT&lt;br /&gt;echo -- toggle echo of generated content&lt;br /&gt;version -- display version&lt;br /&gt;status -- show interpreter status&lt;br /&gt;out -- turn on file output of each page in tmpfiles dir&lt;br /&gt;ret -- set return url&lt;br /&gt;gramurl -- gram base dir&lt;br /&gt;prompturl -- prompt base dir&lt;br /&gt;html -- switch to HTML output&lt;br /&gt;vxml -- switch to VXML output&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;The &lt;span style="font-weight: bold;"&gt;out &lt;/span&gt;command causes each rendered VoiceXML page to be output as a file (page1.vxml, page2.vxml, etc).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Running Servlet in HTML mode&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once you're satisfied with your app, it's time to test it inside a real servlet.  Write your servlet; the one that will output VoiceXML.  However when you run it, add the CGI param "mode=html", like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;http:localhost:8080/MyServlet3/App1?mode=html&lt;br /&gt;&lt;br /&gt;MyServlet3 &lt;/span&gt;is the name of your dynamic web project, and &lt;span style="font-style: italic;"&gt;App1 &lt;/span&gt;is the servlet inside it.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_-ghvQ2vraN4/Remic6K58RI/AAAAAAAAAA8/S3QCr1skXHQ/s1600-h/html_mode_pic1.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp3.blogger.com/_-ghvQ2vraN4/Remic6K58RI/AAAAAAAAAA8/S3QCr1skXHQ/s320/html_mode_pic1.JPG" alt="" id="BLOGGER_PHOTO_ID_5037736275725644050" border="0" /&gt;&lt;/a&gt;  SpeakRight will render into HTML inside VoiceXML.  A sample page is shown on the left.  Pressing the Next or Submit button simulates the VoiceXML platform returning results.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Running Servlet in VoiceXML mode&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;OK, time for the real thing.  Point your VoiceXML platform at your servlet's URL, like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;http://www.someplace.com/MyServlet3/App1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Some platforms (such as &lt;a href="http://community.voxeo.com/"&gt;Voxeo&lt;/a&gt;'s) have a real-time debugger that shows events and log messages as they occur.&lt;br /&gt;&lt;br /&gt;You can also use the log4j log file that SpeakRight writes.  Here's a sample:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;03-03 11:32:12.015 [or24] INFO     srf  - SR: startApp&lt;br /&gt;03-03 11:32:12.015 [or24] INFO     srf  - START: MyApp&lt;br /&gt;03-03 11:32:12.015 [or24] INFO     srf  -  push MyApp&lt;br /&gt;03-03 11:32:12.015 [or24] INFO     srf  -  push PFlow&lt;br /&gt;03-03 11:32:12.015 [or24] INFO     srf  - EXEC PFlow&lt;br /&gt;03-03 11:32:12.031 [or24] DEBUG    srf  - prompt (1 items): Welcome to Joe's Pizza&lt;br /&gt;03-03 11:32:12.359 [or24] INFO     srf  - SR: writing content.&lt;br /&gt;03-03 11:32:12.375 [or24] INFO     srf  - SR: saving state.&lt;br /&gt;03-03 11:32:12.375 [or24] INFO     srf  - SR: done.&lt;br /&gt;03-03 11:32:14.109 [or25] INFO     srf  - SR: doing POST&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-size:130%;"&gt;Automated Testing&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;See &lt;a href="http://speakrightframework.blogspot.com/2007/05/automated-testing.html"&gt;Automated Testing&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-5772436473651343622?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/5772436473651343622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=5772436473651343622' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5772436473651343622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5772436473651343622'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/03/testing.html' title='Testing'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_-ghvQ2vraN4/Remic6K58RI/AAAAAAAAAA8/S3QCr1skXHQ/s72-c/html_mode_pic1.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-4090838135811311736</id><published>2007-03-02T08:56:00.000-08:00</published><updated>2007-06-14T10:46:05.309-07:00</updated><title type='text'>Servlets</title><content type='html'>Let's consider how to enclose a SpeakRight application in a Java servlet.  Servlets are a portable API for responding to HTTP requests.  Tomcat or other types of web servers (such as TBD) support servlets.&lt;br /&gt;&lt;br /&gt;SpeakRight provides a class, &lt;span style="font-weight: bold;"&gt;SRServletRunner&lt;/span&gt;, that does most of the work.  Here's how to use it in the doGet method of a servlet&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {&lt;br /&gt;SRServletRunner runner = new SRServletRunner(new AppFactory(), this, request, response, "GET");&lt;br /&gt;&lt;br /&gt;if (runner.isNewSession()) {&lt;br /&gt;  SRRunner run = runner.createNewSRRunner(this);           &lt;br /&gt;  IFlow flow = new App();&lt;br /&gt;  runner.startApp(flow);&lt;br /&gt; }  else {&lt;br /&gt;   runner.logger().log("contine in GET!!");&lt;br /&gt;   runner.continueApp();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;First we pass the request and response objects into SRServletRunner, along with a string (used for logging) and our app factory (see &lt;a href="http://speakrightframework.blogspot.com/2007/06/initialization.html"&gt;Initialization&lt;/a&gt;).  Then we check if this is a new session.  If it is then we create our SpeakRight application and call startApp; otherwise we call continueApp.  SRServletRunner manages passifying and re-activating the SpeakRight runtime between HTTP requests.&lt;br /&gt;&lt;br /&gt;Logging is done using log4j.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-4090838135811311736?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/4090838135811311736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=4090838135811311736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4090838135811311736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4090838135811311736'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/03/servlets.html' title='Servlets'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-7758443088464030712</id><published>2007-02-26T21:09:00.001-08:00</published><updated>2007-02-26T21:09:53.477-08:00</updated><title type='text'>Technorati sign-up</title><content type='html'>&lt;a href="http://technorati.com/claim/y42wjwk7kr" rel="me"&gt;Technorati Profile&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-7758443088464030712?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/7758443088464030712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=7758443088464030712' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7758443088464030712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7758443088464030712'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/technorati-sign-up.html' title='Technorati sign-up'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-5856235177017801858</id><published>2007-02-26T14:31:00.000-08:00</published><updated>2007-02-26T14:36:46.530-08:00</updated><title type='text'>First Release!</title><content type='html'>Our first release is out!  Click on the Download link on the left to try SpeakRight out.  Pretty minimal support, but enough to get an idea of the approach and build some simple VoiceXML apps. Definitely more coming.  Next up are multi-slot questions, transfer, and a starter set of SROs (re-usable speech objects).&lt;br /&gt;&lt;br /&gt;This is my first open-source project.  It's been an intense learning curve, but getting this far is due to some fine OSS software:  Eclipse, Subversion, SourceForge, StringTemplate, Junit, XMLUnit, Skype,  and the Voxeo community.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-5856235177017801858?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/5856235177017801858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=5856235177017801858' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5856235177017801858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/5856235177017801858'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/first-release.html' title='First Release!'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2241392754138485248</id><published>2007-02-24T16:00:00.000-08:00</published><updated>2007-05-24T09:43:12.864-07:00</updated><title type='text'>Control Flow, Errors, and Event Handling</title><content type='html'>As we saw in &lt;a href="http://speakrightframework.blogspot.com/2007/02/internal-architecture.html"&gt;Internal Architecture&lt;/a&gt; a flow stack is the basis of execution in SpeakRight.  In this approach, pushing a flow object onto the stack is similar to making a sub-routine call.  Popping a flow object off the stack is similar to returning from a sub-routine.&lt;br /&gt;&lt;br /&gt;Execution of a sequence of flow objects is done by a flow object having a list of sub-flow objects.  Every time its &lt;span style="font-weight: bold;"&gt;getNext &lt;/span&gt;method is called it returns the next object from the list.&lt;br /&gt;&lt;br /&gt;Conditional flow is done by adding logic in &lt;span style="font-weight: bold;"&gt;getNext, &lt;/span&gt;to return one flow object or another &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;based on some condition.&lt;br /&gt;&lt;br /&gt;Looping is done by having &lt;span style="font-weight: bold;"&gt;getNext&lt;/span&gt; return its sub-flows more than once, iterating over them multiple times.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Error Handling&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Callflows can have errors, such as user errors (failing to say anything recognizable) and application errors (missing files, db error, etc). SpeakRight manages error handling separately from the &lt;span style="font-weight: bold;"&gt;getFirst/getNext &lt;/span&gt;mechanism. &lt;span style="font-weight: bold;"&gt;getNext&lt;/span&gt; handles the error-free case. If an error occurs then of the IFlow error handling methods is called.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt; IFlow OnNoInput(current, results); //app was expecting input and none was provided by the user&lt;br /&gt;IFlow OnException(current, results);  //a generic failure such as exception being thrown.&lt;br /&gt;IFlow OnDisconnect(current, results); //user terminated the interaction (usually by hanging up the phone. how in multimodal?)&lt;br /&gt;IFlow OnHalt(current, results); //system is stopping&lt;br /&gt;IFlow OnValidateFailed(current, results);&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Note that a number of things that aren't really errors are handled this way. The goal is to keep the "nexting" logic clean, and handle everything else separately.&lt;br /&gt;&lt;br /&gt;Errors are handled in a similar manner as exceptions; a search up the flow stack is done for an error handler. If the current flow doesn't have one, then its parent is tried. It's an runtime error if an error handler is not found.&lt;br /&gt;&lt;br /&gt;The outermost flow is usually a class derived from SRApp. SRApp provides error handlers with default behaviour. They play a prompt indicating that a problem has occurred, and transfers the call to an operator.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Catch and Throw&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The basic flow of control in a SpeakRight app is nesting of flow objects. These behave like subroutine calls; when the nested flow finishes, the parent flow resumes execution. Sometimes a non-local transfer of control is needed. SpeakRight supports a generic throw and catch approach. A flow can throw a custom flow event, which MUST be caught by a flow above it in the flow stack.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt; return new ThrowFlowEvent("abc");&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;and the catch looks like any other error handler&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt; IFlow OnCatch(current, results, thrownEvent);&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Note: like all other handlers a flow event can catch its own throw. May seem weird but this lets developers move code around easily.&lt;br /&gt;&lt;br /&gt;Some control flow is possible in &lt;span style="font-weight: bold;"&gt;execute&lt;/span&gt;. If you want a flow to branch if a db error happens, then do this. However, in this case a flow object can not catch its own flow event, since that would cause Execute to be called again, and infinite recursion...&lt;br /&gt;&lt;br /&gt;Update:  See also &lt;a href="http://speakrightframework.blogspot.com/2007/05/optional-sub-flow-objects.html"&gt;Optional Sub-Flow Objects&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;GotoUrlFlow&lt;br /&gt;&lt;/span&gt;The GotoUrlFlow flow object is used to redirect the VoiceXML browser to an external URL.  It is used to redirect to static VoiceXML pages or to another application. &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2241392754138485248?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2241392754138485248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2241392754138485248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2241392754138485248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2241392754138485248'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/control-flow-errors-and-event-handling.html' title='Control Flow, Errors, and Event Handling'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-95748617247514708</id><published>2007-02-24T15:21:00.000-08:00</published><updated>2007-12-04T16:03:52.307-08:00</updated><title type='text'>Internal Architecture</title><content type='html'>A typical VoiceXML application has a software stack like this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Application code&lt;/li&gt;&lt;li&gt;Web server&lt;/li&gt;&lt;li&gt;VoiceXML browser&lt;/li&gt;&lt;li&gt;VoiceXML platform&lt;/li&gt;&lt;li&gt;Telephony hardware, VOIP stack&lt;/li&gt;&lt;/ul&gt;Starting at the bottom, a phone call arrives at the &lt;span style="font-weight: bold;"&gt;telephony/VOIP laye&lt;/span&gt;r.  This layer notifies the &lt;span style="font-weight: bold;"&gt;VoiceXML platform layer&lt;/span&gt;,  which allocates a speech recognition engine, a text-to-speech engine, and a &lt;span style="font-weight: bold;"&gt;VoiceXML browser.&lt;/span&gt;  The browser plays the same role as a web browser; it makes a HTTP request to a &lt;span style="font-weight: bold;"&gt;web server&lt;/span&gt; which runs some &lt;span style="font-weight: bold;"&gt;application code&lt;/span&gt;.  The application code is a mixture of static and dynamic web content that generates a VoiceXML page.  The web server returns this page to the browser, which renders the page as audio.  Speech input and DTMF digits are collected, according the VoiceXML tags.  At some point, a &lt;goto&gt; or &lt;submit&gt; tag is executed, which makes a new HTTP request (sending user input as GET or POST data), and the process repeats.&lt;br /&gt;&lt;br /&gt;SpeakRight lives in application code layer, typically in a servlet.  The SpeakRight runtime dynamically generates VoiceXML pages, one per HTTP request.  Between requests, the runtime is stateless, in the same sense of a "stateless bean".   State is saved in the servlet session, and restored on each HTTP request.&lt;br /&gt;&lt;br /&gt;The SpeakRight framework is a set of Java classes specifically designed for writing speech rec applications.  Although VoiceXML uses a similar web architecture as HTML, the needs of a speech app are very different (see Why Speech is Hard TBD).&lt;br /&gt;&lt;br /&gt;SpeakRight has a Model-View-Controller architecture (MVC) similar to GUI frameworks.  In GUIs, a &lt;span style="font-style: italic;"&gt;control &lt;/span&gt;represents the view and controller&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Controls can be combined using nesting to produce larger GUI elements.  In SpeakRight, a &lt;span style="font-style: italic;"&gt;flow object &lt;/span&gt;represents the view and controller.  Flow objects can be combined using nesting to produce larger GUI elements.  Flow objects can be customized by setting their properties (getter/setter methods), and extended through inheritance and extension points.  For instance, the confirmation strategy used by a flow object is represented by another flow object.  Various types of confirmation can be plugged-in.&lt;br /&gt;&lt;br /&gt;Flow objects contain &lt;span style="font-style: italic;"&gt;sub-flow objects.  &lt;/span&gt;The application is simply the top-level flow object.&lt;br /&gt;&lt;br /&gt;Flow objects implement the IFlow interface.  The basics of this interface are&lt;br /&gt;&lt;br /&gt;&lt;/submit&gt;&lt;/goto&gt;&lt;blockquote&gt;IFlow getFirst();&lt;br /&gt;IFlow getNext(IFlow current, SRResults results);&lt;br /&gt;void execute(ExecutionContext context);&lt;br /&gt;&lt;/blockquote&gt;&lt;span style="font-weight: bold;"&gt;getFirst &lt;/span&gt;returns the first flow object to be run.  A flow object with sub-flows would return its first sub-flow object.  A &lt;span style="font-style: italic;"&gt;leaf object &lt;/span&gt;(one with no sub-flows) returns itself.  (See also &lt;a href="http://speakrightframework.blogspot.com/2007/05/optional-sub-flow-objects.html"&gt;Optional Sub-Flow Objects&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;getNext &lt;/span&gt;returns the next flow object to be run.  It is passed the results of the previous flow object to help it decide.  The results contain user input and other events sent by the VoiceXML platform.&lt;br /&gt;&lt;br /&gt;In the&lt;span style="font-weight: bold;"&gt;  execute &lt;/span&gt;method, the flow object renders itself into  a VoiceXML page.  (see also &lt;a href="http://speakrightframework.blogspot.com/2007/12/stringtemplate-template-engine.html"&gt;StringTemplate template engine&lt;/a&gt;).&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Execution uses a &lt;span style="font-weight: bold;"&gt;flow stack.   &lt;/span&gt;An application starts by pushing the application flow object (the outer-most flow object) onto the stack.  Pushing a flow object is known as &lt;span style="font-style: italic;"&gt;activation.   &lt;/span&gt;If the application object's &lt;span style="font-weight: bold;"&gt;getFirst &lt;/span&gt;returns a sub-flow then the sub-flow is pushed onto the stack.  This process continues until a leaf object is encountered.  At this point all the flow objects on the stack are considered "active".  Now the runtime executes the top-most stack object, calling its &lt;span style="font-weight: bold;"&gt;execute &lt;/span&gt;method.  The rendered content (a VoiceXML page) is sent to the VoiceXML platform.&lt;br /&gt;&lt;br /&gt;When the results of the VoiceXML page are returned, the runtime gives them to the top-most flow object in the stack, by calling its &lt;span style="font-weight: bold;"&gt;getNext &lt;/span&gt;method.  This method can do one of three things:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;return null to indicate it has finished.  A finished flow object is popped off the stack and the next flow-object is executed.&lt;/li&gt;&lt;li&gt;r&lt;span style="font-style: italic;"&gt;e&lt;/span&gt;turn itself to indicate it wants to execute again.  &lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;return a sub-flow, which is activated (pushed onto the stack).\&lt;/li&gt;&lt;/ul&gt;The result is a new VoiceXML page is generated.  Execution continues like this until the flow stack is empty.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-95748617247514708?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/95748617247514708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=95748617247514708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/95748617247514708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/95748617247514708'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/internal-architecture.html' title='Internal Architecture'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-3633203211006505836</id><published>2007-02-24T14:58:00.000-08:00</published><updated>2007-12-04T16:02:03.347-08:00</updated><title type='text'>Table of Contents</title><content type='html'>Overview&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/what-is-speakright_17.html"&gt;What is SpeakRight?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/benefits-of-code-based-approach.html"&gt;The Benefits of a Code-Based Approach&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/12/matt-raible-has-fascinating-video.html"&gt;Matt Raible on web frameworks&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/features.html"&gt;Features&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/frequently-asked-questions.html"&gt;FAQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/getting-started.html"&gt;Tutorial&lt;/a&gt;, &lt;a href="http://speakrightframework.blogspot.com/2007/04/simpsons-demo.html"&gt;Simpsons Demo&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://sourceforge.net/projects/speakright/"&gt;SourceForge&lt;/a&gt;, &lt;a href="https://sourceforge.net/project/showfiles.php?group_id=189014"&gt;Download&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;SpeakRight documentation&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/getting-started.html"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/tutorial-1-creating-hello-app.html"&gt;Tutorial&lt;/a&gt; and &lt;a href="http://speakrightframework.blogspot.com/2007/04/simpsons-demo.html"&gt;Simpsons Demo&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.net/javadocs/"&gt; Javadocs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Architecture&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/internal-architecture.html"&gt;Internal Architecture&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/03/servlets.html"&gt;Servlets&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Extension Points&lt;/li&gt;&lt;li&gt;Performance&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/12/stringtemplate-template-engine.html"&gt;StringTemplate template engine&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/06/initialization.html"&gt;Initialization&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/list-of-flow-objects.html"&gt;Flow Objects&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/prompts.html"&gt;Prompts&lt;/a&gt;, &lt;a href="http://speakrightframework.blogspot.com/2007/02/grammars.html"&gt;Grammars&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/prompt-ids-and-prompt-xml-files.html"&gt;Prompt Ids and prompt XML files&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/03/prompts-in-sros.html"&gt;Prompts in SROs&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;DTMFOnlyMode&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Internationalization&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/12/nbest.html"&gt;NBest&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/call-control.html"&gt;Call Control&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/control-flow-errors-and-event-handling.html"&gt;Control Flow, Errors and Event Handling&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/optional-sub-flow-objects.html"&gt;Optional Sub-Flow Objects&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;HotWords&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/04/speakright-reusable-objects-sros.html"&gt;SpeakRight Reusable Objects (SROs)&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/03/prompts-in-sros.html"&gt;Prompts in SROs&lt;br /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;VoiceXML&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/voicexml-tags-supported.html"&gt;VoiceXML Tags Supported&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/supported-platforms.html"&gt;Supported Platforms&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/03/testing.html"&gt;Testing&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/05/automated-testing.html"&gt;Automated Testing&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Project Plans&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Project Plan&lt;/li&gt;&lt;li&gt;Wish List&lt;/li&gt;&lt;li&gt;Contributors&lt;/li&gt;&lt;li&gt;Powered By&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-3633203211006505836?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/3633203211006505836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=3633203211006505836' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/3633203211006505836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/3633203211006505836'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/table-of-contents.html' title='Table of Contents'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-6512174659197843106</id><published>2007-02-18T14:12:00.000-08:00</published><updated>2007-03-11T06:44:53.585-07:00</updated><title type='text'>Grammars</title><content type='html'>Grammars define the actual spoken phrases that will be recognized.  The grammar defines the return values (called &lt;span style="font-style: italic;"&gt;slots&lt;/span&gt;).  Grammars are an important abstraction layer in SpeakRight, because they abstract away user input values from how that input is exactly specified.  Synonyms can map to the same user input value.  Both "Los Angeles" and "LA" could map to the result input value &lt;span style="font-style: italic;"&gt;city="Los Angeles"&lt;/span&gt;.  Multi-lingual apps use this feature; the spoken phrases are in the target language but the results are in the default language (usually English).&lt;br /&gt;&lt;br /&gt;SpeakRight supports three types of grammars:  external grammars (referenced by URL), built-in grammars, and inline grammars (which use a simplified GSL format).   Grammars work much like prompts.  You specify a grammar text, known as a &lt;span style="font-style: italic;"&gt;gtext&lt;/span&gt;,&lt;span style="font-style: italic;"&gt; &lt;/span&gt;that uses a simple formatting language:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;(no prefix).  The grammar text is a URL.  It can be an absolute or relative URL.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;inline: &lt;/span&gt;prefix.  An inline grammar.  The prefix is followed by a simplified version of GSL, such as "small medium [large big] (very large)".&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;builtin: &lt;/span&gt;prefix.  One of VoiceXML's built-in grammars.  The prefix is followed by something like "digits?minlength=3;maxlength=9"&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Grammars, like prompts, can have a condition.  Currently the only condition is &lt;span style="font-weight: bold;"&gt;DTMFOnlyMode&lt;/span&gt; (explained below).&lt;br /&gt;&lt;br /&gt;When a flow object is rendered, the grammars are rendered using a pipeline, that applies the following logic:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;check the grammar condition.  If &lt;span style="font-style: italic;"&gt;false &lt;/span&gt;then skip the grammar.&lt;/li&gt;&lt;li&gt;parse an inline grammar into its word list&lt;/li&gt;&lt;li&gt;parse the builtin grammar&lt;/li&gt;&lt;li&gt;convert relative URLs into absolute URLs&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;External Grammars&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The grammar text is a URL.  It can be an absolute URL (eg. http://www.somecompany.com/speechapp7/grammars/fruits.grxml), or a relative URL. Relative URLs (eg. "grammars/fruits.grxml") are converted into absolute URLs when the grammar is rendered.  The servlet's URL is currently used for this.&lt;br /&gt;&lt;br /&gt;The grammar file extension is used to determine the &lt;span style="font-style: italic;"&gt;type &lt;/span&gt;value for the grammar tag&lt;br /&gt;&lt;ul&gt;&lt;li&gt;".grxml" means type="application/srgs+xml"&lt;/li&gt;&lt;li&gt;".gsl" means type="text/gsl"&lt;/li&gt;&lt;li&gt;all other files are assumed to be ABNF SRGS format, type="application/srgs"&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;A Grammar Editor is helpful, such as the wonderful GRXML editor that comes with the (free) Microsoft SASDK.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;Built-In Grammars&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;TDB.   Built-ins are part of VoiceXML 2.0, but optional.  They are also intended for prototyping, and it's recommended that applications use full, properly tuned grammars.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Inline Grammars&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;GSL is (I believe) a propietary Nuance format.  SpeakRight uses  a simplified version that currently only supports [ ] and ( ).&lt;br /&gt;A single utterance can contain one or more slots.  The simplest type of directed dialog VUIs use single slot questions, such as &lt;span style="font-style: italic;"&gt;"How many passengers are there?"&lt;/span&gt;.  SR only supports single slot for now.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Grammar Types&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;There are two types of grammars (represented by the GrammarType enum).&lt;br /&gt;&lt;ul&gt;&lt;li&gt;VOICE is for spoken input&lt;/li&gt;&lt;li&gt;DTMF is for touchtone digits&lt;/li&gt;&lt;/ul&gt;The SpeakRight class Question holds up to two grammars, one of each type.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;DTMF Only Mode&lt;br /&gt;&lt;/span&gt;Speech recognition may not work at all in very noisy environments.  Not only will recognition fail, but prompts may never play due to false barge-in.  For these reasons, speech applications should be able to fall back to a DTMF-only mode.  This mode can be activated by the user by pressing a certain key, usually '*'.  Once activated, SpeakRight will not render any VOICE grammars.  Thus the VoiceXML engine will only listen for DTMF digits.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Slots&lt;br /&gt;&lt;/span&gt;A grammar represents a series of words, such as "A &lt;span style="font-weight: bold;"&gt;large&lt;/span&gt; pizza please".  The application may only care about a few of the words; here, the size word "large" is the only word of importance to the app.  These words are attached to&lt;span style="font-style: italic;"&gt;&lt;/span&gt;named return values called &lt;span style="font-style: italic;"&gt;slots&lt;/span&gt;.   In our pizza example, a slot  called  "size" would be bound to the words "small", "medium", or "large".  Any of those words would fill the slot.&lt;br /&gt;&lt;br /&gt;Slots define the interface between a grammar and a VoiceXML field.   The field's name (shown below) defines a slot that grammar must fill in order for the field to be filled.&lt;br /&gt;&lt;blockquote&gt;&lt;field name="size"&gt;&lt;br /&gt;&lt;/field&gt;&lt;/blockquote&gt;Any grammar that fills the slot "size" can be used.&lt;br /&gt;&lt;br /&gt;A single utterance can fill multiple slots, as in "I would like to fly to &lt;span style="font-weight: bold;"&gt;Atlanta&lt;/span&gt; on &lt;span style="font-weight: bold;"&gt;Friday&lt;/span&gt;."&lt;br /&gt;SpeakRight doesn't yet support multi-slot questions..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-6512174659197843106?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/6512174659197843106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=6512174659197843106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/6512174659197843106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/6512174659197843106'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/grammars.html' title='Grammars'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-8869024761420281282</id><published>2007-02-18T13:25:00.000-08:00</published><updated>2007-05-02T06:44:00.918-07:00</updated><title type='text'>Prompts</title><content type='html'>A prompt text, known as a &lt;span style="font-style: italic;"&gt;ptext, &lt;/span&gt;defines one or more items using a simple formatting scheme.&lt;br /&gt;Here is a basic prompt that plays some text using TTS (text-to-speech):&lt;br /&gt;&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;Welcome to Inky's Travel".  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;PTexts are Java strings.  Here's another prompt:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;        "Welcome to Inky's Travel. {audio:logo.wav}"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;This prompt contains two items&lt;span style="font-style: italic;"&gt;: &lt;/span&gt;a TTS phrase and an audio file.  Items are delimited by '{' and '}'.  The delimiters are optional for the first item. This is equivalent:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    "{Welcome to Inky's Travel. }{audio:logo.wav}"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;PTexts can contains as many items as you want.  They will be rendered as a prompt&lt;prompt&gt; tag, (or possibly as a nomatch &lt;noinput&gt; or &lt;nomatch&gt; noinput tag)&lt;br /&gt;&lt;br /&gt;&lt;/nomatch&gt;&lt;/noinput&gt;&lt;/prompt&gt;&lt;blockquote&gt;&lt;br /&gt;&amp;lt;prompt&amp;gt;Welcome to Inky's Travel. &amp;lt;audio src="http://myIPaddress/logo.wav"&amp;gt;&amp;lt;/audio&amp;gt;&lt;br /&gt;&amp;lt;/prompt&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;For convenience, audio items can be specified without the "audio:" prefix.  The following is equivalent to the previous prompt.  The prefix is optional if the filename ends in ".wav" and contains no whitespace characters.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;        "{Welcome to Inky's Travel. }{logo.wav}"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;You can add pauses as well using "." inside an item.  Each period represents 250 msec.  Pause items contain only periods (otherwise they're considered as TTS).  Here's a 750 msec pause.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;            "{Welcome to Inky's Travel. }{...}{logo.wav}"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Model variables can be prompt items by using a "$M." prefix.  The value of the model is rendered.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;            "The current price is {$M.price}"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;prompt&gt;&lt;noinput&gt;&lt;nomatch&gt;&lt;span&gt;The most recent user input can also be played back, like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"You chose {$INPUT}"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Also&lt;/span&gt;&lt;span&gt; fields (aka. member variables) of a flow object can be items by wrapping them in '%'.  If a flow class has a member variable:   int  m_numPassengers;  then you can play this value in a prompt like this:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/nomatch&gt;&lt;/noinput&gt;&lt;/prompt&gt;&lt;span style="font-style: italic;"&gt;    "There are {%numPassengers%} passengers"&lt;/span&gt;&lt;prompt&gt;&lt;noinput&gt;&lt;nomatch&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;If you're familiar with SSML then you can use raw prompt items, that have a "raw:" prefix.  These are output as it, and can contain SSML tags.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/nomatch&gt;&lt;/noinput&gt;&lt;/prompt&gt;&lt;span style="font-style: italic;"&gt;    "That's a &amp;lt;emphasis&amp;gt;&lt;string&gt;big&lt;/string&gt;&amp;lt;/emphasis&amp;gt; order!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lastly, there are id prompt items, which are references to an external prompt string in an XML file.  This is useful for multi-lingual apps, or for changing prompts after deployment.  See &lt;a href="http://speakrightframework.blogspot.com/2007/05/prompt-ids-and-prompt-xml-files.html"&gt;Prompt Ids and Prompt XML Files&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"id:sayPrice"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;prompt&gt;&lt;noinput&gt;&lt;nomatch&gt;&lt;span&gt;Let's summarize.  There are seven types of prompt items:&lt;br /&gt;&lt;/span&gt;&lt;/nomatch&gt;&lt;/noinput&gt;&lt;/prompt&gt;&lt;ul&gt;&lt;li&gt;&lt;prompt&gt;&lt;noinput&gt;&lt;nomatch&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;"audio:"&lt;/span&gt;       audio prompts&lt;/span&gt;&lt;/nomatch&gt;&lt;/noinput&gt;&lt;/prompt&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;"M$."&lt;/span&gt;             model values&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;"%&lt;/span&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;value&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;%"&lt;/span&gt; field values (of currently executing flow object)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;".."&lt;/span&gt;                   pause (250 msec for each period)&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;"raw:"&lt;/span&gt;           raw SSML prompts&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;"id:" &lt;/span&gt; id prompts&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span&gt;TTS prompt (any prompt item that doesn't match one of the above types is played as TTS)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;prompt&gt;&lt;noinput&gt;&lt;nomatch&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;/nomatch&gt;&lt;/noinput&gt;&lt;/prompt&gt;&lt;h3&gt;Prompt Conditions&lt;/h3&gt;    &lt;p&gt;By default, all the prompts in a flow object are played. However there are occasions when the playing of a prompt needs to be controlled by a condition. Conditions are evaluated when the flow object is executed; if the condition returns false the prompt is not played.&lt;/p&gt;   &lt;table class="TableClass" cellpadding="2" cellspacing="1"&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td style="font-weight: bold;" class="TableCell"&gt;Condition&lt;/td&gt; &lt;td style="font-weight: bold;" class="TableCell"&gt;Description&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;none&lt;/td&gt; &lt;td class="TableCell"&gt;always play prompt&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;PlayOnce&lt;/td&gt; &lt;td class="TableCell"&gt;only play the first time the flow is executed. If the flow is re-executed (the same flow object executes more than once in a row), don't play the prompt. PlayOnce are useful in menus where the initial prompt may contain information that should only be played once.&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;PlayOnceEver&lt;/td&gt; &lt;td class="TableCell"&gt;only play once during the entire session (phone call).&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;PlayIfEmpty&lt;/td&gt; &lt;td class="TableCell"&gt;only play if the given model variable is empty (""). Useful if you want to play a prompt as long as something has not yet occured.&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;PlayIfNotEmpty&lt;/td&gt; &lt;td class="TableCell"&gt;only play if the given model variable is not empty ("")&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Prompt Rendering&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Prompts are rendered using a pipeline of steps.  The order of the steps has been chosen to maximize usefulness.&lt;/p&gt;   &lt;table class="TableClass" cellpadding="2" cellspacing="1"&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td class="TableCell"&gt;Step&lt;/td&gt; &lt;td class="TableCell"&gt;Description&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;1&lt;/td&gt; &lt;td class="TableCell"&gt;Apply condition.  If false then return&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;2&lt;/td&gt; &lt;td class="TableCell"&gt;Resolve ids.  Read external XML file and replace each prompt id with its specified prompt text&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;3&lt;/td&gt; &lt;td class="TableCell"&gt;Evaluate model values&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;4&lt;/td&gt; &lt;td class="TableCell"&gt;Call fixup handlers in the flow objects.  The IFlow method fixupPrompt allows a flow object to tweak TTS prompt items&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;5&lt;/td&gt; &lt;td class="TableCell"&gt;Merge runs of of TTS items into a single item&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td class="TableCell"&gt;6&lt;/td&gt; &lt;td class="TableCell"&gt;Do audio matching. An external XML file defines TTS text for which an audio file exists. The text is replaced with the audio file.&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;   &lt;p&gt;The result is a list of TTS and/or audio items that are sent to the page writer.&lt;/p&gt;   &lt;h2&gt;Audio matching&lt;/h2&gt;    &lt;p&gt;Audio matching is a technique that lets you use TTS for the initial speech app development. Once the app is fairly stable, record audio files for all the prompts. Then you ceate an audio matching xml file that lists each audio file and the prompt text it replaces. Now when the SpeakRight application runs, matching text is automatically replaced with the audio file.  No source code changes are required.&lt;/p&gt;   &lt;p&gt;The match is a soft match that ignores case and punctuation. That is a prompt item "Dr. Smith lives on Maple Dr." would match an audio-match text of "dr smith lives on maple dr".&lt;/p&gt;   &lt;p&gt;Audio matching works at the item level.  Do we need to suport some tag for spanning multi items???&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-8869024761420281282?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/8869024761420281282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=8869024761420281282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8869024761420281282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/8869024761420281282'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/prompts.html' title='Prompts'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2022621804660958150</id><published>2007-02-17T17:15:00.000-08:00</published><updated>2007-05-02T17:49:27.850-07:00</updated><title type='text'>What is SpeakRight?</title><content type='html'>SpeakRight is an &lt;strong&gt;open-source &lt;/strong&gt;&lt;strong&gt;Java         framework&lt;/strong&gt; for writing speech recognition applications in VoiceXML. Unlike most proprietary speech-app tools, SpeakRight is &lt;a href="http://speakrightframework.blogspot.com/2007/05/benefits-of-code-based-approach.html"&gt;code-based&lt;/a&gt;. Developers write their application in Java using SpeakRight classes and their own extensions. Java IDEs such as Eclipse provide great debugging, and fast Java-aware editing and refactoring.&lt;br /&gt;&lt;br /&gt;SpeakRight is based around the &lt;strong&gt;flow object&lt;/strong&gt; which has a similar role to controls in GUI frameworks. A flow object manages presentation (prompts, grammars, and retry logic), and control flow. In MVC terms, a flow object is both the view and the controller. Flow objects can be customized (by setting properties), or extended using sub-classing. SpeakRight provides built-in objects for standard data types (time, date, alphanum), and for standard flow algorithms (forms, menus, list traversal, confirmation).&lt;br /&gt;&lt;br /&gt;Flow objects can contain sub-flow objects.  This nesting continues all the way out to a single application flow object.  At runtime SpeakRight executes the application flow object.  It may decide that the first thing to do is to execute a sub-flow.  The sub-flow may execute its sub-flow.  And so on.  Nesting continues until a &lt;span style="font-style: italic;"&gt;leaf &lt;/span&gt;flow object that actually produces VoiceXML content is encountered.  At this point, a &lt;span style="font-weight: bold;"&gt;flow stack&lt;/span&gt; has been built up of all the active flow objects.  The topmost item in the stack is the leaf.  Only one flow object executes at a time.  SpeakRight persists itself across HTTP requests (using serialization)  .  The results of VoiceXML page arrive back at the servlet as a new HTTP request.  SpeakRight gives the results to the currently executing flow object.  It can do one of three things:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;execute again, and produce another VoiceXML page&lt;/li&gt;&lt;li&gt;return null to indicate it has finished.  It will be popped off the flow stack and the next flow object will be executed.&lt;/li&gt;&lt;li&gt;"throw" an event.  SpeakRight uses a Throw/Catch style of event handling.  A thrown event causes a search down the stack looking for a handler.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;SpeakRight &lt;span style="font-weight: bold;"&gt;prompts &lt;/span&gt;use a powerful formatting system.  A prompt string such as "The current interest rate is {$M.rate} percent.  Please wait while we get your portfolio {..}{music.wav}" represents:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A TTS (text-to-speech) utteran "The current interest rate is"&lt;/li&gt;&lt;li&gt;a model value&lt;/li&gt;&lt;li&gt;more TTS "percent.  Please wait while we get your portfolio.."&lt;/li&gt;&lt;li&gt;silence (500 msec)&lt;/li&gt;&lt;li&gt;audio file&lt;/li&gt;&lt;/ul&gt;Applications can use &lt;span style="font-style: italic;"&gt;in-place prompts&lt;/span&gt;, such as the one shown.  Or they can use &lt;span style="font-style: italic;"&gt;prompt ids&lt;/span&gt;, such as "id:sayInterestRateAndWait" which is a reference to an external XML file containing the prompt string.  Multi-lingual apps are possible by deploying language-specific prompt XML files.&lt;br /&gt;&lt;br /&gt;SpeakRight &lt;span style="font-weight: bold;"&gt;grammars &lt;/span&gt;are... GRXML files.  I've totally punted in this early version.  Dynamic and GSL prompts later, but for now, get the wonderful Grammar Editor that comes (free) with the Microsoft Speech Application SDK (SASDK for MSS 2004 R2).&lt;br /&gt;&lt;br /&gt;MVC architecture requires a &lt;span style="font-weight: bold;"&gt;Model&lt;/span&gt; and SpeakRight has one.  The model is used to share data between flow objects.  User input (or data retrieved from a database) that needs to be used later in the call flow should be put into the model.  SpeakRight provides binding so this occurs automatically.   In SpeakRight you generate the model using code generation -- a tool called &lt;span style="font-weight: bold;"&gt;MGen&lt;/span&gt;.  You write a simple XML file specifying your model fields (such as "Date departureDate") and MGen generates a type-safe Model.java file.  Your application can now use intellisense (called CodeAssist in Eclipse) to inspect the model variables.  Each model variable has get, set, and clear methods.&lt;br /&gt;&lt;br /&gt;Applications need to have side effects.  Their purpose is to interact with some back-end database to transfer funds, buy a train ticket, or vote.  SpeakRight calls these &lt;span style="font-weight: bold;"&gt;transactions.  &lt;/span&gt;Each flow object, upon finishes, can invoke a transaction.  If the transaction is invoked asynchronously, SpeakRight pauses the callflow until the transaction completes.&lt;br /&gt;&lt;br /&gt;Of course, before we accept data we need to &lt;span style="font-weight: bold;"&gt;validate&lt;/span&gt; it.  Flow objects have a ValidateInput method that is called whenever user input has occurred.  The method can accept or reject the input.  If input is rejected, the flow object is executed again.&lt;br /&gt;&lt;br /&gt;Another part of speech recognition is &lt;span style="font-weight: bold;"&gt;confirmation.  &lt;/span&gt;This is done whenever the recognition  confidence level is below a confirmation level.  SpeakRight uses pluggable confirmation strategies.  Some of the strategies are: None, YesNo, ConfirmAndCorrect, and ImplicitConfirm. You can basically plug any confirmation strategy into any flow object.&lt;br /&gt;&lt;br /&gt;Finally, and most importantly, SpeakRight provides an extensible architecture for re-usable components called &lt;span style="font-weight: bold;"&gt;SRO &lt;/span&gt;(SpeakRight Objects).  These &lt;span style="font-style: italic;"&gt;speech objects &lt;/span&gt;provide standard mechanisms for common tasks.  There are (to come) SROs for input of common data types such as time, date, currency, and zip code.  There are also SROs for common control flow algorithms such as list traversal.  SROs are highly configurable: prompts and grammars can be customized or replaced.  Prompts can be customized at several levels, including pluggable formatters for rendering model values.&lt;br /&gt;&lt;br /&gt;Re-usability is a key technical challenge in the project.  It should be easier (and better) to re-use existing objects than rolling your own.  Prompts, for example, need to be highly flexible.  Users do not like prompts that switch back and forth between TTS and pre-recorded audio.  A single voice is important.  SpeakRight provides an &lt;span style="font-weight: bold;"&gt;audio matching &lt;/span&gt;feature, where all prompt segments are looked up in an audio match XML file that contains a replacement audio file for that segment.  Of course, prompt coverage tools are needed to help build the list of prompts to be sent for professional recording.  These tools are (cough) TBD.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2022621804660958150?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2022621804660958150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2022621804660958150' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2022621804660958150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2022621804660958150'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/what-is-speakright_17.html' title='What is SpeakRight?'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-57050832282063759</id><published>2007-02-17T12:36:00.000-08:00</published><updated>2008-02-01T07:35:07.224-08:00</updated><title type='text'>Tutorial</title><content type='html'>This tutorial uses Eclipse 3.2.1 to build a simple SpeakRight application&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/getting-started.html"&gt;Getting Started&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/tutorial-1-creating-hello-app.html"&gt;Creating a Hello App&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://speakrightframework.blogspot.com/2007/02/tutorial-2-adding-menu.html&lt;br /&gt;"&gt;Adding a Menu&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-57050832282063759?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/57050832282063759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=57050832282063759' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/57050832282063759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/57050832282063759'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/tutorial.html' title='Tutorial'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-7459689734746912707</id><published>2007-02-17T12:33:00.001-08:00</published><updated>2008-02-01T07:21:55.563-08:00</updated><title type='text'>Tutorial 2 - Adding a Menu</title><content type='html'>&lt;p&gt;Let's add a menu to our Hello app.&lt;/p&gt;          &lt;p&gt;add the menu class to app1 (as inner class)&lt;/p&gt;                    &lt;p&gt;here's the grxml file&lt;/p&gt;                             &lt;pre&gt;import org.speakright.core.*;&lt;br /&gt;&lt;br /&gt;public class App1 extends SRApp {&lt;br /&gt;public App1(){super("app1"); //give the app a name (useful for logging);&lt;br /&gt;add(new PromptFlow("Welcome to SpeakRight!"));&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;          &lt;p&gt;This flow will simply say "Welcome to SpeakRight!" and hang up.         &lt;/p&gt;          &lt;p&gt;There are a number of ways to run your app. Eventually you'll         embed it in a Java servlet and point a VoiceXML browser at it. But         for now, let's use the ITest console utility that comes with         SpeakRight. Switch back to Hello.java, which should have been created         when you made the project.&lt;/p&gt;                    &lt;blockquote&gt;           &lt;pre&gt;import org.speakright.itest.*;&lt;br /&gt;public class SRHello {public static void main(String[] args){&lt;br /&gt;System.out.println("SRHello");&lt;br /&gt;SRInteractiveTester tester = new SRInteractiveTester();&lt;br /&gt;App1 app = new App1();&lt;br /&gt;tester.run(app);&lt;br /&gt;System.out.println("Done.");}&lt;br /&gt;}&lt;/pre&gt;         &lt;/blockquote&gt;          &lt;p&gt;OK. Let's run the app. In the Package Explorer, find your class         file Hello.java, right-click and select &lt;strong&gt;Run As&lt;/strong&gt; and         &lt;strong&gt;Java Application&lt;/strong&gt;. ITest runs in the java console.         You should see this in the Console view&lt;/p&gt;          &lt;p&gt;&lt;img alt="Hello app running in the console" src="file:///C:/Source/SRWebSite/v1/images/javaproj_console.bmp" /&gt;&lt;/p&gt;          &lt;p&gt;The "1&gt;" indicates this is the first turn. That is, your app is         about to create it's first VoiceXML page. Type "go" and press Enter.         You'll see some logging and the VoiceXML:&lt;/p&gt;         &lt;pre&gt;&lt;voicexml&gt;&lt;/voicexml&gt;&lt;form&gt;&lt;br /&gt;&lt;block&gt;&lt;br /&gt;&lt;prompt&gt;welcome to SpeakRight &lt;/prompt&gt;&lt;br /&gt;&lt;/block&gt;&lt;br /&gt;&lt;submit&gt;&lt;br /&gt;&lt;/submit&gt; &lt;/form&gt; &lt;/pre&gt;          &lt;p&gt;When a SpeakRight app is in a java servlet, this VoiceXML would be         returned to the VoiceXML server, where it would be executed. The         results of that execution would be sent back to SpeakRight. In this         case, the page simply plays some text-to-speech audio, so there is no         user input to send back. In ITest, we are the VoiceXML platform and         we send back (using the "go" command) the results of executing the         most recent page. So type "go" and press Enter again. The app has         nothing more to do so it finishes, along with ITest.&lt;/p&gt;                    &lt;p&gt;That's it. You've created your first SpeakRight app.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-7459689734746912707?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/7459689734746912707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=7459689734746912707' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7459689734746912707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7459689734746912707'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/tutorial-2-adding-menu.html' title='Tutorial 2 - Adding a Menu'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2145217761097701666</id><published>2007-02-17T12:32:00.000-08:00</published><updated>2007-06-14T10:55:13.266-07:00</updated><title type='text'>Tutorial 1 - Creating an Hello app</title><content type='html'>&lt;em&gt;This tutorial uses Ecplise 3.2.1&lt;/em&gt;          &lt;p&gt;First let's create our flow class. Each app will have a top-level flow object. In the Package Explorer, right-click on your project Hello and select &lt;strong&gt;New / Class&lt;/strong&gt;. Name it App1.  Here's the Package Explorer (ignore Model.java for now)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_-ghvQ2vraN4/RdeiTPsnTDI/AAAAAAAAAAY/PacK6bEc9iA/s1600-h/tut_packageexplorer.bmp"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_-ghvQ2vraN4/RdeiTPsnTDI/AAAAAAAAAAY/PacK6bEc9iA/s320/tut_packageexplorer.bmp" alt="" id="BLOGGER_PHOTO_ID_5032669560124689458" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You         should then be able to edit the App1.java file, adding the         following:&lt;/p&gt;                   &lt;pre&gt;import org.speakright.core.*;&lt;br /&gt;&lt;br /&gt;public class App1 extends SRApp {&lt;br /&gt;public App1() {&lt;br /&gt;add(new PromptFlow("Welcome to SpeakRight!"));&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;          &lt;p&gt;This flow will simply say "Welcome to SpeakRight!" and hang up.         &lt;/p&gt;          &lt;p&gt;There are a number of ways to run your app. Eventually you'll         embed it in a Java servlet and point a VoiceXML browser at it. But         for now, let's use the ITest console utility that comes with         SpeakRight. Switch back to Hello.java, which should have been created         when you made the project.&lt;/p&gt;                    &lt;blockquote&gt;           &lt;pre&gt;import org.speakright.itest.*;&lt;br /&gt;&lt;br /&gt;public class SRHello {public static void main(String[] args) {&lt;br /&gt;System.out.println("SRHello");&lt;br /&gt;&lt;br /&gt;SRInteractiveTester tester = new SRInteractiveTester();&lt;br /&gt;SRFactory factory = new SRFactory();&lt;br /&gt;SRRunner runner = factory.createRunner("", "", "", null);&lt;br /&gt;App1 app = new App1();&lt;br /&gt;tester.run(run, app);&lt;br /&gt;&lt;br /&gt;System.out.println("Done.");}&lt;br /&gt;}&lt;/pre&gt;         &lt;/blockquote&gt;          &lt;p&gt;For a simple app we pass empty strings to createRunner.  For more information on the parameters to pass to createRunner, see &lt;a href="http://speakrightframework.blogspot.com/2007/06/initialization.html"&gt;Initialization&lt;/a&gt;. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;OK. Let's run the app. In the Package Explorer, find your class         file Hello.java, right-click and select &lt;strong&gt;Run As&lt;/strong&gt; and         &lt;strong&gt;Java Application&lt;/strong&gt;. ITest runs in the java console.         You should see this in the Console view&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_-ghvQ2vraN4/Rdei7PsnTEI/AAAAAAAAAAg/cjVdT5nznlg/s1600-h/javaproj_console.bmp"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_-ghvQ2vraN4/Rdei7PsnTEI/AAAAAAAAAAg/cjVdT5nznlg/s320/javaproj_console.bmp" alt="" id="BLOGGER_PHOTO_ID_5032670247319456834" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The "1&gt;" indicates this is the first turn. On each turn your app will create a VoiceXML page. Type "go" and press Enter.         You'll see some logging and the VoiceXML:&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_-ghvQ2vraN4/Rdej-vsnTFI/AAAAAAAAAAo/8AY3eEJm2Sg/s1600-h/tut_console_turn2.bmp"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_-ghvQ2vraN4/Rdej-vsnTFI/AAAAAAAAAAo/8AY3eEJm2Sg/s320/tut_console_turn2.bmp" alt="" id="BLOGGER_PHOTO_ID_5032671406960626770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p&gt;When a SpeakRight app is in a java servlet, this VoiceXML page would be sent to the VoiceXML server (as part of an HTTP reply).  The server would execute the page, and send back the results (as a new HTTP request) . In ITest, we take the place of the VoiceXML server.  In the "go" command we specify the results of executing the         most recent page.  In this         case, the page is &lt;span style="font-style: italic;"&gt;output only; &lt;/span&gt;it only plays text-to-speech audio, so there is no         user input to send back.  So type "go" and press Enter again. The app has         nothing more to do so it finishes, along with ITest.&lt;/p&gt;                    That's it. You've created your first SpeakRight app.  To see how a fully-functioned app is written see &lt;a href="http://speakrightframework.blogspot.com/2007/04/simpsons-demo.html"&gt;Simpsons Demo&lt;/a&gt;, or get more documentation at &lt;a href="http://speakrightframework.blogspot.com/2007/02/table-of-contents.html"&gt;Table Of Contents&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2145217761097701666?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2145217761097701666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2145217761097701666' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2145217761097701666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2145217761097701666'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/tutorial-1-creating-hello-app.html' title='Tutorial 1 - Creating an Hello app'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_-ghvQ2vraN4/RdeiTPsnTDI/AAAAAAAAAAY/PacK6bEc9iA/s72-c/tut_packageexplorer.bmp' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-7240136969645660797</id><published>2007-02-17T12:30:00.001-08:00</published><updated>2007-05-17T04:03:11.601-07:00</updated><title type='text'>Getting Started</title><content type='html'>&lt;p&gt;After reading &lt;a href="http://speakrightframework.blogspot.com/2007/02/what-is-speakright_17.html"&gt;What is SpeakRight&lt;/a&gt; and perhaps some other articles in &lt;a href="http://speakrightframework.blogspot.com/2007/02/table-of-contents.html"&gt;Table of Contents,&lt;/a&gt; you're ready to install and try it out.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold;"&gt;Installation&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Download the code from &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=189014"&gt;here&lt;/a&gt;. I used Eclipse 3.2.1 which uses Java 1 (jre/jdk) 1.5.0.11 and Tomcat 5.5.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You'll also need&lt;/p&gt;         &lt;ul&gt;&lt;li&gt;log4j 1.2.8 (comes with Eclipse)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;StringTemplate 3.0 from &lt;a href="http://www.stringtemplate.org/download.html"&gt;here&lt;/a&gt; which includes antlr 2.7.7&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;          &lt;p&gt;This tutorial assumes you are using Eclipse 3.2.1.  Any Java IDE should work.&lt;br /&gt;&lt;/p&gt;          &lt;p&gt;Start Eclipse and select &lt;b&gt;File / New / Project&lt;/b&gt; and select         &lt;strong&gt;New Java Project.&lt;/strong&gt; Name it "SRHello".&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;          &lt;p&gt;In the Package Explorer (on the left-hand side of your screen),         right-click and select &lt;strong&gt;Properties&lt;/strong&gt;. Select         &lt;strong&gt;Java Build Path&lt;/strong&gt; and then the         &lt;strong&gt;Libraries&lt;/strong&gt; tab.             &lt;/p&gt;&lt;p&gt;Select &lt;strong&gt;Add External Jars&lt;/strong&gt; and add SpeakRight,         Log4J, StringTemplate, and antlr.  Here's the dialog box.  Ignore JUnit and XMLUnit; they're not needed at this time.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_-ghvQ2vraN4/RdegXPsnTCI/AAAAAAAAAAM/F79uaKeqhQE/s1600-h/javaproj_properties.bmp"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_-ghvQ2vraN4/RdegXPsnTCI/AAAAAAAAAAM/F79uaKeqhQE/s320/javaproj_properties.bmp" alt="" id="BLOGGER_PHOTO_ID_5032667429820910626" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now we're ready to write some code! On to the &lt;a href="http://speakrightframework.blogspot.com/2007/02/tutorial-1-creating-hello-app.html"&gt;SRHello app&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-7240136969645660797?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/7240136969645660797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=7240136969645660797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7240136969645660797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/7240136969645660797'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/getting-started.html' title='Getting Started'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_-ghvQ2vraN4/RdegXPsnTCI/AAAAAAAAAAM/F79uaKeqhQE/s72-c/javaproj_properties.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-1490294187517786333</id><published>2007-02-17T12:26:00.001-08:00</published><updated>2007-12-06T06:38:16.796-08:00</updated><title type='text'>Frequently Asked Questions</title><content type='html'>&lt;h5&gt;What is SpeakRight?&lt;/h5&gt;          &lt;p&gt;SpeakRight is an open-source Java framwork for writing speech         recognition applications in VoiceXML.SpeakRight apps live inside a         web server, such as a JSP servlet. The SpeakRight runtime executes a         set of flow objects, and generates VoiceXML pages, one a time.         SpeakRight is stateless so it can work across multiple HTTP requests.         &lt;/p&gt;          &lt;h5&gt;How is it licensed?&lt;/h5&gt;          &lt;p&gt;SpeakRight is licensed under the OSS-approved Eclipse Public         License (EPL). Under this license anyone can download and use         SpeakRight. There are no license fees for use within a commercial         product. EPL's main restriction is that if you modify SpeakRight         source files and distribute them, then you must release those files         under the EPL. Of course, your own source files (that may extend or         use SpeakRight classes) are excempt.&lt;br /&gt;&lt;/p&gt;&lt;h5&gt;Where does the name SpeakRight come from?&lt;/h5&gt;          &lt;p&gt;The name comes from the term "speak right into the microphone".  Interviewers used this phrase in the early days of TV.  People being interviewed didn't know how to behave with this new technology, and often froze on camera.  The goal of the SpeakRight Framework is to help make people comfortable with with speech recognition applications.&lt;br /&gt;&lt;/p&gt;&lt;h5&gt;Why use SpeakRight?&lt;br /&gt;&lt;/h5&gt;          &lt;p&gt;I have written a number of speech apps on different SALT and VoiceXML platforms.  After trying a number of different approaches (raw VoiceXML, drag-and-drop toolkits), I came to believe that the complexity of speech application VUIs required a code-based approach (see &lt;a href="http://speakrightframework.blogspot.com/2007/05/benefits-of-code-based-approach.html"&gt;Benefits of a Code-Based Approach&lt;/a&gt;)&lt;br /&gt;&lt;/p&gt;&lt;h5&gt;What's the current status?&lt;/h5&gt;          &lt;p&gt;The current status is alpha. Single-slot questions are supported, with NBest support. Audio can be audio files, TTS, or generated values (such as today's date, or an application variable).  Inline, built-in, and external grammars are supported.  Also  supported: control flow, event handling, the model, DTMF-only-mode, and confirmation.  Transfer and Record too.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Testing can be done from JUnit, a console app, from a web browser (apps can generate an HTML version of themselves), or from a VoiceXML platform.&lt;/p&gt;Not supported: mixed initiative, hot words (link tag).&lt;br /&gt;&lt;h5&gt;What platforms does it run on?&lt;/h5&gt;         &lt;br /&gt;&lt;p&gt;Currently has only been tested on Voxeo's free &lt;a href="http://community.voxeo.com/"&gt;site.&lt;/a&gt;  SpeakRight uses a template engine (&lt;a href="http://speakrightframework.blogspot.com/2007/12/stringtemplate-template-engine.html"&gt;see String Template template engine&lt;/a&gt;) so changing the output is often as easy as changing the template file.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-1490294187517786333?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/1490294187517786333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=1490294187517786333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/1490294187517786333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/1490294187517786333'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/frequently-asked-questions.html' title='Frequently Asked Questions'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-2168005933057296740</id><published>2007-02-17T12:20:00.001-08:00</published><updated>2007-02-17T12:20:53.997-08:00</updated><title type='text'>What is SpeakRight?</title><content type='html'>&lt;p&gt;SpeakRight is an &lt;strong&gt;open-source &lt;/strong&gt;&lt;strong&gt;Java         framework&lt;/strong&gt; for writing speech recognition applications in         VoiceXML.Unlike most proprietary speech-app tools, SpeakRight is         code-based. Developers write their application in Java using         SpeakRight classes and their own extensions. Java IDEs such as         Eclipse provide great debugging, and fast Java-aware editing and         refactoring. &lt;/p&gt;          &lt;p&gt;The basic class is the &lt;strong&gt;flow object&lt;/strong&gt; which has a         similar role to controls in GUI frameworks. A flow object manages         presentation (prompts, grammars, and retry logic), and control flow.         In MVC terms, a flow object is both the view and the controller. Flow         objects can be customized (by setting properties), or extended using         sub-classing. SpeakRight provides built-in objects for standard data         types (time, date, alphanum), and for standard flow algorithms         (forms, menus, list traversal, confirmation). Your application can         combine and customize these built-in flows, or create your own.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-2168005933057296740?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/2168005933057296740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=2168005933057296740' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2168005933057296740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/2168005933057296740'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/what-is-speakright.html' title='What is SpeakRight?'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-1064444331553068990</id><published>2007-02-17T12:18:00.000-08:00</published><updated>2007-12-06T06:32:37.139-08:00</updated><title type='text'>Features</title><content type='html'>SpeakRight provides the features needed to create a quality VUI (Voice User Interface):&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;VoiceXML 2.1 (partial support currently, more to come.  See &lt;a href="http://speakrightframework.blogspot.com/2007/05/voicexml-tags-supported.html"&gt;VoiceXML Tags Supported&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Inline, built-in, and external grammars (GSL and GRXML).&lt;/li&gt;&lt;li&gt;Prompts can be TTS, audio, or rendered data values. External             prompts in XML files for multi-lingual apps and post-deployment flexibility.&lt;/li&gt;&lt;li&gt;Built-in support for noinput, nomatch, and help events.  Escalated prompts.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Built-in validation. A flow object's ValidateInput method can validate user input and accept, ignore, or retry the input.&lt;/li&gt;&lt;li&gt;NBest with confirmation of each NBest result.  Optional skip list.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A library of re-usable "speech objects", called SROs is provided for common tasks such as time and dates, numbers, and currency.&lt;/li&gt;&lt;li&gt;Disconnect, Transfer, and GotoUrl&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Flow Objects. A flow object represents a dialog state such as asking for a flight number. Each flow object is rendered as one or more VoiceXML pages. Flow objects are fully object-oriented: you can use inheritance, composition, and nesting to combine flow objects. The speech application itself is a flow object.&lt;/li&gt;&lt;li&gt;Throw/catch used for errors such as max-retries-exceeded,             validation-failed, or user-defined events.  This simplifies callflow development because it encourages centralized error handling (although local error handling can be done when needed).  Also, throw/catch increases software re-use because (unlike a 'goto') it decouples the part of the app throwing the error from the part of the app that handles it.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;MVC architecture. Built-in model allows sharing of data between             flow objects.&lt;/li&gt;&lt;li&gt;Flow objects can invoke business logic upon completion.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Extension points are available in the framework for customization.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Testing features&lt;br /&gt;&lt;ul&gt;&lt;li&gt;callflows can be unit tested in JUnit&lt;/li&gt;&lt;li&gt;interactive tester for executing callflows using the keyboard.&lt;/li&gt;&lt;li&gt;SpeakRight servlets have an HTML output mode.  This can be used to test a callflow using an ordinary web browser.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;SpeakRight doesn't provide features for data access or web services.  Other open-source projects already do those things very well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-1064444331553068990?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/1064444331553068990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=1064444331553068990' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/1064444331553068990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/1064444331553068990'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/features.html' title='Features'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-350232640321685673.post-4830899078456722357</id><published>2007-02-17T11:52:00.000-08:00</published><updated>2007-02-17T11:55:19.798-08:00</updated><title type='text'>Pre-launch stuff</title><content type='html'>Getting ready to launch SpeakRight has been a steep learning curve.  After trying for four hours to create a web site using Amaya, I gave up and came here :)  The HTML editing is not bad in Amaya, and you can see and edit the tags structure as well.  They even have a neat feature that shows all the CSS tags affecting the currently selected item.  But managing frames and multiple pages is a pain.  Whereas here on Blogger you are more limited in formatting but everything else is managed, and they even do the backup.  Nice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/350232640321685673-4830899078456722357?l=speakrightframework.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://speakrightframework.blogspot.com/feeds/4830899078456722357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=350232640321685673&amp;postID=4830899078456722357' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4830899078456722357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/350232640321685673/posts/default/4830899078456722357'/><link rel='alternate' type='text/html' href='http://speakrightframework.blogspot.com/2007/02/pre-launch-stuff.html' title='Pre-launch stuff'/><author><name>IanRae</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
