[Freeswitch-users] IVR apps in lua
Michael Collins
msc at freeswitch.org
Mon Dec 14 12:58:55 PST 2009
On Fri, Dec 4, 2009 at 7:58 AM, Neil Patel <neilp at cs.stanford.edu> wrote:
> Hi All,
>
> 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.
>
> 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).
>
> 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.
>
> Any guidance on this would be appreciated.
>
> Thanks,
> Neil
>
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...)
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.
-- lua_ivr.lua
--
-- This script is virtually identical to the demo_ivr defined in
conf/autoload_configs/ivr.conf.xml
-- It uses the same sound files and mostly the same settings
-- It is intended to be used as an example of how you can use Lua to create
dynamic IVRs
--
-- This hash defines the main IVR menu. It is equivalent to the <menu
name="demo_ivr" ... > lines in ivr.conf.xml
ivr_def = {
["main"] = undef,
["name"] = "demo_ivr_lua",
["greet_long"] = "phrase:demo_ivr_main_menu",
["greet_short"] = "phrase:demo_ivr_main_menu_short",
["invalid_sound"] = "ivr/ivr-that_was_an_invalid_entry.wav",
["exit_sound"] = "voicemail/vm-goodbye.wav",
["confirm_macro"] = "",
["confirm_key"] = "",
["tts_engine"] = "flite",
["tts_voice"] = "rms",
["confirm_attempts"] = "3",
["inter_digit_timeout"] = "2000",
["digit_len"] = "4",
["timeout"] = "10000",
["max_failures"] = "3",
["max_timeouts"] = "2"
}
-- top is an object of class IVRMenu
-- pass in all 16 args to the constructor to define a new IVRMenu object
top = freeswitch.IVRMenu(
ivr_def["main"],
ivr_def["name"],
ivr_def["greet_long"],
ivr_def["greet_short"],
ivr_def["invalid_sound"],
ivr_def["exit_sound"],
ivr_def["confirm_macro"],
ivr_def["confirm_key"],
ivr_def["tts_engine"],
ivr_def["tts_voice"],
ivr_def["confirm_attempts"],
ivr_def["inter_digit_timeout"],
ivr_def["digit_len"],
ivr_def["timeout"],
ivr_def["max_failures"],
ivr_def["max_timeouts"]
);
-- bindAction args = action, param, digits
-- The following bindAction line is the equivalent of this XML from demo_ivr
in ivr.conf.xml
-- <entry action="menu-exec-app" digits="2" param="transfer 9996 XML
default"/>
top:bindAction("menu-exec-app", "transfer 9996 XML default", "2");
top:bindAction("menu-exec-app", "transfer 9999 XML default", "3");
top:bindAction("menu-exec-app", "transfer 9991 XML default", "4");
top:bindAction("menu-exec-app", "bridge sofia/${domain}/
888 at conference.freeswitch.org", "1");
top:bindAction("menu-exec-app", "transfer 1234*256 enum", "5");
top:bindAction("menu-sub", "demo_ivr_submenu","6");
top:bindAction("menu-exec-app", "transfer $1 XML features",
"/^(10[01][0-9])$/");
top:bindAction("menu-top", "demo_ivr_lua","9");
-- This hash defines the main IVR sub-menu. It is equivalent to the <menu
name="demo_ivr_submenu" ... > lines in ivr.conf.xml
ivr_sub_def = {
["main"] = undef,
["name"] = "demo_ivr_submenu_lua",
["greet_long"] = "phrase:demo_ivr_sub_menu",
["greet_short"] = "phrase:demo_ivr_main_sub_menu_short",
["invalid_sound"] = "ivr/ivr-that_was_an_invalid_entry.wav",
["exit_sound"] = "voicemail/vm-goodbye.wav",
["confirm_macro"] = "",
["confirm_key"] = "",
["tts_engine"] = "flite",
["tts_voice"] = "rms",
["confirm_attempts"] = "3",
["inter_digit_timeout"] = "2000",
["digit_len"] = "4",
["timeout"] = "15000",
["max_failures"] = "3",
["max_timeouts"] = "2"
}
-- sub_menu is an object of class IVRMenu
-- pass in all 16 args to the constructor to define a new IVRMenu object
sub_menu = freeswitch.IVRMenu(
ivr_sub_def["main"],
ivr_sub_def["name"],
ivr_sub_def["greet_long"],
ivr_sub_def["greet_short"],
ivr_sub_def["invalid_sound"],
ivr_sub_def["exit_sound"],
ivr_sub_def["confirm_macro"],
ivr_sub_def["confirm_key"],
ivr_sub_def["tts_engine"],
ivr_sub_def["tts_voice"],
ivr_sub_def["confirm_attempts"],
ivr_sub_def["inter_digit_timeout"],
ivr_sub_def["digit_len"],
ivr_sub_def["timeout"],
ivr_sub_def["max_failures"],
ivr_sub_def["max_timeouts"]
);
-- Bind the action "menu-top" to the * key
sub_menu:bindAction("menu-top","demo_ivr_lua","*");
--sub_menu:execute(session,"demo_ivr_submenu_lua");
-- Run the main menu
top:execute(session, "demo_ivr_lua");
-MC
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.freeswitch.org/pipermail/freeswitch-users/attachments/20091214/958d66a6/attachment-0002.html
More information about the FreeSWITCH-users
mailing list