+ client->reason = TTS_ERROR_ENGINE_NOT_FOUND;
+ client->utt_id = -1;
+
+ ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
+ 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;
+
+ ecore_timer_add(0, __tts_notify_error, (void*)client->tts);
+ 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");
+ }
+
+ 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 (NULL != client->state_changed_cb) {
+ tts_client_use_callback(client);
+ client->state_changed_cb(client->tts, client->before_state, client->current_state, client->state_changed_user_data);
+ tts_client_not_use_callback(client);
+ } else {
+ SLOG(LOG_WARN, TAG_TTSC, "State changed callback is NULL");
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return EINA_FALSE;
+}
+
+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;
+ }
+
+ /* 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;
+ }
+
+ 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()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_INFO, TAG_TTSC, "@@@ Unprepare 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");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ /* check state */
+ if (client->current_state != TTS_STATE_READY) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid State: Current state is not 'READY'");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ int ret = -1;
+ int count = 0;
+ int screen_reader = -1;
+
+ ret = vconf_get_bool(TTS_ACCESSIBILITY_KEY, &screen_reader);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get screen reader");
+ } else {
+ SLOG(LOG_INFO, tts_tag(), "[INFO] Success to get screen reader(%d), g_screen_reader(%s), client->mode(%d)", screen_reader, (true == g_screen_reader) ? "True" : "False", client->mode);
+ 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) {
+ //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);
+ }
+
+ client->before_state = client->current_state;
+ client->current_state = TTS_STATE_CREATED;
+
+ if (NULL != client->state_changed_cb) {
+ tts_client_use_callback(client);
+ client->state_changed_cb(client->tts, client->before_state, client->current_state, client->state_changed_user_data);
+ tts_client_not_use_callback(client);
+ SLOG(LOG_DEBUG, TAG_TTSC, "State changed callback is called");
+ }
+
+ 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)
+{
+ tts_h tts = (tts_h)user_data;
+
+ tts_client_s* client = tts_client_get(tts);
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[WARNING] A handle is not valid");
+ return false;
+ }
+
+ /* call callback function */
+ if (NULL != client->supported_voice_cb) {
+ return client->supported_voice_cb(tts, language, type, client->supported_voice_user_data);
+ } else {
+ SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of supported voice");
+ }
+
+ return false;
+}
+
+int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, void* user_data)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, 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;
+ }
+
+ tts_client_s* client = tts_client_get(tts);
+
+ /* 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;
+ }
+
+ int ret = 0;
+ char* current_engine = NULL;
+ ret = tts_config_mgr_get_engine(¤t_engine);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get current engine : %d", ret);
+ return __tts_convert_config_error_code(ret);
+ }
+
+ 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);
+
+ if (NULL != current_engine) {
+ free(current_engine);
+ current_engine = NULL;
+ }
+
+ client->supported_voice_cb = NULL;
+ client->supported_voice_user_data = NULL;
+
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret);
+ ret = TTS_ERROR_OPERATION_FAILED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return ret;
+}
+
+int tts_get_default_voice(tts_h tts, char** lang, int* vctype)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@ Get default voice");
+
+ if (NULL == tts) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+
+ }
+ 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;
+ }
+
+ /* Request call remote method */
+ int ret = 0;
+ ret = tts_config_mgr_get_voice(lang, vctype);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] result : %d", ret);
+ return __tts_convert_config_error_code(ret);
+ } else {
+ SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Default language(%s), type(%d)", *lang, *vctype);
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return ret;
+}
+
+int tts_get_max_text_size(tts_h tts, unsigned int* size)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ if (NULL == tts || NULL == size) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : Input parameter is null");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ tts_client_s* client = tts_client_get(tts);
+
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : A handle is not valid");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (TTS_STATE_READY != client->current_state) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get max text count : Current state is NOT 'READY'.");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ 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;
+ }
+
+ g_max_text_size = (int)*size;
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "Get max text count : %d", *size);
+ return TTS_ERROR_NONE;
+}
+
+int tts_get_state(tts_h tts, tts_state_e* state)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ if (NULL == tts || NULL == state) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : Input parameter is null");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ tts_client_s* client = tts_client_get(tts);
+
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : A handle is not valid");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ *state = client->current_state;
+
+ switch (*state) {
+ case TTS_STATE_CREATED: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Created'"); break;
+ case TTS_STATE_READY: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Ready'"); break;
+ case TTS_STATE_PLAYING: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Playing'"); break;
+ case TTS_STATE_PAUSED: SLOG(LOG_DEBUG, TAG_TTSC, "Current state is 'Paused'"); break;
+ default: SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Invalid value"); break;
+ }
+
+ return TTS_ERROR_NONE;
+}
+
+int tts_get_speed_range(tts_h tts, int* min, int* normal, int* max)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ if (NULL == tts || NULL == min || NULL == normal || NULL == max) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ tts_client_s* client = tts_client_get(tts);
+
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : A handle is not valid");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ *min = TTS_SPEED_MIN;
+ *normal = TTS_SPEED_NORMAL;
+ *max = TTS_SPEED_MAX;
+
+ return TTS_ERROR_NONE;
+}
+
+int tts_get_error_message(tts_h tts, char** err_msg)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ if (NULL == tts || NULL == err_msg) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ tts_client_s* client = tts_client_get(tts);
+
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Get state : A handle is not valid");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (NULL != client->err_msg) {
+ *err_msg = strdup(client->err_msg);
+ SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Error msg (%s)", *err_msg);
+ } else {
+ *err_msg = NULL;
+ SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Error msg (NULL)");
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ 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_INFO, TAG_TTSC, "[DEBUG] Add text: text(%s), language(%s), type(%d)", (NULL == text) ? "NULL" : text, (NULL == language) ? "NULL" : language, voice_type);
+
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ if (speed < 0) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Speed should not be negative(%d)", speed);
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (voice_type < 0) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Voice type should not be negative(%d)", voice_type);
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@ Add text");
+
+ if (NULL == tts || NULL == utt_id) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input parameter is null");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ 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_CREATED == client->current_state) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Current state is 'CREATED'.");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (-1 == g_max_text_size) {
+ SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] g_max_text_size is %d", g_max_text_size);
+ if (0 != tts_config_mgr_get_max_text_size((unsigned int*)&g_max_text_size)) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get max text size");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ if (0 == g_max_text_size) {
+ if (strlen(text) <= 0) {
+ SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Max Text Size is %d", g_max_text_size);
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input text size is invalid. (max text size is unlimited.)");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] g_max_text_size is %d", g_max_text_size);
+ if (g_max_text_size < strlen(text) || strlen(text) <= 0) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input text size is invalid.");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ if (TTS_SPEED_AUTO > speed || TTS_SPEED_MAX < speed) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] speed value(%d) is invalid.", speed);
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (false == g_screen_reader && TTS_MODE_SCREEN_READER == client->mode) {
+ SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Screen reader option is NOT available. Ignore this request");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (true == client->credential_needed && NULL == client->credential) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Do not have app credential for this engine");
+ return TTS_ERROR_PERMISSION_DENIED;
+ }
+
+ /* check valid utf8 */
+ bool valid = false;
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ valid = dbus_validate_utf8(text, &err);
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Dbus Error(%s), text(%s)", err.message, text);
+ dbus_error_free(&err);
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (valid != true) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Text is invalid - '%s'", text);
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+ 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;
+
+ if (NULL == language)
+ temp = strdup("default");
+ else
+ temp = strdup(language);
+
+ client->current_utt_id++;
+ if (client->current_utt_id == 10000) {
+ client->current_utt_id = 1;
+ }
+
+ /* 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) {
+ //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 add text : %s", __tts_get_error_code(ret));
+ usleep(10000);
+ count++;
+ if (TTS_RETRY_MIN_COUNT == count) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
+ break;
+ }
+ }
+ //LCOV_EXCL_STOP
+ } else {
+ *utt_id = client->current_utt_id;
+ }
+ }
+
+ if (NULL != temp) {
+ free(temp);
+ temp = NULL;
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return ret;
+}
+
+//LCOV_EXCL_START
+static void __tts_play_async(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;
+ }
+
+ 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_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 play : %s", __tts_get_error_code(ret));
+ usleep(10000);
+ count++;
+ if (TTS_RETRY_COUNT == count) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
+ break;
+ }
+ }
+ }
+ }
+
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to play tts : %s", __tts_get_error_code(ret));
+
+ client->reason = ret;
+ client->utt_id = -1;
+
+ ecore_timer_add(0, __tts_notify_error, client->tts);
+ return;
+ }
+
+ client->before_state = client->current_state;
+ client->current_state = TTS_STATE_PLAYING;
+
+ if (NULL != client->state_changed_cb) {
+ tts_client_use_callback(client);
+ client->state_changed_cb(client->tts, client->before_state, client->current_state, client->state_changed_user_data);
+ tts_client_not_use_callback(client);
+ SLOG(LOG_DEBUG, TAG_TTSC, "State changed callback is called");
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return;
+}
+
+int tts_play_async(tts_h tts)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@ Play tts");
+
+ if (NULL == tts) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null.");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ 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_PLAYING == client->current_state || TTS_STATE_CREATED == client->current_state) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] The current state is invalid.");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (false == g_screen_reader && TTS_MODE_SCREEN_READER == client->mode) {
+ SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Screen reader option is NOT available. Ignore this request");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (true == client->credential_needed && NULL == client->credential) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Do not have app credential for this engine");
+ return TTS_ERROR_PERMISSION_DENIED;
+ }
+
+ ecore_main_loop_thread_safe_call_async(__tts_play_async, (void*)tts);
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return TTS_ERROR_NONE;
+}
+//LCOV_EXCL_STOP
+int tts_play(tts_h tts)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_INFO, TAG_TTSC, "@@@ Play tts");
+
+ if (NULL == tts) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null.");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ 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, "@@@");
+ SLOG(LOG_DEBUG, TAG_TTSC, " ");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (TTS_STATE_PLAYING == client->current_state || TTS_STATE_CREATED == client->current_state) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] The current state is invalid.");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (false == g_screen_reader && TTS_MODE_SCREEN_READER == client->mode) {
+ SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Screen reader option is NOT available. Ignore this request");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (true == client->credential_needed && NULL == client->credential) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Do not have app credential for this engine");
+ return TTS_ERROR_PERMISSION_DENIED;
+ }
+
+ 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) {
+ //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 {
+ SLOG(LOG_WARN, TAG_TTSC, "[WARNING] retry play : %s", __tts_get_error_code(ret));
+ usleep(10000);
+ count++;
+ if (TTS_RETRY_COUNT == count) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
+ return ret;
+ }
+ }
+ //LCOV_EXCL_STOP
+ }
+ }
+
+ client->before_state = client->current_state;
+ client->current_state = TTS_STATE_PLAYING;
+
+ if (NULL != client->state_changed_cb) {
+ tts_client_use_callback(client);
+ client->state_changed_cb(client->tts, client->before_state, client->current_state, client->state_changed_user_data);
+ tts_client_not_use_callback(client);
+ SLOG(LOG_DEBUG, TAG_TTSC, "State changed callback is called");
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return TTS_ERROR_NONE;
+}
+//LCOV_EXCL_START
+static void __tts_stop_async(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;
+ }
+
+ 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_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 stop : %s", __tts_get_error_code(ret));
+ usleep(10000);
+ count++;
+ if (TTS_RETRY_COUNT == count) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
+ break;
+ }
+ }
+ }
+ }
+
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to stop tts : %s", __tts_get_error_code(ret));
+
+ client->reason = ret;
+ client->utt_id = -1;
+
+ ecore_timer_add(0, __tts_notify_error, client->tts);
+ return;
+ }
+
+ client->before_state = client->current_state;
+ client->current_state = TTS_STATE_READY;
+
+ if (NULL != client->state_changed_cb) {
+ tts_client_use_callback(client);
+ client->state_changed_cb(client->tts, client->before_state, client->current_state, client->state_changed_user_data);
+ tts_client_not_use_callback(client);
+ SLOG(LOG_DEBUG, TAG_TTSC, "State changed callback is called");
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return;
+}
+
+int tts_stop_aync(tts_h tts)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@ Stop tts");
+
+ if (NULL == tts) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;
+ }
+
+ 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_CREATED == client->current_state) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Current state is 'CREATED'.");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ if (false == g_screen_reader && TTS_MODE_SCREEN_READER == client->mode) {
+ SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Screen reader option is NOT available. Ignore this request");
+ return TTS_ERROR_INVALID_STATE;
+ }
+
+ ecore_main_loop_thread_safe_call_async(__tts_stop_async, (void*)tts);
+
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+
+ return TTS_ERROR_NONE;
+}
+//LCOV_EXCL_STOP
+int tts_stop(tts_h tts)
+{
+ if (0 != __tts_get_feature_enabled()) {
+ return TTS_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_INFO, TAG_TTSC, "@@@ Stop tts");
+
+ if (NULL == tts) {
+ SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input handle is null");
+ SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
+ return TTS_ERROR_INVALID_PARAMETER;