From 97c528bb6b63162a9ab312686a5e20d6102dbc97 Mon Sep 17 00:00:00 2001 From: dyamy-lee Date: Wed, 24 Jul 2024 17:25:52 +0900 Subject: [PATCH] Add client API for letting know personal voices list to client The client can know personal voices list with tts_foreach_supported_personal_voices() API Change-Id: I0fc8eb5713183ae429d1ea163ccd42a6590acea4 --- client/tts.c | 31 ++++++++++++++++++++++++++ client/tts_client.c | 31 ++++++++++++++++++++++++++ client/tts_client.h | 6 +++++ client/tts_core.c | 35 +++++++++++++++++++++++++++++ client/tts_core.h | 1 + common/tts_config_mgr.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ common/tts_config_mgr.h | 3 +++ include/tts.h | 27 +++++++++++++++++++++++ 8 files changed, 192 insertions(+) diff --git a/client/tts.c b/client/tts.c index 0968419..d367875 100644 --- a/client/tts.c +++ b/client/tts.c @@ -580,6 +580,37 @@ int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, voi return TTS_ERROR_NONE; } +int tts_foreach_supported_personal_voices(tts_h tts, tts_supported_personal_voice_cb callback, void* user_data) +{ + RETV_IF(TTS_ERROR_NONE != __tts_get_feature_enabled(), TTS_ERROR_NOT_SUPPORTED); + + SLOG(LOG_INFO, TAG_TTSC, "@@@ Foreach supported personal voices"); + + RETVM_IF(NULL == callback, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is null"); + + tts_client_s* client = tts_client_get(tts); + RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] A handle is not valid. tts(%p)", tts); + + int ret = 0; + char* current_engine = NULL; + ret = tts_config_mgr_get_engine(¤t_engine); + if (0 != ret || NULL == current_engine) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get current engine : %d", ret); + return __tts_convert_config_error_code(ret); + } + + ret = tts_core_foreach_supported_personal_voices(client, current_engine, callback, user_data); + free(current_engine); + + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Result : %d", ret); + return ret; + } + + SLOG(LOG_DEBUG, TAG_TTSC, "@@@"); + return TTS_ERROR_NONE; +} + int tts_get_default_voice(tts_h tts, char** lang, int* vctype) { RETV_IF(TTS_ERROR_NONE != __tts_get_feature_enabled(), TTS_ERROR_NOT_SUPPORTED); diff --git a/client/tts_client.c b/client/tts_client.c index 1648d3d..24aa2ed 100644 --- a/client/tts_client.c +++ b/client/tts_client.c @@ -135,6 +135,12 @@ static inline void __set_supported_voice_cb(tts_client_s* client, tts_supported_ client->supported_voice_user_data = user_data; } +static inline void __set_supported_personal_voice_cb(tts_client_s* client, tts_supported_personal_voice_cb callback, void* user_data) +{ + client->supported_personal_voice_cb = callback; + client->supported_personal_voice_user_data = user_data; +} + static inline void __set_service_state_changed_cb(tts_client_s* client, tts_service_state_changed_cb callback, void* user_data) { if (callback != NULL) { @@ -726,6 +732,14 @@ void tts_client_set_supported_voice_cb(tts_client_s* client, tts_supported_voice __set_supported_voice_cb(client, callback, user_data); } +void tts_client_set_supported_personal_voice_cb(tts_client_s* client, tts_supported_personal_voice_cb callback, void* user_data) +{ + if (false == tts_client_is_valid_client(client)) { + return; + } + __set_supported_personal_voice_cb(client, callback, user_data); +} + void tts_client_set_service_state_changed_cb(tts_client_s* client, tts_service_state_changed_cb callback, void* user_data) { if (false == tts_client_is_valid_client(client)) { @@ -864,6 +878,14 @@ tts_supported_voice_cb tts_client_get_supported_voice_cb(tts_client_s* client) return client->supported_voice_cb; } +tts_supported_personal_voice_cb tts_client_get_supported_personal_voice_cb(tts_client_s* client) +{ + if (false == tts_client_is_valid_client(client)) { + return NULL; + } + return client->supported_personal_voice_cb; +} + void* tts_client_get_supported_voice_user_data(tts_client_s* client) { if (false == tts_client_is_valid_client(client)) { @@ -872,6 +894,14 @@ void* tts_client_get_supported_voice_user_data(tts_client_s* client) return client->supported_voice_user_data; } +void* tts_client_get_supported_personal_voice_user_data(tts_client_s* client) +{ + if (false == tts_client_is_valid_client(client)) { + return NULL; + } + return client->supported_personal_voice_user_data; +} + tts_service_state_changed_cb tts_client_get_service_state_changed_cb(tts_client_s* client) { if (false == tts_client_is_valid_client(client)) { @@ -939,4 +969,5 @@ void tts_client_unset_all_cb(tts_client_s* client) __set_supported_voice_cb(client, NULL, NULL); __set_service_state_changed_cb(client, NULL, NULL); __set_synthesized_pcm_cb(client, NULL, NULL); + __set_supported_personal_voice_cb(client, NULL, NULL); } \ No newline at end of file diff --git a/client/tts_client.h b/client/tts_client.h index 594581e..71562ee 100644 --- a/client/tts_client.h +++ b/client/tts_client.h @@ -57,6 +57,8 @@ typedef struct { void* service_state_changed_user_data; tts_synthesized_pcm_cb synthesized_pcm_cb; void* synthesized_pcm_user_data; + tts_supported_personal_voice_cb supported_personal_voice_cb; + void* supported_personal_voice_user_data; int registered_event_mask; @@ -163,6 +165,7 @@ void tts_client_set_screen_reader_changed_cb(tts_client_s* client, tts_screen_re void tts_client_set_supported_voice_cb(tts_client_s* client, tts_supported_voice_cb callback, void* user_data); void tts_client_set_service_state_changed_cb(tts_client_s* client, tts_service_state_changed_cb callback, void* user_data); void tts_client_set_synthesized_pcm_cb(tts_client_s* client, tts_synthesized_pcm_cb callback, void* user_data); +void tts_client_set_supported_personal_voice_cb(tts_client_s* client, tts_supported_personal_voice_cb callback, void* user_data); tts_state_changed_cb tts_client_get_state_changed_cb(tts_client_s* client); void* tts_client_get_state_changed_user_data(tts_client_s* client); @@ -194,6 +197,9 @@ void* tts_client_get_service_state_changed_user_data(tts_client_s* client); tts_synthesized_pcm_cb tts_client_get_synthesized_pcm_cb(tts_client_s* client); void* tts_client_get_synthesized_pcm_user_data(tts_client_s* client); +tts_supported_personal_voice_cb tts_client_get_supported_personal_voice_cb(tts_client_s* client); +void* tts_client_get_supported_personal_voice_user_data(tts_client_s* client); + int tts_client_get_registered_event_mask(tts_client_s* client); void tts_client_unset_all_cb(tts_client_s* client); diff --git a/client/tts_core.c b/client/tts_core.c index 58974cd..5c0f49b 100644 --- a/client/tts_core.c +++ b/client/tts_core.c @@ -587,6 +587,24 @@ static bool __supported_voice_cb(const char* engine_id, const char* language, in return callback(tts_client_get_handle(client), language, type, data); } +static bool __supported_personal_voice_cb(const char* language, const char* unique_id, const char* display_name, const char* device_name, void* user_data) +{ + unsigned int uid = (uintptr_t)user_data; + tts_client_s* client = tts_client_get_by_uid(uid); + RETVM_IF(NULL == client, false, "[ERROR] uid(%u) is not valid.", uid); + + /* call callback function */ + tts_supported_personal_voice_cb callback = tts_client_get_supported_personal_voice_cb(client); + void* data = tts_client_get_supported_personal_voice_user_data(client); + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get callback."); + return false; + } + + return callback(tts_client_get_handle(client), language, unique_id, display_name, device_name, data); +} + static bool __is_screen_reader_turned_on() { SLOG(LOG_DEBUG, TAG_TTSC, "[DEBUG] Update screen reader state"); @@ -1275,6 +1293,23 @@ int tts_core_foreach_supported_voices(tts_client_s* client, const char* engine_i return TTS_ERROR_NONE; } +int tts_core_foreach_supported_personal_voices(tts_client_s* client, const char* engine_id, tts_supported_personal_voice_cb callback, void* user_data) +{ + RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid."); + + tts_client_set_supported_personal_voice_cb(client, callback, user_data); + uintptr_t uid = tts_client_get_uid(client); + int ret = tts_config_mgr_get_personal_voice_list(engine_id, __supported_personal_voice_cb, (void*)uid); + tts_client_set_supported_personal_voice_cb(client, NULL, NULL); + + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to get voice list"); + return TTS_ERROR_OPERATION_FAILED; + } + + return TTS_ERROR_NONE; +} + static void set_service_out_for_each_client(gpointer data, gpointer user_data) { unsigned int instant_reprepare_uid = TTS_INVALID_UID; diff --git a/client/tts_core.h b/client/tts_core.h index 24da3a5..4103e3d 100644 --- a/client/tts_core.h +++ b/client/tts_core.h @@ -48,6 +48,7 @@ int tts_core_prepare_sync(tts_client_s* client); int tts_core_unprepare(tts_client_s* client); int tts_core_foreach_supported_voices(tts_client_s* client, const char* engine_id, tts_supported_voice_cb callback, void* user_data); +int tts_core_foreach_supported_personal_voices(tts_client_s* client, const char* engine_id, tts_supported_personal_voice_cb callback, void* user_data); // called by tts_ipc int tts_core_add_text(tts_client_s* client, const char* text, const char* language, int voice_type, int speed, int* utt_id); diff --git a/common/tts_config_mgr.c b/common/tts_config_mgr.c index dc83591..7650786 100644 --- a/common/tts_config_mgr.c +++ b/common/tts_config_mgr.c @@ -2466,3 +2466,61 @@ int tts_config_mgr_update_personal_voice(const char* engine_id, const char* lang return 0; } + +int tts_config_mgr_get_personal_voice_list(const char* engine_id, tts_config_supported_personal_voice_cb callback, void* user_data) +{ + int ret = __check_precondition(); + if (TTS_CONFIG_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSCONFIG, "Precondition is not met (%s)", get_error_message(ret)); + return ret; + } + + SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[DEBUG] engine id = %s", engine_id); + if (NULL == engine_id) { + SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Input Parameter is null"); + return TTS_CONFIG_ERROR_INVALID_PARAMETER; + } + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_TTSCONFIG, "tts_config_mgr_get_personal_voice_list callback is not set"); + return TTS_CONFIG_ERROR_INVALID_PARAMETER; + } + + char filepath[512] = {'\0',}; + + memset(filepath, '\0', 512); + snprintf(filepath, 512, "%s/%s-%s", TTS_DOWNLOAD_PERSONAL_INFO, engine_id, "personal.xml"); + + tts_personal_info_s* info = NULL; + ret = tts_parser_get_personal_info(filepath, &info); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] Fail to get personal information"); + return TTS_CONFIG_ERROR_OPERATION_FAILED; + } + + GSList *iter_personal_voice = NULL; + tts_config_personal_s* personal_voice = NULL; + if (g_slist_length(info->personal_voices) > 0) { + /* Get a first item */ + iter_personal_voice = g_slist_nth(info->personal_voices, 0); + + int j = 1; + while (NULL != iter_personal_voice) { + /*Get handle data from list*/ + personal_voice = iter_personal_voice->data; + + SLOG(LOG_DEBUG, TAG_TTSCONFIG, "[%dth] lang(%s) unique_id(%s) display_name(%s) device_name(%s)", j, personal_voice->language, personal_voice->unique_id, personal_voice->display_name, personal_voice->device_name); + if (false == callback(personal_voice->language, personal_voice->unique_id, personal_voice->display_name, personal_voice->device_name, user_data)) + break; + + /*Get next item*/ + iter_personal_voice = g_slist_next(iter_personal_voice); + j++; + } + } else { + SLOG(LOG_ERROR, TAG_TTSCONFIG, "[ERROR] No personal voices list"); + return TTS_CONFIG_ERROR_INVALID_VOICE; + } + + return TTS_CONFIG_ERROR_NONE; +} diff --git a/common/tts_config_mgr.h b/common/tts_config_mgr.h index 3f6f694..ae3eeb7 100644 --- a/common/tts_config_mgr.h +++ b/common/tts_config_mgr.h @@ -72,6 +72,8 @@ typedef void (*tts_config_bg_volume_ratio_changed_cb)(double value, void* user_d typedef void (*tts_config_screen_reader_changed_cb)(bool value, void* user_data); +typedef bool (*tts_config_supported_personal_voice_cb)(const char* language, const char* unique_id, const char* display_name, const char* device_name, void* user_data); + int tts_config_mgr_initialize(unsigned int uid, tts_config_client_type_e client_type); @@ -130,6 +132,7 @@ int tts_config_mgr_get_instant_reprepare_client(unsigned int *uid); int tts_config_mgr_set_instant_reprepare_client(const unsigned int uid); int tts_config_mgr_update_personal_voice(const char* engine_id, const char* language, const char* unique_id, const char* display_name, const char* device_name); +int tts_config_mgr_get_personal_voice_list(const char* engine_id, tts_config_supported_personal_voice_cb callback, void* user_data); #ifdef __cplusplus diff --git a/include/tts.h b/include/tts.h index 739e1df..5426800 100644 --- a/include/tts.h +++ b/include/tts.h @@ -275,6 +275,21 @@ typedef void (*tts_error_cb)(tts_h tts, int utt_id, tts_error_e reason, void* us */ typedef bool(*tts_supported_voice_cb)(tts_h tts, const char* language, int voice_type, void* user_data); +/** + * @brief Called to retrieve the supported personal vocie. + * @since_tizen 9.0 + * @param[in] tts The TTS handle + * @param[in] language Language specified as ISO 3166 alpha-2 two letter country-code followed by ISO 639-1 for the two-letter language code (for example, "ko_KR" for Korean, "en_US" for American English) + * @param[in] unique_id A unique identifier string for personal voice resource + * @param[in] display_name A display name that will be shown in UI for user selection + * @param[in] device_name A device name used for identifying the source target + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, + * @c false to break out of the loop + * @pre tts_foreach_supported_personal_voices() will invoke this callback function. + * @see tts_foreach_supported_personal_voices() +*/ +typedef bool(*tts_supported_personal_voice_cb)(tts_h tts, const char* language, const char* unique_id, const char* display_name, const char* device_name, void* user_data); /** * @brief Called when the default voice is changed. @@ -513,6 +528,18 @@ int tts_prepare_sync(tts_h tts); */ int tts_foreach_supported_voices(tts_h tts, tts_supported_voice_cb callback, void* user_data); +/** + * @brief Retrieves all supported personal voices of the current engine using callback function. + * @since_tiaen 9.0 + * @param[in] tts The TTS handle + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #TTS_ERROR_NONE Successful + * @post This function invokes tts_supported_personal_voice_cb() repeatedly for getting personal voices. +*/ +int tts_foreach_supported_personal_voices(tts_h tts, tts_supported_personal_voice_cb callback, void* user_data); /** * @brief Gets the default voice set by the user. -- 2.7.4