[ACR-1216][tts][Add tts_repeat()]
[platform/core/uifw/tts.git] / client / tts.c
index 1b07804..23cfdb2 100644 (file)
@@ -27,6 +27,7 @@
 #include "tts_dbus.h"
 #include "tts_main.h"
 
+#include "tts_internal.h"
 
 static bool g_screen_reader;
 
@@ -36,6 +37,14 @@ static bool g_err_callback_status = false;
 
 static int g_max_text_size = -1;
 
+/* for repetition */
+static char* g_language = NULL;
+
+static int g_voice_type = -1;
+
+static int g_speed = -1;
+
+
 /* Function definition */
 static Eina_Bool __tts_notify_state_changed(void *data);
 static Eina_Bool __tts_notify_error(void *data);
@@ -131,6 +140,14 @@ void __tts_config_voice_changed_cb(const char* before_lang, int before_voice_typ
                                        language, voice_type, data->default_voice_changed_user_data);
                        }
 
+                       /* Check whether language is changed or not. If it is changed, make 'text_repeat' NULL */
+                       if (0 != strncmp(before_lang, language, strlen(before_lang))) {
+                               if (NULL != data->text_repeat) {
+                                       free(data->text_repeat);
+                                       data->text_repeat = NULL;
+                               }
+                       }
+
                        /* Next item */
                        iter = g_list_next(iter);
                }
@@ -354,6 +371,11 @@ int tts_destroy(tts_h tts)
                }
        }
 
+       if (NULL != g_language) {
+               free(g_language);
+               g_language = NULL;
+       }
+
        tts = NULL;
 
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
@@ -391,7 +413,7 @@ int tts_set_mode(tts_h tts, tts_mode_e mode)
                return TTS_ERROR_INVALID_STATE;
        }
 
-       if (TTS_MODE_DEFAULT <= mode && mode <= TTS_MODE_SCREEN_READER) {
+       if (TTS_MODE_DEFAULT <= mode && mode <= TTS_MODE_INTERRUPT) {
                client->mode = mode;
        } else {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] mode is not valid : %d", mode);
@@ -528,6 +550,10 @@ int tts_set_server_tts(tts_h tts, const char* credential)
                client->credential = strdup(credential);
                if (NULL == client->credential) {
                        SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to allocate memory");
+                       if (NULL != key) {
+                               free(key);
+                               key = NULL;
+                       }
                        return TTS_ERROR_OUT_OF_MEMORY;
                }
        } else {
@@ -542,10 +568,14 @@ int tts_set_server_tts(tts_h tts, const char* credential)
        int pid = getpid();
        char* appid = NULL;
        int ret = app_manager_get_app_id(pid, &appid);
-       if (0 != ret) {
+       if (0 != ret || NULL == appid) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get appid, ret(%d), pid(%d), appid(%s)", ret, pid, appid);
                free(key);
                key = NULL;
+               if (NULL != appid) {
+                       free(appid);
+                       appid = NULL;
+               }
                return TTS_ERROR_OPERATION_FAILED;
        }
 
@@ -554,6 +584,8 @@ int tts_set_server_tts(tts_h tts, const char* credential)
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set private data, ret(%d), pid(%d), appid(%s)", ret, pid, appid);
                free(key);
                key = NULL;
+               free(appid);
+               appid = NULL;
                return ret;
        }
 
@@ -670,13 +702,52 @@ int tts_prepare(tts_h tts)
                return TTS_ERROR_INVALID_STATE;
        }
 
-       client->conn_timer = ecore_timer_add(0, __tts_connect_daemon, (void*)tts);
+       client->conn_timer = ecore_timer_add(0.02, __tts_connect_daemon, (void*)tts);
 
        SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
 
        return TTS_ERROR_NONE;
 }
 
