Change internal function to static
[platform/core/uifw/tts.git] / server / ttsd_engine_agent.c
index f41d412..83abe14 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved
+*  Copyright (c) 2011-2016 Samsung Electronics Co., Ltd All Rights Reserved
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 /*
 * Internal data structure
 */
-typedef struct {
+typedef struct _ttsengine_info {
        /* base info */
        char*   engine_uuid;
-       char*   engine_name;
        char*   engine_path;
+       char*   engine_name;
+       char*   engine_setting_path;
 
        /* info for using engine load */
-       bool    is_set;
        bool    is_loaded;
-       bool    need_network;
-       void    *handle;
+       bool    use_network;
+
+       tts_engine_callback_s* callbacks;
 
        /* engine base setting */
        char*   default_lang;
        int     default_vctype;
        int     default_speed;
        int     default_pitch;
-
-       ttspe_funcs_s*  pefuncs;
-       ttspd_funcs_s*  pdfuncs;
-
-       int (*ttsp_load_engine)(const ttspd_funcs_s* pdfuncs, ttspe_funcs_s* pefuncs);
-       int (*ttsp_unload_engine)();
-} ttsengine_s;
-
-typedef struct {
-       char*   engine_uuid;
-       char*   engine_path;
-       char*   engine_name;
-       char*   setting_ug_path;
-       bool    use_network;
 } ttsengine_info_s;
 
 typedef struct {
@@ -71,34 +58,11 @@ typedef struct {
 /** Init flag */
 static bool g_agent_init;
 
-/** TTS engine list */
-static GList *g_engine_list;
-
 /** Current engine information */
-static ttsengine_s g_cur_engine;
+static ttsengine_info_s* g_engine_info = NULL;
 
 /** Current voice information */
-static GSList* g_cur_voices;
-
-/** Result callback function */
-static synth_result_callback g_result_cb;
-
-
-/** Set current engine */
-static int __internal_set_current_engine(const char* engine_uuid);
-
-/** Check engine id */
-static int __internal_check_engine_id(const char* engine_uuid);
-
-/** Update engine list */
-static int __internal_update_engine_list();
-
-/** Get engine info */
-static int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info);
-
-/** Callback function for result */
-bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, 
-                ttsp_audio_type_e audio_type, int rate, void *user_data);
+static GSList* g_cur_voices = NULL;
 
 /** Callback function for voice list */
 static bool __supported_voice_cb(const char* language, int type, void* user_data);
@@ -106,560 +70,112 @@ static bool __supported_voice_cb(const char* language, int type, void* user_data
 /** Free voice list */
 static void __free_voice_list(GList* voice_list);
 
-/** Callback function for engine info */
-static void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
-                     bool use_network, void* user_data);
-
-
-/** Print list */
-static int ttsd_print_enginelist();
-
 static int ttsd_print_voicelist();
 
-static const char* __ttsd_get_engine_error_code(ttsp_error_e err)
+/** Get engine info */
+static int __internal_get_engine_info(ttse_request_callback_s* callback);
+
+static const char* __ttsd_get_engine_error_code(ttse_error_e err)
 {
        switch (err) {
-       case TTSP_ERROR_NONE:                   return "TTSP_ERROR_NONE";
-       case TTSP_ERROR_OUT_OF_MEMORY:          return "TTSP_ERROR_OUT_OF_MEMORY";
-       case TTSP_ERROR_IO_ERROR:               return "TTSP_ERROR_IO_ERROR";
-       case TTSP_ERROR_INVALID_PARAMETER:      return "TTSP_ERROR_INVALID_PARAMETER";
-       case TTSP_ERROR_OUT_OF_NETWORK:         return "TTSP_ERROR_OUT_OF_NETWORK";
-       case TTSP_ERROR_INVALID_STATE:          return "TTSP_ERROR_INVALID_STATE";
-       case TTSP_ERROR_INVALID_VOICE:          return "TTSP_ERROR_INVALID_VOICE";
-       case TTSP_ERROR_OPERATION_FAILED:       return "TTSP_ERROR_OPERATION_FAILED";
+       case TTSE_ERROR_NONE:                   return "TTSE_ERROR_NONE";
+       case TTSE_ERROR_OUT_OF_MEMORY:          return "TTSE_ERROR_OUT_OF_MEMORY";
+       case TTSE_ERROR_IO_ERROR:               return "TTSE_ERROR_IO_ERROR";
+       case TTSE_ERROR_INVALID_PARAMETER:      return "TTSE_ERROR_INVALID_PARAMETER";
+       case TTSE_ERROR_NETWORK_DOWN:           return "TTSE_ERROR_NETWORK_DOWN";
+       case TTSE_ERROR_INVALID_STATE:          return "TTSE_ERROR_INVALID_STATE";
+       case TTSE_ERROR_INVALID_VOICE:          return "TTSE_ERROR_INVALID_VOICE";
+       case TTSE_ERROR_OPERATION_FAILED:       return "TTSE_ERROR_OPERATION_FAILED";
        default:
                return "Invalid error code";
        }
 }
 
-int ttsd_engine_agent_init(synth_result_callback result_cb)
+int ttsd_engine_agent_init()
 {
-       /* initialize static data */
-       if (result_cb == NULL) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] invalid parameter");
-               return TTSD_ERROR_INVALID_PARAMETER;
-       }
-
-       g_result_cb = result_cb;
-
-       g_cur_engine.engine_uuid = NULL;
-       g_cur_engine.engine_name = NULL;
-       g_cur_engine.engine_path = NULL;
-
-       g_cur_engine.is_set = false;
-       g_cur_engine.handle = NULL;
-       g_cur_engine.pefuncs = (ttspe_funcs_s*)calloc(1, sizeof(ttspe_funcs_s));
-       g_cur_engine.pdfuncs = (ttspd_funcs_s*)calloc(1, sizeof(ttspd_funcs_s));
-
-       g_agent_init = true;
-
-       if (0 != ttsd_config_get_default_voice(&(g_cur_engine.default_lang), &(g_cur_engine.default_vctype))) {
-               SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default voice in config");
-               /* Set default voice */
-               g_cur_engine.default_lang = strdup(TTS_BASE_LANGUAGE);
-               g_cur_engine.default_vctype = TTSP_VOICE_TYPE_FEMALE;
-       }
-
-       if (0 != ttsd_config_get_default_speed(&(g_cur_engine.default_speed))) {
-               SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default speed in config");
-               g_cur_engine.default_speed = TTS_SPEED_NORMAL;
-       }
-
-       if (0 != ttsd_config_get_default_pitch(&(g_cur_engine.default_pitch))) {
-               SLOG(LOG_WARN, get_tag(), "[Server WARNING] There is No default pitch in config");
-               g_cur_engine.default_pitch = TTS_PITCH_NORMAL;
-       }
-
-       SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Initialize Engine Agent");
-
-       return 0;
-}
-
-int ttsd_engine_agent_release()
-{
-       if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       /* unload current engine */
-       ttsd_engine_agent_unload_current_engine();
-
-       /* release engine list */
-       GList *iter = NULL;
-       ttsengine_info_s *data = NULL;
-
-       if (g_list_length(g_engine_list) > 0) {
-               /* Get a first item */
-               iter = g_list_first(g_engine_list);
-               while (NULL != iter) {
-                       /* Get data from item */
-                       data = iter->data;
-                       iter = g_list_remove(iter, data);
-
-                       if (NULL != data) {
-                               if (NULL != data->engine_uuid)          free(data->engine_uuid);
-                               if (NULL != data->engine_name)          free(data->engine_name);
-                               if (NULL != data->setting_ug_path)      free(data->setting_ug_path);
-                               if (NULL != data->engine_path)          free(data->engine_path);
-                               free(data);
-                       }
-               }
-       }
-       g_list_free(iter);
-
-       /* release current engine data */
-       if (g_cur_engine.engine_uuid != NULL)   free(g_cur_engine.engine_uuid);
-       if (g_cur_engine.engine_name != NULL)   free(g_cur_engine.engine_name);
-       if (g_cur_engine.engine_path != NULL)   free(g_cur_engine.engine_path);
-
-       if (g_cur_engine.pefuncs != NULL)       free(g_cur_engine.pefuncs);
-       if (g_cur_engine.pdfuncs != NULL)       free(g_cur_engine.pdfuncs);
-       if (g_cur_engine.default_lang != NULL)  free(g_cur_engine.default_lang);
-       g_result_cb = NULL;
-       g_agent_init = false;
-
-       SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Release Engine Agent");
-
-       return 0;
-}
-
-int ttsd_engine_agent_initialize_current_engine()
-{
-       if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       /* update engine list */
-       if (0 != __internal_update_engine_list()) {
-               SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] No engine error");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       /* 2. get current engine from config */
-       char* cur_engine_uuid = NULL;
-       bool is_get_engineid_from_config = false;
-
-       if (0 != ttsd_config_get_default_engine(&cur_engine_uuid)) {
-               /*not set current engine */
-               /*set system default engine*/
-               GList *iter = NULL;
-               ttsengine_info_s *data = NULL;
-
-               if (g_list_length(g_engine_list) > 0) {
-                       iter = g_list_first(g_engine_list);
-                       data = iter->data;
-
-                       if (NULL != data) {
-                               if (NULL != data->engine_uuid) {
-                                       cur_engine_uuid = strdup(data->engine_uuid);
-                                       ttsd_config_set_default_engine(cur_engine_uuid);
-                               } else {
-                                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Data of current engine is corrupt");
-                                       return TTSD_ERROR_OPERATION_FAILED;
-                               }
-                       }
-               } else {
-                       SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Fail to set a engine of engine list");
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
-
-               is_get_engineid_from_config = false;
-       } else {
-               is_get_engineid_from_config = true;
-       }
-
-       if (NULL == cur_engine_uuid) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Current engine id is NULL");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       /* check whether cur engine uuid is valid or not. */
-       if (0 != __internal_check_engine_id(cur_engine_uuid)) {
-               SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] It is not valid engine id from config");
-
-               GList *iter = NULL;
-
-               if (g_list_length(g_engine_list) > 0)
-                       iter = g_list_first(g_engine_list);
-               else {
-                       SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] NO TTS Engine !!");
-                       if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
-
-               if (cur_engine_uuid != NULL)    free(cur_engine_uuid);
-               ttsengine_info_s *data = NULL;
-               data = iter->data;
-
-               cur_engine_uuid = strdup(data->engine_uuid);
-
-               is_get_engineid_from_config = false;
-       }
-
-       if (NULL != cur_engine_uuid)
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Current Engine Id : %s", cur_engine_uuid);
-       else
-               return TTSD_ERROR_OPERATION_FAILED;
-
-       /* set current engine */
-       if (0 != __internal_set_current_engine(cur_engine_uuid)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to set current engine ");
-               if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       if (false == is_get_engineid_from_config) {
-               if (0 != ttsd_config_set_default_engine(cur_engine_uuid)) {
-                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to set id to config");
-               }
-       }
-
-       if (NULL != cur_engine_uuid)    free(cur_engine_uuid);
-
-       SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set current engine");
-
-       return 0;
-}
-
-static int __internal_check_engine_id(const char* engine_uuid)
-{
-       GList *iter = NULL;
-       ttsengine_s *data = NULL;
-
-       if (g_list_length(g_engine_list) > 0) {
-               iter = g_list_first(g_engine_list);
-
-               while (NULL != iter) {
-                       data = iter->data;
-
-                       if (0 == strncmp(engine_uuid, data->engine_uuid, strlen(data->engine_uuid)))
-                               return 0;
-
-                       iter = g_list_next(iter);
-               }
-       }
-
-       return -1;
-}
-
-void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, 
-                            bool use_network, void* user_data)
-{
-       ttsengine_info_s* temp = (ttsengine_info_s*)user_data;
-
-       if (NULL != engine_uuid)
-               temp->engine_uuid = strdup(engine_uuid);
-
-       if (NULL != engine_name)
-               temp->engine_name = strdup(engine_name);
-
-       if (NULL != setting_ug_name)
-               temp->setting_ug_path = strdup(setting_ug_name);
-
-       temp->use_network = use_network;
-       return;
-}
-
-static int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info)
-{
-       char *error;
-       void* handle;
-
-       handle = dlopen(filepath, RTLD_LAZY);
-
-       if (!handle) {
-               SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Invalid engine : %s", filepath);
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       /* link engine to daemon */
-       dlsym(handle, "ttsp_load_engine");
-       if ((error = dlerror()) != NULL) {
-               SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_load_engine : path(%s) message(%s)", filepath, error);
-               dlclose(handle);
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       dlsym(handle, "ttsp_unload_engine");
-       if ((error = dlerror()) != NULL) {
-               SECURE_SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_unload_engine : path(%s) message(%s)", filepath, error);
-               dlclose(handle);
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       int (*get_engine_info)(ttsp_engine_info_cb callback, void* user_data);
-
-       get_engine_info = (int (*)(ttsp_engine_info_cb, void*))dlsym(handle, "ttsp_get_engine_info");
-       if (NULL != (error = dlerror()) || NULL == get_engine_info) {
-               SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to open ttsp_get_engine_info() :path(%s) message(%s)", filepath, error);
-               dlclose(handle);
+       if (true == g_agent_init) {
+               SLOG(LOG_WARN, tts_tag(), "[Engine Agent] Already initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
        ttsengine_info_s* temp;
        temp = (ttsengine_info_s*)calloc(1, sizeof(ttsengine_info_s));
        if (NULL == temp) {
-               SLOG(LOG_WARN, get_tag(), "[Engine Agent] Fail to alloc memory");
-               dlclose(handle);
+               SLOG(LOG_WARN, tts_tag(), "[Engine Agent] Fail to alloc memory");
                return TTSD_ERROR_OUT_OF_MEMORY;
        }
 
-       /* get engine info */
-       if (0 != get_engine_info(&__engine_info_cb, (void*)temp)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get engine info");
-               dlclose(handle);
-               free(temp);
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (0 != ttsd_config_get_default_voice(&(temp->default_lang), &(temp->default_vctype))) {
+               SLOG(LOG_WARN, tts_tag(), "[Server WARNING] There is No default voice in config");
+               /* Set default voice */
+               temp->default_lang = strdup(TTS_BASE_LANGUAGE);
+               temp->default_vctype = TTSE_VOICE_TYPE_FEMALE;
        }
 
-       /* close engine */
-       dlclose(handle);
+       SLOG(LOG_DEBUG, tts_tag(), "[Server DEBUG] language(%s), type(%d)", temp->default_lang, temp->default_vctype);
 
-       if (TTSD_MODE_SCREEN_READER == ttsd_get_mode() && true == temp->use_network) {
-               SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent WARNING] %s is invalid because of network based", temp->engine_name);
-               if (NULL != temp->engine_uuid)          free(temp->engine_uuid);
-               if (NULL != temp->engine_name)          free(temp->engine_name);
-               if (NULL != temp->setting_ug_path)      free(temp->setting_ug_path);
-               free(temp);
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (0 != ttsd_config_get_default_speed(&(temp->default_speed))) {
+               SLOG(LOG_WARN, tts_tag(), "[Server WARNING] There is No default speed in config");
+               temp->default_speed = TTS_SPEED_NORMAL;
        }
 
-       temp->engine_path = strdup(filepath);
+       if (0 != ttsd_config_get_default_pitch(&(temp->default_pitch))) {
+               SLOG(LOG_WARN, tts_tag(), "[Server WARNING] There is No default pitch in config");
+               temp->default_pitch = TTS_PITCH_NORMAL;
+       }
 
-       SLOG(LOG_DEBUG, get_tag(), "----- Valid engine");
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine uuid : %s", temp->engine_uuid);
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine name : %s", temp->engine_name);
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Setting path : %s", temp->setting_ug_path);
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Engine path : %s", temp->engine_path);
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Use network : %s", temp->use_network ? "true" : "false");
-       SLOG(LOG_DEBUG, get_tag(), "-----");
-       SLOG(LOG_DEBUG, get_tag(), "  ");
+       temp->is_loaded = false;
+       g_engine_info = temp;
 
-       *info = temp;
+       g_agent_init = true;
 
+       SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Initialize Engine Agent");
        return 0;
 }
 
-static int __internal_update_engine_list()
+int ttsd_engine_agent_release()
 {
-       /* relsease engine list */
-       GList *iter = NULL;
-       ttsengine_info_s *data = NULL;
-
-       if (g_list_length(g_engine_list) > 0) {
-               iter = g_list_first(g_engine_list);
-
-               while (NULL != iter) {
-                       data = iter->data;
-
-                       if (data != NULL)       free(data);
-                       g_engine_list = g_list_remove_link(g_engine_list, iter);
-                       g_list_free(iter);
-                       iter = g_list_first(g_engine_list);
-               }
-       }
-
-       /* get file name from engine directory and get engine information from each filename */
-       DIR *dp = NULL;
-       int ret = -1;
-       struct dirent entry;
-       struct dirent *dirp = NULL;
-       dp = opendir(TTS_DEFAULT_ENGINE);
-
-       if (dp != NULL) {
-               do {
-                       ret = readdir_r(dp, &entry, &dirp);
-                       if (0 != ret) {
-                               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to read directory");
-                               break;
-                       }
-
-                       if (NULL != dirp) {
-                               ttsengine_info_s* info;
-                               char* filepath = NULL;
-                               int file_size;
-
-                               file_size = strlen(TTS_DEFAULT_ENGINE) + strlen(dirp->d_name) + 5;
-                               filepath = (char*)calloc(file_size, sizeof(char));
-
-                               if (NULL != filepath) {
-                                       snprintf(filepath, file_size, "%s/%s", TTS_DEFAULT_ENGINE, dirp->d_name);
-                               } else {
-                                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not enough memory!!" );
-                                       continue;
-                               }
-
-                               /* get its info and update engine list */
-                               if (0 == __internal_get_engine_info(filepath, &info)) {
-                                       /* add engine info to g_engine_list */
-                                       g_engine_list = g_list_append(g_engine_list, info);
-                               }
-
-                               if (NULL != filepath)   free(filepath);
-                       }
-               } while (NULL != dirp);
-
-               closedir(dp);
-       }
-
-       dp = opendir(TTS_DOWNLOAD_ENGINE);
-
-       if (dp != NULL) {
-               do {
-                       ret = readdir_r(dp, &entry, &dirp);
-                       if (0 != ret) {
-                               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to read directory");
-                               break;
-                       }
-
-                       if (NULL != dirp) {
-                               ttsengine_info_s* info;
-                               char* filepath = NULL;
-                               int file_size;
-
-                               file_size = strlen(TTS_DOWNLOAD_ENGINE) + strlen(dirp->d_name) + 5;
-                               filepath = (char*)calloc(file_size, sizeof(char));
-
-                               if (NULL != filepath) {
-                                       snprintf(filepath, file_size, "%s/%s", TTS_DOWNLOAD_ENGINE, dirp->d_name);
-                               } else {
-                                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not enough memory!!" );
-                                       continue;
-                               }
-
-                               /* get its info and update engine list */
-                               if (0 == __internal_get_engine_info(filepath, &info)) {
-                                       /* add engine info to g_engine_list */
-                                       g_engine_list = g_list_append(g_engine_list, info);
-                               }
-
-                               if (NULL != filepath)   free(filepath);
-                       }
-               } while (NULL != dirp);
-
-               closedir(dp);
-       }
-
-       if (g_list_length(g_engine_list) <= 0) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Engine");
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-#ifdef ENGINE_AGENT_DEBUG
-       ttsd_print_enginelist();
-#endif
-       return 0;
-}
-
-static int __internal_set_current_engine(const char* engine_uuid)
-{
-       /* check whether engine id is valid or not. */
-       GList *iter = NULL;
-       ttsengine_info_s *data = NULL;
-
-       bool flag = false;
-       if (g_list_length(g_engine_list) > 0) {
-               iter = g_list_first(g_engine_list);
-
-               while (NULL != iter) {
-                       data = iter->data;
-
-                       if (0 == strncmp(data->engine_uuid, engine_uuid, strlen(engine_uuid))) {
-                               flag = true;
-                               break;
-                       }
-
-                       /*Get next item*/
-                       iter = g_list_next(iter);
-               }
+       /* unload current engine */
+       if (g_engine_info->is_loaded) {
+               ttsd_engine_agent_unload_current_engine();
        }
 
-       /* If current engine does not exist, return error */
-       if (false == flag) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Cannot find engine id");
-               return TTSD_ERROR_OPERATION_FAILED;
-       } else {
-               if (g_cur_engine.engine_uuid != NULL) {
-                       /*compare current engine uuid */
-                       if (0 == strncmp(g_cur_engine.engine_uuid, data->engine_uuid, strlen(engine_uuid))) {
-                               SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] tts engine has already been set");
-                               return 0;
-                       }
-               }
+       if (NULL != g_engine_info->default_lang) {
+               free(g_engine_info->default_lang);
+               g_engine_info->default_lang = NULL;
        }
 
-       /* set data from g_engine_list */
-       if (g_cur_engine.engine_uuid != NULL)   free(g_cur_engine.engine_uuid);
-       if (g_cur_engine.engine_name != NULL)   free(g_cur_engine.engine_name);
-       if (g_cur_engine.engine_path != NULL)   free(g_cur_engine.engine_path);
-
-       if (NULL == data->engine_uuid || NULL == data->engine_name || NULL == data->engine_path) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Engine data is NULL");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (NULL != g_engine_info->engine_uuid) {
+               free(g_engine_info->engine_uuid);
+               g_engine_info->engine_uuid = NULL;
        }
 
-       g_cur_engine.engine_uuid = strdup(data->engine_uuid);
-       g_cur_engine.engine_name = strdup(data->engine_name);
-       g_cur_engine.engine_path = strdup(data->engine_path);
-
-       g_cur_engine.handle = NULL;
-       g_cur_engine.is_loaded = false;
-       g_cur_engine.is_set = true;
-       g_cur_engine.need_network = data->use_network;
-
-       SLOG(LOG_DEBUG, get_tag(), "-----");
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine uuid : %s", g_cur_engine.engine_uuid);
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine name : %s", g_cur_engine.engine_name);
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "Current engine path : %s", g_cur_engine.engine_path);
-       SLOG(LOG_DEBUG, get_tag(), "-----");
-
-       return 0;
-}
-
-int __ttsd_get_mode(ttsp_mode_e* mode)
-{
-       if (NULL == mode) {
-               SLOG(LOG_ERROR, get_tag(), "[ERROR] Input parameter is null");
-               return TTSP_ERROR_INVALID_PARAMETER;
+       if (NULL != g_engine_info->engine_name) {
+               free(g_engine_info->engine_name);
+               g_engine_info->engine_name = NULL;
        }
 
-       switch (ttsd_get_mode()) {
-       case TTSD_MODE_DEFAULT:         *mode = TTSP_MODE_DEFAULT;      break;
-       case TTSD_MODE_NOTIFICATION:    *mode = TTSP_MODE_NOTIFICATION; break;
-       case TTSD_MODE_SCREEN_READER:   *mode = TTSP_MODE_SCREEN_READER;        break;
-       default:
-               SLOG(LOG_ERROR, get_tag(), "[ERROR] tts mode is NOT valid");
+       if (NULL != g_engine_info->engine_setting_path) {
+               free(g_engine_info->engine_setting_path);
+               g_engine_info->engine_setting_path = NULL;
        }
 
-       return 0;
-}
-
-int __ttsd_engine_agent_get_speed_range(int* min, int* normal, int* max)
-{
-       if (NULL == min || NULL == normal || NULL == max) {
-               SLOG(LOG_ERROR, get_tag(), "[ERROR] Input parameter is null");
-               return TTSP_ERROR_INVALID_PARAMETER;
+       if (NULL != g_engine_info->engine_path) {
+               free(g_engine_info->engine_path);
+               g_engine_info->engine_path = NULL;
        }
 
-       *min = TTS_SPEED_MIN;
-       *normal = TTS_SPEED_NORMAL;
-       *max = TTS_SPEED_MAX;
-
-       return 0;
-}
+       free(g_engine_info);
+       g_engine_info = NULL;
 
-int __ttsd_engine_agent_get_pitch_range(int* min, int* normal, int* max)
-{
-       if (NULL == min || NULL == normal || NULL == max) {
-               SLOG(LOG_ERROR, get_tag(), "[ERROR] Input parameter is null");
-               return TTSP_ERROR_INVALID_PARAMETER;
-       }
+       g_agent_init = false;
 
-       *min = TTS_PITCH_MIN;
-       *normal = TTS_PITCH_NORMAL;
-       *max = TTS_PITCH_MAX;
+       SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Release Engine Agent");
 
        return 0;
 }
@@ -667,13 +183,13 @@ int __ttsd_engine_agent_get_pitch_range(int* min, int* normal, int* max)
 static bool __set_voice_info_cb(const char* language, int type, void* user_data)
 {
        if (NULL == language) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
                return false;
        }
 
        ttsvoice_s* voice = calloc(1, sizeof(ttsvoice_s));
        if (NULL == voice) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to allocate memory");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
                return false;
        }
        voice->lang = strdup(language);
@@ -682,7 +198,7 @@ static bool __set_voice_info_cb(const char* language, int type, void* user_data)
        voice->client_ref_count = 0;
        voice->is_loaded = false;
 
-       if (0 == strcmp(g_cur_engine.default_lang, language) && g_cur_engine.default_vctype == type) {
+       if (0 == strcmp(g_engine_info->default_lang, language) && g_engine_info->default_vctype == type) {
                voice->is_default = true;
                voice->is_loaded = true;
        } else {
@@ -696,13 +212,42 @@ static bool __set_voice_info_cb(const char* language, int type, void* user_data)
 
 static int __update_voice_list()
 {
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
        /* Get voice list */
+       if (NULL != g_cur_voices) {
+               GSList *iter = NULL;
+               ttsvoice_s* data = NULL;
+
+               iter = g_slist_nth(g_cur_voices, 0);
+               while (NULL != iter) {
+                       data = iter->data;
+
+                       if (NULL != data) {
+                               if (NULL != data->lang) {
+                                       free(data->lang);
+                                       data->lang = NULL;
+                               }
+
+                               g_cur_voices = g_slist_remove(g_cur_voices, data);
+                               free(data);
+                               data = NULL;
+                       }
+
+                       iter = g_slist_nth(g_cur_voices, 0);
+               }
+       }
+
        g_cur_voices = NULL;
-       int ret = 0;
 
-       ret = g_cur_engine.pefuncs->foreach_voices(__set_voice_info_cb, NULL);
+       int ret = -1;
+       ret = g_engine_info->callbacks->foreach_voices(__set_voice_info_cb, NULL);
+
        if (0 != ret || 0 >= g_slist_length(g_cur_voices)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
                return -1;
        }
 
@@ -712,178 +257,103 @@ static int __update_voice_list()
        return 0;
 }
 
-int ttsd_engine_agent_load_current_engine()
+int ttsd_engine_agent_load_current_engine(ttse_request_callback_s* callback)
 {
-       if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
+       SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent DEBUG] load current engine START");
+
 
-       if (false == g_cur_engine.is_set) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Current Engine ");
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
        /* check whether current engine is loaded or not */
-       if (true == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent] Engine has already been loaded ");
+       if (true == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent] Engine has already been loaded ");
                return 0;
        }
 
-       /* open engine */
-       char *error = NULL;
-       g_cur_engine.handle = dlopen(g_cur_engine.engine_path, RTLD_LAZY); /* RTLD_LAZY RTLD_NOW*/
-
-       if (NULL != (error = dlerror()) || NULL == g_cur_engine.handle) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to get current engine handle : %s", error);
-               return -2;
-       }
-
-       g_cur_engine.ttsp_unload_engine = (int (*)())dlsym(g_cur_engine.handle, "ttsp_unload_engine");
-       if (NULL != (error = dlerror()) || NULL == g_cur_engine.ttsp_unload_engine) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to link daemon to ttsp_unload_engine() : %s", error);
-               return -3;
+       if (NULL == callback) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
-       g_cur_engine.ttsp_load_engine = (int (*)(const ttspd_funcs_s* , ttspe_funcs_s*))dlsym(g_cur_engine.handle, "ttsp_load_engine");
-       if (NULL != (error = dlerror()) || NULL == g_cur_engine.ttsp_load_engine) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to link daemon to ttsp_load_engine() : %s", error);
-               return -3;
+       if (NULL == callback->get_info
+               || NULL == callback->initialize || NULL == callback->deinitialize
+               || NULL == callback->foreach_voices || NULL == callback->is_valid_voice
+               || NULL == callback->set_pitch
+               || NULL == callback->load_voice || NULL == callback->unload_voice
+               || NULL == callback->start_synth || NULL == callback->cancel_synth
+               || NULL == callback->check_app_agreed || NULL == callback->need_app_credential) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
-       /* load engine */
-       g_cur_engine.pdfuncs->version = 1;
-       g_cur_engine.pdfuncs->size = sizeof(ttspd_funcs_s);
-       g_cur_engine.pdfuncs->get_mode = __ttsd_get_mode;
-       g_cur_engine.pdfuncs->get_speed_range = __ttsd_engine_agent_get_speed_range;
-       g_cur_engine.pdfuncs->get_pitch_range = __ttsd_engine_agent_get_pitch_range;
-
-       int ret = 0;
-       ret = g_cur_engine.ttsp_load_engine(g_cur_engine.pdfuncs, g_cur_engine.pefuncs);
+       /* Get current engine info */
+       int ret = __internal_get_engine_info(callback);
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to load engine - %s : result(%s)",
-                        g_cur_engine.engine_path, __ttsd_get_engine_error_code(ret));
-               return TTSD_ERROR_OPERATION_FAILED;
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get engine info");
+               return ret;
        }
 
-       /* engine error check */
-       if (g_cur_engine.pefuncs->size != sizeof(ttspe_funcs_s)) {
-               SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] The size of engine function is not valid");
-       }
-
-       if (NULL == g_cur_engine.pefuncs->initialize ||
-               NULL == g_cur_engine.pefuncs->deinitialize ||
-               NULL == g_cur_engine.pefuncs->foreach_voices ||
-               NULL == g_cur_engine.pefuncs->is_valid_voice ||
-               NULL == g_cur_engine.pefuncs->start_synth ||
-               NULL == g_cur_engine.pefuncs->cancel_synth) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] The engine functions are NOT valid");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       ret = g_cur_engine.pefuncs->initialize(__result_cb);
+       /* Initialize engine */
+       ret = g_engine_info->callbacks->initialize();
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to initialize current engine : %s", __ttsd_get_engine_error_code(ret));
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to initialize current engine : %s", __ttsd_get_engine_error_code(ret));
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
        /* Get voice info of current engine */
        ret = __update_voice_list();
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set voice info : result(%d)", ret);
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set voice info : result(%d)", ret);
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
        /* Select default voice */
-       if (NULL != g_cur_engine.default_lang) {
-               if (true == g_cur_engine.pefuncs->is_valid_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype)) {
-                       SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set origin default voice to current engine : lang(%s), type(%d)",
-                                g_cur_engine.default_lang,  g_cur_engine.default_vctype);
-               } else {
-                       SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Fail set origin default voice : lang(%s), type(%d)",
-                                g_cur_engine.default_lang, g_cur_engine.default_vctype);
+       if (NULL != g_engine_info->default_lang) {
+               bool is_valid = false;
+               ret = g_engine_info->callbacks->is_valid_voice(g_engine_info->default_lang, g_engine_info->default_vctype, &is_valid);
+               if (0 == ret) {
+                       if (true == is_valid) {
+                               SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set origin default voice to current engine : lang(%s), type(%d)", 
+                                       g_engine_info->default_lang, g_engine_info->default_vctype);
+                       } else {
+                               SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Fail to set origin default voice : lang(%s), type(%d)",
+                                       g_engine_info->default_lang, g_engine_info->default_vctype);
 
-                       return TTSD_ERROR_OPERATION_FAILED;
+                               /* TODO - Error Tolerance when Default voice is not valid */
+                               return TTSD_ERROR_OPERATION_FAILED;
+                       }
+               } else {
+                       SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail(Engine ERROR) : %s", __ttsd_get_engine_error_code(ret));
+                       return ret;
                }
        }
 
        /* load default voice */
