Refactor prepare/unprepare logic with tts_core 88/246888/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Fri, 30 Oct 2020 03:03:17 +0000 (12:03 +0900)
committerSuyeon Hwang <stom.hwang@samsung.com>
Thu, 5 Nov 2020 03:29:11 +0000 (12:29 +0900)
This patch moves core logic of prepare/unprepare into tts_core.c/h.

Change-Id: Ib64b862845aa6fc8b0f6a69847066a1ae7e691e2
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
client/tts.c
client/tts_client.c
client/tts_client.h
client/tts_core.c
client/tts_core.h
client/tts_dbus.c

index 2ccd66546f254b7ffeb052d62438938d53cc668a..ff6427cb10114c3dd35619fe8c8f9fb394c47c13 100644 (file)
@@ -40,7 +40,6 @@ static int g_max_text_size = -1;
 
 static Ecore_Timer* g_check_state_timer = NULL;
 static Ecore_Timer* g_notify_error_timer = NULL;
-static Ecore_Timer* g_prepare_timer = NULL;
 
 /* for repetition */
 static char* g_language = NULL;
@@ -48,24 +47,19 @@ static char* g_language = NULL;
 static int g_voice_type = -1;
 
 static int g_speed = -1;
-static int g_retry_cnt = 0;
 
 /* for checking engine update */
 static pkgmgr_client* g_pkgmgr = NULL;
 static char* g_pkgmgr_status = NULL;
-static char* g_engine_name = NULL;
-static char g_engine_appid[256];
 static int g_engine_update_status = 0;
 static pthread_mutex_t g_pkgmgr_mutex = PTHREAD_MUTEX_INITIALIZER;
 static Ecore_Thread* g_pkgmgr_thread = NULL;
 static volatile bool g_is_finished_pkgmgr_thread = false;
-static bool __is_engine_launched(const char* appid);
 
 /* Function definition */
 static Eina_Bool __tts_notify_state_changed(void *data);
 static Eina_Bool __tts_notify_error(void *data);
 int __tts_cb_error(int uid, tts_error_e reason, int utt_id, char* err_msg);
-int __tts_recheck_screen_reader();
 static void __start_reprepare_thread(void* data, Ecore_Thread* thread);
 static void __end_reprepare_thread(void* data, Ecore_Thread* thread);
 static void __cancel_reprepare_thread(void* data, Ecore_Thread* thread);
@@ -134,6 +128,25 @@ static int __tts_convert_config_error_code(tts_config_error_e code)
        return code;
 }
 
+static int __tts_recheck_screen_reader()
+{
+       SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Check screen reader again");
+
+       int ret = -1;
+       int screen_reader = 0;
+
+       ret = vconf_get_bool(TTS_ACCESSIBILITY_KEY, &screen_reader);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get screen reader vconf(%d)", ret);
+               return TTS_ERROR_INVALID_STATE;
+       } else {
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] Current screen reader status(%d)", screen_reader);
+               g_screen_reader = (bool)screen_reader;
+       }
+
+       return TTS_ERROR_NONE;
+}
+
 //LCOV_EXCL_START
 void __tts_config_voice_changed_cb(const char* before_lang, int before_voice_type, const char* language, int voice_type, bool auto_voice, void* user_data)
 {
@@ -265,36 +278,37 @@ static int __pkgmgr_status_cb(uid_t target_uid, int req_id, const char *type, co
        // type (the type of the pkgname)
        SLOG(LOG_INFO, TAG_TTSC, "[INFO] pkgmgr status cb is invoked. pkgname(%s), type(%s), key(%s), val(%s)", pkgname, type, key, val);
 
-       if (NULL == g_engine_name) {
+       const char* engine_name = tts_core_get_engine_name();
+       if (NULL == engine_name) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] engine name is NULL");
                return 0;
        }
 
-       if (0 != strncmp(g_engine_name, pkgname, strlen(g_engine_name))) {
+       if (0 != strncmp(engine_name, pkgname, strlen(engine_name))) {
                SLOG(LOG_DEBUG, TAG_TTSC, "[WARN] this is not tts engine");
                return 0;
        } else {
                if (key) {
                        if (0 == strncmp(key, "start", strlen(key))) {
-                       if (NULL != g_pkgmgr_status) {
-                               free(g_pkgmgr_status);
-                               g_pkgmgr_status = NULL;
-                       }
+                               if (NULL != g_pkgmgr_status) {
+                                       free(g_pkgmgr_status);
+                                       g_pkgmgr_status = NULL;
+                               }
 
-                       if (val) {
-                               g_pkgmgr_status = strdup(val);
-                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] pkgmgr status. key(%s), status(%s)", key, g_pkgmgr_status);
+                               if (val) {
+                                       g_pkgmgr_status = strdup(val);
+                                       SLOG(LOG_INFO, TAG_TTSC, "[INFO] pkgmgr status. key(%s), status(%s)", key, g_pkgmgr_status);
 
-                               if ((0 == strncmp(val, "update", strlen(val) || 0 == strncmp(val, "uninstall", strlen(val))))) {
-                               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] start to install.");
-                               g_engine_update_status = 1;
-                       }
-                       }
+                                               if ((0 == strncmp(val, "update", strlen(val) || 0 == strncmp(val, "uninstall", strlen(val))))) {
+                                               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] start to install.");
+                                               g_engine_update_status = 1;
+                                       }
+                               }
                        } else if (0 == strncmp(key, "end", strlen(key)) && val && 0 == strncmp(val, "ok", strlen(val))) {
                                if (g_pkgmgr_status) {
                                        if (0 == strncmp(g_pkgmgr_status, "install", strlen(g_pkgmgr_status)) || 0 == strncmp(g_pkgmgr_status, "update", strlen(g_pkgmgr_status))) {
-                       SLOG(LOG_ERROR, TAG_TTSC, "[INFO] finish to install");
-                       g_engine_update_status = 0;
+                                               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] finish to install");
+                                               g_engine_update_status = 0;
 
                                                free(g_pkgmgr_status);
                                                g_pkgmgr_status = NULL;
@@ -399,62 +413,15 @@ static void __pkgmgr_thread(void* data)
        return ;
 }
 
-static void __tts_get_engine_appid(tts_client_s* client, char* engine_name, char** engine_appid)
-{
-       char temp[256];
-       memset(temp, '\0', 256);
-
-       if (NULL == client) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
-               return;
-       }
-
-       if (TTS_MODE_DEFAULT == client->mode) {
-               snprintf(temp, 256, "%s", engine_name);
-       } else if (TTS_MODE_NOTIFICATION == client->mode) {
-               snprintf(temp, 256, "%s-noti", engine_name);
-       } else if (TTS_MODE_SCREEN_READER == client->mode) {
-               snprintf(temp, 256, "%s-sr", engine_name);
-       } else if (TTS_MODE_INTERRUPT == client->mode) {
-               snprintf(temp, 256, "%s-interrupt", engine_name);
-       }
-       *engine_appid = strdup(temp);
-       return;
-}
-
 static void __tts_config_engine_changed_cb(keynode_t* key, void* data)
 {
        SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine vconfkey is changed");
 
-       tts_h temp = (tts_h)data;
-
-       g_engine_name = vconf_get_str(TTS_ENGINE_DB_DEFAULT);
-       if (NULL == g_engine_name) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine name");
+       if (0 != tts_core_update_engine_name()) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set engine name into core module");
                return;
-       } else {
-               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Engine name(%s)", g_engine_name);
        }
 
-       memset(g_engine_appid, '\0', 256);
-
-       tts_client_s* client = tts_client_get(temp);
-       if (NULL == client) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
-               snprintf(g_engine_appid, 256, "%s", g_engine_name);
-               SLOG(LOG_INFO, TAG_TTSC, "[INFO] default tts engine name(%s), appid(%s)", g_engine_name, g_engine_appid);
-               return ;
-       }
-
-       char* engine_appid = NULL;
-       __tts_get_engine_appid(client, g_engine_name, &engine_appid);
-       if (engine_appid) {
-               snprintf(g_engine_appid, 256, "%s", engine_appid);
-               free(engine_appid);
-       }
-
-       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine name(%s), appid(%s)", g_engine_name, g_engine_appid);
-
        return;
 }
 
