Monday, February 26, 2007

Announcing the SpeakRight Framework

There's been a big change in direction for me in the last month. I'm going open-source. Spent the last month learning Java and Eclipse...and creating an open-source VoiceXML framework called the SpeakRight Framework. It's a code-based approach to writing speech recognition apps that, I believe, results in much higher code re-use and therefore faster development time. Also, modern Java IDEs are amazingly smart and helpful. A good Intellisense (called Code Assist in Eclipse) is as good as a GUI-based/property page approach.

Currently SpeakRight has only been tested on the Voxeo community site. It's VoiceXML 2.0.

A key part of the plan are "SROs". SpeakRight Objects are re-usable speech objects that, being open-source, should help encourage a growing body of components to build speech apps out of.

Can't wait to try SpeakRight out on Linux, and on MSS 2007!

Tuesday, February 13, 2007

Grokking StringTemplate

The StringTemplate template engine is a powerful tool for generating markup text or code. It does, though, take a little getting used to. The templates may like a type of programming language, but there are some key differences. And since it's not compiled, bad syntax may just fail silently. Luckily it's quick to try things.

Update: I have corrected errors in the original post. Namely $if(it.CountIsOne)$ is the syntax for referencing $it$ inside an $if$.

First of all let's start with something that works. We want a field tag to output a prompt tag for each prompt in the list promptL Assume promptL contains an ArrayList of two strings "a" and "b". This is the XML we want (ignoring whitespace issues)

<field>
<prompt>some a</prompt>
<prompt>some b</prompt>
</field>


Here are the templates that successfully did this.

//generate the field tag
field(promptL) ::= << <field> $prompts(promptL)$ </field> >>

//generate a tag for each item in the list. There are other prompt tags so we parameterize tagname
prompts(promptL) ::= << $promptL:prompt(tagname="prompt"); separator="\n"$ >>

//output a single tag
prompt(tagname) ::= << <$tagname$>some $it$</tagname>
>>


Now let's add one thing to the output and see what template changes are required. Let's say we want each prompt tag to have a count attribute that is "1" for the first tag, "2" for the second and so on. Like this:javascript:void(0)
Publish

<field>
<prompt count="1">some a</prompt>
<prompt count="2">some b</prompt>
</field>


This is easy. We can just use the built-in $i$ to do this:

prompt(tagname) ::= << <$tagname$ count="$i$">some $it$</tagname>
>>

Now let's say we want to output the count attribute only when the count is greater than "1". This is where things got tricky.

This DOESN'T WORK. ST doesn't let you compare values in $if$. This would go against the spirit of ST whose goal is a strict seperation between presentation and model logic.

prompt(tagname) ::= << $if($it.count$=="1")$ <$tagname$ count="$i$">some $it$</tagname>
$else$
<$tagname$ count="$i$">some $it$</tagname>
$endif$
>>
Maybe we can replace the strings in promptL with Java objects that have a getCountIsOne method. We'll also need a getText method to get the string as well. Recall that $it.someFunc$ resolves in Java to a search for a method named getSomeFunc().

This WORKS!. Just remember the syntax is is to leave the '$' characters off it when inside a $if$. You're inside $$ already.

prompt(tagname) ::= << $if(it.countIsOne)$ <$tagname$>some $it.text$</tagname>
$else$
<$tagname$ count="$i$">some $it.text$</tagname>
$endif$
>>

Another approach is template application. We change our Java method to getCountNotOne and have it return null when it's the first item in the list, and the count otherwise.

This WORKS! We apply the template docountattr on $it$

prompt(tagname) ::= << <$tagname$ $it.countNotOne:docountattr()$>$it.text()$</tagname>
>>
//a way of outputting count attr only when count not 1
docountattr() ::= << count="$it$">>

Template application is powerful. You can pass parameters in as well.

THIS WORKS!. We're applying the template prompt with two parameters tagname and bargeIn.

//generate a tag for each item in the list. There are other prompt tags so we parameterize tagname
prompts(promptL) ::= << $promptL:prompt(tagname="prompt",bargeIn="true"); separator="\n"$ >>

prompt(tagname, index) ::= << $if(it.CountIsOne)$ <$tagname$ count="$i$" bargeIn="$bargeIn$">some $it$</tagname>
$else$
<$tagname$ count="$i$"
bargeIn="$bargeIn$">some $it$</tagname>
$endif$
>>


Once you've grokked things, StringTemplate gives you excellent separation of presentation from logic, and is very good at extracting what it needs from ordinary Java objects.

Friday, February 09, 2007

Learning Java

After years in the Microsoft I am finally learning Java and Eclipse. For anyone familiar with C#, Java is extremely close but feels its age. No properties, delegates, or events? I can live without them. Eclipse however is another story. What AN AMAZING PIECE OF SOFTWARE! Miles ahead of Visual Studio in many areas. Mainly it just works; which is a huge kudo to any piece of complicated software.

And Eclipse is free. In fact, one person with a laptop, GMail, Eclipse, and SourceForge is the equivalent of a five person company from the 1980s.

Open-source software is unstoppable in many ways. You just can't compete with free. Software tool vendors have to keep moving into more and more niche areas. All the big ones, like source controls, IDEs, and bug tracking, are well covered by OSS. That being said, Microsoft has something like 50 billion dollars in the bank. They could not earn a cent for the next ten years and keep paying every employee. That's kind of unstoppable too!

Saturday, February 03, 2007

Daily backup of a laptop

Thanks to Gerald Gibson Jr.'s great article I now have a free way to do daily backups of my laptop. Windows natively supports the zip format (as "compressed folders"). The article is a C# program that generates ZIP files using the Shell API.

(Be sure to get the latest version from Gerald's web site)

My app zips several important directories into zip files in c:\zip. Then, using a free account at box.net I upload the zip files daily. The free account has a limit of 1 GB and each file must be less than 10 MB. But for 5$ a month you get much larger maximums.

Not the finest solution; but it'll do for now. KISS.

Update: A Mozilla plug-in called GSpace turns your GMail account into a FTP site. Each file you upload becomes an e-mail. GMail now has 2.5 GB of storage.