-       if (NULL != g_cur_engine.pefuncs->load_voice) {
-               ret = g_cur_engine.pefuncs->load_voice(g_cur_engine.default_lang, g_cur_engine.default_vctype);
-               if (0 == ret) {
-                       SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Load default voice : lang(%s), type(%d)",
-                                g_cur_engine.default_lang,  g_cur_engine.default_vctype);
-               } else {
-                       SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] Fail to load default voice : lang(%s), type(%d) result(%s)",
-                               g_cur_engine.default_lang, g_cur_engine.default_vctype, __ttsd_get_engine_error_code(ret));
+       ret = g_engine_info->callbacks->load_voice(g_engine_info->default_lang, g_engine_info->default_vctype);
+       if (0 == ret) {
+               SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Load default voice : lang(%s), type(%d)",
+                       g_engine_info->default_lang, g_engine_info->default_vctype);
+       } else {
+               SLOG(LOG_WARN, tts_tag(), "[Engine Agent ERROR] Fail to load default voice : lang(%s), type(%d) result(%s)",
+                       g_engine_info->default_lang, g_engine_info->default_vctype, __ttsd_get_engine_error_code(ret));
 
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
+               return TTSD_ERROR_OPERATION_FAILED;
        }
 
        /* set default pitch */
-       if (NULL != g_cur_engine.pefuncs->set_pitch) {
-               ret = g_cur_engine.pefuncs->set_pitch(g_cur_engine.default_pitch);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)", 
-                               g_cur_engine.default_pitch, __ttsd_get_engine_error_code(ret));
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
-               SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set default pitch : pitch(%d)", g_cur_engine.default_pitch);
+       ret = g_engine_info->callbacks->set_pitch(g_engine_info->default_pitch);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)", 
+                       g_engine_info->default_pitch, __ttsd_get_engine_error_code(ret));
+               return ret;
+       } else {
+               SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set default pitch : pitch(%d)", g_engine_info->default_pitch);
        }
 