@@ -511,25 +478,15 @@ int tts_create(tts_h* tts)
 
        SLOG(LOG_INFO, TAG_TTSC, "[INFO] call ecore thread for creating pkgmgr thread");
 
-       g_engine_name = vconf_get_str(TTS_ENGINE_DB_DEFAULT);
-       if (NULL == g_engine_name) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine name");
-       } else {
-               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Engine name(%s)", g_engine_name);
-       }
-
-       memset(g_engine_appid, '\0', 256);
-       if (NULL != g_engine_name) {
-               snprintf(g_engine_appid, 256, "%s", g_engine_name);
-
-               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] engine appid(%s)", g_engine_appid);
+       if (0 != tts_core_update_engine_name()) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set engine name into core module");
+               return TTS_ERROR_OPERATION_FAILED;
        }
 
        /* Register vconfkey callback to detect engine change */
        vconf_notify_key_changed(TTS_ENGINE_DB_DEFAULT, __tts_config_engine_changed_cb, client->tts);
 
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
-       SLOG(LOG_DEBUG, TAG_TTSC, " ");
 
        return TTS_ERROR_NONE;
 }
@@ -620,11 +577,6 @@ int tts_destroy(tts_h tts)
                client->current_state = TTS_STATE_CREATED;
 
        case TTS_STATE_CREATED:
-               if (NULL != client->conn_timer) {
-                       SLOG(LOG_DEBUG, TAG_TTSC, "Connect Timer is deleted");
-                       ecore_timer_del(client->conn_timer);
-                       client->conn_timer = NULL;
-               }
                /* Unset registered callbacks */
                __tts_unset_all_callbacks(tts);
 
@@ -696,12 +648,6 @@ int tts_destroy(tts_h tts)
                ecore_timer_del(g_notify_error_timer);
                g_notify_error_timer = NULL;
        }
-       /* Delete prepare timer before destroying handle */
-       if (NULL != g_prepare_timer) {
-               ecore_timer_del(g_prepare_timer);
-               g_prepare_timer = NULL;
-       }
-
 
        tts = NULL;
 
@@ -763,18 +709,6 @@ int tts_set_mode(tts_h tts, tts_mode_e mode)
                tts_config_unset_screen_reader_callback(client->uid);
        }
 
-       memset(g_engine_appid, '\0', 256);
-       if (TTS_MODE_DEFAULT == mode) {
-               snprintf(g_engine_appid, 256, "%s", g_engine_name);
-       } else if (TTS_MODE_NOTIFICATION == mode) {
-               snprintf(g_engine_appid, 256, "%s-noti", g_engine_name);
-       } else if (TTS_MODE_SCREEN_READER == mode) {
-               snprintf(g_engine_appid, 256, "%s-sr", g_engine_name);
-       } else if (TTS_MODE_INTERRUPT == mode) {
-               snprintf(g_engine_appid, 256, "%s-interrupt", g_engine_name);
-       }
-
-       SLOG(LOG_INFO, TAG_TTSC, "[INFO] engine appid(%s)", g_engine_appid);
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
 
        return TTS_ERROR_NONE;
@@ -940,314 +874,17 @@ int tts_set_server_tts(tts_h tts, const char* credential)
 }
 // LCOV_EXCL_STOP
 
