/** \brief Load module */
static int load_module(void)
{
	ast_log(LOG_NOTICE, "Load Res-Speech-UniMRCP module\n");

	if(uni_engine_load() == FALSE) {
		return AST_MODULE_LOAD_FAILURE;
	}

	if(mrcp_client_start(uni_engine.client) != TRUE) {
		ast_log(LOG_ERROR, "Failed to start MRCP client\n");
		uni_engine_unload();
		return AST_MODULE_LOAD_FAILURE;
	}

#if AST_VERSION_AT_LEAST(10,0,0)

#if AST_VERSION_AT_LEAST(13,0,0)
	ast_engine.formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
#elif AST_VERSION_AT_LEAST(12,0,0)
	ast_engine.formats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK);
#else /* <= 11 */
	ast_engine.formats = ast_format_cap_alloc_nolock();
#endif
	if(!ast_engine.formats) {
		ast_log(LOG_ERROR, "Failed to alloc media format capabilities\n");
		uni_engine_unload();
		return AST_MODULE_LOAD_FAILURE;
	}
#if AST_VERSION_AT_LEAST(13,0,0)
	ast_format_cap_append(ast_engine.formats, ast_format_slin, 0);
#else
	struct ast_format format;
	ast_format_set(&format, AST_FORMAT_SLINEAR, 0);
	ast_format_cap_add(ast_engine.formats, &format);
#endif

#else /* <= 1.8 */
	ast_engine.formats = AST_FORMAT_SLINEAR;
#endif

	if(ast_speech_register(&ast_engine)) {
		ast_log(LOG_ERROR, "Failed to register module\n");
		mrcp_client_shutdown(uni_engine.client);
		uni_engine_unload();
		return AST_MODULE_LOAD_FAILURE;
	}

	return AST_MODULE_LOAD_SUCCESS;
}
/** \brief Unload module */
static int unload_module(void)
{
	ast_log(LOG_NOTICE, "Unload UniMRCP module\n");
	if(ast_speech_unregister(UNI_ENGINE_NAME)) {
		ast_log(LOG_ERROR, "Failed to unregister module\n");
	}

	if(uni_engine.client) {
		mrcp_client_shutdown(uni_engine.client);
	}

	uni_engine_unload();
	return 0;
}
/** \brief Load UniMRCP engine */
static apt_bool_t uni_engine_load()
{
	apr_pool_t *pool;
	apt_dir_layout_t *dir_layout;

	/* APR global initialization */
	if(apr_initialize() != APR_SUCCESS) {
		ast_log(LOG_ERROR, "Failed to initialize APR\n");
		return FALSE;
	}

	uni_engine.pool = NULL;
	uni_engine.client = NULL;
	uni_engine.application = NULL;
	uni_engine.profile = NULL;
	uni_engine.log_level = APT_PRIO_INFO;
	uni_engine.log_output = APT_LOG_OUTPUT_CONSOLE | APT_LOG_OUTPUT_FILE;
	uni_engine.grammars = NULL;

	pool = apt_pool_create();
	if(!pool) {
		ast_log(LOG_ERROR, "Failed to create APR pool\n");
		uni_engine_unload();
		return FALSE;
	}

	uni_engine.pool = pool;
	uni_engine.v2_properties = NULL;
	uni_engine.v1_properties = NULL;

	/* Load engine configuration */
	uni_engine_config_load(pool);

	if(!uni_engine.profile) {
		uni_engine.profile = "uni2";
	}

	dir_layout = apt_default_dir_layout_create(UNIMRCP_DIR_LOCATION,pool);
	/* Create singleton logger */
	apt_log_instance_create(uni_engine.log_output, uni_engine.log_level, pool);
	/* Open the log file */
	apt_log_file_open(dir_layout->log_dir_path,"astuni",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,TRUE,pool);

	uni_engine.client = unimrcp_client_create(dir_layout);
	if(uni_engine.client) {
		uni_engine.application = mrcp_application_create(
										uni_message_handler,
										&uni_engine,
										pool);
		if(uni_engine.application) {
			mrcp_client_application_register(
							uni_engine.client,
							uni_engine.application,
							"ASTMRCP");
		}
	}

	if(!uni_engine.client || !uni_engine.application) {
		ast_log(LOG_ERROR, "Failed to initialize client stack\n");
		uni_engine_unload();
		return FALSE;
	}

	return TRUE;
}
/** \brief Load UniMRCP engine */
static apt_bool_t uni_engine_load()
{
	apr_pool_t *pool;
	apt_dir_layout_t *dir_layout;

	/* APR global initialization */
	if(apr_initialize() != APR_SUCCESS) {
		ast_log(LOG_ERROR, "Failed to initialize APR\n");
		return FALSE;
	}

	uni_engine.pool = NULL;
	uni_engine.client = NULL;
	uni_engine.application = NULL;
	uni_engine.profile = NULL;
	uni_engine.log_level = APT_PRIO_INFO;
	uni_engine.log_output = APT_LOG_OUTPUT_CONSOLE | APT_LOG_OUTPUT_FILE;
	uni_engine.grammars = NULL;
	uni_engine.v2_properties = NULL;
	uni_engine.v1_properties = NULL;
	uni_engine.mutex = NULL;
	uni_engine.current_speech_index = 0;

	pool = apt_pool_create();
	if(!pool) {
		ast_log(LOG_ERROR, "Failed to create APR pool\n");
		uni_engine_unload();
		return FALSE;
	}

	uni_engine.pool = pool;

	if(apr_thread_mutex_create(&uni_engine.mutex, APR_THREAD_MUTEX_DEFAULT, pool) != APR_SUCCESS) {
		ast_log(LOG_ERROR, "Failed to create engine mutex\n");
		uni_engine_unload();
		return FALSE;
	}

	/* Load engine configuration */
	uni_engine_config_load(pool);

	if(!uni_engine.profile) {
		uni_engine.profile = "uni2";
	}

	dir_layout = apt_default_dir_layout_create(UNIMRCP_DIR_LOCATION,pool);
	/* Create singleton logger */
	apt_log_instance_create(uni_engine.log_output, uni_engine.log_level, pool);
	if(apt_log_output_mode_check(APT_LOG_OUTPUT_FILE) == TRUE) {
#ifdef OPAQUE_DIR_LAYOUT
		const char *log_dir_path = apt_dir_layout_path_get(dir_layout,APT_LAYOUT_LOG_DIR);
#else
		const char *log_dir_path = dir_layout->log_dir_path;
#endif
		/* Open the log file */
		apt_log_file_open(log_dir_path,"astuni",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,TRUE,pool);
	}

	uni_engine.client = unimrcp_client_create(dir_layout);
	if(uni_engine.client) {
		uni_engine.application = mrcp_application_create(
										uni_message_handler,
										&uni_engine,
										pool);
		if(uni_engine.application) {
			mrcp_client_application_register(
							uni_engine.client,
							uni_engine.application,
							"ASTMRCP");
		}
	}

	if(!uni_engine.client || !uni_engine.application) {
		ast_log(LOG_ERROR, "Failed to initialize MRCP client\n");
		uni_engine_unload();
		return FALSE;
	}

	return TRUE;
}