<br><br><div class="gmail_quote">On Fri, Dec 4, 2009 at 7:58 AM, Neil Patel <span dir="ltr">&lt;<a href="mailto:neilp@cs.stanford.edu">neilp@cs.stanford.edu</a>&gt;</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&#39;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&#39;re writing that deals with IVRs so I&#39;ve started looking at this much more closely. Lua (and Perl, PHP, and the other swig&#39;d langs) support a light OOP way of defining IVR menus (via the IVRMenu class, btw) in a dynamic way. I&#39;ve got the demo IVR all converted to a Lua script with the exception that I&#39;ve got a bug to track down when using &quot;menu-sub&quot; 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&#39;s what I&#39;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 &lt;menu name=&quot;demo_ivr&quot; ... &gt; lines in ivr.conf.xml<br>
ivr_def = {<br>    [&quot;main&quot;]                = undef,<br>    [&quot;name&quot;]                = &quot;demo_ivr_lua&quot;,<br>    [&quot;greet_long&quot;]          = &quot;phrase:demo_ivr_main_menu&quot;,<br>    [&quot;greet_short&quot;]         = &quot;phrase:demo_ivr_main_menu_short&quot;,<br>
    [&quot;invalid_sound&quot;]       = &quot;ivr/ivr-that_was_an_invalid_entry.wav&quot;,<br>    [&quot;exit_sound&quot;]          = &quot;voicemail/vm-goodbye.wav&quot;,<br>    [&quot;confirm_macro&quot;]       = &quot;&quot;,<br>
    [&quot;confirm_key&quot;]         = &quot;&quot;,<br>    [&quot;tts_engine&quot;]          = &quot;flite&quot;,<br>    [&quot;tts_voice&quot;]           = &quot;rms&quot;,<br>    [&quot;confirm_attempts&quot;]    = &quot;3&quot;,<br>
    [&quot;inter_digit_timeout&quot;] = &quot;2000&quot;,<br>    [&quot;digit_len&quot;]           = &quot;4&quot;,<br>    [&quot;timeout&quot;]             = &quot;10000&quot;,<br>    [&quot;max_failures&quot;]        = &quot;3&quot;,<br>
    [&quot;max_timeouts&quot;]        = &quot;2&quot;<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[&quot;main&quot;],<br>
    ivr_def[&quot;name&quot;],<br>    ivr_def[&quot;greet_long&quot;],<br>    ivr_def[&quot;greet_short&quot;],<br>    ivr_def[&quot;invalid_sound&quot;],<br>    ivr_def[&quot;exit_sound&quot;],<br>    ivr_def[&quot;confirm_macro&quot;],<br>
    ivr_def[&quot;confirm_key&quot;],<br>    ivr_def[&quot;tts_engine&quot;],<br>    ivr_def[&quot;tts_voice&quot;],<br>    ivr_def[&quot;confirm_attempts&quot;],<br>    ivr_def[&quot;inter_digit_timeout&quot;],<br>    ivr_def[&quot;digit_len&quot;],<br>
    ivr_def[&quot;timeout&quot;],<br>    ivr_def[&quot;max_failures&quot;],<br>    ivr_def[&quot;max_timeouts&quot;]<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>
-- &lt;entry action=&quot;menu-exec-app&quot; digits=&quot;2&quot; param=&quot;transfer 9996 XML default&quot;/&gt;<br>top:bindAction(&quot;menu-exec-app&quot;, &quot;transfer 9996 XML default&quot;, &quot;2&quot;);<br>top:bindAction(&quot;menu-exec-app&quot;, &quot;transfer 9999 XML default&quot;, &quot;3&quot;);<br>
top:bindAction(&quot;menu-exec-app&quot;, &quot;transfer 9991 XML default&quot;, &quot;4&quot;);<br>top:bindAction(&quot;menu-exec-app&quot;, &quot;bridge sofia/${domain}/<a href="mailto:888@conference.freeswitch.org">888@conference.freeswitch.org</a>&quot;, &quot;1&quot;);<br>
top:bindAction(&quot;menu-exec-app&quot;, &quot;transfer 1234*256 enum&quot;, &quot;5&quot;);<br>top:bindAction(&quot;menu-sub&quot;, &quot;demo_ivr_submenu&quot;,&quot;6&quot;);<br>top:bindAction(&quot;menu-exec-app&quot;, &quot;transfer $1 XML features&quot;, &quot;/^(10[01][0-9])$/&quot;);<br>
top:bindAction(&quot;menu-top&quot;, &quot;demo_ivr_lua&quot;,&quot;9&quot;);<br><br>-- This hash defines the main IVR sub-menu. It is equivalent to the &lt;menu name=&quot;demo_ivr_submenu&quot; ... &gt; lines in ivr.conf.xml<br>
ivr_sub_def = {<br>    [&quot;main&quot;]                = undef,<br>    [&quot;name&quot;]                = &quot;demo_ivr_submenu_lua&quot;,<br>    [&quot;greet_long&quot;]          = &quot;phrase:demo_ivr_sub_menu&quot;,<br>
    [&quot;greet_short&quot;]         = &quot;phrase:demo_ivr_main_sub_menu_short&quot;,<br>    [&quot;invalid_sound&quot;]       = &quot;ivr/ivr-that_was_an_invalid_entry.wav&quot;,<br>    [&quot;exit_sound&quot;]          = &quot;voicemail/vm-goodbye.wav&quot;,<br>
    [&quot;confirm_macro&quot;]       = &quot;&quot;,<br>    [&quot;confirm_key&quot;]         = &quot;&quot;,<br>    [&quot;tts_engine&quot;]          = &quot;flite&quot;,<br>    [&quot;tts_voice&quot;]           = &quot;rms&quot;,<br>
    [&quot;confirm_attempts&quot;]    = &quot;3&quot;,<br>    [&quot;inter_digit_timeout&quot;] = &quot;2000&quot;,<br>    [&quot;digit_len&quot;]           = &quot;4&quot;,<br>    [&quot;timeout&quot;]             = &quot;15000&quot;,<br>
    [&quot;max_failures&quot;]        = &quot;3&quot;,<br>    [&quot;max_timeouts&quot;]        = &quot;2&quot;<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[&quot;main&quot;],<br>    ivr_sub_def[&quot;name&quot;],<br>    ivr_sub_def[&quot;greet_long&quot;],<br>    ivr_sub_def[&quot;greet_short&quot;],<br>    ivr_sub_def[&quot;invalid_sound&quot;],<br>
    ivr_sub_def[&quot;exit_sound&quot;],<br>    ivr_sub_def[&quot;confirm_macro&quot;],<br>    ivr_sub_def[&quot;confirm_key&quot;],<br>    ivr_sub_def[&quot;tts_engine&quot;],<br>    ivr_sub_def[&quot;tts_voice&quot;],<br>
    ivr_sub_def[&quot;confirm_attempts&quot;],<br>    ivr_sub_def[&quot;inter_digit_timeout&quot;],<br>    ivr_sub_def[&quot;digit_len&quot;],<br>    ivr_sub_def[&quot;timeout&quot;],<br>    ivr_sub_def[&quot;max_failures&quot;],<br>
    ivr_sub_def[&quot;max_timeouts&quot;]<br>);<br><br>-- Bind the action &quot;menu-top&quot; to the * key<br>sub_menu:bindAction(&quot;menu-top&quot;,&quot;demo_ivr_lua&quot;,&quot;*&quot;);<br>--sub_menu:execute(session,&quot;demo_ivr_submenu_lua&quot;);<br>
<br>-- Run the main menu<br>top:execute(session, &quot;demo_ivr_lua&quot;);<br><br><br>-MC<br>