mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-07-14 19:16:59 +00:00
Finalization of speech detect interface and API
This changes the core to have the necessary tools to create a speech detection interface. It also changes the code in javascript (mod_spidermonkey) there are a few api changes in how it handles callbacks It also adds grammars as a system dir to store asr grammars git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3291 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
b942d8e044
commit
44fc26f7d4
433
scripts/js_modules/SpeechTools.jm
Normal file
433
scripts/js_modules/SpeechTools.jm
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
/*
|
||||||
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||||
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||||
|
*
|
||||||
|
* 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 <anthmct@yahoo.com>
|
||||||
|
* Portions created by the Initial Developer are Copyright (C)
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
*
|
||||||
|
* Anthony Minessale II <anthmct@yahoo.com>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SpeechTools.jm Speech Detection Interface
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Constructor for Grammar Class (Class to identify a grammar entity) */
|
||||||
|
function Grammar(grammar_name, path, obj_path, min_score, confirm_score, halt) {
|
||||||
|
this.grammar_name = grammar_name;
|
||||||
|
this.path = path;
|
||||||
|
this.min_score = min_score;
|
||||||
|
this.confirm_score = confirm_score;
|
||||||
|
this.halt = halt;
|
||||||
|
this.obj_path = obj_path;
|
||||||
|
|
||||||
|
if (!this.min_score) {
|
||||||
|
this.min_score = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.confirm_score) {
|
||||||
|
this.confirm_score = 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constructor for SpeechDetect Class (Class to Detect Speech) */
|
||||||
|
function SpeechDetect(session, mod, ip) {
|
||||||
|
this.ip = ip;
|
||||||
|
this.session = session;
|
||||||
|
this.mod = mod;
|
||||||
|
this.grammar_name = undefined;
|
||||||
|
this.grammar_hash = new Array();
|
||||||
|
this.grammar_name = false;
|
||||||
|
this.audio_base = "";
|
||||||
|
this.audio_ext = ".wav";
|
||||||
|
this.tts_eng = false;
|
||||||
|
this.tts_voice = false;
|
||||||
|
this.AutoUnload = false;
|
||||||
|
this.debug = false;
|
||||||
|
|
||||||
|
/* Set the TTS info*/
|
||||||
|
this.setTTS = function (tts_eng, tts_voice) {
|
||||||
|
this.tts_eng = tts_eng;
|
||||||
|
this.tts_voice = tts_voice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio base */
|
||||||
|
this.setAudioBase = function (audio_base) {
|
||||||
|
this.audio_base = audio_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio extension */
|
||||||
|
this.setAudioExt= function (audio_ext) {
|
||||||
|
this.audio_ext = audio_ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a grammar to be used*/
|
||||||
|
this.addGrammar = function(grammar_object) {
|
||||||
|
this.grammar_hash[grammar_object.grammar_name] = grammar_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Play an audio file */
|
||||||
|
this.streamFile = function(str) {
|
||||||
|
var rv;
|
||||||
|
if (!str) {
|
||||||
|
console_log("error", "No file specified!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
files = str.split(",");
|
||||||
|
for( x = 0; x < files.length; x++) {
|
||||||
|
if (!files[x] || files[x] == "noop") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.session.streamFile(this.audio_base + files[x] + this.audio_ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speak with TTS */
|
||||||
|
this.speak = function(str) {
|
||||||
|
return this.session.speak(this.tts_eng, this.tts_voice, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the current grammar */
|
||||||
|
this.setGrammar = function (grammar_name) {
|
||||||
|
var grammar_object = this.grammar_hash[grammar_name];
|
||||||
|
|
||||||
|
if (!grammar_object) {
|
||||||
|
console_log("error", "Missing Grammar!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.grammar_name) {
|
||||||
|
if (this.AutoUnload) {
|
||||||
|
console_log("debug", "Unloading grammar " + this.grammar_name + "\n");
|
||||||
|
this.session.execute("detect_speech", "nogrammar " + this.grammar_name);
|
||||||
|
}
|
||||||
|
if (grammar_object.path) {
|
||||||
|
this.session.execute("detect_speech", "grammar " + grammar_name + " " + grammar_object.path);
|
||||||
|
} else {
|
||||||
|
this.session.execute("detect_speech", "grammar " + grammar_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.session.execute("detect_speech", this.mod + " " + grammar_name + " " + grammar_object.path + " " + this.ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.grammar_name = grammar_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pause speech detection */
|
||||||
|
this.pause = function() {
|
||||||
|
this.session.execute("detect_speech", "pause");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume speech detection */
|
||||||
|
this.resume = function() {
|
||||||
|
this.session.execute("detect_speech", "resume");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop speech detection */
|
||||||
|
this.stop = function() {
|
||||||
|
this.session.execute("detect_speech", "stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callback function for streaming,TTS or bridged calls */
|
||||||
|
this.onInput = function(type, inputEvent, _this) {
|
||||||
|
if (type == "event") {
|
||||||
|
var speech_type = inputEvent.getHeader("Speech-Type");
|
||||||
|
var rv = new Array();
|
||||||
|
|
||||||
|
if (!_this.grammar_name) {
|
||||||
|
console_log("error", "No Grammar name!\n");
|
||||||
|
_this.session.hangup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var grammar_object = _this.grammar_hash[_this.grammar_name];
|
||||||
|
|
||||||
|
if (!grammar_object) {
|
||||||
|
console_log("error", "Can't find grammar for " + _this.grammar_name + "\n");
|
||||||
|
_this.session.hangup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speech_type == "begin-speaking") {
|
||||||
|
if (grammar_object.halt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var body = inputEvent.getBody();
|
||||||
|
var interp = new XML(body);
|
||||||
|
|
||||||
|
_this.lastDetect = body;
|
||||||
|
|
||||||
|
if (_this.debug) {
|
||||||
|
console_log("debug", "----XML:\n" + body);
|
||||||
|
console_log("debug", "----Heard [" + interp.input + "]\n");
|
||||||
|
console_log("debug", "----Hit score " + interp.@score + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interp.@score < grammar_object.min_score) {
|
||||||
|
delete interp;
|
||||||
|
rv.push("_no_idea_");
|
||||||
|
return rv;
|
||||||
|
} else {
|
||||||
|
if (interp.@score < grammar_object.confirm_score) {
|
||||||
|
rv.push("_confirm_");
|
||||||
|
}
|
||||||
|
|
||||||
|
eval("xo = interp." + grammar_object.obj_path + ";");
|
||||||
|
|
||||||
|
for (x = 0; x < xo.length(); x++) {
|
||||||
|
rv.push(xo[x]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete interp;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constructor for SpeechObtainer Class (Class to collect data from a SpeechDetect Class) */
|
||||||
|
function SpeechObtainer(asr, req, wait_time) {
|
||||||
|
|
||||||
|
this.items = new Array();
|
||||||
|
this.collected_items = new Array();
|
||||||
|
this.index = 0;
|
||||||
|
this.collected_index = 0;
|
||||||
|
this.req = req;
|
||||||
|
this.tts_eng = undefined;
|
||||||
|
this.tts_voice = false;
|
||||||
|
this.asr = asr;
|
||||||
|
this.top_sound = false;
|
||||||
|
this.add_sound = false;
|
||||||
|
this.dup_sound = false;
|
||||||
|
this.bad_sound = false;
|
||||||
|
this.needConfirm = false;
|
||||||
|
this.grammar_name = false;
|
||||||
|
this.audio_base = asr.audio_base;
|
||||||
|
this.audio_ext = asr.audio_ext;
|
||||||
|
this.tts_eng = asr.tts_eng;
|
||||||
|
this.tts_voice = asr.tts_voice;
|
||||||
|
this.debug = asr.debug;
|
||||||
|
|
||||||
|
if (!req) {
|
||||||
|
req = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wait_time) {
|
||||||
|
wait_time = 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.waitTime = wait_time + 0;
|
||||||
|
|
||||||
|
/* Set the TTS info*/
|
||||||
|
this.setTTS = function (tts_eng, tts_voice) {
|
||||||
|
this.tts_eng = tts_eng;
|
||||||
|
this.tts_voice = tts_voice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio base */
|
||||||
|
this.setAudioBase = function (audio_base) {
|
||||||
|
this.audio_base = audio_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio extension */
|
||||||
|
this.setAudioExt= function (audio_ext) {
|
||||||
|
this.audio_ext = audio_ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the grammar to use */
|
||||||
|
this.setGrammar = function (grammar_name, path, obj_path, min_score, confirm_score, halt) {
|
||||||
|
var grammar_object = new Grammar(grammar_name, path, obj_path, min_score, confirm_score, halt);
|
||||||
|
this.asr.addGrammar(grammar_object);
|
||||||
|
this.grammar_name = grammar_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the top audio file or tts for the collection */
|
||||||
|
this.setTopSound = function (top_sound) {
|
||||||
|
this.top_sound = top_sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio file or tts for misunderstood input */
|
||||||
|
this.setBadSound = function (bad_sound) {
|
||||||
|
this.bad_sound = bad_sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio file or tts for duplicate input */
|
||||||
|
this.setDupSound = function (dup_sound) {
|
||||||
|
this.dup_sound = dup_sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the audio file or tts for accepted input */
|
||||||
|
this.setAddSound = function (add_sound) {
|
||||||
|
this.add_sound = add_sound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add acceptable items (comma sep list)*/
|
||||||
|
this.addItem = function(item) {
|
||||||
|
ia = item.split(",");
|
||||||
|
var x;
|
||||||
|
for (x = 0; x < ia.length; x++) {
|
||||||
|
this.items[this.index++] = ia[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a regex */
|
||||||
|
this.addRegEx = function(item) {
|
||||||
|
this.items[this.index++] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the object and delete all collect items */
|
||||||
|
this.reset = function() {
|
||||||
|
this.collected_index = 0;
|
||||||
|
delete this.collected_items;
|
||||||
|
this.collected_items = new Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stream a file, collecting input */
|
||||||
|
this.streamFile = function(str) {
|
||||||
|
var rv;
|
||||||
|
if (!str) {
|
||||||
|
console_log("error", "No file specified!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
files = str.split(",");
|
||||||
|
for( x = 0; x < files.length; x++) {
|
||||||
|
if (!files[x] || files[x] == "noop") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rv = this.asr.session.streamFile(this.audio_base + files[x] + this.audio_ext , "", this.asr.onInput, this.asr);
|
||||||
|
if (rv) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Speak some text, collecting input */
|
||||||
|
this.speak = function(str) {
|
||||||
|
return this.asr.session.speak(this.tts_eng, this.tts_voice, str, this.asr.onInput, this.asr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process collected input */
|
||||||
|
this.react = function(say_str, play_str) {
|
||||||
|
var rv;
|
||||||
|
|
||||||
|
this.asr.resume();
|
||||||
|
if (this.tts_eng && this.tts_voice) {
|
||||||
|
rv = this.speak(say_str);
|
||||||
|
} else {
|
||||||
|
rv = this.streamFile(play_str);
|
||||||
|
}
|
||||||
|
if (!rv) {
|
||||||
|
rv = this.asr.session.collectInput(this.asr.onInput, this.asr, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect input */
|
||||||
|
this.run = function() {
|
||||||
|
var rv;
|
||||||
|
var hit;
|
||||||
|
var dup;
|
||||||
|
|
||||||
|
if (this.collected_index) {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.grammar_name) {
|
||||||
|
console_log("error", "No Grammar name!\n");
|
||||||
|
this.session.hangup();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.asr.setGrammar(this.grammar_name);
|
||||||
|
|
||||||
|
while(this.asr.session.ready() && this.collected_index < this.req) {
|
||||||
|
var x;
|
||||||
|
this.needConfirm = false;
|
||||||
|
if (!rv) {
|
||||||
|
rv = this.react(this.top_sound, this.top_sound);
|
||||||
|
}
|
||||||
|
if (!rv) {
|
||||||
|
this.asr.resume();
|
||||||
|
rv = this.asr.session.collectInput(this.asr.onInput, this.asr, this.waitTime);
|
||||||
|
}
|
||||||
|
hit = false;
|
||||||
|
if (rv) {
|
||||||
|
for (y = 0; y < rv.length; y++) {
|
||||||
|
if (rv[y] == "_confirm_") {
|
||||||
|
this.needConfirm = true;
|
||||||
|
if (this.debug) {
|
||||||
|
console_log("debug", "----We need to confirm this one\n");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(x = 0 ; x < this.index; x++) {
|
||||||
|
if (this.debug) {
|
||||||
|
console_log("debug", "----Testing " + rv[y] + " =~ [" + this.items[x] + "]\n");
|
||||||
|
}
|
||||||
|
var re = new RegExp(this.items[x]);
|
||||||
|
match = re.exec(rv[y]);
|
||||||
|
if (match) {
|
||||||
|
for (i = 0; i < match.length; i++) {
|
||||||
|
dup = false;
|
||||||
|
for(z = 0; z < this.collected_items.length; z++) {
|
||||||
|
if (this.collected_items[z] == match[i]) {
|
||||||
|
dup = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dup) {
|
||||||
|
if (this.dup_sound) {
|
||||||
|
rv = this.react(this.dup_sound + " " + match[i], this.dup_sound + "," + match[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.debug) {
|
||||||
|
console_log("debug", "----Adding " + match[i] + "\n");
|
||||||
|
}
|
||||||
|
this.collected_items[this.collected_index++] = match[i];
|
||||||
|
hit = true;
|
||||||
|
if (this.add_sound) {
|
||||||
|
rv = this.react(this.add_sound + " " + match[i], this.add_sound + "," + match[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rv) {
|
||||||
|
rv = this.asr.session.collectInput(this.asr.onInput, this.asr, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rv && !hit && !dup) {
|
||||||
|
rv = this.react(this.bad_sound, this.bad_sound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.collected_items;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -124,5 +124,5 @@
|
|||||||
/* Define to rpl_malloc if the replacement function should be used. */
|
/* Define to rpl_malloc if the replacement function should be used. */
|
||||||
#undef malloc
|
#undef malloc
|
||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||||
#undef size_t
|
#undef size_t
|
||||||
|
@ -119,14 +119,21 @@ struct switch_core_port_allocator;
|
|||||||
\param session the session to add the bug to
|
\param session the session to add the bug to
|
||||||
\param callback a callback for events
|
\param callback a callback for events
|
||||||
\param user_data arbitrary user data
|
\param user_data arbitrary user data
|
||||||
|
\param flags flags to choose the stream
|
||||||
\param new_bug pointer to assign new bug to
|
\param new_bug pointer to assign new bug to
|
||||||
\return SWITCH_STATUS_SUCCESS if the operation was a success
|
\return SWITCH_STATUS_SUCCESS if the operation was a success
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
|
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
|
||||||
switch_media_bug_callback_t callback,
|
switch_media_bug_callback_t callback,
|
||||||
void *user_data,
|
void *user_data,
|
||||||
|
switch_media_bug_flag_t flags,
|
||||||
switch_media_bug_t **new_bug);
|
switch_media_bug_t **new_bug);
|
||||||
|
/*!
|
||||||
|
\brief Obtain private data from a media bug
|
||||||
|
\param session the session to obtain the private data from
|
||||||
|
\return the private data
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Remove a media bug from the session
|
\brief Remove a media bug from the session
|
||||||
@ -1060,7 +1067,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
|
|||||||
\param module_name the speech module to use
|
\param module_name the speech module to use
|
||||||
\param voice_name the desired voice name
|
\param voice_name the desired voice name
|
||||||
\param rate the sampling rate
|
\param rate the sampling rate
|
||||||
\param flags asr/tts flags
|
\param flags tts flags
|
||||||
\param pool the pool to use (NULL for new pool)
|
\param pool the pool to use (NULL for new pool)
|
||||||
\return SWITCH_STATUS_SUCCESS if the handle is opened
|
\return SWITCH_STATUS_SUCCESS if the handle is opened
|
||||||
*/
|
*/
|
||||||
@ -1070,28 +1077,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *
|
|||||||
unsigned int rate,
|
unsigned int rate,
|
||||||
switch_speech_flag_t *flags,
|
switch_speech_flag_t *flags,
|
||||||
switch_memory_pool_t *pool);
|
switch_memory_pool_t *pool);
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Feed data to the ASR module
|
|
||||||
\param sh the speech handle to feed
|
|
||||||
\param data the buffer of audio data
|
|
||||||
\param len the in-use size of the buffer
|
|
||||||
\param rate the rate of the audio (in hz)
|
|
||||||
\param flags flags in/out for fine tuning
|
|
||||||
\return SWITCH_STATUS_SUCCESS with possible new flags on success
|
|
||||||
*/
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_asr(switch_speech_handle_t *sh, void *data, unsigned int *len, int rate, switch_speech_flag_t *flags);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Get text back from the ASR module
|
|
||||||
\param sh the speech handle to read
|
|
||||||
\param buf the buffer to insert the text into
|
|
||||||
\param buflen the max size of the buffer
|
|
||||||
\param flags flags in/out for fine tuning
|
|
||||||
\return SWITCH_STATUS_SUCCESS with possible new flags on success
|
|
||||||
*/
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_speech_interpret_asr(switch_speech_handle_t *sh, char *buf, unsigned int buflen, switch_speech_flag_t *flags);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Feed text to the TTS module
|
\brief Feed text to the TTS module
|
||||||
\param sh the speech handle to feed
|
\param sh the speech handle to feed
|
||||||
@ -1152,6 +1137,92 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle
|
|||||||
\return SWITCH_STATUS_SUCCESS if the file handle was closed
|
\return SWITCH_STATUS_SUCCESS if the file handle was closed
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags);
|
SWITCH_DECLARE(switch_status_t) switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Open an asr handle
|
||||||
|
\param ah the asr handle to open
|
||||||
|
\param module_name the name of the asr module
|
||||||
|
\param codec the preferred codec
|
||||||
|
\param rate the preferred rate
|
||||||
|
\param dest the destination address
|
||||||
|
\param flags flags to influence behaviour
|
||||||
|
\param pool the pool to use (NULL for new pool)
|
||||||
|
\return SWITCH_STATUS_SUCCESS if the asr handle was opened
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah,
|
||||||
|
char *module_name,
|
||||||
|
char *codec,
|
||||||
|
int rate,
|
||||||
|
char *dest,
|
||||||
|
switch_asr_flag_t *flags,
|
||||||
|
switch_memory_pool_t *pool);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Close an asr handle
|
||||||
|
\param ah the handle to close
|
||||||
|
\param flags flags to influence behaviour
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Feed audio data to an asr handle
|
||||||
|
\param ah the handle to feed data to
|
||||||
|
\param data a pointer to the data
|
||||||
|
\param len the size in bytes of the data
|
||||||
|
\param flags flags to influence behaviour
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Check an asr handle for results
|
||||||
|
\param ah the handle to check
|
||||||
|
\param flags flags to influence behaviour
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Get results from an asr handle
|
||||||
|
\param ah the handle to get results from
|
||||||
|
\param xmlstr a pointer to dynamically allocate an xml result string to
|
||||||
|
\param flags flags to influence behaviour
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Load a grammar to an asr handle
|
||||||
|
\param ah the handle to load to
|
||||||
|
\param grammar the name of the grammar
|
||||||
|
\param path the path to the grammaar file
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, char *grammar, char *path);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Unload a grammar from an asr handle
|
||||||
|
\param ah the handle to unload the grammar from
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, char *grammar);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Pause detection on an asr handle
|
||||||
|
\param ah the handle to pause
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_pause(switch_asr_handle_t *ah);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Resume detection on an asr handle
|
||||||
|
\param ah the handle to resume
|
||||||
|
\return SWITCH_STATUS_SUCCESS
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah);
|
||||||
|
|
||||||
///\}
|
///\}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,12 +69,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session);
|
|||||||
\param dtmf_callback code to execute if any dtmf is dialed during the recording
|
\param dtmf_callback code to execute if any dtmf is dialed during the recording
|
||||||
\param buf an object to maintain across calls
|
\param buf an object to maintain across calls
|
||||||
\param buflen the size of buf
|
\param buflen the size of buf
|
||||||
|
\param timeout a timeout in milliseconds
|
||||||
\return SWITCH_STATUS_SUCCESS to keep the collection moving.
|
\return SWITCH_STATUS_SUCCESS to keep the collection moving.
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
|
SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
|
||||||
switch_input_callback_function_t dtmf_callback,
|
switch_input_callback_function_t dtmf_callback,
|
||||||
void *buf,
|
void *buf,
|
||||||
unsigned int buflen);
|
unsigned int buflen,
|
||||||
|
unsigned int timeout);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.
|
\brief Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.
|
||||||
@ -95,6 +97,61 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_sess
|
|||||||
char *terminator,
|
char *terminator,
|
||||||
unsigned int timeout);
|
unsigned int timeout);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Engage background Speech detection on a session
|
||||||
|
\param session the session to attach
|
||||||
|
\param mod_name the module name of the ASR library
|
||||||
|
\param grammar the grammar name
|
||||||
|
\param path the path to the grammar file
|
||||||
|
\param dest the destination address
|
||||||
|
\param ah an ASR handle to use (NULL to create one)
|
||||||
|
\return SWITCH_STATUS_SUCCESS if all is well
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session,
|
||||||
|
char *mod_name,
|
||||||
|
char *grammar,
|
||||||
|
char *path,
|
||||||
|
char *dest,
|
||||||
|
switch_asr_handle_t *ah);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Stop background Speech detection on a session
|
||||||
|
\param session The session to stop detection on
|
||||||
|
\return SWITCH_STATUS_SUCCESS if all is well
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_stop_detect_speech(switch_core_session_t *session);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Pause background Speech detection on a session
|
||||||
|
\param session The session to pause detection on
|
||||||
|
\return SWITCH_STATUS_SUCCESS if all is well
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_pause_detect_speech(switch_core_session_t *session);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Resume background Speech detection on a session
|
||||||
|
\param session The session to resume detection on
|
||||||
|
\return SWITCH_STATUS_SUCCESS if all is well
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_session_t *session);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Load a grammar on a background speech detection handle
|
||||||
|
\param session The session to change the grammar on
|
||||||
|
\param grammar the grammar name
|
||||||
|
\param path the grammar path
|
||||||
|
\return SWITCH_STATUS_SUCCESS if all is well
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Unload a grammar on a background speech detection handle
|
||||||
|
\param session The session to change the grammar on
|
||||||
|
\param grammar the grammar name
|
||||||
|
\return SWITCH_STATUS_SUCCESS if all is well
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, char *grammar);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Record a session to disk
|
\brief Record a session to disk
|
||||||
\param session the session to record
|
\param session the session to record
|
||||||
|
@ -75,6 +75,8 @@ struct switch_loadable_module_interface {
|
|||||||
const switch_directory_interface_t *directory_interface;
|
const switch_directory_interface_t *directory_interface;
|
||||||
/*! the table of chat interfaces the module has implmented */
|
/*! the table of chat interfaces the module has implmented */
|
||||||
const switch_chat_interface_t *chat_interface;
|
const switch_chat_interface_t *chat_interface;
|
||||||
|
/*! the table of asr interfaces the module has implmented */
|
||||||
|
const switch_asr_interface_t *asr_interface;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -158,6 +160,13 @@ SWITCH_DECLARE(switch_file_interface_t *) switch_loadable_module_get_file_interf
|
|||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_interface(char *name);
|
SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_interface(char *name);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Retrieve the asr interface by it's registered name
|
||||||
|
\param name the name of the asr interface
|
||||||
|
\return the desired asr interface
|
||||||
|
*/
|
||||||
|
SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(char *name);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Retrieve the directory interface by it's registered name
|
\brief Retrieve the directory interface by it's registered name
|
||||||
\param name the name of the directory interface
|
\param name the name of the directory interface
|
||||||
|
@ -315,6 +315,53 @@ struct switch_file_handle {
|
|||||||
switch_buffer_t *audio_buffer;
|
switch_buffer_t *audio_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief Abstract interface to an asr module */
|
||||||
|
struct switch_asr_interface {
|
||||||
|
/*! the name of the interface */
|
||||||
|
const char *interface_name;
|
||||||
|
/*! function to open the asr interface */
|
||||||
|
switch_status_t (*asr_open)(switch_asr_handle_t *ah,
|
||||||
|
char *codec,
|
||||||
|
int rate,
|
||||||
|
char *dest,
|
||||||
|
switch_asr_flag_t *flags);
|
||||||
|
/*! function to load a grammar to the asr interface */
|
||||||
|
switch_status_t (*asr_load_grammar)(switch_asr_handle_t *ah, char *grammar, char *path);
|
||||||
|
/*! function to unload a grammar to the asr interface */
|
||||||
|
switch_status_t (*asr_unload_grammar)(switch_asr_handle_t *ah, char *grammar);
|
||||||
|
/*! function to close the asr interface */
|
||||||
|
switch_status_t (*asr_close)(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
|
||||||
|
/*! function to feed audio to the ASR*/
|
||||||
|
switch_status_t (*asr_feed)(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
|
||||||
|
/*! function to resume the ASR*/
|
||||||
|
switch_status_t (*asr_resume)(switch_asr_handle_t *ah);
|
||||||
|
/*! function to pause the ASR*/
|
||||||
|
switch_status_t (*asr_pause)(switch_asr_handle_t *ah);
|
||||||
|
/*! function to read results from the ASR*/
|
||||||
|
switch_status_t (*asr_check_results)(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
|
||||||
|
/*! function to read results from the ASR*/
|
||||||
|
switch_status_t (*asr_get_results)(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
|
||||||
|
const struct switch_asr_interface *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! an abstract representation of an asr speech interface. */
|
||||||
|
struct switch_asr_handle {
|
||||||
|
/*! the interface of the module that implemented the current speech interface */
|
||||||
|
const switch_asr_interface_t *asr_interface;
|
||||||
|
/*! flags to control behaviour */
|
||||||
|
uint32_t flags;
|
||||||
|
/*! The Name*/
|
||||||
|
char *name;
|
||||||
|
/*! The Codec*/
|
||||||
|
char *codec;
|
||||||
|
/*! The Rate*/
|
||||||
|
uint32_t rate;
|
||||||
|
char *grammar;
|
||||||
|
/*! the handle's memory pool */
|
||||||
|
switch_memory_pool_t *memory_pool;
|
||||||
|
/*! private data for the format module to store handle specific info */
|
||||||
|
void *private_info;
|
||||||
|
};
|
||||||
|
|
||||||
/*! \brief Abstract interface to a speech module */
|
/*! \brief Abstract interface to a speech module */
|
||||||
struct switch_speech_interface {
|
struct switch_speech_interface {
|
||||||
@ -328,10 +375,6 @@ struct switch_speech_interface {
|
|||||||
/*! function to close the speech interface */
|
/*! function to close the speech interface */
|
||||||
switch_status_t (*speech_close)(switch_speech_handle_t *, switch_speech_flag_t *flags);
|
switch_status_t (*speech_close)(switch_speech_handle_t *, switch_speech_flag_t *flags);
|
||||||
/*! function to feed audio to the ASR*/
|
/*! function to feed audio to the ASR*/
|
||||||
switch_status_t (*speech_feed_asr)(switch_speech_handle_t *sh, void *data, unsigned int *len, int rate, switch_speech_flag_t *flags);
|
|
||||||
/*! function to read text from the ASR*/
|
|
||||||
switch_status_t (*speech_interpret_asr)(switch_speech_handle_t *sh, char *buf, unsigned int buflen, switch_speech_flag_t *flags);
|
|
||||||
/*! function to feed text to the TTS*/
|
|
||||||
switch_status_t (*speech_feed_tts)(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags);
|
switch_status_t (*speech_feed_tts)(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags);
|
||||||
/*! function to read audio from the TTS*/
|
/*! function to read audio from the TTS*/
|
||||||
switch_status_t (*speech_read_tts)(switch_speech_handle_t *sh,
|
switch_status_t (*speech_read_tts)(switch_speech_handle_t *sh,
|
||||||
|
@ -72,6 +72,10 @@ SWITCH_BEGIN_EXTERN_C
|
|||||||
#define SWITCH_HTDOCS_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "htdocs"
|
#define SWITCH_HTDOCS_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "htdocs"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SWITCH_GRAMMAR_DIR
|
||||||
|
#define SWITCH_GRAMMAR_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "grammar"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SWITCH_R_SDP_VARIABLE "_switch_r_sdp_"
|
#define SWITCH_R_SDP_VARIABLE "_switch_r_sdp_"
|
||||||
#define SWITCH_L_SDP_VARIABLE "_switch_l_sdp_"
|
#define SWITCH_L_SDP_VARIABLE "_switch_l_sdp_"
|
||||||
#define SWITCH_B_SDP_VARIABLE "_switch_m_sdp_"
|
#define SWITCH_B_SDP_VARIABLE "_switch_m_sdp_"
|
||||||
@ -82,7 +86,7 @@ SWITCH_BEGIN_EXTERN_C
|
|||||||
#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "_local_media_port_"
|
#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "_local_media_port_"
|
||||||
#define SWITCH_REMOTE_MEDIA_IP_VARIABLE "_remote_media_ip_"
|
#define SWITCH_REMOTE_MEDIA_IP_VARIABLE "_remote_media_ip_"
|
||||||
#define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "_remote_media_port_"
|
#define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "_remote_media_port_"
|
||||||
|
#define SWITCH_SPEECH_KEY "_speech_"
|
||||||
|
|
||||||
#define SWITCH_BITS_PER_BYTE 8
|
#define SWITCH_BITS_PER_BYTE 8
|
||||||
typedef uint8_t switch_byte_t;
|
typedef uint8_t switch_byte_t;
|
||||||
@ -132,6 +136,7 @@ struct switch_directories {
|
|||||||
char *script_dir;
|
char *script_dir;
|
||||||
char *temp_dir;
|
char *temp_dir;
|
||||||
char *htdocs_dir;
|
char *htdocs_dir;
|
||||||
|
char *grammar_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct switch_directories switch_directories;
|
typedef struct switch_directories switch_directories;
|
||||||
@ -313,6 +318,7 @@ typedef enum {
|
|||||||
SWITCH_STATUS_SOCKERR - A socket error
|
SWITCH_STATUS_SOCKERR - A socket error
|
||||||
SWITCH_STATUS_MORE_DATA - Need More Data
|
SWITCH_STATUS_MORE_DATA - Need More Data
|
||||||
SWITCH_STATUS_NOTFOUND - Not Found
|
SWITCH_STATUS_NOTFOUND - Not Found
|
||||||
|
SWITCH_STATUS_UNLOAD - Unload
|
||||||
</pre>
|
</pre>
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -330,7 +336,8 @@ typedef enum {
|
|||||||
SWITCH_STATUS_BREAK,
|
SWITCH_STATUS_BREAK,
|
||||||
SWITCH_STATUS_SOCKERR,
|
SWITCH_STATUS_SOCKERR,
|
||||||
SWITCH_STATUS_MORE_DATA,
|
SWITCH_STATUS_MORE_DATA,
|
||||||
SWITCH_STATUS_NOTFOUND
|
SWITCH_STATUS_NOTFOUND,
|
||||||
|
SWITCH_STATUS_UNLOAD
|
||||||
} switch_status_t;
|
} switch_status_t;
|
||||||
|
|
||||||
|
|
||||||
@ -522,26 +529,42 @@ typedef enum {
|
|||||||
\enum switch_speech_flag_t
|
\enum switch_speech_flag_t
|
||||||
\brief Speech related flags
|
\brief Speech related flags
|
||||||
<pre>
|
<pre>
|
||||||
SWITCH_SPEECH_FLAG_TTS = (1 << 0) - Interface can/should convert text to speech.
|
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0) - Interface is has text to read.
|
||||||
SWITCH_SPEECH_FLAG_ASR = (1 << 1) - Interface can/should convert audio to text.
|
SWITCH_SPEECH_FLAG_PEEK = (1 << 1) - Read data but do not erase it.
|
||||||
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 2) - Interface is has text to read.
|
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 2) - Free interface's pool on destruction.
|
||||||
SWITCH_SPEECH_FLAG_PEEK = (1 << 3) - Read data but do not erase it.
|
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 3) - Indicate that a blocking call is desired
|
||||||
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 4) - Free interface's pool on destruction.
|
SWITCH_SPEECH_FLAG_PAUSE = (1 << 4) - Pause toggle for playback
|
||||||
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 5) - Indicate that a blocking call is desired
|
|
||||||
SWITCH_SPEECH_FLAG_PAUSE = (1 << 6) - Pause toggle for playback
|
|
||||||
</pre>
|
</pre>
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SWITCH_SPEECH_FLAG_TTS = (1 << 0),
|
SWITCH_SPEECH_FLAG_NONE = 0,
|
||||||
SWITCH_SPEECH_FLAG_ASR = (1 << 1),
|
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 0),
|
||||||
SWITCH_SPEECH_FLAG_HASTEXT = (1 << 2),
|
SWITCH_SPEECH_FLAG_PEEK = (1 << 1),
|
||||||
SWITCH_SPEECH_FLAG_PEEK = (1 << 3),
|
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 2),
|
||||||
SWITCH_SPEECH_FLAG_FREE_POOL = (1 << 4),
|
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 3),
|
||||||
SWITCH_SPEECH_FLAG_BLOCKING = (1 << 5),
|
SWITCH_SPEECH_FLAG_PAUSE = (1 << 4)
|
||||||
SWITCH_SPEECH_FLAG_PAUSE = (1 << 6)
|
|
||||||
|
|
||||||
} switch_speech_flag_t;
|
} switch_speech_flag_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum switch_asr_flag_t
|
||||||
|
\brief Asr related flags
|
||||||
|
<pre>
|
||||||
|
SWITCH_ASR_FLAG_DATA = (1 << 0) - Interface has data
|
||||||
|
SWITCH_ASR_FLAG_FREE_POOL = (1 << 1) - Pool needs to be freed
|
||||||
|
SWITCH_ASR_FLAG_CLOSED = (1 << 2) - Interface has been closed
|
||||||
|
SWITCH_ASR_FLAG_FIRE_EVENTS = (1 << 3) - Fire all speech events
|
||||||
|
SWITCH_ASR_FLAG_AUTO_RESUME = (1 << 4) - Auto Resume
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SWITCH_ASR_FLAG_NONE = 0,
|
||||||
|
SWITCH_ASR_FLAG_DATA = (1 << 0),
|
||||||
|
SWITCH_ASR_FLAG_FREE_POOL = (1 << 1),
|
||||||
|
SWITCH_ASR_FLAG_CLOSED = (1 << 2),
|
||||||
|
SWITCH_ASR_FLAG_FIRE_EVENTS = (1 << 3),
|
||||||
|
SWITCH_ASR_FLAG_AUTO_RESUME = (1 << 4)
|
||||||
|
} switch_asr_flag_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\enum switch_directory_flag_t
|
\enum switch_directory_flag_t
|
||||||
@ -584,6 +607,21 @@ typedef enum {
|
|||||||
SWITCH_TIMER_FLAG_FREE_POOL = (1 << 0),
|
SWITCH_TIMER_FLAG_FREE_POOL = (1 << 0),
|
||||||
} switch_timer_flag_t;
|
} switch_timer_flag_t;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum switch_timer_flag_t
|
||||||
|
\brief Timer related flags
|
||||||
|
<pre>
|
||||||
|
SMBF_READ_STREAM - Include the Read Stream
|
||||||
|
SMBF_WRITE_STREAM - Include the Write Stream
|
||||||
|
</pre>
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SMBF_BOTH = 0,
|
||||||
|
SMBF_READ_STREAM = (1 << 0),
|
||||||
|
SMBF_WRITE_STREAM = (1 << 1)
|
||||||
|
} switch_media_bug_flag_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\enum switch_file_flag_t
|
\enum switch_file_flag_t
|
||||||
\brief File flags
|
\brief File flags
|
||||||
@ -653,6 +691,7 @@ typedef enum {
|
|||||||
SWITCH_EVENT_PRESENCE - Presence Info
|
SWITCH_EVENT_PRESENCE - Presence Info
|
||||||
SWITCH_EVENT_CODEC - Codec Change
|
SWITCH_EVENT_CODEC - Codec Change
|
||||||
SWITCH_EVENT_BACKGROUND_JOB - Background Job
|
SWITCH_EVENT_BACKGROUND_JOB - Background Job
|
||||||
|
SWITCH_EVENT_DETECTED_SPEECH - Detected Speech
|
||||||
SWITCH_EVENT_ALL - All events at once
|
SWITCH_EVENT_ALL - All events at once
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -690,6 +729,7 @@ typedef enum {
|
|||||||
SWITCH_EVENT_ROSTER,
|
SWITCH_EVENT_ROSTER,
|
||||||
SWITCH_EVENT_CODEC,
|
SWITCH_EVENT_CODEC,
|
||||||
SWITCH_EVENT_BACKGROUND_JOB,
|
SWITCH_EVENT_BACKGROUND_JOB,
|
||||||
|
SWITCH_EVENT_DETECTED_SPEECH,
|
||||||
SWITCH_EVENT_ALL
|
SWITCH_EVENT_ALL
|
||||||
} switch_event_types_t;
|
} switch_event_types_t;
|
||||||
|
|
||||||
@ -800,10 +840,9 @@ typedef struct switch_io_event_hook_waitfor_write switch_io_event_hook_waitfor_w
|
|||||||
typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
|
typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
|
||||||
typedef struct switch_io_routines switch_io_routines_t;
|
typedef struct switch_io_routines switch_io_routines_t;
|
||||||
typedef struct switch_io_event_hooks switch_io_event_hooks_t;
|
typedef struct switch_io_event_hooks switch_io_event_hooks_t;
|
||||||
|
|
||||||
typedef struct switch_speech_handle switch_speech_handle_t;
|
typedef struct switch_speech_handle switch_speech_handle_t;
|
||||||
|
typedef struct switch_asr_handle switch_asr_handle_t;
|
||||||
typedef struct switch_directory_handle switch_directory_handle_t;
|
typedef struct switch_directory_handle switch_directory_handle_t;
|
||||||
|
|
||||||
typedef struct switch_loadable_module_interface switch_loadable_module_interface_t;
|
typedef struct switch_loadable_module_interface switch_loadable_module_interface_t;
|
||||||
typedef struct switch_endpoint_interface switch_endpoint_interface_t;
|
typedef struct switch_endpoint_interface switch_endpoint_interface_t;
|
||||||
typedef struct switch_timer_interface switch_timer_interface_t;
|
typedef struct switch_timer_interface switch_timer_interface_t;
|
||||||
@ -813,6 +852,7 @@ typedef struct switch_application_interface switch_application_interface_t;
|
|||||||
typedef struct switch_api_interface switch_api_interface_t;
|
typedef struct switch_api_interface switch_api_interface_t;
|
||||||
typedef struct switch_file_interface switch_file_interface_t;
|
typedef struct switch_file_interface switch_file_interface_t;
|
||||||
typedef struct switch_speech_interface switch_speech_interface_t;
|
typedef struct switch_speech_interface switch_speech_interface_t;
|
||||||
|
typedef struct switch_asr_interface switch_asr_interface_t;
|
||||||
typedef struct switch_directory_interface switch_directory_interface_t;
|
typedef struct switch_directory_interface switch_directory_interface_t;
|
||||||
typedef struct switch_chat_interface switch_chat_interface_t;
|
typedef struct switch_chat_interface switch_chat_interface_t;
|
||||||
typedef struct switch_core_port_allocator switch_core_port_allocator_t;
|
typedef struct switch_core_port_allocator switch_core_port_allocator_t;
|
||||||
|
@ -393,10 +393,12 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
|
|||||||
switch_channel_t *caller_channel;
|
switch_channel_t *caller_channel;
|
||||||
switch_core_session_t *caller_session;
|
switch_core_session_t *caller_session;
|
||||||
char *argv[7] = {0};
|
char *argv[7] = {0};
|
||||||
int x, argc = 0;
|
int i = 0, x, argc = 0;
|
||||||
char *aleg, *exten, *dp, *context, *cid_name, *cid_num;
|
char *aleg, *exten, *dp, *context, *cid_name, *cid_num;
|
||||||
uint32_t timeout = 60;
|
uint32_t timeout = 60;
|
||||||
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
|
||||||
|
uint8_t machine = 1;
|
||||||
|
|
||||||
if (isession) {
|
if (isession) {
|
||||||
stream->write_function(stream, "Illegal Usage\n");
|
stream->write_function(stream, "Illegal Usage\n");
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
@ -415,12 +417,17 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aleg = argv[0];
|
if (!strcasecmp(argv[0], "machine")) {
|
||||||
exten = argv[1];
|
machine = 1;
|
||||||
dp = argv[2];
|
i++;
|
||||||
context = argv[3];
|
}
|
||||||
cid_name = argv[4];
|
|
||||||
cid_num = argv[5];
|
aleg = argv[i++];
|
||||||
|
exten = argv[i++];
|
||||||
|
dp = argv[i++];
|
||||||
|
context = argv[i++];
|
||||||
|
cid_name = argv[i++];
|
||||||
|
cid_num = argv[i++];
|
||||||
|
|
||||||
if (!dp) {
|
if (!dp) {
|
||||||
dp = "XML";
|
dp = "XML";
|
||||||
@ -435,7 +442,11 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (switch_ivr_originate(NULL, &caller_session, &cause, aleg, timeout, &noop_state_handler, cid_name, cid_num, NULL) != SWITCH_STATUS_SUCCESS) {
|
if (switch_ivr_originate(NULL, &caller_session, &cause, aleg, timeout, &noop_state_handler, cid_name, cid_num, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||||
stream->write_function(stream, "Cannot Create Outgoing Channel! [%s]\n", aleg);
|
if (machine) {
|
||||||
|
stream->write_function(stream, "fail: %s", switch_channel_cause2str(cause));
|
||||||
|
} else {
|
||||||
|
stream->write_function(stream, "Cannot Create Outgoing Channel! [%s] cause: %s\n", aleg, switch_channel_cause2str(cause));
|
||||||
|
}
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,7 +478,13 @@ static switch_status_t originate_function(char *cmd, switch_core_session_t *ises
|
|||||||
} else {
|
} else {
|
||||||
switch_ivr_session_transfer(caller_session, exten, dp, context);
|
switch_ivr_session_transfer(caller_session, exten, dp, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (machine) {
|
||||||
|
stream->write_function(stream, "success: %s\n", switch_core_session_get_uuid(caller_session));
|
||||||
|
} else {
|
||||||
stream->write_function(stream, "Created Session: %s\n", switch_core_session_get_uuid(caller_session));
|
stream->write_function(stream, "Created Session: %s\n", switch_core_session_get_uuid(caller_session));
|
||||||
|
}
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;;
|
return SWITCH_STATUS_SUCCESS;;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +666,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
|||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
|
|
||||||
if (conference->fnode->type == NODE_TYPE_SPEECH) {
|
if (conference->fnode->type == NODE_TYPE_SPEECH) {
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
switch_core_speech_close(&conference->fnode->sh, &flags);
|
switch_core_speech_close(&conference->fnode->sh, &flags);
|
||||||
} else {
|
} else {
|
||||||
switch_core_file_close(&conference->fnode->fh);
|
switch_core_file_close(&conference->fnode->fh);
|
||||||
@ -957,7 +957,7 @@ static void conference_loop(conference_member_t *member)
|
|||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
|
|
||||||
if (member->fnode->type == NODE_TYPE_SPEECH) {
|
if (member->fnode->type == NODE_TYPE_SPEECH) {
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
switch_core_speech_close(&member->fnode->sh, &flags);
|
switch_core_speech_close(&member->fnode->sh, &flags);
|
||||||
} else {
|
} else {
|
||||||
switch_core_file_close(&member->fnode->fh);
|
switch_core_file_close(&member->fnode->fh);
|
||||||
@ -1340,7 +1340,7 @@ static switch_status_t conference_member_say(conference_obj_t *conference, confe
|
|||||||
{
|
{
|
||||||
confernce_file_node_t *fnode, *nptr;
|
confernce_file_node_t *fnode, *nptr;
|
||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
|
|
||||||
if (!(conference->tts_engine && conference->tts_voice)) {
|
if (!(conference->tts_engine && conference->tts_voice)) {
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
@ -1399,7 +1399,7 @@ static switch_status_t conference_say(conference_obj_t *conference, char *text,
|
|||||||
{
|
{
|
||||||
confernce_file_node_t *fnode, *nptr;
|
confernce_file_node_t *fnode, *nptr;
|
||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
|
||||||
switch_mutex_lock(conference->mutex);
|
switch_mutex_lock(conference->mutex);
|
||||||
|
@ -34,6 +34,33 @@
|
|||||||
|
|
||||||
static const char modname[] = "mod_dptools";
|
static const char modname[] = "mod_dptools";
|
||||||
|
|
||||||
|
static const switch_application_interface_t detect_speech_application_interface;
|
||||||
|
|
||||||
|
static void detect_speech_function(switch_core_session_t *session, char *data)
|
||||||
|
{
|
||||||
|
char *argv[4];
|
||||||
|
int argc;
|
||||||
|
char *lbuf = NULL;
|
||||||
|
|
||||||
|
if ((lbuf = switch_core_session_strdup(session, data)) && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
||||||
|
if (!strcasecmp(argv[0], "grammar") && argc >= 1) {
|
||||||
|
switch_ivr_detect_speech_load_grammar(session, argv[1], argv[2]);
|
||||||
|
} else if (!strcasecmp(argv[0], "nogrammar")) {
|
||||||
|
switch_ivr_detect_speech_unload_grammar(session, argv[1]);
|
||||||
|
} else if (!strcasecmp(argv[0], "pause")) {
|
||||||
|
switch_ivr_pause_detect_speech(session);
|
||||||
|
} else if (!strcasecmp(argv[0], "resume")) {
|
||||||
|
switch_ivr_resume_detect_speech(session);
|
||||||
|
} else if (!strcasecmp(argv[0], "stop")) {
|
||||||
|
switch_ivr_stop_detect_speech(session);
|
||||||
|
} else if (argc >= 3) {
|
||||||
|
switch_ivr_detect_speech(session, argv[0], argv[1], argv[2], argv[3], NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", detect_speech_application_interface.syntax);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void ringback_function(switch_core_session_t *session, char *data)
|
static void ringback_function(switch_core_session_t *session, char *data)
|
||||||
{
|
{
|
||||||
@ -253,7 +280,6 @@ static switch_api_interface_t dptools_api_interface = {
|
|||||||
/*.next */ &chat_api_interface
|
/*.next */ &chat_api_interface
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static switch_api_interface_t presence_api_interface = {
|
static switch_api_interface_t presence_api_interface = {
|
||||||
/*.interface_name */ "presence",
|
/*.interface_name */ "presence",
|
||||||
/*.desc */ "presence",
|
/*.desc */ "presence",
|
||||||
@ -262,6 +288,14 @@ static switch_api_interface_t presence_api_interface = {
|
|||||||
/*.next */ &dptools_api_interface
|
/*.next */ &dptools_api_interface
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const switch_application_interface_t detect_speech_application_interface = {
|
||||||
|
/*.interface_name */ "detect_speech",
|
||||||
|
/*.application_function */ detect_speech_function,
|
||||||
|
/* long_desc */ "Detect speech on a channel.",
|
||||||
|
/* short_desc */ "Detect speech",
|
||||||
|
/* syntax */ "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR pause OR resume",
|
||||||
|
/*.next */ NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const switch_application_interface_t ringback_application_interface = {
|
static const switch_application_interface_t ringback_application_interface = {
|
||||||
/*.interface_name */ "ringback",
|
/*.interface_name */ "ringback",
|
||||||
@ -269,8 +303,7 @@ static const switch_application_interface_t ringback_application_interface = {
|
|||||||
/* long_desc */ "Indicate Ringback on a channel.",
|
/* long_desc */ "Indicate Ringback on a channel.",
|
||||||
/* short_desc */ "Indicate Ringback",
|
/* short_desc */ "Indicate Ringback",
|
||||||
/* syntax */ "",
|
/* syntax */ "",
|
||||||
/*.next */ NULL
|
/*.next */ &detect_speech_application_interface
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const switch_application_interface_t set_application_interface = {
|
static const switch_application_interface_t set_application_interface = {
|
||||||
|
@ -167,6 +167,123 @@ static void tts_function(switch_core_session_t *session, char *data)
|
|||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
static void asrtest_function(switch_core_session_t *session, char *data)
|
||||||
|
{
|
||||||
|
switch_ivr_detect_speech(session,
|
||||||
|
"lumenvox",
|
||||||
|
"demo",
|
||||||
|
data,
|
||||||
|
"127.0.0.1",
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static void asrtest_function(switch_core_session_t *session, char *data)
|
||||||
|
{
|
||||||
|
switch_asr_handle_t ah = {0};
|
||||||
|
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
char *codec_name = "L16";
|
||||||
|
switch_codec_t codec = {0}, *read_codec;
|
||||||
|
switch_frame_t write_frame = {0}, *write_frame_p = NULL;
|
||||||
|
char xdata[1024] = "";
|
||||||
|
|
||||||
|
read_codec = switch_core_session_get_read_codec(session);
|
||||||
|
assert(read_codec != NULL);
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_core_asr_open(&ah, "lumenvox",
|
||||||
|
read_codec->implementation->iananame,
|
||||||
|
8000,
|
||||||
|
"127.0.0.1",
|
||||||
|
&flags,
|
||||||
|
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
if (strcmp(ah.codec, read_codec->implementation->iananame)) {
|
||||||
|
if (switch_core_codec_init(&codec,
|
||||||
|
ah.codec,
|
||||||
|
NULL,
|
||||||
|
ah.rate,
|
||||||
|
read_codec->implementation->microseconds_per_frame / 1000,
|
||||||
|
read_codec->implementation->number_of_channels,
|
||||||
|
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
|
||||||
|
NULL, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
|
||||||
|
switch_core_session_set_read_codec(session, &codec);
|
||||||
|
write_frame.data = xdata;
|
||||||
|
write_frame.buflen = sizeof(xdata);
|
||||||
|
write_frame.codec = &codec;
|
||||||
|
write_frame_p = &write_frame;
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec Activation Failed %s@%uhz %u channels %dms\n",
|
||||||
|
codec_name, read_codec->implementation->samples_per_second, read_codec->implementation->number_of_channels,
|
||||||
|
read_codec->implementation->microseconds_per_frame / 1000);
|
||||||
|
switch_core_session_reset(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_core_asr_load_grammar(&ah, "demo", "/opt/lumenvox/engine_7.0/Lang/BuiltinGrammars/ABNFPhone.gram") != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(switch_channel_ready(channel)) {
|
||||||
|
switch_frame_t *read_frame;
|
||||||
|
switch_status_t status = switch_core_session_read_frame(session, &read_frame, -1, 0);
|
||||||
|
char *xmlstr = NULL;
|
||||||
|
switch_xml_t xml = NULL, result;
|
||||||
|
|
||||||
|
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_test_flag(read_frame, SFF_CNG)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_core_asr_feed(&ah, read_frame->data, read_frame->datalen, &flags) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error Feeding Data\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_core_asr_check_results(&ah, &flags) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
if (switch_core_asr_get_results(&ah, &xmlstr, &flags) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RAW XML\n========\n%s\n", xmlstr);
|
||||||
|
|
||||||
|
if ((xml = switch_xml_parse_str(xmlstr, strlen(xmlstr))) && (result = switch_xml_child(xml, "result"))) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Results [%s]\n", result->txt);
|
||||||
|
switch_xml_free(xml);
|
||||||
|
}
|
||||||
|
switch_safe_free(xmlstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_frame_p) {
|
||||||
|
write_frame.datalen = read_frame->datalen;
|
||||||
|
switch_core_session_write_frame(session, write_frame_p, -1, 0);
|
||||||
|
} else {
|
||||||
|
memset(read_frame->data, 0, read_frame->datalen);
|
||||||
|
switch_core_session_write_frame(session, read_frame, -1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (write_frame_p) {
|
||||||
|
switch_core_session_set_read_codec(session, read_codec);
|
||||||
|
switch_core_codec_destroy(&codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_core_asr_close(&ah, &flags);
|
||||||
|
switch_core_session_reset(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ivrtest_function(switch_core_session_t *session, char *data)
|
static void ivrtest_function(switch_core_session_t *session, char *data)
|
||||||
{
|
{
|
||||||
switch_channel_t *channel;
|
switch_channel_t *channel;
|
||||||
@ -272,13 +389,20 @@ static const switch_application_interface_t ivrtest_application_interface = {
|
|||||||
/*.next*/ &dirtest_application_interface
|
/*.next*/ &dirtest_application_interface
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const switch_application_interface_t asrtest_application_interface = {
|
||||||
|
/*.interface_name */ "asrtest",
|
||||||
|
/*.application_function */ asrtest_function,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
/*.next*/ &ivrtest_application_interface
|
||||||
|
};
|
||||||
|
|
||||||
static const switch_loadable_module_interface_t mod_ivrtest_module_interface = {
|
static const switch_loadable_module_interface_t mod_ivrtest_module_interface = {
|
||||||
/*.module_name = */ modname,
|
/*.module_name = */ modname,
|
||||||
/*.endpoint_interface = */ NULL,
|
/*.endpoint_interface = */ NULL,
|
||||||
/*.timer_interface = */ NULL,
|
/*.timer_interface = */ NULL,
|
||||||
/*.dialplan_interface = */ NULL,
|
/*.dialplan_interface = */ NULL,
|
||||||
/*.codec_interface = */ NULL,
|
/*.codec_interface = */ NULL,
|
||||||
/*.application_interface */ &ivrtest_application_interface
|
/*.application_interface */ &asrtest_application_interface
|
||||||
};
|
};
|
||||||
|
|
||||||
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
|
SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
|
||||||
|
@ -169,7 +169,7 @@ static void rss_function(switch_core_session_t *session, char *data)
|
|||||||
char *voice = TTS_DEFAULT_VOICE;
|
char *voice = TTS_DEFAULT_VOICE;
|
||||||
char *timer_name = NULL;
|
char *timer_name = NULL;
|
||||||
switch_speech_handle_t sh;
|
switch_speech_handle_t sh;
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
switch_core_thread_session_t thread_session;
|
switch_core_thread_session_t thread_session;
|
||||||
uint32_t rate, interval = 20;
|
uint32_t rate, interval = 20;
|
||||||
int stream_id = 0;
|
int stream_id = 0;
|
||||||
|
@ -109,10 +109,6 @@ static swift_result_t write_audio(swift_event *event, swift_event_t type, void *
|
|||||||
|
|
||||||
static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, char *voice_name, int rate, switch_speech_flag_t *flags)
|
static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, char *voice_name, int rate, switch_speech_flag_t *flags)
|
||||||
{
|
{
|
||||||
if (*flags & SWITCH_SPEECH_FLAG_ASR) {
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
if (*flags & SWITCH_SPEECH_FLAG_TTS) {
|
|
||||||
cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral));
|
cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral));
|
||||||
char srate[25];
|
char srate[25];
|
||||||
|
|
||||||
@ -171,7 +167,6 @@ static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, char *vo
|
|||||||
|
|
||||||
sh->private_info = cepstral;
|
sh->private_info = cepstral;
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
|
||||||
|
|
||||||
all_done:
|
all_done:
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
@ -227,7 +222,7 @@ static switch_status_t cepstral_speech_feed_tts(switch_speech_handle_t *sh, char
|
|||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
swift_port_speak_text(cepstral->port, "<break time=\"400ms\"/>", 0, NULL, &cepstral->tts_stream, NULL);
|
swift_port_speak_text(cepstral->port, "<break time=\"500ms\"/>", 0, NULL, &cepstral->tts_stream, NULL);
|
||||||
swift_port_speak_text(cepstral->port, text, 0, NULL, &cepstral->tts_stream, NULL);
|
swift_port_speak_text(cepstral->port, text, 0, NULL, &cepstral->tts_stream, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,8 +399,6 @@ static const switch_speech_interface_t cepstral_speech_interface = {
|
|||||||
/*.interface_name*/ "cepstral",
|
/*.interface_name*/ "cepstral",
|
||||||
/*.speech_open*/ cepstral_speech_open,
|
/*.speech_open*/ cepstral_speech_open,
|
||||||
/*.speech_close*/ cepstral_speech_close,
|
/*.speech_close*/ cepstral_speech_close,
|
||||||
/*.speech_feed_asr*/ NULL,
|
|
||||||
/*.speech_interpret_asr*/ NULL,
|
|
||||||
/*.speech_feed_tts*/ cepstral_speech_feed_tts,
|
/*.speech_feed_tts*/ cepstral_speech_feed_tts,
|
||||||
/*.speech_read_tts*/ cepstral_speech_read_tts,
|
/*.speech_read_tts*/ cepstral_speech_read_tts,
|
||||||
/*.speech_flush_tts*/ cepstral_speech_flush_tts,
|
/*.speech_flush_tts*/ cepstral_speech_flush_tts,
|
||||||
|
@ -77,6 +77,7 @@ static struct {
|
|||||||
char *ip;
|
char *ip;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
char *password;
|
char *password;
|
||||||
|
int done;
|
||||||
} prefs;
|
} prefs;
|
||||||
|
|
||||||
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip)
|
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip)
|
||||||
@ -166,6 +167,8 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void)
|
|||||||
{
|
{
|
||||||
listener_t *l;
|
listener_t *l;
|
||||||
|
|
||||||
|
prefs.done = 1;
|
||||||
|
|
||||||
close_socket(&listen_list.sock);
|
close_socket(&listen_list.sock);
|
||||||
|
|
||||||
switch_mutex_lock(listen_list.mutex);
|
switch_mutex_lock(listen_list.mutex);
|
||||||
@ -1003,7 +1006,11 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_runtime(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((rv = switch_socket_accept(&inbound_socket, listen_list.sock, listener_pool))) {
|
if ((rv = switch_socket_accept(&inbound_socket, listen_list.sock, listener_pool))) {
|
||||||
|
if (prefs.done) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
|
||||||
|
} else {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,13 +97,18 @@ typedef enum {
|
|||||||
S_HUP = (1 << 0)
|
S_HUP = (1 << 0)
|
||||||
} session_flag_t;
|
} session_flag_t;
|
||||||
|
|
||||||
struct dtmf_callback_state {
|
struct input_callback_state {
|
||||||
struct js_session *session_state;
|
struct js_session *session_state;
|
||||||
char code_buffer[1024];
|
char code_buffer[1024];
|
||||||
size_t code_buffer_len;
|
size_t code_buffer_len;
|
||||||
char ret_buffer[1024];
|
char ret_buffer[1024];
|
||||||
int ret_buffer_len;
|
int ret_buffer_len;
|
||||||
int digit_count;
|
int digit_count;
|
||||||
|
JSFunction *function;
|
||||||
|
jsval arg;
|
||||||
|
jsval ret;
|
||||||
|
JSContext *cx;
|
||||||
|
JSObject *obj;
|
||||||
void *extra;
|
void *extra;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,8 +130,9 @@ struct teletone_obj {
|
|||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
switch_timer_t *timer;
|
switch_timer_t *timer;
|
||||||
switch_timer_t timer_base;
|
switch_timer_t timer_base;
|
||||||
char code_buffer[1024];
|
JSFunction *function;
|
||||||
char ret_val[1024];
|
jsval arg;
|
||||||
|
jsval ret;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,15 +157,24 @@ struct db_obj {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct event_obj {
|
||||||
|
switch_event_t *event;
|
||||||
|
int freed;
|
||||||
|
};
|
||||||
|
|
||||||
/* Event Object */
|
/* Event Object */
|
||||||
/*********************************************************************************/
|
/*********************************************************************************/
|
||||||
static JSBool event_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
switch_event_t *event;
|
switch_event_t *event;
|
||||||
|
struct event_obj *eo;
|
||||||
switch_event_types_t etype;
|
switch_event_types_t etype;
|
||||||
char *ename = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
char *ename = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||||
|
|
||||||
|
if ((eo = malloc(sizeof(*eo)))) {
|
||||||
|
|
||||||
if (switch_name_event(ename, &etype) != SWITCH_STATUS_SUCCESS) {
|
if (switch_name_event(ename, &etype) != SWITCH_STATUS_SUCCESS) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
@ -185,27 +200,34 @@ static JSBool event_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_SetPrivate(cx, obj, event);
|
eo->event = event;
|
||||||
|
eo->freed = 0;
|
||||||
|
|
||||||
|
JS_SetPrivate(cx, obj, eo);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void event_destroy(JSContext *cx, JSObject *obj)
|
static void event_destroy(JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (event) {
|
if (eo) {
|
||||||
switch_event_destroy(&event);
|
if (!eo->freed && eo->event) {
|
||||||
|
switch_event_destroy(&eo->event);
|
||||||
|
}
|
||||||
|
switch_safe_free(eo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool event_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (!event) {
|
if (!eo || eo->freed) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -213,7 +235,7 @@ static JSBool event_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *
|
|||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||||
char *hval = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
char *hval = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||||
switch_event_add_header(event, SWITCH_STACK_BOTTOM, hname, hval);
|
switch_event_add_header(eo->event, SWITCH_STACK_BOTTOM, hname, hval);
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -224,16 +246,16 @@ static JSBool event_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *
|
|||||||
|
|
||||||
static JSBool event_get_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_get_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (!event) {
|
if (!eo) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
char *hname = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||||
char *val = switch_event_get_header(event, hname);
|
char *val = switch_event_get_header(eo->event, hname);
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, val));
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, val));
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -244,16 +266,16 @@ static JSBool event_get_header(JSContext *cx, JSObject *obj, uintN argc, jsval *
|
|||||||
|
|
||||||
static JSBool event_add_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_add_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (!event) {
|
if (!eo || eo->freed) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
char *body = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
char *body = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||||
switch_event_add_body(event, body);
|
switch_event_add_body(eo->event, body);
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -264,25 +286,39 @@ static JSBool event_add_body(JSContext *cx, JSObject *obj, uintN argc, jsval *ar
|
|||||||
|
|
||||||
static JSBool event_get_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_get_body(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (!event) {
|
if (!eo) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_event_get_body(event)));
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_event_get_body(eo->event)));
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool event_get_type(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
|
if (!eo) {
|
||||||
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_event_name(eo->event->event_id)));
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
uint8_t isxml = 0;
|
uint8_t isxml = 0;
|
||||||
|
|
||||||
if (!event) {
|
if (!eo) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -297,7 +333,7 @@ static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *a
|
|||||||
if (isxml) {
|
if (isxml) {
|
||||||
switch_xml_t xml;
|
switch_xml_t xml;
|
||||||
char *xmlstr;
|
char *xmlstr;
|
||||||
if ((xml = switch_event_xmlize(event, NULL))) {
|
if ((xml = switch_event_xmlize(eo->event, NULL))) {
|
||||||
xmlstr = switch_xml_toxml(xml);
|
xmlstr = switch_xml_toxml(xml);
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, xmlstr));
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, xmlstr));
|
||||||
switch_xml_free(xml);
|
switch_xml_free(xml);
|
||||||
@ -306,7 +342,7 @@ static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *a
|
|||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch_event_serialize(event, buf, sizeof(buf), NULL);
|
switch_event_serialize(eo->event, buf, sizeof(buf), NULL);
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, buf));
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,11 +351,12 @@ static JSBool event_serialize(JSContext *cx, JSObject *obj, uintN argc, jsval *a
|
|||||||
|
|
||||||
static JSBool event_fire(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_fire(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (event) {
|
if (eo) {
|
||||||
switch_event_fire(&event);
|
switch_event_fire(&eo->event);
|
||||||
JS_SetPrivate(cx, obj, NULL);
|
JS_SetPrivate(cx, obj, NULL);
|
||||||
|
switch_safe_free(eo);
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -330,11 +367,14 @@ static JSBool event_fire(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||||||
|
|
||||||
static JSBool event_destroy_(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool event_destroy_(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
switch_event_t *event = JS_GetPrivate(cx, obj);
|
struct event_obj *eo = JS_GetPrivate(cx, obj);
|
||||||
|
|
||||||
if (event) {
|
if (eo) {
|
||||||
switch_event_destroy(&event);
|
if (!eo->freed) {
|
||||||
|
switch_event_destroy(&eo->event);
|
||||||
|
}
|
||||||
JS_SetPrivate(cx, obj, NULL);
|
JS_SetPrivate(cx, obj, NULL);
|
||||||
|
switch_safe_free(eo);
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -354,6 +394,7 @@ static JSFunctionSpec event_methods[] = {
|
|||||||
{"getHeader", event_get_header, 1},
|
{"getHeader", event_get_header, 1},
|
||||||
{"addBody", event_add_body, 1},
|
{"addBody", event_add_body, 1},
|
||||||
{"getBody", event_get_body, 1},
|
{"getBody", event_get_body, 1},
|
||||||
|
{"getType", event_get_type, 1},
|
||||||
{"serialize", event_serialize, 0},
|
{"serialize", event_serialize, 0},
|
||||||
{"fire", event_fire, 0},
|
{"fire", event_fire, 0},
|
||||||
{"destroy", event_destroy_, 0},
|
{"destroy", event_destroy_, 0},
|
||||||
@ -410,7 +451,8 @@ JSClass event_class = {
|
|||||||
static void js_error(JSContext *cx, const char *message, JSErrorReport *report)
|
static void js_error(JSContext *cx, const char *message, JSErrorReport *report)
|
||||||
{
|
{
|
||||||
if (message) {
|
if (message) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", message);
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, (char *)report->filename, modname, report->lineno, SWITCH_LOG_ERROR,
|
||||||
|
"%s %s%s\n", message, report->linebuf ? "near " : "", report->linebuf ? report->linebuf : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -433,43 +475,80 @@ static switch_status_t init_js(void)
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static switch_status_t js_stream_dtmf_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
JSObject *new_js_event(switch_event_t *event, char *name, JSContext *cx, JSObject *obj)
|
||||||
{
|
{
|
||||||
switch (itype) {
|
struct event_obj *eo;
|
||||||
case SWITCH_INPUT_TYPE_DTMF: {
|
JSObject *Event = NULL;
|
||||||
char *dtmf = (char *) input;
|
|
||||||
char code[2048];
|
if ((eo = malloc(sizeof(*eo)))) {
|
||||||
struct dtmf_callback_state *cb_state = buf;
|
eo->event = event;
|
||||||
|
eo->freed = 1;
|
||||||
|
if ((Event = JS_DefineObject(cx, obj, name, &event_class, NULL, 0))) {
|
||||||
|
if ((JS_SetPrivate(cx, Event, eo) &&
|
||||||
|
JS_DefineProperties(cx, Event, event_props) &&
|
||||||
|
JS_DefineFunctions(cx, Event, event_methods))) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Event;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static switch_status_t js_common_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
||||||
|
{
|
||||||
|
char *dtmf = NULL;
|
||||||
|
switch_event_t *event = NULL;
|
||||||
|
struct input_callback_state *cb_state = buf;
|
||||||
struct js_session *jss = cb_state->session_state;
|
struct js_session *jss = cb_state->session_state;
|
||||||
switch_file_handle_t *fh = cb_state->extra;
|
uintN argc = 0;
|
||||||
jsval rval;
|
jsval argv[4];
|
||||||
char *ret;
|
JSObject *Event = NULL;
|
||||||
|
|
||||||
if (!jss) {
|
if (!jss) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb_state->digit_count || (cb_state->code_buffer[0] > 47 && cb_state->code_buffer[0] < 58)) {
|
switch (itype) {
|
||||||
char *d;
|
case SWITCH_INPUT_TYPE_EVENT:
|
||||||
if (!cb_state->digit_count) {
|
if ((event = (switch_event_t *) input)) {
|
||||||
cb_state->digit_count = atoi(cb_state->code_buffer);
|
if ((Event = new_js_event(event, "_XX_EVENT_XX_", cb_state->cx, cb_state->obj))) {
|
||||||
|
argv[argc++] = STRING_TO_JSVAL (JS_NewStringCopyZ(cb_state->cx, "event"));
|
||||||
|
argv[argc++] = OBJECT_TO_JSVAL(Event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for(d = dtmf; *d; d++) {
|
if (!Event) {
|
||||||
cb_state->ret_buffer[cb_state->ret_buffer_len++] = *d;
|
|
||||||
if ((cb_state->ret_buffer_len > cb_state->digit_count)||
|
|
||||||
(cb_state->ret_buffer_len > (int32_t) sizeof(cb_state->ret_buffer))||
|
|
||||||
(cb_state->ret_buffer_len >= cb_state->digit_count)
|
|
||||||
) {
|
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case SWITCH_INPUT_TYPE_DTMF:
|
||||||
|
dtmf = (char *) input;
|
||||||
|
argv[argc++] = STRING_TO_JSVAL (JS_NewStringCopyZ(cb_state->cx, "dtmf"));
|
||||||
|
argv[argc++] = STRING_TO_JSVAL (JS_NewStringCopyZ(cb_state->cx, dtmf));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
} else {
|
|
||||||
snprintf(code, sizeof(code), "~%s(\"%s\")", cb_state->code_buffer, dtmf);
|
|
||||||
eval_some_js(code, jss->cx, jss->obj, &rval);
|
|
||||||
ret = JS_GetStringBytes(JS_ValueToString(jss->cx, rval));
|
|
||||||
|
|
||||||
|
if (cb_state->arg) {
|
||||||
|
argv[argc++] = cb_state->arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_CallFunction(cb_state->cx, cb_state->obj, cb_state->function, argc, argv, &cb_state->ret);
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static switch_status_t js_stream_input_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
||||||
|
{
|
||||||
|
char *ret;
|
||||||
|
switch_status_t status;
|
||||||
|
struct input_callback_state *cb_state = buf;
|
||||||
|
switch_file_handle_t *fh = cb_state->extra;
|
||||||
|
struct js_session *jss = cb_state->session_state;
|
||||||
|
|
||||||
|
if ((status = js_common_callback(session, input, itype, buf, buflen)) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = JS_GetStringBytes(JS_ValueToString(cb_state->cx, cb_state->ret)))) {
|
||||||
if (!strncasecmp(ret, "speed", 4)) {
|
if (!strncasecmp(ret, "speed", 4)) {
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
@ -535,58 +614,23 @@ static switch_status_t js_stream_dtmf_callback(switch_core_session_t *session, v
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
return SWITCH_STATUS_BREAK;
|
||||||
switch_copy_string(cb_state->ret_buffer, ret, sizeof(cb_state->ret_buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static switch_status_t js_record_dtmf_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
static switch_status_t js_record_input_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
||||||
{
|
{
|
||||||
switch (itype) {
|
|
||||||
case SWITCH_INPUT_TYPE_DTMF: {
|
|
||||||
char *dtmf = (char *) input;
|
|
||||||
char code[2048];
|
|
||||||
struct dtmf_callback_state *cb_state = buf;
|
|
||||||
struct js_session *jss = cb_state->session_state;
|
|
||||||
switch_file_handle_t *fh = cb_state->extra;
|
|
||||||
jsval rval;
|
|
||||||
char *ret;
|
char *ret;
|
||||||
|
switch_status_t status;
|
||||||
|
struct input_callback_state *cb_state = buf;
|
||||||
|
switch_file_handle_t *fh = cb_state->extra;
|
||||||
|
|
||||||
if (!jss) {
|
if ((status = js_common_callback(session, input, itype, buf, buflen)) != SWITCH_STATUS_SUCCESS) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb_state->digit_count || (cb_state->code_buffer[0] > 47 && cb_state->code_buffer[0] < 58)) {
|
if ((ret = JS_GetStringBytes(JS_ValueToString(cb_state->cx, cb_state->ret)))) {
|
||||||
char *d;
|
|
||||||
if (!cb_state->digit_count) {
|
|
||||||
cb_state->digit_count = atoi(cb_state->code_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(d = dtmf; *d; d++) {
|
|
||||||
cb_state->ret_buffer[cb_state->ret_buffer_len++] = *d;
|
|
||||||
if ((cb_state->ret_buffer_len > cb_state->digit_count)||
|
|
||||||
(cb_state->ret_buffer_len > (int32_t) sizeof(cb_state->ret_buffer))||
|
|
||||||
(cb_state->ret_buffer_len >= cb_state->digit_count)
|
|
||||||
) {
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
} else {
|
|
||||||
snprintf(code, sizeof(code), "~%s(\"%s\")", cb_state->code_buffer, dtmf);
|
|
||||||
eval_some_js(code, jss->cx, jss->obj, &rval);
|
|
||||||
ret = JS_GetStringBytes(JS_ValueToString(jss->cx, rval));
|
|
||||||
|
|
||||||
if (!strcasecmp(ret, "pause")) {
|
if (!strcasecmp(ret, "pause")) {
|
||||||
if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
|
if (switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
|
||||||
switch_clear_flag(fh, SWITCH_FILE_PAUSE);
|
switch_clear_flag(fh, SWITCH_FILE_PAUSE);
|
||||||
@ -605,75 +649,30 @@ static switch_status_t js_record_dtmf_callback(switch_core_session_t *session, v
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
return SWITCH_STATUS_BREAK;
|
||||||
switch_copy_string(cb_state->ret_buffer, ret, sizeof(cb_state->ret_buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static switch_status_t js_collect_input_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
||||||
static switch_status_t js_speak_dtmf_callback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
|
||||||
{
|
{
|
||||||
switch (itype) {
|
|
||||||
case SWITCH_INPUT_TYPE_DTMF: {
|
|
||||||
char *dtmf = (char *) input;
|
|
||||||
char code[2048];
|
|
||||||
struct dtmf_callback_state *cb_state = buf;
|
|
||||||
struct js_session *jss = cb_state->session_state;
|
|
||||||
jsval rval;
|
|
||||||
char *ret;
|
char *ret;
|
||||||
|
switch_status_t status;
|
||||||
|
struct input_callback_state *cb_state = buf;
|
||||||
|
|
||||||
if (!jss) {
|
if ((status = js_common_callback(session, input, itype, buf, buflen)) != SWITCH_STATUS_SUCCESS) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb_state->digit_count || (cb_state->code_buffer[0] > 47 && cb_state->code_buffer[0] < 58)) {
|
if ((ret = JS_GetStringBytes(JS_ValueToString(cb_state->cx, cb_state->ret)))) {
|
||||||
char *d;
|
|
||||||
if (!cb_state->digit_count) {
|
|
||||||
cb_state->digit_count = atoi(cb_state->code_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(d = dtmf; *d; d++) {
|
|
||||||
cb_state->ret_buffer[cb_state->ret_buffer_len++] = *d;
|
|
||||||
if ((cb_state->ret_buffer_len > cb_state->digit_count)||
|
|
||||||
(cb_state->ret_buffer_len > (int32_t) sizeof(cb_state->ret_buffer))||
|
|
||||||
(cb_state->ret_buffer_len >= cb_state->digit_count)
|
|
||||||
) {
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
} else {
|
|
||||||
snprintf(code, sizeof(code), "~%s(\"%s\")", cb_state->code_buffer, dtmf);
|
|
||||||
eval_some_js(code, jss->cx, jss->obj, &rval);
|
|
||||||
ret = JS_GetStringBytes(JS_ValueToString(jss->cx, rval));
|
|
||||||
|
|
||||||
if (!strcmp(ret, "true") || !strcmp(ret, "undefined")) {
|
if (!strcmp(ret, "true") || !strcmp(ret, "undefined")) {
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
return SWITCH_STATUS_BREAK;
|
||||||
if (ret) {
|
|
||||||
switch_copy_string(cb_state->ret_buffer, ret, sizeof(cb_state->ret_buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SWITCH_STATUS_FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool session_flush_digits(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool session_flush_digits(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
@ -713,12 +712,13 @@ static JSBool session_recordfile(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
struct js_session *jss = JS_GetPrivate(cx, obj);
|
struct js_session *jss = JS_GetPrivate(cx, obj);
|
||||||
switch_channel_t *channel;
|
switch_channel_t *channel;
|
||||||
char *file_name = NULL;
|
char *file_name = NULL;
|
||||||
char *dtmf_callback = NULL;
|
char *input_callback = NULL;
|
||||||
void *bp = NULL;
|
void *bp = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
switch_input_callback_function_t dtmf_func = NULL;
|
switch_input_callback_function_t dtmf_func = NULL;
|
||||||
struct dtmf_callback_state cb_state = {0};
|
struct input_callback_state cb_state = {0};
|
||||||
switch_file_handle_t fh;
|
switch_file_handle_t fh;
|
||||||
|
JSFunction *function;
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(jss->session);
|
channel = switch_core_session_get_channel(jss->session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
@ -730,15 +730,18 @@ static JSBool session_recordfile(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
dtmf_callback = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
if ((function = JS_ValueToFunction(cx, argv[1]))) {
|
||||||
if (switch_strlen_zero(dtmf_callback)) {
|
|
||||||
dtmf_callback = NULL;
|
|
||||||
} else {
|
|
||||||
memset(&cb_state, 0, sizeof(cb_state));
|
memset(&cb_state, 0, sizeof(cb_state));
|
||||||
switch_copy_string(cb_state.code_buffer, dtmf_callback, sizeof(cb_state.code_buffer));
|
switch_copy_string(cb_state.code_buffer, input_callback, sizeof(cb_state.code_buffer));
|
||||||
cb_state.code_buffer_len = strlen(cb_state.code_buffer);
|
|
||||||
cb_state.session_state = jss;
|
cb_state.session_state = jss;
|
||||||
dtmf_func = js_record_dtmf_callback;
|
cb_state.function = function;
|
||||||
|
cb_state.cx = cx;
|
||||||
|
cb_state.obj = obj;
|
||||||
|
if (argc > 2) {
|
||||||
|
cb_state.arg = argv[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
dtmf_func = js_record_input_callback;
|
||||||
bp = &cb_state;
|
bp = &cb_state;
|
||||||
len = sizeof(cb_state);
|
len = sizeof(cb_state);
|
||||||
}
|
}
|
||||||
@ -748,6 +751,49 @@ static JSBool session_recordfile(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
cb_state.extra = &fh;
|
cb_state.extra = &fh;
|
||||||
|
|
||||||
switch_ivr_record_file(jss->session, &fh, file_name, dtmf_func, bp, len);
|
switch_ivr_record_file(jss->session, &fh, file_name, dtmf_func, bp, len);
|
||||||
|
*rval = cb_state.ret;
|
||||||
|
|
||||||
|
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static JSBool session_collect_input(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
struct js_session *jss = JS_GetPrivate(cx, obj);
|
||||||
|
switch_channel_t *channel;
|
||||||
|
void *bp = NULL;
|
||||||
|
int len = 0;
|
||||||
|
int32 to = 0;
|
||||||
|
switch_input_callback_function_t dtmf_func = NULL;
|
||||||
|
struct input_callback_state cb_state = {0};
|
||||||
|
JSFunction *function;
|
||||||
|
|
||||||
|
channel = switch_core_session_get_channel(jss->session);
|
||||||
|
assert(channel != NULL);
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
if ((function = JS_ValueToFunction(cx, argv[0]))) {
|
||||||
|
memset(&cb_state, 0, sizeof(cb_state));
|
||||||
|
cb_state.function = function;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
cb_state.arg = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_state.session_state = jss;
|
||||||
|
cb_state.cx = cx;
|
||||||
|
cb_state.obj = obj;
|
||||||
|
dtmf_func = js_collect_input_callback;
|
||||||
|
bp = &cb_state;
|
||||||
|
len = sizeof(cb_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
JS_ValueToInt32(jss->cx, argv[2], &to);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_ivr_collect_digits_callback(jss->session, dtmf_func, bp, len, to);
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
|
||||||
|
|
||||||
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
||||||
@ -759,12 +805,13 @@ static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
switch_channel_t *channel;
|
switch_channel_t *channel;
|
||||||
char *file_name = NULL;
|
char *file_name = NULL;
|
||||||
char *timer_name = NULL;
|
char *timer_name = NULL;
|
||||||
char *dtmf_callback = NULL;
|
//char *input_callback = NULL;
|
||||||
void *bp = NULL;
|
void *bp = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
switch_input_callback_function_t dtmf_func = NULL;
|
switch_input_callback_function_t dtmf_func = NULL;
|
||||||
struct dtmf_callback_state cb_state = {0};
|
struct input_callback_state cb_state = {0};
|
||||||
switch_file_handle_t fh;
|
switch_file_handle_t fh;
|
||||||
|
JSFunction *function;
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(jss->session);
|
channel = switch_core_session_get_channel(jss->session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
@ -782,15 +829,18 @@ static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
dtmf_callback = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
|
if ((function = JS_ValueToFunction(cx, argv[2]))) {
|
||||||
if (switch_strlen_zero(dtmf_callback)) {
|
|
||||||
dtmf_callback = NULL;
|
|
||||||
} else {
|
|
||||||
memset(&cb_state, 0, sizeof(cb_state));
|
memset(&cb_state, 0, sizeof(cb_state));
|
||||||
switch_copy_string(cb_state.code_buffer, dtmf_callback, sizeof(cb_state.code_buffer));
|
cb_state.function = function;
|
||||||
cb_state.code_buffer_len = strlen(cb_state.code_buffer);
|
|
||||||
|
if (argc > 3) {
|
||||||
|
cb_state.arg = argv[3];
|
||||||
|
}
|
||||||
|
|
||||||
cb_state.session_state = jss;
|
cb_state.session_state = jss;
|
||||||
dtmf_func = js_stream_dtmf_callback;
|
cb_state.cx = cx;
|
||||||
|
cb_state.obj = obj;
|
||||||
|
dtmf_func = js_stream_input_callback;
|
||||||
bp = &cb_state;
|
bp = &cb_state;
|
||||||
len = sizeof(cb_state);
|
len = sizeof(cb_state);
|
||||||
}
|
}
|
||||||
@ -800,7 +850,7 @@ static JSBool session_streamfile(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
cb_state.extra = &fh;
|
cb_state.extra = &fh;
|
||||||
|
|
||||||
switch_ivr_play_file(jss->session, &fh, file_name, timer_name, dtmf_func, bp, len);
|
switch_ivr_play_file(jss->session, &fh, file_name, timer_name, dtmf_func, bp, len);
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
|
*rval = cb_state.ret;
|
||||||
|
|
||||||
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
||||||
}
|
}
|
||||||
@ -861,13 +911,13 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
|
|||||||
char *tts_name = NULL;
|
char *tts_name = NULL;
|
||||||
char *voice_name = NULL;
|
char *voice_name = NULL;
|
||||||
char *text = NULL;
|
char *text = NULL;
|
||||||
char *dtmf_callback = NULL;
|
|
||||||
char *timer_name = NULL;
|
char *timer_name = NULL;
|
||||||
switch_codec_t *codec;
|
switch_codec_t *codec;
|
||||||
void *bp = NULL;
|
void *bp = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
struct dtmf_callback_state cb_state = {0};
|
struct input_callback_state cb_state = {0};
|
||||||
switch_input_callback_function_t dtmf_func = NULL;
|
switch_input_callback_function_t dtmf_func = NULL;
|
||||||
|
JSFunction *function;
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(jss->session);
|
channel = switch_core_session_get_channel(jss->session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
@ -882,15 +932,17 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
|
|||||||
text = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
|
text = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
|
||||||
}
|
}
|
||||||
if (argc > 3) {
|
if (argc > 3) {
|
||||||
dtmf_callback = JS_GetStringBytes(JS_ValueToString(cx, argv[3]));
|
if ((function = JS_ValueToFunction(cx, argv[3]))) {
|
||||||
if (switch_strlen_zero(dtmf_callback)) {
|
|
||||||
dtmf_callback = NULL;
|
|
||||||
} else {
|
|
||||||
memset(&cb_state, 0, sizeof(cb_state));
|
memset(&cb_state, 0, sizeof(cb_state));
|
||||||
switch_copy_string(cb_state.code_buffer, dtmf_callback, sizeof(cb_state.code_buffer));
|
cb_state.function = function;
|
||||||
cb_state.code_buffer_len = strlen(cb_state.code_buffer);
|
if (argc > 4) {
|
||||||
|
cb_state.arg = argv[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_state.cx = cx;
|
||||||
|
cb_state.obj = obj;
|
||||||
cb_state.session_state = jss;
|
cb_state.session_state = jss;
|
||||||
dtmf_func = js_speak_dtmf_callback;
|
dtmf_func = js_collect_input_callback;
|
||||||
bp = &cb_state;
|
bp = &cb_state;
|
||||||
len = sizeof(cb_state);
|
len = sizeof(cb_state);
|
||||||
}
|
}
|
||||||
@ -915,7 +967,7 @@ static JSBool session_speak(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
|
|||||||
bp,
|
bp,
|
||||||
len);
|
len);
|
||||||
|
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, cb_state.ret_buffer));
|
*rval = cb_state.ret;
|
||||||
|
|
||||||
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
return (switch_channel_ready(channel)) ? JS_TRUE : JS_FALSE;
|
||||||
}
|
}
|
||||||
@ -971,6 +1023,41 @@ static JSBool session_ready(JSContext *cx, JSObject *obj, uintN argc, jsval *arg
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static JSBool session_wait_for_media(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
|
{
|
||||||
|
struct js_session *jss = JS_GetPrivate(cx, obj);
|
||||||
|
switch_channel_t *channel;
|
||||||
|
switch_time_t started;
|
||||||
|
unsigned int elapsed;
|
||||||
|
int32 timeout = 60;
|
||||||
|
channel = switch_core_session_get_channel(jss->session);
|
||||||
|
assert(channel != NULL);
|
||||||
|
started = switch_time_now();
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
JS_ValueToInt32(cx, argv[0], &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
if (((elapsed = (unsigned int)((switch_time_now() - started) / 1000)) > (switch_time_t)timeout) || switch_channel_get_state(channel) >= CS_HANGUP) {
|
||||||
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_channel_ready(channel) && (switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) {
|
||||||
|
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_yield(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static JSBool session_wait_for_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool session_wait_for_answer(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
struct js_session *jss = JS_GetPrivate(cx, obj);
|
struct js_session *jss = JS_GetPrivate(cx, obj);
|
||||||
@ -987,9 +1074,13 @@ static JSBool session_wait_for_answer(JSContext *cx, JSObject *obj, uintN argc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
elapsed = (unsigned int)((switch_time_now() - started) / 1000);
|
if (((elapsed = (unsigned int)((switch_time_now() - started) / 1000)) > (switch_time_t)timeout) || switch_channel_get_state(channel) >= CS_HANGUP) {
|
||||||
if ((int32)elapsed > timeout || switch_channel_test_flag(channel, CF_ANSWERED) ||
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
switch_channel_test_flag(channel, CF_EARLY_MEDIA)) {
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_channel_ready(channel) && switch_channel_test_flag(channel, CF_ANSWERED)) {
|
||||||
|
*rval = BOOLEAN_TO_JSVAL( JS_TRUE );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1027,8 +1118,14 @@ static JSBool session_get_event(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
|
|
||||||
if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
|
if (switch_core_session_dequeue_event(jss->session, &event) == SWITCH_STATUS_SUCCESS) {
|
||||||
JSObject *Event;
|
JSObject *Event;
|
||||||
if ((Event = JS_DefineObject(cx, obj, "Event", &event_class, NULL, 0))) {
|
struct event_obj *eo;
|
||||||
if ((JS_SetPrivate(cx, Event, event) &&
|
|
||||||
|
if ((eo = malloc(sizeof(*eo)))) {
|
||||||
|
eo->event = event;
|
||||||
|
eo->freed = 0;
|
||||||
|
|
||||||
|
if ((Event = JS_DefineObject(cx, obj, "__event__", &event_class, NULL, 0))) {
|
||||||
|
if ((JS_SetPrivate(cx, Event, eo) &&
|
||||||
JS_DefineProperties(cx, Event, event_props) &&
|
JS_DefineProperties(cx, Event, event_props) &&
|
||||||
JS_DefineFunctions(cx, Event, event_methods))) {
|
JS_DefineFunctions(cx, Event, event_methods))) {
|
||||||
*rval = OBJECT_TO_JSVAL ( Event );
|
*rval = OBJECT_TO_JSVAL ( Event );
|
||||||
@ -1036,6 +1133,7 @@ static JSBool session_get_event(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
@ -1045,13 +1143,13 @@ static JSBool session_get_event(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
static JSBool session_send_event(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool session_send_event(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
struct js_session *jss = JS_GetPrivate(cx, obj);
|
struct js_session *jss = JS_GetPrivate(cx, obj);
|
||||||
switch_event_t *event;
|
|
||||||
JSObject *Event;
|
JSObject *Event;
|
||||||
|
struct event_obj *eo;
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
if (JS_ValueToObject(cx, argv[0], &Event)) {
|
if (JS_ValueToObject(cx, argv[0], &Event)) {
|
||||||
if ((event = JS_GetPrivate(cx, Event))) {
|
if ((eo = JS_GetPrivate(cx, Event))) {
|
||||||
if (switch_core_session_receive_event(jss->session, &event) != SWITCH_STATUS_SUCCESS) {
|
if (switch_core_session_receive_event(jss->session, &eo->event) != SWITCH_STATUS_SUCCESS) {
|
||||||
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
*rval = BOOLEAN_TO_JSVAL( JS_FALSE );
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -1240,6 +1338,7 @@ enum session_tinyid {
|
|||||||
|
|
||||||
static JSFunctionSpec session_methods[] = {
|
static JSFunctionSpec session_methods[] = {
|
||||||
{"streamFile", session_streamfile, 1},
|
{"streamFile", session_streamfile, 1},
|
||||||
|
{"collectInput", session_collect_input, 1},
|
||||||
{"recordFile", session_recordfile, 1},
|
{"recordFile", session_recordfile, 1},
|
||||||
{"flushEvents", session_flush_events, 1},
|
{"flushEvents", session_flush_events, 1},
|
||||||
{"flushDigits", session_flush_digits, 1},
|
{"flushDigits", session_flush_digits, 1},
|
||||||
@ -1250,6 +1349,7 @@ static JSFunctionSpec session_methods[] = {
|
|||||||
{"answer", session_answer, 0},
|
{"answer", session_answer, 0},
|
||||||
{"ready", session_ready, 0},
|
{"ready", session_ready, 0},
|
||||||
{"waitForAnswer", session_wait_for_answer, 0},
|
{"waitForAnswer", session_wait_for_answer, 0},
|
||||||
|
{"waitForMedia", session_wait_for_media, 0},
|
||||||
{"getEvent", session_get_event, 0},
|
{"getEvent", session_get_event, 0},
|
||||||
{"sendEvent", session_send_event, 0},
|
{"sendEvent", session_send_event, 0},
|
||||||
{"hangup", session_hangup, 0},
|
{"hangup", session_hangup, 0},
|
||||||
@ -1280,6 +1380,10 @@ static JSBool session_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval
|
|||||||
switch_caller_profile_t *caller_profile;
|
switch_caller_profile_t *caller_profile;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
if (!jss || !jss->session) {
|
||||||
|
return JS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(jss->session);
|
channel = switch_core_session_get_channel(jss->session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
|
|
||||||
@ -1478,6 +1582,8 @@ static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, switch_channel_cause2str(cause)));
|
||||||
|
|
||||||
jss = switch_core_session_alloc(peer_session, sizeof(*jss));
|
jss = switch_core_session_alloc(peer_session, sizeof(*jss));
|
||||||
jss->session = peer_session;
|
jss->session = peer_session;
|
||||||
jss->flags = 0;
|
jss->flags = 0;
|
||||||
@ -1772,6 +1878,7 @@ static int db_callback(void *pArg, int argc, char **argv, char **columnNames)
|
|||||||
snprintf(code, sizeof(code), "~_Db_RoW_[\"%s\"] = \"%s\"", columnNames[x], argv[x]);
|
snprintf(code, sizeof(code), "~_Db_RoW_[\"%s\"] = \"%s\"", columnNames[x], argv[x]);
|
||||||
eval_some_js(code, dbo->cx, dbo->obj, &rval);
|
eval_some_js(code, dbo->cx, dbo->obj, &rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(code, sizeof(code), "~%s(_Db_RoW_)", dbo->code_buffer);
|
snprintf(code, sizeof(code), "~%s(_Db_RoW_)", dbo->code_buffer);
|
||||||
eval_some_js(code, dbo->cx, dbo->obj, &rval);
|
eval_some_js(code, dbo->cx, dbo->obj, &rval);
|
||||||
|
|
||||||
@ -1810,6 +1917,7 @@ static JSBool db_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsv
|
|||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static JSBool db_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
static JSBool db_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
struct db_obj *dbo = JS_GetPrivate(cx, obj);
|
struct db_obj *dbo = JS_GetPrivate(cx, obj);
|
||||||
@ -2065,8 +2173,10 @@ static JSBool teletone_on_dtmf(JSContext *cx, JSObject *obj, uintN argc, jsval *
|
|||||||
{
|
{
|
||||||
struct teletone_obj *tto = JS_GetPrivate(cx, obj);
|
struct teletone_obj *tto = JS_GetPrivate(cx, obj);
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
char *func = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
tto->function = JS_ValueToFunction(cx, argv[0]);
|
||||||
switch_copy_string(tto->code_buffer, func, sizeof(tto->code_buffer));
|
if (argc > 1) {
|
||||||
|
tto->arg = argv[1];
|
||||||
|
}
|
||||||
switch_set_flag(tto, TTF_DTMF);
|
switch_set_flag(tto, TTF_DTMF);
|
||||||
}
|
}
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
@ -2126,17 +2236,18 @@ static JSBool teletone_generate(JSContext *cx, JSObject *obj, uintN argc, jsval
|
|||||||
|
|
||||||
if (switch_test_flag(tto, TTF_DTMF)) {
|
if (switch_test_flag(tto, TTF_DTMF)) {
|
||||||
char dtmf[128];
|
char dtmf[128];
|
||||||
char code[512];
|
|
||||||
char *ret;
|
char *ret;
|
||||||
jsval tt_rval;
|
|
||||||
if (switch_channel_has_dtmf(channel)) {
|
if (switch_channel_has_dtmf(channel)) {
|
||||||
|
uintN aargc = 0;
|
||||||
|
jsval aargv[4];
|
||||||
|
|
||||||
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
|
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
|
||||||
snprintf(code, sizeof(code), "~%s(\"%s\")", tto->code_buffer, dtmf);
|
aargv[aargc++] = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, dtmf));
|
||||||
eval_some_js(code, cx, obj, &tt_rval);
|
JS_CallFunction(cx, obj, tto->function, aargc, aargv, &tto->ret);
|
||||||
ret = JS_GetStringBytes(JS_ValueToString(cx, tt_rval));
|
ret = JS_GetStringBytes(JS_ValueToString(cx, tto->ret));
|
||||||
if (strcmp(ret, "true") && strcmp(ret, "undefined")) {
|
if (strcmp(ret, "true") && strcmp(ret, "undefined")) {
|
||||||
switch_copy_string(tto->ret_val, ret, sizeof(tto->ret_val));
|
*rval = tto->ret;
|
||||||
*rval = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, tto->ret_val));
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2239,6 +2350,19 @@ static JSBool js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsva
|
|||||||
{
|
{
|
||||||
char *level_str, *msg;
|
char *level_str, *msg;
|
||||||
switch_log_level_t level = SWITCH_LOG_DEBUG;
|
switch_log_level_t level = SWITCH_LOG_DEBUG;
|
||||||
|
JSScript *script = NULL;
|
||||||
|
const char *file = __FILE__;
|
||||||
|
int line = __LINE__;
|
||||||
|
JSStackFrame *caller;
|
||||||
|
|
||||||
|
caller = JS_GetScriptedCaller(cx, NULL);
|
||||||
|
script = JS_GetFrameScript(cx, caller);
|
||||||
|
|
||||||
|
if (script) {
|
||||||
|
file = JS_GetScriptFilename(cx, script);
|
||||||
|
line = JS_GetScriptBaseLineNumber(cx, script);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
if ((level_str = JS_GetStringBytes(JS_ValueToString(cx, argv[0])))) {
|
if ((level_str = JS_GetStringBytes(JS_ValueToString(cx, argv[0])))) {
|
||||||
@ -2246,12 +2370,12 @@ static JSBool js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsva
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((msg = JS_GetStringBytes(JS_ValueToString(cx, argv[1])))) {
|
if ((msg = JS_GetStringBytes(JS_ValueToString(cx, argv[1])))) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, level, "JS_LOG: %s", msg);
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, (char*) file, "console_log", line, level, "%s", msg);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
} else if (argc > 0) {
|
} else if (argc > 0) {
|
||||||
if ((msg = JS_GetStringBytes(JS_ValueToString(cx, argv[0])))) {
|
if ((msg = JS_GetStringBytes(JS_ValueToString(cx, argv[0])))) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, level, "JS_LOG: %s", msg);
|
switch_log_printf(SWITCH_CHANNEL_ID_LOG, (char*) file, "console_log", line, level, "%s", msg);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2323,6 +2447,11 @@ static JSBool js_bridge(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, j
|
|||||||
{
|
{
|
||||||
struct js_session *jss_a = NULL, *jss_b = NULL;
|
struct js_session *jss_a = NULL, *jss_b = NULL;
|
||||||
JSObject *session_obj_a = NULL, *session_obj_b = NULL;
|
JSObject *session_obj_a = NULL, *session_obj_b = NULL;
|
||||||
|
void *bp = NULL;
|
||||||
|
int len = 0;
|
||||||
|
switch_input_callback_function_t dtmf_func = NULL;
|
||||||
|
struct input_callback_state cb_state = {0};
|
||||||
|
JSFunction *function;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
if (JS_ValueToObject(cx, argv[0], &session_obj_a)) {
|
if (JS_ValueToObject(cx, argv[0], &session_obj_a)) {
|
||||||
@ -2344,7 +2473,28 @@ static JSBool js_bridge(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, j
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_ivr_multi_threaded_bridge(jss_a->session, jss_b->session, NULL, NULL, NULL);
|
|
||||||
|
if (argc > 2) {
|
||||||
|
if ((function = JS_ValueToFunction(cx, argv[2]))) {
|
||||||
|
memset(&cb_state, 0, sizeof(cb_state));
|
||||||
|
cb_state.function = function;
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
cb_state.arg = argv[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_state.cx = cx;
|
||||||
|
cb_state.obj = obj;
|
||||||
|
|
||||||
|
cb_state.session_state = jss_a;
|
||||||
|
dtmf_func = js_collect_input_callback;
|
||||||
|
bp = &cb_state;
|
||||||
|
len = sizeof(cb_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_ivr_multi_threaded_bridge(jss_a->session, jss_b->session, dtmf_func, bp, bp);
|
||||||
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2402,7 +2552,10 @@ static JSBool js_email(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js
|
|||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
snprintf(buf, B64BUFFLEN, "\n\n--%s\nContent-Type: application/octet-stream\nContent-Transfer-Encoding: base64\nContent-Description: Sound attachment.\nContent-Disposition: attachment; filename=\"%s\"\n\n", bound, file);
|
snprintf(buf, B64BUFFLEN, "\n\n--%s\nContent-Type: application/octet-stream\n"
|
||||||
|
"Content-Transfer-Encoding: base64\n"
|
||||||
|
"Content-Description: Sound attachment.\n"
|
||||||
|
"Content-Disposition: attachment; filename=\"%s\"\n\n", bound, file);
|
||||||
if (!write_buf(fd, buf))
|
if (!write_buf(fd, buf))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
|
||||||
@ -2488,7 +2641,7 @@ static int eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval)
|
|||||||
{
|
{
|
||||||
JSScript *script;
|
JSScript *script;
|
||||||
char *cptr;
|
char *cptr;
|
||||||
char path[512];
|
char *path = NULL;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
JS_ClearPendingException(cx);
|
JS_ClearPendingException(cx);
|
||||||
@ -2497,11 +2650,11 @@ static int eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval)
|
|||||||
cptr = code + 1;
|
cptr = code + 1;
|
||||||
script = JS_CompileScript(cx, obj, cptr, strlen(cptr), "inline", 1);
|
script = JS_CompileScript(cx, obj, cptr, strlen(cptr), "inline", 1);
|
||||||
} else {
|
} else {
|
||||||
if (code[0] == '/') {
|
if (*code == '/') {
|
||||||
script = JS_CompileFile(cx, obj, code);
|
script = JS_CompileFile(cx, obj, code);
|
||||||
} else {
|
} else if ((path = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR, code))) {
|
||||||
snprintf(path, sizeof(path), "%s%s%s", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR, code);
|
|
||||||
script = JS_CompileFile(cx, obj, path);
|
script = JS_CompileFile(cx, obj, path);
|
||||||
|
switch_safe_free(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +348,11 @@ SWITCH_DECLARE(char *) switch_channel_get_variable(switch_channel_t *channel, ch
|
|||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
|
|
||||||
if (!(v=switch_core_hash_find(channel->variables, varname))) {
|
if (!(v=switch_core_hash_find(channel->variables, varname))) {
|
||||||
v = switch_caller_get_field_by_name(channel->caller_profile, varname);
|
if (!(v = switch_caller_get_field_by_name(channel->caller_profile, varname))) {
|
||||||
|
if (!strcmp(varname, "base_dir")) {
|
||||||
|
return SWITCH_GLOBAL_dirs.base_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
@ -987,6 +991,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan
|
|||||||
switch_event_fire(&event);
|
switch_event_fire(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch_channel_set_variable(channel, "hangup_cause", switch_channel_cause2str(channel->hangup_cause));
|
||||||
switch_channel_presence(channel, "unavailable", switch_channel_cause2str(channel->hangup_cause));
|
switch_channel_presence(channel, "unavailable", switch_channel_cause2str(channel->hangup_cause));
|
||||||
|
|
||||||
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
|
switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL);
|
||||||
@ -1190,7 +1195,7 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
|||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nlen = sub_val ? strlen(sub_val) : 0;
|
nlen = strlen(sub_val);
|
||||||
if (len + nlen >= olen) {
|
if (len + nlen >= olen) {
|
||||||
olen += block;
|
olen += block;
|
||||||
cpos = c - data;
|
cpos = c - data;
|
||||||
@ -1205,11 +1210,10 @@ SWITCH_DECLARE(char *) switch_channel_expand_variables(switch_channel_t *channel
|
|||||||
vname = data + vvalpos;
|
vname = data + vvalpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlen) {
|
|
||||||
len += nlen;
|
len += nlen;
|
||||||
strcat(c, sub_val);
|
strcat(c, sub_val);
|
||||||
c += nlen;
|
c += nlen;
|
||||||
}
|
|
||||||
if (func_val) {
|
if (func_val) {
|
||||||
free(func_val);
|
free(func_val);
|
||||||
func_val = NULL;
|
func_val = NULL;
|
||||||
|
@ -64,6 +64,7 @@ struct switch_media_bug {
|
|||||||
switch_mutex_t *write_mutex;
|
switch_mutex_t *write_mutex;
|
||||||
switch_core_session_t *session;
|
switch_core_session_t *session;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
uint32_t flags;
|
||||||
struct switch_media_bug *next;
|
struct switch_media_bug *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -168,6 +169,11 @@ static void switch_core_media_bug_destroy(switch_media_bug_t *bug)
|
|||||||
switch_buffer_destroy(&bug->raw_write_buffer);
|
switch_buffer_destroy(&bug->raw_write_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *bug)
|
||||||
|
{
|
||||||
|
return bug->user_data;
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame)
|
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *bug, switch_frame_t *frame)
|
||||||
{
|
{
|
||||||
uint32_t bytes = 0;
|
uint32_t bytes = 0;
|
||||||
@ -175,21 +181,35 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
|
|||||||
uint32_t datalen = 0;
|
uint32_t datalen = 0;
|
||||||
int16_t *dp, *fp;
|
int16_t *dp, *fp;
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
size_t rlen = switch_buffer_inuse(bug->raw_read_buffer);
|
size_t rlen = 0;
|
||||||
size_t wlen = switch_buffer_inuse(bug->raw_write_buffer);
|
size_t wlen = 0;
|
||||||
uint32_t blen;
|
uint32_t blen;
|
||||||
size_t rdlen = 0;
|
size_t rdlen = 0;
|
||||||
uint32_t maxlen;
|
uint32_t maxlen;
|
||||||
|
|
||||||
if (!rlen && !wlen) {
|
|
||||||
|
if (bug->raw_read_buffer) {
|
||||||
|
rlen = switch_buffer_inuse(bug->raw_read_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bug->raw_write_buffer) {
|
||||||
|
wlen = switch_buffer_inuse(bug->raw_write_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((bug->raw_read_buffer && bug->raw_write_buffer) && (!rlen && !wlen)) {
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
maxlen = sizeof(data) > frame->buflen ? frame->buflen : sizeof(data);
|
maxlen = sizeof(data) > frame->buflen ? frame->buflen : sizeof(data);
|
||||||
if ((rdlen = rlen > wlen ? wlen : rlen) > maxlen) {
|
if ((rdlen = rlen > wlen ? wlen : rlen) > maxlen) {
|
||||||
rdlen = maxlen;
|
rdlen = maxlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rdlen) {
|
||||||
|
rdlen = maxlen;
|
||||||
|
}
|
||||||
|
|
||||||
frame->datalen = 0;
|
frame->datalen = 0;
|
||||||
|
|
||||||
if (rlen) {
|
if (rlen) {
|
||||||
@ -209,6 +229,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
|
|||||||
switch_mutex_unlock(bug->write_mutex);
|
switch_mutex_unlock(bug->write_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bytes = (datalen > frame->datalen) ? datalen : frame->datalen;
|
bytes = (datalen > frame->datalen) ? datalen : frame->datalen;
|
||||||
|
|
||||||
if (bytes) {
|
if (bytes) {
|
||||||
@ -233,6 +254,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame->datalen = bytes;
|
frame->datalen = bytes;
|
||||||
|
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,6 +266,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b
|
|||||||
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
|
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t *session,
|
||||||
switch_media_bug_callback_t callback,
|
switch_media_bug_callback_t callback,
|
||||||
void *user_data,
|
void *user_data,
|
||||||
|
switch_media_bug_flag_t flags,
|
||||||
switch_media_bug_t **new_bug)
|
switch_media_bug_t **new_bug)
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -256,13 +280,25 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t
|
|||||||
bug->callback = callback;
|
bug->callback = callback;
|
||||||
bug->user_data = user_data;
|
bug->user_data = user_data;
|
||||||
bug->session = session;
|
bug->session = session;
|
||||||
|
bug->flags = flags;
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attaching BUG to %s\n", switch_channel_get_name(session->channel));
|
||||||
bytes = session->read_codec->implementation->bytes_per_frame;
|
bytes = session->read_codec->implementation->bytes_per_frame;
|
||||||
|
|
||||||
|
if (!bug->flags) {
|
||||||
|
bug->flags = (SMBF_READ_STREAM | SMBF_WRITE_STREAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_test_flag(bug, SMBF_READ_STREAM)) {
|
||||||
switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
|
switch_buffer_create_dynamic(&bug->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
|
||||||
bytes = session->write_codec->implementation->bytes_per_frame;
|
|
||||||
switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
|
|
||||||
switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
switch_mutex_init(&bug->read_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = session->write_codec->implementation->bytes_per_frame;
|
||||||
|
|
||||||
|
if (switch_test_flag(bug, SMBF_WRITE_STREAM)) {
|
||||||
|
switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
|
||||||
switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
|
||||||
|
}
|
||||||
|
|
||||||
switch_thread_rwlock_wrlock(session->bug_rwlock);
|
switch_thread_rwlock_wrlock(session->bug_rwlock);
|
||||||
bug->next = session->bugs;
|
bug->next = session->bugs;
|
||||||
@ -292,6 +328,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(switch_core_ses
|
|||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing BUG from %s\n", switch_channel_get_name(session->channel));
|
||||||
}
|
}
|
||||||
switch_thread_rwlock_unlock(session->bug_rwlock);
|
switch_thread_rwlock_unlock(session->bug_rwlock);
|
||||||
|
session->bugs = NULL;
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,18 +983,108 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *
|
|||||||
return sh->speech_interface->speech_open(sh, voice_name, rate, flags);
|
return sh->speech_interface->speech_open(sh, voice_name, rate, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_asr(switch_speech_handle_t *sh, void *data, unsigned int *len, int rate, switch_speech_flag_t *flags)
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah,
|
||||||
|
char *module_name,
|
||||||
|
char *codec,
|
||||||
|
int rate,
|
||||||
|
char *dest,
|
||||||
|
switch_asr_flag_t *flags,
|
||||||
|
switch_memory_pool_t *pool)
|
||||||
{
|
{
|
||||||
assert(sh != NULL);
|
switch_status_t status;
|
||||||
|
|
||||||
return sh->speech_interface->speech_feed_asr(sh, data, len, rate, flags);
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
if ((ah->asr_interface = switch_loadable_module_get_asr_interface(module_name)) == 0) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid asr module [%s]!\n", module_name);
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ah->flags = *flags;
|
||||||
|
|
||||||
|
if (pool) {
|
||||||
|
ah->memory_pool = pool;
|
||||||
|
} else {
|
||||||
|
if ((status = switch_core_new_memory_pool(&ah->memory_pool)) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
switch_set_flag(ah, SWITCH_ASR_FLAG_FREE_POOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ah->rate = rate;
|
||||||
|
ah->name = switch_core_strdup(ah->memory_pool, module_name);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_open(ah, codec, rate, dest, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_speech_interpret_asr(switch_speech_handle_t *sh, char *buf, unsigned int buflen, switch_speech_flag_t *flags)
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_load_grammar(switch_asr_handle_t *ah, char *grammar, char *path)
|
||||||
{
|
{
|
||||||
assert(sh != NULL);
|
char *epath = NULL;
|
||||||
|
switch_status_t status;
|
||||||
|
|
||||||
return sh->speech_interface->speech_interpret_asr(sh, buf, buflen, flags);
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
if (*path != '/') {
|
||||||
|
epath = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_PATH_SEPARATOR, path);
|
||||||
|
path = epath;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = ah->asr_interface->asr_load_grammar(ah, grammar, path);
|
||||||
|
switch_safe_free(epath);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_unload_grammar(switch_asr_handle_t *ah, char *grammar)
|
||||||
|
{
|
||||||
|
switch_status_t status;
|
||||||
|
|
||||||
|
assert(ah != NULL);
|
||||||
|
status = ah->asr_interface->asr_unload_grammar(ah, grammar);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_pause(switch_asr_handle_t *ah)
|
||||||
|
{
|
||||||
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_pause(ah);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_resume(switch_asr_handle_t *ah)
|
||||||
|
{
|
||||||
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_resume(ah);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
|
||||||
|
{
|
||||||
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_close(ah, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags)
|
||||||
|
{
|
||||||
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_feed(ah, data, len, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
|
||||||
|
{
|
||||||
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_check_results(ah, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags)
|
||||||
|
{
|
||||||
|
assert(ah != NULL);
|
||||||
|
|
||||||
|
return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags)
|
SWITCH_DECLARE(switch_status_t) switch_core_speech_feed_tts(switch_speech_handle_t *sh, char *text, switch_speech_flag_t *flags)
|
||||||
@ -1765,6 +1892,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
|||||||
switch_media_bug_t *bp;
|
switch_media_bug_t *bp;
|
||||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||||
for (bp = session->bugs; bp; bp = bp->next) {
|
for (bp = session->bugs; bp; bp = bp->next) {
|
||||||
|
if (switch_test_flag(bp, SMBF_READ_STREAM)) {
|
||||||
switch_mutex_lock(bp->read_mutex);
|
switch_mutex_lock(bp->read_mutex);
|
||||||
switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
|
switch_buffer_write(bp->raw_read_buffer, read_frame->data, read_frame->datalen);
|
||||||
if (bp->callback) {
|
if (bp->callback) {
|
||||||
@ -1772,6 +1900,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
|||||||
}
|
}
|
||||||
switch_mutex_unlock(bp->read_mutex);
|
switch_mutex_unlock(bp->read_mutex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
switch_thread_rwlock_unlock(session->bug_rwlock);
|
switch_thread_rwlock_unlock(session->bug_rwlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1999,6 +2128,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
|||||||
switch_media_bug_t *bp;
|
switch_media_bug_t *bp;
|
||||||
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
switch_thread_rwlock_rdlock(session->bug_rwlock);
|
||||||
for (bp = session->bugs; bp; bp = bp->next) {
|
for (bp = session->bugs; bp; bp = bp->next) {
|
||||||
|
if (switch_test_flag(bp, SMBF_WRITE_STREAM)) {
|
||||||
switch_mutex_lock(bp->write_mutex);
|
switch_mutex_lock(bp->write_mutex);
|
||||||
switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
|
switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
|
||||||
switch_mutex_unlock(bp->write_mutex);
|
switch_mutex_unlock(bp->write_mutex);
|
||||||
@ -2006,6 +2136,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
|||||||
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
|
bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
switch_thread_rwlock_unlock(session->bug_rwlock);
|
switch_thread_rwlock_unlock(session->bug_rwlock);
|
||||||
}
|
}
|
||||||
if (do_bugs) {
|
if (do_bugs) {
|
||||||
@ -3193,7 +3324,7 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
|
|||||||
switch_mutex_unlock(runtime.session_table_mutex);
|
switch_mutex_unlock(runtime.session_table_mutex);
|
||||||
|
|
||||||
switch_core_session_run(session);
|
switch_core_session_run(session);
|
||||||
|
switch_core_media_bug_remove_all(session);
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %u (%s) Locked, Waiting on external entities\n", session->id, switch_channel_get_name(session->channel));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %u (%s) Locked, Waiting on external entities\n", session->id, switch_channel_get_name(session->channel));
|
||||||
switch_core_session_write_lock(session);
|
switch_core_session_write_lock(session);
|
||||||
switch_core_session_rwunlock(session);
|
switch_core_session_rwunlock(session);
|
||||||
@ -3609,6 +3740,9 @@ SWITCH_DECLARE(void) switch_core_set_globals(void)
|
|||||||
if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
|
if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
|
||||||
snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%shtdocs", exePath);
|
snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%shtdocs", exePath);
|
||||||
}
|
}
|
||||||
|
if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) {
|
||||||
|
snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%sgrammar", exePath);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
SWITCH_GLOBAL_dirs.base_dir = SWITCH_PREFIX_DIR;
|
SWITCH_GLOBAL_dirs.base_dir = SWITCH_PREFIX_DIR;
|
||||||
SWITCH_GLOBAL_dirs.mod_dir = SWITCH_MOD_DIR;
|
SWITCH_GLOBAL_dirs.mod_dir = SWITCH_MOD_DIR;
|
||||||
@ -3617,6 +3751,7 @@ SWITCH_DECLARE(void) switch_core_set_globals(void)
|
|||||||
SWITCH_GLOBAL_dirs.db_dir = SWITCH_DB_DIR;
|
SWITCH_GLOBAL_dirs.db_dir = SWITCH_DB_DIR;
|
||||||
SWITCH_GLOBAL_dirs.script_dir = SWITCH_SCRIPT_DIR;
|
SWITCH_GLOBAL_dirs.script_dir = SWITCH_SCRIPT_DIR;
|
||||||
SWITCH_GLOBAL_dirs.htdocs_dir = SWITCH_HTDOCS_DIR;
|
SWITCH_GLOBAL_dirs.htdocs_dir = SWITCH_HTDOCS_DIR;
|
||||||
|
SWITCH_GLOBAL_dirs.grammar_dir = SWITCH_GRAMMAR_DIR;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SWITCH_TEMP_DIR
|
#ifdef SWITCH_TEMP_DIR
|
||||||
SWITCH_GLOBAL_dirs.temp_dir = SWITCH_TEMP_DIR;
|
SWITCH_GLOBAL_dirs.temp_dir = SWITCH_TEMP_DIR;
|
||||||
@ -3987,6 +4122,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
|
|||||||
free(SWITCH_GLOBAL_dirs.db_dir);
|
free(SWITCH_GLOBAL_dirs.db_dir);
|
||||||
free(SWITCH_GLOBAL_dirs.script_dir);
|
free(SWITCH_GLOBAL_dirs.script_dir);
|
||||||
free(SWITCH_GLOBAL_dirs.htdocs_dir);
|
free(SWITCH_GLOBAL_dirs.htdocs_dir);
|
||||||
|
free(SWITCH_GLOBAL_dirs.grammar_dir);
|
||||||
free(SWITCH_GLOBAL_dirs.temp_dir);
|
free(SWITCH_GLOBAL_dirs.temp_dir);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -128,6 +128,7 @@ static char *EVENT_NAMES[] = {
|
|||||||
"ROSTER",
|
"ROSTER",
|
||||||
"CODEC",
|
"CODEC",
|
||||||
"BACKGROUND_JOB",
|
"BACKGROUND_JOB",
|
||||||
|
"DETECTED_SPEECH",
|
||||||
"ALL"
|
"ALL"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -539,6 +540,7 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
|
|||||||
switch_event_t *ep = *event;
|
switch_event_t *ep = *event;
|
||||||
switch_event_header_t *hp, *this;
|
switch_event_header_t *hp, *this;
|
||||||
|
|
||||||
|
if (ep) {
|
||||||
for (hp = ep->headers; hp;) {
|
for (hp = ep->headers; hp;) {
|
||||||
this = hp;
|
this = hp;
|
||||||
hp = hp->next;
|
hp = hp->next;
|
||||||
@ -548,6 +550,7 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event)
|
|||||||
}
|
}
|
||||||
FREE(ep->body);
|
FREE(ep->body);
|
||||||
FREE(ep);
|
FREE(ep);
|
||||||
|
}
|
||||||
*event = NULL;
|
*event = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
316
src/switch_ivr.c
316
src/switch_ivr.c
@ -176,10 +176,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_park(switch_core_session_t *session)
|
|||||||
SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
|
SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
|
||||||
switch_input_callback_function_t input_callback,
|
switch_input_callback_function_t input_callback,
|
||||||
void *buf,
|
void *buf,
|
||||||
unsigned int buflen)
|
unsigned int buflen,
|
||||||
|
unsigned int timeout)
|
||||||
{
|
{
|
||||||
switch_channel_t *channel;
|
switch_channel_t *channel;
|
||||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
switch_time_t started = 0;
|
||||||
|
unsigned int elapsed;
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session);
|
channel = switch_core_session_get_channel(session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
@ -188,12 +191,21 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_s
|
|||||||
return SWITCH_STATUS_GENERR;
|
return SWITCH_STATUS_GENERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
started = switch_time_now();
|
||||||
|
}
|
||||||
|
|
||||||
while(switch_channel_ready(channel)) {
|
while(switch_channel_ready(channel)) {
|
||||||
switch_frame_t *read_frame;
|
switch_frame_t *read_frame;
|
||||||
switch_event_t *event;
|
switch_event_t *event;
|
||||||
|
|
||||||
char dtmf[128];
|
char dtmf[128];
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
elapsed = (unsigned int)((switch_time_now() - started) / 1000);
|
||||||
|
if (elapsed >= timeout) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
|
if (switch_core_session_dequeue_private_event(session, &event) == SWITCH_STATUS_SUCCESS) {
|
||||||
switch_ivr_parse_event(session, event);
|
switch_ivr_parse_event(session, event);
|
||||||
@ -585,6 +597,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
|
|||||||
if ((status = switch_core_media_bug_add(session,
|
if ((status = switch_core_media_bug_add(session,
|
||||||
record_callback,
|
record_callback,
|
||||||
fh,
|
fh,
|
||||||
|
SMBF_BOTH,
|
||||||
&bug)) != SWITCH_STATUS_SUCCESS) {
|
&bug)) != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_core_file_close(fh);
|
switch_core_file_close(fh);
|
||||||
return status;
|
return status;
|
||||||
@ -595,6 +608,299 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_session(switch_core_session_t
|
|||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct speech_thread_handle {
|
||||||
|
switch_core_session_t *session;
|
||||||
|
switch_asr_handle_t *ah;
|
||||||
|
switch_media_bug_t *bug;
|
||||||
|
switch_mutex_t *mutex;
|
||||||
|
switch_thread_cond_t *cond;
|
||||||
|
switch_memory_pool_t *pool;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj)
|
||||||
|
{
|
||||||
|
struct speech_thread_handle *sth = (struct speech_thread_handle *) obj;
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(sth->session);
|
||||||
|
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
|
||||||
|
switch_status_t status;
|
||||||
|
|
||||||
|
switch_thread_cond_create(&sth->cond, sth->pool);
|
||||||
|
switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool);
|
||||||
|
|
||||||
|
|
||||||
|
switch_core_session_read_lock(sth->session);
|
||||||
|
switch_mutex_lock(sth->mutex);
|
||||||
|
|
||||||
|
while (switch_channel_ready(channel) && !switch_test_flag(sth->ah, SWITCH_ASR_FLAG_CLOSED)) {
|
||||||
|
char *xmlstr = NULL;
|
||||||
|
|
||||||
|
switch_thread_cond_wait(sth->cond, sth->mutex);
|
||||||
|
if (switch_core_asr_check_results(sth->ah, &flags) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_t *event;
|
||||||
|
|
||||||
|
status = switch_core_asr_get_results(sth->ah, &xmlstr, &flags);
|
||||||
|
|
||||||
|
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (switch_event_create(&event, SWITCH_EVENT_DETECTED_SPEECH) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
if (status == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speech-Type", "detected-speech");
|
||||||
|
switch_event_add_body(event, xmlstr);
|
||||||
|
} else {
|
||||||
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speech-Type", "begin-speaking");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_test_flag(sth->ah, SWITCH_ASR_FLAG_FIRE_EVENTS)) {
|
||||||
|
switch_event_t *dup;
|
||||||
|
|
||||||
|
if (switch_event_dup(&dup, event) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_fire(&dup);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_core_session_queue_event(sth->session, &event) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event queue failed!\n");
|
||||||
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
|
||||||
|
switch_event_fire(&event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_safe_free(xmlstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
|
||||||
|
switch_mutex_unlock(sth->mutex);
|
||||||
|
switch_core_session_rwunlock(sth->session);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void speech_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
|
||||||
|
{
|
||||||
|
struct speech_thread_handle *sth = (struct speech_thread_handle *) user_data;
|
||||||
|
uint8_t data[SWITCH_RECCOMMENDED_BUFFER_SIZE];
|
||||||
|
switch_frame_t frame = {0};
|
||||||
|
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
|
||||||
|
|
||||||
|
frame.data = data;
|
||||||
|
frame.buflen = SWITCH_RECCOMMENDED_BUFFER_SIZE;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case SWITCH_ABC_TYPE_INIT: {
|
||||||
|
switch_thread_t *thread;
|
||||||
|
switch_threadattr_t *thd_attr = NULL;
|
||||||
|
|
||||||
|
switch_threadattr_create(&thd_attr, sth->pool);
|
||||||
|
switch_threadattr_detach_set(thd_attr, 1);
|
||||||
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||||
|
switch_thread_create(&thread, thd_attr, speech_thread, sth, sth->pool);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWITCH_ABC_TYPE_CLOSE:
|
||||||
|
switch_core_asr_close(sth->ah, &flags);
|
||||||
|
switch_mutex_lock(sth->mutex);
|
||||||
|
switch_thread_cond_signal(sth->cond);
|
||||||
|
switch_mutex_unlock(sth->mutex);
|
||||||
|
case SWITCH_ABC_TYPE_READ:
|
||||||
|
if (sth->ah) {
|
||||||
|
if (switch_core_media_bug_read(bug, &frame) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
if (switch_core_asr_feed(sth->ah, frame.data, frame.datalen, &flags) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error Feeding Data\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (switch_core_asr_check_results(sth->ah, &flags) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_mutex_lock(sth->mutex);
|
||||||
|
switch_thread_cond_signal(sth->cond);
|
||||||
|
switch_mutex_unlock(sth->mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SWITCH_ABC_TYPE_WRITE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_stop_detect_speech(switch_core_session_t *session)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
struct speech_thread_handle *sth;
|
||||||
|
|
||||||
|
assert(channel != NULL);
|
||||||
|
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
|
||||||
|
switch_channel_set_private(channel, SWITCH_SPEECH_KEY, NULL);
|
||||||
|
switch_core_media_bug_remove(session, &sth->bug);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_pause_detect_speech(switch_core_session_t *session)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
struct speech_thread_handle *sth;
|
||||||
|
|
||||||
|
assert(channel != NULL);
|
||||||
|
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
|
||||||
|
switch_core_asr_pause(sth->ah);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_resume_detect_speech(switch_core_session_t *session)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
struct speech_thread_handle *sth;
|
||||||
|
|
||||||
|
assert(channel != NULL);
|
||||||
|
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
|
||||||
|
switch_core_asr_resume(sth->ah);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_load_grammar(switch_core_session_t *session, char *grammar, char *path)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
|
||||||
|
struct speech_thread_handle *sth;
|
||||||
|
|
||||||
|
assert(channel != NULL);
|
||||||
|
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
|
||||||
|
if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
|
||||||
|
switch_core_asr_close(sth->ah, &flags);
|
||||||
|
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech_unload_grammar(switch_core_session_t *session, char *grammar)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||||
|
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
|
||||||
|
struct speech_thread_handle *sth;
|
||||||
|
|
||||||
|
assert(channel != NULL);
|
||||||
|
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
|
||||||
|
if (switch_core_asr_unload_grammar(sth->ah, grammar) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error unloading Grammar\n");
|
||||||
|
switch_core_asr_close(sth->ah, &flags);
|
||||||
|
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *session,
|
||||||
|
char *mod_name,
|
||||||
|
char *grammar,
|
||||||
|
char *path,
|
||||||
|
char *dest,
|
||||||
|
switch_asr_handle_t *ah)
|
||||||
|
{
|
||||||
|
switch_channel_t *channel;
|
||||||
|
switch_codec_t *read_codec;
|
||||||
|
switch_status_t status;
|
||||||
|
switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
|
||||||
|
struct speech_thread_handle *sth;
|
||||||
|
char *val;
|
||||||
|
|
||||||
|
if (!ah) {
|
||||||
|
if (!(ah = switch_core_session_alloc(session, sizeof(*ah)))) {
|
||||||
|
return SWITCH_STATUS_MEMERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channel = switch_core_session_get_channel(session);
|
||||||
|
assert(channel != NULL);
|
||||||
|
|
||||||
|
read_codec = switch_core_session_get_read_codec(session);
|
||||||
|
assert(read_codec != NULL);
|
||||||
|
|
||||||
|
|
||||||
|
if ((val = switch_channel_get_variable(channel, "fire_asr_events"))) {
|
||||||
|
switch_set_flag(ah, SWITCH_ASR_FLAG_FIRE_EVENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY))) {
|
||||||
|
if (switch_core_asr_load_grammar(sth->ah, grammar, path) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
|
||||||
|
switch_core_asr_close(sth->ah, &flags);
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switch_core_asr_open(ah,
|
||||||
|
mod_name,
|
||||||
|
"L16",
|
||||||
|
read_codec->implementation->samples_per_second,
|
||||||
|
dest,
|
||||||
|
&flags,
|
||||||
|
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
|
||||||
|
if (switch_core_asr_load_grammar(ah, grammar, path) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading Grammar\n");
|
||||||
|
switch_core_asr_close(ah, &flags);
|
||||||
|
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||||
|
return SWITCH_STATUS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sth = switch_core_session_alloc(session, sizeof(*sth));
|
||||||
|
sth->pool = switch_core_session_get_pool(session);
|
||||||
|
sth->session = session;
|
||||||
|
sth->ah = ah;
|
||||||
|
|
||||||
|
if ((status = switch_core_media_bug_add(session,
|
||||||
|
speech_callback,
|
||||||
|
sth,
|
||||||
|
SMBF_READ_STREAM,
|
||||||
|
&sth->bug)) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_core_asr_close(ah, &flags);
|
||||||
|
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_channel_set_private(channel, SWITCH_SPEECH_KEY, sth);
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#define FILE_STARTSAMPLES 1024 * 32
|
#define FILE_STARTSAMPLES 1024 * 32
|
||||||
#define FILE_BLOCKSIZE 1024 * 8
|
#define FILE_BLOCKSIZE 1024 * 8
|
||||||
#define FILE_BUFSIZE 1024 * 64
|
#define FILE_BUFSIZE 1024 * 64
|
||||||
@ -1130,7 +1436,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
int lead_in_out = 10;
|
int lead_in_out = 10;
|
||||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
uint32_t rate = 0, samples = 0;
|
uint32_t rate = 0, samples = 0;
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session);
|
channel = switch_core_session_get_channel(session);
|
||||||
@ -1323,7 +1629,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
|
|||||||
int stream_id;
|
int stream_id;
|
||||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
switch_speech_handle_t sh;
|
switch_speech_handle_t sh;
|
||||||
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_TTS;
|
switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
|
||||||
|
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session);
|
channel = switch_core_session_get_channel(session);
|
||||||
@ -1502,7 +1808,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
|
|||||||
status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0);
|
status = input_callback(session_a, event, SWITCH_INPUT_TYPE_EVENT, user_data, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
|
if (event->event_id != SWITCH_EVENT_MESSAGE || switch_core_session_receive_event(session_b, &event) != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_event_destroy(&event);
|
switch_event_destroy(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ struct switch_loadable_module_container {
|
|||||||
switch_hash_t *api_hash;
|
switch_hash_t *api_hash;
|
||||||
switch_hash_t *file_hash;
|
switch_hash_t *file_hash;
|
||||||
switch_hash_t *speech_hash;
|
switch_hash_t *speech_hash;
|
||||||
|
switch_hash_t *asr_hash;
|
||||||
switch_hash_t *directory_hash;
|
switch_hash_t *directory_hash;
|
||||||
switch_hash_t *chat_hash;
|
switch_hash_t *chat_hash;
|
||||||
switch_memory_pool_t *pool;
|
switch_memory_pool_t *pool;
|
||||||
@ -218,6 +219,20 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_module->module_interface->asr_interface) {
|
||||||
|
const switch_asr_interface_t *ptr;
|
||||||
|
|
||||||
|
for (ptr = new_module->module_interface->asr_interface; ptr; ptr = ptr->next) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Asr interface '%s'\n", ptr->interface_name);
|
||||||
|
if (switch_event_create(&event, SWITCH_EVENT_MODULE_LOAD) == SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "type", "asr");
|
||||||
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "name", "%s", ptr->interface_name);
|
||||||
|
switch_event_fire(&event);
|
||||||
|
}
|
||||||
|
switch_core_hash_insert(loadable_modules.asr_hash, (char *) ptr->interface_name, (void *) ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (new_module->module_interface->directory_interface) {
|
if (new_module->module_interface->directory_interface) {
|
||||||
const switch_directory_interface_t *ptr;
|
const switch_directory_interface_t *ptr;
|
||||||
|
|
||||||
@ -490,6 +505,7 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_init()
|
|||||||
switch_core_hash_init(&loadable_modules.api_hash, loadable_modules.pool);
|
switch_core_hash_init(&loadable_modules.api_hash, loadable_modules.pool);
|
||||||
switch_core_hash_init(&loadable_modules.file_hash, loadable_modules.pool);
|
switch_core_hash_init(&loadable_modules.file_hash, loadable_modules.pool);
|
||||||
switch_core_hash_init(&loadable_modules.speech_hash, loadable_modules.pool);
|
switch_core_hash_init(&loadable_modules.speech_hash, loadable_modules.pool);
|
||||||
|
switch_core_hash_init(&loadable_modules.asr_hash, loadable_modules.pool);
|
||||||
switch_core_hash_init(&loadable_modules.directory_hash, loadable_modules.pool);
|
switch_core_hash_init(&loadable_modules.directory_hash, loadable_modules.pool);
|
||||||
switch_core_hash_init(&loadable_modules.chat_hash, loadable_modules.pool);
|
switch_core_hash_init(&loadable_modules.chat_hash, loadable_modules.pool);
|
||||||
switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
|
switch_core_hash_init(&loadable_modules.dialplan_hash, loadable_modules.pool);
|
||||||
@ -582,12 +598,18 @@ SWITCH_DECLARE(void) switch_loadable_module_shutdown(void)
|
|||||||
for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
|
for (hi = switch_hash_first(loadable_modules.pool, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
|
||||||
switch_hash_this(hi, NULL, NULL, &val);
|
switch_hash_this(hi, NULL, NULL, &val);
|
||||||
module = (switch_loadable_module_t *) val;
|
module = (switch_loadable_module_t *) val;
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Checking %s\t", module->module_interface->module_name);
|
|
||||||
if (module->switch_module_shutdown) {
|
if (module->switch_module_shutdown) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "(yes)\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping: %s\n", module->module_interface->module_name);
|
||||||
module->switch_module_shutdown();
|
if (module->switch_module_shutdown() == SWITCH_STATUS_UNLOAD) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s unloaded.\n", module->module_interface->module_name);
|
||||||
|
apr_dso_unload(module->lib);
|
||||||
|
module->lib = NULL;
|
||||||
} else {
|
} else {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "(no)\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s shutdown.\n", module->module_interface->module_name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s has no shutdown routine\n", module->module_interface->module_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,6 +670,11 @@ SWITCH_DECLARE(switch_speech_interface_t *) switch_loadable_module_get_speech_in
|
|||||||
return switch_core_hash_find(loadable_modules.speech_hash, name);
|
return switch_core_hash_find(loadable_modules.speech_hash, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_asr_interface_t *) switch_loadable_module_get_asr_interface(char *name)
|
||||||
|
{
|
||||||
|
return switch_core_hash_find(loadable_modules.asr_hash, name);
|
||||||
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_directory_interface(char *name)
|
SWITCH_DECLARE(switch_directory_interface_t *) switch_loadable_module_get_directory_interface(char *name)
|
||||||
{
|
{
|
||||||
return switch_core_hash_find(loadable_modules.directory_hash, name);
|
return switch_core_hash_find(loadable_modules.directory_hash, name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user