<br><br><div class="gmail_quote">On Fri, Dec 4, 2009 at 7:58 AM, Neil Patel <span dir="ltr"><<a href="mailto:neilp@cs.stanford.edu">neilp@cs.stanford.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi All,<br><br>I haven't found a substantial example of IVR applications implemented in lua. Can anyone suggest where to look? My issue has to do with appropriate coding style.<br><br>I am implementing a voice message board application in lua. I want to allow the user to dial buttons to navigate forward and back in the list of messages. One way to implement playmessage() is to check for a forward/back command while playing the current message, and if a command is given to invoke playmessage() with the prev/next message in the list. However, this leaves a chain of unreturned playmessage calls on the execution stack (a recursive function).<br>
<br>Alternatively, the playmessage() function can return control to its caller (perhaps a while loop that spins forever) and pass back a code to indicate the command. The caller acts accordingly. This is non-recursive, but for anything but simple applications this style becomes tedious as you start needing to pass back more info and up longer chains of functions.<br>
<br>Any guidance on this would be appreciated.<br><br>Thanks,<br><font color="#888888">Neil<br></font></blockquote><div><br>Sorry for the late response. Tony and I have just gotten to the point in the book we're writing that deals with IVRs so I've started looking at this much more closely. Lua (and Perl, PHP, and the other swig'd langs) support a light OOP way of defining IVR menus (via the IVRMenu class, btw) in a dynamic way. I've got the demo IVR all converted to a Lua script with the exception that I've got a bug to track down when using "menu-sub" as an action. (Says that the menu is invalid when I try it; I am gonna work with bkw when we get a few minutes...)<br>
<br>Anyway, here's what I've got so far and I intend to drop it into the scripts/lua directory in the source tree once we confirm that it all works.<br></div></div><br>-- lua_ivr.lua<br>--<br>-- This script is virtually identical to the demo_ivr defined in conf/autoload_configs/ivr.conf.xml<br>
-- It uses the same sound files and mostly the same settings<br>-- It is intended to be used as an example of how you can use Lua to create dynamic IVRs<br>--<br><br>-- This hash defines the main IVR menu. It is equivalent to the <menu name="demo_ivr" ... > lines in ivr.conf.xml<br>
ivr_def = {<br> ["main"] = undef,<br> ["name"] = "demo_ivr_lua",<br> ["greet_long"] = "phrase:demo_ivr_main_menu",<br> ["greet_short"] = "phrase:demo_ivr_main_menu_short",<br>
["invalid_sound"] = "ivr/ivr-that_was_an_invalid_entry.wav",<br> ["exit_sound"] = "voicemail/vm-goodbye.wav",<br> ["confirm_macro"] = "",<br>
["confirm_key"] = "",<br> ["tts_engine"] = "flite",<br> ["tts_voice"] = "rms",<br> ["confirm_attempts"] = "3",<br>
["inter_digit_timeout"] = "2000",<br> ["digit_len"] = "4",<br> ["timeout"] = "10000",<br> ["max_failures"] = "3",<br>
["max_timeouts"] = "2"<br>}<br><br>-- top is an object of class IVRMenu<br>-- pass in all 16 args to the constructor to define a new IVRMenu object<br>top = freeswitch.IVRMenu(<br> ivr_def["main"],<br>
ivr_def["name"],<br> ivr_def["greet_long"],<br> ivr_def["greet_short"],<br> ivr_def["invalid_sound"],<br> ivr_def["exit_sound"],<br> ivr_def["confirm_macro"],<br>
ivr_def["confirm_key"],<br> ivr_def["tts_engine"],<br> ivr_def["tts_voice"],<br> ivr_def["confirm_attempts"],<br> ivr_def["inter_digit_timeout"],<br> ivr_def["digit_len"],<br>
ivr_def["timeout"],<br> ivr_def["max_failures"],<br> ivr_def["max_timeouts"]<br>);<br><br>-- bindAction args = action, param, digits<br>-- The following bindAction line is the equivalent of this XML from demo_ivr in ivr.conf.xml<br>
-- <entry action="menu-exec-app" digits="2" param="transfer 9996 XML default"/><br>top:bindAction("menu-exec-app", "transfer 9996 XML default", "2");<br>top:bindAction("menu-exec-app", "transfer 9999 XML default", "3");<br>
top:bindAction("menu-exec-app", "transfer 9991 XML default", "4");<br>top:bindAction("menu-exec-app", "bridge sofia/${domain}/<a href="mailto:888@conference.freeswitch.org">888@conference.freeswitch.org</a>", "1");<br>
top:bindAction("menu-exec-app", "transfer 1234*256 enum", "5");<br>top:bindAction("menu-sub", "demo_ivr_submenu","6");<br>top:bindAction("menu-exec-app", "transfer $1 XML features", "/^(10[01][0-9])$/");<br>
top:bindAction("menu-top", "demo_ivr_lua","9");<br><br>-- This hash defines the main IVR sub-menu. It is equivalent to the <menu name="demo_ivr_submenu" ... > lines in ivr.conf.xml<br>
ivr_sub_def = {<br> ["main"] = undef,<br> ["name"] = "demo_ivr_submenu_lua",<br> ["greet_long"] = "phrase:demo_ivr_sub_menu",<br>
["greet_short"] = "phrase:demo_ivr_main_sub_menu_short",<br> ["invalid_sound"] = "ivr/ivr-that_was_an_invalid_entry.wav",<br> ["exit_sound"] = "voicemail/vm-goodbye.wav",<br>
["confirm_macro"] = "",<br> ["confirm_key"] = "",<br> ["tts_engine"] = "flite",<br> ["tts_voice"] = "rms",<br>
["confirm_attempts"] = "3",<br> ["inter_digit_timeout"] = "2000",<br> ["digit_len"] = "4",<br> ["timeout"] = "15000",<br>
["max_failures"] = "3",<br> ["max_timeouts"] = "2"<br>}<br><br>-- sub_menu is an object of class IVRMenu<br>-- pass in all 16 args to the constructor to define a new IVRMenu object<br>
sub_menu = freeswitch.IVRMenu(<br> ivr_sub_def["main"],<br> ivr_sub_def["name"],<br> ivr_sub_def["greet_long"],<br> ivr_sub_def["greet_short"],<br> ivr_sub_def["invalid_sound"],<br>
ivr_sub_def["exit_sound"],<br> ivr_sub_def["confirm_macro"],<br> ivr_sub_def["confirm_key"],<br> ivr_sub_def["tts_engine"],<br> ivr_sub_def["tts_voice"],<br>
ivr_sub_def["confirm_attempts"],<br> ivr_sub_def["inter_digit_timeout"],<br> ivr_sub_def["digit_len"],<br> ivr_sub_def["timeout"],<br> ivr_sub_def["max_failures"],<br>
ivr_sub_def["max_timeouts"]<br>);<br><br>-- Bind the action "menu-top" to the * key<br>sub_menu:bindAction("menu-top","demo_ivr_lua","*");<br>--sub_menu:execute(session,"demo_ivr_submenu_lua");<br>
<br>-- Run the main menu<br>top:execute(session, "demo_ivr_lua");<br><br><br>-MC<br>