From 67a72ac95443149530d25409df432db79cfc8d53 Mon Sep 17 00:00:00 2001 From: "sungwook79.park" Date: Tue, 13 Feb 2024 20:06:13 +0900 Subject: [PATCH] Add silence generation API Change-Id: Id73f0c2a9ad5c406287ee911e1e1d015a54ccabd Signed-off-by: sungwook79.park --- client/tts.c | 25 ++++++- client/tts_core.c | 39 +++++++++++ client/tts_core.h | 1 + client/tts_dbus.c | 43 ++++++++++++ client/tts_dbus.h | 2 + client/tts_ipc.c | 15 +++- client/tts_ipc.h | 2 + client/tts_tidl.c | 27 ++++++++ client/tts_tidl.h | 2 + common/tts_defs.h | 1 + include/tts.h | 17 +++++ server/ttsd_data.cpp | 24 +++++-- server/ttsd_data.h | 4 +- server/ttsd_dbus.c | 3 + server/ttsd_dbus_server.c | 56 +++++++++++++++ server/ttsd_dbus_server.h | 2 + server/ttsd_server.c | 169 ++++++++++++++++++++++++++++++++++++---------- server/ttsd_server.h | 2 + server/ttsd_tidl.c | 16 +++++ tidl/tts.tidl | 1 + 20 files changed, 407 insertions(+), 44 deletions(-) diff --git a/client/tts.c b/client/tts.c index f337ea6..ea0f7d5 100644 --- a/client/tts.c +++ b/client/tts.c @@ -1419,7 +1419,6 @@ int tts_unset_synthesized_pcm_cb(tts_h tts) return TTS_ERROR_NONE; } - int tts_synthesis_parameter_create(tts_synthesis_parameter_h *parameter) { SLOG(LOG_INFO, TAG_TTSC, "@@@ Create TTS synthesis parameter handle"); @@ -1557,3 +1556,27 @@ int tts_synthesis_parameter_set_background_volume_ratio(tts_synthesis_parameter_ SLOG(LOG_DEBUG, TAG_TTSC, "[SUCCESS] Set background volume ratio(%f) to a synthesis parameter", background_volume_ratio); return TTS_ERROR_NONE; } + +int tts_add_silent_utterance(tts_h tts, long duration_in_msec, int* utt_id) +{ + RETV_IF(TTS_ERROR_NONE != __tts_get_feature_enabled(), TTS_ERROR_NOT_SUPPORTED); + + 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); + RETVM_IF(NULL == utt_id, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Input parameter is null."); + + tts_state_e current_state = tts_client_get_current_state(client); + RETVM_IF(TTS_STATE_CREATED == current_state, TTS_ERROR_INVALID_STATE, "[ERROR] The current state(%d) is invalid", current_state); + + RETVM_IF(false == tts_core_check_screen_reader(client), TTS_ERROR_SCREEN_READER_OFF, "[ERROR] Screen reader option is not available"); + RETVM_IF(false == tts_core_check_credential(client), TTS_ERROR_PERMISSION_DENIED, "[ERROR] Do not have app credential for this engine"); + + int ret = tts_core_add_silent_utterance(client, duration_in_msec, utt_id); + if (TTS_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request add silent. ret(%s)", tts_core_covert_error_code(ret)); + return ret; + } + + SLOG(LOG_DEBUG, TAG_TTSC, "@@@"); + return TTS_ERROR_NONE; +} diff --git a/client/tts_core.c b/client/tts_core.c index b389d62..3725b08 100644 --- a/client/tts_core.c +++ b/client/tts_core.c @@ -664,6 +664,34 @@ static inline int __request_add_text(tts_client_s* client, const char* text, con return TTS_ERROR_NONE; } +static inline int __request_add_silent_utterance(tts_client_s* client, long duration_in_msec, int* utt_id) +{ + int new_utt_id = tts_client_new_utterance_id(client); + if (0 > new_utt_id) { + return TTS_ERROR_OPERATION_FAILED; + } + + // TODO: If use cpp, remove dupliceated code using command class pattern + unsigned int uid = tts_client_get_uid(client); + int ret = -1; + tts_client_set_reprepared(client, false); + for (int count = 0; count < TTS_RETRY_COUNT; count++) { + ret = tts_ipc_request_add_silent_utterance(uid, duration_in_msec, new_utt_id, client->credential); + if (false == __is_ipc_retry_needed(client, ret)) { + break; + } + } + + if (TTS_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to request"); + return ret; + } + + SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success __request_add_silent_utterance"); + *utt_id = new_utt_id; + return TTS_ERROR_NONE; +} + static inline int __request_play(tts_client_s* client) { unsigned int uid = tts_client_get_uid(client); @@ -1602,3 +1630,14 @@ int tts_core_get_service_state(tts_client_s* client, tts_service_state_e* servic SLOG(LOG_INFO, TAG_TTSC, "[INFO] Success tts_core_get_service_state"); return TTS_ERROR_NONE; } + +int tts_core_add_silent_utterance(tts_client_s* client, long duration_in_msec, int* utt_id) +{ + RETVM_IF(NULL == utt_id, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Parameter is invalid."); + RETVM_IF(false == tts_client_is_valid_client(client), TTS_ERROR_INVALID_PARAMETER, "[ERROR] Client is invalid."); + reprepare_on_demand(client); + + SLOG(LOG_ERROR, TAG_TTSC, "[DEBUG] duration_in_msec(%ld)", duration_in_msec); + + return __request_add_silent_utterance(client, duration_in_msec, utt_id); +} \ No newline at end of file diff --git a/client/tts_core.h b/client/tts_core.h index 0dfa313..716a28d 100644 --- a/client/tts_core.h +++ b/client/tts_core.h @@ -51,6 +51,7 @@ int tts_core_foreach_supported_voices(tts_client_s* client, const char* engine_i // 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); +int tts_core_add_silent_utterance(tts_client_s* client, long duration_in_msec, int* utt_id); int tts_core_play(tts_client_s* client); int tts_core_stop(tts_client_s* client); int tts_core_pause(tts_client_s* client); diff --git a/client/tts_dbus.c b/client/tts_dbus.c index be7db58..8524a79 100644 --- a/client/tts_dbus.c +++ b/client/tts_dbus.c @@ -765,6 +765,49 @@ int tts_dbus_request_add_text(unsigned int uid, const char* text, const char* la return result; } +int tts_dbus_request_add_silent_utterance(unsigned int uid, long duration_in_msec, int uttid, const char* credential) +{ + DBusMessage* msg = __tts_dbus_make_message(uid, TTS_METHOD_ADD_SILENT_UTTERANCE); + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts add silent utterance : Fail to make message"); + return TTS_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts add silent utterance : uid(%u), duration_in_msec(%ld), id(%d), credential(%s)", + uid, duration_in_msec, uttid, (NULL == credential) ? "NULL" : credential); + } + + char *temp = NULL; + if (NULL == credential) { + temp = strdup("NULL"); + } else { + temp = strdup(credential); + } + + if (true != dbus_message_append_args(msg, + DBUS_TYPE_UINT32, &uid, + DBUS_TYPE_INT32, &duration_in_msec, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_STRING, &temp, + DBUS_TYPE_INVALID)) { + dbus_message_unref(msg); + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to append args"); + + if (NULL != temp) { + free(temp); + temp = NULL; + } + return TTS_ERROR_OPERATION_FAILED; + } + + int result = __send_message_and_get_result(msg, TTS_METHOD_ADD_SILENT_UTTERANCE); + if (NULL != temp) { + free(temp); + temp = NULL; + } + return result; +} + + int tts_dbus_request_set_private_data(unsigned int uid, const char* key, const char* data) { if (NULL == key || NULL == data) { diff --git a/client/tts_dbus.h b/client/tts_dbus.h index 15f2271..b25d5d8 100644 --- a/client/tts_dbus.h +++ b/client/tts_dbus.h @@ -38,6 +38,8 @@ int tts_dbus_request_finalize(unsigned int uid); int tts_dbus_request_add_text(unsigned int uid, const char* text, const char* lang, int vctype, int speed, int uttid, const char* credential); +int tts_dbus_request_add_silent_utterance(unsigned int uid, long duration_in_msec, int uttid, const char* credential); + int tts_dbus_request_play(unsigned int uid, const char* credential); int tts_dbus_request_stop(unsigned int uid); diff --git a/client/tts_ipc.c b/client/tts_ipc.c index 5229a56..47ffada 100644 --- a/client/tts_ipc.c +++ b/client/tts_ipc.c @@ -25,6 +25,7 @@ typedef enum { REQUEST_INITIALIZE, REQUEST_FINALIZE, REQUEST_ADD_TEXT, + REQUEST_ADD_SILENT_UTTERANCE, REQUEST_PLAY, REQUEST_STOP, REQUEST_PAUSE, @@ -39,14 +40,14 @@ typedef enum { static int(*ttsc_dbus_vtable[])() = { &tts_dbus_open_connection, &tts_dbus_close_connection, &tts_dbus_stop_listening, &tts_dbus_request_hello, &tts_dbus_request_hello_sync, &tts_dbus_request_initialize, - &tts_dbus_request_finalize, &tts_dbus_request_add_text, &tts_dbus_request_play, &tts_dbus_request_stop, + &tts_dbus_request_finalize, &tts_dbus_request_add_text, &tts_dbus_request_add_silent_utterance, &tts_dbus_request_play, &tts_dbus_request_stop, &tts_dbus_request_pause, &tts_dbus_request_set_private_data, &tts_dbus_request_get_private_data, &tts_dbus_request_play_pcm, &tts_dbus_request_stop_pcm, &tts_dbus_request_add_pcm, &tts_dbus_request_get_service_state }; static int(*ttsc_tidl_vtable[])() = { &tts_tidl_open_connection, &tts_tidl_close_connection, &tts_tidl_stop_listening, &tts_tidl_request_hello, &tts_tidl_request_hello_sync, &tts_tidl_request_initialize, - &tts_tidl_request_finalize, &tts_tidl_request_add_text, &tts_tidl_request_play, &tts_tidl_request_stop, + &tts_tidl_request_finalize, &tts_tidl_request_add_text, &tts_tidl_request_add_silent_utterance, &tts_tidl_request_play, &tts_tidl_request_stop, &tts_tidl_request_pause, &tts_tidl_request_set_private_data, &tts_tidl_request_get_private_data, &tts_tidl_request_play_pcm, &tts_tidl_request_stop_pcm, &tts_tidl_request_add_pcm, &tts_tidl_request_get_service_state }; @@ -159,6 +160,16 @@ int tts_ipc_request_add_text(unsigned int uid, const char* text, const char* lan return g_vtable[REQUEST_ADD_TEXT](uid, text, lang, vctype, speed, uttid, credential); } +int tts_ipc_request_add_silent_utterance(unsigned int uid, long duration_in_msec, int uttid, const char* credential) +{ + SLOG(LOG_INFO, TAG_TTSC, "[IPC] tts_ipc_request_add_silent_utterance"); + + RETVM_IF(false == tts_client_is_valid_uid(uid), TTS_ERROR_INVALID_PARAMETER, "Fail to get tts_client with uid(%u)", uid); + RETVM_IF(NULL == g_vtable, TTS_ERROR_OPERATION_FAILED, "[ERROR] IPC method is not set"); + + return g_vtable[REQUEST_ADD_SILENT_UTTERANCE](uid, duration_in_msec, uttid, credential); +} + int tts_ipc_request_set_private_data(unsigned int uid, const char* key, const char* data) { SLOG(LOG_INFO, TAG_TTSC, "[IPC] tts_ipc_request_set_private_data"); diff --git a/client/tts_ipc.h b/client/tts_ipc.h index 08abd12..73c1b47 100644 --- a/client/tts_ipc.h +++ b/client/tts_ipc.h @@ -40,6 +40,8 @@ int tts_ipc_request_finalize(unsigned int uid); int tts_ipc_request_add_text(unsigned int uid, const char* text, const char* lang, int vctype, int speed, int uttid, const char* credential); +int tts_ipc_request_add_silent_utterance(unsigned int uid, long duration_in_msec, int uttid, const char* credential); + int tts_ipc_request_play(unsigned int uid, const char* credential); int tts_ipc_request_stop(unsigned int uid); diff --git a/client/tts_tidl.c b/client/tts_tidl.c index 7edd94f..bedd2e5 100644 --- a/client/tts_tidl.c +++ b/client/tts_tidl.c @@ -659,6 +659,33 @@ int tts_tidl_request_add_text(unsigned int uid, const char* text, const char* la return TTS_ERROR_NONE; } +int tts_tidl_request_add_silent_utterance(unsigned int uid, long duration_in_msec, int uttid, const char* credential) +{ + SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_add_silent_utterance"); + + tts_client_s* client = tts_client_get_by_uid(uid); + RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client"); + + tts_tidl_info_s* info = __get_tidl_info_s(uid); + RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); + + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); + + const char *not_null_credential = NULL == credential ? "NULL" : credential; + int ret = rpc_port_proxy_tts_invoke_add_silent_utterance(info->rpc_h, uid, duration_in_msec, uttid, not_null_credential); + int exception = get_last_result(); + if (RPC_PORT_ERROR_NONE != exception) { + ret = __convert_and_handle_tidl_error(exception, info); + } + + if (TTS_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request add silent utterance : Fail to invoke message"); + return ret; + } + + return TTS_ERROR_NONE; +} + int tts_tidl_request_set_private_data(unsigned int uid, const char* key, const char* data) { SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_set_private_data"); diff --git a/client/tts_tidl.h b/client/tts_tidl.h index a8aa34b..56335c8 100644 --- a/client/tts_tidl.h +++ b/client/tts_tidl.h @@ -37,6 +37,8 @@ int tts_tidl_request_finalize(unsigned int uid); int tts_tidl_request_add_text(unsigned int uid, const char* text, const char* lang, int vctype, int speed, int uttid, const char* credential); +int tts_tidl_request_add_silent_utterance(unsigned int uid, long duration_in_msec, int uttid, const char* credential); + int tts_tidl_request_play(unsigned int uid, const char* credential); int tts_tidl_request_stop(unsigned int uid); diff --git a/common/tts_defs.h b/common/tts_defs.h index 7ba90a2..10d518d 100644 --- a/common/tts_defs.h +++ b/common/tts_defs.h @@ -74,6 +74,7 @@ extern "C" { #define TTS_METHOD_GET_SUPPORT_VOICES "tts_method_get_support_voices" #define TTS_METHOD_GET_CURRENT_VOICE "tts_method_get_current_voice" #define TTS_METHOD_ADD_TEXT "tts_method_add_text" +#define TTS_METHOD_ADD_SILENT_UTTERANCE "tts_method_add_silent_utterance" #define TTS_METHOD_PLAY "tts_method_play" #define TTS_METHOD_STOP "tts_method_stop" #define TTS_METHOD_PAUSE "tts_method_pause" diff --git a/include/tts.h b/include/tts.h index bd4e452..604cc8f 100644 --- a/include/tts.h +++ b/include/tts.h @@ -1123,6 +1123,23 @@ int tts_set_synthesized_pcm_cb(tts_h tts, tts_synthesized_pcm_cb callback, void* int tts_unset_synthesized_pcm_cb(tts_h tts); +/** + * @brief Add silence for the specified amount of time + * @since_tizen 9.0 + * @param[in] tts The TTS handle + * @param[in] duration_in_ms The duration of the silence + * @param[out] utt_id The utterance ID passed to the callback function + * @return @c 0 on success, + * otherwise a negative error value + * @retval #TTS_ERROR_NONE Successful + * @retval #TTS_ERROR_NOT_SUPPORTED TTS NOT supported + * @retval #TTS_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #TTS_ERROR_INVALID_STATE Invalid state + * @retval #TTS_ERROR_OPERATION_FAILED Operation failure + * @pre The state should be #TTS_STATE_READY, #TTS_STATE_PLAYING, or #TTS_STATE_PAUSED. +*/ +int tts_add_silent_utterance(tts_h tts, long duration_in_ms, int* utt_id); + #ifdef __cplusplus } #endif diff --git a/server/ttsd_data.cpp b/server/ttsd_data.cpp index fe36510..78c2d9b 100644 --- a/server/ttsd_data.cpp +++ b/server/ttsd_data.cpp @@ -197,8 +197,7 @@ int ttsd_data_new_client(int pid, unsigned int uid, ttsd_mode_e mode, ttsd_playi static inline void destroy_speak_data(speak_data_s* speak_data) { SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)", - speak_data->utt_id, speak_data->text, speak_data->voice.language, speak_data->voice.type, - speak_data->synth_parameter.speed); + speak_data->utt_id, speak_data->text == nullptr ? "NULL" : speak_data->text, speak_data->voice.language == nullptr ? "NULL" : speak_data->voice.language, speak_data->voice.type, speak_data->synth_parameter.speed); free(speak_data->text); speak_data->text = nullptr; @@ -484,7 +483,7 @@ int ttsd_data_reset_used_voice(unsigned int uid, ttsd_used_voice_cb callback) return TTSD_ERROR_NONE; } -speak_data_s* ttsd_data_create_speak_data(const char* text, const char* language, int voice_type, int speed, int utt_id) +speak_data_s* ttsd_data_create_speak_data(const char* text, const char* language, int voice_type, int speed, int utt_id, bool is_silent, long duration_in_msec) { speak_data_s* speak_data = new speak_data_s(); if (nullptr == speak_data) { @@ -492,8 +491,20 @@ speak_data_s* ttsd_data_create_speak_data(const char* text, const char* language return nullptr; } - speak_data->text = strdup(text); - speak_data->voice.language = strdup(language); + if (text == NULL) { + speak_data->text = nullptr; + SLOG(LOG_INFO, tts_tag(), "[DATA INFO] text of speak_data for silent generation is null"); + } else { + speak_data->text = strdup(text); + } + + if (language == NULL) { + speak_data->voice.language = nullptr; + SLOG(LOG_INFO, tts_tag(), "[DATA INFO] lang of speak_data for silent generation is null"); + } else { + speak_data->voice.language = strdup(language); + } + speak_data->voice.ptts_id = nullptr; speak_data->voice.type = voice_type; @@ -501,7 +512,10 @@ speak_data_s* ttsd_data_create_speak_data(const char* text, const char* language speak_data->synth_parameter.pitch = 0; speak_data->synth_parameter.volume = -1.0; speak_data->synth_parameter.background_volume_ratio = -1.0; + speak_data->utt_id = utt_id; + speak_data->is_silent = is_silent; + speak_data->duration_in_msec = duration_in_msec; return speak_data; } diff --git a/server/ttsd_data.h b/server/ttsd_data.h index 8611013..543bb71 100644 --- a/server/ttsd_data.h +++ b/server/ttsd_data.h @@ -55,6 +55,8 @@ typedef struct { char* text; voice_s voice; synthesis_parameter_s synth_parameter; + bool is_silent; + long duration_in_msec; } speak_data_s; typedef struct { @@ -97,7 +99,7 @@ int ttsd_data_set_credential(unsigned int uid, const char* credential); char* ttsd_data_get_credential(unsigned int uid); /* speak data */ -speak_data_s* ttsd_data_create_speak_data(const char* text, const char* language, int voice_type, int speed, int utt_id); +speak_data_s* ttsd_data_create_speak_data(const char* text, const char* language, int voice_type, int speed, int utt_id, bool is_silent, long duration_in_msec); void ttsd_data_destroy_speak_data(speak_data_s* speak_data); diff --git a/server/ttsd_dbus.c b/server/ttsd_dbus.c index 3fce979..48ecbb4 100644 --- a/server/ttsd_dbus.c +++ b/server/ttsd_dbus.c @@ -324,6 +324,9 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle } else if (dbus_message_is_method_call(msg, g_service_interface, TTS_METHOD_ADD_TEXT)) { ttsd_dbus_server_add_text(g_conn_listener, msg); + } else if (dbus_message_is_method_call(msg, g_service_interface, TTS_METHOD_ADD_SILENT_UTTERANCE)) { + ttsd_dbus_server_add_silent_utterance(g_conn_listener, msg); + } else if (dbus_message_is_method_call(msg, g_service_interface, TTS_METHOD_PLAY)) { ttsd_dbus_server_play(g_conn_listener, msg); diff --git a/server/ttsd_dbus_server.c b/server/ttsd_dbus_server.c index 59ffc0e..6c3d39c 100644 --- a/server/ttsd_dbus_server.c +++ b/server/ttsd_dbus_server.c @@ -408,6 +408,62 @@ int ttsd_dbus_server_add_text(DBusConnection* conn, DBusMessage* msg) return 0; } +int ttsd_dbus_server_add_silent_utterance(DBusConnection* conn, DBusMessage* msg) +{ + DBusError err; + dbus_error_init(&err); + + unsigned int uid, duration_in_msec, uttid; + char *credential; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_UINT32, &uid, + DBUS_TYPE_INT32, &duration_in_msec, + DBUS_TYPE_INT32, &uttid, + DBUS_TYPE_STRING, &credential, + DBUS_TYPE_INVALID); + + SLOG(LOG_DEBUG, tts_tag(), ">>>>> TTS ADD SILENT UTTERANCE"); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, tts_tag(), "[IN ERROR] tts add silent utterance : Get arguments error (%s)", err.message); + dbus_error_free(&err); + ret = TTSD_ERROR_OPERATION_FAILED; + } else { + SECURE_SLOG(LOG_DEBUG, tts_tag(), "[IN] tts add silent utterance : uid(%u), duration_in_msec(%d), uttid(%d), credential(%s)", + uid, duration_in_msec, uttid, (NULL == credential) ? "NULL" : credential); + ret = ttsd_server_add_silent_utterance(uid, duration_in_msec, uttid, credential); + } + + DBusMessage* reply; + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); + + if (0 == ret) { + SLOG(LOG_DEBUG, tts_tag(), "[OUT] tts add silent utterance : result(%d)", ret); + } else { + SLOG(LOG_ERROR, tts_tag(), "[OUT ERROR] tts add silent utterance : result(%d)", ret); + } + + if (!dbus_connection_send(conn, reply, NULL)) { + SLOG(LOG_ERROR, tts_tag(), "[OUT ERROR] tts add silent utterance : Out Of Memory!"); + } + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, tts_tag(), "[OUT ERROR] tts add silent utterance : Fail to create reply message!!"); + } + + SLOG(LOG_DEBUG, tts_tag(), "<<<<<"); + SLOG(LOG_DEBUG, tts_tag(), " "); + + return 0; +} + int ttsd_dbus_server_play(DBusConnection* conn, DBusMessage* msg) { DBusError err; diff --git a/server/ttsd_dbus_server.h b/server/ttsd_dbus_server.h index 42075fe..6c65879 100644 --- a/server/ttsd_dbus_server.h +++ b/server/ttsd_dbus_server.h @@ -39,6 +39,8 @@ int ttsd_dbus_server_get_current_voice(DBusConnection* conn, DBusMessage* msg); int ttsd_dbus_server_add_text(DBusConnection* conn, DBusMessage* msg); +int ttsd_dbus_server_add_silent_utterance(DBusConnection* conn, DBusMessage* msg); + int ttsd_dbus_server_play(DBusConnection* conn, DBusMessage* msg); int ttsd_dbus_server_stop(DBusConnection* conn, DBusMessage* msg); diff --git a/server/ttsd_server.c b/server/ttsd_server.c index 3354ec3..a5b7ec6 100644 --- a/server/ttsd_server.c +++ b/server/ttsd_server.c @@ -87,6 +87,7 @@ static int __stop_and_send_ready_state(unsigned int uid) } static void __synthesis(unsigned int uid); +static bool __generate_silent(long duration_in_msec); static Eina_Bool __wait_synthesis(void *data) { @@ -166,50 +167,63 @@ static void __synthesis(unsigned int uid) SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to get app id"); } - if (NULL == speak_data->voice.language || NULL == speak_data->text) { - SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Current data is NOT valid"); - __stop_and_send_ready_state(uid); - ttsd_data_destroy_speak_data(speak_data); - speak_data = NULL; - return; - } - g_utt.uid = uid; g_utt.uttid = speak_data->utt_id; - char* credential = ttsd_data_get_credential(uid); - SLOG(LOG_INFO, tts_tag(), "-----------------------------------------------------------"); - SLOG(LOG_INFO, tts_tag(), "ID : uid (%u), uttid(%d) ", g_utt.uid, g_utt.uttid); - SLOG(LOG_INFO, tts_tag(), "Voice : language(%s), type(%d), speed(%d)", speak_data->voice.language, - speak_data->voice.type, speak_data->synth_parameter.speed); - SLOG(LOG_INFO, tts_tag(), "Text : %s", speak_data->text); - SLOG(LOG_INFO, tts_tag(), "Credential : %s", credential); - SLOG(LOG_INFO, tts_tag(), "-----------------------------------------------------------"); - - ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DOING); - ret = ttsd_engine_start_synthesis(speak_data->voice.language, speak_data->voice.type, speak_data->text, - speak_data->synth_parameter.speed, appid, credential, NULL); - if (TTSD_ERROR_NONE != ret) { - SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] * FAIL to start SYNTHESIS !!!! * "); + if (speak_data->is_silent) { + ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DOING); + if (__generate_silent(speak_data->duration_in_msec)) { + g_wait_timer = ecore_timer_add(0.05, __wait_synthesis, (void*)credential); + } else { + SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] * FAIL to make GENERATE silent !!!! * "); - ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE); - __stop_and_send_ready_state(uid); + ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE); + __stop_and_send_ready_state(uid); + } } else { - g_wait_timer = ecore_timer_add(0.05, __wait_synthesis, (void*)credential); - } - if (ttsd_data_get_synth_control() == TTSD_SYNTHESIS_CONTROL_DOING && ttsd_state_get_state() == TTSD_STATE_READY) { - int ret = vconf_set_bool(TTS_PLAYING_STATUS_KEY, 1); - SLOG(LOG_INFO, tts_tag(), "[Server] Synthesis starting. Set playing status (True). ret(%d)", ret); + if (NULL == speak_data->voice.language || NULL == speak_data->text) { + SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Current data is NOT valid"); + __stop_and_send_ready_state(uid); + ttsd_data_destroy_speak_data(speak_data); + speak_data = NULL; + return; + } - ttsd_state_set_state(TTSD_STATE_SYNTHESIZING); - } + SLOG(LOG_INFO, tts_tag(), "-----------------------------------------------------------"); + SLOG(LOG_INFO, tts_tag(), "ID : uid (%u), uttid(%d) ", g_utt.uid, g_utt.uttid); + SLOG(LOG_INFO, tts_tag(), "Voice : language(%s), type(%d), speed(%d)", speak_data->voice.language, + speak_data->voice.type, speak_data->synth_parameter.speed); + SLOG(LOG_INFO, tts_tag(), "Text : %s", speak_data->text); + SLOG(LOG_INFO, tts_tag(), "Credential : %s", credential); + SLOG(LOG_INFO, tts_tag(), "-----------------------------------------------------------"); + + ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DOING); + ret = ttsd_engine_start_synthesis(speak_data->voice.language, speak_data->voice.type, speak_data->text, + speak_data->synth_parameter.speed, appid, credential, NULL); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] * FAIL to start SYNTHESIS !!!! * "); + + ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE); + __stop_and_send_ready_state(uid); + } else { + g_wait_timer = ecore_timer_add(0.05, __wait_synthesis, (void*)credential); + } + + if (ttsd_data_get_synth_control() == TTSD_SYNTHESIS_CONTROL_DOING && ttsd_state_get_state() == TTSD_STATE_READY) { + int ret = vconf_set_bool(TTS_PLAYING_STATUS_KEY, 1); + SLOG(LOG_INFO, tts_tag(), "[Server] Synthesis starting. Set playing status (True). ret(%d)", ret); - write_debugger_information(speak_data, appid, ret); + ttsd_state_set_state(TTSD_STATE_SYNTHESIZING); + } + + write_debugger_information(speak_data, appid, ret); + + free(credential); + credential = NULL; + } - free(credential); - credential = NULL; ttsd_data_destroy_speak_data(speak_data); speak_data = NULL; SLOG(LOG_DEBUG, tts_tag(), "@@@ SYNTHESIS END"); @@ -217,6 +231,51 @@ static void __synthesis(unsigned int uid) return; } +static bool __generate_silent(long duration_in_msec) +{ + SLOG(LOG_DEBUG, tts_tag(), "@@@ GENERATE SILENT START"); + + int audio_type = TTSE_AUDIO_TYPE_RAW_S16; + int sample_bytes = 2; + int sample_rate = 16000; + + long bytes = duration_in_msec * sample_bytes * sample_rate * 0.001; + SLOG(LOG_INFO, TAG_TTSC, "[INFO] data size for duration_in_msec in silence utterance is [%ld]", bytes); + char* data = (char*)calloc(sizeof(char), bytes); + + /* add wav data */ + sound_data_s* sound_data_start = ttsd_data_create_sound_data(g_utt.uttid, data, bytes, TTSE_RESULT_EVENT_START, audio_type, sample_rate, 0); + if (NULL == sound_data_start) { + SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] Out of memory"); + return false; + } + + if (0 != ttsd_data_add_sound_data(g_utt.uid, sound_data_start)) { + SECURE_SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] Fail to add sound data : uid(%u)", g_utt.uid); + ttsd_data_destroy_sound_data(sound_data_start); + return false; + } + + /* add finish wav data */ + sound_data_s* sound_data_finish = ttsd_data_create_sound_data(g_utt.uttid, NULL, 0, TTSE_RESULT_EVENT_FINISH, audio_type, sample_rate, 0); + if (NULL == sound_data_finish) { + SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] Out of memory"); + return false; + } + + if (0 != ttsd_data_add_sound_data(g_utt.uid, sound_data_finish)) { + SECURE_SLOG(LOG_ERROR, tts_tag(), "[SERVER ERROR] Fail to add sound data : uid(%u)", g_utt.uid); + ttsd_data_destroy_sound_data(sound_data_finish); + return false; + } + + ttsd_data_set_synth_control(TTSD_SYNTHESIS_CONTROL_DONE); + + SLOG(LOG_DEBUG, tts_tag(), "@@@ GENERATE SILENT END"); + + return true; +} + /* * TTS Server Callback Functions */ @@ -1031,7 +1090,7 @@ int ttsd_server_add_text(unsigned int uid, const char* text, const char* lang, i return TTSD_ERROR_INVALID_VOICE; } - speak_data_s* speak_data = ttsd_data_create_speak_data(text, lang, voice_type, speed, utt_id); + speak_data_s* speak_data = ttsd_data_create_speak_data(text, lang, voice_type, speed, utt_id, false, 0); if (NULL == speak_data) { SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to allocate memory"); if (NULL != temp_lang) { @@ -1097,6 +1156,46 @@ int ttsd_server_add_text(unsigned int uid, const char* text, const char* lang, i return TTSD_ERROR_NONE; } +int ttsd_server_add_silent_utterance(unsigned int uid, long duration_in_msec, int utt_id, const char* credential) +{ + app_tts_state_e state = ttsd_data_get_client_state(uid); + if (APP_STATE_NONE == state) { + SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] ttsd_server_add_silent_utterance : uid is not valid"); + return TTSD_ERROR_INVALID_PARAMETER; + } + + speak_data_s* speak_data = ttsd_data_create_speak_data(NULL, NULL, 0, 0, utt_id, true, duration_in_msec); + if (NULL == speak_data) { + SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to allocate memory"); + return TTSD_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_INFO, tts_tag(), "[Server] Add queue, uttid(%d), credential(%s)", utt_id, credential); + + int ret = -1; + ret = ttsd_data_add_speak_data(uid, speak_data); + if (0 != ret) { + SLOG(LOG_ERROR, tts_tag(), "[Server ERROR] Fail to add speak data"); + ttsd_data_destroy_speak_data(speak_data); + speak_data = NULL; + + return ret; + } + + if (APP_STATE_PLAYING == state) { + ttsd_data_set_credential(uid, credential); + ttsd_synthesis_control_e synth_control = ttsd_data_get_synth_control(); + SLOG(LOG_INFO, tts_tag(), "[Server INFO] synth_control(%d)", synth_control); + if (TTSD_SYNTHESIS_CONTROL_DOING == synth_control) { + SLOG(LOG_WARN, tts_tag(), "[Server WARNING] Engine has already been running."); + } else { + __synthesis(uid); + } + } + + return TTSD_ERROR_NONE; +} + static int __interrupt_player_by_policy(unsigned int request_app_uid) { unsigned int playing_app_uid = ttsd_data_get_current_playing(); diff --git a/server/ttsd_server.h b/server/ttsd_server.h index f6dddca..653e9cf 100644 --- a/server/ttsd_server.h +++ b/server/ttsd_server.h @@ -61,6 +61,8 @@ int ttsd_server_get_current_voice(unsigned int uid, char** language, int* voice_ int ttsd_server_add_text(unsigned int uid, const char* text, const char* lang, int voice_type, int speed, int utt_id, const char* credential); +int ttsd_server_add_silent_utterance(unsigned int uid, long duration_in_msec, int utt_id, const char* credential); + int ttsd_server_play(unsigned int uid, const char* credential); int ttsd_server_stop(unsigned int uid); diff --git a/server/ttsd_tidl.c b/server/ttsd_tidl.c index f410154..20ad2ac 100644 --- a/server/ttsd_tidl.c +++ b/server/ttsd_tidl.c @@ -334,6 +334,21 @@ static int __add_text_cb(rpc_port_stub_tts_context_h context, int uid, const cha return TTSD_ERROR_NONE; } +static int __add_silent_utterance_cb(rpc_port_stub_tts_context_h context, int uid, long long duration_in_msec, int uttid, const char *credential, void *user_data) +{ + unsigned int u_uid = (unsigned int)uid; + SLOG(LOG_DEBUG, tts_tag(), ">>>>> TTS ADD SILENT UTTERANCE (%u)", u_uid); + + int ret = ttsd_server_add_silent_utterance(u_uid, duration_in_msec, uttid, credential); + if (TTSD_ERROR_NONE != ret) { + SLOG(LOG_ERROR, tts_tag(), "[ERROR] TTS ADD SILENT UTTERANCE (%u) fail (%d/%s) <<<<<", u_uid, ret, get_error_message(ret)); + return ret; + } + + SLOG(LOG_DEBUG, tts_tag(), "<<<<<"); + return TTSD_ERROR_NONE; +} + static int __stop_cb(rpc_port_stub_tts_context_h context, int uid, void *user_data) { unsigned int u_uid = (unsigned int)uid; @@ -491,6 +506,7 @@ int ttsd_tidl_open_connection() g_callback.initialize = __initialize_cb; g_callback.finalize = __finalize_cb; g_callback.add_text = __add_text_cb; + g_callback.add_silent_utterance = __add_silent_utterance_cb; g_callback.stop = __stop_cb; g_callback.pause = __pause_cb; g_callback.play_pcm = __play_pcm_cb; diff --git a/tidl/tts.tidl b/tidl/tts.tidl index 505137b..0deb5b5 100644 --- a/tidl/tts.tidl +++ b/tidl/tts.tidl @@ -6,6 +6,7 @@ interface tts { int initialize(in int pid, in int uid, in int mode, in int playing_mode, in int registered_event_mask, out int service_state, out bool credential_needed); int finalize(in int uid); int add_text(int uid, string text, string lang, int vctype, int speed, int uttid, string credential); + int add_silent_utterance(int uid, long duration_in_msec, int uttid, string credential); int stop(in int uid); int pause(in int uid); int play_pcm(in int uid); -- 2.7.4