-static Eina_Bool __tts_connect_daemon(void *data)
-{
-       tts_h tts = (tts_h)data;
-       tts_client_s* client = tts_client_get(tts);
-
-       /* check handle */
-       if (NULL == client) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
-               return EINA_FALSE;
-       }
-
-       bool is_launched = __is_engine_launched(g_engine_appid);
-       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
-
-       if (false == is_launched) {
-               /* check whether engine is updating or not */
-               if (g_engine_update_status) {
-                       SLOG(LOG_ERROR, TAG_TTSC, "[DEBUG] cannot prepare due to engine update");
-                       if (NULL == client->thread) {
-                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] ecore thread run: start_reprepare_thread");
-                               client->thread = ecore_thread_run(__start_reprepare_thread, __end_reprepare_thread, __cancel_reprepare_thread, tts);
-                       }
-                       return EINA_FALSE;
-               }
-       }
-
-       /* Send hello */
-       if (0 != tts_dbus_request_hello_sync(client->uid)) {
-               return EINA_TRUE;
-       }
-
-       SLOG(LOG_INFO, TAG_TTSC, "@@@ Connect daemon");
-
-       /* do request initialize */
-       int ret = -1;
-       bool credential_needed = false;
-
-       ret = tts_dbus_request_initialize(client->uid, &credential_needed);
-
-       if (TTS_ERROR_ENGINE_NOT_FOUND == ret) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", __tts_get_error_code(ret));
-
-               client->reason = TTS_ERROR_ENGINE_NOT_FOUND;
-               client->utt_id = -1;
-
-               if (NULL != g_notify_error_timer) {
-                       ecore_timer_del(g_notify_error_timer);
-                       g_notify_error_timer = NULL;
-               }
-               g_notify_error_timer =  ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
-
-               if (client->conn_timer) {
-                       ecore_timer_del(client->conn_timer);
-                       client->conn_timer = NULL;
-               }
-               return EINA_FALSE;
-
-       } else if (TTS_ERROR_PERMISSION_DENIED == ret) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", __tts_get_error_code(ret));
-
-               client->reason = TTS_ERROR_PERMISSION_DENIED;
-               client->utt_id = -1;
-
-               if (NULL != g_notify_error_timer) {
-                       ecore_timer_del(g_notify_error_timer);
-                       g_notify_error_timer = NULL;
-               }
-               g_notify_error_timer = ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
-
-               if (client->conn_timer) {
-                       ecore_timer_del(client->conn_timer);
-                       client->conn_timer = NULL;
-               }
-               return EINA_FALSE;
-
-       } else if (TTS_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to connection. Retry to connect : %s", __tts_get_error_code(ret));
-               return EINA_TRUE;
-
-       } else {
-               /* success to connect tts-daemon */
-               client->credential_needed = credential_needed;
-               SLOG(LOG_ERROR, TAG_TTSC, "Supported options : credential(%s)", credential_needed ? "need" : "no need");
-       }
-
-       if (client->conn_timer) {
-               ecore_timer_del(client->conn_timer);
-               client->conn_timer = NULL;
-       }
-
-       client = tts_client_get(tts);
-       /* check handle */
-       if (NULL == client) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
-               return EINA_FALSE;
-       }
-
-       client->before_state = client->current_state;
-       client->current_state = TTS_STATE_READY;
-
-       if (0 != tts_core_notify_state_changed(client, client->before_state, client->current_state)) {
-               return EINA_FALSE;
-       }
-
-       SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
-
-       return EINA_FALSE;
-}
-
-int __tts_cb_hello(int uid, int ret, int credential_needed)
-{
-       tts_client_s* client = tts_client_get_by_uid(uid);
-       if (NULL == client) {
-               SLOG(LOG_ERROR, TAG_TTSC, "Fail to get TTS client or ignore this uid(%d)", uid);
-               return TTS_ERROR_OPERATION_FAILED;
-       }
-
-       if (client->hello_timer) {
-               ecore_timer_del(client->hello_timer);
-               client->hello_timer = NULL;
-       }
-
-       if (TTS_STATE_READY == client->current_state) {
-               SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts client is already READY");
-               return TTS_ERROR_NONE;
-       }
-
-       if (TTS_ERROR_ENGINE_NOT_FOUND == ret) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", __tts_get_error_code(ret));
-
-               client->reason = TTS_ERROR_ENGINE_NOT_FOUND;
-               client->utt_id = -1;
-
-               if (NULL != g_notify_error_timer) {
-                       ecore_timer_del(g_notify_error_timer);
-                       g_notify_error_timer = NULL;
-               }
-               g_notify_error_timer = ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
-
-               return TTS_ERROR_OPERATION_FAILED;
-
-       } else if (TTS_ERROR_PERMISSION_DENIED == ret) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", __tts_get_error_code(ret));
-
-               client->reason = TTS_ERROR_PERMISSION_DENIED;
-               client->utt_id = -1;
-
-               if (NULL != g_notify_error_timer) {
-                       ecore_timer_del(g_notify_error_timer);
-                       g_notify_error_timer = NULL;
-               }
-               g_notify_error_timer = ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
-
-               return TTS_ERROR_PERMISSION_DENIED;
-
-       } else if (TTS_ERROR_NONE != ret) {
-               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to connection. Retry to connect : %s", __tts_get_error_code(ret));
-               return TTS_ERROR_OPERATION_FAILED;
-
-       } else {
-               /* success to connect tts-daemon */
-               if (TTS_CREDENTIAL_NEEDED_ALREADY_INITIALIZED != credential_needed) {
-                       client->credential_needed = credential_needed;
-                       SLOG(LOG_ERROR, TAG_TTSC, "Supported options : credential(%s)", credential_needed ? "need" : "no need");
-               }
-       }
-
-       client->before_state = client->current_state;
-       client->current_state = TTS_STATE_READY;
-
-       if (NULL != g_check_state_timer) {
-               ecore_timer_del(g_check_state_timer);
-               g_check_state_timer = NULL;
-       }
-       g_check_state_timer = ecore_timer_add(0.0, __tts_notify_state_changed, client->tts);
-
-       SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
-       return TTS_ERROR_NONE;
-}
-
-static bool __is_engine_installed(const char* appid)
-{
-       app_info_h app_info = NULL;
-       int ret = app_manager_get_app_info(appid, &app_info);
-       if (APP_MANAGER_ERROR_NONE != ret || NULL == app_info) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] There is no tts engine (%s). ret(%d)", appid, ret);
-               return false;
-       } else {
-               SLOG(LOG_INFO, TAG_TTSC, "[INFO] There is tts engine (%s)", appid);
-       }
-
-       ret = app_info_destroy(app_info);
-       if (APP_MANAGER_ERROR_NONE != ret)
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy app_info. ret(%d)", ret);
-
-       return true;
-}
-
-static bool __is_engine_launched(const char* appid)
-{
-       int ret = -1;
-       bool is_installed = false;
-       bool is_running = false;
-       is_installed = __is_engine_installed(appid);
-
-       if (false == is_installed) {
-               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] tts engine(%s) is not installed", appid);
-               return false;
-       } else {
-               ret = app_manager_is_running(appid, &is_running);
-               if (APP_MANAGER_ERROR_NONE != ret) {
-                       SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to check whether appid(%s) is running or not. ret(%d)", appid, ret);
-                       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is installed(%d)", is_installed);
-                       return false;
-               } else {
-                       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is%s running. is_installed(%d)", (is_running) ? "" : " not", is_installed);
-               }
-
-               return is_running;
-       }
-}
-
-static Eina_Bool __send_hello(void *data)
-{
-       tts_h tts = (tts_h)data;
-       tts_client_s* client = tts_client_get(tts);
-
-       /* check handle */
-       if (NULL == client) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
-               g_prepare_timer = NULL;
-               return EINA_FALSE;
-       }
-
-       /* check state */
-       if (client->current_state == TTS_STATE_READY) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[INFO] TTS client has been already connected to tts service"); //LCOV_EXCL_LINE
-               SLOG(LOG_ERROR, TAG_TTSC, "@@@");
-               client->hello_timer = NULL;
-               g_prepare_timer = NULL;
-               return EINA_FALSE;
-       }
-
-       SLOG(LOG_ERROR, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", tts, client, client->uid);
-
-       bool is_launched = __is_engine_launched(g_engine_appid);
-       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
-
-       if (false == is_launched) {
-               /* If engine is NOT launched, check whether engine is updating or not */
-               if (g_engine_update_status) {
-                       SLOG(LOG_ERROR, TAG_TTSC, "[DEBUG] cannot prepare due to engine update");
-                       if (NULL == client->thread) {
-                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] ecore thread run: start_reprepare_thread");
-                               client->thread = ecore_thread_run(__start_reprepare_thread, __end_reprepare_thread, __cancel_reprepare_thread, tts);
-                       }
-                       client->hello_timer = NULL;
-                       g_prepare_timer = NULL;
-                       return EINA_FALSE;
-               }
-       }
-
-       /* Send hello */
-       int ret = tts_dbus_request_hello(client->uid);
-       if (0 != ret)  {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request hello !!"); //LCOV_EXCL_LINE
-       } else {
-               SLOG(LOG_ERROR, TAG_TTSC, "@@@ Send Hello");
-       }
-
-       g_retry_cnt++;
-       if (TTS_HELLO_RETRY_COUNT == g_retry_cnt) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Stop to send hello, retry count reaches the limit");
-               g_retry_cnt = 0;
-               client->hello_timer = NULL;
-               g_prepare_timer = NULL;
-
-               is_launched = __is_engine_launched(g_engine_appid);
-               SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
-
-               return EINA_FALSE;
-       }
-
-       if (!client->hello_timer) {
-               SLOG(LOG_ERROR, TAG_TTSC, "@@@ Call checking Hello timer callback");
-               client->hello_timer = ecore_timer_add(0.5, __send_hello, tts);
-               g_prepare_timer = NULL;
-
-               return EINA_FALSE;
-       }
-
-       return EINA_TRUE;
-}
-
 int tts_prepare(tts_h tts)
 {
        if (0 != __tts_get_feature_enabled()) {
                return TTS_ERROR_NOT_SUPPORTED;
        }
 
-       SLOG(LOG_INFO, TAG_TTSC, "@@@ Prepare TTS");
-
        tts_client_s* client = tts_client_get(tts);
 
        /* check handle */
        if (NULL == client) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not available");
-               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
                return TTS_ERROR_INVALID_PARAMETER;
        }
 
