From: Wonnam Jang Date: Tue, 15 Mar 2016 06:48:05 +0000 (+0900) Subject: sync codes to 2.4 spin X-Git-Tag: submit/tizen/20160318.103722^0 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Ftts.git;a=commitdiff_plain;h=3148014a7511856db9228c211cad9f4e80d103a4 sync codes to 2.4 spin Change-Id: Icb0193f9686d1dd7368a5f7f53b88107e3e19a0d Signed-off-by: Wonnam Jang --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c32051d..7698a22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,8 @@ PROJECT(tts) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(EXEC_PREFIX "${PREFIX}") -SET(VERSION 0.2.41) +SET(INCLUDEDIR "${PREFIX}/include") +SET(VERSION 0.2.43) IF (LIBDIR MATCHES "/usr/lib64") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLIB64") diff --git a/changelog b/changelog index b96985c..1718976 100644 --- a/changelog +++ b/changelog @@ -1,8 +1,14 @@ +tts (0.2.43) -- Wed, 29 Jul 2015 + + * Update utt message to change method call to signal (Dongyeol Lee ) + * Support dbus activation for daemon start (Dongyeol Lee ) + * Move default config file to /usr/share/voice/tts (Dongyeol Lee ) + * Move test program to /usr/share/voice/test (Dongyeol Lee ) + tts (0.2.42) -- Fri, 29 May 2015 * Update utt message to change file message to dbus ipc (Dongyeol Lee ) * Remove unused smack label (Kwangyoun Kim ) - * Upgate utt message IPC based on signal (Dongyeol Lee ) tts (0.2.41) -- Sat, 13 Aug 2014 diff --git a/client/tts.c b/client/tts.c index 7e327cb..59ae6b2 100644 --- a/client/tts.c +++ b/client/tts.c @@ -31,6 +31,8 @@ static Ecore_Timer* g_connect_timer = NULL; static bool g_screen_reader; +static int g_feature_enabled = -1; + /* Function definition */ static Eina_Bool __tts_notify_state_changed(void *data); static Eina_Bool __tts_notify_error(void *data); @@ -40,6 +42,30 @@ const char* tts_tag() return "ttsc"; } +static int __tts_get_feature_enabled() +{ + if (0 == g_feature_enabled) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS feature NOT supported"); + return TTS_ERROR_NOT_SUPPORTED; + } else if (-1 == g_feature_enabled) { + bool tts_supported = false; + if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { + if (false == tts_supported) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS feature NOT supported"); + g_feature_enabled = 0; + return TTS_ERROR_NOT_SUPPORTED; + } + + g_feature_enabled = 1; + } else { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get feature value"); + return TTS_ERROR_NOT_SUPPORTED; + } + } + + return 0; +} + static const char* __tts_get_error_code(tts_error_e err) { switch (err) { @@ -80,7 +106,7 @@ static int __tts_convert_config_error_code(tts_config_error_e code) 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)", - before_lang, before_voice_type, language, voice_type); + before_lang, before_voice_type, language, voice_type); GList* client_list = NULL; client_list = tts_client_get_client_list(); @@ -110,12 +136,8 @@ void __tts_config_voice_changed_cb(const char* before_lang, int before_voice_typ int tts_create(tts_h* tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Create TTS"); @@ -168,12 +190,8 @@ int tts_create(tts_h* tts) int tts_destroy(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Destroy TTS"); @@ -266,12 +284,8 @@ void __tts_screen_reader_changed_cb(bool value) int tts_set_mode(tts_h tts, tts_mode_e mode) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Set TTS mode"); @@ -325,12 +339,8 @@ int tts_set_mode(tts_h tts, tts_mode_e mode) int tts_get_mode(tts_h tts, tts_mode_e* mode) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Get TTS mode"); @@ -435,12 +445,8 @@ static Eina_Bool __tts_connect_daemon(void *data) int tts_prepare(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Prepare TTS"); @@ -473,12 +479,8 @@ int tts_prepare(tts_h tts) int tts_unprepare(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Unprepare TTS"); @@ -559,12 +561,8 @@ bool __tts_supported_voice_cb(const char* engine_id, const char* language, int t int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, void* user_data) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Foreach supported voices"); @@ -618,12 +616,8 @@ int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, voi int tts_get_default_voice(tts_h tts, char** lang, int* vctype) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Get default voice"); @@ -662,12 +656,8 @@ int tts_get_default_voice(tts_h tts, char** lang, int* vctype) int tts_get_max_text_size(tts_h tts, unsigned int* size) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == size) { @@ -695,12 +685,8 @@ int tts_get_max_text_size(tts_h tts, unsigned int* size) int tts_get_state(tts_h tts, tts_state_e* state) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == state) { @@ -730,12 +716,8 @@ int tts_get_state(tts_h tts, tts_state_e* state) int tts_get_speed_range(tts_h tts, int* min, int* normal, int* max) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == min || NULL == normal || NULL == max) { @@ -759,12 +741,18 @@ int tts_get_speed_range(tts_h tts, int* min, int* normal, int* max) int tts_add_text(tts_h tts, const char* text, const char* language, int voice_type, int speed, int* utt_id) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + 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"); @@ -887,12 +875,8 @@ int tts_add_text(tts_h tts, const char* text, const char* language, int voice_ty int tts_play(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Play tts"); @@ -962,12 +946,8 @@ int tts_play(tts_h tts) int tts_stop(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Stop tts"); @@ -1037,12 +1017,8 @@ int tts_stop(tts_h tts) int tts_pause(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } SLOG(LOG_DEBUG, TAG_TTSC, "===== Pause tts"); @@ -1210,30 +1186,6 @@ int __tts_cb_set_state(int uid, int state) return 0; } -static Eina_Bool __tts_notify_utt_started(void *data) -{ - tts_h tts = (tts_h)data; - - tts_client_s* client = tts_client_get(tts); - - /* check handle */ - if (NULL == client) { - SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to notify utt started : A handle is not valid"); - return EINA_FALSE; - } - - if (NULL != client->utt_started_cb) { - SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance started "); - tts_client_use_callback(client); - client->utt_started_cb(client->tts, client->utt_id, client->utt_started_user_data); - tts_client_not_use_callback(client); - } else { - SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance started "); - } - - return EINA_FALSE; -} - int __tts_cb_utt_started(int uid, int utt_id) { tts_client_s* client = tts_client_get_by_uid(uid); @@ -1249,36 +1201,15 @@ int __tts_cb_utt_started(int uid, int utt_id) /* call callback function */ if (NULL != client->utt_started_cb) { - ecore_timer_add(0, __tts_notify_utt_started, client->tts); - } else { - SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance started "); - } - - return 0; -} - -static Eina_Bool __tts_notify_utt_completed(void *data) -{ - tts_h tts = (tts_h)data; - - tts_client_s* client = tts_client_get(tts); - - /* check handle */ - if (NULL == client) { - SLOG(LOG_WARN, TAG_TTSC, "[WARNING] Fail to notify utt completed : A handle is not valid"); - return EINA_FALSE; - } - - if (NULL != client->utt_completeted_cb) { - SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance completed "); + SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance started "); tts_client_use_callback(client); - client->utt_completeted_cb(client->tts, client->utt_id, client->utt_completed_user_data); + client->utt_started_cb(client->tts, client->utt_id, client->utt_started_user_data); tts_client_not_use_callback(client); } else { - SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance completed "); + SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance started "); } - return EINA_FALSE; + return 0; } int __tts_cb_utt_completed(int uid, int utt_id) @@ -1296,7 +1227,10 @@ int __tts_cb_utt_completed(int uid, int utt_id) /* call callback function */ if (NULL != client->utt_completeted_cb) { - ecore_timer_add(0, __tts_notify_utt_completed, client->tts); + SLOG(LOG_DEBUG, TAG_TTSC, "Call callback function of utterance completed "); + tts_client_use_callback(client); + client->utt_completeted_cb(client->tts, client->utt_id, client->utt_completed_user_data); + tts_client_not_use_callback(client); } else { SLOG(LOG_WARN, TAG_TTSC, "No registered callback function of utterance completed "); } @@ -1306,12 +1240,8 @@ int __tts_cb_utt_completed(int uid, int utt_id) int tts_set_state_changed_cb(tts_h tts, tts_state_changed_cb callback, void* user_data) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == callback) { @@ -1341,12 +1271,8 @@ int tts_set_state_changed_cb(tts_h tts, tts_state_changed_cb callback, void* use int tts_unset_state_changed_cb(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts) { @@ -1376,12 +1302,8 @@ int tts_unset_state_changed_cb(tts_h tts) int tts_set_utterance_started_cb(tts_h tts, tts_utterance_started_cb callback, void* user_data) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == callback) { @@ -1411,12 +1333,8 @@ int tts_set_utterance_started_cb(tts_h tts, tts_utterance_started_cb callback, v int tts_unset_utterance_started_cb(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts) { @@ -1446,12 +1364,8 @@ int tts_unset_utterance_started_cb(tts_h tts) int tts_set_utterance_completed_cb(tts_h tts, tts_utterance_completed_cb callback, void* user_data) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == callback) { @@ -1481,12 +1395,8 @@ int tts_set_utterance_completed_cb(tts_h tts, tts_utterance_completed_cb callbac int tts_unset_utterance_completed_cb(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts) { @@ -1515,12 +1425,8 @@ int tts_unset_utterance_completed_cb(tts_h tts) int tts_set_error_cb(tts_h tts, tts_error_cb callback, void* user_data) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == callback) { @@ -1550,12 +1456,8 @@ int tts_set_error_cb(tts_h tts, tts_error_cb callback, void* user_data) int tts_unset_error_cb(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts) { @@ -1585,12 +1487,8 @@ int tts_unset_error_cb(tts_h tts) int tts_set_default_voice_changed_cb(tts_h tts, tts_default_voice_changed_cb callback, void* user_data) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts || NULL == callback) { @@ -1620,12 +1518,8 @@ int tts_set_default_voice_changed_cb(tts_h tts, tts_default_voice_changed_cb cal int tts_unset_default_voice_changed_cb(tts_h tts) { - bool tts_supported = false; - if (0 == system_info_get_platform_bool(TTS_FEATURE_PATH, &tts_supported)) { - if (false == tts_supported) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] TTS NOT supported"); - return TTS_ERROR_NOT_SUPPORTED; - } + if (0 != __tts_get_feature_enabled()) { + return TTS_ERROR_NOT_SUPPORTED; } if (NULL == tts) { diff --git a/client/tts_client.c b/client/tts_client.c index bd03627..75718bf 100644 --- a/client/tts_client.c +++ b/client/tts_client.c @@ -112,6 +112,9 @@ int tts_client_destroy(tts_h tts) free(data); free(tts); + SLOG(LOG_DEBUG, TAG_TTSC, "Client destroy"); + g_list_free(iter); + return TTS_ERROR_NONE; } diff --git a/client/tts_dbus.c b/client/tts_dbus.c index 16c5eea..b6fe537 100644 --- a/client/tts_dbus.c +++ b/client/tts_dbus.c @@ -94,7 +94,7 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle if (0 == __tts_cb_utt_completed(uid, uttid)) { SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts utterance completed : uid(%d) uttid(%d)", uid, uttid); } - } /* TTSD_METHOD_UTTERANCE_COMPLETED */ + } /* TTS_SIGNAL_UTTERANCE_STARTED */ else if (dbus_message_is_signal(msg, if_name, TTSD_METHOD_SET_STATE)) { int uid = 0; @@ -109,7 +109,7 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle if (0 == __tts_cb_set_state(uid, state)) { SLOG(LOG_DEBUG, TAG_TTSC, "<<<< tts state changed : uid(%d) state(%d)", uid, state); } - } /* TTSD_METHOD_SET_STATE */ + } /* TTSD_SIGNAL_SET_STATE */ else if (dbus_message_is_signal(msg, if_name, TTSD_METHOD_ERROR)) { int uid; @@ -130,7 +130,7 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle if (0 == __tts_cb_error(uid, reason, uttid)) { SLOG(LOG_ERROR, TAG_TTSC, "<<<< Get Error message : uid(%d), error(%d), uttid(%d)", uid, reason, uttid); } - } /* TTSD_METHOD_ERROR */ + } /* TTSD_SIGNAL_ERROR */ /* free the message */ dbus_message_unref(msg); @@ -175,25 +175,8 @@ int tts_dbus_open_connection() return TTS_ERROR_OPERATION_FAILED; } -#if 0 - int pid = getpid(); - - char service_name[64]; - memset(service_name, 0, 64); - snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); - - SLOG(LOG_DEBUG, TAG_TTSC, "Service name is %s", service_name); - - /* register our name on the bus, and check for errors */ - dbus_bus_request_name(g_conn_listener, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &err); - if (dbus_error_is_set(&err)) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Name Error (%s)", err.message); - dbus_error_free(&err); - } -#endif char rule[128] = {0, }; snprintf(rule, 128, "type='signal',interface='%s'", TTS_CLIENT_SERVICE_INTERFACE); - SLOG(LOG_DEBUG, TAG_TTSC, "rule is %s", rule); /* add a rule for which messages we want to see */ dbus_bus_add_match(g_conn_listener, rule, &err); @@ -225,20 +208,13 @@ int tts_dbus_close_connection() ecore_main_fd_handler_del(g_dbus_fd_handler); g_dbus_fd_handler = NULL; } -#if 0 - int pid = getpid(); - char service_name[64]; - memset(service_name, 0, 64); - snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); - snprintf(service_name, 64, "%s", TTS_CLIENT_SERVICE_NAME); + dbus_connection_close(g_conn_sender); + dbus_connection_close(g_conn_listener); + + dbus_connection_unref(g_conn_sender); + dbus_connection_unref(g_conn_listener); - dbus_bus_release_name(g_conn_listener, service_name, &err); - if (dbus_error_is_set(&err)) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Release name error (%s)", err.message); - dbus_error_free(&err); - } -#endif g_conn_sender = NULL; g_conn_listener = NULL; diff --git a/common/tts_config_mgr.c b/common/tts_config_mgr.c index 371cdbf..842df9a 100644 --- a/common/tts_config_mgr.c +++ b/common/tts_config_mgr.c @@ -124,8 +124,8 @@ int __tts_config_mgr_check_engine_is_valid(const char* engine_id) g_config_info->type = voice->type; SLOG(LOG_DEBUG, tts_tag(), "Default voice is changed : lang(%s) type(%d)", voice->language, voice->type); + break; } - break; } } } @@ -637,7 +637,7 @@ void __tts_config_screen_reader_changed_cb(keynode_t *key, void *data) { int ret; int screen_reader; - ret = vconf_get_int(TTS_ACCESSIBILITY_KEY, &screen_reader); + ret = vconf_get_bool(TTS_ACCESSIBILITY_KEY, &screen_reader); if (0 != ret) { SLOG(LOG_ERROR, tts_tag(), "[Config ERROR] Fail to get screen reader"); return; @@ -1283,8 +1283,10 @@ int tts_config_mgr_set_engine(const char* engine) return TTS_CONFIG_ERROR_INVALID_PARAMETER; /* Check current engine id with new engine id */ - if (0 == strcmp(g_config_info->engine_id, engine)) - return 0; + if (NULL != g_config_info->engine_id) { + if (0 == strcmp(g_config_info->engine_id, engine)) + return 0; + } if (0 >= g_slist_length(g_engine_list)) { SLOG(LOG_ERROR, tts_tag(), "[ERROR] There is no engine!!"); @@ -1347,13 +1349,7 @@ int tts_config_mgr_set_engine(const char* engine) if (voice->type == g_config_info->type) { /* language is valid */ is_valid_voice = true; - - if (NULL != g_config_info->language) { - free(g_config_info->language); - - g_config_info->language = strdup(voice->language); - g_config_info->type = voice->type; - } + g_config_info->type = voice->type; } break; } diff --git a/doc/images/capi_uix_tts_state_diagram.png b/doc/images/capi_uix_tts_state_diagram.png index 83efe11..81e959a 100644 Binary files a/doc/images/capi_uix_tts_state_diagram.png and b/doc/images/capi_uix_tts_state_diagram.png differ diff --git a/doc/uix_tts_doc.h b/doc/uix_tts_doc.h index 6c9b53a..03446f6 100644 --- a/doc/uix_tts_doc.h +++ b/doc/uix_tts_doc.h @@ -27,10 +27,10 @@ * \#include * * @section CAPI_UIX_TTS_MODULE_OVERVIEW Overview - * A main function of Text-To-Speech(below TTS) API reads sound data transformed by the engine using input texts. - * Applications can add input-text to queue for reading continuously and control a player that can play, pause, and stop sound data synthesized from text. + * You can use Text-To-Speech (TTS) API to read sound data transformed by the engine from input texts. + * Applications can add input-text to queue for reading continuously and control the player that can play, pause, and stop sound data synthesized from text. * - * To use of TTS, use the following steps:
+ * To use TTS, follow these steps:
* 1. Create a handle
* 2. Register callback functions for notifications
* 3. Prepare tts-daemon asynchronously
@@ -47,11 +47,21 @@ * tts_utterance_completed_cb(), tts_default_voice_changed_cb(), tts_error_cb(). * * @section CAPI_UIX_TTS_MODULE_STATE_DIAGRAM State Diagram - * The following diagram shows the life cycle and the states of the TTS. + * The following diagram shows the life cycle and the states of the TTS. + * This state diagram shows that the state can be changed from 'None' to 'Created' by calling the tts_create() function. + * Similarly, you can know the relation between the states and API functions. + * You need to know the current state before calling the API, because the TTS API is based on state machine. + * The current state can be known from the state changed callback. * * @image html capi_uix_tts_state_diagram.png "State diagram" * * @section CAPI_UIX_TTS_MODULE_STATE_TRANSITIONS State Transitions + * The following table shows previous state and post state of main function. + * It can be known what precondition is and which synchronous type is. + * Please check both previous state and post state from the table carefully. + * In case of tts_prepare() function, state doesn't be changed at once, but acynchronously. + * From the above state diagram, you can see dotted line as asynchronous api. + * In this case, the state changed callback is only way to know state transition as ready. * * * diff --git a/packaging/tts.spec b/packaging/tts.spec index 433d2b5..9658a69 100644 --- a/packaging/tts.spec +++ b/packaging/tts.spec @@ -1,6 +1,6 @@ Name: tts Summary: Text To Speech client library and daemon -Version: 0.2.42 +Version: 0.2.43 Release: 1 Group: Graphics & UI Framework/Voice Framework License: Apache-2.0 @@ -83,7 +83,7 @@ install LICENSE %{buildroot}/usr/share/license/%{name} mkdir -p %{_libdir}/voice -mkdir -p /usr/share/voice +mkdir -p /usr/share/voice/test mkdir -p /opt/usr/data/voice/tts/1.0/engine-info @@ -102,7 +102,7 @@ chown 5000:5000 /opt/usr/data/voice/tts/1.0/engine-info %{_bindir}/tts-daemon* /usr/share/dbus-1/system-services/org.tizen.voice* /etc/dbus-1/system.d/tts-server.conf -/opt/usr/devel/bin/tts-test +/usr/share/voice/test/tts-test /usr/share/license/%{name} %files devel diff --git a/server/ttsd_data.cpp b/server/ttsd_data.cpp index e295294..7270e65 100644 --- a/server/ttsd_data.cpp +++ b/server/ttsd_data.cpp @@ -11,7 +11,10 @@ * limitations under the License. */ +#include +#include #include + #include "ttsd_main.h" #include "ttsd_data.h" @@ -30,19 +33,19 @@ typedef struct int utt_id_stopped; app_state_e state; - std::vector m_speak_data; - std::vector m_wav_data; + std::list m_speak_data; + std::list m_wav_data; - std::vector m_used_voice; + std::list m_used_voice; }app_data_s; static vector g_app_list; +static pthread_mutex_t g_sound_data_mutex = PTHREAD_MUTEX_INITIALIZER; /* * functions for debug */ - int __data_show_list() { int vsize = g_app_list.size(); @@ -66,10 +69,12 @@ int __data_show_sound_list(int index) { SLOG(LOG_DEBUG, get_tag(), "----- Sound list -----"); - unsigned int i; - for (i=0 ; i < g_app_list[index].m_wav_data.size() ; i++) { - SECURE_SLOG(LOG_DEBUG, get_tag(), "[%dth] data size(%ld), uttid(%d), type(%d)", - i+1, g_app_list[index].m_wav_data[i].data_size, g_app_list[index].m_wav_data[i].utt_id, g_app_list[index].m_wav_data[i].audio_type); + unsigned int i = 0; + std::list::iterator iter; + for (iter = g_app_list[index].m_wav_data.begin(); iter != g_app_list[index].m_wav_data.end(); iter++) { + SLOG(LOG_DEBUG, get_tag(), "[%dth][%p] data(%p) data size(%ld), uttid(%d), type(%d)", + i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type); + i++; } if (i == 0) { @@ -84,11 +89,12 @@ int __data_show_text_list(int index) { SLOG(LOG_DEBUG, get_tag(), "----- Text list -----"); - unsigned int i; - for (i=0 ; i< g_app_list[index].m_speak_data.size() ; i++) { - SECURE_SLOG(LOG_DEBUG, get_tag(), "[%dth] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)", - i+1, g_app_list[index].m_speak_data[i].lang, g_app_list[index].m_speak_data[i].vctype, g_app_list[index].m_speak_data[i].speed, - g_app_list[index].m_speak_data[i].utt_id, g_app_list[index].m_speak_data[i].text); + unsigned int i = 0; + std::list::iterator iter; + for (iter = g_app_list[index].m_speak_data.begin(); iter != g_app_list[index].m_speak_data.end(); iter++) { + SLOG(LOG_DEBUG, get_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)", + i + 1, *iter, (*iter)->lang, (*iter)->vctype, (*iter)->speed, (*iter)->utt_id, (*iter)->text); + i++; } if (0 == i) { @@ -101,19 +107,20 @@ int __data_show_text_list(int index) int __data_show_used_voice_list(int index) { - SLOG(LOG_DEBUG, get_tag(), "----- Voice list -----"); + SLOG(LOG_DEBUG, get_tag(), "----- Used voice list -----"); - unsigned int i; - for (i=0 ; i< g_app_list[index].m_speak_data.size() ; i++) { - SECURE_SLOG(LOG_DEBUG, get_tag(), "[%dth] lang(%s), vctype(%d)", - i+1, g_app_list[index].m_used_voice[i].lang, g_app_list[index].m_used_voice[i].vctype); + unsigned int i = 0; + std::list::iterator iter; + for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); iter++) { + SLOG(LOG_DEBUG, get_tag(), "[%dth] lang(%s), vctype(%d)", i + 1, iter->lang, iter->vctype); + i++; } if (0 == i) { SLOG(LOG_DEBUG, get_tag(), "No Voice Data"); } - SLOG(LOG_DEBUG, get_tag(), "---------------------"); + SLOG(LOG_DEBUG, get_tag(), "---------------------------"); return TTSD_ERROR_NONE; } @@ -223,12 +230,10 @@ int ttsd_data_set_used_voice(int uid, const char* lang, int type) } /* Find voice */ - int vsize = g_app_list[index].m_used_voice.size(); - int i = 0; + std::list::iterator iter; - for (i = 0;i < vsize;i++) { - if (0 == strcmp(lang, g_app_list[index].m_used_voice[i].lang) && - type == g_app_list[index].m_used_voice[i].vctype) { + for (iter = g_app_list[index].m_used_voice.begin();iter != g_app_list[index].m_used_voice.end();iter++) { + if (0 == strcmp(lang, iter->lang) && type == iter->vctype) { SLOG(LOG_DEBUG, get_tag(), "[DATA] The voice is already registered (%s)(%d)", lang, type); return 0; } @@ -258,28 +263,33 @@ int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback) return TTSD_ERROR_INVALID_PARAMETER; } + if (NULL == callback) { + SLOG(LOG_WARN, get_tag(), "[DATA WARNING] Used voice callback is NULL"); + } + /* Find voice */ - int vsize = g_app_list[index].m_used_voice.size(); - int i = 0; + std::list::iterator iter; - for (i = 0;i < vsize;i++) { + for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); iter++) { if (NULL != callback) { - callback(g_app_list[index].m_used_voice[i].lang, g_app_list[index].m_used_voice[i].vctype); - } else { - SECURE_SLOG(LOG_WARN, get_tag(), "[DATA WARNING] Used voice callback is NULL"); + callback(iter->lang, iter->vctype); } - if (NULL != g_app_list[index].m_used_voice[i].lang) { - free(g_app_list[index].m_used_voice[i].lang); + if (NULL != iter->lang) { + free(iter->lang); } } g_app_list[index].m_used_voice.clear(); +#ifdef DATA_DEBUG + __data_show_used_voice_list(index); +#endif + return TTSD_ERROR_NONE; } -int ttsd_data_add_speak_data(int uid, speak_data_s data) +int ttsd_data_add_speak_data(int uid, speak_data_s* data) { int index = 0; index = ttsd_data_is_client(uid); @@ -291,7 +301,7 @@ int ttsd_data_add_speak_data(int uid, speak_data_s data) g_app_list[index].m_speak_data.insert(g_app_list[index].m_speak_data.end(), data); - if (1 == data.utt_id) + if (1 == data->utt_id) g_app_list[index].utt_id_stopped = 0; #ifdef DATA_DEBUG @@ -300,7 +310,7 @@ int ttsd_data_add_speak_data(int uid, speak_data_s data) return TTSD_ERROR_NONE; } -int ttsd_data_get_speak_data(int uid, speak_data_s* data) +int ttsd_data_get_speak_data(int uid, speak_data_s** data) { int index = 0; index = ttsd_data_is_client(uid); @@ -317,14 +327,9 @@ int ttsd_data_get_speak_data(int uid, speak_data_s* data) return -1; } - data->lang = g_strdup(g_app_list[index].m_speak_data[0].lang); - data->vctype = g_app_list[index].m_speak_data[0].vctype; - data->speed = g_app_list[index].m_speak_data[0].speed; - - data->text = g_app_list[index].m_speak_data[0].text; - data->utt_id = g_app_list[index].m_speak_data[0].utt_id; - - g_app_list[index].m_speak_data.erase(g_app_list[index].m_speak_data.begin()); + std::list::iterator iter = g_app_list[index].m_speak_data.begin(); + *data = *iter; + g_app_list[index].m_speak_data.pop_front(); #ifdef DATA_DEBUG __data_show_text_list(index); @@ -332,7 +337,7 @@ int ttsd_data_get_speak_data(int uid, speak_data_s* data) return TTSD_ERROR_NONE; } -int ttsd_data_add_sound_data(int uid, sound_data_s data) +int ttsd_data_add_sound_data(int uid, sound_data_s* data) { int index = 0; index = ttsd_data_is_client(uid); @@ -342,15 +347,26 @@ int ttsd_data_add_sound_data(int uid, sound_data_s data) return TTSD_ERROR_INVALID_PARAMETER; } + if (NULL == data) { + SLOG(LOG_ERROR, get_tag(), "[DATA ERROR] sound data is NULL"); + return TTSD_ERROR_INVALID_PARAMETER; + } + /* mutex is locked */ + pthread_mutex_lock(&g_sound_data_mutex); + g_app_list[index].m_wav_data.insert(g_app_list[index].m_wav_data.end(), data); #ifdef DATA_DEBUG __data_show_sound_list(index); #endif + + /* mutex is unlocked */ + pthread_mutex_unlock(&g_sound_data_mutex); + return TTSD_ERROR_NONE; } -int ttsd_data_get_sound_data(int uid, sound_data_s* data) +int ttsd_data_get_sound_data(int uid, sound_data_s** data) { int index = 0; index = ttsd_data_is_client(uid); @@ -360,26 +376,29 @@ int ttsd_data_get_sound_data(int uid, sound_data_s* data) return TTSD_ERROR_INVALID_PARAMETER; } + /* mutex is locked */ + pthread_mutex_lock(&g_sound_data_mutex); + if (0 == g_app_list[index].m_wav_data.size()) { #ifdef DATA_DEBUG SLOG(LOG_DEBUG, get_tag(), "[DATA] There is no wav data"); #endif + /* mutex is unlocked */ + pthread_mutex_unlock(&g_sound_data_mutex); return -1; } - data->data = g_app_list[index].m_wav_data[0].data; - data->data_size = g_app_list[index].m_wav_data[0].data_size; - data->utt_id = g_app_list[index].m_wav_data[0].utt_id; - data->audio_type = g_app_list[index].m_wav_data[0].audio_type; - data->rate = g_app_list[index].m_wav_data[0].rate; - data->channels = g_app_list[index].m_wav_data[0].channels; - data->event = g_app_list[index].m_wav_data[0].event; - - g_app_list[index].m_wav_data.erase(g_app_list[index].m_wav_data.begin()); + std::list::iterator iter = g_app_list[index].m_wav_data.begin(); + *data = *iter; + g_app_list[index].m_wav_data.pop_front(); #ifdef DATA_DEBUG __data_show_sound_list(index); #endif + + /* mutex is unlocked */ + pthread_mutex_unlock(&g_sound_data_mutex); + return TTSD_ERROR_NONE; } @@ -407,17 +426,32 @@ int ttsd_data_clear_data(int uid) } int removed_last_uttid = -1; + speak_data_s* temp_speak = NULL; + sound_data_s* temp_sound = NULL; + /* free allocated data */ while(1) { - speak_data_s temp; - if (0 != ttsd_data_get_speak_data(uid, &temp)) { + if (0 != ttsd_data_get_speak_data(uid, &temp_speak)) { break; } - if (NULL != temp.text) free(temp.text); - if (NULL != temp.lang) free(temp.lang); + if (NULL != temp_speak) { + SLOG(LOG_DEBUG, get_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)", + temp_speak->utt_id, temp_speak->text, temp_speak->lang, temp_speak->vctype, temp_speak->speed); + + if (NULL != temp_speak->text) { + free(temp_speak->text); + temp_speak->text = NULL; + } + if (NULL != temp_speak->lang) { + free(temp_speak->lang); + temp_speak->lang = NULL; + } + removed_last_uttid = temp_speak->utt_id; - removed_last_uttid = temp.utt_id; + free(temp_speak); + temp_speak = NULL; + } } if (-1 != removed_last_uttid) { @@ -425,15 +459,21 @@ int ttsd_data_clear_data(int uid) } while(1) { - sound_data_s temp; - if (0 != ttsd_data_get_sound_data(uid, &temp)) { + if (0 != ttsd_data_get_sound_data(uid, &temp_sound)) { break; } - if (0 < temp.data_size) { - if (NULL != temp.data) free(temp.data); - } else { - SLOG(LOG_ERROR, get_tag(), "Sound data is NULL"); + if (NULL != temp_sound) { + SLOG(LOG_ERROR, get_tag(), "[DEBUG][%p] uid(%d), event(%d) data(%p) size(%d) rate(%d) utt(%d)", + temp_sound, uid, temp_sound->event, temp_sound->data, temp_sound->data_size, temp_sound->rate, temp_sound->utt_id); + + if (NULL != temp_sound->data) { + free(temp_sound->data); + temp_sound->data = NULL; + } + + free(temp_sound); + temp_sound = NULL; } } @@ -605,23 +645,33 @@ int ttsd_data_save_error_log(int uid, FILE* fp) unsigned int i; index = ttsd_data_is_client(uid); + if (0 > index) { + SLOG(LOG_ERROR, get_tag(), "[ERROR] Invalid client"); + return -1; + } /* get sound data */ fprintf(fp, "----- Sound list -----"); - - for (i=0 ; i < g_app_list[index].m_wav_data.size() ; i++) { - fprintf(fp, "[%dth] data size(%d), uttid(%d), type(%d)", - i+1, g_app_list[index].m_wav_data[i].data_size, g_app_list[index].m_wav_data[i].utt_id, g_app_list[index].m_wav_data[i].audio_type ); + + i = 0; + std::list::iterator iter; + for (iter = g_app_list[index].m_wav_data.begin(); iter != g_app_list[index].m_wav_data.end(); iter++) { + SLOG(LOG_DEBUG, get_tag(), "[%dth][%p] data(%p) data size(%ld), uttid(%d), type(%d)", + i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type); + i++; } + fprintf(fp, "----------------------"); /* get speck data */ fprintf(fp, "----- Text list -----"); - for (i=0 ; i< g_app_list[index].m_speak_data.size() ; i++) { - fprintf(fp, "[%dth] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)", - i+1, g_app_list[index].m_speak_data[i].lang, g_app_list[index].m_speak_data[i].vctype, g_app_list[index].m_speak_data[i].speed, - g_app_list[index].m_speak_data[i].utt_id, g_app_list[index].m_speak_data[i].text ); + i = 0; + std::list::iterator iter_speak; + for (iter_speak = g_app_list[index].m_speak_data.begin(); iter_speak != g_app_list[index].m_speak_data.end(); iter_speak++) { + SLOG(LOG_DEBUG, get_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)", + i, *iter_speak, (*iter_speak)->lang, (*iter_speak)->vctype, (*iter_speak)->speed, (*iter_speak)->utt_id, (*iter_speak)->text); + i++; } fprintf(fp, "---------------------"); diff --git a/server/ttsd_data.h b/server/ttsd_data.h index 1c94ebf..8039e9e 100644 --- a/server/ttsd_data.h +++ b/server/ttsd_data.h @@ -62,16 +62,16 @@ int ttsd_data_get_client_count(); int ttsd_data_get_pid(int uid); /* speak data */ -int ttsd_data_add_speak_data(int uid, speak_data_s data); +int ttsd_data_add_speak_data(int uid, speak_data_s* data); -int ttsd_data_get_speak_data(int uid, speak_data_s* data); +int ttsd_data_get_speak_data(int uid, speak_data_s** data); int ttsd_data_get_speak_data_size(int uid); /* sound data */ -int ttsd_data_add_sound_data(int uid, sound_data_s data); +int ttsd_data_add_sound_data(int uid, sound_data_s* data); -int ttsd_data_get_sound_data(int uid, sound_data_s* data); +int ttsd_data_get_sound_data(int uid, sound_data_s** data); int ttsd_data_get_sound_data_size(int uid); @@ -95,8 +95,6 @@ int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data) bool ttsd_data_is_uttid_valid(int uid, int uttid); -int ttsd_data_is_current_playing(); - int ttsd_data_get_same_pid_client_count(int pid); /* For error handing */ diff --git a/server/ttsd_dbus.c b/server/ttsd_dbus.c index f15c6d4..7ada226 100644 --- a/server/ttsd_dbus.c +++ b/server/ttsd_dbus.c @@ -27,7 +27,7 @@ static DBusConnection* g_conn_listener = NULL; static Ecore_Fd_Handler* g_dbus_fd_handler = NULL; -static int g_waiting_time = 3000; +//static int g_waiting_time = 3000; static char *g_service_name = NULL; static char *g_service_object = NULL; @@ -64,12 +64,10 @@ int ttsdc_send_hello(int pid, int uid) char service_name[64]; memset(service_name, 0, 64); - /*snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); */ - snprintf(service_name, 64, "%s", TTS_CLIENT_SERVICE_NAME); + snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); char target_if_name[64]; - /*snprintf(target_if_name, sizeof(target_if_name), "%s%d", TTS_CLIENT_SERVICE_INTERFACE, pid); */ - snprintf(target_if_name, sizeof(target_if_name), "%s", TTS_CLIENT_SERVICE_INTERFACE); + snprintf(target_if_name, sizeof(target_if_name), "%s%d", TTS_CLIENT_SERVICE_INTERFACE, pid); DBusMessage* msg; @@ -129,16 +127,12 @@ int ttsdc_send_message(int pid, int uid, int data, const char *method) return -1; } - char target_if_name[64]; - memset(target_if_name, 0, 64); - snprintf(target_if_name, sizeof(target_if_name), "%s", TTS_CLIENT_SERVICE_INTERFACE); - DBusMessage* msg = NULL; - /* create a message & check for errors */ + /* create a message */ msg = dbus_message_new_signal( TTS_CLIENT_SERVICE_OBJECT_PATH, /* object name of the signal */ - target_if_name, /* interface name of the signal */ + TTS_CLIENT_SERVICE_INTERFACE, /* interface name of the signal */ method); /* name of the signal */ if (NULL == msg) { @@ -158,6 +152,8 @@ int ttsdc_send_message(int pid, int uid, int data, const char *method) dbus_connection_flush(g_conn_sender); } + dbus_message_unref(msg); + return 0; } @@ -183,20 +179,13 @@ int ttsdc_send_error_message(int pid, int uid, int uttid, int reason) return -1; } - char service_name[64]; - memset(service_name, 0, 64); - snprintf(service_name, 64, "%s%d", TTS_CLIENT_SERVICE_NAME, pid); - - char target_if_name[128]; - snprintf(target_if_name, sizeof(target_if_name), "%s%d", TTS_CLIENT_SERVICE_INTERFACE, pid); - - DBusMessage* msg; + DBusMessage* msg = NULL; - msg = dbus_message_new_method_call( - service_name, - TTS_CLIENT_SERVICE_OBJECT_PATH, - target_if_name, - TTSD_METHOD_ERROR); + /* create a message */ + msg = dbus_message_new_signal( + TTS_CLIENT_SERVICE_OBJECT_PATH, /* object name of the signal */ + TTS_CLIENT_SERVICE_INTERFACE, /* interface name of the signal */ + TTSD_METHOD_ERROR); /* name of the signal */ if (NULL == msg) { SLOG(LOG_ERROR, get_tag(), "[Dbus ERROR] Fail to create error message : uid(%d)", uid); @@ -289,7 +278,7 @@ int ttsd_dbus_open_connection() int ret; /* Create connection for sender */ - g_conn_sender = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + g_conn_sender = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); if (dbus_error_is_set(&err)) { SLOG(LOG_ERROR, get_tag(), "[Dbus ERROR] Fail dbus_bus_get : %s", err.message); dbus_error_free(&err); @@ -301,10 +290,11 @@ int ttsd_dbus_open_connection() } /* connect to the bus and check for errors */ - g_conn_listener = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + g_conn_listener = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); if (dbus_error_is_set(&err)) { SLOG(LOG_ERROR, get_tag(), "[Dbus ERROR] Fail dbus_bus_get : %s", err.message); dbus_error_free(&err); + return -1; } if (NULL == g_conn_listener) { @@ -392,6 +382,12 @@ int ttsd_dbus_close_connection() dbus_error_free(&err); } + dbus_connection_close(g_conn_sender); + dbus_connection_close(g_conn_listener); + + dbus_connection_unref(g_conn_sender); + dbus_connection_unref(g_conn_listener); + g_conn_listener = NULL; g_conn_sender = NULL; diff --git a/server/ttsd_dbus_server.c b/server/ttsd_dbus_server.c index c720e1d..fd11070 100644 --- a/server/ttsd_dbus_server.c +++ b/server/ttsd_dbus_server.c @@ -199,7 +199,7 @@ int ttsd_dbus_server_get_support_voices(DBusConnection* conn, DBusMessage* msg) } voice_list = g_list_remove_link(voice_list, iter); - + g_list_free(iter); iter = g_list_first(voice_list); } } diff --git a/server/ttsd_engine_agent.c b/server/ttsd_engine_agent.c index 3fffd78..f41d412 100644 --- a/server/ttsd_engine_agent.c +++ b/server/ttsd_engine_agent.c @@ -85,39 +85,36 @@ static synth_result_callback g_result_cb; /** Set current engine */ -int __internal_set_current_engine(const char* engine_uuid); +static int __internal_set_current_engine(const char* engine_uuid); /** Check engine id */ -int __internal_check_engine_id(const char* engine_uuid); +static int __internal_check_engine_id(const char* engine_uuid); /** Update engine list */ -int __internal_update_engine_list(); +static int __internal_update_engine_list(); /** Get engine info */ -int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info); +static int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info); /** Callback function for result */ bool __result_cb(ttsp_result_event_e event, const void* data, unsigned int data_size, ttsp_audio_type_e audio_type, int rate, void *user_data); /** Callback function for voice list */ -bool __supported_voice_cb(const char* language, int type, void* user_data); +static bool __supported_voice_cb(const char* language, int type, void* user_data); /** Free voice list */ -void __free_voice_list(GList* voice_list); +static void __free_voice_list(GList* voice_list); /** Callback function for engine info */ -void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, +static void __engine_info_cb(const char* engine_uuid, const char* engine_name, const char* setting_ug_name, bool use_network, void* user_data); -/** Callback fucntion for engine setting */ -bool __engine_setting_cb(const char* key, const char* value, void* user_data); - /** Print list */ -int ttsd_print_enginelist(); +static int ttsd_print_enginelist(); -int ttsd_print_voicelist(); +static int ttsd_print_voicelist(); static const char* __ttsd_get_engine_error_code(ttsp_error_e err) { @@ -326,7 +323,7 @@ int ttsd_engine_agent_initialize_current_engine() return 0; } -int __internal_check_engine_id(const char* engine_uuid) +static int __internal_check_engine_id(const char* engine_uuid) { GList *iter = NULL; ttsengine_s *data = NULL; @@ -365,7 +362,7 @@ void __engine_info_cb(const char* engine_uuid, const char* engine_name, const ch return; } -int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info) +static int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info) { char *error; void* handle; @@ -445,7 +442,7 @@ int __internal_get_engine_info(const char* filepath, ttsengine_info_s** info) return 0; } -int __internal_update_engine_list() +static int __internal_update_engine_list() { /* relsease engine list */ GList *iter = NULL; @@ -459,6 +456,7 @@ int __internal_update_engine_list() if (data != NULL) free(data); g_engine_list = g_list_remove_link(g_engine_list, iter); + g_list_free(iter); iter = g_list_first(g_engine_list); } } @@ -555,7 +553,7 @@ int __internal_update_engine_list() return 0; } -int __internal_set_current_engine(const char* engine_uuid) +static int __internal_set_current_engine(const char* engine_uuid) { /* check whether engine id is valid or not. */ GList *iter = NULL; @@ -620,7 +618,53 @@ int __internal_set_current_engine(const char* engine_uuid) return 0; } -bool __set_voice_info_cb(const char* language, int type, void* user_data) +int __ttsd_get_mode(ttsp_mode_e* mode) +{ + if (NULL == mode) { + SLOG(LOG_ERROR, get_tag(), "[ERROR] Input parameter is null"); + return TTSP_ERROR_INVALID_PARAMETER; + } + + switch (ttsd_get_mode()) { + case TTSD_MODE_DEFAULT: *mode = TTSP_MODE_DEFAULT; break; + case TTSD_MODE_NOTIFICATION: *mode = TTSP_MODE_NOTIFICATION; break; + case TTSD_MODE_SCREEN_READER: *mode = TTSP_MODE_SCREEN_READER; break; + default: + SLOG(LOG_ERROR, get_tag(), "[ERROR] tts mode is NOT valid"); + } + + return 0; +} + +int __ttsd_engine_agent_get_speed_range(int* min, int* normal, int* max) +{ + if (NULL == min || NULL == normal || NULL == max) { + SLOG(LOG_ERROR, get_tag(), "[ERROR] Input parameter is null"); + return TTSP_ERROR_INVALID_PARAMETER; + } + + *min = TTS_SPEED_MIN; + *normal = TTS_SPEED_NORMAL; + *max = TTS_SPEED_MAX; + + return 0; +} + +int __ttsd_engine_agent_get_pitch_range(int* min, int* normal, int* max) +{ + if (NULL == min || NULL == normal || NULL == max) { + SLOG(LOG_ERROR, get_tag(), "[ERROR] Input parameter is null"); + return TTSP_ERROR_INVALID_PARAMETER; + } + + *min = TTS_PITCH_MIN; + *normal = TTS_PITCH_NORMAL; + *max = TTS_PITCH_MAX; + + return 0; +} + +static bool __set_voice_info_cb(const char* language, int type, void* user_data) { if (NULL == language) { SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Input parameter is NULL in voice list callback!!!!"); @@ -628,6 +672,10 @@ bool __set_voice_info_cb(const char* language, int type, void* user_data) } ttsvoice_s* voice = calloc(1, sizeof(ttsvoice_s)); + if (NULL == voice) { + SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to allocate memory"); + return false; + } voice->lang = strdup(language); voice->type = type; @@ -646,7 +694,7 @@ bool __set_voice_info_cb(const char* language, int type, void* user_data) return true; } -int __update_voice_list() +static int __update_voice_list() { /* Get voice list */ g_cur_voices = NULL; @@ -706,6 +754,9 @@ int ttsd_engine_agent_load_current_engine() /* load engine */ g_cur_engine.pdfuncs->version = 1; g_cur_engine.pdfuncs->size = sizeof(ttspd_funcs_s); + g_cur_engine.pdfuncs->get_mode = __ttsd_get_mode; + g_cur_engine.pdfuncs->get_speed_range = __ttsd_engine_agent_get_speed_range; + g_cur_engine.pdfuncs->get_pitch_range = __ttsd_engine_agent_get_pitch_range; int ret = 0; ret = g_cur_engine.ttsp_load_engine(g_cur_engine.pdfuncs, g_cur_engine.pefuncs); @@ -764,10 +815,21 @@ int ttsd_engine_agent_load_current_engine() g_cur_engine.default_lang, g_cur_engine.default_vctype); } else { SLOG(LOG_WARN, get_tag(), "[Engine Agent ERROR] Fail to load default voice : lang(%s), type(%d) result(%s)", - g_cur_engine.default_lang, g_cur_engine.default_vctype, __ttsd_get_engine_error_code(ret)); + g_cur_engine.default_lang, g_cur_engine.default_vctype, __ttsd_get_engine_error_code(ret)); + + return TTSD_ERROR_OPERATION_FAILED; + } + } + /* set default pitch */ + if (NULL != g_cur_engine.pefuncs->set_pitch) { + ret = g_cur_engine.pefuncs->set_pitch(g_cur_engine.default_pitch); + if (0 != ret) { + SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to set pitch : pitch(%d), result(%s)", + g_cur_engine.default_pitch, __ttsd_get_engine_error_code(ret)); return TTSD_ERROR_OPERATION_FAILED; } + SLOG(LOG_DEBUG, get_tag(), "[Engine Agent SUCCESS] Set default pitch : pitch(%d)", g_cur_engine.default_pitch); } #if 0 @@ -1477,6 +1539,10 @@ bool __supported_voice_cb(const char* language, int type, void* user_data) } voice_s* voice = calloc(1, sizeof(voice_s)); + if (NULL == voice) { + SLOG(LOG_ERROR, get_tag(), "[Engine Agent ERROR] Fail to allocate memory"); + return false; + } voice->language = strdup(language); voice->type = type; @@ -1556,7 +1622,7 @@ void __free_voice_list(GList* voice_list) } voice_list = g_list_remove_link(voice_list, iter); - + g_list_free(iter); iter = g_list_first(voice_list); } } diff --git a/server/ttsd_player.c b/server/ttsd_player.c index de4762f..256eca2 100644 --- a/server/ttsd_player.c +++ b/server/ttsd_player.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "ttsd_main.h" #include "ttsd_player.h" @@ -39,8 +40,8 @@ typedef struct { bool is_paused_data; int idx; - sound_data_s paused_data; -} player_s; + sound_data_s* paused_data; +}player_s; #define SOUND_BUFFER_LENGTH 2048 @@ -132,7 +133,7 @@ static int __create_audio_out(ttsp_audio_type_e type, int rate) sample_type = AUDIO_SAMPLE_TYPE_U8; } - ret = audio_out_create(rate, AUDIO_CHANNEL_MONO, sample_type, SOUND_TYPE_MEDIA, &g_audio_h); + ret = audio_out_create(rate, AUDIO_CHANNEL_MONO, sample_type, SOUND_TYPE_VOICE, &g_audio_h); if (AUDIO_IO_ERROR_NONE != ret) { g_audio_state = AUDIO_STATE_NONE; g_audio_h = NULL; @@ -195,7 +196,30 @@ static int __destroy_audio_out() static void __end_play_thread(void *data, Ecore_Thread *thread) { - SLOG(LOG_DEBUG, get_tag(), "===== End thread"); + SLOG(LOG_ERROR, get_tag(), "===== End thread"); +} + +static void __set_volume_using_voice_policy(int volume) +{ +/* + SLOG(LOG_WARN, get_tag(), "[Player WARNING] set volume policy"); + int ret = sound_manager_set_volume_voice_policy(volume); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, get_tag(), "[Player WARNING] Fail to set volume policy"); + } +*/ + return; +} + +static void __unset_volume_using_voice_policy() +{ +/* + SLOG(LOG_WARN, get_tag(), "[Player WARNING] unset volume policy"); + int ret = sound_manager_unset_volume_voice_policy(); + if (SOUND_MANAGER_ERROR_NONE != ret) { + SLOG(LOG_WARN, get_tag(), "[Player WARNING] Fail to unset volume policy"); + } +*/ return; } @@ -209,32 +233,26 @@ static void __play_thread(void *data, Ecore_Thread *thread) } player_s* player = g_playing_info; - sound_data_s wdata; + sound_data_s* sound_data = NULL; int ret = -1; int len = SOUND_BUFFER_LENGTH; int idx = 0; + /* set volume policy as 40% */ + __set_volume_using_voice_policy(40); while (1) { if (true == player->is_paused_data) { /* Resume player */ - wdata.data = player->paused_data.data; - wdata.data_size = player->paused_data.data_size; - wdata.utt_id = player->paused_data.utt_id; - wdata.audio_type = player->paused_data.audio_type; - wdata.rate = player->paused_data.rate; - wdata.channels = player->paused_data.channels; - wdata.event = player->paused_data.event; + sound_data = player->paused_data; + player->paused_data = NULL; idx = player->idx; player->is_paused_data = false; player->idx = 0; - } else { - if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) { - g_playing_info = NULL; - SLOG(LOG_DEBUG, get_tag(), "[Player] No sound data. Finish thread"); + if (NULL == sound_data) { /* Request unprepare */ ret = audio_out_unprepare(g_audio_h); if (AUDIO_IO_ERROR_NONE != ret) { @@ -244,74 +262,122 @@ static void __play_thread(void *data, Ecore_Thread *thread) } g_audio_state = AUDIO_STATE_READY; + + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } + SLOG(LOG_INFO, get_tag(), "[Player] Sound info : id(%d) data(%p) size(%d) audiotype(%d) rate(%d) event(%d)", + sound_data->utt_id, sound_data->data, sound_data->data_size, sound_data->audio_type, sound_data->rate, sound_data->event); + } else { + sound_data = NULL; + ret = ttsd_data_get_sound_data(player->uid, &sound_data); + if (0 != ret || NULL == sound_data) { + /* empty queue */ + SLOG(LOG_DEBUG, get_tag(), "[Player] No sound data. Waiting mode"); + /* release audio & recover session */ + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } else { + SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Unprepare audio"); + } + g_audio_state = AUDIO_STATE_READY; + + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); + + /* wait for new audio data come */ + while (1) { + usleep(10000); + if (NULL == g_playing_info) { + /* current playing uid is replaced */ + SLOG(LOG_DEBUG, get_tag(), "[Player] Finish thread"); + return; + } else if (0 < ttsd_data_get_sound_data_size(player->uid)) { + /* new audio data come */ + SLOG(LOG_DEBUG, get_tag(), "[Player] Resume thread"); + break; + } + } + + /* set volume policy as 40%, when resume play thread*/ + __set_volume_using_voice_policy(40); + + /* resume play thread */ + player->state = APP_STATE_PLAYING; + continue; + } /* If wdata's event is 'start', current wdata is first data of engine for synthesis. * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not. * When previous wdata's event is 'finish' and current wdata's event is 'finish', * the player should send utt started event. */ - if (TTSP_RESULT_EVENT_START == wdata.event || - (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == wdata.event)) { + if (TTSP_RESULT_EVENT_START == sound_data->event || + (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == sound_data->event)) { int pid = ttsd_data_get_pid(player->uid); if (pid <= 0) { SLOG(LOG_WARN, get_tag(), "[Send WARNIING] Current player is not valid"); + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } - if (0 != ttsdc_send_utt_start_message(pid, player->uid, wdata.utt_id)) { + if (0 != ttsdc_send_utt_start_message(pid, player->uid, sound_data->utt_id)) { SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", - pid, player->uid, wdata.utt_id); + pid, player->uid, sound_data->utt_id); } - SLOG(LOG_DEBUG, get_tag(), "[Player] Start utterance : uid(%d), uttid(%d)", player->uid, wdata.utt_id); + SLOG(LOG_DEBUG, get_tag(), "[Player] Start utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id); } /* Save last event to check utterance start */ - player->event = wdata.event; + player->event = sound_data->event; idx = 0; - if (NULL == wdata.data || 0 >= wdata.data_size) { - if (TTSP_RESULT_EVENT_FINISH == wdata.event) { + if (NULL == sound_data->data || 0 >= sound_data->data_size) { + if (TTSP_RESULT_EVENT_FINISH == sound_data->event) { SLOG(LOG_DEBUG, get_tag(), "No sound data"); /* send utterence finish signal */ int pid = ttsd_data_get_pid(player->uid); if (pid <= 0) { SLOG(LOG_WARN, get_tag(), "[Send WARNIING] Current player is not valid"); + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } - if (0 != ttsdc_send_utt_finish_message(pid, player->uid, wdata.utt_id)) { - SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, player->uid, wdata.utt_id); + if (0 != ttsdc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) { + SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", + pid, player->uid, sound_data->utt_id); } } - SLOG(LOG_DEBUG, get_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, wdata.utt_id); + SLOG(LOG_DEBUG, get_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id); continue; } } - SLOG(LOG_DEBUG, get_tag(), "[Player] Sound info : id(%d) size(%d) audiotype(%d) rate(%d) event(%d)", - wdata.utt_id, wdata.data_size, wdata.audio_type, wdata.rate, wdata.event); - - if (g_sampling_rate != wdata.rate || g_audio_type != wdata.audio_type) { + if (g_sampling_rate != sound_data->rate || g_audio_type != sound_data->audio_type) { SLOG(LOG_DEBUG, get_tag(), "[Player] Change audio handle : org type(%d) org rate(%d)", g_audio_type, g_sampling_rate); if (NULL != g_audio_h) { __destroy_audio_out(); } - if (0 > __create_audio_out(wdata.audio_type, wdata.rate)) { + if (0 > __create_audio_out(sound_data->audio_type, sound_data->rate)) { SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to create audio out"); + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } } while (APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) { - if ((unsigned int)idx >= wdata.data_size) + if ((unsigned int)idx >= sound_data->data_size) break; - if ((unsigned int)idx + SOUND_BUFFER_LENGTH > wdata.data_size) { - len = wdata.data_size - idx; + if ((unsigned int)idx + SOUND_BUFFER_LENGTH > sound_data->data_size) { + len = sound_data->data_size - idx; } else { len = SOUND_BUFFER_LENGTH; } @@ -322,13 +388,15 @@ static void __play_thread(void *data, Ecore_Thread *thread) if (AUDIO_IO_ERROR_NONE != ret) { SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to prepare audio : %d", ret); g_playing_info = NULL; + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Prepare audio"); g_audio_state = AUDIO_STATE_PLAY; } - char* temp_data = wdata.data; + char* temp_data = sound_data->data; ret = audio_out_write(g_audio_h, &temp_data[idx], len); if (0 > ret) { SLOG(LOG_WARN, get_tag(), "[Player WARNING] Fail to audio write - %d", ret); @@ -336,15 +404,32 @@ static void __play_thread(void *data, Ecore_Thread *thread) idx += len; } + if (NULL == g_playing_info && APP_STATE_PAUSED != player->state) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Current player is NULL"); + g_audio_state = AUDIO_STATE_READY; + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); + + if (NULL != sound_data) { + if (NULL != sound_data->data) { + free(sound_data->data); + sound_data->data = NULL; + } + + free(sound_data); + sound_data = NULL; + } + + return; + } + if (APP_STATE_PAUSED == player->state) { /* Save data */ - player->paused_data.data = wdata.data; - player->paused_data.data_size = wdata.data_size; - player->paused_data.utt_id = wdata.utt_id; - player->paused_data.audio_type = wdata.audio_type; - player->paused_data.rate = wdata.rate; - player->paused_data.channels = wdata.channels; - player->paused_data.event = wdata.event; + player->paused_data = sound_data; player->is_paused_data = true; player->idx = idx; @@ -359,16 +444,14 @@ static void __play_thread(void *data, Ecore_Thread *thread) } else { SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Unprepare audio"); } + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } } - if (NULL != wdata.data) { - free(wdata.data); - wdata.data = NULL; - } - - if (APP_STATE_READY == player->state) { + if (NULL == g_playing_info && APP_STATE_READY == player->state) { + /* player_stop */ g_audio_state = AUDIO_STATE_READY; SLOG(LOG_DEBUG, get_tag(), "[Player] Stop player thread"); @@ -379,25 +462,65 @@ static void __play_thread(void *data, Ecore_Thread *thread) } else { SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Unprepare audio"); } + + if (NULL != sound_data) { + if (NULL != sound_data->data) { + free(sound_data->data); + sound_data->data = NULL; + } + + free(sound_data); + sound_data = NULL; + } + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } - if (TTSP_RESULT_EVENT_FINISH == wdata.event) { + if ((APP_STATE_PLAYING == player->state || APP_STATE_PAUSED == player->state) && + (TTSP_RESULT_EVENT_FINISH == sound_data->event)) { /* send utterence finish signal */ int pid = ttsd_data_get_pid(player->uid); if (pid <= 0) { SLOG(LOG_WARN, get_tag(), "[Send WARNIING] Current player is not valid"); + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } - if (0 != ttsdc_send_utt_finish_message(pid, player->uid, wdata.utt_id)) { + if (0 != ttsdc_send_utt_finish_message(pid, player->uid, sound_data->utt_id)) { SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", - pid, player->uid, wdata.utt_id); + pid, player->uid, sound_data->utt_id); + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); return; } - SLOG(LOG_DEBUG, get_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, wdata.utt_id); + SLOG(LOG_DEBUG, get_tag(), "[Player] Finish utterance : uid(%d), uttid(%d)", player->uid, sound_data->utt_id); + } + + if (NULL != sound_data) { + if (NULL != sound_data->data) { + free(sound_data->data); + sound_data->data = NULL; + } + + free(sound_data); + sound_data = NULL; + } + + if (NULL == g_playing_info) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Current player is NULL"); + g_audio_state = AUDIO_STATE_READY; + ret = audio_out_unprepare(g_audio_h); + if (AUDIO_IO_ERROR_NONE != ret) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to unprepare audio : %d", ret); + } + /* unset volume policy, volume will be 100% */ + __unset_volume_using_voice_policy(); + + return; } } } @@ -447,10 +570,6 @@ int ttsd_player_release(void) int ret; - ret = __destroy_audio_out(); - if (0 != ret) - return -1; - SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] =========================="); SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] Active thread count : %d", ecore_thread_active_get()); SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] =========================="); @@ -462,7 +581,7 @@ int ttsd_player_release(void) usleep(10000); count++; - if (100 == count) { + if (20 == count) { SLOG(LOG_WARN, get_tag(), "[Player WARNING!!] Thread is blocked. Player release continue."); break; } @@ -472,6 +591,10 @@ int ttsd_player_release(void) SLOG(LOG_DEBUG, get_tag(), "[Player DEBUG] Thread is released"); + ret = __destroy_audio_out(); + if (0 != ret) + return -1; + /* clear g_player_list */ g_playing_info = NULL; g_player_init = false; @@ -493,15 +616,19 @@ int ttsd_player_create_instance(int uid) } player_s* new_client = (player_s*)calloc(1, sizeof(player_s)); + if (NULL == new_client) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to allocate memory"); + return TTSP_ERROR_OUT_OF_MEMORY; + } new_client->uid = uid; new_client->event = TTSP_RESULT_EVENT_FINISH; new_client->state = APP_STATE_READY; new_client->is_paused_data = false; new_client->idx = 0; - new_client->paused_data.data = NULL; - - SLOG(LOG_DEBUG, get_tag(), "[Player] Create player : uid(%d)", uid); + new_client->paused_data = NULL; + + SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Create player : uid(%d)", uid); g_player_list = g_list_append(g_player_list, new_client); @@ -544,6 +671,7 @@ int ttsd_player_destroy_instance(int uid) if (uid == data->uid) { g_player_list = g_list_remove_link(g_player_list, iter); free(data); + g_list_free(iter); break; } } @@ -569,6 +697,9 @@ int ttsd_player_play(int uid) if (uid == g_playing_info->uid) { SLOG(LOG_DEBUG, get_tag(), "[Player] uid(%d) has already played", g_playing_info->uid); return 0; + } else { + SLOG(LOG_WARN, get_tag(), "[Player WARNING] stop old player (%d)", g_playing_info->uid); + ttsd_player_stop(g_playing_info->uid); } } @@ -628,9 +759,14 @@ int ttsd_player_stop(int uid) } if (true == current->is_paused_data) { - if (NULL != current->paused_data.data) { - free(current->paused_data.data); - current->paused_data.data = NULL; + if (NULL != current->paused_data) { + if (NULL != current->paused_data->data) { + free(current->paused_data->data); + current->paused_data->data = NULL; + } + + free(current->paused_data); + current->paused_data = NULL; } } @@ -639,11 +775,73 @@ int ttsd_player_stop(int uid) current->is_paused_data = false; current->idx = 0; + if (NULL == g_playing_info) { + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + SLOG(LOG_ERROR, get_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + + /* The thread should be released */ + int thread_count = ecore_thread_active_get(); + int count = 0; + while (0 < thread_count) { + usleep(10000); + + count++; + if (30 == count) { + SLOG(LOG_WARN, get_tag(), "[Player WARNING!!] Thread is blocked. Player release continue."); + break; + } + + thread_count = ecore_thread_active_get(); + } + + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + SLOG(LOG_ERROR, get_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + } + SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid); return 0; } +int ttsd_player_clear(int uid) +{ + if (false == g_player_init) { + SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized"); + return -1; + } + + /* Check uid */ + player_s* current; + current = __player_get_item(uid); + if (NULL == current) { + SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); + return -1; + } + + if (true == current->is_paused_data) { + if (NULL != current->paused_data) { + if (NULL != current->paused_data->data) { + free(current->paused_data->data); + current->paused_data->data = NULL; + } + + free(current->paused_data); + current->paused_data = NULL; + } + } + + current->event = TTSP_RESULT_EVENT_FINISH; + current->state = APP_STATE_READY; + current->is_paused_data = false; + current->idx = 0; + + SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Clear player : uid(%d)", uid); + + return 0; +} + int ttsd_player_pause(int uid) { SLOG(LOG_DEBUG, get_tag(), "[Player] pause player : uid(%d)", uid); @@ -672,6 +870,31 @@ int ttsd_player_pause(int uid) } current->state = APP_STATE_PAUSED; + + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + SLOG(LOG_ERROR, get_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + + /* The thread should be released */ + int thread_count = ecore_thread_active_get(); + int count = 0; + while (0 < thread_count) { + usleep(10000); + + count++; + if (30 == count) { + SLOG(LOG_WARN, get_tag(), "[Player WARNING!!] Thread is blocked. Player release continue."); + break; + } + + thread_count = ecore_thread_active_get(); + } + + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + SLOG(LOG_ERROR, get_tag(), "[Player] Active thread count : %d", ecore_thread_active_get()); + SLOG(LOG_DEBUG, get_tag(), "[Player] =========================="); + + SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Pause player : uid(%d)", uid); return 0; } @@ -739,9 +962,14 @@ int ttsd_player_all_stop() data->state = APP_STATE_READY; if (true == data->is_paused_data) { - if (NULL != data->paused_data.data) { - free(data->paused_data.data); - data->paused_data.data = NULL; + if (NULL != data->paused_data) { + if (NULL != data->paused_data->data) { + free(data->paused_data->data); + data->paused_data->data = NULL; + } + + free(data->paused_data); + data->paused_data = NULL; } } diff --git a/server/ttsd_player.h b/server/ttsd_player.h index 5fcbbe5..4662b4e 100644 --- a/server/ttsd_player.h +++ b/server/ttsd_player.h @@ -47,6 +47,8 @@ int ttsd_player_play(int uid); int ttsd_player_stop(int uid); +int ttsd_player_clear(int uid); + int ttsd_player_pause(int uid); int ttsd_player_resume(int uid); diff --git a/server/ttsd_server.c b/server/ttsd_server.c index 7b452fe..1d740c4 100644 --- a/server/ttsd_server.c +++ b/server/ttsd_server.c @@ -47,6 +47,8 @@ static Ecore_Timer* g_wait_timer = NULL; static utterance_t g_utt; +static GList *g_proc_list = NULL; + /* Function definitions */ static int __synthesis(int uid); @@ -88,33 +90,45 @@ static int __synthesis(int uid) { SLOG(LOG_DEBUG, get_tag(), "===== SYNTHESIS START"); - speak_data_s sdata; - if (0 == ttsd_data_get_speak_data(uid, &sdata)) { + speak_data_s* speak_data = NULL; + if (0 == ttsd_data_get_speak_data(uid, &speak_data)) { + if (NULL == speak_data) { + return 0; + } - if (NULL == sdata.lang || NULL == sdata.text) { + if (NULL == speak_data->lang || NULL == speak_data->text) { SLOG(LOG_ERROR, get_tag(), "[Server ERROR] Current data is NOT valid"); ttsd_server_stop(uid); int pid = ttsd_data_get_pid(uid); ttsdc_send_set_state_message(pid, uid, APP_STATE_READY); - if (NULL != sdata.lang) free(sdata.lang); + if (NULL != speak_data) { + if (NULL != speak_data->lang) free(speak_data->lang); + if (NULL != speak_data->text) free(speak_data->text); + + speak_data->lang = NULL; + speak_data->text = NULL; + + free(speak_data); + speak_data = NULL; + } return 0; } g_utt.uid = uid; - g_utt.uttid = sdata.utt_id; + g_utt.uttid = speak_data->utt_id; SLOG(LOG_DEBUG, get_tag(), "-----------------------------------------------------------"); - SLOG(LOG_DEBUG, get_tag(), "ID : uid (%d), uttid(%d) ", g_utt.uid, g_utt.uttid); - SLOG(LOG_DEBUG, get_tag(), "Voice : langauge(%s), type(%d), speed(%d)", sdata.lang, sdata.vctype, sdata.speed); - SLOG(LOG_DEBUG, get_tag(), "Text : %s", sdata.text); + SECURE_SLOG(LOG_DEBUG, get_tag(), "ID : uid (%d), uttid(%d) ", g_utt.uid, g_utt.uttid); + SECURE_SLOG(LOG_DEBUG, get_tag(), "Voice : langauge(%s), type(%d), speed(%d)", speak_data->lang, speak_data->vctype, speak_data->speed); + SECURE_SLOG(LOG_DEBUG, get_tag(), "Text : %s", speak_data->text); SLOG(LOG_DEBUG, get_tag(), "-----------------------------------------------------------"); int ret = 0; __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DOING); - ret = ttsd_engine_start_synthesis(sdata.lang, sdata.vctype, sdata.text, sdata.speed, NULL); + ret = ttsd_engine_start_synthesis(speak_data->lang, speak_data->vctype, speak_data->text, speak_data->speed, NULL); if (0 != ret) { SLOG(LOG_ERROR, get_tag(), "[Server ERROR] * FAIL to start SYNTHESIS !!!! * "); @@ -128,8 +142,16 @@ static int __synthesis(int uid) g_wait_timer = ecore_timer_add(0, __wait_synthesis, NULL); } - free(sdata.lang); - free(sdata.text); + if (NULL != speak_data) { + if (NULL != speak_data->lang) free(speak_data->lang); + if (NULL != speak_data->text) free(speak_data->text); + + speak_data->lang = NULL; + speak_data->text = NULL; + + free(speak_data); + speak_data = NULL; + } } SLOG(LOG_DEBUG, get_tag(), "===== SYNTHESIS END"); @@ -151,10 +173,19 @@ int __synthesis_result_callback(ttsp_result_event_e event, const void* data, uns /* Synthesis is success */ if (TTSP_RESULT_EVENT_START == event || TTSP_RESULT_EVENT_CONTINUE == event || TTSP_RESULT_EVENT_FINISH == event) { + + if (TTSP_RESULT_EVENT_START == event) { + SLOG(LOG_DEBUG, get_tag(), "[SERVER] Event : TTSP_RESULT_EVENT_START"); + SECURE_SLOG(LOG_DEBUG, get_tag(), "[SERVER] Result Info : uid(%d), utt(%d), data(%p), data size(%d) audiotype(%d) rate(%d)", + uid, uttid, data, data_size, audio_type, rate); + } else if (TTSP_RESULT_EVENT_FINISH == event) { + SLOG(LOG_DEBUG, get_tag(), "[SERVER] Event : TTSP_RESULT_EVENT_FINISH"); + SECURE_SLOG(LOG_DEBUG, get_tag(), "[SERVER] Result Info : uid(%d), utt(%d), data(%p), data size(%d) audiotype(%d) rate(%d)", + uid, uttid, data, data_size, audio_type, rate); + } else { + /*if (TTSP_RESULT_EVENT_CONTINUE == event) SLOG(LOG_DEBUG, get_tag(), "[SERVER] Event : TTSP_RESULT_EVENT_CONTINUE");*/ + } - if (TTSP_RESULT_EVENT_START == event) SLOG(LOG_DEBUG, get_tag(), "[SERVER] Event : TTSP_RESULT_EVENT_START"); - if (TTSP_RESULT_EVENT_CONTINUE == event) SLOG(LOG_DEBUG, get_tag(), "[SERVER] Event : TTSP_RESULT_EVENT_CONTINUE"); - if (TTSP_RESULT_EVENT_FINISH == event) SLOG(LOG_DEBUG, get_tag(), "[SERVER] Event : TTSP_RESULT_EVENT_FINISH"); if (false == ttsd_data_is_uttid_valid(uid, uttid)) { __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE); @@ -164,9 +195,6 @@ int __synthesis_result_callback(ttsp_result_event_e event, const void* data, uns return 0; } - SLOG(LOG_DEBUG, get_tag(), "[SERVER] Result Info : uid(%d), utt(%d), data(%p), data size(%d) audiotype(%d) rate(%d)", - uid, uttid, data, data_size, audio_type, rate); - if (rate <= 0 || audio_type < 0 || audio_type > TTSP_AUDIO_TYPE_MAX) { __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE); SLOG(LOG_ERROR, get_tag(), "[SERVER ERROR] audio data is invalid"); @@ -176,26 +204,38 @@ int __synthesis_result_callback(ttsp_result_event_e event, const void* data, uns } /* add wav data */ - sound_data_s temp_data; - temp_data.data = NULL; - temp_data.rate = 0; - temp_data.data_size = 0; + sound_data_s* temp_sound_data = NULL; + temp_sound_data = (sound_data_s*)calloc(1, sizeof(sound_data_s)); + if (NULL == temp_sound_data) { + SLOG(LOG_ERROR, get_tag(), "[SERVER ERROR] Out of memory"); + return 0; + } + + temp_sound_data->data = NULL; + temp_sound_data->rate = 0; + temp_sound_data->data_size = 0; if (0 < data_size) { - temp_data.data = (char*)calloc(data_size, sizeof(char)); - memcpy(temp_data.data, data, data_size); + temp_sound_data->data = (char*)calloc(data_size + 5, sizeof(char)); + if (NULL != temp_sound_data->data) { + memcpy(temp_sound_data->data, data, data_size); + temp_sound_data->data_size = data_size; + SLOG(LOG_ERROR, get_tag(), "[DEBUG][free] uid(%d), event(%d) sound_data(%p) data(%p) size(%d)", + uid, event, temp_sound_data, temp_sound_data->data, temp_sound_data->data_size); + } else { + SLOG(LOG_ERROR, get_tag(), "Fail to allocate memory"); + } } else { SLOG(LOG_ERROR, get_tag(), "Sound data is NULL"); } - temp_data.data_size = data_size; - temp_data.utt_id = uttid; - temp_data.event = event; - temp_data.audio_type = audio_type; - temp_data.rate = rate; + temp_sound_data->utt_id = uttid; + temp_sound_data->event = event; + temp_sound_data->audio_type = audio_type; + temp_sound_data->rate = rate; - if (0 != ttsd_data_add_sound_data(uid, temp_data)) { - SLOG(LOG_ERROR, get_tag(), "[SERVER ERROR] Fail to add sound data : uid(%d)", uid); + if (0 != ttsd_data_add_sound_data(uid, temp_sound_data)) { + SECURE_SLOG(LOG_ERROR, get_tag(), "[SERVER ERROR] Fail to add sound data : uid(%d)", uid); } if (event == TTSP_RESULT_EVENT_FINISH) { @@ -218,8 +258,8 @@ int __synthesis_result_callback(ttsp_result_event_e event, const void* data, uns } - SLOG(LOG_DEBUG, get_tag(), "===== SYNTHESIS RESULT CALLBACK END"); - SLOG(LOG_DEBUG, get_tag(), " "); + /*SLOG(LOG_DEBUG, get_tag(), "===== SYNTHESIS RESULT CALLBACK END"); + SLOG(LOG_DEBUG, get_tag(), " ");*/ return 0; } @@ -402,6 +442,16 @@ int ttsd_initialize() int ttsd_finalize() { + GList *iter = NULL; + if (0 < g_list_length(g_proc_list)) { + iter = g_list_first(g_proc_list); + while (NULL != iter) { + g_proc_list = g_list_remove_link(g_proc_list, iter); + g_list_free(iter); + iter = g_list_first(g_proc_list); + } + } + ttsd_config_finalize(); ttsd_player_release(); @@ -411,8 +461,70 @@ int ttsd_finalize() return TTSD_ERROR_NONE; } +static void __read_proc() +{ + DIR *dp = NULL; + struct dirent entry; + struct dirent *dirp = NULL; + int ret = -1; + int tmp; + + GList *iter = NULL; + if (0 < g_list_length(g_proc_list)) { + iter = g_list_first(g_proc_list); + while (NULL != iter) { + g_proc_list = g_list_remove_link(g_proc_list, iter); + g_list_free(iter); + iter = g_list_first(g_proc_list); + } + } + + dp = opendir("/proc"); + if (NULL == dp) { + SLOG(LOG_ERROR, get_tag(), "[ERROR] Fail to open proc"); + } else { + do { + ret = readdir_r(dp, &entry, &dirp); + if (0 != ret) { + SLOG(LOG_ERROR, get_tag(), "[ERROR] Fail to readdir"); + break; + } + + if (NULL != dirp) { + tmp = atoi(dirp->d_name); + if (0 >= tmp) continue; + g_proc_list = g_list_append(g_proc_list, GINT_TO_POINTER(tmp)); + } + } while (NULL != dirp); + closedir(dp); + } + return; +} + bool __get_client_for_clean_up(int pid, int uid, app_state_e state, void* user_data) { + bool exist = false; + int i = 0; + + GList *iter = NULL; + for (i = 0; i < g_list_length(g_proc_list); i++) { + iter = g_list_nth(g_proc_list, i); + if (NULL != iter) { + if (pid == GPOINTER_TO_INT(iter->data)) { + SLOG(LOG_DEBUG, get_tag(), "uid (%d) is running", uid); + exist = true; + break; + } + } + } + + if (false == exist) { + SLOG(LOG_ERROR, get_tag(), "uid (%d) should be removed", uid); + ttsd_server_finalize(uid); + } + + return true; +#if 0 char appid[128] = {0, }; if (0 != aul_app_get_appid_bypid(pid, appid, sizeof(appid))) { SLOG(LOG_ERROR, get_tag(), "[Server ERROR] Fail to get app id"); @@ -434,12 +546,14 @@ bool __get_client_for_clean_up(int pid, int uid, app_state_e state, void* user_d } } return true; +#endif } Eina_Bool ttsd_cleanup_client(void *data) { SLOG(LOG_DEBUG, get_tag(), "===== CLEAN UP CLIENT START"); + __read_proc(); ttsd_data_foreach_clients(__get_client_for_clean_up, NULL); SLOG(LOG_DEBUG, get_tag(), "====="); SLOG(LOG_DEBUG, get_tag(), " "); @@ -511,7 +625,8 @@ int ttsd_server_finalize(int uid) } ttsd_server_stop(uid); - + ttsd_player_stop(uid); + ttsd_player_destroy_instance(uid); /* Need to unload voice when used voice is unregistered */ @@ -552,21 +667,38 @@ int ttsd_server_add_queue(int uid, const char* text, const char* lang, int voice SLOG(LOG_ERROR, get_tag(), "[Server ERROR] Fail to select valid voice : result lang is NULL"); return TTSD_ERROR_INVALID_VOICE; } + + speak_data_s* speak_data = NULL; + speak_data = (speak_data_s*)calloc(1, sizeof(speak_data_s)); + if (NULL == speak_data) { + SLOG(LOG_ERROR, get_tag(), "[Server ERROR] Fail to allocate memory"); + if (NULL != temp_lang) free(temp_lang); + return TTSD_ERROR_OPERATION_FAILED; + } - speak_data_s data; - - data.lang = strdup(lang); - data.vctype = voice_type; + speak_data->lang = strdup(lang); + speak_data->vctype = voice_type; - data.speed = speed; - data.utt_id = utt_id; + speak_data->speed = speed; + speak_data->utt_id = utt_id; - data.text = strdup(text); + speak_data->text = strdup(text); /* if state is APP_STATE_READY , APP_STATE_PAUSED , only need to add speak data to queue*/ - if (0 != ttsd_data_add_speak_data(uid, data)) { + if (0 != ttsd_data_add_speak_data(uid, speak_data)) { SLOG(LOG_ERROR, get_tag(), "[Server ERROR] Fail to add speak data"); if (NULL != temp_lang) free(temp_lang); + if (NULL != speak_data) { + if (NULL != speak_data->lang) free(speak_data->lang); + if (NULL != speak_data->text) free(speak_data->text); + + speak_data->lang = NULL; + speak_data->text = NULL; + + free(speak_data); + speak_data = NULL; + } + return TTSD_ERROR_OPERATION_FAILED; } @@ -638,6 +770,7 @@ int ttsd_server_play(int uid) } int current_uid = ttsd_data_get_current_playing(); + SLOG(LOG_ERROR, get_tag(), "[Server] playing uid (%d)", current_uid); if (uid != current_uid && -1 != current_uid) { if (TTSD_MODE_DEFAULT != ttsd_get_mode()) { @@ -648,6 +781,9 @@ int ttsd_server_play(int uid) if (0 != ttsd_server_stop(current_uid)) { SLOG(LOG_WARN, get_tag(), "[Server ERROR] Fail to stop : uid (%d)", current_uid); } + if (0 != ttsd_player_stop(current_uid)) { + SLOG(LOG_WARN, get_tag(), "[Server ERROR] Fail to player stop : uid (%d)", current_uid); + } ecore_timer_add(0, __send_interrupt_client, (void*)current_uid); } else { @@ -714,7 +850,7 @@ int ttsd_server_stop(int uid) __server_set_synth_control(TTSD_SYNTHESIS_CONTROL_EXPIRED); - if (0 != ttsd_player_stop(uid)) + if (0 != ttsd_player_clear(uid)) SLOG(LOG_WARN, get_tag(), "[Server] Fail to ttsd_player_stop()"); ttsd_data_set_client_state(uid, APP_STATE_READY); diff --git a/server/ttsp.h b/server/ttsp.h index 9414d25..929b86b 100644 --- a/server/ttsp.h +++ b/server/ttsp.h @@ -60,19 +60,14 @@ typedef enum { TTSP_RESULT_EVENT_FINISH = 3 /**< event when the sound data is last data or sound data is only one result */ }ttsp_result_event_e; -/** -* @brief Defines of speaking speed. -*/ -#define TTSP_SPEED_MIN 1 -#define TTSP_SPEED_NORMAL 8 -#define TTSP_SPEED_MAX 15 - -/** -* @brief Defines of speaking pitch. +/** +* @brief Enumerations of TTS mode. */ -#define TTSP_PITCH_MIN 1 -#define TTSP_PITCH_NORMAL 8 -#define TTSP_PITCH_MAX 15 +typedef enum { + TTSP_MODE_DEFAULT = 0, /**< Default mode for normal application */ + TTSP_MODE_NOTIFICATION = 1, /**< Notification mode */ + TTSP_MODE_SCREEN_READER = 2 /**< Accessibiliity mode */ +}ttsp_mode_e; /** * @brief Defines of voice type. @@ -257,6 +252,47 @@ typedef int (* ttspe_start_synthesis)(const char* language, int type, const char */ typedef int (* ttspe_cancel_synthesis)(void); + +/** +* @brief Gets the mode. +* +* @param[out] mode The tts daemon mode +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* +*/ +typedef int (* ttspd_get_mode)(ttsp_mode_e* mode); + +/** +* @brief Gets the speed range. +* +* @param[out] min The minimun speed value +* @param[out] normal The normal speed value +* @param[out] max The maximum speed value +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* +*/ +typedef int (* ttspd_get_speed_range)(int* min, int* normal, int* max); + +/** +* @brief Gets the pitch range. +* +* @param[out] min The minimun pitch value +* @param[out] normal The normal pitch value +* @param[out] max The maximum pitch value +* +* @return 0 on success, otherwise a negative error value +* @retval #TTSP_ERROR_NONE Successful +* @retval #TTSP_ERROR_INVALID_PARAMETER Invalid parameter +* +*/ +typedef int (* ttspd_get_pitch_range)(int* min, int* normal, int* max); + /** * @brief A structure of the engine functions */ @@ -288,6 +324,9 @@ typedef struct { int size; /**< size */ int version; /**< version */ + ttspd_get_mode get_mode; /**< Get mode */ + ttspd_get_speed_range get_speed_range; /**< Get speed range */ + ttspd_get_pitch_range get_pitch_range; /**< Get pitch range */ }ttspd_funcs_s; /** diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b23f449..eb9b623 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,7 +11,8 @@ FOREACH(flag ${pkgs_test_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie") FIND_PROGRAM(UNAME NAMES uname) EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") @@ -24,4 +25,4 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_test_LDFLAGS} tts) -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /opt/usr/devel/bin) \ No newline at end of file +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/share/voice/test) diff --git a/test/test_main.c b/test/test_main.c index 0c04033..113d898 100644 --- a/test/test_main.c +++ b/test/test_main.c @@ -45,37 +45,70 @@ static bool __tts_test_get_text_from_file(const char* path, char** text) int text_len = ftell(fp); if (0 >= text_len) { - SLOG(LOG_ERROR, tts_tag(), "File has no contents\n"); + SLOG(LOG_ERROR, tts_tag(), "File has no contents"); fclose(fp); return 0; } - SLOG(LOG_ERROR, tts_tag(), "text_len(%d)\n", text_len); + SLOG(LOG_ERROR, tts_tag(), "text_len(%d)", text_len); rewind(fp); - *text = (char*)calloc(1, text_len+1); + char* temp = NULL; + temp = (char*)calloc(1, text_len+1); - if (text == NULL) { - SLOG(LOG_ERROR, tts_tag(), "Fail to memory allocation\n"); + if (temp == NULL) { + SLOG(LOG_ERROR, tts_tag(), "Fail to memory allocation"); fclose(fp); return 0; } int result_len = 1; while (!feof(fp)) { - result_len = fread(*text, sizeof(char), text_len, fp); + result_len = fread(temp, sizeof(char), text_len, fp); if (result_len != text_len) { - SLOG(LOG_ERROR, tts_tag(), "Fail to read\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to read : result(%d) text_len(%d)", result_len, text_len); fclose(fp); + if (NULL != temp) { + free(temp); + temp = NULL; + } return 0; } } - *text[result_len] = '\0'; + temp[result_len] = '\0'; + + text = &temp; fclose(fp); return 1; } +Eina_Bool __tts_test_resume(void *data) +{ + int ret = tts_play(g_tts); + if (TTS_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "Fail to resume"); + ecore_timer_add(0, __tts_test_destroy, NULL); + return EINA_FALSE; + } + + return EINA_FALSE; +} + +Eina_Bool __tts_test_pause(void *data) +{ + int ret = tts_pause(g_tts); + if (TTS_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "Fail to pause"); + ecore_timer_add(0, __tts_test_destroy, NULL); + return EINA_FALSE; + } + + ecore_timer_add(3, __tts_test_resume, data); + + return EINA_FALSE; +} + Eina_Bool __tts_test_play(void *data) { int utt_id; @@ -86,41 +119,43 @@ Eina_Bool __tts_test_play(void *data) ret = tts_add_text(g_tts, g_text, lang, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utt_id); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to add text\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to add text"); ecore_timer_add(0, __tts_test_destroy, NULL); return EINA_FALSE; } - SLOG(LOG_ERROR, tts_tag(), "Play : utt id(%d)\n", utt_id); + SLOG(LOG_ERROR, tts_tag(), "Play : utt id(%d)", utt_id); ret = tts_play(g_tts); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to play\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to play"); ecore_timer_add(0, __tts_test_destroy, NULL); return EINA_FALSE; } +// ecore_timer_add(1, __tts_test_pause, data); + return EINA_FALSE; } Eina_Bool __tts_test_destroy(void *data) { int ret; - SLOG(LOG_ERROR, tts_tag(), "Stop\n"); + SLOG(LOG_ERROR, tts_tag(), "Stop"); ret = tts_stop(g_tts); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to stop\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to stop"); } - SLOG(LOG_ERROR, tts_tag(), "Unprepare (Disconnection)\n"); + SLOG(LOG_ERROR, tts_tag(), "Unprepare (Disconnection)"); ret = tts_unprepare(g_tts); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to unprepare\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to unprepare"); } - SLOG(LOG_ERROR, tts_tag(), "Destory tts client\n"); + SLOG(LOG_ERROR, tts_tag(), "Destory tts client"); ret = tts_destroy(g_tts); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to destroy\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to destroy"); } ecore_main_loop_quit(); @@ -131,7 +166,7 @@ Eina_Bool __tts_test_destroy(void *data) static void __tts_test_state_changed_cb(tts_h tts, tts_state_e previous, tts_state_e current, void* user_data) { if (TTS_STATE_CREATED == previous && TTS_STATE_READY == current) { - SLOG(LOG_ERROR, tts_tag(), "State is ready after prepare\n"); + SLOG(LOG_ERROR, tts_tag(), "State is ready after prepare"); ecore_timer_add(0, __tts_test_play, user_data); } @@ -140,25 +175,24 @@ static void __tts_test_state_changed_cb(tts_h tts, tts_state_e previous, tts_sta static void __tts_test_utt_started_cb(tts_h tts, int utt_id, void* user_data) { - SLOG(LOG_DEBUG, tts_tag(), "Utterance started : utt id(%d) \n", utt_id); + SLOG(LOG_DEBUG, tts_tag(), "Utterance started : utt id(%d)", utt_id); return; } static void __tts_test_utt_completed_cb(tts_h tts, int utt_id, void* user_data) { - SLOG(LOG_DEBUG, tts_tag(), "Utterance completed : utt id(%d) \n", utt_id); + SLOG(LOG_DEBUG, tts_tag(), "Utterance completed : utt id(%d)", utt_id); ecore_timer_add(0, __tts_test_destroy, NULL); return; } -int main(int argc, char *argv[]) +int main (int argc, char *argv[]) { if (1 == argc || 5 < argc) { - SLOG(LOG_DEBUG, tts_tag(), "Please check parameter\n"); - SLOG(LOG_DEBUG, tts_tag(), "Ex> tts-test 'text'\n"); - SLOG(LOG_DEBUG, tts_tag(), "Specific mode> tts-test 'text' '-sr || -noti'\n"); + SLOG(LOG_DEBUG, tts_tag(), "Please check parameter"); + SLOG(LOG_DEBUG, tts_tag(), "Ex> tts-test -t 'text'"); return 0; } @@ -169,36 +203,34 @@ int main(int argc, char *argv[]) while (NULL != argv[n]) { - if (!strcmp("-h", argv[n])) { - SLOG(LOG_DEBUG, tts_tag(), "\n"); - SLOG(LOG_DEBUG, tts_tag(), " ==========================================\n"); - SLOG(LOG_DEBUG, tts_tag(), " TTS test usage\n"); - SLOG(LOG_DEBUG, tts_tag(), " ==========================================\n\n"); - SLOG(LOG_DEBUG, tts_tag(), " -t : Synthesize text \n"); - SLOG(LOG_DEBUG, tts_tag(), " -l : Determine langage to synthesize text, ex) en_US, ko_KR ...\n"); - SLOG(LOG_DEBUG, tts_tag(), " -f : Determine file path which include text\n\n"); - SLOG(LOG_DEBUG, tts_tag(), " ***************************************************\n"); - SLOG(LOG_DEBUG, tts_tag(), " Example : #tts-test -l en_US -t \"1 2 3 4\" \n"); - SLOG(LOG_DEBUG, tts_tag(), " ***************************************************\n"); - SLOG(LOG_DEBUG, tts_tag(), "\n"); + if(!strcmp("-h", argv[n])) { + SLOG(LOG_DEBUG, tts_tag(), " =========================================="); + SLOG(LOG_DEBUG, tts_tag(), " TTS test usage"); + SLOG(LOG_DEBUG, tts_tag(), " =========================================="); + SLOG(LOG_DEBUG, tts_tag(), " -t : Synthesize text"); + SLOG(LOG_DEBUG, tts_tag(), " -l : Determine langage to synthesize text, ex) en_US, ko_KR ..."); + SLOG(LOG_DEBUG, tts_tag(), " -f : Determine file path which include text"); + SLOG(LOG_DEBUG, tts_tag(), " ***************************************************"); + SLOG(LOG_DEBUG, tts_tag(), " Example : #tts-test -l en_US -t \"1 2 3 4\" "); + SLOG(LOG_DEBUG, tts_tag(), " ***************************************************"); return 0; } /* check langage option */ if (!strcmp("-l", argv[n])) { lang = TTS_STRDUP(argv[n+1]); - SLOG(LOG_ERROR, tts_tag(), "Language : %s\n", lang); + SLOG(LOG_ERROR, tts_tag(), "Language : %s", lang); } /* check text to synthesize */ else if (!strcmp("-t", argv[n])) { g_text = TTS_STRDUP(argv[n+1]); - SLOG(LOG_ERROR, tts_tag(), "Text : %s\n", g_text); + SLOG(LOG_ERROR, tts_tag(), "Text : %s", g_text); } /* check file path to synthesize */ else if (!strcmp("-f", argv[n])) { src_path = TTS_STRDUP(argv[n+1]); - SLOG(LOG_ERROR, tts_tag(), "File path : %s\n", src_path); - if (!__tts_test_get_text_from_file(src_path, &g_text)) { + SLOG(LOG_ERROR, tts_tag(), "File path : %s", src_path); + if(!__tts_test_get_text_from_file(src_path, &g_text)) { return 0; } } @@ -216,60 +248,60 @@ int main(int argc, char *argv[]) SLOG(LOG_DEBUG, tts_tag(), " "); SLOG(LOG_DEBUG, tts_tag(), " "); - SLOG(LOG_DEBUG, tts_tag(), "===== TTS Sample start =====\n"); + SLOG(LOG_DEBUG, tts_tag(), "===== TTS Sample start ====="); - SLOG(LOG_DEBUG, tts_tag(), "Input text : %s\n", g_text ? g_text : "NULL"); - SLOG(LOG_DEBUG, tts_tag(), "Input lang : %s\n", lang ? lang : "NULL"); - SLOG(LOG_DEBUG, tts_tag(), "Input file path : %s\n", src_path ? src_path : "NULL"); + SLOG(LOG_DEBUG, tts_tag(), "Input text : %s", g_text ? g_text : "NULL"); + SLOG(LOG_DEBUG, tts_tag(), "Input lang : %s", lang ? lang : "NULL"); + SLOG(LOG_DEBUG, tts_tag(), "Input file path : %s", src_path ? src_path : "NULL"); if (!ecore_init()) { - SLOG(LOG_ERROR, tts_tag(), "[Main ERROR] Fail ecore_init()\n"); + SLOG(LOG_ERROR, tts_tag(), "[Main ERROR] Fail ecore_init()"); return 0; } int ret; - SLOG(LOG_DEBUG, tts_tag(), "Create tts client\n"); + SLOG(LOG_DEBUG, tts_tag(), "Create tts client"); ret = tts_create(&g_tts); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to create\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to create"); return 0; } - SLOG(LOG_DEBUG, tts_tag(), "Set tts mode - %d\n", mode); + SLOG(LOG_DEBUG, tts_tag(), "Set tts mode - %d", mode); ret = tts_set_mode(g_tts, mode); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to set mode\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to set mode"); tts_destroy(g_tts); return 0; } - SLOG(LOG_DEBUG, tts_tag(), "Set Callback func\n"); + SLOG(LOG_DEBUG, tts_tag(), "Set Callback func"); ret = tts_set_state_changed_cb(g_tts, __tts_test_state_changed_cb, (void*)lang); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to set state changed cb\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to set state changed cb"); tts_destroy(g_tts); return 0; } ret = tts_set_utterance_started_cb(g_tts, __tts_test_utt_started_cb, NULL); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to set utt started cb\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to set utt started cb"); tts_destroy(g_tts); return 0; } ret = tts_set_utterance_completed_cb(g_tts, __tts_test_utt_completed_cb, NULL); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to set utt completed cb\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to set utt completed cb"); tts_destroy(g_tts); return 0; } - SLOG(LOG_DEBUG, tts_tag(), "Prepare (Daemon Connection) asynchronously : Wait for ready state \n"); + SLOG(LOG_DEBUG, tts_tag(), "Prepare (Daemon Connection) asynchronously : Wait for ready state"); ret = tts_prepare(g_tts); if (TTS_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "Fail to prepare\n"); + SLOG(LOG_ERROR, tts_tag(), "Fail to prepare"); tts_destroy(g_tts); return 0; } @@ -282,7 +314,7 @@ int main(int argc, char *argv[]) if (lang) free(lang); if (g_text) free(g_text); - SLOG(LOG_DEBUG, tts_tag(), "===== TTS END =====\n\n\n"); + SLOG(LOG_DEBUG, tts_tag(), "===== TTS END ====="); return 0; }