/*! \brief Stop the in-progress recognition */ static int uni_recog_stop(struct ast_speech *speech) { uni_speech_t *uni_speech = speech->data; mrcp_message_t *mrcp_message; if(!uni_speech->is_inprogress) { return 0; } ast_log(LOG_NOTICE, "Stop recognition '%s'\n",uni_speech_id_get(uni_speech)); mrcp_message = mrcp_application_message_create( uni_speech->session, uni_speech->channel, RECOGNIZER_STOP); if(!mrcp_message) { ast_log(LOG_WARNING, "Failed to create MRCP message\n"); return -1; } /* Reset last event (if any) */ uni_speech->mrcp_event = NULL; /* Send MRCP request and wait for response */ if(uni_recog_mrcp_request_send(uni_speech,mrcp_message) != TRUE) { ast_log(LOG_WARNING, "Failed to send MRCP message\n"); return -1; } /* Check received response */ if(!uni_speech->mrcp_response || uni_speech->mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS) { ast_log(LOG_WARNING, "Received failure response\n"); return -1; } /* Reset media buffer */ mpf_frame_buffer_restart(uni_speech->media_buffer); ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); uni_speech->is_inprogress = FALSE; return 0; }
/** \brief Unload a local grammar */ static int uni_recog_unload_grammar(struct ast_speech *speech, ast_compat_const char *grammar_name) { uni_speech_t *uni_speech = speech->data; mrcp_message_t *mrcp_message; mrcp_generic_header_t *generic_header; if(uni_speech->is_inprogress) { uni_recog_stop(speech); } ast_log(LOG_NOTICE, "(%s) Unload grammar name: %s\n", uni_speech->name, grammar_name); apr_hash_set(uni_speech->active_grammars,grammar_name,APR_HASH_KEY_STRING,NULL); mrcp_message = mrcp_application_message_create( uni_speech->session, uni_speech->channel, RECOGNIZER_DEFINE_GRAMMAR); if(!mrcp_message) { ast_log(LOG_WARNING, "(%s) Failed to create MRCP message\n",uni_speech->name); return -1; } /* Get/allocate generic header */ generic_header = mrcp_generic_header_prepare(mrcp_message); if(generic_header) { /* Set generic header fields */ apt_string_assign(&generic_header->content_id,grammar_name,mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_ID); } /* Send MRCP request and wait for response */ if(uni_recog_mrcp_request_send(uni_speech,mrcp_message) != TRUE) { ast_log(LOG_WARNING, "(%s) Failed to unload grammar\n",uni_speech->name); return -1; } return 0; }
/** Create demo MRCP message (RECOGNIZE request) */ mrcp_message_t* demo_recognize_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout) { const char text[] = "session:[email protected]"; /* create MRCP message */ mrcp_message_t *mrcp_message = mrcp_application_message_create(session,channel,RECOGNIZER_RECOGNIZE); if(mrcp_message) { mrcp_recog_header_t *recog_header; mrcp_generic_header_t *generic_header; /* get/allocate generic header */ generic_header = mrcp_generic_header_prepare(mrcp_message); if(generic_header) { /* set generic header fields */ apt_string_assign(&generic_header->content_type,"text/uri-list",mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE); } /* get/allocate recognizer header */ recog_header = mrcp_resource_header_prepare(mrcp_message); if(recog_header) { if(mrcp_message->start_line.version == MRCP_VERSION_2) { /* set recognizer header fields */ recog_header->cancel_if_queue = FALSE; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CANCEL_IF_QUEUE); } recog_header->no_input_timeout = 5000; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_NO_INPUT_TIMEOUT); recog_header->recognition_timeout = 10000; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_RECOGNITION_TIMEOUT); recog_header->start_input_timers = TRUE; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_START_INPUT_TIMERS); recog_header->confidence_threshold = 0.87f; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD); } /* set message body */ apt_string_assign(&mrcp_message->body,text,mrcp_message->pool); } return mrcp_message; }
/** \brief Set properties */ static apt_bool_t uni_recog_properties_set(uni_speech_t *uni_speech) { mrcp_message_t *mrcp_message; mrcp_message_header_t *properties; ast_log(LOG_DEBUG, "(%s) Set properties\n",uni_speech->name); mrcp_message = mrcp_application_message_create( uni_speech->session, uni_speech->channel, RECOGNIZER_SET_PARAMS); if(!mrcp_message) { ast_log(LOG_WARNING, "(%s) Failed to create MRCP message\n",uni_speech->name); return FALSE; } /* Inherit properties loaded from config */ if(mrcp_message->start_line.version == MRCP_VERSION_2) { properties = uni_engine.v2_properties; } else { properties = uni_engine.v1_properties; } if(properties) { #if defined(TRANSPARENT_HEADER_FIELDS_SUPPORT) mrcp_header_fields_inherit(&mrcp_message->header,properties,mrcp_message->pool); #else mrcp_message_header_inherit(&mrcp_message->header,properties,mrcp_message->pool); #endif } /* Send MRCP request and wait for response */ if(uni_recog_mrcp_request_send(uni_speech,mrcp_message) != TRUE) { ast_log(LOG_WARNING, "(%s) Failed to set properties\n",uni_speech->name); return FALSE; } return TRUE; }
/*! \brief Stop the in-progress recognition */ static int uni_recog_stop(struct ast_speech *speech) { uni_speech_t *uni_speech = speech->data; mrcp_message_t *mrcp_message; if(!uni_speech->is_inprogress) { return 0; } ast_log(LOG_NOTICE, "(%s) Stop recognition\n",uni_speech->name); mrcp_message = mrcp_application_message_create( uni_speech->session, uni_speech->channel, RECOGNIZER_STOP); if(!mrcp_message) { ast_log(LOG_WARNING, "(%s) Failed to create MRCP message\n",uni_speech->name); return -1; } /* Reset last event (if any) */ uni_speech->mrcp_event = NULL; /* Send MRCP request and wait for response */ if(uni_recog_mrcp_request_send(uni_speech,mrcp_message) != TRUE) { ast_log(LOG_WARNING, "(%s) Failed to stop recognition\n",uni_speech->name); return -1; } /* Reset media buffer */ mpf_frame_buffer_restart(uni_speech->media_buffer); ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY); uni_speech->is_inprogress = FALSE; return 0; }
/* Send SPEAK request to synthesizer. */ static int synth_channel_speak(speech_channel_t *schannel, const char *content, const char *content_type, apr_hash_t *header_fields) { int status = 0; mrcp_message_t *mrcp_message = NULL; mrcp_generic_header_t *generic_header = NULL; mrcp_synth_header_t *synth_header = NULL; if (!schannel || !content || !content_type) { ast_log(LOG_ERROR, "synth_channel_speak: unknown channel error!\n"); return -1; } apr_thread_mutex_lock(schannel->mutex); if (schannel->state != SPEECH_CHANNEL_READY) { apr_thread_mutex_unlock(schannel->mutex); return -1; } if ((mrcp_message = mrcp_application_message_create(schannel->unimrcp_session, schannel->unimrcp_channel, SYNTHESIZER_SPEAK)) == NULL) { ast_log(LOG_ERROR, "(%s) Failed to create SPEAK message\n", schannel->name); apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Set generic header fields (content-type). */ if ((generic_header = (mrcp_generic_header_t *)mrcp_generic_header_prepare(mrcp_message)) == NULL) { apr_thread_mutex_unlock(schannel->mutex); return -1; } apt_string_assign(&generic_header->content_type, content_type, mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message, GENERIC_HEADER_CONTENT_TYPE); /* Set synthesizer header fields (voice, rate, etc.). */ if ((synth_header = (mrcp_synth_header_t *)mrcp_resource_header_prepare(mrcp_message)) == NULL) { apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Add params to MRCP message. */ speech_channel_set_params(schannel, mrcp_message, header_fields); /* Set body (plain text or SSML). */ apt_string_assign(&mrcp_message->body, content, schannel->pool); /* Empty audio queue and send SPEAK to MRCP server. */ audio_queue_clear(schannel->audio_queue); if (!mrcp_application_message_send(schannel->unimrcp_session, schannel->unimrcp_channel, mrcp_message)) { ast_log(LOG_ERROR,"(%s) Failed to send SPEAK message", schannel->name); apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Wait for IN PROGRESS. */ apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC); if (schannel->state != SPEECH_CHANNEL_PROCESSING) { apr_thread_mutex_unlock(schannel->mutex); return -1; } apr_thread_mutex_unlock(schannel->mutex); return status; }
/** brief Prepare engine to accept audio */ static int uni_recog_start(struct ast_speech *speech) { uni_speech_t *uni_speech = speech->data; mrcp_message_t *mrcp_message; mrcp_generic_header_t *generic_header; mrcp_recog_header_t *recog_header; if(uni_speech->is_inprogress) { uni_recog_stop(speech); } ast_log(LOG_NOTICE, "Start audio '%s'\n",uni_speech_id_get(uni_speech)); mrcp_message = mrcp_application_message_create( uni_speech->session, uni_speech->channel, RECOGNIZER_RECOGNIZE); if(!mrcp_message) { ast_log(LOG_WARNING, "Failed to create MRCP message\n"); return -1; } /* Get/allocate generic header */ generic_header = mrcp_generic_header_prepare(mrcp_message); if(generic_header) { apr_hash_index_t *it; void *val; const char *grammar_name; const char *content = NULL; /* Set generic header fields */ apt_string_assign(&generic_header->content_type,"text/uri-list",mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE); /* Construct and set message body */ it = apr_hash_first(mrcp_message->pool,uni_speech->active_grammars); if(it) { apr_hash_this(it,NULL,NULL,&val); grammar_name = val; content = apr_pstrcat(mrcp_message->pool,"session:",grammar_name,NULL); it = apr_hash_next(it); } for(; it; it = apr_hash_next(it)) { apr_hash_this(it,NULL,NULL,&val); grammar_name = val; content = apr_pstrcat(mrcp_message->pool,content,"\nsession:",grammar_name,NULL); } if(content) { apt_string_set(&mrcp_message->body,content); } } /* Get/allocate recognizer header */ recog_header = (mrcp_recog_header_t*) mrcp_resource_header_prepare(mrcp_message); if(recog_header) { /* Set recognizer header fields */ if(mrcp_message->start_line.version == MRCP_VERSION_2) { recog_header->cancel_if_queue = FALSE; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CANCEL_IF_QUEUE); } recog_header->start_input_timers = TRUE; mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_START_INPUT_TIMERS); } /* Reset last event (if any) */ uni_speech->mrcp_event = NULL; /* Send MRCP request and wait for response */ if(uni_recog_mrcp_request_send(uni_speech,mrcp_message) != TRUE) { ast_log(LOG_WARNING, "Failed to send MRCP message\n"); return -1; } /* Check received response */ if(!uni_speech->mrcp_response || uni_speech->mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS) { ast_log(LOG_WARNING, "Received failure response\n"); return -1; } /* Reset media buffer */ mpf_frame_buffer_restart(uni_speech->media_buffer); ast_speech_change_state(speech, AST_SPEECH_STATE_READY); uni_speech->is_inprogress = TRUE; return 0; }
/*! \brief Load a local grammar on the speech structure */ static int uni_recog_load_grammar(struct ast_speech *speech, ast_compat_const char *grammar_name, ast_compat_const char *grammar_path) { uni_speech_t *uni_speech = speech->data; mrcp_message_t *mrcp_message; mrcp_generic_header_t *generic_header; const char *content_type = NULL; apt_bool_t inline_content = FALSE; char *tmp; apr_file_t *file; apt_str_t *body = NULL; mrcp_message = mrcp_application_message_create( uni_speech->session, uni_speech->channel, RECOGNIZER_DEFINE_GRAMMAR); if(!mrcp_message) { ast_log(LOG_WARNING, "Failed to create MRCP message\n"); return -1; } /* * Grammar name and path are mandatory attributes, * grammar type can be optionally specified with path. * * SpeechLoadGrammar(name|path) * SpeechLoadGrammar(name|type:path) * SpeechLoadGrammar(name|uri:path) * SpeechLoadGrammar(name|builtin:grammar/digits) */ tmp = strchr(grammar_path,':'); if(tmp) { const char builtin_token[] = "builtin"; const char uri_token[] = "uri"; if(strncmp(grammar_path,builtin_token,sizeof(builtin_token)-1) == 0) { content_type = "text/uri-list"; inline_content = TRUE; } else if(strncmp(grammar_path,uri_token,sizeof(uri_token)-1) == 0) { content_type = "text/uri-list"; inline_content = TRUE; grammar_path = tmp+1; } else { *tmp = '\0'; content_type = grammar_path; grammar_path = tmp+1; } } if(inline_content == TRUE) { body = &mrcp_message->body; apt_string_assign(body,grammar_path,mrcp_message->pool); } else { if(apr_file_open(&file,grammar_path,APR_FOPEN_READ|APR_FOPEN_BINARY,0,mrcp_message->pool) == APR_SUCCESS) { apr_finfo_t finfo; if(apr_file_info_get(&finfo,APR_FINFO_SIZE,file) == APR_SUCCESS) { /* Read message body */ body = &mrcp_message->body; body->buf = apr_palloc(mrcp_message->pool,finfo.size+1); body->length = (apr_size_t)finfo.size; if(apr_file_read(file,body->buf,&body->length) != APR_SUCCESS) { ast_log(LOG_WARNING, "Failed to read the content of grammar file: %s\n",grammar_path); } body->buf[body->length] = '\0'; } apr_file_close(file); } else { ast_log(LOG_WARNING, "No such grammar file available: %s\n",grammar_path); return -1; } } if(!body || !body->buf) { ast_log(LOG_WARNING, "No content available: %s\n",grammar_path); return -1; } /* Try to implicitly detect content type, if it's not specified */ if(!content_type) { if(strstr(body->buf,"#JSGF")) { content_type = "application/x-jsgf"; } else if(strstr(body->buf,"#ABNF")) { content_type = "application/srgs"; } else { content_type = "application/srgs+xml"; } } ast_log(LOG_NOTICE, "Load grammar name:%s type:%s path:%s '%s'\n", grammar_name, content_type, grammar_path, uni_speech_id_get(uni_speech)); /* Get/allocate generic header */ generic_header = mrcp_generic_header_prepare(mrcp_message); if(generic_header) { /* Set generic header fields */ apt_string_assign(&generic_header->content_type,content_type,mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE); apt_string_assign(&generic_header->content_id,grammar_name,mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_ID); } /* Send MRCP request and wait for response */ if(uni_recog_mrcp_request_send(uni_speech,mrcp_message) != TRUE) { ast_log(LOG_WARNING, "Failed to send MRCP message\n"); return -1; } /* Check received response */ if(!uni_speech->mrcp_response || uni_speech->mrcp_response->start_line.status_code != MRCP_STATUS_CODE_SUCCESS) { ast_log(LOG_WARNING, "Received failure response\n"); return -1; } return 0; }
mrcp_message_t* UmcSession::CreateMrcpMessage( mrcp_channel_t* pMrcpChannel, mrcp_method_id method_id) { return mrcp_application_message_create(m_pMrcpSession,pMrcpChannel,method_id); }