@@ -1258,18 +895,11 @@ int tts_prepare(tts_h tts)
                return TTS_ERROR_INVALID_STATE;
        }
 
-       SLOG(LOG_ERROR, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", tts, client, client->uid);
-
-       if (NULL == client->hello_timer) {
-               SLOG(LOG_ERROR, TAG_TTSC, "@@@ Call checking Hello timer callback");
-               g_retry_cnt = 0;
-               ecore_thread_main_loop_begin();
-               if (NULL != g_prepare_timer) {
-                       ecore_timer_del(g_prepare_timer);
-                       g_prepare_timer = NULL;
-               }
-               g_prepare_timer = ecore_timer_add(0.0, __send_hello, (void*)tts);
-               ecore_thread_main_loop_end();
+       SLOG(LOG_INFO, TAG_TTSC, "@@@ Prepare TTS");
+       int ret = tts_core_prepare(client);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] tts_core_prepare failed. (%s)", __tts_get_error_code(ret));
+               return ret;
        }
 
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
@@ -1284,14 +914,11 @@ int tts_prepare_sync(tts_h tts)
                return TTS_ERROR_NOT_SUPPORTED;
        }
 
-       SLOG(LOG_INFO, TAG_TTSC, "@@@ Prepare TTS");
-
        tts_client_s* client = tts_client_get(tts);
 
        /* check handle */
        if (NULL == client) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not available");
-               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
                return TTS_ERROR_INVALID_PARAMETER;
        }
 
@@ -1302,18 +929,15 @@ int tts_prepare_sync(tts_h tts)
                return TTS_ERROR_INVALID_STATE;
        }
 
-       int cnt = 0;
-       while (EINA_TRUE == __tts_connect_daemon((void*)tts) && TTS_CONNECTION_RETRY_COUNT > cnt) {
-               cnt++;
+       SLOG(LOG_INFO, TAG_TTSC, "@@@ Prepare TTS synchronously");
+       int ret = tts_core_prepare_sync(client);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] tts_core_prepare_sync failed. (%s)", __tts_get_error_code(ret));
+               return ret;
        }
 
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
 
-       if (TTS_CONNECTION_RETRY_COUNT == cnt) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to connect daemon");
-               return TTS_ERROR_OPERATION_FAILED;
-       }
-
        return TTS_ERROR_NONE;
 }
 //LCOV_EXCL_STOP
@@ -1324,8 +948,6 @@ int tts_unprepare(tts_h tts)
                return TTS_ERROR_NOT_SUPPORTED;
        }
 
-       SLOG(LOG_INFO, TAG_TTSC, "@@@ Unprepare TTS");
-
        tts_client_s* client = tts_client_get(tts);
 
        /* check handle */
@@ -1340,74 +962,32 @@ int tts_unprepare(tts_h tts)
                return TTS_ERROR_INVALID_STATE;
        }
 
-       SLOG(LOG_ERROR, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", tts, client, client->uid);
-
-       if (client->hello_timer) {
-               ecore_timer_del(client->hello_timer);
-               client->hello_timer = NULL;
-       }
+       SLOG(LOG_INFO, TAG_TTSC, "@@@ Unprepare TTS");
 
        int ret = -1;
-       int count = 0;
-
        ret = __tts_recheck_screen_reader();
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get screen reader(%d)", ret);
        }
 
-       SLOG(LOG_INFO, TAG_TTSC, "[INFO] g_screen_reader(%s), client->mode(%d)", (true == g_screen_reader) ? "True" : "False", client->mode);
-
-       bool is_prepared = false;
-       if (!(false == g_screen_reader && TTS_MODE_SCREEN_READER == client->mode)) {
-               do {
-                       ret = tts_dbus_request_finalize(client->uid);
-                       if (0 != ret) {
-                               //LCOV_EXCL_START
-                               if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
-                                       client->current_state = TTS_STATE_CREATED;
-                                       if (0 == tts_prepare_sync(tts)) {
-                                               is_prepared = true;
-                                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
-                                       }
-                               } else if (TTS_ERROR_TIMED_OUT != ret) {
-                                       SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %s", __tts_get_error_code(ret));
-                                       break;
-                               } else {
-                                       SLOG(LOG_WARN, TAG_TTSC, "[WARNING] retry finalize : %s", __tts_get_error_code(ret));
-                                       usleep(10000);
-                                       count++;
-                                       if (TTS_RETRY_COUNT == count) {
-                                               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
-                                               break;
-                                       }
-                               }
-                               //LCOV_EXCL_STOP
-                       }
-               } while (0 != ret);
-       } else {
-               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Do not request finalize : g_sr(%d) mode(%d)", g_screen_reader, client->mode);
-               ret = tts_dbus_remove_match(client->mode);
-               if (0 != ret) {
-                       SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to remove match : %s", __tts_get_error_code(ret));
-               }
+       ret = tts_core_unprepare(tts_client_get(tts), g_screen_reader);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] tts_core_unprepare is failed(%s)", __tts_get_error_code(ret));
+               return ret;
        }
 
-       client->before_state = client->current_state;
-       client->current_state = TTS_STATE_CREATED;
-
-       tts_core_notify_state_changed(client, client->before_state, client->current_state);
-
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
 
        return TTS_ERROR_NONE;
 }
 
-bool __tts_supported_voice_cb(const char* engine_id, const char* language, int type, void* user_data)
+static bool __tts_supported_voice_cb(const char* engine_id, const char* language, int type, void* user_data)
 {
-       tts_h tts = (tts_h)user_data;
+       tts_client_s* client = (tts_client_s*)user_data;
 
        /* call callback function */
-       tts_core_notify_supported_voice(tts_client_get(tts), language, type);
+       // TODO: pass return value of callback
+       tts_core_notify_supported_voice(client, language, type);
        return false;
 }
 
@@ -1417,11 +997,10 @@ int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, voi
                return TTS_ERROR_NOT_SUPPORTED;
        }
 
-       SLOG(LOG_DEBUG, TAG_TTSC, "@@@ Foreach supported voices");
+       SLOG(LOG_INFO, TAG_TTSC, "@@@ Foreach supported voices");
 
        if (NULL == tts || NULL == callback) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null");
-               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
                return TTS_ERROR_INVALID_PARAMETER;
        }
 
@@ -1430,7 +1009,6 @@ int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, voi
        /* check handle */
        if (NULL == client) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
-               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
                return TTS_ERROR_INVALID_PARAMETER;
        }
 
@@ -1444,8 +1022,7 @@ int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, voi
 
        client->supported_voice_cb = callback;
        client->supported_voice_user_data = user_data;
-
-       ret = tts_config_mgr_get_voice_list(current_engine, __tts_supported_voice_cb, client->tts);
+       ret = tts_config_mgr_get_voice_list(current_engine, __tts_supported_voice_cb, client);
 
        if (NULL != current_engine) {
                free(current_engine);
@@ -1623,25 +1200,6 @@ int tts_get_error_message(tts_h tts, char** err_msg)
        return TTS_ERROR_NONE;
 }
 
