X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=client%2Ftts.c;h=67038a28d0b28da80c6c83465b0a126279867081;hb=9f8e5df9fc2420988ab7bfbeba56e5560c27fa22;hp=1b078042c8d6a1106c391f6a2c7b6eaa4e67b987;hpb=5553a907bd9e7c456e9fd626b423a1536f383c98;p=platform%2Fcore%2Fuifw%2Ftts.git diff --git a/client/tts.c b/client/tts.c index 1b07804..67038a2 100644 --- a/client/tts.c +++ b/client/tts.c @@ -27,6 +27,7 @@ #include "tts_dbus.h" #include "tts_main.h" +#include "tts_internal.h" static bool g_screen_reader; @@ -36,6 +37,17 @@ static bool g_err_callback_status = false; static int g_max_text_size = -1; +static Ecore_Timer* g_check_state_timer = NULL; + + +/* 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); @@ -108,6 +120,7 @@ static int __tts_convert_config_error_code(tts_config_error_e code) return code; } +//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) { SLOG(LOG_DEBUG, TAG_TTSC, "Voice changed : Before lang(%s) type(%d) , Current lang(%s), type(%d)", @@ -131,6 +144,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); } @@ -210,6 +231,7 @@ void _tts_config_engine_changed_cb(const char* engine_id, const char* setting, c } return; } +//LCOV_EXCL_STOP int tts_create(tts_h* tts) { @@ -313,6 +335,7 @@ int tts_destroy(tts_h tts) do { ret = tts_dbus_request_finalize(client->uid); if (0 != ret) { + //LCOV_EXCL_START if (TTS_ERROR_TIMED_OUT != ret) { SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %s", __tts_get_error_code(ret)); break; @@ -325,6 +348,7 @@ int tts_destroy(tts_h tts) break; } } + //LCOV_EXCL_STOP } } while (0 != ret); } else { @@ -354,6 +378,17 @@ int tts_destroy(tts_h tts) } } + if (NULL != g_language) { + free(g_language); + g_language = NULL; + } + + /* Delete state timer before destroying handle */ + if (NULL != g_check_state_timer) { + ecore_timer_del(g_check_state_timer); + g_check_state_timer = NULL; + } + tts = NULL; SLOG(LOG_DEBUG, TAG_TTSC, "@@@"); @@ -361,10 +396,12 @@ int tts_destroy(tts_h tts) return TTS_ERROR_NONE; } +//LCOV_EXCL_START void __tts_screen_reader_changed_cb(bool value) { g_screen_reader = value; } +//LCOV_EXCL_STOP int tts_set_mode(tts_h tts, tts_mode_e mode) { @@ -391,7 +428,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); @@ -492,6 +529,7 @@ int tts_set_credential(tts_h tts, const char* credential) return TTS_ERROR_NONE; } +//LCOV_EXCL_START int tts_set_server_tts(tts_h tts, const char* credential) { if (0 != __tts_get_feature_enabled()) { @@ -528,6 +566,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 +584,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 +600,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; } @@ -566,6 +614,7 @@ int tts_set_server_tts(tts_h tts, const char* credential) return TTS_ERROR_NONE; } +// LCOV_EXCL_STOP static Eina_Bool __tts_connect_daemon(void *data) { @@ -670,13 +719,56 @@ int tts_prepare(tts_h tts) return TTS_ERROR_INVALID_STATE; } - client->conn_timer = ecore_timer_add(0, __tts_connect_daemon, (void*)tts); + ecore_thread_main_loop_begin(); + client->conn_timer = ecore_timer_add(0.02, __tts_connect_daemon, (void*)tts); + ecore_thread_main_loop_end(); SLOG(LOG_DEBUG, TAG_TTSC, "@@@"); return TTS_ERROR_NONE; } +//LCOV_EXCL_START +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; +} +//LCOV_EXCL_STOP + int tts_unprepare(tts_h tts) { if (0 != __tts_get_feature_enabled()) { @@ -711,11 +803,19 @@ 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) { + //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 { @@ -727,6 +827,7 @@ int tts_unprepare(tts_h tts) break; } } + //LCOV_EXCL_STOP } } while (0 != ret); } else { @@ -882,7 +983,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 +1179,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 +1217,18 @@ 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) { + //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 { @@ -1110,6 +1240,7 @@ int tts_add_text(tts_h tts, const char* text, const char* language, int voice_ty break; } } + //LCOV_EXCL_STOP } else { *utt_id = client->current_utt_id; } @@ -1125,6 +1256,7 @@ int tts_add_text(tts_h tts, const char* text, const char* language, int voice_ty return ret; } +//LCOV_EXCL_START static void __tts_play_async(void *data) { tts_h tts = (tts_h)data; @@ -1138,10 +1270,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 { @@ -1224,7 +1363,7 @@ int tts_play_async(tts_h tts) return TTS_ERROR_NONE; } - +//LCOV_EXCL_STOP int tts_play(tts_h tts) { if (0 != __tts_get_feature_enabled()) { @@ -1265,10 +1404,18 @@ 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) { + //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)); return ret; } else { @@ -1280,6 +1427,7 @@ int tts_play(tts_h tts) return ret; } } + //LCOV_EXCL_STOP } } @@ -1297,7 +1445,7 @@ int tts_play(tts_h tts) return TTS_ERROR_NONE; } - +//LCOV_EXCL_START static void __tts_stop_async(void *data) { tts_h tts = (tts_h)data; @@ -1311,10 +1459,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 { @@ -1392,7 +1547,7 @@ int tts_stop_aync(tts_h tts) return TTS_ERROR_NONE; } - +//LCOV_EXCL_STOP int tts_stop(tts_h tts) { if (0 != __tts_get_feature_enabled()) { @@ -1427,10 +1582,18 @@ 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) { + //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)); return ret; } else { @@ -1442,6 +1605,7 @@ int tts_stop(tts_h tts) return ret; } } + //LCOV_EXCL_STOP } } @@ -1459,7 +1623,7 @@ int tts_stop(tts_h tts) return TTS_ERROR_NONE; } - +//LCOV_EXCL_START static void __tts_pause_async(void *data) { tts_h tts = (tts_h)data; @@ -1473,10 +1637,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 { @@ -1555,7 +1726,7 @@ int tts_pause_async(tts_h tts) return TTS_ERROR_NONE; } - +//LCOV_EXCL_STOP int tts_pause(tts_h tts) { if (0 != __tts_get_feature_enabled()) { @@ -1591,10 +1762,18 @@ 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) { + //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)); return ret; } else { @@ -1606,6 +1785,7 @@ int tts_pause(tts_h tts) return ret; } } + //LCOV_EXCL_STOP } } @@ -1633,7 +1813,7 @@ int tts_set_private_data(tts_h tts, const char* key, const char* data) SLOG(LOG_INFO, TAG_TTSC, "@@@ Set private data, key(%s), data(%s)", key, data); if (NULL == tts) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle isnull"); + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null"); return TTS_ERROR_INVALID_PARAMETER; } @@ -1661,10 +1841,18 @@ 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) { + //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)); return ret; } else { @@ -1676,6 +1864,7 @@ int tts_set_private_data(tts_h tts, const char* key, const char* data) return ret; } } + //LCOV_EXCL_STOP } } @@ -1716,10 +1905,18 @@ 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) { + //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)); return ret; } else { @@ -1731,6 +1928,7 @@ int tts_get_private_data(tts_h tts, const char* key, char** data) return ret; } } + //LCOV_EXCL_STOP } } @@ -1744,6 +1942,7 @@ int tts_get_private_data(tts_h tts, const char* key, char** data) return 0; } +//LCOV_EXCL_START static Eina_Bool __tts_notify_error(void *data) { tts_h tts = (tts_h)data; @@ -1894,7 +2093,11 @@ int __tts_cb_set_state(int uid, int state) } if (NULL != client->state_changed_cb) { - ecore_timer_add(0, __tts_notify_state_changed, client->tts); + 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, __tts_notify_state_changed, client->tts); } else { SLOG(LOG_WARN, TAG_TTSC, "[WARNING] State changed callback is null"); } @@ -1904,6 +2107,7 @@ int __tts_cb_set_state(int uid, int state) return 0; } +//LCOV_EXCL_STOP int __tts_cb_utt_started(int uid, int utt_id) { @@ -2014,6 +2218,11 @@ int tts_unset_state_changed_cb(tts_h tts) client->state_changed_cb = NULL; client->state_changed_user_data = NULL; + if (NULL != g_check_state_timer) { + ecore_timer_del(g_check_state_timer); + g_check_state_timer = NULL; + } + SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Unset state changed cb"); return 0; @@ -2328,6 +2537,7 @@ int tts_unset_engine_changed_cb(tts_h tts) return 0; } +//LCOV_EXCL_START int tts_add_pcm(tts_h tts, int event, const void* data, unsigned int data_size, int audio_type, int rate) { if (0 != __tts_get_feature_enabled()) { @@ -2350,7 +2560,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 +2572,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 +2636,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 +2698,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 +2710,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 +2749,97 @@ int tts_stop_pcm(tts_h tts) return TTS_ERROR_NONE; } +//LCOV_EXCL_STOP + +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; +}