-#if 0
-       if (false == set_voice) {
-               /* get language list */
-               int ret;
-               GList* voice_list = NULL;
-
-               ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list);
-
-               if (0 == ret && 0 < g_list_length(voice_list)) {
-                       GList *iter = NULL;
-                       voice_s* voice = NULL;
-
-                       iter = g_list_first(voice_list);
-
-                       /* check english */
-                       while (NULL != iter) {
-                               voice = iter->data;
-
-                               if (NULL != voice) {
-                                       if (0 == strcmp("en_US", voice->language))
-                                               break;
-                               }
-
-                               iter = g_list_next(iter);
-                       }
-                       if (NULL == voice) {
-                               SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail to find voice in list");
-                               return TTSD_ERROR_OPERATION_FAILED;
-                       }
-
-                       /* Set selected language and type */
-                       if (true != g_cur_engine.pefuncs->is_valid_voice(voice->language, voice->type)) {
-                               SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail voice is NOT valid");
-                               return TTSD_ERROR_OPERATION_FAILED;
-                       }
-
-                       ttsd_config_set_default_voice(voice->language, (int)voice->type);
-
-                       g_cur_engine.default_lang = strdup(voice->language);
-                       g_cur_engine.default_vctype = voice->type;
-
-                       SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Select default voice : lang(%s), type(%d)",
-                                voice->language,  voice->type);
-
-                       __free_voice_list(voice_list);
-               } else {
-                       SLOG(LOG_ERROR, get_tag(), "[Engine ERROR] Fail to get language list : result(%d)", ret);
-                       return TTSD_ERROR_OPERATION_FAILED;
-               }
-       }
-#endif
-       g_cur_engine.is_loaded = true;
+       g_engine_info->is_loaded = true;
 
        return 0;
 }
