FS-5583 --resolve
This commit is contained in:
parent
fb887acb44
commit
453cfaaf7f
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue