Example #1
0
/* 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;
}