@@ -891,35 +361,24 @@ int ttsd_engine_agent_load_current_engine()
 int ttsd_engine_agent_unload_current_engine()
 {
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       if (false == g_cur_engine.is_set) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] No Current Engine ");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Engine has already been unloaded ");
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Engine has already been unloaded ");
                return 0;
        }
 
        /* shutdown engine */
        int ret = 0;
-       ret = g_cur_engine.pefuncs->deinitialize();
+       ret = g_engine_info->callbacks->deinitialize();
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent] Fail deinitialize() : %s", __ttsd_get_engine_error_code(ret));
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent] Fail deinitialize() : %s", __ttsd_get_engine_error_code(ret));
        }
 
-       /* unload engine */
-       g_cur_engine.ttsp_unload_engine();
-
-       dlclose(g_cur_engine.handle);
-
        /* reset current engine data */
-       g_cur_engine.handle = NULL;
-       g_cur_engine.is_loaded = false;
+       g_engine_info->is_loaded = false;
 
        GSList *iter = NULL;
        ttsvoice_s* data = NULL;
@@ -929,7 +388,10 @@ int ttsd_engine_agent_unload_current_engine()
                data = iter->data;
 
                if (NULL != data) {
-                       if (NULL != data->lang)         free(data->lang);
+                       if (NULL != data->lang) {
+                               free(data->lang);
+                               data->lang = NULL;
+                       }
                        g_cur_voices = g_slist_remove(g_cur_voices, data);
                        free(data);
                        data = NULL;
@@ -938,22 +400,49 @@ int ttsd_engine_agent_unload_current_engine()
                iter = g_slist_nth(g_cur_voices, 0);
        }
 
