FS-5583 --resolve

This commit is contained in:
Anthony Minessale 2013-07-19 14:02:58 -05:00
parent fb887acb44
commit 453cfaaf7f
5 changed files with 225 additions and 3 deletions

View File

@ -1936,6 +1936,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
/*!
\brief Get result headers from an asr handle
\param ah the handle to get results from
\param headers a pointer to dynamically allocate an switch_event_t result to
\param flags flags to influence behaviour
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
/*!
\brief Load a grammar to an asr handle
\param ah the handle to load to

View File

@ -377,6 +377,8 @@ struct switch_asr_interface {
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);
/*! function to read result headers from the ASR */
switch_status_t (*asr_get_result_headers) (switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
/*! function to start ASR input timers */
switch_status_t (*asr_start_input_timers) (switch_asr_handle_t *ah);
void (*asr_text_param) (switch_asr_handle_t *ah, char *param, const char *val);

View File

@ -450,6 +450,8 @@ struct recognizer_data {
switch_hash_t *enabled_grammars;
/** recognize result */
char *result;
/** recognize result headers */
switch_event_t *result_headers;
/** true, if voice has started */
int start_of_input;
/** true, if input timers have started */
@ -483,6 +485,7 @@ static switch_status_t recog_asr_resume(switch_asr_handle_t *ah);
static switch_status_t recog_asr_pause(switch_asr_handle_t *ah);
static switch_status_t recog_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
static switch_status_t recog_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
static switch_status_t recog_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
static switch_status_t recog_asr_start_input_timers(switch_asr_handle_t *ah);
static void recog_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val);
static void recog_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val);
@ -505,7 +508,9 @@ static switch_status_t recog_channel_check_results(speech_channel_t *schannel);
static switch_status_t recog_channel_set_start_of_input(speech_channel_t *schannel);
static switch_status_t recog_channel_start_input_timers(speech_channel_t *schannel);
static switch_status_t recog_channel_set_results(speech_channel_t *schannel, const char *results);
static switch_status_t recog_channel_set_result_headers(speech_channel_t *schannel, mrcp_recog_header_t *recog_hdr);
static switch_status_t recog_channel_get_results(speech_channel_t *schannel, char **results);
static switch_status_t recog_channel_get_result_headers(speech_channel_t *schannel, switch_event_t **result_headers);
static switch_status_t recog_channel_set_params(speech_channel_t *schannel, mrcp_message_t *msg, mrcp_generic_header_t *gen_hdr,
mrcp_recog_header_t *recog_hdr);
static switch_status_t recog_channel_set_header(speech_channel_t *schannel, int id, char *val, mrcp_message_t *msg, mrcp_recog_header_t *recog_hdr);
@ -2156,9 +2161,9 @@ static switch_status_t recog_channel_start(speech_channel_t *schannel)
recognizer_data_t *r;
char *start_input_timers;
const char *mime_type;
char *key;
char *key = NULL;
switch_size_t len;
grammar_t *grammar;
grammar_t *grammar = NULL;
switch_size_t grammar_uri_count = 0;
switch_size_t grammar_uri_list_len = 0;
char *grammar_uri_list = NULL;
@ -2176,6 +2181,9 @@ static switch_status_t recog_channel_start(speech_channel_t *schannel)
}
r = (recognizer_data_t *) schannel->data;
r->result = NULL;
if (r->result_headers) {
switch_event_destroy(&r->result_headers);
}
r->start_of_input = 0;
/* input timers are started by default unless the start-input-timers=false param is set */
@ -2598,6 +2606,141 @@ static switch_status_t recog_channel_set_results(speech_channel_t *schannel, con
return status;
}
/**
* Find a parameter from a ;-separated string
*
* @param str the input string to find data in
* @param param the parameter to to look for
* @return a pointer in the str if successful, or NULL.
*/
static char *find_parameter(const char *str, const char *param)
{
char *ptr = (char *) str;
while (ptr) {
if (!strncasecmp(ptr, param, strlen(param)))
return ptr;
if ((ptr = strchr(ptr, ';')))
ptr++;
while (ptr && *ptr == ' ') {
ptr++;
}
}
return NULL;
}
/**
* Get a parameter value from a ;-separated string
*
* @param str the input string to parse data from
* @param param the parameter to to look for
* @return a malloc'ed char* if successful, or NULL.
*/
static char *get_parameter_value(const char *str, const char *param)
{
const char *param_ptr;
char *param_value = NULL;
char *tmp;
switch_size_t param_len;
char *param_tmp;
if (zstr(str) || zstr(param)) return NULL;
/* Append "=" to the end of the string */
param_tmp = switch_mprintf("%s=", param);
if (!param_tmp) return NULL;
param = param_tmp;
param_len = strlen(param);
param_ptr = find_parameter(str, param);
if (zstr(param_ptr)) goto fail;
param_value = strdup(param_ptr + param_len);
if (zstr(param_value)) goto fail;
if ((tmp = strchr(param_value, ';'))) *tmp = '\0';
switch_safe_free(param_tmp);
return param_value;
fail:
switch_safe_free(param_tmp);
switch_safe_free(param_value);
return NULL;
}
/**
* Set the recognition result headers
*
* @param schannel the channel whose results are set
* @param recog_hdr the recognition headers
* @return SWITCH_STATUS_SUCCESS if successful
*/
static switch_status_t recog_channel_set_result_headers(speech_channel_t *schannel, mrcp_recog_header_t *recog_hdr)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
recognizer_data_t *r;
switch_mutex_lock(schannel->mutex);
r = (recognizer_data_t *) schannel->data;
if (r->result_headers) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) result headers are already set\n", schannel->name);
status = SWITCH_STATUS_FALSE;
goto done;
}
if (!recog_hdr) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) result headers are NULL\n", schannel->name);
status = SWITCH_STATUS_FALSE;
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) ASR adding result headers\n", schannel->name);
if ((status = switch_event_create(&r->result_headers, SWITCH_EVENT_CLONE)) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Completion-Cause", "%d", recog_hdr->completion_cause);
if (!zstr(recog_hdr->completion_reason.buf)) {
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Completion-Reason", recog_hdr->completion_reason.buf);
}
if (!zstr(recog_hdr->waveform_uri.buf)) {
char *tmp;
if ((tmp = strdup(recog_hdr->waveform_uri.buf))) {
char *tmp2;
if ((tmp2 = strchr(tmp, ';'))) *tmp2 = '\0';
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Waveform-URI", tmp);
free(tmp);
}
if ((tmp = get_parameter_value(recog_hdr->waveform_uri.buf, "size"))) {
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Waveform-Size", tmp);
free(tmp);
}
if ((tmp = get_parameter_value(recog_hdr->waveform_uri.buf, "duration"))) {
switch_event_add_header_string(r->result_headers, SWITCH_STACK_BOTTOM, "ASR-Waveform-Duration", tmp);
free(tmp);
}
}
}
done:
switch_mutex_unlock(schannel->mutex);
return status;
}
/**
* Get the recognition results.
*
@ -2627,6 +2770,29 @@ static switch_status_t recog_channel_get_results(speech_channel_t *schannel, cha
return status;
}
/**
* Get the recognition result headers.
*
* @param schannel the channel to get results from
* @param result_headers the recognition result headers. switch_event_destroy() the results when finished with them.
* @return SWITCH_STATUS_SUCCESS will always be returned, since this is just optional data.
*/
static switch_status_t recog_channel_get_result_headers(speech_channel_t *schannel, switch_event_t **result_headers)
{
recognizer_data_t *r = (recognizer_data_t *) schannel->data;
switch_mutex_lock(schannel->mutex);
if (r->result_headers && result_headers) {
*result_headers = r->result_headers;
r->result_headers = NULL;
}
switch_mutex_unlock(schannel->mutex);
return SWITCH_STATUS_SUCCESS;
}
/**
* Set parameters in a recognizer MRCP header
*
@ -3207,6 +3373,9 @@ static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_
r->dtmf_generator_active = 0;
mpf_dtmf_generator_destroy(r->dtmf_generator);
}
if (r->result_headers) {
switch_event_destroy(&r->result_headers);
}
switch_mutex_unlock(schannel->mutex);
speech_channel_destroy(schannel);
}
@ -3326,6 +3495,19 @@ static switch_status_t recog_asr_get_results(switch_asr_handle_t *ah, char **xml
return recog_channel_get_results(schannel, xmlstr);
}
/**
* Process asr_get_result_headers request from FreeSWITCH. Return the headers back
* to FreeSWITCH. FreeSWITCH will switch_event_destroy() the headers.
*
* @param ah the FreeSWITCH speech recognition handle
* @param flags other flags
*/
static switch_status_t recog_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags)
{
speech_channel_t *schannel = (speech_channel_t *) ah->private_info;
return recog_channel_get_result_headers(schannel, headers);
}
/**
* Send START-INPUT-TIMERS to executing recognition request
* @param ah the handle to start timers on
@ -3473,6 +3655,7 @@ static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp
recog_hdr->completion_cause);
if (message->body.length > 0) {
if (message->body.buf[message->body.length - 1] == '\0') {
recog_channel_set_result_headers(schannel, recog_hdr);
recog_channel_set_results(schannel, message->body.buf);
} else {
/* string is not null terminated */
@ -3481,11 +3664,13 @@ static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp
"(%s) Recognition result is not null-terminated. Appending null terminator.\n", schannel->name);
strncpy(result, message->body.buf, message->body.length);
result[message->body.length] = '\0';
recog_channel_set_result_headers(schannel, recog_hdr);
recog_channel_set_results(schannel, result);
}
} else {
char *completion_cause = switch_mprintf("Completion-Cause: %03d", recog_hdr->completion_cause);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) No result\n", schannel->name);
recog_channel_set_result_headers(schannel, recog_hdr);
recog_channel_set_results(schannel, completion_cause);
switch_safe_free(completion_cause);
}
@ -3584,6 +3769,7 @@ static switch_status_t recog_load(switch_loadable_module_interface_t *module_int
asr_interface->asr_pause = recog_asr_pause;
asr_interface->asr_check_results = recog_asr_check_results;
asr_interface->asr_get_results = recog_asr_get_results;
asr_interface->asr_get_result_headers = recog_asr_get_result_headers;
asr_interface->asr_start_input_timers = recog_asr_start_input_timers;
asr_interface->asr_text_param = recog_asr_text_param;
asr_interface->asr_numeric_param = recog_asr_numeric_param;
@ -3620,7 +3806,7 @@ static switch_status_t recog_load(switch_loadable_module_interface_t *module_int
switch_core_hash_insert(globals.recog.param_id_map, "N-Best-List-Length", unimrcp_param_id_create(RECOGNIZER_HEADER_N_BEST_LIST_LENGTH, pool));
switch_core_hash_insert(globals.recog.param_id_map, "No-Input-Timeout", unimrcp_param_id_create(RECOGNIZER_HEADER_NO_INPUT_TIMEOUT, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Recognition-Timeout", unimrcp_param_id_create(RECOGNIZER_HEADER_RECOGNITION_TIMEOUT, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Waveform-Url", unimrcp_param_id_create(RECOGNIZER_HEADER_WAVEFORM_URI, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Waveform-Uri", unimrcp_param_id_create(RECOGNIZER_HEADER_WAVEFORM_URI, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Completion-Cause", unimrcp_param_id_create(RECOGNIZER_HEADER_COMPLETION_CAUSE, pool));
switch_core_hash_insert(globals.recog.param_id_map, "Recognizer-Context-Block",
unimrcp_param_id_create(RECOGNIZER_HEADER_RECOGNIZER_CONTEXT_BLOCK, pool));

View File

@ -299,6 +299,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_get_results(switch_asr_handle_t
return ah->asr_interface->asr_get_results(ah, xmlstr, flags);
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags)
{
switch_assert(ah != NULL);
if (ah->asr_interface->asr_get_result_headers) {
return ah->asr_interface->asr_get_result_headers(ah, headers, flags);
} else {
/* Since this is not always implemented, return success if the function can't be called */
return SWITCH_STATUS_SUCCESS;
}
}
SWITCH_DECLARE(switch_status_t) switch_core_asr_start_input_timers(switch_asr_handle_t *ah)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;

View File

@ -3855,6 +3855,7 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
while (switch_channel_up_nosig(channel) && !switch_test_flag(sth->ah, SWITCH_ASR_FLAG_CLOSED)) {
char *xmlstr = NULL;
switch_event_t *headers = NULL;
switch_thread_cond_wait(sth->cond, sth->mutex);
@ -3868,6 +3869,9 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
goto done;
} else if (status == SWITCH_STATUS_SUCCESS) {
/* Try to fetch extra information for this result, the return value doesn't really matter here - it's just optional data. */
switch_core_asr_get_result_headers(sth->ah, &headers, &flags);
}
if (status == SWITCH_STATUS_SUCCESS && switch_true(switch_channel_get_variable(channel, "asr_intercept_dtmf"))) {
@ -3917,6 +3921,11 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
if (switch_event_create(&event, SWITCH_EVENT_DETECTED_SPEECH) == SWITCH_STATUS_SUCCESS) {
if (status == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Speech-Type", "detected-speech");
if (headers) {
switch_event_merge(event, headers);
}
switch_event_add_body(event, "%s", xmlstr);
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Speech-Type", "begin-speaking");
@ -3940,6 +3949,10 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj
}
switch_safe_free(xmlstr);
if (headers) {
switch_event_destroy(&headers);
}
}
}
done: