2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
15 #include <stdatomic.h>
17 #include <app_manager.h>
19 #include <package-manager.h>
21 #include "tts_internal.h"
28 static const int TTS_ERROR_FAIL_TO_SEND_HELLO = TIZEN_ERROR_TTS | 0xFF;
31 /* Static variables */
32 static atomic_bool g_is_thread_canceled = false;
34 static char* g_engine_name = NULL;
35 static int g_engine_update_status = 0;
36 static atomic_bool g_is_engine_name_changed = false;
38 static Ecore_Thread* g_reprepare_thread = NULL;
39 static Ecore_Idler *g_unset_app_context_cb_idler = NULL;
41 static char* g_pkgmgr_status = NULL;
42 static pkgmgr_client* g_pkgmgr = NULL;
43 static Ecore_Thread* g_pkgmgr_thread = NULL;
44 static pthread_mutex_t g_pkgmgr_mutex = PTHREAD_MUTEX_INITIALIZER;
46 static char* g_language = NULL;
47 static int g_voice_type = -1;
48 static int g_speed = -1;
51 /* Static functions */
52 // TODO: make tts_util? or tts_log?
53 static const char* __convert_state(tts_state_e state)
56 case TTS_STATE_CREATED: return "Created";
57 case TTS_STATE_READY: return "Ready";
58 case TTS_STATE_PLAYING: return "Playing";
59 case TTS_STATE_PAUSED: return "Paused";
62 return "Invalid state";
65 static char* get_engine_appid() {
66 if (NULL == g_engine_name) {
70 char* appid = (char*)calloc(TTS_ENGINE_APPID_LEN, sizeof(char));
75 snprintf(appid, TTS_ENGINE_APPID_LEN, "%s", g_engine_name);
79 static int __update_engine_name()
81 char* new_engine_name = vconf_get_str(TTS_ENGINE_DB_DEFAULT);
82 RETVM_IF(NULL == new_engine_name, TTS_ERROR_OPERATION_FAILED, "[ERROR] Fail to get engine name");
84 if (NULL != g_engine_name && 0 == strncmp(g_engine_name, new_engine_name, TTS_ENGINE_APPID_LEN)) {
85 SLOG(LOG_INFO, TAG_TTSC, "[INFO] engine name is same");
86 free(new_engine_name);
87 return TTS_ERROR_NONE;
91 g_engine_name = new_engine_name;
92 g_is_engine_name_changed = true;
94 SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Engine name(%s)", g_engine_name);
95 return TTS_ERROR_NONE;
98 static inline void __client_error_cb(tts_client_s* client, int utt_id, tts_error_e reason)
100 tts_error_cb callback = tts_client_get_error_cb(client);
101 void* data = tts_client_get_error_user_data(client);
103 if (NULL != callback) {
104 SLOG(LOG_DEBUG, TAG_TTSC, "Notify error");
105 tts_client_use_callback(client);
106 callback(tts_client_get_handle(client), utt_id, reason, data);
107 tts_client_not_use_callback(client);
109 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(error)");
113 static inline void __client_state_changed_cb(tts_client_s* client, tts_state_e before_state, tts_state_e current_state)
115 tts_state_changed_cb callback = tts_client_get_state_changed_cb(client);
116 void* data = tts_client_get_state_changed_user_data(client);
118 if (NULL != callback) {
119 SLOG(LOG_DEBUG, TAG_TTSC, "State changed data : before_state(%s) curret_state(%s)", __convert_state(before_state), __convert_state(current_state));
120 tts_client_use_callback(client);
121 callback(tts_client_get_handle(client), before_state, current_state, data);
122 tts_client_not_use_callback(client);
124 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(state_changed)");
128 static Eina_Bool __notify_error_timer_cb(void *data)
130 unsigned int uid = (uintptr_t)data;
131 tts_client_s* client = tts_client_get_by_uid(uid);
132 RETVM_IF(NULL == client, EINA_FALSE, "[ERROR] uid(%u) is not valid.", uid);
134 __client_error_cb(client, client->utt_id, client->reason);
135 client->notify_error_timer = NULL;
140 static bool __is_engine_installed(const char* appid)
142 app_info_h app_info = NULL;
143 int ret = app_manager_get_app_info(appid, &app_info);
144 if (APP_MANAGER_ERROR_NONE != ret || NULL == app_info) {
145 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] There is no tts engine (%s). ret(%d)", appid, ret);
148 SLOG(LOG_INFO, TAG_TTSC, "[INFO] There is tts engine (%s)", appid);
151 ret = app_info_destroy(app_info);
152 if (APP_MANAGER_ERROR_NONE != ret)
153 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy app_info. ret(%d)", ret);
158 static bool __is_engine_launched()
160 char* appid = get_engine_appid();
162 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get engine app ID");
166 bool is_installed = __is_engine_installed(appid);
167 if (false == is_installed) {
168 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] tts engine(%s) is not installed", appid);
173 bool is_running = false;
174 int ret = app_manager_is_running(appid, &is_running);
175 if (APP_MANAGER_ERROR_NONE != ret) {
176 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to check whether appid(%s) is running or not. ret(%d)", appid, ret);
177 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is installed(%d)", is_installed);
183 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is %s running. is_installed(%d)", (is_running) ? "" : " not", is_installed);
188 static int __pkgmgr_status_cb(uid_t target_uid, int req_id, const char *type, const char *pkgname, const char *key, const char *val, const void *pmsg, void *data)
190 // type (the type of the pkgname)
191 SLOG(LOG_INFO, TAG_TTSC, "[INFO] pkgmgr status cb is invoked. pkgname(%s), type(%s), key(%s), val(%s)", pkgname, type, key, val);
193 if (NULL == g_engine_name) {
194 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] engine name is NULL");
198 if (0 != strncmp(g_engine_name, pkgname, strlen(g_engine_name))) {
199 SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] this is not tts engine");
204 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] key is NULL");
208 if (0 == strncmp(key, "start", strlen(key))) {
209 if (NULL != g_pkgmgr_status) {
210 free(g_pkgmgr_status);
211 g_pkgmgr_status = NULL;
215 g_pkgmgr_status = strdup(val);
216 SLOG(LOG_INFO, TAG_TTSC, "[INFO] pkgmgr status. key(%s), status(%s)", key, g_pkgmgr_status);
218 if ((0 == strncmp(val, "update", strlen(val) || 0 == strncmp(val, "uninstall", strlen(val))))) {
219 SLOG(LOG_ERROR, TAG_TTSC, "[INFO] start to install.");
220 g_engine_update_status = 1;
223 } else if (0 == strncmp(key, "end", strlen(key)) && val && 0 == strncmp(val, "ok", strlen(val))) {
224 if (g_pkgmgr_status) {
225 if (0 == strncmp(g_pkgmgr_status, "install", strlen(g_pkgmgr_status)) || 0 == strncmp(g_pkgmgr_status, "update", strlen(g_pkgmgr_status))) {
226 SLOG(LOG_ERROR, TAG_TTSC, "[INFO] finish to install");
227 g_engine_update_status = 0;
229 free(g_pkgmgr_status);
230 g_pkgmgr_status = NULL;
239 static void __create_pkgmgr_thread(void* data, Ecore_Thread* thread)
241 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] create pkgmgr thread");
243 pthread_mutex_lock(&g_pkgmgr_mutex);
244 int time_delay = 10000;
246 while (NULL == g_pkgmgr) {
247 /* Checking the thread is canceled or not */
248 if (g_is_thread_canceled) {
249 SLOG(LOG_INFO, TAG_TTSC, "[INFO] g_pkgmgr_thread is canceled. Exit");
253 /* Checking handle which can be destroyed on other thread */
254 if (0 == tts_client_get_size()) {
255 SLOG(LOG_INFO, TAG_TTSC, "[INFO] All client is already destroyed");
259 g_pkgmgr = pkgmgr_client_new(PC_LISTENING);
260 if (NULL == g_pkgmgr) {
262 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create pkgmgr handle");
266 int ret = pkgmgr_client_set_status_type(g_pkgmgr, PKGMGR_CLIENT_STATUS_INSTALL | PKGMGR_CLIENT_STATUS_UNINSTALL | PKGMGR_CLIENT_STATUS_UPGRADE);
268 if (pkgmgr_client_listen_status(g_pkgmgr, __pkgmgr_status_cb, NULL) < 0) {
269 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to listen pkgmgr status. remove and recreate client");
270 pkgmgr_client_free(g_pkgmgr);
275 SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Succeed to register pkgmgr cb");
279 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set status type on pkgmgr, ret(%d)", ret);
280 pkgmgr_client_free(g_pkgmgr);
290 pthread_mutex_unlock(&g_pkgmgr_mutex);
292 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] create pkgmgr end");
295 static void __finish_pkgmgr_thread(void* data, Ecore_Thread* thread)
297 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] Finish pkgmgr thread");
298 g_is_thread_canceled = false;
299 g_pkgmgr_thread = NULL;
303 static void __cancel_pkgmgr_thread(void* data, Ecore_Thread* thread)
305 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] Cancel pkgmgr thread");
306 g_is_thread_canceled = false;
307 g_pkgmgr_thread = NULL;
311 static void __pkgmgr_thread(void* data)
313 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] call pkgmgr_thread");
314 if (NULL == g_pkgmgr_thread) {
315 SLOG(LOG_INFO, TAG_TTSC, "[INFO] ecore thread run: create_pkgmgr_thread");
316 g_pkgmgr_thread = ecore_thread_run(__create_pkgmgr_thread, __finish_pkgmgr_thread, __cancel_pkgmgr_thread, NULL);
323 static void __start_reprepare_thread(void* data, Ecore_Thread* thread)
325 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] start reprepare thread. engine update status(%d)", g_engine_update_status);
327 if (0 == g_engine_update_status && g_is_engine_name_changed) {
328 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Reprepare by engine change");
333 while (!g_engine_update_status && cnt < 20) {
334 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] wait for starting update");
339 // TODO: fix way to exit thread safely
340 /* Checking thread is canceled or not */
341 if (ecore_thread_check(g_reprepare_thread)) {
342 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] client thread is canceled. Exit");
347 SLOG(LOG_INFO, TAG_TTSC, "[DEBUG] update status(%d)", g_engine_update_status);
349 while (g_engine_update_status && (NULL != g_pkgmgr)) {
352 // TODO: fix way to exit thread safely
353 /* Checking thread is canceled or not */
354 if (ecore_thread_check(g_reprepare_thread)) {
355 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] client thread is canceled. Exit");
360 SLOG(LOG_INFO, TAG_TTSC, "[INFO] finish updating. request to prepare");
366 static void __end_reprepare_thread(void* data, Ecore_Thread* thread)
368 SLOG(LOG_INFO, TAG_TTSC, "[INFO] end reprepare thread");
370 GList* clients = tts_client_get_client_list();
371 if (NULL == clients) {
372 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get client list");
373 g_is_engine_name_changed = false;
374 g_reprepare_thread = NULL;
379 if (g_list_length(clients) > 0) {
380 iter = g_list_first(clients);
382 while (NULL != iter) {
383 tts_client_s* client = iter->data;
384 if (NULL != client) {
385 tts_core_prepare(client);
388 iter = g_list_next(iter);
392 g_list_free(clients);
393 g_is_engine_name_changed = false;
394 g_reprepare_thread = NULL;
398 static void __cancel_reprepare_thread(void* data, Ecore_Thread* thread)
400 SLOG(LOG_INFO, TAG_TTSC, "[INFO] cancel reprepare thread");
401 g_is_engine_name_changed = false;
402 g_reprepare_thread = NULL;
406 static inline void __run_client_reprepare_thread()
408 if (NULL == g_reprepare_thread) {
409 SLOG(LOG_INFO, TAG_TTSC, "[INFO] ecore thread run: start_reprepare_thread");
410 g_reprepare_thread = ecore_thread_run(__start_reprepare_thread, __end_reprepare_thread, __cancel_reprepare_thread, NULL);
412 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Reprepare thread is already running");
416 static int __send_hello_msg(tts_client_s* client)
418 tts_state_e current_state = tts_client_get_current_state(client);
419 if (TTS_STATE_READY == current_state) {
420 SLOG(LOG_INFO, TAG_TTSC, "[INFO] TTS client has been already connected to tts service"); //LCOV_EXCL_LINE
421 return TTS_ERROR_INVALID_STATE;
424 if (false == tts_core_check_screen_reader(client)) {
425 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Screen reader option is not available");
426 return TTS_ERROR_SCREEN_READER_OFF;
429 unsigned int uid = tts_client_get_uid(client);
430 tts_mode_e mode = tts_client_get_mode(client);
431 tts_playing_mode_e playing_mode = tts_client_get_playing_mode(client);
432 int registered_callback_mask = tts_client_get_registered_event_mask(client);
433 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%u), mode(%d), playing_mode(%d)", tts_client_get_handle(client), client, uid, (int)mode, (int)playing_mode);
435 /* check service engine status */
436 bool is_launched = __is_engine_launched();
437 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
438 if (false == is_launched) {
439 /* If engine is NOT launched, check whether engine is updating or not */
440 if (g_engine_update_status) {
441 /* suyeon wait engine update */
442 SLOG(LOG_INFO, TAG_TTSC, "[INFO] cannot prepare due to engine update");
443 __run_client_reprepare_thread();
444 return TTS_ERROR_INVALID_STATE;
448 if (0 != tts_ipc_request_hello(uid, mode, playing_mode, registered_callback_mask)) {
449 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request hello !!"); //LCOV_EXCL_LINE
451 SLOG(LOG_INFO, TAG_TTSC, "@@@ Send Hello");
454 return TTS_ERROR_NONE;
457 static Eina_Bool __prepare_cb(void *data)
459 unsigned int uid = (uintptr_t)data;
460 tts_client_s* client = tts_client_get_by_uid(uid);
461 RETVM_IF(NULL == client, EINA_FALSE, "[ERROR] uid(%u) is not valid.", uid);
463 int ret = __send_hello_msg(client);
464 if (ret != TTS_ERROR_NONE) {
465 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to send hello message"); //LCOV_EXCL_LINE
466 client->hello_timer = NULL;
470 client->prepare_count++;
471 if (TTS_HELLO_RETRY_COUNT == client->prepare_count) {
472 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare, retry count reaches the limit");
474 bool is_launched = __is_engine_launched();
475 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
477 client->hello_timer = NULL;
479 tts_core_notify_error_async(client, TTS_ERROR_TIMED_OUT, -1, "[ERROR] Fail to prepare. Please call tts_prepare() again.");
487 static Eina_Bool __prepare_first_cb(void *data)
489 /* send first hello message */
490 unsigned int uid = (uintptr_t)data;
491 tts_client_s* client = tts_client_get_by_uid(uid);
492 RETVM_IF(NULL == client, EINA_FALSE, "[ERROR] uid(%u) is not valid.", uid);
494 int ret = __send_hello_msg(client);
495 if (ret != TTS_ERROR_NONE) {
496 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to sent hello message"); //LCOV_EXCL_LINE
497 client->hello_timer = NULL;
499 /* Set retry timer callback */
500 client->prepare_count = 0;
501 client->hello_timer = ecore_timer_add(0.5, __prepare_cb, data);
507 static int __prepare_sync_cb(tts_client_s* client, tts_service_state_e* service_state)
509 // TODO: make function duplicated block
510 bool is_launched = __is_engine_launched();
511 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine is launched(%d)", is_launched);
513 if (false == is_launched) {
514 /* check whether engine is updating or not */
515 if (g_engine_update_status) {
516 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Cannot prepare due to engine update.");
517 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Client automatically tries to reprepare asynchrnously.");
518 __run_client_reprepare_thread();
519 return TTS_ERROR_OPERATION_FAILED;
523 // TODO: make function duplicated block
524 unsigned int uid = tts_client_get_uid(client);
525 if (TTS_ERROR_NONE != tts_ipc_request_hello_sync(uid)) {
526 return TTS_ERROR_FAIL_TO_SEND_HELLO;
529 SLOG(LOG_INFO, TAG_TTSC, "@@@ Connect daemon");
531 // TODO: make function duplicated block
532 /* do request initialize */
533 bool credential_needed = false;
534 tts_service_state_e tmp_service_state = TTS_SERVICE_STATE_NONE;
535 tts_mode_e mode = tts_client_get_mode(client);
536 tts_playing_mode_e playing_mode = tts_client_get_playing_mode(client);
537 int registered_callback_mask = tts_client_get_registered_event_mask(client);
538 int ret = tts_ipc_request_initialize(uid, mode, playing_mode, registered_callback_mask, &tmp_service_state, &credential_needed);
539 if (TTS_ERROR_ENGINE_NOT_FOUND == ret || TTS_ERROR_PERMISSION_DENIED == ret) {
540 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize. ret(%d/%s)", ret, get_error_message(ret));
541 tts_core_notify_error_async(client, ret, -1, NULL);
544 } else if (TTS_ERROR_NONE != ret) {
545 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to connection. Retry to connect. ret(%d/%s)", ret, get_error_message(ret));
546 return TTS_ERROR_FAIL_TO_SEND_HELLO;
548 /* success to connect tts-daemon */
549 client->credential_needed = credential_needed;
550 SLOG(LOG_ERROR, TAG_TTSC, "Supported options : credential(%s)", credential_needed ? "need" : "no need");
552 // TODO: make function duplicated block
554 *service_state = tmp_service_state;
555 SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
556 return TTS_ERROR_NONE;
559 static void __engine_changed_cb(keynode_t* key, void* data)
561 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts engine vconfkey is changed");
562 if (0 != __update_engine_name()) {
563 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set engine name into core module");
569 static bool __supported_voice_cb(const char* engine_id, const char* language, int type, void* user_data)
571 unsigned int uid = (uintptr_t)user_data;
572 tts_client_s* client = tts_client_get_by_uid(uid);
573 RETVM_IF(NULL == client, false, "[ERROR] uid(%u) is not valid.", uid);
575 /* call callback function */
576 tts_supported_voice_cb callback = tts_client_get_supported_voice_cb(client);
577 void* data = tts_client_get_supported_voice_user_data(client);
579 if (NULL == callback) {
580 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get callback.");
584 return callback(tts_client_get_handle(client), language, type, data);
587 static bool __is_screen_reader_turned_on()
589 SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Update screen reader state");
591 int screen_reader = 0;
592 int ret = vconf_get_bool(TTS_ACCESSIBILITY_KEY, &screen_reader);
594 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get screen reader vconf(%d)", ret);
598 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Current screen reader status(%d)", screen_reader);
599 return (bool)screen_reader;
602 static inline bool __is_ipc_retry_needed(tts_client_s* client, tts_error_e ret)
604 if (TTS_ERROR_NONE == ret) {
605 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success the IPC request");
609 if (TTS_ERROR_TIMED_OUT == ret) {
610 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] IPC is failed. Try again. ret(%d/%s)", ret, get_error_message(ret));
615 if (tts_client_is_reprepared(client)) {
616 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Prepare was already tried.");
617 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] IPC request is failed. ret(%d/%s)", ret, get_error_message(ret));
621 if (TTS_ERROR_INVALID_PARAMETER == ret || TTS_ERROR_IO_ERROR == ret) {
622 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] IPC is failed by unregistered client or network error. ret(%d/%s)", ret, get_error_message(ret));
623 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Try to prepare again");
624 tts_client_set_current_state(client, TTS_STATE_CREATED);
625 tts_core_prepare_sync(client);
626 tts_client_set_reprepared(client, true);
630 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] IPC request is failed. ret(%d/%s)", ret, get_error_message(ret));
634 static inline int __request_add_text(tts_client_s* client, const char* text, const char* language, int voice_type, int speed, int* utt_id)
636 /* change default language value */
637 const char* convert_language = (NULL == language ? "default" : language);
638 int new_utt_id = tts_client_new_utterance_id(client);
639 if (0 > new_utt_id) {
640 return TTS_ERROR_OPERATION_FAILED;
643 // TODO: If use cpp, remove dupliceated code using command class pattern
644 unsigned int uid = tts_client_get_uid(client);
646 tts_client_set_reprepared(client, false);
647 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
648 ret = tts_ipc_request_add_text(uid, text, convert_language, voice_type, speed, new_utt_id, client->credential);
649 if (false == __is_ipc_retry_needed(client, ret)) {
654 if (TTS_ERROR_NONE != ret) {
655 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
659 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_add_text");
660 *utt_id = new_utt_id;
661 return TTS_ERROR_NONE;
664 static inline int __request_play(tts_client_s* client)
666 unsigned int uid = tts_client_get_uid(client);
668 tts_client_set_reprepared(client, false);
669 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
670 ret = tts_ipc_request_play(uid, client->credential);
671 if (false == __is_ipc_retry_needed(client, ret)) {
676 if (TTS_ERROR_NONE != ret) {
677 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request. ret(%d)", ret);
681 SLOG(LOG_ERROR, TAG_TTSC, "[INFO] Success tts_dbus_request_play");
682 return tts_core_notify_state_changed(client, TTS_STATE_PLAYING);
685 int tts_core_initialize()
687 ecore_main_loop_thread_safe_call_async(__pkgmgr_thread, NULL);
689 if (0 != __update_engine_name()) {
690 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set engine name into core module");
692 g_is_engine_name_changed = false;
694 /* Register vconfkey callback to detect engine change */
695 vconf_notify_key_changed(TTS_ENGINE_DB_DEFAULT, __engine_changed_cb, NULL);
697 return TTS_ERROR_NONE;
700 int tts_core_deinitialize()
702 if (NULL != g_reprepare_thread && EINA_FALSE == ecore_thread_check(g_reprepare_thread)) {
703 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Cancel reprepare thread");
704 ecore_thread_cancel(g_reprepare_thread);
705 ecore_thread_wait(g_reprepare_thread, 0.5); // wait g_reprepare_thread is terminated.
708 if (NULL != g_unset_app_context_cb_idler) {
709 ecore_idler_del(g_unset_app_context_cb_idler);
710 g_unset_app_context_cb_idler = NULL;
713 if (NULL != g_pkgmgr_thread) {
714 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Cancel pkgmgr thread");
715 g_is_thread_canceled = true;
718 if (NULL != g_language) {
723 if (NULL != g_engine_name) {
725 g_engine_name = NULL;
728 pthread_mutex_lock(&g_pkgmgr_mutex);
729 if (NULL != g_pkgmgr) {
730 pkgmgr_client_remove_listen_status(g_pkgmgr);
731 pkgmgr_client_free(g_pkgmgr);
735 if (NULL != g_pkgmgr_status) {
736 free(g_pkgmgr_status);
737 g_pkgmgr_status = NULL;
739 pthread_mutex_unlock(&g_pkgmgr_mutex);
741 /* Unregister vconfkey callback */
742 vconf_ignore_key_changed(TTS_ENGINE_DB_DEFAULT, __engine_changed_cb);
744 return TTS_ERROR_NONE;
747 int tts_core_notify_state_changed(tts_client_s* client, tts_state_e current_state)
749 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
751 tts_state_e before_state = tts_client_get_current_state(client);
752 if (before_state == current_state) {
753 SLOG(LOG_INFO, TAG_TTSC, "[INFO] State is not changed. before(%s), current(%s)", __convert_state(before_state), __convert_state(current_state));
754 return TTS_ERROR_NONE;
757 SLOG(LOG_DEBUG, TAG_TTSC, "State changed to (%s).", __convert_state(current_state));
758 tts_client_set_current_state(client, current_state);
759 __client_state_changed_cb(client, before_state, current_state);
761 return TTS_ERROR_NONE;
764 int tts_core_notify_utt_started(tts_client_s* client, int utt_id)
766 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
768 client->utt_id = utt_id;
769 SLOG(LOG_DEBUG, TAG_TTSC, "Utterance started data : utt_id(%d)", client->utt_id);
771 tts_utterance_started_cb callback = tts_client_get_utterance_started_cb(client);
772 void* data = tts_client_get_utterance_started_user_data(client);
774 if (NULL != callback) {
775 SLOG(LOG_DEBUG, TAG_TTSC, "Notify utterance started");
776 tts_client_use_callback(client);
777 callback(tts_client_get_handle(client), client->utt_id, data);
778 tts_client_not_use_callback(client);
780 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(utt_started)");
783 return TTS_ERROR_NONE;
786 int tts_core_notify_utt_completeted(tts_client_s* client, int utt_id)
788 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
790 client->utt_id = utt_id;
791 SLOG(LOG_DEBUG, TAG_TTSC, "Utterance completed data : utt_id(%d)", utt_id);
793 tts_utterance_completed_cb callback = tts_client_get_utterance_completed_cb(client);
794 void* data = tts_client_get_utterance_completed_user_data(client);
796 if (NULL != callback) {
797 SLOG(LOG_DEBUG, TAG_TTSC, "Notify utterance started");
798 tts_client_use_callback(client);
799 callback(tts_client_get_handle(client), utt_id, data);
800 tts_client_not_use_callback(client);
802 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(utt_completed)");
805 return TTS_ERROR_NONE;
808 int tts_core_notify_error_async(tts_client_s* client, tts_error_e reason, int utt_id, const char* err_msg)
810 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
812 SLOG(LOG_DEBUG, TAG_TTSC, "Error data : utt_id(%d) reason(%s)", utt_id, tts_core_covert_error_code(reason));
813 client->utt_id = utt_id;
814 client->reason = reason;
815 tts_client_set_error_message(client, err_msg);
817 SLOG(LOG_DEBUG, TAG_TTSC, "Notify error asynchronously");
818 if (NULL != client->notify_error_timer) {
819 ecore_timer_del(client->notify_error_timer);
822 uintptr_t uid = tts_client_get_uid(client);
823 client->notify_error_timer = ecore_timer_add(0, __notify_error_timer_cb, (void*)uid);
825 return TTS_ERROR_NONE;
829 int tts_core_notify_default_voice_changed(tts_client_s* client, const char* before_lang, int before_voice_type, const char* language, int voice_type)
831 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
833 SLOG(LOG_DEBUG, TAG_TTSC, "Default voice changed data : before_lang(%s), before_voice_type(%d), language(%s), voice_type(%d)",
834 before_lang, before_voice_type, language, voice_type);
836 tts_default_voice_changed_cb callback = tts_client_get_default_voice_changed_cb(client);
837 void* data = tts_client_get_default_voice_changed_user_data(client);
839 if (NULL != callback) {
840 SLOG(LOG_DEBUG, TAG_TTSC, "Notify default voice changed");
841 tts_client_use_callback(client);
842 callback(tts_client_get_handle(client), before_lang, before_voice_type, language, voice_type, data);
843 tts_client_not_use_callback(client);
845 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(default_voice_changed)");
848 return TTS_ERROR_NONE;
851 int tts_core_notify_engine_changed(tts_client_s* client, const char* engine_id, const char* language, int voice_type, bool need_credential)
853 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
855 SLOG(LOG_DEBUG, TAG_TTSC, "Engine changed data : engine_id(%s) language(%s), voicd_type(%d), need_credential(%d)",
856 engine_id, language, voice_type, need_credential);
858 tts_engine_changed_cb callback = tts_client_get_engine_changed_cb(client);
859 void* data = tts_client_get_engine_changed_user_data(client);
861 if (NULL != callback) {
862 SLOG(LOG_DEBUG, TAG_TTSC, "Notify engine changed");
863 tts_client_use_callback(client);
864 callback(tts_client_get_handle(client), engine_id, language, voice_type, need_credential, data);
865 tts_client_not_use_callback(client);
867 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(engine_changed)");
870 return TTS_ERROR_NONE;
874 int tts_core_notify_screen_reader_changed(tts_client_s* client, bool value)
876 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
878 SLOG(LOG_DEBUG, TAG_TTSC, "Screen reader is changed. Current status(%d)", value);
880 tts_screen_reader_changed_cb callback = tts_client_get_screen_reader_changed_cb(client);
881 void* data = tts_client_get_screen_reader_changed_user_data(client);
883 if (NULL != callback) {
884 SLOG(LOG_DEBUG, TAG_TTSC, "Notify screen reader changed");
885 tts_client_use_callback(client);
886 callback(tts_client_get_handle(client), value, data);
887 tts_client_not_use_callback(client);
889 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(screen_reader_changed)");
892 return TTS_ERROR_NONE;
895 int tts_core_notify_service_state_changed(tts_client_s* client, tts_service_state_e before_state, tts_service_state_e current_state)
897 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
899 SLOG(LOG_DEBUG, TAG_TTSC, "Service state changed from (%d) to (%d).", before_state, current_state);
901 tts_service_state_changed_cb callback = tts_client_get_service_state_changed_cb(client);
902 void* data = tts_client_get_service_state_changed_user_data(client);
904 if (NULL != callback) {
905 SLOG(LOG_DEBUG, TAG_TTSC, "Notify service state changed");
906 tts_client_set_current_service_state(client, current_state);
908 tts_client_use_callback(client);
909 callback(tts_client_get_handle(client), before_state, current_state, data);
910 tts_client_not_use_callback(client);
912 SLOG(LOG_WARN, TAG_TTSC, "No registered callback(service_state_changed)");
915 return TTS_ERROR_NONE;
918 bool tts_core_is_valid_text(const char* text)
924 /* check valid utf8 */
926 dbus_error_init(&err);
927 bool valid = dbus_validate_utf8(text, &err);
928 if (dbus_error_is_set(&err)) {
929 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Dbus Error(%s), text(%s)", err.message, text);
930 dbus_error_free(&err);
934 if (false == valid) {
935 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Text is invalid - '%s'", text);
939 if (strlen(text) <= 0) {
940 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input text size is invalid.");
944 unsigned int max_text_size = 0;
945 /* check text size */
946 if (0 != tts_config_mgr_get_max_text_size(&max_text_size)) {
947 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get max text size");
951 SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] max_text_size is %d byte", max_text_size);
952 if (0 < max_text_size && max_text_size < strlen(text)) {
953 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Input text size is bigger than maximum test size. text_size(%zu byte)", strlen(text));
960 bool tts_core_check_screen_reader(tts_client_s* client)
962 RETVM_IF(false == tts_client_is_valid_client(client), false, "[ERROR] Client is invalid.");
964 tts_mode_e mode = tts_client_get_mode(client);
965 if (TTS_MODE_SCREEN_READER == mode && false == __is_screen_reader_turned_on()) {
972 bool tts_core_check_credential(tts_client_s* client)
974 RETVM_IF(false == tts_client_is_valid_client(client), false, "[ERROR] Client is invalid.");
976 if (true == client->credential_needed && NULL == tts_client_get_credential_key(client)) {
977 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Do not have app credential for this engine");
985 const char* tts_core_covert_error_code(tts_error_e err)
988 case TTS_ERROR_NONE: return "TTS_ERROR_NONE";
989 case TTS_ERROR_OUT_OF_MEMORY: return "TTS_ERROR_OUT_OF_MEMORY";
990 case TTS_ERROR_IO_ERROR: return "TTS_ERROR_IO_ERROR";
991 case TTS_ERROR_INVALID_PARAMETER: return "TTS_ERROR_INVALID_PARAMETER";
992 case TTS_ERROR_OUT_OF_NETWORK: return "TTS_ERROR_OUT_OF_NETWORK";
993 case TTS_ERROR_TIMED_OUT: return "TTS_ERROR_TIMED_OUT";
994 case TTS_ERROR_PERMISSION_DENIED: return "TTS_ERROR_PERMISSION_DENIED";
995 case TTS_ERROR_NOT_SUPPORTED: return "TTS_ERROR_NOT_SUPPORTED";
996 case TTS_ERROR_INVALID_STATE: return "TTS_ERROR_INVALID_STATE";
997 case TTS_ERROR_INVALID_VOICE: return "TTS_ERROR_INVALID_VOICE";
998 case TTS_ERROR_ENGINE_NOT_FOUND: return "TTS_ERROR_ENGINE_NOT_FOUND";
999 case TTS_ERROR_OPERATION_FAILED: return "TTS_ERROR_OPERATION_FAILED";
1000 case TTS_ERROR_AUDIO_POLICY_BLOCKED: return "TTS_ERROR_AUDIO_POLICY_BLOCKED";
1001 case TTS_ERROR_NOT_SUPPORTED_FEATURE: return "TTS_ERROR_NOT_SUPPORTED_FEATURE";
1002 case TTS_ERROR_SERVICE_RESET: return "TTS_ERROR_SERVICE_RESET";
1003 case TTS_ERROR_SCREEN_READER_OFF: return "TTS_ERROR_SCREEN_READER_OFF";
1005 return "Invalid error code";
1011 int tts_core_receive_hello(unsigned int uid, int ret, tts_service_state_e service_state, int credential_needed)
1013 tts_client_s* client = tts_client_get_by_uid(uid);
1014 RETVM_IF(NULL == client, TTS_ERROR_OPERATION_FAILED, "Fail to get TTS client or ignore this uid(%u)", uid);
1016 tts_state_e current_state = tts_client_get_current_state(client);
1017 RETVM_IF(TTS_STATE_CREATED != current_state, TTS_ERROR_NONE, "[INFO] tts client is already READY");
1019 if (client->hello_timer) {
1020 ecore_timer_del(client->hello_timer);
1021 client->hello_timer = NULL;
1024 if (TTS_ERROR_ENGINE_NOT_FOUND == ret || TTS_ERROR_PERMISSION_DENIED == ret) {
1025 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to initialize : %s", tts_core_covert_error_code(ret));
1026 tts_core_notify_error_async(client, ret, -1, NULL);
1028 return TTS_ERROR_OPERATION_FAILED;
1029 } else if (TTS_ERROR_ALREADY_INITIALIZED == ret) {
1030 /* success to connect tts-daemon */
1031 if (TTS_CREDENTIAL_NEEDED_ALREADY_INITIALIZED != credential_needed) {
1032 client->credential_needed = credential_needed;
1033 SLOG(LOG_ERROR, TAG_TTSC, "Supported options : credential(%d)", credential_needed);
1035 } else if (TTS_ERROR_NONE != ret) {
1036 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to connection. Retry to connect : %s", tts_core_covert_error_code(ret));
1037 return TTS_ERROR_OPERATION_FAILED;
1040 tts_client_set_service_out(client, false);
1041 tts_core_notify_state_changed(client, TTS_STATE_READY);
1043 tts_service_state_e before_state = tts_client_get_current_service_state(client);
1044 tts_core_notify_service_state_changed(client, before_state, service_state);
1046 SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
1047 return TTS_ERROR_NONE;
1050 int tts_core_prepare(tts_client_s* client)
1052 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1054 if (false == tts_core_check_screen_reader(client)) {
1055 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Screen reader option is not available");
1056 return TTS_ERROR_SCREEN_READER_OFF;
1059 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Start core_prepare. tts_h(%p), tts_client(%p)", tts_client_get_handle(client), client);
1060 if (NULL == client->hello_timer) {
1061 SLOG(LOG_ERROR, TAG_TTSC, "Register timer for __prepare_first_cb");
1063 ecore_thread_main_loop_begin();
1064 uintptr_t uid = tts_client_get_uid(client);
1065 client->hello_timer = ecore_timer_add(0.0, __prepare_first_cb, (void*)uid);
1066 ecore_thread_main_loop_end();
1068 LOGD("Client is already trying to prepare");
1071 return TTS_ERROR_NONE;
1074 int tts_core_prepare_sync(tts_client_s* client)
1076 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1078 unsigned int uid = tts_client_get_uid(client);
1079 tts_service_state_e service_state = TTS_SERVICE_STATE_NONE;
1080 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Start core_prepare_sync. tts_h(%p), tts_client(%p), uid(%u)", tts_client_get_handle(client), client, uid);
1082 while (TTS_CONNECTION_RETRY_COUNT > cnt) {
1083 if (false == tts_core_check_screen_reader(client)) {
1084 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Screen reader option is not available");
1085 return TTS_ERROR_SCREEN_READER_OFF;
1088 int ret = __prepare_sync_cb(client, &service_state);
1089 if (TTS_ERROR_NONE == ret) {
1090 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Prepare succeeds. uid(%u)", uid);
1094 if (TTS_ERROR_FAIL_TO_SEND_HELLO == ret) {
1095 SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Fail to send hello. Try again. uid(%u)", uid);
1097 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare. uid(%u), ret(%d/%s)", uid, ret, get_error_message(ret));
1104 if (TTS_CONNECTION_RETRY_COUNT == cnt) {
1105 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to connect daemon");
1106 return TTS_ERROR_OPERATION_FAILED;
1109 tts_client_set_service_out(client, false);
1110 tts_core_notify_state_changed(client, TTS_STATE_READY);
1112 tts_service_state_e before_state = tts_client_get_current_service_state(client);
1113 tts_core_notify_service_state_changed(client, before_state, service_state);
1115 SLOG(LOG_DEBUG, TAG_TTSC, "@@@");
1116 return TTS_ERROR_NONE;
1119 int tts_core_unprepare(tts_client_s* client)
1121 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1123 unsigned int uid = tts_client_get_uid(client);
1124 SLOG(LOG_INFO, TAG_TTSC, "[INFO] tts_h(%p), tts_client(%p), uid(%u)", tts_client_get_handle(client), client, uid);
1125 if (client->hello_timer) {
1126 ecore_timer_del(client->hello_timer);
1127 client->hello_timer = NULL;
1130 int ret = tts_ipc_stop_listening(uid);
1132 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to remove match : %s", tts_core_covert_error_code(ret));
1135 if (tts_client_is_service_out(client)) {
1136 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Service is already out. Do not need to finalize");
1137 tts_client_set_service_out(client, false);
1138 return TTS_ERROR_NONE;
1141 if (false == tts_core_check_screen_reader(client)) {
1142 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Do not request finalize. Handled by screen reader");
1144 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Request finalize");
1146 tts_client_set_reprepared(client, false);
1147 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1148 ret = tts_ipc_request_finalize(uid);
1149 if (false == __is_ipc_retry_needed(client, ret)) {
1154 if (TTS_ERROR_NONE == ret) {
1155 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_finalize");
1159 return TTS_ERROR_NONE;
1162 int tts_core_reprepare()
1164 GList* clients = tts_client_get_client_list();
1165 RETVM_IF(NULL == clients, TTS_ERROR_OPERATION_FAILED, "[ERROR] Fail to get client list");
1168 if (g_list_length(clients) > 0) {
1169 iter = g_list_first(clients);
1171 while (NULL != iter) {
1172 tts_client_s* client = iter->data;
1173 if (true == tts_client_is_valid_client(client)) {
1174 tts_client_set_current_state(client, TTS_STATE_CREATED);
1177 iter = g_list_next(iter);
1181 g_list_free(clients);
1182 __run_client_reprepare_thread();
1184 return TTS_ERROR_NONE;
1187 int tts_core_foreach_supported_voices(tts_client_s* client, const char* engine_id, tts_supported_voice_cb callback, void* user_data)
1189 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1191 tts_client_set_supported_voice_cb(client, callback, user_data);
1192 uintptr_t uid = tts_client_get_uid(client);
1193 int ret = tts_config_mgr_get_voice_list(engine_id, __supported_voice_cb, (void*)uid);
1194 tts_client_set_supported_voice_cb(client, NULL, NULL);
1197 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get voice list");
1198 return TTS_ERROR_OPERATION_FAILED;
1201 return TTS_ERROR_NONE;
1204 static void set_service_out_for_each_client(gpointer data, gpointer user_data)
1206 unsigned int instant_reprepare_uid = TTS_INVALID_UID;
1207 if (NULL != user_data) {
1208 instant_reprepare_uid = *((unsigned int *)user_data);
1209 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Instant on client UID(%u)", instant_reprepare_uid);
1212 tts_client_s *client = (tts_client_s *)data;
1213 if (false == tts_client_is_valid_client(client)) {
1214 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Client is not valid");
1218 const tts_state_e state = tts_client_get_current_state(client);
1219 if (state == TTS_STATE_INVALID || state == TTS_STATE_CREATED) {
1220 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Client is not connected yet. state(%d)", state);
1224 tts_client_set_service_out(client, true);
1225 tts_core_notify_error_async(client, TTS_ERROR_SERVICE_RESET, -1, "Daemon Reset");
1227 unsigned int uid = tts_client_get_uid(client);
1228 if (uid != instant_reprepare_uid) {
1229 SLOG(LOG_INFO, TAG_TTSC, "[INFO] On-demand repreparation required. UID(%u)", uid);
1230 tts_client_set_current_state(client, TTS_STATE_READY);
1232 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Instantly repreparation required. UID(%u)", uid);
1233 tts_client_set_current_state(client, TTS_STATE_CREATED);
1234 tts_core_prepare(client);
1237 const tts_service_state_e before_state = tts_client_get_current_service_state(client);
1238 tts_core_notify_service_state_changed(client, before_state, TTS_SERVICE_STATE_BLOCKED);
1241 static void notify_engine_launch_for_each_client(gpointer data, gpointer user_data)
1243 tts_client_s *client = (tts_client_s *)data;
1244 RETM_IF(false == tts_client_is_valid_client(client), "[ERROR] Client is not valid");
1246 const tts_service_state_e before_state = tts_client_get_current_service_state(client);
1247 if (TTS_SERVICE_STATE_BLOCKED == before_state) {
1248 tts_core_notify_service_state_changed(client, before_state, TTS_SERVICE_STATE_READY);
1252 static Eina_Bool unset_app_context_cb_by_idler(void *user_data)
1254 app_manager_unset_app_context_event_cb();
1255 g_unset_app_context_cb_idler = NULL;
1256 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Unset callback for checking engine launching status");
1260 static void check_engine_launching_status(app_context_h app_context, app_context_event_e event, void *user_data)
1262 RET_IF(event != APP_CONTEXT_EVENT_LAUNCHED);
1264 char *app_id = NULL;
1265 int ret = app_context_get_app_id(app_context, &app_id);
1267 RET_IF(ret != APP_MANAGER_ERROR_NONE || NULL == app_id);
1269 char *engine_id = get_engine_appid();
1270 bool is_engine = (0 == strncmp(app_id, engine_id, TTS_ENGINE_APPID_LEN));
1274 RET_IF(false == is_engine);
1276 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Engine is launched now");
1277 GList* client_list = tts_client_get_client_list();
1278 if (NULL != client_list) {
1279 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Set service out to all clients");
1280 g_list_foreach(client_list, notify_engine_launch_for_each_client, NULL);
1281 g_list_free(client_list);
1284 if (NULL == g_unset_app_context_cb_idler) {
1285 g_unset_app_context_cb_idler = ecore_idler_add(unset_app_context_cb_by_idler, NULL);
1289 int tts_core_handle_service_reset()
1291 SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Service Reset");
1293 GList* client_list = tts_client_get_client_list();
1294 RETVM_IF(NULL == client_list, TTS_ERROR_OPERATION_FAILED, "[ERROR] Fail to get client list");
1296 unsigned int instant_reprepare_uid = TTS_INVALID_UID;
1297 int ret = tts_config_mgr_get_instant_reprepare_client(&instant_reprepare_uid);
1298 if (TTS_CONFIG_ERROR_NONE != ret) {
1299 SLOG(LOG_WARN, TAG_TTSC, "[WARN] Fail to get instant reprepare uid. Skip instant reprepare");
1302 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Set service out to all clients");
1303 g_list_foreach(client_list, set_service_out_for_each_client, &instant_reprepare_uid);
1304 g_list_free(client_list);
1306 ret = app_manager_set_app_context_event_cb(check_engine_launching_status, NULL);
1307 if (APP_MANAGER_ERROR_NONE != ret) {
1308 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to set engine launching status callback. ret(%d/%s)", ret, get_error_message(ret));
1309 return TTS_ERROR_OPERATION_FAILED;
1312 return TTS_ERROR_NONE;
1315 static inline void reprepare_on_demand(tts_client_s* client)
1317 if (false == tts_client_is_service_out(client)) {
1321 const unsigned int uid = tts_client_get_uid(client);
1322 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Client is out of service. Try to reprepare. uid(%u)", uid);
1324 int ret = tts_core_prepare_sync(client);
1325 if (TTS_ERROR_NONE != ret) {
1326 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Client fails to prepare. uid(%u)", uid);
1330 int tts_core_add_text(tts_client_s* client, const char* text, const char* language, int voice_type, int speed, int* utt_id)
1332 RETVM_IF(NULL == text || NULL == utt_id, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Parameter is invalid.");
1333 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1334 reprepare_on_demand(client);
1336 tts_client_set_repeat_text(client, text);
1338 if (NULL != g_language) {
1342 g_language = (NULL == language ? NULL : strdup(language));
1343 g_voice_type = voice_type;
1346 SLOG(LOG_ERROR, TAG_TTSC, "[DEBUG] text(%s), language(%s), voice type(%d), speed(%d)", text, (g_language) ? g_language : "NULL", g_voice_type, g_speed);
1347 return __request_add_text(client, text, language, voice_type, speed, utt_id);
1350 int tts_core_play(tts_client_s* client)
1352 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1353 reprepare_on_demand(client);
1355 return __request_play(client);
1358 int tts_core_stop(tts_client_s* client)
1360 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1361 reprepare_on_demand(client);
1363 unsigned int uid = tts_client_get_uid(client);
1365 tts_client_set_reprepared(client, false);
1366 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1367 ret = tts_ipc_request_stop(uid);
1368 if (false == __is_ipc_retry_needed(client, ret)) {
1373 if (TTS_ERROR_NONE != ret) {
1374 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1378 return tts_core_notify_state_changed(client, TTS_STATE_READY);
1381 int tts_core_pause(tts_client_s* client)
1383 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1384 reprepare_on_demand(client);
1386 unsigned int uid = tts_client_get_uid(client);
1388 tts_client_set_reprepared(client, false);
1389 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1390 ret = tts_ipc_request_pause(uid);
1391 if (false == __is_ipc_retry_needed(client, ret)) {
1396 if (TTS_ERROR_NONE != ret) {
1397 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1401 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_pause");
1402 return tts_core_notify_state_changed(client, TTS_STATE_PAUSED);
1405 int tts_core_repeat(tts_client_s* client, char** text_repeat, int* utt_id)
1407 RETVM_IF(NULL == text_repeat || NULL == utt_id, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Parameter is invalid.");
1408 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1409 reprepare_on_demand(client);
1411 char* repeat_text = tts_client_get_repeat_text(client);
1412 if (NULL == repeat_text) {
1413 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] There is no previous added texts. Please add texts");
1414 return TTS_ERROR_OPERATION_FAILED;
1417 int new_utt_id = -1;
1418 int ret = __request_add_text(client, repeat_text, g_language, g_voice_type, g_speed, &new_utt_id);
1419 if (TTS_ERROR_NONE != ret) {
1420 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to add texts for repetition.");
1425 /* Play added texts */
1426 ret = __request_play(client);
1427 if (TTS_ERROR_NONE != ret) {
1428 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to play texts for repetition.");
1433 SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] text to repeat(%s), utt_id(%d)", repeat_text, new_utt_id);
1435 *utt_id = new_utt_id;
1436 *text_repeat = repeat_text;
1437 return TTS_ERROR_NONE;
1440 int tts_core_add_pcm(tts_client_s* client, int event, const void* data, unsigned int data_size, int audio_type, int rate)
1442 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1443 reprepare_on_demand(client);
1445 unsigned int uid = tts_client_get_uid(client);
1447 tts_client_set_reprepared(client, false);
1448 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1449 ret = tts_ipc_request_add_pcm(uid, event, data, data_size, audio_type, rate);
1450 if (false == __is_ipc_retry_needed(client, ret)) {
1455 if (TTS_ERROR_NONE != ret) {
1456 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1460 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_add_pcm");
1461 return TTS_ERROR_NONE;
1464 int tts_core_play_pcm(tts_client_s* client)
1466 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1467 reprepare_on_demand(client);
1469 unsigned int uid = tts_client_get_uid(client);
1471 tts_client_set_reprepared(client, false);
1472 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1473 ret = tts_ipc_request_play_pcm(uid);
1474 if (false == __is_ipc_retry_needed(client, ret)) {
1479 if (TTS_ERROR_NONE != ret) {
1480 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1484 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_play_pcm");
1485 return tts_core_notify_state_changed(client, TTS_STATE_PLAYING);
1488 int tts_core_stop_pcm(tts_client_s* client)
1490 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1491 reprepare_on_demand(client);
1493 unsigned int uid = tts_client_get_uid(client);
1495 tts_client_set_reprepared(client, false);
1496 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1497 ret = tts_ipc_request_stop_pcm(uid);
1498 if (false == __is_ipc_retry_needed(client, ret)) {
1503 if (TTS_ERROR_NONE != ret) {
1504 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1508 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_stop_pcm");
1509 return tts_core_notify_state_changed(client, TTS_STATE_READY);
1512 int tts_core_set_private_data(tts_client_s* client, const char* key, const char* data)
1514 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1515 reprepare_on_demand(client);
1517 unsigned int uid = tts_client_get_uid(client);
1519 tts_client_set_reprepared(client, false);
1520 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1521 ret = tts_ipc_request_set_private_data(uid, key, data);
1522 if (false == __is_ipc_retry_needed(client, ret)) {
1527 if (TTS_ERROR_NONE != ret) {
1528 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1532 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_set_private_data");
1533 return TTS_ERROR_NONE;
1536 int tts_core_get_private_data(tts_client_s* client, const char* key, char** data)
1538 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1539 reprepare_on_demand(client);
1541 unsigned int uid = tts_client_get_uid(client);
1543 tts_client_set_reprepared(client, false);
1544 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1545 ret = tts_ipc_request_get_private_data(uid, key, data);
1546 if (false == __is_ipc_retry_needed(client, ret)) {
1551 if (TTS_ERROR_NONE != ret) {
1552 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1556 if (0 == strncmp(*data, "NULL", strlen(*data))) {
1561 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_dbus_request_get_private_data");
1562 return TTS_ERROR_NONE;
1565 int tts_core_get_service_state(tts_client_s* client, tts_service_state_e* service_state)
1567 RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid.");
1568 reprepare_on_demand(client);
1570 unsigned int uid = tts_client_get_uid(client);
1572 tts_client_set_reprepared(client, false);
1573 for (int count = 0; count < TTS_RETRY_COUNT; count++) {
1574 ret = tts_ipc_request_get_service_state(uid, service_state);
1575 if (false == __is_ipc_retry_needed(client, ret)) {
1580 if (TTS_ERROR_NONE != ret) {
1581 SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request");
1585 SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_core_get_service_state");
1586 return TTS_ERROR_NONE;