+       SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent Success] Unload current engine");
+
        return 0;
 }
 
 bool ttsd_engine_agent_need_network()
 {
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
+       return g_engine_info->use_network;
+}
+
+bool ttsd_engine_agent_is_same_engine(const char* engine_id)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return false;
+       }
+
+       if (NULL == engine_id) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] engine_id is NULL");
+               return false;
+       }
+
+       if (NULL == g_engine_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
+               return false;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
+               return false;
        }
 
-       return g_cur_engine.need_network;
+       /* compare current engine and engine id.*/
+       if (NULL != g_engine_info->engine_uuid && 0 == strncmp(g_engine_info->engine_uuid, engine_id, strlen(engine_id))) {
+               return true;
+       }
+
+       return false;
 }
 
 bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang, int* out_type)
@@ -962,28 +451,37 @@ bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang,
                return false;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_WARN, get_tag(), "[Engine Agent WARNING] Not loaded engine");
+       if (NULL == g_engine_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
                return false;
        }
 
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Select voice : input lang(%s), input type(%d), default lang(%s), default type(%d)", 
-               lang, type, g_cur_engine.default_lang, g_cur_engine.default_vctype);
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Not loaded engine");
+               return false;
+       }
+
+       SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Select voice : input lang(%s), input type(%d), default lang(%s), default type(%d)", 
+               (NULL == lang) ? "NULL" : lang, type, (NULL == g_engine_info->default_lang) ? "NULL" : g_engine_info->default_lang, g_engine_info->default_vctype);
 
        /* case 1 : Both are default */
-       if (0 == strncmp(lang, "default", strlen("default")) && 0 == type) {
-               *out_lang = strdup(g_cur_engine.default_lang);
-               *out_type = g_cur_engine.default_vctype;
+       if (0 == strncmp(lang, "default", strlen(lang)) && 0 == type) {
+               if (NULL != g_engine_info->default_lang) {
+                       *out_lang = strdup(g_engine_info->default_lang);
+               } else {
+                       *out_lang = NULL;
+               }
+
+               *out_type = g_engine_info->default_vctype;
                return true;
        }
 
        /* Get voice list */
        GList* voice_list = NULL;
        int ret = 0;
-
-       ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, &voice_list);
+       ret = g_engine_info->callbacks->foreach_voices(__supported_voice_cb, &voice_list);
        if (0 != ret || 0 >= g_list_length(voice_list)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail to get voice list : result(%d)", ret);
                return false;
        }
 
@@ -993,7 +491,7 @@ bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang,
        GList *iter = NULL;
        voice_s* voice;
 
-       /* lang and type are not default type */
+       /* case 2 : lang and type are not default type */
        if (0 != strncmp(lang, "default", strlen("default")) && 0 != type) {
                iter = g_list_first(voice_list);
 
@@ -1013,9 +511,9 @@ bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang,
 
        } else if (0 != strncmp(lang, "default", strlen("default")) && 0 == type) {
                /* Only type is default */
-               if (0 == strncmp(lang, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang))) {
-                       *out_lang = strdup(g_cur_engine.default_lang);
-                       *out_type = g_cur_engine.default_vctype;
+               if (0 == strncmp(lang, g_engine_info->default_lang, strlen(g_engine_info->default_lang))) {
+                       *out_lang = strdup(g_engine_info->default_lang);
+                       *out_type = g_engine_info->default_vctype;
                        result = true;
                } else {
                        voice_s* voice_selected = NULL;
@@ -1026,7 +524,7 @@ bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang,
 
                                if (0 == strncmp(voice->language, lang, strlen(lang))) {
                                        voice_selected = voice;
-                                       if (voice->type == g_cur_engine.default_vctype) {
+                                       if (voice->type == g_engine_info->default_vctype) {
                                                voice_selected = voice;
                                                break;
                                        }
@@ -1042,9 +540,9 @@ bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang,
                }
        } else if (0 == strncmp(lang, "default", strlen("default")) && 0 != type) {
                /* Only lang is default */
-               if (type == g_cur_engine.default_vctype) {
-                       *out_lang = strdup(g_cur_engine.default_lang);
-                       *out_type = g_cur_engine.default_vctype;
+               if (type == g_engine_info->default_vctype) {
+                       *out_lang = strdup(g_engine_info->default_lang);
+                       *out_type = g_engine_info->default_vctype;
                        result = true;
                } else {
                        voice_s* voice_selected = NULL;
@@ -1053,137 +551,76 @@ bool ttsd_engine_select_valid_voice(const char* lang, int type, char** out_lang,
                                /* Get handle data from list */
                                voice = iter->data;
 
-                               if (0 == strncmp(voice->language, g_cur_engine.default_lang, strlen(g_cur_engine.default_lang))) {
-                                       voice_selected = voice;
-                                       if (voice->type == type) {
-                                               voice_selected = voice;
-                                               break;
-                                       }
-                               }
-                               iter = g_list_next(iter);
-                       }
-
-                       if (NULL != voice_selected) {
-                               *out_lang = strdup(voice->language);
-                               *out_type = voice_selected->type;
-                               result = true;
-                       }
-               }
-       }
-
-       if (true == result) {
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Selected voice : lang(%s), type(%d)", *out_lang, *out_type);
-       }
-
-       __free_voice_list(voice_list);
-
-       return result;
-}
-
-bool ttsd_engine_agent_is_same_engine(const char* engine_id)
-{
-       if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
-               return false;
-       }
-
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return false;
-       }
-
-       /* compare current engine and engine id.*/
-       if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) {
-               return true;
-       }
-
-       return false;
-}
-
-int ttsd_engine_agent_set_default_engine(const char* engine_id)
-{
-       if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       /* compare current engine and new engine.*/
-       if (0 == strncmp(g_cur_engine.engine_uuid, engine_id, strlen(engine_id))) {
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] new engine(%s) is the same as current engine", engine_id);
-               return 0;
-       }
-
-       bool is_engine_loaded = false;
-       char* tmp_uuid = NULL;
-       tmp_uuid = strdup(g_cur_engine.engine_uuid);
-       if (NULL == tmp_uuid) {
-                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Current engine id is NULL");
-                       return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       is_engine_loaded = g_cur_engine.is_loaded;
+                               if (0 == strncmp(voice->language, g_engine_info->default_lang, strlen(g_engine_info->default_lang))) {
+                                       voice_selected = voice;
+                                       if (voice->type == type) {
+                                               voice_selected = voice;
+                                               break;
+                                       }
+                               }
+                               iter = g_list_next(iter);
+                       }
 
-       if (true == is_engine_loaded) {
-               /* unload engine */
-               if (0 != ttsd_engine_agent_unload_current_engine()) {
-                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent Error] fail to unload current engine");
+                       if (NULL != voice_selected) {
+                               *out_lang = strdup(voice->language);
+                               *out_type = voice_selected->type;
+                               result = true;
+                       }
                }
        }
 
-       /* change current engine */
-       if (0 != __internal_set_current_engine(engine_id)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set current engine. Recovery origin engine");
-
-               /* roll back to old current engine. */
-               __internal_set_current_engine(tmp_uuid);
-               if (true == is_engine_loaded) {
-                       ttsd_engine_agent_load_current_engine();
-               }
-
-               if (tmp_uuid != NULL)   free(tmp_uuid);
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (true == result) {
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Selected voice : lang(%s), type(%d)", *out_lang, *out_type);
        }
 
-       if (true == is_engine_loaded) {
-               /* load engine */
-               if (0 != ttsd_engine_agent_load_current_engine()) {
-                       SLOG(LOG_ERROR, get_tag(), "[Engine Agent Error] Fail to load new engine. Recovery origin engine");
+       __free_voice_list(voice_list);
 
-                       /* roll back to old current engine. */
-                       __internal_set_current_engine(tmp_uuid);
-                       if (true == is_engine_loaded) {
-                               ttsd_engine_agent_load_current_engine();
-                       }
+       return result;
+}
 
-                       if (tmp_uuid != NULL)   free(tmp_uuid);
-                       return TTSD_ERROR_OPERATION_FAILED;
-               } else {
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] load new engine : %s", engine_id);
-               }
-       }
 
