+ 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, "@@@");