-int __tts_recheck_screen_reader()
-{
-       SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Check screen reader again");
-
-       int ret = -1;
-       int screen_reader = 0;
-
-       ret = vconf_get_bool(TTS_ACCESSIBILITY_KEY, &screen_reader);
-       if (0 != ret) {
-               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get screen reader vconf(%d)", ret);
-               return TTS_ERROR_INVALID_STATE;
-       } else {
-               SLOG(LOG_INFO, TAG_TTSC, "[INFO] Current screen reader status(%d)", screen_reader);
-               g_screen_reader = (bool)screen_reader;
-       }
-
-       return TTS_ERROR_NONE;
-}
-
 int tts_add_text(tts_h tts, const char* text, const char* language, int voice_type, int speed, int* utt_id)
 {
        SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Add text: text(%s), language(%s), type(%d)", (NULL == text) ? "NULL" : text, (NULL == language) ? "NULL" : language, voice_type);
@@ -1798,7 +1356,7 @@ int tts_add_text(tts_h tts, const char* text, const char* language, int voice_ty
                        //LCOV_EXCL_START
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -1850,7 +1408,7 @@ static void __tts_play_async(void *data)
                if (0 != ret) {
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2004,7 +1562,7 @@ int tts_play(tts_h tts)
                        //LCOV_EXCL_START
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2052,7 +1610,7 @@ static void __tts_stop_async(void *data)
                if (0 != ret) {
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2194,7 +1752,7 @@ int tts_stop(tts_h tts)
                        //LCOV_EXCL_START
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2242,7 +1800,7 @@ static void __tts_pause_async(void *data)
                if (0 != ret) {
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2385,7 +1943,7 @@ int tts_pause(tts_h tts)
                        //LCOV_EXCL_START
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2458,7 +2016,7 @@ int tts_set_private_data(tts_h tts, const char* key, const char* data)
                        //LCOV_EXCL_START
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -2522,7 +2080,7 @@ int tts_get_private_data(tts_h tts, const char* key, char** data)
                        //LCOV_EXCL_START
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -3285,7 +2843,7 @@ int tts_add_pcm(tts_h tts, int event, const void* data, unsigned int data_size,
                if (0 != ret) {
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -3359,7 +2917,7 @@ int tts_play_pcm(tts_h tts)
                if (0 != ret) {
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
@@ -3437,7 +2995,7 @@ int tts_stop_pcm(tts_h tts)
                if (0 != ret) {
                        if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
                                client->current_state = TTS_STATE_CREATED;
-                               if (0 == tts_prepare_sync(tts)) {
+                               if (0 == tts_core_prepare_sync(client)) {
                                        is_prepared = true;
                                        SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
                                }
index 438d0f3c614fae82a5f9d98cc1e2c9e66c729bc2..4e76b7c2db5ebff19bbc50d2929d974915664f54 100644 (file)
@@ -91,7 +91,6 @@ int tts_client_new(tts_h* tts)
        client->reason = 0;
        client->err_msg = NULL;
 
-       client->conn_timer = NULL;
        client->hello_timer = NULL;
 
        client->credential = NULL;
@@ -100,6 +99,11 @@ int tts_client_new(tts_h* tts)
 
        client->text_repeat = NULL;
 
+       client->thread = NULL;
+
+       client->notify_error_timer = NULL;
+       client->notify_state_timer = NULL;
+
        pthread_mutex_lock(&g_client_list_mutex);
        g_client_list = g_list_append(g_client_list, client);
        pthread_mutex_unlock(&g_client_list_mutex);
index 536fff3213680c3f76788e281eec27f3d3924653..1a6822a56a934e6a697ec8d0a5496faea079debb 100644 (file)
@@ -62,7 +62,7 @@ typedef struct {
        char*           err_msg;
 
        /* connection */
-       Ecore_Timer*    conn_timer;
+       int             prepare_count;
        Ecore_Timer*    hello_timer;
 
        /* options */
@@ -75,6 +75,10 @@ typedef struct {
 
        /* thread */
        Ecore_Thread* thread;
+
+       /* timer */
+       Ecore_Timer* notify_error_timer;
+       Ecore_Timer* notify_state_timer;
 } tts_client_s;
 
 int tts_client_new(tts_h* tts);
index 69a3d2c6ffb2b2157eacf77f69562fba1e489c05..cff606ecd159655b16189d515ffa4302184e7bee 100644 (file)
 *  limitations under the License.
 */
 
+#include <string.h>
+
+#include <app_manager.h>
 #include <dlog.h>
+#include <package-manager.h>
 
+#include "tts_internal.h"
+#include "tts_dbus.h"
 #include "tts_defs.h"
 #include "tts_core.h"
 
 /* Static variables */
+static char* g_engine_name = NULL;
+static int g_engine_update_status = 0;
+
+static pkgmgr_client* g_pkgmgr = NULL;
+
 
 /* Static functions */
 static const char* __tts_get_error_code(tts_error_e err)
@@ -43,6 +54,372 @@ static const char* __tts_get_error_code(tts_error_e err)
        return NULL;
 }
 
+static char* __get_engine_appid(int mode) {
+       char* appid = NULL;
+       appid = (char*)calloc(sizeof(char), 256);
+
+       if (NULL == appid || NULL == g_engine_name) {
+               return NULL;
+       }
+
+       memset(appid, '\0', 256);
+       if (TTS_MODE_DEFAULT == mode) {
+               snprintf(appid, 256, "%s", g_engine_name);
+       } else if (TTS_MODE_NOTIFICATION == mode) {
+               snprintf(appid, 256, "%s-noti", g_engine_name);
+       } else if (TTS_MODE_SCREEN_READER == mode) {
+               snprintf(appid, 256, "%s-sr", g_engine_name);
+       } else if (TTS_MODE_INTERRUPT == mode) {
+               snprintf(appid, 256, "%s-interrupt", g_engine_name);
+       }
+       return appid;
+}
+
+static Eina_Bool __notify_error_timer_cb(void *data)
+{
+       tts_client_s* client = (tts_client_s*)data;
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+       } else {
+               tts_core_notify_error(client, client->utt_id, client->reason);
+       }
+
+       client->notify_error_timer = NULL;
+
+       return EINA_FALSE;
+}
+
+static Eina_Bool __notify_state_timer_cb(void *data)
+{
+       tts_client_s* client = (tts_client_s*)data;
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+       } else {
+               tts_core_notify_state_changed(client, client->before_state, client->current_state);
+       }
+
+       client->notify_state_timer = NULL;
+       return EINA_FALSE;
+}
+
+static bool __is_engine_installed(const char* appid)
+{
+       app_info_h app_info = NULL;
+       int ret = app_manager_get_app_info(appid, &app_info);
+       if (APP_MANAGER_ERROR_NONE != ret || NULL == app_info) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] There is no tts engine (%s). ret(%d)", appid, ret);
+               return false;
+       } else {
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] There is tts engine (%s)", appid);
+       }
+
+       ret = app_info_destroy(app_info);
+       if (APP_MANAGER_ERROR_NONE != ret)
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy app_info. ret(%d)", ret);
+
+       return true;
+}
+
+static bool __is_engine_launched(int mode)
+{
+       int ret = -1;
+       bool is_installed = false;
+       bool is_running = false;
+
+       char* appid = __get_engine_appid(mode);
+       if (NULL == appid) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine app ID");
+               return false;
+       }
+
+       is_installed = __is_engine_installed(appid);
+       if (false == is_installed) {
+               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] tts engine(%s) is not installed", appid);
+               free(appid);
+               return false;
+       }
+
+       ret = app_manager_is_running(appid, &is_running);
+       if (APP_MANAGER_ERROR_NONE != ret) {
+               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to check whether appid(%s) is running or not. ret(%d)", appid, ret);
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is installed(%d)", is_installed);
+               free(appid);
+               return false;
+       } else {
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is %s running. is_installed(%d)", (is_running) ? "" : " not", is_installed);
+       }
+
+       free(appid);
+       return is_running;
+}
+
+static void __start_reprepare_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] start reprepare thread. engine update status(%d)", g_engine_update_status);
+
+       tts_client_s* client = (tts_client_s*)data;
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               return;
+       }
+
+       int cnt = 0;
+       while (!g_engine_update_status && cnt < 20) {
+               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] wait for starting update");
+               /* Checking handle which can be destroyed on other thread */
+               if (false == tts_client_is_valid(client->tts)) {
+                       SLOG(LOG_INFO, TAG_TTSC, "[INFO] client is already destroyed");
+                       return;
+               }
+
+               usleep(50000);
+               cnt++;
+
+               /* Checking thread is canceled or not */
+               if (ecore_thread_check(client->thread)) {
+                       SLOG(LOG_WARN, TAG_TTSC, "[WARNING] client thread is canceled. Exit");
+                       return;
+               }
+       }
+
+       SLOG(LOG_ERROR, TAG_TTSC, "[DEBUG] update status(%d)", g_engine_update_status);
+
+       while (g_engine_update_status && (NULL != g_pkgmgr)) {
+               /* Checking handle which can be destroyed on other thread */
+               if (false == tts_client_is_valid(client->tts)) {
+                       SLOG(LOG_INFO, TAG_TTSC, "[INFO] client is already destroyed");
+                       return;
+               }
+
+               usleep(200000);
+
+               /* Checking thread is canceled or not */
+               if (ecore_thread_check(client->thread)) {
+                       SLOG(LOG_WARN, TAG_TTSC, "[WARNING] client thread is canceled. Exit");
+                       return;
+               }
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] finish updating. request to prepare");
+
+       if (0 != tts_core_prepare(client)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare");
+       }
+
+       return;
+}
+
+static void __end_reprepare_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] end reprepare thread");
+
+       tts_client_s* client = (tts_client_s*)data;
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               return;
+       }
+
+       client->thread = NULL;
+}
+
+static void __cancel_reprepare_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] cancel reprepare thread");
+
+       tts_client_s* client = (tts_client_s*)data;
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               return;
+       }
+
+       client->thread = NULL;
+}
+
+static int __send_hello_msg(tts_client_s* client)
+{
+       if (NULL == client) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       /* check state */
+       if (client->current_state == TTS_STATE_READY) {
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] TTS client has been already connected to tts service"); //LCOV_EXCL_LINE
+               return TTS_ERROR_INVALID_STATE;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", client->tts, client, client->uid);
+
+       /* check service engine status */
+       bool is_launched = __is_engine_launched(client->mode);
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
+       if (false == is_launched) {
+               /* If engine is NOT launched, check whether engine is updating or not */
+               if (g_engine_update_status) {
+                       /* suyeon wait engine update */
+                       SLOG(LOG_INFO, TAG_TTSC, "[INFO] cannot prepare due to engine update");
+                       if (NULL == client->thread) {
+                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] ecore thread run: start_reprepare_thread");
+                               client->thread = ecore_thread_run(__start_reprepare_thread, __end_reprepare_thread, __cancel_reprepare_thread, client);
+                       }
+                       return TTS_ERROR_INVALID_STATE;
+               }
+       }
+
+       /* Send hello */
+       int ret = tts_dbus_request_hello(client->uid);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request hello !!"); //LCOV_EXCL_LINE
+       } else {
+               SLOG(LOG_INFO, TAG_TTSC, "@@@ Send Hello");
+       }
+
+       return TTS_ERROR_NONE;
+}
+
+static Eina_Bool __prepare_cb(void *data)
+{
+       tts_client_s* client = (tts_client_s*)data;
+
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               client->hello_timer = NULL;
+               return EINA_FALSE;
+       }
+
+       /* check state */
+       int ret = __send_hello_msg(client);
+       if (ret != TTS_ERROR_NONE) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to send hello message"); //LCOV_EXCL_LINE
+               client->hello_timer = NULL;
+               return EINA_FALSE;
+       }
+
+       client->prepare_count++;
+       if (TTS_HELLO_RETRY_COUNT == client->prepare_count) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Stop to prepare, retry count reaches the limit");
+
+               bool is_launched = __is_engine_launched(client->mode);
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
+
+               client->hello_timer = NULL;
+               return EINA_FALSE;
+       }
+
+       return EINA_TRUE;
+}
+
+static Eina_Bool __prepare_first_cb(void *data)
+{
+       /* send first hello message */
+       tts_client_s* client = (tts_client_s*)data;
+
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               client->hello_timer = NULL;
+               return EINA_FALSE;
+       }
+
+       int ret = __send_hello_msg(client);
+       if (ret != TTS_ERROR_NONE) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to sent hello message"); //LCOV_EXCL_LINE
+               client->hello_timer = NULL;
+       } else {
+               /* Set retry timer callback */
+               client->prepare_count = 0;
+               client->hello_timer = ecore_timer_add(0.5, __prepare_cb, data);
+       }
+
+       return EINA_FALSE;
+}
+
+static Eina_Bool __prepare_sync_cb(tts_client_s* client)
+{
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               client->hello_timer = NULL;
+               return EINA_FALSE;
+       }
+
+       // TODO: make function duplicated block
+       bool is_launched = __is_engine_launched(client->mode);
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
+
+       if (false == is_launched) {
+               /* check whether engine is updating or not */
+               if (g_engine_update_status) {
+                       SLOG(LOG_ERROR, TAG_TTSC, "[DEBUG] cannot prepare due to engine update");
+                       if (NULL == client->thread) {
+                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] ecore thread run: start_reprepare_thread");
+                               client->thread = ecore_thread_run(__start_reprepare_thread, __end_reprepare_thread, __cancel_reprepare_thread, client);
+                       }
+                       return EINA_FALSE;
+               }
+       }
+       // TODO: make function duplicated block
+
+       /* Send hello */
+       if (0 != tts_dbus_request_hello_sync(client->uid)) {
+               return EINA_TRUE;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "@@@ Connect daemon");
+
+       // TODO: make function duplicated block
+       /* do request initialize */
+       int ret = -1;
+       bool credential_needed = false;
+
+       ret = tts_dbus_request_initialize(client->uid, &credential_needed);
+
+       if (TTS_ERROR_ENGINE_NOT_FOUND == ret || TTS_ERROR_PERMISSION_DENIED == ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", __tts_get_error_code(ret));
+
+               client->reason = ret;
+               client->utt_id = -1;
+
+               if (NULL != client->notify_error_timer) {
+                       ecore_timer_del(client->notify_error_timer);
+               }
+               client->notify_error_timer = ecore_timer_add(0, __notify_error_timer_cb, (void*)client);
+
+               return EINA_FALSE;
+       } else if (TTS_ERROR_NONE != ret) {
+               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to connection. Retry to connect : %s", __tts_get_error_code(ret));
+               return EINA_TRUE;
+       } else {
+               /* success to connect tts-daemon */
+               client->credential_needed = credential_needed;
+               SLOG(LOG_ERROR, TAG_TTSC, "Supported options : credential(%s)", credential_needed ? "need" : "no need");
+       }
+       // TODO: make function duplicated block
+
+       /* check handle */
+       if (false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid");
+               return EINA_FALSE;
+       }
+
+       client->before_state = client->current_state;
+       client->current_state = TTS_STATE_READY;
+
+       if (0 != tts_core_notify_state_changed(client, client->before_state, client->current_state)) {
+               return EINA_FALSE;
+       }
+
+       SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+       return EINA_FALSE;
+}
+
+
 /* Public functions */
 int tts_core_notify_state_changed(tts_client_s* client, tts_state_e before_state, tts_state_e current_state)
 {
@@ -214,3 +591,187 @@ int tts_core_notify_supported_voice(tts_client_s* client, const char* language,
 
        return TTS_ERROR_NONE;
 }
+
+int tts_core_receive_hello(int uid, int ret, int credential_needed)
+{
+       tts_client_s* client = tts_client_get_by_uid(uid);
+       if (NULL == client) {
+               SLOG(LOG_ERROR, TAG_TTSC, "Fail to get TTS client or ignore this uid(%d)", uid);
+               return TTS_ERROR_OPERATION_FAILED;
+       }
+
+       if (client->hello_timer) {
+               ecore_timer_del(client->hello_timer);
+               client->hello_timer = NULL;
+       }
+
+       if (TTS_STATE_READY == client->current_state) {
+               SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts client is already READY");
+               return TTS_ERROR_NONE;
+       }
+
+       if (TTS_ERROR_ENGINE_NOT_FOUND == ret || TTS_ERROR_PERMISSION_DENIED == ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", __tts_get_error_code(ret));
+
+               client->reason = ret;
+               client->utt_id = -1;
+
+               if (NULL != client->notify_error_timer) {
+                       ecore_timer_del(client->notify_error_timer);
+               }
+               client->notify_error_timer = ecore_timer_add(0, __notify_error_timer_cb, (void*)client);
+
+               return TTS_ERROR_OPERATION_FAILED;
+       } else if (TTS_ERROR_NONE != ret) {
+               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to connection. Retry to connect : %s", __tts_get_error_code(ret));
+               return TTS_ERROR_OPERATION_FAILED;
+       } else {
+               /* success to connect tts-daemon */
+               if (TTS_CREDENTIAL_NEEDED_ALREADY_INITIALIZED != credential_needed) {
+                       client->credential_needed = credential_needed;
+                       SLOG(LOG_ERROR, TAG_TTSC, "Supported options : credential(%d)", credential_needed);
+               }
+       }
+
+       client->before_state = client->current_state;
+       client->current_state = TTS_STATE_READY;
+
+       if (NULL != client->notify_state_timer) {
+               ecore_timer_del(client->notify_state_timer);
+       }
+       client->notify_state_timer = ecore_timer_add(0, __notify_state_timer_cb, client);
+
+       SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+       return TTS_ERROR_NONE;
+}
+
+int tts_core_update_engine_name()
+{
+       if (g_engine_name) {
+               free(g_engine_name);
+               g_engine_name = NULL;
+       }
+
+       g_engine_name = vconf_get_str(TTS_ENGINE_DB_DEFAULT);
+       if (NULL == g_engine_name) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine name");
+               return TTS_ERROR_OPERATION_FAILED;
+       }
+
+       SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Engine name(%s)", g_engine_name);
+       return TTS_ERROR_NONE;
+}
+
+const char* tts_core_get_engine_name()
+{
+       return g_engine_name;
+}
+
+int tts_core_prepare(tts_client_s* client)
+{
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", client->tts, client, client->uid);
+       if (NULL == client->hello_timer) {
+               SLOG(LOG_ERROR, TAG_TTSC, "Register timer for __prepare_first_cb");
+
+               ecore_thread_main_loop_begin();
+               client->hello_timer = ecore_timer_add(0.0, __prepare_first_cb, (void*)client);
+               ecore_thread_main_loop_end();
+       } else {
+               LOGD("Client is already trying to prepare");
+       }
+
+       return TTS_ERROR_NONE;
+}
+
+int tts_core_prepare_sync(tts_client_s* client)
+{
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", client->tts, client, client->uid);
+       int cnt = 0;
+       while (EINA_TRUE == __prepare_sync_cb(client) && TTS_CONNECTION_RETRY_COUNT > cnt) {
+               cnt++;
+       }
+
+       SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+       if (TTS_CONNECTION_RETRY_COUNT == cnt) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to connect daemon");
+               return TTS_ERROR_OPERATION_FAILED;
+       }
+
+       return TTS_ERROR_NONE;
+}
+
+int tts_core_unprepare(tts_client_s* client, bool is_screen_reader_on)
+{
+       /* check handle */
+       if (NULL == client || false == tts_client_is_valid(client->tts)) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is not valid.");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%d)", client->tts, client, client->uid);
+       if (client->hello_timer) {
+               ecore_timer_del(client->hello_timer);
+               client->hello_timer = NULL;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "[INFO] screen_reader(%s), client->mode(%d)", (true == is_screen_reader_on) ? "True" : "False", client->mode);
+
+       int ret = -1;
+       int count = 0;
+       if (false == is_screen_reader_on && TTS_MODE_SCREEN_READER == client->mode) {
+               SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Do not request finalize : is_screen_reader(%d) mode(%d)", is_screen_reader_on, client->mode);
+
+               ret = tts_dbus_remove_match(client->mode);
+               if (0 != ret) {
+                       SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to remove match : %s", __tts_get_error_code(ret));
+               }
+       } else {
+               bool is_prepared = false;
+
+               do {
+                       ret = tts_dbus_request_finalize(client->uid);
+                       if (0 != ret) {
+                               //LCOV_EXCL_START
+                               if (TTS_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
+                                       client->current_state = TTS_STATE_CREATED;
+                                       if (0 == tts_core_prepare_sync(client)) {
+                                               SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_prepare_sync");
+                                               is_prepared = true;
+                                       }
+                               } else if (TTS_ERROR_TIMED_OUT != ret) {
+                                       SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %s", __tts_get_error_code(ret));
+                                       break;
+                               } else {
+                                       SLOG(LOG_WARN, TAG_TTSC, "[WARNING] retry finalize : %s", __tts_get_error_code(ret));
+                                       usleep(10000);
+                                       count++;
+                                       if (TTS_RETRY_COUNT == count) {
+                                               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
+                                               break;
+                                       }
+                               }
+                               //LCOV_EXCL_STOP
+                       }
+               } while (0 != ret);
+       }
+
+       client->before_state = client->current_state;
+       client->current_state = TTS_STATE_CREATED;
+
+       tts_core_notify_state_changed(client, client->before_state, client->current_state);
+
+       return TTS_ERROR_NONE;
+}
index c5e7d69f99ab981fad0d6bcd2ba84a51f4d7fe61..9c8b7d28f18f44caebf7270b8abbded19affe1e0 100644 (file)
@@ -21,6 +21,7 @@ extern "C" {
 
 #include "tts_client.h"
 
+// common function
 int tts_core_notify_state_changed(tts_client_s* client, tts_state_e before_state, tts_state_e current_state);
 int tts_core_notify_utt_started(tts_client_s* client, int utt_id);
 int tts_core_notify_utt_completeted(tts_client_s* client, int utt_id);
@@ -29,6 +30,17 @@ int tts_core_notify_default_voice_changed(tts_client_s* client, const char* befo
 int tts_core_notify_engine_changed(tts_client_s* client, const char* engine_id, const char* language, int voice_type, bool need_credential);
 int tts_core_notify_supported_voice(tts_client_s* client, const char* language, int voice_type);
 
+// called by tts.c
+int tts_core_update_engine_name();
+const char* tts_core_get_engine_name();
+
+int tts_core_prepare(tts_client_s* client);
+int tts_core_prepare_sync(tts_client_s* client);
+int tts_core_unprepare(tts_client_s* client, bool is_screen_reader_on);
+
+// called by tts_dbus.c
+int tts_core_receive_hello(int uid, int ret, int credential_needed);
+
 
 #ifdef __cplusplus
 }
index ee7ae99abebee12ea22f0d83ea90e2d27b78c2d1..1dcd55d4f96a9947dabf0e8375b38e0daeb163c6 100644 (file)
@@ -16,6 +16,7 @@
 #include <fcntl.h>
 #include <sys/inotify.h>
 
+#include "tts_core.h"
 #include "tts_client.h"
 #include "tts_config_mgr.h"
 #include "tts_dbus.h"
@@ -40,8 +41,6 @@ extern int __tts_cb_utt_started(int uid, int utt_id);
 
 extern int __tts_cb_utt_completed(int uid, int utt_id);
 
-extern int __tts_cb_hello(int uid, int ret, int credential_needed);
-
 
 static int __tts_dbus_add_match(int uid)
 {
@@ -162,9 +161,9 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle
                                        SLOG(LOG_INFO, TAG_TTSC, "@@ tts Get Hello message : already initialized");
                                        ret = 0;
                                } else {
-                               __tts_dbus_add_match(uid);
+                                       __tts_dbus_add_match(uid);
                                }
-                               __tts_cb_hello(uid, ret, credential_needed);
+                               tts_core_receive_hello(uid, ret, credential_needed);
                        }
 
                        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");