-       if (tmp_uuid != NULL)   free(tmp_uuid);
-       return 0;
-}
 
 int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
 {
+       if (NULL == language) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] language is NULL");
+               return false;
+       }
+
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (NULL == g_engine_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] g_engine_info is NULL");
+               return false;
        }
 
-       if (false == g_cur_engine.pefuncs->is_valid_voice(language, vctype)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice is NOT valid !!");
-               return TTSD_ERROR_INVALID_VOICE;
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
        int ret = -1;
+       bool is_valid = false;
+       ret = g_engine_info->callbacks->is_valid_voice(language, vctype, &is_valid);
+       if (0 == ret) {
+               if (true == is_valid) {
+                       SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Current voice is valid : lang(%s), type(%d)", 
+                               (NULL == g_engine_info->default_lang) ? "NULL" : g_engine_info->default_lang, g_engine_info->default_vctype);
+               } else {
+                       SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Current voice is invalid : lang(%s), type(%d)",
+                               (NULL == g_engine_info->default_lang) ? "NULL" : g_engine_info->default_lang, g_engine_info->default_vctype);
+
+                       return TTSD_ERROR_OPERATION_FAILED;
+               }
+       } else {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail(Engine ERROR) : %s", __ttsd_get_engine_error_code(ret));
+               return ret;
+       }
+
+
        GSList *iter = NULL;
        ttsvoice_s* data = NULL;
 
@@ -1194,26 +631,24 @@ int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
                data = iter->data;
 
                if (NULL == data) {
-                       SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice data is NULL");
+                       SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Voice data is NULL");
                        return TTSD_ERROR_OPERATION_FAILED;
                }
 
+               if (NULL != data->lang) {
                if (0 == strcmp(data->lang, language) && data->type == vctype) {
                        data->is_default = true;
                        if (0 == data->client_ref_count) {
                                /* load voice */
-                               if (NULL != g_cur_engine.pefuncs->load_voice) {
-                                       ret = g_cur_engine.pefuncs->load_voice(data->lang, data->type);
+                                       ret = g_engine_info->callbacks->load_voice(data->lang, data->type);
                                        if (0 == ret) {
-                                               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] load voice : lang(%s), type(%d)", 
+                                               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] load voice : lang(%s), type(%d)", 
                                                        data->lang, data->type);
                                                data->is_loaded = true;
                                        } else {
-                                               SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
+                                               SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
                                                        data->lang, data->type, __ttsd_get_engine_error_code(ret));
                                        }
-                               } else {
-                                       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Load voice of engine function is NULL");
                                }
                        }
                        break;
@@ -1234,26 +669,22 @@ int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
                data = iter->data;
 
                if (NULL == data) {
-                       SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Voice data is NULL");
+                       SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Voice data is NULL");
                        return TTSD_ERROR_OPERATION_FAILED;
                }
 
-               if (0 == strcmp(data->lang, g_cur_engine.default_lang) && data->type == g_cur_engine.default_vctype) {
+               if (0 == strcmp(data->lang, g_engine_info->default_lang) && data->type == g_engine_info->default_vctype) {
                        data->is_default = false;
                        if (0 == data->client_ref_count) {
                                /* Unload voice */
-                               if (NULL != g_cur_engine.pefuncs->unload_voice) {
-                                       ret = g_cur_engine.pefuncs->unload_voice(data->lang, data->type);
-                                       if (0 == ret) {
-                                               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
-                                                       data->lang, data->type);
-                                               data->is_loaded = false;
-                                       } else {
-                                               SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
-                                                       data->lang, data->type, __ttsd_get_engine_error_code(ret));
-                                       }
+                               ret = g_engine_info->callbacks->unload_voice(data->lang, data->type);
+                               if (0 == ret) {
+                                       SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
+                                               data->lang, data->type);
+                                       data->is_loaded = false;
                                } else {
-                                       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Unload voice of engine function is NULL");
+                                       SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
+                                               data->lang, data->type, __ttsd_get_engine_error_code(ret));
                                }
                        }
                        break;
@@ -1263,17 +694,20 @@ int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
                iter = g_slist_next(iter);
        }
 
-       if (NULL != g_cur_engine.default_lang)  free(g_cur_engine.default_lang);
+       if (NULL != g_engine_info->default_lang) {
+               free(g_engine_info->default_lang);
+               g_engine_info->default_lang = NULL;
+       }
 
-       g_cur_engine.default_lang = strdup(language);
-       g_cur_engine.default_vctype = vctype;
+       g_engine_info->default_lang = strdup(language);
+       g_engine_info->default_vctype = vctype;
 
 #ifdef ENGINE_AGENT_DEBUG
        ttsd_print_voicelist();
 #endif
 
-       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set default voice : lang(%s), type(%d)",
-               g_cur_engine.default_lang, g_cur_engine.default_vctype);
+       SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Set default voice : lang(%s), type(%d)",
+               g_engine_info->default_lang, g_engine_info->default_vctype);
 
        return 0;
 }
@@ -1281,11 +715,11 @@ int ttsd_engine_agent_set_default_voice(const char* language, int vctype)
 int ttsd_engine_agent_set_default_speed(int speed)
 {
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       g_cur_engine.default_speed = speed;
+       g_engine_info->default_speed = speed;
 
        return 0;
 }
@@ -1293,38 +727,84 @@ int ttsd_engine_agent_set_default_speed(int speed)
 int ttsd_engine_agent_set_default_pitch(int pitch)
 {
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (NULL == g_engine_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No engine info");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
-       if (NULL == g_cur_engine.pefuncs->set_pitch) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not support pitch");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
-       int ret = g_cur_engine.pefuncs->set_pitch(pitch);
+       int ret = g_engine_info->callbacks->set_pitch(pitch);
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)",
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)",
                         pitch, __ttsd_get_engine_error_code(ret));
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       g_cur_engine.default_pitch = pitch;
+       g_engine_info->default_pitch = pitch;
 
+       SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Set pitch(%d)", pitch);
        return 0;
 }
 
+int ttsd_engine_agent_is_credential_needed(int uid, bool* credential_needed)
+{
+       if (NULL == credential_needed) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid Parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (NULL == g_engine_info->callbacks->need_app_credential) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not support to check app credential");
+               return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
+       }
+
+       bool result = false;
+       result = g_engine_info->callbacks->need_app_credential();
+       *credential_needed = result;
+
+       SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Need app credential, credential_needed(%d)", *credential_needed);
+       return TTSD_ERROR_NONE;
+}
+
 /******************************************************************************************
 * TTS Engine Interfaces for client
 *******************************************************************************************/
 
 int ttsd_engine_load_voice(const char* lang, const int vctype)
 {
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL == lang) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No language parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
        /* 1. Find voice info */
        int ret = -1;
        GSList *iter = NULL;
@@ -1336,8 +816,8 @@ int ttsd_engine_load_voice(const char* lang, const int vctype)
                data = iter->data;
 
                if (NULL != data) {
-                       if (0 == strcmp(data->lang, lang) && data->type == vctype) {
-                               SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
+                       if (NULL != data->lang && 0 == strcmp(data->lang, lang) && data->type == vctype) {
+                               SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
                                         data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
                                break;
                        }
@@ -1349,34 +829,30 @@ int ttsd_engine_load_voice(const char* lang, const int vctype)
        }
 
        if (NULL == data) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       /* 2. increse ref count */
+       /* 2. increase ref count */
        data->client_ref_count++;
 
        /* 3. if ref count change 0 to 1 and not default, load voice */
        if (1 == data->client_ref_count && false == data->is_default) {
                /* load voice */
-               if (NULL != g_cur_engine.pefuncs->load_voice) {
-                       ret = g_cur_engine.pefuncs->load_voice(data->lang, data->type);
-                       if (0 == ret) {
-                               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Load voice : lang(%s), type(%d)", 
-                                       data->lang, data->type);
-                               data->is_loaded = true;
-                       } else {
-                               SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
-                                       data->lang, data->type, __ttsd_get_engine_error_code(ret));
-
-                               return TTSD_ERROR_OPERATION_FAILED;
-                       }
+               ret = g_engine_info->callbacks->load_voice(data->lang, data->type);
+               if (0 == ret) {
+                       SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Load voice : lang(%s), type(%d)", 
+                               data->lang, data->type);
+                       data->is_loaded = true;
                } else {
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Load voice of engine function is NULL");
+                       SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to load voice : lang(%s), type(%d), result(%s)",
+                               data->lang, data->type, __ttsd_get_engine_error_code(ret));
+
+                       return TTSD_ERROR_OPERATION_FAILED;
                }
        } else {
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Not load voice : default voice(%d) or ref count(%d)",
-                       data->is_default, data->client_ref_count);
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Not load voice : default voice(%d) or ref count(%d)",
+               data->is_default, data->client_ref_count);
        }
 
 #ifdef ENGINE_AGENT_DEBUG