+int tts_prepare_sync(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;
+       }
+
+       /* check state */
+       if (client->current_state != TTS_STATE_CREATED) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid State: Current state is not 'CREATED'");
+               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+               return TTS_ERROR_INVALID_STATE;
+       }
+
+       int cnt = 0;
+       while (EINA_TRUE == __tts_connect_daemon((void*)tts) && 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_unprepare(tts_h tts)
 {
        if (0 != __tts_get_feature_enabled()) {
@@ -711,11 +782,18 @@ int tts_unprepare(tts_h tts)
                g_screen_reader = (bool)screen_reader;
        }
 
+       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) {
-                               if (TTS_ERROR_TIMED_OUT != ret) {
+                               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 {
@@ -882,7 +960,6 @@ int tts_get_max_text_size(tts_h tts, unsigned int* size)
                return TTS_ERROR_INVALID_STATE;
        }
 
-//     *size = TTS_MAX_TEXT_SIZE;
        if (0 != tts_config_mgr_get_max_text_size(size)) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get max text size");
                return TTS_ERROR_INVALID_PARAMETER;
@@ -1079,6 +1156,28 @@ int tts_add_text(tts_h tts, const char* text, const char* language, int voice_ty
        }
        SLOG(LOG_DEBUG, TAG_TTSC, "Text is valid - text is '%s'", text);
 
+       /* save texts for repetition */
+       if (NULL != client->text_repeat) {
+               free(client->text_repeat);
+               client->text_repeat = NULL;
+       }
+
+       client->text_repeat = strdup(text);
+
+       if (NULL != g_language) {
+               free(g_language);
+               g_language = NULL;
+       }
+       if (NULL == language)
+               g_language = NULL;
+       else
+               g_language = strdup(language);
+
+       g_voice_type = voice_type;
+       g_speed = speed;
+
+       SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] repeat: text(%s), language(%s), voice type(%d), speed(%d)", client->text_repeat, g_language, g_voice_type, g_speed);
+
        /* change default language value */
        char* temp = NULL;
 
@@ -1095,10 +1194,17 @@ int tts_add_text(tts_h tts, const char* text, const char* language, int voice_ty
        /* do request */
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_add_text(client->uid, text, temp, voice_type, speed, client->current_utt_id, client->credential);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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 {
@@ -1138,10 +1244,17 @@ static void __tts_play_async(void *data)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_play(client->uid, client->credential);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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 {
@@ -1265,10 +1378,17 @@ int tts_play(tts_h tts)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_play(client->uid, client->credential);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -1311,10 +1431,17 @@ static void __tts_stop_async(void *data)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_stop(client->uid);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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 {
@@ -1427,10 +1554,17 @@ int tts_stop(tts_h tts)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_stop(client->uid);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -1473,10 +1607,17 @@ static void __tts_pause_async(void *data)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_pause(client->uid);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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 {
@@ -1591,10 +1732,17 @@ int tts_pause(tts_h tts)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_pause(client->uid);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -1661,10 +1809,17 @@ int tts_set_private_data(tts_h tts, const char* key, const char* data)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_set_private_data(client->uid, key, data);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -1716,10 +1871,17 @@ int tts_get_private_data(tts_h tts, const char* key, char** data)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_get_private_data(client->uid, key, data);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -2350,7 +2512,7 @@ int tts_add_pcm(tts_h tts, int event, const void* data, unsigned int data_size,
                return TTS_ERROR_INVALID_PARAMETER;
        }
 
-       if (TTS_STATE_PLAYING != client->current_state) {
+       if (TTS_STATE_CREATED == client->current_state) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] The current state is invalid.");
                return TTS_ERROR_INVALID_STATE;
        }
@@ -2362,10 +2524,17 @@ int tts_add_pcm(tts_h tts, int event, const void* data, unsigned int data_size,
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_add_pcm(client->uid, event, data, data_size, audio_type, rate);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -2419,10 +2588,17 @@ int tts_play_pcm(tts_h tts)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_play_pcm(client->uid);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -2474,7 +2650,7 @@ int tts_stop_pcm(tts_h tts)
                return TTS_ERROR_INVALID_PARAMETER;
        }
 
-       if (TTS_STATE_PLAYING != client->current_state) {
+       if (TTS_STATE_CREATED == client->current_state) {
                SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] The current state is invalid.");
                return TTS_ERROR_INVALID_STATE;
        }
@@ -2486,10 +2662,17 @@ int tts_stop_pcm(tts_h tts)
 
        int ret = -1;
        int count = 0;
+       bool is_prepared = false;
        while (0 != ret) {
                ret = tts_dbus_request_stop_pcm(client->uid);
                if (0 != ret) {
-                       if (TTS_ERROR_TIMED_OUT != ret) {
+                       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));
                                return ret;
                        } else {
@@ -2518,3 +2701,96 @@ int tts_stop_pcm(tts_h tts)
 
        return TTS_ERROR_NONE;
 }
+
+int tts_repeat(tts_h tts, char** text_repeat, int* utt_id)
+{
+       if (0 != __tts_get_feature_enabled()) {
+               return TTS_ERROR_NOT_SUPPORTED;
+       }
+
+       SLOG(LOG_INFO, TAG_TTSC, "@@@ Repeat TTS");
+
+       if (NULL == tts) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null.");
+               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (NULL == text_repeat || NULL == utt_id) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null.");
+               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       *text_repeat = NULL;
+       *utt_id = -1;
+
+       tts_client_s* client = tts_client_get(tts);
+
+       if (NULL == client) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] A handle is not valid.");
+               SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+               return TTS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (TTS_STATE_READY != client->current_state) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] The current state is invalid. (%d)", client->current_state);
+               return TTS_ERROR_INVALID_STATE;
+       }
+
+       /* Clear the legacy and Add texts to be played repeatedly */
+       int ret = -1;
+       ret = tts_stop(tts);
+       if (TTS_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to clear the legacy");
+               return ret;
+       }
+
+       if (NULL != client->text_repeat) {
+               char* tmp_text = strdup(client->text_repeat);
+               char* tmp_lang = NULL;
+               if (NULL != g_language) {
+                       tmp_lang = strdup(g_language);
+               }
+               ret = tts_add_text(tts, tmp_text, tmp_lang, g_voice_type, g_speed, utt_id);
+               if (TTS_ERROR_NONE != ret) {
+                       SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to add texts for repetition.");
+                       if (NULL != tmp_text) {
+                               free(tmp_text);
+                               tmp_text = NULL;
+                       }
+                       if (NULL != tmp_lang) {
+                               free(tmp_lang);
+                               tmp_lang = NULL;
+                       }
+                       return ret;
+               }
+               *text_repeat = strdup(client->text_repeat);
+               SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] text to repeat(%s), utt_id(%d)", *text_repeat, *utt_id);
+               if (NULL != tmp_text) {
+                       free(tmp_text);
+                       tmp_text = NULL;
+               }
+               if (NULL != tmp_lang) {
+                       free(tmp_lang);
+                       tmp_lang = NULL;
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] There is no previous added texts. Please add texts");
+               return TTS_ERROR_OPERATION_FAILED;
+       }
+
+       /* Play added texts */
+       ret = tts_play(tts);
+       if (TTS_ERROR_NONE != ret) {
+               SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to play texts for repetition.");
+               if (NULL != *text_repeat) {
+                       free(*text_repeat);
+                       *text_repeat = NULL;
+               }
+               *utt_id = -1;
+               return ret;
+       }
+
+       return TTS_ERROR_NONE;
+}