/* Open the speech channel. */ int speech_channel_open(speech_channel_t *schannel, ast_mrcp_profile_t *profile) { int status = 0; mpf_termination_t *termination = NULL; mrcp_resource_type_e resource_type; if ((schannel == NULL) || (profile == NULL)) return -1; if (schannel->mutex != NULL) apr_thread_mutex_lock(schannel->mutex); /* Make sure we can open channel. */ if (schannel->state != SPEECH_CHANNEL_CLOSED) { if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return -1; } schannel->profile = profile; /* Create MRCP session. */ if ((schannel->unimrcp_session = mrcp_application_session_create(schannel->application->app, profile->name, schannel)) == NULL) { /* Profile doesn't exist? */ ast_log(LOG_ERROR, "(%s) Unable to create session with %s\n", schannel->name, profile->name); if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return 2; } /* Set session name for logging purposes. */ mrcp_application_session_name_set(schannel->unimrcp_session, schannel->name); /* Create audio termination and add to channel. */ if ((termination = speech_channel_create_mpf_termination(schannel)) == NULL) { ast_log(LOG_ERROR, "(%s) Unable to create termination with %s\n", schannel->name, profile->name); if (!mrcp_application_session_destroy(schannel->unimrcp_session)) ast_log(LOG_WARNING, "(%s) Unable to destroy application session for %s\n", schannel->name, profile->name); if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return -1; } if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) resource_type = MRCP_SYNTHESIZER_RESOURCE; else resource_type = MRCP_RECOGNIZER_RESOURCE; if ((schannel->unimrcp_channel = mrcp_application_channel_create(schannel->unimrcp_session, resource_type, termination, NULL, schannel)) == NULL) { ast_log(LOG_ERROR, "(%s) Unable to create channel with %s\n", schannel->name, profile->name); if (!mrcp_application_session_destroy(schannel->unimrcp_session)) ast_log(LOG_WARNING, "(%s) Unable to destroy application session for %s\n", schannel->name, profile->name); if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Add channel to session. This establishes the connection to the MRCP server. */ if (mrcp_application_channel_add(schannel->unimrcp_session, schannel->unimrcp_channel) != TRUE) { ast_log(LOG_ERROR, "(%s) Unable to add channel to session with %s\n", schannel->name, profile->name); if (!mrcp_application_session_destroy(schannel->unimrcp_session)) ast_log(LOG_WARNING, "(%s) Unable to destroy application session for %s\n", schannel->name, profile->name); if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return -1; } /* Wait for channel to be ready. */ while ((schannel->mutex != NULL) && (schannel->cond != NULL) && (schannel->state == SPEECH_CHANNEL_CLOSED)) apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC); if (schannel->state == SPEECH_CHANNEL_READY) { ast_log(LOG_DEBUG, "(%s) channel is ready\n", schannel->name); } else if (schannel->state == SPEECH_CHANNEL_CLOSED) { ast_log(LOG_ERROR, "(%s) Timed out waiting for channel to be ready\n", schannel->name); /* Can't retry. */ status = -1; } else if (schannel->state == SPEECH_CHANNEL_ERROR) { /* Wait for session to be cleaned up. */ if (schannel->cond != NULL) apr_thread_cond_timedwait(schannel->cond, schannel->mutex, SPEECH_CHANNEL_TIMEOUT_USEC); if (schannel->state != SPEECH_CHANNEL_CLOSED) { /* Major issue. Can't retry. */ status = -1; } else { /* Failed to open profile, retry is allowed. */ status = 2; } } if (schannel->type == SPEECH_CHANNEL_RECOGNIZER) { recognizer_data_t *r = (recognizer_data_t *)apr_palloc(schannel->pool, sizeof(recognizer_data_t)); if (r != NULL) { schannel->data = r; memset(r, 0, sizeof(recognizer_data_t)); if ((r->grammars = apr_hash_make(schannel->pool)) == NULL) { ast_log(LOG_ERROR, "Unable to allocate hash for grammars\n"); status = -1; } } else { ast_log(LOG_ERROR, "Unable to allocate recognizer data structure\n"); status = -1; } } if (schannel->mutex != NULL) apr_thread_mutex_unlock(schannel->mutex); return status; }
/** \brief Set up the speech structure within the engine */ static int uni_recog_create_internal(struct ast_speech *speech, ast_format_compat *format) { uni_speech_t *uni_speech; mrcp_session_t *session; apr_pool_t *pool; const mpf_codec_descriptor_t *descriptor; /* Create session instance */ session = mrcp_application_session_create(uni_engine.application,uni_engine.profile,speech); if(!session) { ast_log(LOG_ERROR, "Failed to create MRCP session\n"); return -1; } pool = mrcp_application_session_pool_get(session); uni_speech = apr_palloc(pool,sizeof(uni_speech_t)); uni_speech->name = apr_psprintf(pool, "RSU-%hu", uni_speech_id_get()); uni_speech->session = session; uni_speech->channel = NULL; uni_speech->wait_object = NULL; uni_speech->mutex = NULL; uni_speech->media_buffer = NULL; uni_speech->active_grammars = apr_hash_make(pool); uni_speech->is_sm_request = FALSE; uni_speech->is_inprogress = FALSE; uni_speech->sm_request = 0; uni_speech->sm_response = MRCP_SIG_STATUS_CODE_SUCCESS; uni_speech->mrcp_request = NULL; uni_speech->mrcp_response = NULL; uni_speech->mrcp_event = NULL; uni_speech->speech_base = speech; speech->data = uni_speech; /* Create cond wait object and mutex */ apr_thread_mutex_create(&uni_speech->mutex,APR_THREAD_MUTEX_DEFAULT,pool); apr_thread_cond_create(&uni_speech->wait_object,pool); ast_log(LOG_NOTICE, "(%s) Create speech resource\n",uni_speech->name); /* Set session name for logging purposes. */ mrcp_application_session_name_set(session,uni_speech->name); /* Create recognition channel instance */ if(uni_recog_channel_create(uni_speech,format) != TRUE) { ast_log(LOG_ERROR, "(%s) Failed to create MRCP channel\n",uni_speech->name); uni_recog_cleanup(uni_speech); return -1; } /* Send add channel request and wait for response */ if(uni_recog_sm_request_send(uni_speech,MRCP_SIG_COMMAND_CHANNEL_ADD) != TRUE) { ast_log(LOG_WARNING, "(%s) Failed to send add-channel request\n",uni_speech->name); uni_recog_cleanup(uni_speech); return -1; } /* Check received response */ if(uni_speech->sm_response != MRCP_SIG_STATUS_CODE_SUCCESS) { ast_log(LOG_WARNING, "(%s) Failed to add MRCP channel status: %d\n",uni_speech->name,uni_speech->sm_response); uni_recog_sm_request_send(uni_speech,MRCP_SIG_COMMAND_SESSION_TERMINATE); uni_recog_cleanup(uni_speech); return -1; } descriptor = mrcp_application_source_descriptor_get(uni_speech->channel); if(descriptor) { mpf_frame_buffer_t *media_buffer; apr_size_t frame_size = mpf_codec_linear_frame_size_calculate(descriptor->sampling_rate,descriptor->channel_count); /* Create media buffer */ ast_log(LOG_DEBUG, "(%s) Create media buffer frame_size:%"APR_SIZE_T_FMT"\n",uni_speech->name,frame_size); media_buffer = mpf_frame_buffer_create(frame_size,20,pool); uni_speech->media_buffer = media_buffer; } if(!uni_speech->media_buffer) { ast_log(LOG_WARNING, "(%s) Failed to create media buffer\n",uni_speech->name); uni_recog_sm_request_send(uni_speech,MRCP_SIG_COMMAND_SESSION_TERMINATE); uni_recog_cleanup(uni_speech); return -1; } /* Set properties for session */ uni_recog_properties_set(uni_speech); /* Preload grammars */ uni_recog_grammars_preload(uni_speech); return 0; }