@@ -1388,6 +864,21 @@ int ttsd_engine_load_voice(const char* lang, const int vctype)
 
 int ttsd_engine_unload_voice(const char* lang, const int vctype)
 {
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL == lang) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No language parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
        /* 1. Find voice info */
        int ret = -1;
        GSList *iter = NULL;
@@ -1399,8 +890,8 @@ int ttsd_engine_unload_voice(const char* lang, const int vctype)
                data = iter->data;
 
                if (NULL != data) {
-                       if (0 == strcmp(data->lang, lang) && data->type == vctype) {
-                               SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
+                       if (NULL != data->lang && 0 == strcmp(data->lang, lang) && data->type == vctype) {
+                               SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Find voice : default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
                                         data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
                                break;
                        }
@@ -1412,34 +903,30 @@ int ttsd_engine_unload_voice(const char* lang, const int vctype)
        }
 
        if (NULL == data) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] This voice is not supported voice : lang(%s) type(%d)", lang, vctype);
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       /* 2. Decrese ref count */
+       /* 2. Decrease ref count */
        data->client_ref_count--;
 
        /* 3. if ref count change 0 and not default, load voice */
        if (0 == data->client_ref_count && false == data->is_default) {
-               /* load voice */
-               if (NULL != g_cur_engine.pefuncs->unload_voice) {
-                       ret = g_cur_engine.pefuncs->unload_voice(data->lang, data->type);
-                       if (0 == ret) {
-                               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
-                                       data->lang, data->type);
-                               data->is_loaded = false;
-                       } else {
-                               SECURE_SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
-                                       data->lang, data->type, __ttsd_get_engine_error_code(ret));
-
-                               return TTSD_ERROR_OPERATION_FAILED;
-                       }
+               /* unload voice */
+               ret = g_engine_info->callbacks->unload_voice(data->lang, data->type);
+               if (0 == ret) {
+                       SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent SUCCESS] Unload voice : lang(%s), type(%d)", 
+                               data->lang, data->type);
+                       data->is_loaded = false;
                } else {
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent ERROR] Unload voice of engine function is NULL");
+                       SECURE_SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to unload voice : lang(%s), type(%d), result(%s)",
+                               data->lang, data->type, __ttsd_get_engine_error_code(ret));
+
+                       return TTSD_ERROR_OPERATION_FAILED;
                }
        } else {
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Not unload voice : default voice(%d) or ref count(%d)",
-                       data->is_default, data->client_ref_count);
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Not unload voice : default voice(%d) or ref count(%d)",
+               data->is_default, data->client_ref_count);
        }
 
 #ifdef ENGINE_AGENT_DEBUG
@@ -1448,85 +935,88 @@ int ttsd_engine_unload_voice(const char* lang, const int vctype)
        return 0;
 }
 
-int ttsd_engine_start_synthesis(const char* lang, int vctype, const char* text, int speed, void* user_param)
+int ttsd_engine_start_synthesis(const char* lang, int vctype, const char* text, int speed, const char* appid, const char* credential, void* user_param)
 {
+       if (NULL == lang || NULL == text) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
        /* select voice for default */
        char* temp_lang = NULL;
        int temp_type;
        if (true != ttsd_engine_select_valid_voice(lang, vctype, &temp_lang, &temp_type)) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to select default voice");
-               if (NULL != temp_lang)  free(temp_lang);
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to select default voice");
+               if (NULL != temp_lang) {
+                       free(temp_lang);
+                       temp_lang = NULL;
+               }
                return TTSD_ERROR_INVALID_VOICE;
        } else {
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine Agent] Start synthesis : language(%s), type(%d), speed(%d), text(%s)", 
-                       temp_lang, temp_type, speed, text);
-       }
-
-       if (NULL == g_cur_engine.pefuncs->start_synth) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] start_synth() of engine is NULL!!");
-               if (NULL != temp_lang)  free(temp_lang);
-               return TTSD_ERROR_OPERATION_FAILED;
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent] Start synthesis : language(%s), type(%d), speed(%d), text(%s), credential(%s)", 
+                       (NULL == temp_lang) ? "NULL" : temp_lang, temp_type, speed, (NULL == text) ? "NULL" : text, (NULL == credential) ? "NULL" : credential);
        }
 
        int temp_speed;
 
        if (0 == speed) {
-               temp_speed = g_cur_engine.default_speed;
+               temp_speed = g_engine_info->default_speed;
        } else {
                temp_speed = speed;
        }
 
        /* synthesize text */
        int ret = 0;
-       ret = g_cur_engine.pefuncs->start_synth(temp_lang, temp_type, text, temp_speed, user_param);
+       ret = g_engine_info->callbacks->start_synth(temp_lang, temp_type, text, temp_speed, appid, credential, user_param);
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] ***************************************");
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] * synthesize error : %s *", __ttsd_get_engine_error_code(ret));
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] ***************************************");
-               if (NULL != temp_lang)  free(temp_lang);
-               return TTSD_ERROR_OPERATION_FAILED;
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] ***************************************");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] * synthesize error : %s *", __ttsd_get_engine_error_code(ret));
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] ***************************************");
+               if (NULL != temp_lang) {
+                       free(temp_lang);
+                       temp_lang = NULL;
+               }
+               return ret;
        }
 
-       if (NULL != temp_lang)  free(temp_lang);
+       if (NULL != temp_lang)  {
+               free(temp_lang);
+               temp_lang = NULL;
+       }
        return 0;
 }
 
 int ttsd_engine_cancel_synthesis()
 {
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
-       }
-
-       if (NULL == g_cur_engine.pefuncs->cancel_synth) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] cancel_synth() of engine is NULL!!");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
+       SLOG(LOG_INFO, tts_tag(), "[Engine Agent] Cancel synth");
        /* stop synthesis */
        int ret = 0;
-       ret = g_cur_engine.pefuncs->cancel_synth();
+       ret = g_engine_info->callbacks->cancel_synth();
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] fail cancel synthesis : %s", __ttsd_get_engine_error_code(ret));
-               return TTSD_ERROR_OPERATION_FAILED;
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] fail cancel synthesis : %s", __ttsd_get_engine_error_code(ret));
        }
 
-       return 0;
+       return ret;
 }
 
 bool __supported_voice_cb(const char* language, int type, void* user_data)
@@ -1534,13 +1024,13 @@ bool __supported_voice_cb(const char* language, int type, void* user_data)
        GList** voice_list = (GList**)user_data;
 
        if (NULL == language || NULL == voice_list) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!");
                return false;
        }
 
        voice_s* voice = calloc(1, sizeof(voice_s));
        if (NULL == voice) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to allocate memory");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
                return false;
        }
        voice->language = strdup(language);
@@ -1553,56 +1043,165 @@ bool __supported_voice_cb(const char* language, int type, void* user_data)
 
 int ttsd_engine_get_voice_list(GList** voice_list)
 {
+       if (NULL == voice_list) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
        int ret = 0;
-       ret = g_cur_engine.pefuncs->foreach_voices(__supported_voice_cb, (void*)voice_list);
+       ret = g_engine_info->callbacks->foreach_voices(__supported_voice_cb, (void*)voice_list);
        if (0 != ret) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to get voice list : %s", __ttsd_get_engine_error_code(ret));
-               return TTSD_ERROR_OPERATION_FAILED;
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get voice list : %s", __ttsd_get_engine_error_code(ret));
        }
 
-       return 0;
+       return ret;
 }
 
 int ttsd_engine_get_default_voice(char** lang, int* vctype)
 {
        if (false == g_agent_init) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not Initialized");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
-       if (false == g_cur_engine.is_loaded) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Not loaded engine");
-               return TTSD_ERROR_OPERATION_FAILED;
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
        }
 
        if (NULL == lang || NULL == vctype) {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] BAD Parameter");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] BAD Parameter");
                return TTSD_ERROR_INVALID_PARAMETER;
        }
 
-       if (NULL != g_cur_engine.default_lang) {
-               *lang = strdup(g_cur_engine.default_lang);
-               *vctype = g_cur_engine.default_vctype;
+       if (NULL != g_engine_info->default_lang) {
+               *lang = strdup(g_engine_info->default_lang);
+               *vctype = g_engine_info->default_vctype;
 
-               SECURE_SLOG(LOG_DEBUG, get_tag(), "[Engine] Get default voice : language(%s), type(%d)", *lang, *vctype);
+               SECURE_SLOG(LOG_DEBUG, tts_tag(), "[Engine] Get default voice : language(%s), type(%d)", *lang, *vctype);
        } else {
-               SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Default voice is NULL");
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Default voice is NULL");
                return TTSD_ERROR_OPERATION_FAILED;
        }
 
        return 0;
 }
 
