]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
updated directory using asr/tts
authorBrian West <brian@freeswitch.org>
Sat, 5 Jul 2014 14:22:59 +0000 (09:22 -0500)
committerBrian West <brian@freeswitch.org>
Sat, 5 Jul 2014 14:22:59 +0000 (09:22 -0500)
scripts/lua/directory.gram [new file with mode: 0644]
scripts/lua/directory.lua [new file with mode: 0644]

diff --git a/scripts/lua/directory.gram b/scripts/lua/directory.gram
new file mode 100644 (file)
index 0000000..edfd6b6
--- /dev/null
@@ -0,0 +1,13 @@
+#JSGF V1.0;
+/**
+  * JSGF Grammar for Directory
+  */
+
+grammar directory;
+
+<anthony> = [ anthony ];
+<michael> = [ michael ];
+<brian>   = [ brian ];
+
+public <directory> = <anthony> <michael> <brian>;
+
diff --git a/scripts/lua/directory.lua b/scripts/lua/directory.lua
new file mode 100644 (file)
index 0000000..3059f32
--- /dev/null
@@ -0,0 +1,182 @@
+--[[
+FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+Copyright (C) 2005/2006, Anthony Minessale II <anthm@freeswitch.org>
+
+Version: MPL 1.1
+
+The contents of this file are subject to the Mozilla Public License Version
+1.1 (the "License"); you may not use this file except in compliance with
+the License. You may obtain a copy of the License at
+http://www.mozilla.org/MPL/
+
+   Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the
+License.
+
+The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+
+The Initial Developer of the Original Code is
+Anthony Minessale II <anthm@freeswitch.org>
+   Portions created by the Initial Developer are Copyright (C)
+the Initial Developer. All Rights Reserved.
+
+Contributor(s):
+
+Brian West <brian@freeswitch.org>
+
+   Example for Speech Enabled LUA Applications.
+]]
+
+-- Used in parse_xml
+function parseargs_xml(s)
+   local arg = {}
+   string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
+                                           arg[w] = a
+                                        end)
+   return arg
+end
+
+-- Turns XML into a lua table.
+function parse_xml(s)
+   local stack = {};
+   local top = {};
+   table.insert(stack, top);
+   local ni,c,label,xarg, empty;
+   local i, j = 1, 1;
+   while true do
+      ni,j,c,label,xarg, empty = string.find(s, "<(%/?)(%w+)(.-)(%/?)>", i);
+      if not ni then
+        break
+      end
+      local text = string.sub(s, i, ni-1);
+      if not string.find(text, "^%s*$") then
+        table.insert(top, text);
+      end
+      if empty == "/" then
+        table.insert(top, {label=label, xarg=parseargs_xml(xarg), empty=1});
+      elseif c == "" then
+        top = {label=label, xarg=parseargs_xml(xarg)};
+        table.insert(stack, top);
+      else
+        local toclose = table.remove(stack);
+        top = stack[#stack];
+        if #stack < 1 then
+           error("nothing to close with "..label);
+        end
+        if toclose.label ~= label then
+           error("trying to close "..toclose.label.." with "..label);
+        end
+        table.insert(top, toclose);
+      end
+      i = j+1;
+   end
+   local text = string.sub(s, i);
+   if not string.find(text, "^%s*$") then
+      table.insert(stack[stack.n], text);
+   end
+   if #stack > 1 then
+      error("unclosed "..stack[stack.n].label);
+   end
+   return stack[1];
+end
+
+function dump(o)
+   if type(o) == 'table' then
+      local s = '{ '
+      for k,v in pairs(o) do
+        if type(k) ~= 'number' then k = '"'..k..'"' end
+        s = s .. '['..k..'] = ' .. dump(v) .. ','
+      end
+      return s .. '} '
+   else
+      return tostring(o)
+   end
+end
+
+-- Used to parse the XML results.
+function getResults(s) 
+   local xml = parse_xml(s);
+   local stack = {}
+   local top = {}
+
+   -- freeswitch.consoleLog("crit", "\n" .. dump(xml) .. "\n");
+   table.insert(stack, top)
+   top = {grammar=xml[2].xarg.grammar, score=xml[2].xarg.confidence, text=xml[2][1][1][1]}
+   table.insert(stack, top)
+   return top;
+end
+
+-- This is the input callback used by dtmf or any other events on this session such as ASR.
+function onInput(s, type, obj)
+   freeswitch.consoleLog("info", "Callback with type " .. type .. "\n");
+   if (type == "dtmf") then
+      freeswitch.consoleLog("info", "DTMF Digit: " .. obj.digit .. "\n");
+   else if (type == "event") then
+        local event = obj:getHeader("Speech-Type");
+        if (event == "begin-speaking") then
+           freeswitch.consoleLog("info", "\n" .. obj:serialize() .. "\n");
+           -- Return break on begin-speaking events to stop playback of the fire or tts.
+           return "break";
+        end
+        if (event == "detected-speech") then
+           freeswitch.consoleLog("info", "\n" .. obj:serialize() .. "\n");
+           if (obj:getBody()) then
+              -- Pause speech detection (this is on auto but pausing it just in case)
+              session:execute("detect_speech", "pause");
+              -- Parse the results from the event into the results table for later use.
+              results = getResults(obj:getBody());
+           end
+           return "break";
+        end
+      end
+   end
+end
+
+
+--Used to map returned names to extension numbers
+extensions = {
+   ["anthony"] = 3000,
+   ["michael"] = 3001,
+   ["brian"] = 3002
+}
+
+-- Create the empty results table.
+results = {};
+-- Answer the call.
+session:answer();
+-- Define TTS Engine
+session:set_tts_params("flite", "slt");
+-- Register the input callback 
+session:setInputCallback("onInput");
+-- Sleep a little bit to give media time to be fully up.
+session:sleep(200);
+session:speak("Welcome to the directory.");
+-- Start the detect_speech app.  This attaches the bug to fire events
+session:execute("detect_speech", "pocketsphinx directory directory");   
+
+-- Magic happens here.
+-- It would be ok to loop like 3 times and error to the operator if this doesn't work or revert to reading names off with TTS.
+while (session:ready() == true) do 
+   session:sleep(100);
+   -- Who are they looking for?
+   session:speak("Say the name of the person you're trying to reach.");
+   -- This sleep is what blocks till the detected-speech event.  This has to give you enough time to speak plus get the results.
+   session:sleep(3000);
+   session:sleep(3000);
+   -- If the results aren't null and we have an extension in the table.
+   if (results.text ~= nil and extensions[results.text] ~= nil) then
+      -- Letting the caller know we are trying.
+      session:speak("Please hold while I transfer your call.");
+      -- It's critical to stop the detect_detect otherwise it will continue to fire speech events and waste resources.
+      session:execute("detect_speech", "stop"); 
+      -- Transfer the call to the extension out of the lua table.
+      session:execute("transfer", extensions[results.text] .. " XML default");
+   end
+   -- We didn't have them in our directory table.
+   session:speak("Sorry, I don't have that person listed, please try again.");
+   -- Clear any results we have just in case.
+   results = {};
+   -- Resume detect_speech.
+   session:execute("detect_speech", "resume");
+end