+int ttsd_engine_set_private_data(const char* key, const char* data)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL == key) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (NULL == g_engine_info->callbacks->private_data_set) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not supported feature");
+               return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
+       }
+
+       int ret = g_engine_info->callbacks->private_data_set(key, data);
+
+       if (0 != ret) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to set private data(%d)", ret);
+       }
+
+       return ret;
+}
+
+int ttsd_engine_get_private_data(const char* key, char** data)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL == key || NULL == data) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid parameter");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+
+       if (NULL == g_engine_info->callbacks->private_data_requested) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not supported feature");
+               return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
+       }
+
+       char* temp = NULL;
+       int ret = 0;
+       ret = g_engine_info->callbacks->private_data_requested(key, &temp);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get private data(%d)", ret);
+       }
+
+       if (NULL == temp)
+               *data = strdup("NULL");
+       else
+               *data = strdup(temp);
+
+       return ret;
+}
+
+int ttsd_engine_check_app_agreed(const char* appid, bool* is_agreed)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] No loaded engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL == appid || NULL == is_agreed) {
+               SLOG(LOG_WARN, tts_tag(), "[Engine Agent WARNING] Invalid parameter, appid is NULL");
+               return TTSD_ERROR_NONE;
+       }
+
+
+       if (NULL == g_engine_info->callbacks->check_app_agreed) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not supported feature");
+               return TTSD_ERROR_NOT_SUPPORTED_FEATURE;
+       }
+
+       int ret = 0;
+       bool tmp = true; // default value is true until now
+       ret = g_engine_info->callbacks->check_app_agreed(appid, &tmp);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to check app agreed(%d)", ret);
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       *is_agreed = tmp;
+
+       return ret;
+}
+
 void __free_voice_list(GList* voice_list)
 {
        GList *iter = NULL;
@@ -1617,8 +1216,12 @@ void __free_voice_list(GList* voice_list)
                        data = iter->data;
 
                        if (NULL != data) {
-                               if (NULL != data->language)     free(data->language);
+                               if (NULL != data->language) {
+                                       free(data->language);
+                                       data->language = NULL;
+                               }
                                free(data);
+                               data = NULL;
                        }
 
                        voice_list = g_list_remove_link(voice_list, iter);
@@ -1631,54 +1234,15 @@ void __free_voice_list(GList* voice_list)
 /*
 * TTS Engine Callback Functions                                                                                        `                                 *
 */
-bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, ttsp_audio_type_e audio_type, int rate, void *user_data)
-{
-       g_result_cb(event, data, data_size, audio_type, rate, user_data);
-       return true;
-}
 
 /* function for debugging */
-int ttsd_print_enginelist()
-{
-       GList *iter = NULL;
-       ttsengine_info_s *data = NULL;
-
-       if (g_list_length(g_engine_list) > 0) {
-               iter = g_list_first(g_engine_list);
-
-               SLOG(LOG_DEBUG, get_tag(), "----- engine list -----");
-
-               int i = 1;
-               while (NULL != iter) {
-                       data = iter->data;
-
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "[%dth]", i);
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "engine uuid : %s", data->engine_uuid);
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "engine name : %s", data->engine_name);
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "engine path : %s", data->engine_path);
-                       SECURE_SLOG(LOG_DEBUG, get_tag(), "setting ug path : %s", data->setting_ug_path);
-
-                       iter = g_list_next(iter);
-                       i++;
-               }
-               SLOG(LOG_DEBUG, get_tag(), "-----------------------");
-               SLOG(LOG_DEBUG, get_tag(), "  ");
-       } else {
-               SLOG(LOG_DEBUG, get_tag(), "----- engine list -----");
-               SLOG(LOG_DEBUG, get_tag(), "No Engine in directory");
-               SLOG(LOG_DEBUG, get_tag(), "-----------------------");
-       }
-
-       return 0;
-}
-
 int ttsd_print_voicelist()
 {
        /* Test log */
        GSList *iter = NULL;
        ttsvoice_s* data = NULL;
 
-       SLOG(LOG_DEBUG, get_tag(), "=== Voice list ===");
+       SLOG(LOG_DEBUG, tts_tag(), "@@@ Voice list @@@");
 
        if (g_slist_length(g_cur_voices) > 0) {
                /* Get a first item */
@@ -1690,11 +1254,11 @@ int ttsd_print_voicelist()
                        data = iter->data;
 
                        if (NULL == data || NULL == data->lang) {
-                               SLOG(LOG_ERROR, get_tag(), "[ERROR] Data is invalid");
+                               SLOG(LOG_ERROR, tts_tag(), "[ERROR] Data is invalid");
                                return 0;
                        }
 
-                       SLOG(LOG_DEBUG, get_tag(), "[%dth] default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
+                       SLOG(LOG_DEBUG, tts_tag(), "[%dth] default(%d) loaded(%d) ref(%d) lang(%s) type(%d)",
                                 i, data->is_default, data->is_loaded,  data->client_ref_count, data->lang, data->type);
 
                        /*Get next item*/
@@ -1703,7 +1267,120 @@ int ttsd_print_voicelist()
                }
        }
 
-       SLOG(LOG_DEBUG, get_tag(), "==================");
+       SLOG(LOG_DEBUG, tts_tag(), "@@@@@");
 
        return 0;
-}
\ No newline at end of file
+}
+
+static int __internal_get_engine_info(ttse_request_callback_s* callback)
+{
+       SLOG(LOG_DEBUG, tts_tag(), "[Engine Agent DEBUG] internal get engine info");
+
+       if (NULL == callback) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL == callback->get_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Invalid engine");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (0 != callback->get_info(&(g_engine_info->engine_uuid), &(g_engine_info->engine_name), &(g_engine_info->engine_setting_path), &(g_engine_info->use_network))) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to get engine info");
+               return TTSD_ERROR_ENGINE_NOT_FOUND;
+       }
+
+       if (NULL != g_engine_info->engine_path) {
+               free(g_engine_info->engine_path);
+               g_engine_info->engine_path = NULL;
+       }
+       g_engine_info->engine_path = strdup("empty");
+       g_engine_info->is_loaded = false;
+
+       if (NULL != g_engine_info->callbacks) {
+               free(g_engine_info->callbacks);
+               g_engine_info->callbacks = NULL;
+       }
+       g_engine_info->callbacks = (tts_engine_callback_s*)calloc(1, sizeof(tts_engine_callback_s));
+       if (NULL == g_engine_info->callbacks) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Fail to allocate memory");
+               return TTSD_ERROR_OUT_OF_MEMORY;
+       }
+
+       g_engine_info->callbacks->get_info = callback->get_info;
+       g_engine_info->callbacks->initialize = callback->initialize;
+       g_engine_info->callbacks->deinitialize = callback->deinitialize;
+       g_engine_info->callbacks->foreach_voices = callback->foreach_voices;
+       g_engine_info->callbacks->is_valid_voice = callback->is_valid_voice;
+       g_engine_info->callbacks->set_pitch = callback->set_pitch;
+       g_engine_info->callbacks->load_voice = callback->load_voice;
+       g_engine_info->callbacks->unload_voice = callback->unload_voice;
+       g_engine_info->callbacks->start_synth = callback->start_synth;
+       g_engine_info->callbacks->cancel_synth = callback->cancel_synth;
+       g_engine_info->callbacks->check_app_agreed = callback->check_app_agreed;
+       g_engine_info->callbacks->need_app_credential = callback->need_app_credential;
+
+       g_engine_info->callbacks->private_data_set = NULL;
+       g_engine_info->callbacks->private_data_requested = NULL;
+
+       SLOG(LOG_DEBUG, tts_tag(), "--- Valid Engine ---");
+       SLOG(LOG_DEBUG, tts_tag(), "Engine uuid : %s", g_engine_info->engine_uuid);
+       SLOG(LOG_DEBUG, tts_tag(), "Engine name : %s", g_engine_info->engine_name);
+       SLOG(LOG_DEBUG, tts_tag(), "Engine path : %s", g_engine_info->engine_path);
+       SLOG(LOG_DEBUG, tts_tag(), "Engine setting path : %s", g_engine_info->engine_setting_path);
+       SLOG(LOG_DEBUG, tts_tag(), "Use network : %s", g_engine_info->use_network ? "true" : "false");
+       SLOG(LOG_DEBUG, tts_tag(), "--------------------");
+       SLOG(LOG_DEBUG, tts_tag(), "  ");
+
+       return TTSD_ERROR_NONE;
+
+}
+
+
+/** Set callbacks of the current engine */
+int ttsd_engine_agent_set_private_data_set_cb(ttse_private_data_set_cb callback)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (NULL == g_engine_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] The engine is not valid");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       g_engine_info->callbacks->private_data_set = callback;
+
+       return TTSD_ERROR_NONE;
+}
+
+int ttsd_engine_agent_set_private_data_requested_cb(ttse_private_data_requested_cb callback)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not Initialized");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       if (NULL == g_engine_info) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] The engine is not valid");
+               return TTSD_ERROR_INVALID_PARAMETER;
+       }
+
+       if (false == g_engine_info->is_loaded) {
+               SLOG(LOG_ERROR, tts_tag(), "[Engine Agent ERROR] Not loaded engine");
+               return TTSD_ERROR_OPERATION_FAILED;
+       }
+
+       g_engine_info->callbacks->private_data_requested = callback;
+
+       return TTSD_ERROR_NONE;
+}
+
+