[ACR-1297] Add VCE APIs for supporting tts feedback 30/188030/10 accepted/tizen/unified/20180918.062907 submit/tizen/20180917.073702
authorsooyeon.kim <sooyeon.kim@samsung.com>
Thu, 30 Aug 2018 12:27:52 +0000 (21:27 +0900)
committersooyeon.kim <sooyeon.kim@samsung.com>
Fri, 14 Sep 2018 03:16:06 +0000 (12:16 +0900)
- add tts feedback api for vc client

Change-Id: I120eb805bafa7b9d0a44014e7c16e979bb9d5633
Signed-off-by: sooyeon.kim <sooyeon.kim@samsung.com>
35 files changed:
client/CMakeLists.txt
client/vc.c
client/vc_client.c
client/vc_client.h
client/vc_data.cpp [new file with mode: 0644]
client/vc_data.h [new file with mode: 0644]
client/vc_dbus.c
client/vc_dbus.h
client/vc_mgr.c
client/vc_mgr_client.c
client/vc_mgr_client.h
client/vc_mgr_data.cpp
client/vc_mgr_data.h
client/vc_mgr_dbus.c
client/vc_mgr_dbus.h
common/vc_defs.h
include/CMakeLists.txt
include/vce.h
include/vce_internal.h [new file with mode: 0644]
include/voice_control_internal.h
include/voice_control_manager.h
packaging/voice-control.spec
server/CMakeLists.txt
server/vcd_dbus.c
server/vcd_dbus.h
server/vcd_dbus_server.c
server/vcd_dbus_server.h
server/vcd_engine_agent.c
server/vcd_engine_agent.h
server/vcd_main.h
server/vcd_server.c
server/vcd_server.h
server/vcd_server_data.cpp [new file with mode: 0644]
server/vcd_server_data.h [new file with mode: 0644]
server/vce.c

index 0380cc0834b38a3a13741825f9922deb46db3c1b..10ce754b3810c0782233d8746d34e80440825533 100644 (file)
@@ -1,5 +1,6 @@
 SET(SRCS 
        vc.c
+       vc_data.cpp
        vc_client.c
        vc_dbus.c
        ../common/vc_cmd_db.c
index df42efe41188d682ec34062fda22c3fe9c37fb32..cc75683d40985dfea4f96044042b0928d51d31c8 100644 (file)
@@ -29,6 +29,7 @@
 #include "vc_cmd_db.h"
 #include "vc_command.h"
 #include "vc_config_mgr.h"
+#include "vc_data.h"
 #include "vc_dbus.h"
 #include "vc_info_parser.h"
 #include "vc_json_parser.h"
@@ -46,6 +47,8 @@ static Ecore_Timer* g_connect_timer = NULL;
 static Ecore_Event_Handler* g_focus_in_handler = NULL;
 static Ecore_Event_Handler* g_focus_out_handler = NULL;
 
+static Ecore_Thread* g_tts_thread = NULL;
+
 static vc_h g_vc = NULL;
 
 static int g_daemon_pid = 0;
@@ -2868,3 +2871,461 @@ int vc_auth_cancel(void)
        return ret;
 }
 //LCOV_EXCL_STOP
+
+static void __start_tts_streaming_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Start tts streaming thread");
+
+       vc_tts_data_s* tts_data = NULL;
+       vc_tts_streaming_cb callback = NULL;
+       void* user_data = NULL;
+
+       vc_client_get_tts_streaming_cb(g_vc, &callback, &user_data);
+       if (NULL == callback) {
+               SLOG(LOG_WARN, TAG_VCC, "[WARNING] tts streaming callback is null");
+               return;
+       }
+
+       while (1) {
+               int ret = -1;
+               int cnt = 0;
+
+               /* get tts data */
+               ret = vc_data_get_tts_data(&tts_data);
+               if (0 != ret || NULL == tts_data) {
+                       /* empty queue */
+                       SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] No tts data. Waiting mode");
+
+                       /* waiting */
+                       while (1) {
+                               usleep(10000);
+                               if (0 < vc_data_get_tts_data_size()) {
+                                       SLOG(LOG_INFO, TAG_VCC, "[INFO] Resume thread");
+                                       break;
+                               }
+                               if (200 < cnt) {
+                                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Wrong request, there's no pcm data");
+                                       return;
+                               }
+                               cnt++;
+                       }
+                       SLOG(LOG_INFO, TAG_VCC, "[INFO] Finish to wait for new tts data come");
+
+                       /* resume tts thread */
+                       continue;
+               }
+
+               SLOG(LOG_DEBUG, TAG_VCC, "tts streaming callback is called");
+               vc_client_use_callback(g_vc);
+               callback(tts_data->event, tts_data->data, tts_data->data_size, tts_data->utt_id, user_data);
+               vc_client_not_use_callback(g_vc);
+
+               /* If no tts data and EVENT_FINISH */
+               if (0 >= vc_data_get_tts_data_size() && VC_TTS_EVENT_FINISH == tts_data->event) {
+                       SLOG(LOG_INFO, TAG_VCC, "[INFO] Finish tts");
+                       break;
+               }
+       }
+}
+
+static void __end_tts_streaming_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] End tts streaming thread");
+       g_tts_thread = NULL;
+}
+
+int __vc_cb_tts_streaming(int utt_id, vc_tts_event_e event, char* buffer, int len)
+{
+       /* add tts data */
+       vc_tts_data_s* temp_tts_data = NULL;
+       temp_tts_data = (vc_tts_data_s*)calloc(1, sizeof(vc_tts_data_s));
+       if (NULL == temp_tts_data) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Out of memory");
+               return VC_ERROR_OUT_OF_MEMORY;
+       }
+
+       temp_tts_data->data = NULL;
+       temp_tts_data->data_size = 0;
+
+       if (0 < len) {
+               temp_tts_data->data = (char*)calloc(len + 5, sizeof(char));
+               if (NULL != temp_tts_data->data) {
+                       memcpy(temp_tts_data->data, buffer, len);
+                       temp_tts_data->data_size = len;
+                       SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG][memcpy] data(%p) size(%d)",
+                                       temp_tts_data->data, temp_tts_data->data_size);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] fail to allocate memory");
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] tts data is NULL");
+       }
+
+       temp_tts_data->utt_id = utt_id;
+       temp_tts_data->event = event;
+
+       int ret = vc_data_add_tts_data(temp_tts_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to add tts data");
+               if (NULL != temp_tts_data->data) {
+                       free(temp_tts_data->data);
+                       temp_tts_data->data = NULL;
+               }
+               if (NULL != temp_tts_data) {
+                       free(temp_tts_data);
+                       temp_tts_data = NULL;
+               }
+       }
+
+       bool is_canceled = ecore_thread_check(g_tts_thread);
+       if (NULL == g_tts_thread || TRUE == is_canceled) {
+               SLOG(LOG_INFO, TAG_VCC, "ecore thread run : __start_tts_streaming_thread ");
+               g_tts_thread = ecore_thread_run(__start_tts_streaming_thread, __end_tts_streaming_thread, NULL, NULL);
+       }
+
+       return ret;
+}
+
+int vc_tts_request(const char* text, const char* language, bool to_vcm, int* utt_id)
+{
+       vc_state_e state;
+       int ret = -1;
+       int pid = getpid();
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@ Request tts");
+
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid");
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state);
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* Check service state */
+       vc_service_state_e service_state = -1;
+       vc_client_get_service_state(g_vc, &service_state);
+       if (service_state != VC_SERVICE_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state);
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@ tts request, pid(%d), text(%s), language(%s), to_vcm(%d)", pid, text, language, to_vcm);
+
+       int count = 0;
+       bool is_prepared = false;
+       do {
+               ret = vc_dbus_request_tts(pid, text, language, to_vcm, utt_id);
+               if (0 != ret) {
+                       if (VC_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
+                               vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED);
+                               if (0 == vc_prepare_sync()) {
+                                       is_prepared = true;
+                                       SLOG(LOG_INFO, TAG_VCC, "[INFO] Success vc_prepare_sync");
+                               }
+                       } else if (VC_ERROR_TIMED_OUT != ret) {
+                               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request tts to vc service : %s", __vc_get_error_code(ret));
+                               break;
+                       } else {
+                               SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request tts : %s", __vc_get_error_code(ret));
+                               usleep(10000);
+                               count++;
+                               if (VC_RETRY_COUNT == count) {
+                                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request");
+                                       break;
+                               }
+                       }
+               }
+       } while (0 != ret);
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+
+       return ret;
+}
+
+int vc_tts_cancel(int utt_id)
+{
+       vc_state_e state;
+       int ret = -1;
+       int pid = getpid();
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@ Cancel tts");
+
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid");
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state);
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* Check service state */
+       vc_service_state_e service_state = -1;
+       vc_client_get_service_state(g_vc, &service_state);
+       if (service_state != VC_SERVICE_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state);
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@ tts cancel, pid(%d), utt_id(%d)", pid, utt_id);
+
+       ret = vc_data_clear_tts_data_by_uttid(utt_id);
+       if (0 != ret) {
+               SLOG(LOG_INFO, TAG_VCC, "[INFO] There's no data in client pcm queue");
+       }
+
+       int count = 0;
+       bool is_prepared = false;
+       do {
+               ret = vc_dbus_cancel_tts(pid, utt_id);
+               if (0 != ret) {
+                       if (VC_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
+                               vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED);
+                               if (0 == vc_prepare_sync()) {
+                                       is_prepared = true;
+                                       SLOG(LOG_INFO, TAG_VCC, "[INFO] Success vc_prepare_sync");
+                               }
+                       } else if (VC_ERROR_TIMED_OUT != ret) {
+                               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to cancel tts to vc service : %s", __vc_get_error_code(ret));
+                               break;
+                       } else {
+                               SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry cancel tts : %s", __vc_get_error_code(ret));
+                               usleep(10000);
+                               count++;
+                               if (VC_RETRY_COUNT == count) {
+                                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to cancel");
+                                       break;
+                               }
+                       }
+               }
+       } while (0 != ret);
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+
+       return ret;
+}
+
+int vc_tts_get_audio_format(int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type)
+{
+       vc_state_e state;
+       int ret = -1;
+       int pid = getpid();
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@ Get tts audio format");
+
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid");
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state);
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* Check service state */
+       vc_service_state_e service_state = -1;
+       vc_client_get_service_state(g_vc, &service_state);
+       if (service_state != VC_SERVICE_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state);
+               SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@ get tts audio format, pid(%d)", pid);
+
+       int count = 0;
+       bool is_prepared = false;
+       do {
+               ret = vc_dbus_get_tts_audio_format(pid, rate, channel, audio_type);
+               if (0 != ret) {
+                       if (VC_ERROR_INVALID_PARAMETER == ret && false == is_prepared) {
+                               vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED);
+                               if (0 == vc_prepare_sync()) {
+                                       is_prepared = true;
+                                       SLOG(LOG_INFO, TAG_VCC, "[INFO] Success vc_prepare_sync");
+                               }
+                       } else if (VC_ERROR_TIMED_OUT != ret) {
+                               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get tts audio format : %s", __vc_get_error_code(ret));
+                               break;
+                       } else {
+                               SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry to get tts audio format : %s", __vc_get_error_code(ret));
+                               usleep(10000);
+                               count++;
+                               if (VC_RETRY_COUNT == count) {
+                                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get tts audio format");
+                                       break;
+                               }
+                       }
+               }
+       } while (0 != ret);
+
+       SLOG(LOG_DEBUG, TAG_VCC, "@@@");
+
+       return ret;
+}
+
+int vc_tts_set_streaming_cb(vc_tts_streaming_cb callback, void* user_data)
+{
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       if (NULL == callback)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       vc_state_e state;
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts streaming callback : A handle is not available");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_INITIALIZED) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts streaming callback : Current state(%d) is not 'Initialized'", state);
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       vc_client_set_tts_streaming_cb(g_vc, callback,  user_data);
+
+       return 0;
+}
+
+int vc_tts_unset_streaming_cb(void)
+{
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       vc_state_e state;
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts streaming callback : A handle is not available");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_INITIALIZED) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts streaming callback : Current state(%d) is not 'Initialized'", state);
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       vc_client_set_tts_streaming_cb(g_vc, NULL, NULL);
+
+       return 0;
+}
+
+int __vc_cb_utterance_status(int utt_id, int utt_status)
+{
+       vc_tts_utterance_status_cb callback = NULL;
+       void* user_data = NULL;
+
+       vc_client_get_tts_utterance_status_cb(g_vc, &callback, &user_data);
+       if (NULL == callback) {
+               SLOG(LOG_WARN, TAG_VCC, "[WARNING] Utterance status callback is null");
+               return -1;
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCC, "Utterance status callback is called");
+       vc_client_use_callback(g_vc);
+       callback(utt_id, (vc_tts_utterance_status_e)utt_status);
+       vc_client_not_use_callback(g_vc);
+
+       return 0;
+}
+
+int vc_tts_set_utterance_status_cb(vc_tts_utterance_status_cb callback, void* user_data)
+{
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       if (NULL == callback)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       vc_state_e state;
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts utterance status callback : A handle is not available");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_INITIALIZED) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set tts utterance status callback : Current state(%d) is not 'Initialized'", state);
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       vc_client_set_tts_utterance_status_cb(g_vc, callback,  user_data);
+
+       return 0;
+}
+
+int vc_tts_unset_utterance_status_cb(void)
+{
+       if (0 != __vc_get_feature_enabled()) {
+               return VC_ERROR_NOT_SUPPORTED;
+       }
+       if (0 != __vc_check_privilege()) {
+               return VC_ERROR_PERMISSION_DENIED;
+       }
+
+       vc_state_e state;
+       if (0 != vc_client_get_client_state(g_vc, &state)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts utterance status callback : A handle is not available");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_INITIALIZED) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset tts utterance status callback : Current state(%d) is not 'Initialized'", state);
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       vc_client_set_tts_utterance_status_cb(g_vc, NULL, NULL);
+
+       return 0;
+}
index 70c4b4bebe2c9d33713e7bf9c24acf749cec4d59..c7db4cc014be2051d6377edd4e078aa2d7278ade 100644 (file)
@@ -35,6 +35,12 @@ typedef struct {
        vc_current_language_changed_cb  current_lang_changed_cb;
        void*                           current_lang_changed_user_data;
 
+       /* tts feedback */
+       vc_tts_streaming_cb tts_streaming_cb;
+       void*                           tts_streaming_user_data;
+       vc_tts_utterance_status_cb      tts_utterance_status_cb;
+       void*                                           tts_utterance_status_user_data;
+
 #if 0
        /* exclusive option */
        bool                    exclusive_cmd;
@@ -133,6 +139,10 @@ int vc_client_create(vc_h* vc)
        client->current_lang_changed_user_data = NULL;
        client->error_cb = NULL;
        client->error_user_data = NULL;
+       client->tts_streaming_cb = NULL;
+       client->tts_streaming_user_data = NULL;
+       client->tts_utterance_status_cb = NULL;
+       client->tts_utterance_status_user_data = NULL;
 
 #if 0
        client->exclusive_cmd = false;
@@ -781,3 +791,59 @@ int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid)
 
        return 0;
 }
+
+int vc_client_set_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb callback, void* user_data)
+{
+       vc_client_s* client = __client_get(vc);
+
+       /* check handle */
+       if (NULL == client)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       client->tts_streaming_cb = callback;
+       client->tts_streaming_user_data = user_data;
+
+       return 0;
+}
+
+int vc_client_get_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb* callback, void** user_data)
+{
+       vc_client_s* client = __client_get(vc);
+
+       /* check handle */
+       if (NULL == client)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       *callback = client->tts_streaming_cb;
+       *user_data = client->tts_streaming_user_data;
+
+       return 0;
+}
+
+int vc_client_set_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb callback, void* user_data)
+{
+       vc_client_s* client = __client_get(vc);
+
+       /* check handle */
+       if (NULL == client)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       client->tts_utterance_status_cb = callback;
+       client->tts_utterance_status_user_data = user_data;
+
+       return 0;
+}
+
+int vc_client_get_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb* callback, void** user_data)
+{
+       vc_client_s* client = __client_get(vc);
+
+       /* check handle */
+       if (NULL == client)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       *callback = client->tts_utterance_status_cb;
+       *user_data = client->tts_utterance_status_user_data;
+
+       return 0;
+}
index 0d03bda63415f6cb84dee7a97b3257d030d302e7..e084fe73837be9c4d4f58a7538f95fb01227f2d3 100644 (file)
@@ -22,6 +22,7 @@
 #include "vc_main.h"
 #include "voice_control.h"
 #include "voice_control_authority.h"
+#include "voice_control_internal.h"
 
 
 #ifdef __cplusplus
@@ -128,6 +129,16 @@ int vc_client_set_mgr_pid(vc_h vc, int mgr_pid);
 int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid);
 
 
+/* TTS feedback */
+int vc_client_set_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb callback, void* user_data);
+
+int vc_client_get_tts_streaming_cb(vc_h vc, vc_tts_streaming_cb* callback, void** user_data);
+
+int vc_client_set_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb callback, void* user_data);
+
+int vc_client_get_tts_utterance_status_cb(vc_h vc, vc_tts_utterance_status_cb* callback, void** user_data);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/client/vc_data.cpp b/client/vc_data.cpp
new file mode 100644 (file)
index 0000000..2358f6f
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <list>
+#include <vector>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#include "vc_data.h"
+
+using namespace std;
+
+std::list<vc_tts_data_s*> g_tts_data;
+
+static pthread_mutex_t g_tts_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int vc_data_add_tts_data(vc_tts_data_s* data)
+{
+       if (NULL == data) {
+               SLOG(LOG_ERROR, TAG_VCC, "[DATA ERROR] tts data is NULL");
+               return VC_ERROR_INVALID_PARAMETER;
+       }
+
+       pthread_mutex_lock(&g_tts_data_mutex);
+
+       std::list<vc_tts_data_s*>::iterator iter;
+
+       try {
+               iter = g_tts_data.insert(g_tts_data.end(), data);
+       } catch (const std::bad_alloc&) {
+               SLOG(LOG_ERROR, TAG_VCC, "[DATA ERROR] Fail to insert tts data (bad alloc)");
+               pthread_mutex_unlock(&g_tts_data_mutex);
+
+               return VC_ERROR_OUT_OF_MEMORY;
+       }
+
+       pthread_mutex_unlock(&g_tts_data_mutex);
+
+       return VC_ERROR_NONE;
+}
+
+int vc_data_get_tts_data(vc_tts_data_s** data)
+{
+       SLOG(LOG_DEBUG, TAG_VCC, "[DATA] tts_data : %p", *data);
+
+       pthread_mutex_lock(&g_tts_data_mutex);
+
+       if (0 == g_tts_data.size()) {
+               SLOG(LOG_DEBUG, TAG_VCC, "[DATA] There is no tts data");
+               *data = NULL;
+               pthread_mutex_unlock(&g_tts_data_mutex);
+
+               return -1;
+       }
+
+       std::list<vc_tts_data_s*>::iterator iter;
+
+       if (!g_tts_data.empty()) {
+               iter = g_tts_data.begin();
+               *data = *iter;
+               g_tts_data.pop_front();
+       }
+
+       pthread_mutex_unlock(&g_tts_data_mutex);
+
+       return VC_ERROR_NONE;
+}
+
+int vc_data_get_tts_data_size()
+{
+       int data_size = 0;
+
+       pthread_mutex_lock(&g_tts_data_mutex);
+       data_size = g_tts_data.size();
+
+       pthread_mutex_unlock(&g_tts_data_mutex);
+
+       return data_size;
+}
+
+int vc_data_clear_tts_data(vc_tts_data_s** data)
+{
+       SLOG(LOG_DEBUG, TAG_VCC, "[DATA] clear tts data");
+
+       pthread_mutex_lock(&g_tts_data_mutex);
+
+       if (!g_tts_data.empty()) {
+               SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] event(%d) data(%p) size(%d)", (*data)->event, (*data)->data, (*data)->data_size);
+
+               if (NULL != (*data)->data) {
+                       free((*data)->data);
+                       (*data)->data = NULL;
+               }
+
+               free(*data);
+               *data = NULL;
+       }
+
+       pthread_mutex_unlock(&g_tts_data_mutex);
+
+       return VC_ERROR_NONE;
+}
+
+int vc_data_clear_tts_data_by_uttid(int utt_id)
+{
+       SLOG(LOG_DEBUG, TAG_VCC, "[DATA] clear tts data by utt_id(%d)", utt_id);
+
+       pthread_mutex_lock(&g_tts_data_mutex);
+
+       if (g_tts_data.empty())  {
+               SLOG(LOG_ERROR, TAG_VCC, "[DATA ERROR] There is no tts data");
+               pthread_mutex_unlock(&g_tts_data_mutex);
+               return -1;
+       }
+
+       std::list<vc_tts_data_s*>::iterator iter;
+       for (iter = g_tts_data.begin(); (NULL != *iter && iter != g_tts_data.end()); ++iter) {
+               if (utt_id == (*iter)->utt_id) {
+                       if (NULL != (*iter)->data) {
+                               free((*iter)->data);
+                               (*iter)->data = NULL;
+                       }
+                       g_tts_data.erase(iter);
+                       free(*iter);
+               }
+       }
+
+       pthread_mutex_unlock(&g_tts_data_mutex);
+
+       return VC_ERROR_NONE;
+}
\ No newline at end of file
diff --git a/client/vc_data.h b/client/vc_data.h
new file mode 100644 (file)
index 0000000..9ca9668
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+#ifndef __VC_DATA_H__
+#define __VC_DATA_H__
+
+#include <tizen.h>
+#include <voice_control_common.h>
+#include <voice_control_internal.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TAG_VCC     "vcc"       /* vc client log tag */
+
+typedef struct {
+       int utt_id;
+       void* data;
+       unsigned int data_size;
+       vc_tts_event_e event;
+} vc_tts_data_s;
+
+
+int vc_data_add_tts_data(vc_tts_data_s* data);
+
+int vc_data_get_tts_data(vc_tts_data_s** data);
+
+int vc_data_get_tts_data_size();
+
+int vc_data_clear_tts_data(vc_tts_data_s** data);
+
+int vc_data_clear_tts_data_by_uttid(int utt_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VC_DATA_H__ */
index fb2af05269d71ea4862dc1ad139aa587993d140f..2da8f6bc1f33cdee0a38e1e9eb3c2a67312539fe 100644 (file)
@@ -34,6 +34,10 @@ extern int __vc_cb_service_state(int state);
 
 extern int __vc_cb_manager_pid(int manager_pid);
 
+extern int __vc_cb_tts_streaming(int utt_id, vc_feedback_event_e event, char* buffer, int len);
+
+extern int __vc_cb_utterance_status(int utt_id, int utt_status);
+
 //LCOV_EXCL_START
 static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
 {
@@ -156,6 +160,40 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle
                        SLOG(LOG_DEBUG, TAG_VCC, "@@@");
                } /* VCD_METHOD_ERROR */
 
+               else if (dbus_message_is_method_call(msg, if_name, VCD_METHOD_FEEDBACK_STREAMING)) {
+                       SLOG(LOG_INFO, TAG_VCC, "@@@ Get TTS feedback streaming");
+                       int utt_id;
+                       vc_feedback_event_e event;
+                       char* buffer = NULL;
+                       int len;
+
+                       dbus_message_get_args(msg, &err,
+                                       DBUS_TYPE_INT32, &utt_id,
+                                       DBUS_TYPE_INT32, &event,
+                                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+                                       &buffer, &len,
+                                       DBUS_TYPE_INVALID);
+
+                       __vc_cb_tts_streaming(utt_id, event, buffer, len);
+
+                       SLOG(LOG_INFO, TAG_VCC, "@@@");
+               } /* VCD_METHOD_FEEDBACK_STREAMING */
+
+               else if (dbus_message_is_method_call(msg, if_name, VC_MANAGER_METHOD_UTTERANCE_STATUS)) {
+                       SLOG(LOG_INFO, TAG_VCC, "@@@ Get TTS utterance status streaming");
+                       int utt_id;
+                       int utt_status;
+
+                       dbus_message_get_args(msg, &err,
+                                       DBUS_TYPE_INT32, &utt_id,
+                                       DBUS_TYPE_INT32, &utt_status,
+                                       DBUS_TYPE_INVALID);
+
+                       __vc_cb_utterance_status(utt_id, utt_status);
+
+                       SLOG(LOG_INFO, TAG_VCC, "@@@");
+               } /* VC_MANAGER_METHOD_UTTERANCE_STATUS */
+
                else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameOwnerChanged")) {
                        SLOG(LOG_DEBUG, TAG_VCC, "@@@ Owner Changed");
                        DBusError err;
@@ -1655,3 +1693,234 @@ int vc_dbus_request_auth_cancel(int pid, int mgr_pid)
        return result;
 }
 //LCOV_EXCL_STOP
+
+int vc_dbus_request_tts(int pid, const char* text, const char* language, bool to_vcm, int* utt_id)
+{
+       if (NULL == g_conn_sender) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection");
+               if (0 != vc_dbus_reconnect()) {
+                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect");
+               }
+       }
+
+       DBusMessage* msg;
+       int tmp_to_vcm = 0;
+
+       tmp_to_vcm = (int)to_vcm;
+
+       msg = dbus_message_new_method_call(
+               VC_SERVER_SERVICE_NAME,
+               VC_SERVER_SERVICE_OBJECT_PATH,
+               VC_SERVER_SERVICE_INTERFACE,
+               VC_METHOD_REQUEST_TTS);
+
+       if (NULL == msg) {
+               SLOG(LOG_ERROR, TAG_VCC, "@@ vc request tts to manager : Fail to make message");
+               return VC_ERROR_OPERATION_FAILED;
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCC, "@@ vc request tts to manager : client pid(%d), disp_text(%s), utt_text(%s), continuous(%d)", pid, text, language, to_vcm);
+       }
+
+       dbus_message_append_args(msg,
+                               DBUS_TYPE_INT32, &pid,
+                               DBUS_TYPE_STRING, &text,
+                               DBUS_TYPE_STRING, &language,
+                               DBUS_TYPE_INT32, &tmp_to_vcm,
+                               DBUS_TYPE_INVALID);
+
+       DBusError err;
+       dbus_error_init(&err);
+
+       DBusMessage* result_msg;
+       int result = VC_ERROR_OPERATION_FAILED;
+
+       result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err);
+       dbus_message_unref(msg);
+
+       if (dbus_error_is_set(&err)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message);
+               dbus_error_free(&err);
+       }
+
+       int tmp_utt_id = -1;
+       if (NULL != result_msg) {
+               dbus_message_get_args(result_msg, &err,
+                               DBUS_TYPE_INT32, &result,
+                               DBUS_TYPE_INT32, &tmp_utt_id,
+                               DBUS_TYPE_INVALID);
+
+               if (dbus_error_is_set(&err)) {
+                       SLOG(LOG_ERROR, TAG_VCC, "@@ Get arguments error (%s)", err.message);
+                       dbus_error_free(&err);
+                       result = VC_ERROR_OPERATION_FAILED;
+               }
+               dbus_message_unref(result_msg);
+
+               if (0 == result) {
+                       *utt_id = tmp_utt_id;
+                       SLOG(LOG_DEBUG, TAG_VCC, "@@ vc request tts : result = %d, utt_id = %d", result, *utt_id);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCC, "@@ vc request tts : result = %d", result);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCC, "@@ Result message is NULL");
+               vc_dbus_reconnect();
+               result = VC_ERROR_TIMED_OUT;
+       }
+
+       return result;
+
+       return 0;
+}
+
+int vc_dbus_cancel_tts(int pid, int utt_id)
+{
+       if (NULL == g_conn_sender) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection");
+               if (0 != vc_dbus_reconnect()) {
+                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect");
+               }
+       }
+
+       DBusMessage* msg;
+
+       msg = dbus_message_new_method_call(
+               VC_SERVER_SERVICE_NAME,
+               VC_SERVER_SERVICE_OBJECT_PATH,
+               VC_SERVER_SERVICE_INTERFACE,
+               VC_METHOD_CANCEL_TTS);
+
+       if (NULL == msg) {
+               SLOG(LOG_ERROR, TAG_VCC, "@@ vc cancel tts to manager : Fail to make message");
+               return VC_ERROR_OPERATION_FAILED;
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCC, "@@ vc cancel tts to manager : client pid(%d), utt_id(%d)", pid, utt_id);
+       }
+
+       dbus_message_append_args(msg,
+                               DBUS_TYPE_INT32, &pid,
+                               DBUS_TYPE_INT32, &utt_id,
+                               DBUS_TYPE_INVALID);
+
+       DBusError err;
+       dbus_error_init(&err);
+
+       DBusMessage* result_msg;
+       int result = VC_ERROR_OPERATION_FAILED;
+
+       result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err);
+       dbus_message_unref(msg);
+
+       if (dbus_error_is_set(&err)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message);
+               dbus_error_free(&err);
+       }
+
+       if (NULL != result_msg) {
+               dbus_message_get_args(result_msg, &err,
+                               DBUS_TYPE_INT32, &result,
+                               DBUS_TYPE_INVALID);
+
+               if (dbus_error_is_set(&err)) {
+                       SLOG(LOG_ERROR, TAG_VCC, "@@ Get arguments error (%s)", err.message);
+                       dbus_error_free(&err);
+                       result = VC_ERROR_OPERATION_FAILED;
+               }
+               dbus_message_unref(result_msg);
+
+               if (0 == result) {
+                       SLOG(LOG_DEBUG, TAG_VCC, "@@ vc cancel tts : result = %d", result);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCC, "@@ vc cancel tts : result = %d", result);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCC, "@@ Result message is NULL");
+               vc_dbus_reconnect();
+               result = VC_ERROR_TIMED_OUT;
+       }
+
+       return result;
+
+       return 0;
+}
+
+int vc_dbus_get_tts_audio_format(int pid, int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type)
+{
+       if (NULL == g_conn_sender) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL connection");
+               if (0 != vc_dbus_reconnect()) {
+                       SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect");
+               }
+       }
+
+       DBusMessage* msg;
+
+       msg = dbus_message_new_method_call(
+               VC_SERVER_SERVICE_NAME,
+               VC_SERVER_SERVICE_OBJECT_PATH,
+               VC_SERVER_SERVICE_INTERFACE,
+               VC_METHOD_GET_TTS_AUDIO_FORMAT);
+
+       if (NULL == msg) {
+               SLOG(LOG_ERROR, TAG_VCC, "@@ vc get tts audio format : Fail to make message");
+               return VC_ERROR_OPERATION_FAILED;
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCC, "@@ vc get tts audio format : client pid(%d)", pid);
+       }
+
+       dbus_message_append_args(msg,
+                               DBUS_TYPE_INT32, &pid,
+                               DBUS_TYPE_INVALID);
+
+       DBusError err;
+       dbus_error_init(&err);
+
+       DBusMessage* result_msg;
+       int result = VC_ERROR_OPERATION_FAILED;
+
+       result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, g_waiting_time, &err);
+       dbus_message_unref(msg);
+
+       if (dbus_error_is_set(&err)) {
+               SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message);
+               dbus_error_free(&err);
+       }
+
+       int tmp_rate;
+       int tmp_channel;
+       int tmp_audio_type;
+
+       if (NULL != result_msg) {
+               dbus_message_get_args(result_msg, &err,
+                               DBUS_TYPE_INT32, &result,
+                               DBUS_TYPE_INT32, &tmp_rate,
+                               DBUS_TYPE_INT32, &tmp_channel,
+                               DBUS_TYPE_INT32, &tmp_audio_type,
+                               DBUS_TYPE_INVALID);
+
+               if (dbus_error_is_set(&err)) {
+                       SLOG(LOG_ERROR, TAG_VCC, "@@ Get arguments error (%s)", err.message);
+                       dbus_error_free(&err);
+                       result = VC_ERROR_OPERATION_FAILED;
+               }
+               dbus_message_unref(result_msg);
+
+               if (0 == result) {
+                       *rate = tmp_rate;
+                       *channel = tmp_channel;
+                       *audio_type = tmp_audio_type;
+                       SLOG(LOG_DEBUG, TAG_VCC, "@@ vc get tts audio format : result = %d, rate = %d, channel = %d, audio_type = %d", result, *rate, *channel, *audio_type);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCC, "@@ vc get tts audio format : result = %d", result);
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCC, "@@ Result message is NULL");
+               vc_dbus_reconnect();
+               result = VC_ERROR_TIMED_OUT;
+       }
+
+       return result;
+
+       return 0;
+}
+
index e7f751253bfa147dc0b8b8eefa3d4b66db43507f..5d13712644c945d021d7f796b7ba486b0c87114a 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef __VC_DBUS_H_
 #define __VC_DBUS_H_
 
+#include "voice_control_common.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -67,6 +68,14 @@ int vc_dbus_request_auth_stop(int pid, int mgr_pid);
 
 int vc_dbus_request_auth_cancel(int pid, int mgr_pid);
 
+/* tts feedback */
+
+int vc_dbus_request_tts(int pid, const char* text, const char* language, bool to_vcm, int* utt_id);
+
+int vc_dbus_cancel_tts(int pid, int utt_id);
+
+int vc_dbus_get_tts_audio_format(int pid, int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type);
+
 #ifdef __cplusplus
 }
 #endif
index a4b01c0613cc771dc481044cfbbf7c623bab7b72..17bbbb8cb9c782fb6243845fc839abe8c1bcc337 100644 (file)
@@ -3372,7 +3372,7 @@ int __vc_mgr_cb_feedback_audio_format(int rate, vc_audio_channel_e channel, vc_a
        return VC_ERROR_NONE;
 }
 
-int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int len)
+int __vc_mgr_cb_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len)
 {
        /* add feedback data */
        vc_feedback_data_s* temp_feedback_data = NULL;
@@ -3381,6 +3381,7 @@ int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Out of memory");
                return VC_ERROR_OUT_OF_MEMORY;
        }
+       SLOG(LOG_INFO, TAG_VCM, "[INFO] feedback streaming before queing");
 
        temp_feedback_data->data = NULL;
        temp_feedback_data->rate = g_feedback_rate;
@@ -3400,10 +3401,14 @@ int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] feedback data is NULL");
        }
 
+       temp_feedback_data->pid = pid;
+       temp_feedback_data->utt_id = utt_id;
        temp_feedback_data->event = event;
        temp_feedback_data->audio_type = g_feedback_audio_type;
        temp_feedback_data->channel = g_feedback_audio_channel;
 
+       SLOG(LOG_INFO, TAG_VCM, "[INFO] add feedback data, pid(%d), utt_id(%d), event(%d), audio_type(%d), channel(%d)", pid, utt_id, event, g_feedback_audio_type, g_feedback_audio_channel);
+
        int ret = vc_mgr_data_add_feedback_data(temp_feedback_data);
        if (0 != ret) {
                SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to add feedback data");
@@ -3415,13 +3420,12 @@ int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int
                        free(temp_feedback_data);
                        temp_feedback_data = NULL;
                }
-
-               return ret;
        }
 
-       return VC_ERROR_NONE;
+               return ret;
 }
 
+
 int vc_mgr_set_dialog_request_cb(vc_mgr_dialog_request_cb callback, void* user_data)
 {
        if (0 != __vc_mgr_get_feature_enabled()) {
@@ -3984,19 +3988,56 @@ int vc_mgr_unset_feedback_streaming_cb()
        return 0;
 }
 
+int vc_mgr_set_vc_tts_streaming_cb(vc_mgr_vc_tts_streaming_cb callback, void* user_data)
+{
+       if (NULL == callback)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       vc_state_e state;
+       if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set feedback streaming callback : A handle is not available");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (VC_STATE_INITIALIZED != state) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set feedback streaming callback : Current state is not 'Initialized' (%d)", state);
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       vc_mgr_client_set_vc_tts_streaming_cb(g_vc_m, callback, user_data);
+
+       SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Set feedback streaming callback");
+
+       return 0;
+}
+
+int vc_mgr_unset_vc_tts_streaming_cb()
+{
+       vc_state_e state;
+       if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset feedback streaming callback : A handle is not available");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (VC_STATE_INITIALIZED != state) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset feedback streaming callback : Current state is not 'Initialized' (%d)", state);
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       vc_mgr_client_set_vc_tts_streaming_cb(g_vc_m, NULL, NULL);
+
+       SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Unset feedback streaming callback");
+
+       return 0;
+}
+
 static void __tts_feedback_thread(void* data, Ecore_Thread* thread)
 {
        SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Start thread");
 
        vc_feedback_data_s* feedback_data = NULL;
-       vc_mgr_feedback_streaming_cb callback = NULL;
-       void* user_data = NULL;
-
-       vc_mgr_client_get_feedback_streaming_cb(g_vc_m, &callback, &user_data);
-       if (NULL == callback) {
-               SLOG(LOG_WARN, TAG_VCM, "[WARNING] TTS feedback streaming callback is null");
-               return;
-       }
 
        while (1) {
                int ret = -1;
@@ -4027,6 +4068,16 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread)
                        continue;
                }
 
+               if (getpid() == feedback_data->pid) {
+                       vc_mgr_feedback_streaming_cb callback = NULL;
+                       void* user_data = NULL;
+
+                       vc_mgr_client_get_feedback_streaming_cb(g_vc_m, &callback, &user_data);
+                       if (NULL == callback) {
+                               SLOG(LOG_WARN, TAG_VCM, "[WARNING] TTS feedback streaming callback is null");
+                               return;
+                       }
+
                SLOG(LOG_DEBUG, TAG_VCM, "TTS feedback streaming callback is called");
                vc_mgr_client_use_callback(g_vc_m);
                callback(feedback_data->event, feedback_data->data, feedback_data->data_size, user_data);
@@ -4037,6 +4088,30 @@ static void __tts_feedback_thread(void* data, Ecore_Thread* thread)
                        SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish feedback");
                        break;
                }
+               } else {
+                       vc_mgr_vc_tts_streaming_cb callback = NULL;
+                       void* user_data = NULL;
+
+                       vc_mgr_client_get_vc_tts_streaming_cb(g_vc_m, &callback, &user_data);
+                       if (NULL == callback) {
+                               SLOG(LOG_WARN, TAG_VCM, "[WARNING] vc tts streaming callback is null");
+                               vc_mgr_data_clear_feedback_data(&feedback_data);
+                               return;
+                       }
+
+                       SLOG(LOG_DEBUG, TAG_VCM, "vc tts feedback streaming callback is called");
+                       vc_mgr_client_use_callback(g_vc_m);
+                       callback(feedback_data->pid, feedback_data->utt_id, feedback_data->event, feedback_data->data, feedback_data->data_size, user_data);
+                       vc_mgr_client_not_use_callback(g_vc_m);
+
+                       /* If no feedback data and EVENT_FINISH */
+                       if (0 >= vc_mgr_data_get_feedback_data_size() && VC_FEEDBACK_EVENT_FINISH == feedback_data->event) {
+                               SLOG(LOG_INFO, TAG_VCM, "[INFO] Finish vc tts feedback");
+                               break;
+                       }
+               }
+               if (feedback_data)
+                       free(feedback_data);
        }
 }
 
@@ -4139,3 +4214,44 @@ int vc_mgr_stop_feedback(void)
 #endif
        return ret;
 }
+
+int vc_mgr_send_utterance_status(int pid, int utt_id, int utt_status)
+{
+       SLOG(LOG_DEBUG, TAG_VCM, "@@@ [Manager] send utterance status, pid(%d), utt_id(%d), utt_status(%d)", pid, utt_id, utt_status);
+
+       vc_state_e state;
+       if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available");
+               SLOG(LOG_DEBUG, TAG_VCM, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* check state */
+       if (state != VC_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state(%d) is not 'READY'", state);
+               SLOG(LOG_DEBUG, TAG_VCM, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       /* Check service state */
+       vc_service_state_e service_state = -1;
+       vc_mgr_client_get_service_state(g_vc_m, &service_state);
+       if (service_state != VC_SERVICE_STATE_READY) {
+               SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state(%d) is not 'READY'", service_state);
+               SLOG(LOG_DEBUG, TAG_VCM, "@@@");
+               return VC_ERROR_INVALID_STATE;
+       }
+
+       int ret = -1;
+               ret = vc_mgr_dbus_send_utterance_status(pid, utt_id, utt_status);
+               if (0 != ret) {
+                               SLOG(LOG_DEBUG, TAG_VCM, "[ERROR] Fail to send utterance status : %s", __vc_mgr_get_error_code(ret));
+               return ret;
+               } else {
+                       SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Send utterance status");
+               }
+       SLOG(LOG_DEBUG, TAG_VCM, "@@@");
+
+       return 0;
+}
+
index 861c64d6c9d1adbfd471361d532a608210f93459..9f5124db4d9f17fb09d81a5b76ef849902fea5d1 100644 (file)
@@ -55,6 +55,8 @@ typedef struct {
        void*                           feedback_audio_format_user_data;
        vc_mgr_feedback_streaming_cb    feedback_streaming_cb;
        void*                           feedback_streaming_user_data;
+       vc_mgr_vc_tts_streaming_cb              vc_tts_streaming_cb;
+       void*                                                   vc_tts_streaming_user_data;
 
        /* All result */
        vc_result_event_e       all_result_event;
@@ -189,6 +191,8 @@ int vc_mgr_client_create(vc_h* vc)
        client->feedback_audio_format_user_data = NULL;
        client->feedback_streaming_cb = NULL;
        client->feedback_streaming_user_data = NULL;
+       client->vc_tts_streaming_cb = NULL;
+       client->vc_tts_streaming_user_data = NULL;
 
        client->exclusive_cmd_option = false;
 
@@ -716,6 +720,34 @@ int vc_mgr_client_get_feedback_streaming_cb(vc_h vc, vc_mgr_feedback_streaming_c
        return 0;
 }
 
+int vc_mgr_client_set_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb callback, void* user_data)
+{
+       vc_mgr_client_s* client = __mgr_client_get(vc);
+
+       /* check handle */
+       if (NULL == client)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       client->vc_tts_streaming_cb = callback;
+       client->vc_tts_streaming_user_data = user_data;
+
+       return 0;
+}
+
+int vc_mgr_client_get_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb* callback, void** user_data)
+{
+       vc_mgr_client_s* client = __mgr_client_get(vc);
+
+       /* check handle */
+       if (NULL == client)
+               return VC_ERROR_INVALID_PARAMETER;
+
+       *callback = client->vc_tts_streaming_cb;
+       *user_data = client->vc_tts_streaming_user_data;
+
+       return 0;
+}
+
 /* set/get option */
 int vc_mgr_client_set_service_state(vc_h vc, vc_service_state_e state)
 {
index e8104c0e4b30e90d2d9e9a929f66ca648c40582b..9128f95cf9d48087e62fbf7255aeaee3bae95901 100644 (file)
@@ -107,6 +107,10 @@ int vc_mgr_client_set_feedback_streaming_cb(vc_h vc, vc_mgr_feedback_streaming_c
 
 int vc_mgr_client_get_feedback_streaming_cb(vc_h vc, vc_mgr_feedback_streaming_cb* callback, void** user_data);
 
+int vc_mgr_client_set_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb callback, void* user_data);
+
+int vc_mgr_client_get_vc_tts_streaming_cb(vc_h vc, vc_mgr_vc_tts_streaming_cb* callback, void** user_data);
+
 
 /*
 * set/get option
index fa455cdc7b0b06a3eb7c2190215b65f50ff8244c..7053c46ca8e0e9b2fb278ebe46d9a127c4db01b4 100644 (file)
@@ -35,6 +35,7 @@ int vc_mgr_data_add_feedback_data(vc_feedback_data_s* data)
                SLOG(LOG_ERROR, TAG_VCM, "[DATA ERROR] feedback data is NULL");
                return VC_ERROR_INVALID_PARAMETER;
        }
+       SLOG(LOG_DEBUG, TAG_VCM, "[DATA] feedback_data : %p", *data);
 
        pthread_mutex_lock(&g_feedback_data_mutex);
 
@@ -83,8 +84,6 @@ int vc_mgr_data_get_feedback_data(vc_feedback_data_s** data)
 
 int vc_mgr_data_get_feedback_data_size()
 {
-       SLOG(LOG_DEBUG, TAG_VCM, "[DATA] get feedback data size");
-
        int data_size = 0;
 
        pthread_mutex_lock(&g_feedback_data_mutex);
@@ -102,7 +101,7 @@ int vc_mgr_data_clear_feedback_data(vc_feedback_data_s** data)
        pthread_mutex_lock(&g_feedback_data_mutex);
 
        if (!g_feedback_data.empty()) {
-               SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] data(%p) size(%d) rate(%d)", (*data)->data, (*data)->data_size, (*data)->rate);
+               SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] pid(%d), utt_id(%d), data(%p) size(%d) rate(%d)", (*data)->pid, (*data)->utt_id, (*data)->data, (*data)->data_size, (*data)->rate);
 
                if (NULL != (*data)->data) {
                        free((*data)->data);
index 3e2960fe08ea97935b209273eb55405cd29bffc6..dcd6b63f11340d59de006479e706086a4e809f83 100644 (file)
@@ -35,6 +35,7 @@ typedef enum {
 } vc_feedback_state_e;
 
 typedef struct {
+       int pid;
        int utt_id;
        void* data;
        unsigned int data_size;
index 246c59e06f72ed14c8f9efb95b86e371a23b26c0..8f8adf6d9fa7bd243fbbd8a9a82aa1228693ca15 100644 (file)
@@ -54,7 +54,7 @@ extern int __vc_mgr_cb_private_data_requested(const char* key, char** data);
 /* for TTS feedback */
 extern int __vc_mgr_cb_feedback_audio_format(int rate, vc_audio_channel_e channel, vc_audio_type_e audio_type);
 
-extern int __vc_mgr_cb_feedback_streaming(vc_feedback_event_e event, char* buffer, int len);
+extern int __vc_mgr_cb_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len);
 
 /* Authority */
 extern int __vc_mgr_request_auth_enable(int pid);
@@ -411,17 +411,21 @@ static Eina_Bool vc_mgr_listener_event_callback(void* data, Ecore_Fd_Handler *fd
 
                else if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_FEEDBACK_STREAMING)) {
                        SLOG(LOG_INFO, TAG_VCM, "@@@ Get TTS feedback streaming");
+                       int pid = -1;
+                       int utt_id = -1;;
                        vc_feedback_event_e event;
                        char* buffer = NULL;
                        int len;
 
                        dbus_message_get_args(msg, &err,
+                                       DBUS_TYPE_INT32, &pid,
+                                       DBUS_TYPE_INT32, &utt_id,
                                        DBUS_TYPE_INT32, &event,
                                        DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
                                        &buffer, &len,
                                        DBUS_TYPE_INVALID);
 
-                       __vc_mgr_cb_feedback_streaming(event, buffer, len);
+                       __vc_mgr_cb_feedback_streaming(pid, utt_id, event, buffer, len);
 
                        SLOG(LOG_INFO, TAG_VCM, "@@@");
                } /* VCD_MANAGER_METHOD_FEEDBACK_STREAMING */
@@ -2293,3 +2297,35 @@ int vc_mgr_dbus_send_specific_engine_request(int pid, const char* engine_app_id,
 
        return 0;
 }
+
+int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status)
+{
+       DBusMessage* msg;
+
+       /* create a signal & check for errors */
+       msg = __get_message(pid, VC_MANAGER_METHOD_UTTERANCE_STATUS, VC_COMMAND_TYPE_FOREGROUND);
+
+       if (NULL == msg) {
+               SLOG(LOG_ERROR, TAG_VCM, "@@ vc send utterance status : Fail to make message");
+               return VC_ERROR_OPERATION_FAILED;
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCM, "@@ vc send utterance status : pid(%d), utt_id(%d), utt_status(%d)", pid, utt_id, utt_status);
+       }
+
+       dbus_message_append_args(msg,
+                               DBUS_TYPE_INT32, &utt_id,
+                               DBUS_TYPE_INT32, &utt_status,
+                               DBUS_TYPE_INVALID);
+
+       dbus_message_set_no_reply(msg, TRUE);
+
+       if (1 != dbus_connection_send(g_m_conn_sender, msg, NULL)) {
+               SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Fail to Send");
+               return -1;
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCM, "[Dbus] SUCCESS Send");
+               dbus_connection_flush(g_m_conn_sender);
+       }
+
+       return 0;
+}
index 26789e8796c36aefbd520cbf208a7ea8aa58952e..b0b5c2fe4412acd695b7f4b00565496e7aea35af 100644 (file)
@@ -74,6 +74,9 @@ int vc_mgr_dbus_request_start_feedback(int pid);
 
 int vc_mgr_dbus_request_stop_feedback(int pid);
 
+int vc_mgr_dbus_send_utterance_status(int pid, int utt_id, int utt_status);
+
+
 #ifdef __cplusplus
 }
 #endif
index d58ed69965be6028559902bdd708682de05e4f76..0458c37a698b39f6782240f63760a6cacf79523c 100644 (file)
@@ -69,12 +69,17 @@ extern "C" {
 #define VC_METHOD_SET_SERVER_DIALOG    "vc_method_set_server_dialog"
 #define VC_METHOD_DIALOG               "vc_method_dialog"
 #define VC_METHOD_IS_SYS_COMMAND_VALID "vc_method_is_system_command_valid"
+#define VC_METHOD_REQUEST_TTS  "vc_method_request_tts"
+#define VC_METHOD_CANCEL_TTS   "vc_method_cancel_tts"
+#define VC_METHOD_GET_TTS_AUDIO_FORMAT "vc_method_get_tts_audio_format"
+
 
 #define VCD_METHOD_RESULT              "vcd_method_result"
 #define VCD_METHOD_ERROR               "vcd_method_error"
 #define VCD_METHOD_HELLO               "vcd_method_hello"
 #define VCD_METHOD_SET_SERVICE_STATE   "vcd_method_set_service_state"
 #define VCD_METHOD_SEND_MANAGER_PID    "vcd_method_send_manager_pid"
+#define VCD_METHOD_FEEDBACK_STREAMING  "vcd_method_feedback_streaming"
 
 /* Authority */
 #if 0
@@ -144,6 +149,7 @@ extern "C" {
 
 #define VC_MANAGER_METHOD_START_FEEDBACK       "vc_manager_method_request_start_feedback"
 #define VC_MANAGER_METHOD_STOP_FEEDBACK                "vc_manager_method_request_stop_feedback"
+#define VC_MANAGER_METHOD_UTTERANCE_STATUS     "vc_manager_method_utterance_status"
 
 #define VCD_MANAGER_METHOD_HELLO               "vcd_manager_method_hello"
 #define VCD_MANAGER_METHOD_SPEECH_DETECTED     "vcd_manager_method_speech_detected"
index eeacc297305fb3dd4a0854487cc1f4e55989414b..52960a416d36c88abdebd738817208af2996e8ab 100644 (file)
@@ -25,3 +25,4 @@ INSTALL(FILES ${CMAKE_BINARY_DIR}/include/voice_control_manager_internal.h DESTI
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/voice_control_setting.h DESTINATION ${INCLUDEDIR})
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/voice_control_widget.h DESTINATION ${INCLUDEDIR})
 INSTALL(FILES ${CMAKE_BINARY_DIR}/include/vce.h DESTINATION ${INCLUDEDIR})
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/vce_internal.h DESTINATION ${INCLUDEDIR})
index af5c5fd6fce787e2909626ea94584ba73834580e..af6f5ce495d76d9b1f72cbb01a30c6dd299164e5 100644 (file)
@@ -557,6 +557,72 @@ typedef int (*vce_get_info_cb)(char** engine_uuid, char** engine_name, char** en
  */
 typedef bool (*vce_command_cb)(int id, int type, int format, const char* command, const char* param, int domain, void* user_data);
 
+/**
+ * @brief Called when the engine service user (voice control client) requests to send TTS feedback.
+ * @since_tizen 5.0
+ * @remarks The @a text and @a language can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] pid The process id of the engine service user (voice control client)
+ * @param[in] utt_id The utterance id
+ * @param[in] text The text for TTS feedback
+ * @param[in] language The language
+ * @param[in] user_data The user data passed from the callback setter function
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #VCE_ERROR_NONE Successful
+ * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VCE_ERROR_OPERATION_FAILED Operation failure
+ *
+ * @pre An application registers callback function using vce_set_request_tts_cb().
+ *
+ * @see vce_set_request_tts_cb()
+ * @see vce_unset_request_tts_cb()
+ */
+typedef int (*vce_request_tts_cb)(int pid, int utt_id, const char* text, const char* language, void* user_data);
+
+/**
+ * @brief Called when the engine service user cancels TTS feedback.
+ * @since_tizen 5.0
+ *
+ * @param[in] pid The process id of the engine service user
+ * @param[in] utt_id The utterance id corresponding to the text
+ * @param[in] user_data The user data passed from the callback setter function
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #VCE_ERROR_NONE Successful
+ * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VCE_ERROR_OPERATION_FAILED Operation failure
+ *
+ * @pre An application registers callback function using vce_set_cancel_tts_cb().
+ *
+ * @see vce_set_cancel_tts_cb()
+ * @see vce_unset_cancel_tts_cb()
+*/
+typedef int (*vce_cancel_tts_cb)(int pid, int utt_id, void* user_data);
+
+/**
+ * @brief Called when the engine service user requests TTS audio format.
+ * @since_tizen 5.0
+ * @remarks The @a rate, @a channel, and @a audio_type should not be released.
+ *          The @a rate, @a channel, and @a audio_type are managed by the platform and will be released after the audio format is transferred to the VC client.
+ *
+ * @param[out] rate The audio sample rate
+ * @param[out] channel The audio channel
+ * @param[out] audio_type The audio type
+ * @param[in] user_data The user data passed from the callback setter function
+ *
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #VCE_ERROR_NONE Successful
+ * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VCE_ERROR_OPERATION_FAILED Operation failure
+ *
+ * @pre An application registers callback function using vce_set_tts_audio_format_request_cb().
+ *
+ * @see vce_set_tts_audio_format_request_cb()
+ * @see vce_unset_tts_audio_format_request_cb()
+ */
+typedef int (*vce_tts_audio_format_request_cb)(int* rate, int* channel, int* audio_type, void* user_data);
+
 
 /**
  * @brief A structure for the VC engine functions.
@@ -596,10 +662,10 @@ typedef struct {
        vce_process_haptic_event_cb                     process_haptic_event;   /**< Request to process haptic event */
 
        /* Optional callbacks */
-       vce_private_data_set_cb                         private_data_set;
-       vce_private_data_requested_cb           private_data_request;
-       vce_nlu_base_info_requested_cb          nlu_base_info_request;
-       vce_specific_engine_request_cb          specific_engine_request;
+       vce_private_data_set_cb                         private_data_set;               /**< Set private data from the app */
+       vce_private_data_requested_cb           private_data_request;   /**< Send private data to the app */
+       vce_nlu_base_info_requested_cb          nlu_base_info_request;  /**< Send essential value from NLU result */
+       vce_specific_engine_request_cb          specific_engine_request;        /**< Get specific engine's request from the engine service user */
 } vce_request_callback_s;
 
 /**
@@ -1038,6 +1104,93 @@ int vce_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_au
  */
 int vce_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int len);
 
+/**
+ * @brief Sets a callback function for getting the request of sending TTS feedback from the engine service user.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback_func Callback function to be registered
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VCE_ERROR_NONE Successful
+ * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VCE_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see vce_request_tts_cb()
+ * @see vce_unset_request_tts_cb()
+ */
+int vce_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data);
+
+/**
+ * @brief Unsets the TTS feedback request callback function.
+ * @since_tizen 5.0
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see vce_set_request_tts_cb()
+ */
+int vce_unset_request_tts_cb(void);
+
+/**
+ * @brief Sets a callback function for getting the request of canceling TTS feedback from the engine service user.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback_func Callback function to be registered
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VCE_ERROR_NONE Successful
+ * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VCE_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see vce_cancel_tts_cb()
+ * @see vce_unset_cancel_tts_cb()
+ */
+int vce_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data);
+
+/**
+ * @brief Unsets the TTS feedback cancellation callback function.
+ * @since_tizen 5.0
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see vce_set_cancel_tts_cb()
+ */
+int vce_unset_cancel_tts_cb(void);
+
+/**
+ * @brief Sets a callback function for sending TTS audio format to the engine service user.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback_func Callback function to be registered
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VCE_ERROR_NONE Successful
+ * @retval #VCE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VCE_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see vce_tts_audio_format_request_cb()
+ * @see vce_unset_get_tts_audio_format_cb()
+ */
+int vce_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data);
+
+/**
+ * @brief Unsets the TTS audio format request callback function.
+ * @since_tizen 5.0
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @see vce_set_tts_audio_format_cb()
+ */
+int vce_unset_get_tts_audio_format_cb(void);
+
 
 #ifdef __cplusplus
 }
diff --git a/include/vce_internal.h b/include/vce_internal.h
new file mode 100644 (file)
index 0000000..c7439bb
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __VCE_INTERNAL_H__
+#define __VCE_INTERNAL_H__
+
+#include <tizen.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief A structure for the VC engine functions.
+ * @details This structure contains essential callback functions for operating VC engine.
+ * @since_tizen 4.0
+ * @remarks These functions are optional for operating VC engine.
+ */
+typedef struct {
+       /* Optional callbacks */
+       vce_request_tts_cb                                      request_tts;
+       void*                                                           request_tts_user_data;
+       vce_cancel_tts_cb                                       cancel_tts;
+       void*                                                           cancel_tts_user_data;
+       vce_tts_audio_format_request_cb         get_tts_audio_format;
+       void*                                                           get_tts_audio_format_user_data;
+} vce_internal_request_callback_s;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+* @}
+*/
+
+#endif /* __VCE_INTERNAL_H__ */
index 0f62a231559010077c215fb4361cdd4c64cfe0a1..dc261860b15e32fee51b56c488cae59be9de6d29 100644 (file)
@@ -26,6 +26,20 @@ extern "C"
 {
 #endif
 
+typedef enum {
+       VC_TTS_EVENT_FAIL = -1,    /**< Failed */
+       VC_TTS_EVENT_START = 1,    /**< Start event */
+       VC_TTS_EVENT_CONTINUE = 2, /**< Continue event */
+       VC_TTS_EVENT_FINISH = 3    /**< Finish event */
+} vc_tts_event_e;
+
+typedef enum {
+       VC_TTS_UTTERANCE_NONE = -1,
+       VC_TTS_UTTERANCE_STARTED = 1,
+       VC_TTS_UTTERANCE_COMPLETED = 2,
+       VC_TTS_UTTERANCE_CANCELED = 3
+} vc_tts_utterance_status_e;
+
 /**
 * @brief Called when client gets the asr recognition result from vc-daemon.
 *
@@ -42,6 +56,37 @@ extern "C"
 */
 typedef bool (*vc_asr_result_cb)(vc_result_event_e event, const char* result, void *user_data);
 
+/**
+ * @brief Called when client gets TTS streaming data from vc engine service.
+ * @since_tizen 4.0
+ *
+ * @param[in] event The TTS event
+ * @param[in] buffer The TTS streaming data
+ * @param[in] len The length of the TTS streaming data
+ * @param[in] utt_id The utterance id
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @pre An application registers callback function using vc_tts_set_streaming_cb().
+ *
+ * @see vc_tts_set_streaming_cb()
+ * @see vc_tts_unset_streaming_cb()
+ */
+typedef void (*vc_tts_streaming_cb)(vc_tts_event_e event, char* buffer, int len, int utt_id, void *user_data);
+
+/**
+ * @brief Called when client gets TTS utterance status.
+ * @since_tizen 4.0
+ *
+ * @param[in] utt_id The utterance id
+ * @param[in] status The TTS utterance status (e.g. #VC_TTS_UTTERANCE_STARTED, #VC_TTS_UTTERANCE_COMPLETED, and so on)
+ *
+ * @pre An application registers callback function using vc_tts_set_utterance_status_cb().
+ *
+ * @see vc_tts_set_utterance_status_cb()
+ * @see vc_tts_unset_utterance_status_cb()
+ */
+typedef void (*vc_tts_utterance_status_cb)(int utt_id, vc_tts_utterance_status_e  status);
+
 /**
  * @brief Sets command list from file.
  * @since_tizen 3.0
@@ -86,6 +131,131 @@ int vc_set_command_list_from_file(const char* file_path, int type);
  */
 int vc_prepare_sync(void);
 
+/**
+ * @brief Requests to send TTS streaming data.
+ * @since_tizen 4.0
+ *
+ * @param[in] text The text to be requested for TTS
+ * @param[in] language The language for TTS
+ * @param[in] to_vcm A value whether the TTS request is from vc client or vc manager
+ * @param[in] utt_id The utterance id
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_READY.
+ *
+ * @see vc_tts_cancel()
+ */
+int vc_tts_request(const char* text, const char* language, bool to_vcm, int* utt_id);
+
+/**
+ * @brief Requests to cancel TTS streaming data.
+ * @since_tizen 4.0
+ *
+ * @param[in] utt_id The utterance id
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_READY.
+ *
+ * @see vc_tts_request()
+ */
+int vc_tts_cancel(int utt_id);
+
+/**
+ * @brief Gets TTS audio format.
+ * @since_tizen 4.0
+ *
+ * @param[out] rate The audio sampling rate
+ * @param[out] channel The audio channel
+ * @param[out] audio_type The audio type
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_READY.
+ */
+int vc_tts_get_audio_format(int* rate, vc_audio_channel_e* channel, vc_audio_type_e* audio_type);
+
+/**
+ * @brief Sets TTS streaming callback function.
+ * @since_tizen 4.0
+ *
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_INITIALIZED.
+ */
+int vc_tts_set_streaming_cb(vc_tts_streaming_cb callback, void* user_data);
+
+/**
+ * @brief Unsets TTS streaming callback function.
+ * @since_tizen 4.0
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_INITIALIZED.
+ */
+int vc_tts_unset_streaming_cb(void);
+
+/**
+ * @brief Sets TTS utterance status callback function.
+ * @since_tizen 4.0
+ *
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_INITIALIZED.
+ */
+int vc_tts_set_utterance_status_cb(vc_tts_utterance_status_cb callback, void* user_data);
+
+/**
+ * @brief Unsets TTS utterance status callback function.
+ * @since_tizen 4.0
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #VC_ERROR_NOT_SUPPORTED Not supported
+ *
+ * @pre The state should be #VC_STATE_INITIALIZED.
+ */
+int vc_tts_unset_utterance_status_cb(void);
+
 
 #ifdef __cplusplus
 }
index b6918e8d5db1f3ccc15cd27ea2324462a05ef838..430daa584f577b7c574faba5effef3f344dc3ac9 100644 (file)
@@ -248,6 +248,7 @@ typedef int (*vc_mgr_private_data_requested_cb)(const char *key, char **data, vo
 /* for TTS feedback */
 /**
 * @brief Called when engine sends audio formats necessary for playing TTS feedback
+* @since_tizen 5.0
 *
 * @param[in] rate Audio sampling rate
 * @param[in] channel Audio channel (e.g. #VC_AUDIO_CHANNEL_MONO, #VC_AUDIO_CHANNEL_STEREO)
@@ -263,6 +264,7 @@ typedef void (*vc_mgr_feedback_audio_format_cb)(int rate, vc_audio_channel_e cha
 
 /**
 * @brief Called when engine sends audio streaming for TTS feedback
+* @since_tizen 5.0
 *
 * @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE)
 * @param[in] buffer Audio streaming data
@@ -276,6 +278,25 @@ typedef void (*vc_mgr_feedback_audio_format_cb)(int rate, vc_audio_channel_e cha
 */
 typedef void (*vc_mgr_feedback_streaming_cb)(vc_feedback_event_e event, char* buffer, int len, void *user_data);
 
+/**
+* @brief Called when the vc client sends audio streaming for TTS feedback
+* @since_tizen 5.0
+*
+* @remarks The @a buffer must be released with free() by you when you no longer need it.
+*
+* @param[in] pid The process id of the vc client
+* @param[in] utt_id The utterance id
+* @param[in] event TTS feedback event (e.g. #VC_FEEDBACK_EVENT_START, #VC_FEEDBACK_EVENT_CONTINUE)
+* @param[in] buffer Audio streaming data
+* @param[in] len Length of the audio streaming data
+* @param[in] user_data The user data passed from the callback registration function
+*
+* @pre An application registers callback function using vc_mgr_set_vc_tts_streaming_cb().
+*
+* @see vc_mgr_set_vc_tts_streaming_cb()
+* @see vc_mgr_unset_vc_tts_streaming_cb()
+*/
+typedef void (*vc_mgr_vc_tts_streaming_cb)(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len, void *user_data);
 
 /**
  * @platform
@@ -1701,6 +1722,40 @@ int vc_mgr_start_feedback(void);
 */
 int vc_mgr_stop_feedback(void);
 
+/**
+ * @brief Sets TTS streaming callback function.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ * @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #VC_STATE_INITIALIZED.
+ *
+ * @see vc_mgr_vc_tts_streaming_cb()
+ * @see vc_mgr_unset_vc_tts_streaming_cb()
+ */
+int vc_mgr_set_vc_tts_streaming_cb(vc_mgr_vc_tts_streaming_cb callback, void* user_data);
+
+/**
+ * @brief Unsets TTS streaming callback function.
+ * @since_tizen 5.0
+ *
+ * @return 0 on success, otherwise a negative error value
+ * @retval #VC_ERROR_NONE Successful
+ * @retval #VC_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #VC_STATE_INITIALIZED.
+ *
+ * @see vc_mgr_vc_tts_streaming_cb()
+ * @see vc_mgr_set_vc_tts_streaming_cb()
+ */
+int vc_mgr_unset_vc_tts_streaming_cb(void);
+
 
 #ifdef __cplusplus
 }
index 4b94bd52ecd674af187fc34f3439ce53473d8256..06035f503ee934721e0d99862de8f5de08ec9f0a 100644 (file)
@@ -177,4 +177,5 @@ mkdir -p %{_libdir}/voice/vc
 %defattr(-,root,root,-)
 %{_libdir}/pkgconfig/voice-control-engine.pc
 %{_includedir}/vce.h
+%{_includedir}/vce_internal.h
 
index 006586337db6040ae360cdb33ce16658601a0c6d..778f56d26774c1580735086a54a5ad89d212ffdc 100644 (file)
@@ -7,6 +7,7 @@ SET(SRCS
        ../common/vc_info_parser.c
        ../common/vc_json_parser.c
        vcd_client_data.c
+       vcd_server_data.cpp
        vcd_config.c
        vcd_dbus_server.c
        vcd_dbus.c
@@ -26,6 +27,7 @@ FOREACH(flag ${pkgs_CFLAGS})
 ENDFOREACH(flag)
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE")
+SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE")
 SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -fPIE")
 SET(CMAKE_C_FLAGS_RELEASE "-O2 -fPIE")
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
index e53814c2bf2de090b2bb0447702b723f5847367d..69e1f5222a3bacd201e97290c03b0d66a4994bc7 100644 (file)
@@ -980,9 +980,9 @@ int vcdc_send_feedback_audio_format_to_manager(int manager_pid, int rate, vc_aud
        return ret;
 }
 
-int vcdc_send_feedback_streaming_to_manager(int manager_pid, vc_feedback_event_e event, char* buffer, int len)
+int vcdc_send_feedback_streaming_to_manager(int manager_pid, int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len)
 {
-       SLOG(LOG_INFO, TAG_VCD, "[Dbus] Send TTS feedback streaming : manager_pid(%d), feedback event(%d), buffer(%p), length(%d)", manager_pid, event, buffer, len);
+       SLOG(LOG_INFO, TAG_VCD, "[Dbus] Send TTS feedback streaming : manager_pid(%d), pid(%d), utt_id(%d) feedback event(%d), buffer(%p), length(%d)", manager_pid, pid, utt_id, event, buffer, len);
 
        if (0 != __dbus_check()) {
                return VCD_ERROR_OPERATION_FAILED;
@@ -1000,6 +1000,51 @@ int vcdc_send_feedback_streaming_to_manager(int manager_pid, vc_feedback_event_e
        }
 
        dbus_message_append_args(msg,
+                       DBUS_TYPE_INT32, &pid,
+                       DBUS_TYPE_INT32, &utt_id,
+                       DBUS_TYPE_INT32, &event,
+                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+                       &buffer, len,
+                       DBUS_TYPE_INVALID);
+
+       dbus_message_set_no_reply(msg, TRUE);
+
+       int ret = VCD_ERROR_NONE;
+
+       if (1 != dbus_connection_send(g_conn_sender, msg, NULL)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Dbus ERROR] Fail to Send");
+               ret = VCD_ERROR_OPERATION_FAILED;
+       } else {
+               SLOG(LOG_INFO, TAG_VCD, "[Dbus] SUCCESS Send");
+               dbus_connection_flush(g_conn_sender);
+       }
+
+       dbus_message_unref(msg);
+
+       return ret;
+}
+
+int vcdc_send_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len)
+{
+       SLOG(LOG_INFO, TAG_VCD, "[Dbus] Send TTS feedback streaming : pid(%d), utt_id(%d), feedback event(%d), buffer(%p), length(%d)", pid, utt_id, event, buffer, len);
+
+       if (0 != __dbus_check()) {
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       DBusError err;
+       dbus_error_init(&err);
+
+       /* make dbus message */
+       DBusMessage* msg = NULL;
+       msg = __get_message(pid, VCD_METHOD_FEEDBACK_STREAMING, VCD_CLIENT_TYPE_NORMAL);
+       if (NULL == msg) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Dbus ERROR] Message is NULL");
+               return VCD_ERROR_OUT_OF_MEMORY;
+       }
+
+       dbus_message_append_args(msg,
+                       DBUS_TYPE_INT32, &utt_id,
                        DBUS_TYPE_INT32, &event,
                        DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
                        &buffer, len,
@@ -1168,6 +1213,15 @@ static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handle
                else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_SETTING_METHOD_SET_LANGUAGE))
                        vcd_dbus_server_set_language(g_conn_listener, msg);
 
+               else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_REQUEST_TTS))
+                       vcd_dbus_server_request_tts(g_conn_listener, msg);
+
+               else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_CANCEL_TTS))
+                       vcd_dbus_server_cancel_tts(g_conn_listener, msg);
+
+               else if (dbus_message_is_method_call(msg, VC_SERVER_SERVICE_INTERFACE, VC_METHOD_GET_TTS_AUDIO_FORMAT))
+                       vcd_dbus_server_get_tts_audio_format(g_conn_listener, msg);
+
                else {
                        SLOG(LOG_DEBUG, TAG_VCD, "Message is NOT valid");
                        dbus_message_unref(msg);
index 0dbe18876220ea4320f408d010325497ed1fef6f..a6d97a549e1aa2ec1cc131ea0ca6313f52c975c0 100644 (file)
@@ -71,7 +71,9 @@ int vcdc_send_request_get_private_data(int pid, const char* key, char** data);
 /* for TTS feedback */
 int vcdc_send_feedback_audio_format_to_manager(int manager_pid, int rate, vc_audio_channel_e channel, vce_audio_type_e audio_type);
 
-int vcdc_send_feedback_streaming_to_manager(int manager_pid, vc_feedback_event_e event, char* buffer, int len);
+int vcdc_send_feedback_streaming_to_manager(int manager_pid, int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len);
+
+int vcdc_send_feedback_streaming(int pid, int utt_id, vc_feedback_event_e event, char* buffer, int len);
 
 
 #ifdef __cplusplus
index 71329a68dceda212463606b43ae8b5f3c1fd28ba..68b0ae1fa209dfe582f08216cc636db6ee1c7a92 100644 (file)
@@ -2205,4 +2205,172 @@ int vcd_dbus_server_set_language(DBusConnection* conn, DBusMessage* msg)
        SLOG(LOG_DEBUG, TAG_VCD, "@@@");
 
        return 0;
-}
\ No newline at end of file
+}
+int vcd_dbus_server_request_tts(DBusConnection* conn, DBusMessage* msg)
+{
+       DBusError err;
+       dbus_error_init(&err);
+
+       int pid;
+       char* text = NULL;
+       char* language = NULL;
+       int to_vcm;
+       int utt_id = -1;
+       int ret = VCD_ERROR_OPERATION_FAILED;
+
+       dbus_message_get_args(msg, &err,
+                               DBUS_TYPE_INT32, &pid,
+                               DBUS_TYPE_STRING, &text,
+                               DBUS_TYPE_STRING, &language,
+                               DBUS_TYPE_INT32, &to_vcm,
+                               DBUS_TYPE_INVALID);
+
+       SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD request tts");
+
+       if (dbus_error_is_set(&err)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd request tts : get arguments error (%s)", err.message);
+               dbus_error_free(&err);
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd request tts : pid(%d), text(%s), language(%s), to_vcm(%d)", pid, text, language, to_vcm);
+               ret = vcd_server_request_tts(pid, text, language, to_vcm, &utt_id);
+       }
+
+       DBusMessage* reply;
+       reply = dbus_message_new_method_return(msg);
+
+       if (NULL != reply) {
+               dbus_message_append_args(reply,
+                       DBUS_TYPE_INT32, &ret,
+                       DBUS_TYPE_INT32, &utt_id,
+                       DBUS_TYPE_INVALID);
+
+               if (0 == ret) {
+                       SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d), utt_id(%d)", ret, utt_id);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret);
+               }
+
+               if (!dbus_connection_send(conn, reply, NULL)) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!");
+               }
+
+               dbus_connection_flush(conn);
+               dbus_message_unref(reply);
+       } else {
+               SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!");
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCD, "@@@");
+
+       return 0;
+}
+
+int vcd_dbus_server_cancel_tts(DBusConnection* conn, DBusMessage* msg)
+{
+       DBusError err;
+       dbus_error_init(&err);
+
+       int pid;
+       int utt_id;
+       int ret = VCD_ERROR_OPERATION_FAILED;
+
+       dbus_message_get_args(msg, &err,
+                               DBUS_TYPE_INT32, &pid,
+                               DBUS_TYPE_INT32, &utt_id,
+                               DBUS_TYPE_INVALID);
+
+       SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD cancel tts");
+
+       if (dbus_error_is_set(&err)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd cancel tts : get arguments error (%s)", err.message);
+               dbus_error_free(&err);
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd cancel tts : pid(%d), utt_id(%d)", pid, utt_id);
+               ret = vcd_server_cancel_tts(pid, utt_id);
+       }
+
+       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, TAG_VCD, "[OUT SUCCESS] Result(%d)", ret);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret);
+               }
+
+               if (!dbus_connection_send(conn, reply, NULL)) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!");
+               }
+
+               dbus_connection_flush(conn);
+               dbus_message_unref(reply);
+       } else {
+               SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!");
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCD, "@@@");
+
+       return 0;
+}
+
+int vcd_dbus_server_get_tts_audio_format(DBusConnection* conn, DBusMessage* msg)
+{
+       DBusError err;
+       dbus_error_init(&err);
+
+       int pid;
+       int rate;
+       int channel;
+       int audio_type;
+       int ret = VCD_ERROR_OPERATION_FAILED;
+
+       dbus_message_get_args(msg, &err,
+                               DBUS_TYPE_INT32, &pid,
+                               DBUS_TYPE_INVALID);
+
+       SLOG(LOG_DEBUG, TAG_VCD, "@@@ VCD request tts");
+
+       if (dbus_error_is_set(&err)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[IN ERROR] vcd get tts audio format : get arguments error (%s)", err.message);
+               dbus_error_free(&err);
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "[IN] vcd get tts audio format : pid(%d)", pid);
+               ret = vcd_server_get_tts_audio_format(pid, &rate, &channel, &audio_type);
+       }
+
+       DBusMessage* reply;
+       reply = dbus_message_new_method_return(msg);
+
+       if (NULL != reply) {
+               dbus_message_append_args(reply,
+                       DBUS_TYPE_INT32, &ret,
+                       DBUS_TYPE_INT32, &rate,
+                       DBUS_TYPE_INT32, &channel,
+                       DBUS_TYPE_INT32, &audio_type,
+                       DBUS_TYPE_INVALID);
+
+               if (0 == ret) {
+                       SLOG(LOG_DEBUG, TAG_VCD, "[OUT SUCCESS] Result(%d)", ret);
+               } else {
+                       SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Result(%d)", ret);
+               }
+
+               if (!dbus_connection_send(conn, reply, NULL)) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Out Of Memory!");
+               }
+
+               dbus_connection_flush(conn);
+               dbus_message_unref(reply);
+       } else {
+               SLOG(LOG_ERROR, TAG_VCD, "[OUT ERROR] Fail to create reply message!!");
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCD, "@@@");
+
+       return 0;
+}
index 145653636ad200d2d6dcaf6c491c773426248133..bef7205e9536c3df6002f36d1ecd2ada213c0f58 100644 (file)
@@ -126,6 +126,13 @@ int vcd_dbus_server_widget_enable_asr_result(DBusConnection* conn, DBusMessage*
 
 int vcd_dbus_server_set_language(DBusConnection* conn, DBusMessage* msg);
 
+int vcd_dbus_server_request_tts(DBusConnection* conn, DBusMessage* msg);
+
+int vcd_dbus_server_cancel_tts(DBusConnection* conn, DBusMessage* msg);
+
+int vcd_dbus_server_get_tts_audio_format(DBusConnection* conn, DBusMessage* msg);
+
+
 #ifdef __cplusplus
 }
 #endif
index 8794ae0b5a5bd3df7481099467cf6b91305e6486..68b8f83f03baa811f700bcb40f2a9cf998ee8799 100644 (file)
@@ -24,6 +24,7 @@
 #include "vcd_main.h"
 #include "vcd_recorder.h"
 #include "vcd_dbus.h"
+#include "vce_internal.h"
 
 /*
  * Internal data structure
@@ -43,6 +44,7 @@ typedef struct {
        void    *handle;
 
        vce_request_callback_s* callbacks;
+       vce_internal_request_callback_s* internal_callbacks;
 } vcengine_s;
 
 typedef struct _vcengine_info {
@@ -96,7 +98,13 @@ int vcd_engine_agent_init()
 
        g_dynamic_engine.callbacks = (vce_request_callback_s*)calloc(1, sizeof(vce_request_callback_s));
        if (NULL == g_dynamic_engine.callbacks) {
-               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to allocate memory");
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to allocate memory for callbacks");
+               return VCD_ERROR_OUT_OF_MEMORY;
+       }
+
+       g_dynamic_engine.internal_callbacks = (vce_internal_request_callback_s*)calloc(1, sizeof(vce_internal_request_callback_s));
+       if (NULL == g_dynamic_engine.internal_callbacks) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Fail to allocate memory for internal callbacks");
                return VCD_ERROR_OUT_OF_MEMORY;
        }
 
@@ -188,7 +196,17 @@ int __internal_get_engine_info(vce_request_callback_s* callback)
        }
        g_dynamic_engine.callbacks = (vce_request_callback_s*)calloc(1, sizeof(vce_request_callback_s));
        if (NULL == g_dynamic_engine.callbacks) {
-               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to allocate memory");
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to allocate memory for callbacks");
+               return VCD_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (NULL != g_dynamic_engine.internal_callbacks) {
+               free(g_dynamic_engine.internal_callbacks);
+               g_dynamic_engine.internal_callbacks = NULL;
+       }
+       g_dynamic_engine.internal_callbacks = (vce_internal_request_callback_s*)calloc(1, sizeof(vce_internal_request_callback_s));
+       if (NULL == g_dynamic_engine.internal_callbacks) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to allocate memory for internal callbacks");
                return VCD_ERROR_OUT_OF_MEMORY;
        }
 
@@ -217,6 +235,9 @@ int __internal_get_engine_info(vce_request_callback_s* callback)
        g_dynamic_engine.callbacks->private_data_request = NULL;
        g_dynamic_engine.callbacks->nlu_base_info_request = NULL;
        g_dynamic_engine.callbacks->specific_engine_request = NULL;
+       g_dynamic_engine.internal_callbacks->request_tts = NULL;
+       g_dynamic_engine.internal_callbacks->cancel_tts = NULL;
+       g_dynamic_engine.internal_callbacks->get_tts_audio_format = NULL;
 
        SLOG(LOG_DEBUG, TAG_VCD, "@@@ Valid Engine");
        SLOG(LOG_DEBUG, TAG_VCD, "Engine uuid : %s", g_dynamic_engine.engine_uuid);
@@ -668,6 +689,75 @@ int vcd_engine_process_haptic_event(int pid, const char* event)
        return 0;
 }
 
+int vcd_engine_request_tts(int pid, int utt_id, const char* text, const char* language)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent] Request tts to engine");
+
+       int ret = -1;
+       if (true == g_dynamic_engine.is_loaded && NULL != g_dynamic_engine.internal_callbacks->request_tts) {
+               ret = g_dynamic_engine.internal_callbacks->request_tts(pid, utt_id, text, language, g_dynamic_engine.internal_callbacks->request_tts_user_data);
+               if (0 != ret) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set request tts (%d)", ret);
+                       return VCD_ERROR_OPERATION_FAILED;
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no request tts callback");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       return 0;
+}
+
+int vcd_engine_cancel_tts(int pid, int utt_id)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       int ret = -1;
+       if (true == g_dynamic_engine.is_loaded && NULL != g_dynamic_engine.internal_callbacks->cancel_tts) {
+               ret = g_dynamic_engine.internal_callbacks->cancel_tts(pid, utt_id, g_dynamic_engine.internal_callbacks->cancel_tts_user_data);
+               if (0 != ret) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to set cancel tts (%d)", ret);
+                       return VCD_ERROR_OPERATION_FAILED;
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no cancel tts callback");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       return 0;
+}
+
+int vcd_engine_get_tts_audio_format(int* rate, int* channel, int* audio_type)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       int ret = -1;
+       if (true == g_dynamic_engine.is_loaded && NULL != g_dynamic_engine.internal_callbacks->get_tts_audio_format) {
+               ret = g_dynamic_engine.internal_callbacks->get_tts_audio_format(rate, channel, audio_type, g_dynamic_engine.internal_callbacks->get_tts_audio_format_user_data);
+               if (0 != ret) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Fail to get tts audio format(%d)", ret);
+                       return VCD_ERROR_OPERATION_FAILED;
+               }
+       } else {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Engine is not loaded or There is no get tts audio format callback");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       return 0;
+}
+
+
 /*
  * VCS Engine Interfaces for client and setting
  */
@@ -904,3 +994,57 @@ int vcd_engine_agent_set_specific_engine_request_cb(vce_specific_engine_request_
 
        return VCD_ERROR_NONE;
 }
+
+int vcd_engine_agent_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_dynamic_engine.is_loaded) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not loaded engine");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       g_dynamic_engine.internal_callbacks->request_tts = callback_func;
+       g_dynamic_engine.internal_callbacks->request_tts_user_data = user_data;
+
+       return VCD_ERROR_NONE;
+}
+
+int vcd_engine_agent_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_dynamic_engine.is_loaded) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not loaded engine");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       g_dynamic_engine.internal_callbacks->cancel_tts = callback_func;
+       g_dynamic_engine.internal_callbacks->cancel_tts_user_data = user_data;
+
+       return VCD_ERROR_NONE;
+}
+
+int vcd_engine_agent_set_get_tts_audio_format_cb(vce_tts_audio_format_request_cb callback_func, void* user_data)
+{
+       if (false == g_agent_init) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not Initialized");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       if (false == g_dynamic_engine.is_loaded) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Engine Agent ERROR] Not loaded engine");
+               return VCD_ERROR_OPERATION_FAILED;
+       }
+
+       g_dynamic_engine.internal_callbacks->get_tts_audio_format = callback_func;
+       g_dynamic_engine.internal_callbacks->get_tts_audio_format_user_data = user_data;
+
+       return VCD_ERROR_NONE;
+}
index 4dc5e25fb42c37040eacf909de1f873917cacc86..2532a82a36fad0469ab786bf0d979c03bc6e1a77 100644 (file)
@@ -84,6 +84,13 @@ int vcd_engine_process_list_event(int pid, const char* event);
 
 int vcd_engine_process_haptic_event(int pid, const char* event);
 
+int vcd_engine_request_tts(int pid, int utt_id, const char* text, const char* language);
+
+int vcd_engine_cancel_tts(int pid, int utt_id);
+
+int vcd_engine_get_tts_audio_format(int* rate, int* channel, int* audio_type);
+
+
 /* for engine service */
 int vcd_engine_agent_get_foreach_command(vce_cmd_h vce_command, vce_command_cb callback, void* user_data);
 
@@ -107,6 +114,13 @@ int vcd_engine_agent_set_nlu_base_info_requested_cb(vce_nlu_base_info_requested_
 
 int vcd_engine_agent_set_specific_engine_request_cb(vce_specific_engine_request_cb callback_func);
 
+int vcd_engine_agent_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data);
+
+int vcd_engine_agent_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data);
+
+int vcd_engine_agent_set_get_tts_audio_format_cb(vce_tts_audio_format_request_cb callback_func, void* user_data);
+
+
 #ifdef __cplusplus
 }
 #endif
index a9f794389057a294c61dc564035773835a3bafcd..3d8525b7eab815eeb3f50fd5ac2d9801b59b3eef 100644 (file)
@@ -74,9 +74,9 @@ typedef enum {
        VCD_STATE_PROCESSING = 3
 } vcd_state_e;
 
-typedef struct {
+struct vce_cmd_s {
        int index;
-} vce_cmd_s;
+};
 
 
 #ifdef __cplusplus
index f94996296f3eb7b7dc53f4ce11d1006c4b34bb88..d79b9464a238a47a434d9289b7216aa0244d1a39 100644 (file)
@@ -23,6 +23,7 @@
 #include "vc_info_parser.h"
 #include "vcd_main.h"
 #include "vcd_server.h"
+#include "vcd_server_data.h"
 #include "vcd_client_data.h"
 
 #include "vcd_engine_agent.h"
@@ -43,6 +44,10 @@ static Ecore_Timer *g_restart_timer = NULL;
 static Ecore_Timer *g_check_widget_client_timer = NULL;
 static Ecore_Timer *g_check_client_timer = NULL;
 
+static Ecore_Thread* g_tts_thread = NULL;
+static int g_current_uid = -1;
+static int g_current_utt_id = -1;
+
 /**
 * @brief Enumerations of send event type.
 */
@@ -1096,25 +1101,51 @@ int vcd_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_au
 
        /* send TTS feedback audio format to VC manager */
        int ret = VCD_ERROR_NONE;
+       int pid = g_current_uid / 1000;
+       if (-1 == g_current_uid || vcd_client_manager_get_pid() == pid) {
        ret = vcdc_send_feedback_audio_format_to_manager(vcd_client_manager_get_pid(), rate, channel, audio_type);
        if (VCD_ERROR_NONE != ret) {
                SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback audio format to VC manager");
        }
+       } else {
+               SLOG(LOG_INFO, TAG_VCD, "[Server INFO] Do not send TTS feedback audio format to VC manager");
+       }
 
        return ret;
 }
 
 int vcd_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int len)
 {
-       SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback streaming");
+       if (-1 == g_current_uid && VCE_FEEDBACK_EVENT_START == event) {
+               g_current_utt_id = (g_current_utt_id + 1) % 1000;
+               g_current_uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id;
+               SLOG(LOG_INFO, TAG_VCD, "[Server info] set current uid and utt_id as manager pid");
+       }
 
-       /* send TTS feedback streaming to VC manager */
        int ret = VCD_ERROR_NONE;
-       ret = vcdc_send_feedback_streaming_to_manager(vcd_client_manager_get_pid(), event, buffer, len);
+       int pid = g_current_uid / 1000;
+       int utt_id = g_current_uid % 1000;
+
+       SLOG(LOG_INFO, TAG_VCD, "[Server DEBUG] Engine - Send TTS feedback streaming to pid(%d), is_mgr_client(%d)", pid, (pid == vcd_client_manager_get_pid() ? true : false));
+
+       if (pid == vcd_client_manager_get_pid()) {
+               /* send TTS feedback streaming to manager client */
+               ret = vcdc_send_feedback_streaming_to_manager(vcd_client_manager_get_pid(), pid, utt_id, event, buffer, len);
+               if (VCD_ERROR_NONE != ret) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to manager client");
+               }
+       } else {
+               /* send TTS feedback streaming to client */
+               ret = vcdc_send_feedback_streaming(pid, utt_id, event, buffer, len);
        if (VCD_ERROR_NONE != ret) {
-               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to VC manager");
+                       SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to send TTS feedback streaming to client");
+       }
        }
 
+       if (VCE_FEEDBACK_EVENT_FINISH == event) {
+               /* reset current uid */
+               g_current_uid = -1;
+       }
        return ret;
 }
 
@@ -1221,6 +1252,9 @@ int vcd_initialize(vce_request_callback_s *callback)
                SLOG(LOG_WARN, TAG_VCD, "[Server Warning] Fail to create timer of client check");
        }
 
+       g_current_uid = -1;
+       g_current_utt_id = -1;
+
        SLOG(LOG_ERROR, TAG_VCD, "[Server SUCCESS] initialize");
 
        return 0;
@@ -2420,6 +2454,157 @@ int vcd_server_is_system_command_valid(int pid, int* is_sys_cmd_valid)
        return 0;
 }
 
+static void __start_tts_request_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[SUCCESS] Start tts request thread");
+       vc_tts_text_data_s* tts_text_data = NULL;
+
+       while (1) {
+               int ret = -1;
+
+               /* Get tts text data */
+               ret = vcd_data_get_first_tts_text_data(&tts_text_data);
+               if (0 != ret || NULL == tts_text_data) {
+                       /* empty queue */
+                       if (0 >= vcd_data_get_tts_text_data_size()) {
+                               SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] No tts text data");
+                               return;
+                       }
+                       SLOG(LOG_INFO, TAG_VCD, "[INFO] tts text data is just incoming");
+                       continue;
+               }
+
+               /* Request tts to engine */
+               ret = vcd_engine_request_tts(tts_text_data->pid, tts_text_data->utt_id, tts_text_data->text, tts_text_data->language);
+               if (0 != ret) {
+                       SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to request tts : %d", ret);
+               } else {
+                       SLOG(LOG_DEBUG, TAG_VCD, "[Server SUCCESS] request tts, uid(%d) pid(%d), text(%s), language(%s), utt_id(%d)",
+                               tts_text_data->uid, tts_text_data->pid, tts_text_data->text, tts_text_data->language, tts_text_data->utt_id);
+               }
+               /* clear tts text data after use */
+               vcd_data_clear_tts_text_data(&tts_text_data);
+
+       }
+}
+
+static void __end_tts_request_thread(void* data, Ecore_Thread* thread)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[SUCCESS] End tts request thread");
+       g_tts_thread = NULL;
+}
+
+int vcd_server_request_tts(int pid, const char* text, const char* language, int to_vcm, int* utt_id)
+{
+       /* check if pid is valid */
+       if (false == vcd_client_is_available(pid)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid ");
+               return VCD_ERROR_INVALID_PARAMETER;
+       }
+
+       vcd_state_e state = vcd_config_get_service_state();
+       if (VCD_STATE_READY != state) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready, state(%d)", state);
+               return VCD_ERROR_INVALID_STATE;
+       }
+
+       g_current_utt_id = (g_current_utt_id + 1) % 1000;
+       *utt_id = g_current_utt_id;
+       if (0 == to_vcm) {
+               g_current_uid = pid * 1000 + g_current_utt_id;
+       } else {
+               g_current_uid = vcd_client_manager_get_pid() * 1000 + g_current_utt_id;
+       }
+       SLOG(LOG_INFO, TAG_VCD, "[Server INFO] pid(%d), text(%s), language(%s), to_vcm(%d), ", pid, text, language, to_vcm);
+       SLOG(LOG_INFO, TAG_VCD, "[Server INFO] current_uid(%d), current_utt_id(%d)", g_current_uid, g_current_utt_id);
+
+       vc_tts_text_data_s* tts_text_data;
+       tts_text_data = (vc_tts_text_data_s*)calloc(1, sizeof(vc_tts_text_data_s));
+       if (!tts_text_data) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to callocate memory ");
+               return VCD_ERROR_OUT_OF_MEMORY;
+       }
+       tts_text_data->uid = g_current_uid;
+       tts_text_data->pid = pid;
+       tts_text_data->utt_id = g_current_utt_id;
+       tts_text_data->text = strdup(text);
+       tts_text_data->language = strdup(language);
+
+       int ret = vcd_data_add_tts_text_data(tts_text_data->uid, tts_text_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to add tts text data : %d", ret);
+       }
+
+       bool is_canceled = ecore_thread_check(g_tts_thread);
+       if (NULL == g_tts_thread || TRUE == is_canceled) {
+               SLOG(LOG_INFO, TAG_VCD, "[Server INFO] ecore thread run : start_tts_request_thread ");
+               g_tts_thread = ecore_thread_run(__start_tts_request_thread, __end_tts_request_thread, NULL, NULL);
+       }
+
+       return 0;
+}
+
+int vcd_server_cancel_tts(int pid, int utt_id)
+{
+       /* check if pid is valid */
+       if (false == vcd_client_is_available(pid)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid ");
+               return VCD_ERROR_INVALID_PARAMETER;
+       }
+
+       vcd_state_e state = vcd_config_get_service_state();
+       if (VCD_STATE_READY != state) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready, state(%d)", state);
+               return VCD_ERROR_INVALID_STATE;
+       }
+
+       vc_tts_text_data_s* tts_text_data = NULL;
+
+       int uid = pid * 1000 + utt_id;
+       int ret = vcd_data_get_tts_text_data(uid, &tts_text_data);
+       if (0 != ret) {
+               SLOG(LOG_WARN, TAG_VCD, "[Server WARN] No data in vcd tts text queue");
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "[Server] Clear tts text data, pid(%d), utt_id(%d), text(%s)", pid, utt_id, tts_text_data->text);
+               vcd_data_clear_tts_text_data(&tts_text_data);
+       }
+
+       /* Request tts to engine */
+       ret = vcd_engine_cancel_tts(pid, utt_id);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to cancel tts : %d", ret);
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "[Server SUCCESS] request tts, pid(%d), utt_id(%d)", pid, utt_id);
+       }
+
+       return 0;
+}
+
+int vcd_server_get_tts_audio_format(int pid, int* rate, int* channel, int* audio_type)
+{
+       /* check if pid is valid */
+       if (false == vcd_client_is_available(pid)) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] pid is NOT valid ");
+               return VCD_ERROR_INVALID_PARAMETER;
+       }
+
+       vcd_state_e state = vcd_config_get_service_state();
+       if (VCD_STATE_READY != state) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Current state is not ready");
+               return VCD_ERROR_INVALID_STATE;
+       }
+
+       /* Request tts to engine */
+       int ret = vcd_engine_get_tts_audio_format(rate, channel, audio_type);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to get tts audio format : %d", ret);
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "[Server SUCCESS] get tts audio format, pid(%d), rate(%d), channel(%d), audio_type(%d)", pid, *rate, *channel, *audio_type);
+       }
+
+       return ret;
+}
+
 #if 0
 int vcd_server_set_exclusive_command(int pid, bool value)
 {
@@ -2909,3 +3094,39 @@ int vcd_set_specific_engine_request_cb(vce_specific_engine_request_cb callback_f
 
        return ret;
 }
+
+int vcd_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set request tts cb");
+       int ret = 0;
+       ret = vcd_engine_agent_set_request_tts_cb(callback_func, user_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to set request tts cb : ret(%d)", ret);
+       }
+
+       return ret;
+}
+
+int vcd_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set cancel tts cb");
+       int ret = 0;
+       ret = vcd_engine_agent_set_cancel_tts_cb(callback_func, user_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to set cancel tts cb : ret(%d)", ret);
+       }
+
+       return ret;
+}
+
+int vcd_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[Server] Set tts audio format request cb");
+       int ret = 0;
+       ret = vcd_engine_agent_set_get_tts_audio_format_cb(callback_func, user_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to set tts audio format request : ret(%d)", ret);
+       }
+
+       return ret;
+}
index e11108f91fb9a733869fe3dcdb14feb28af3590d..87b735c37c4ffe30adc044ca5e5cbda77cb34fa9 100644 (file)
@@ -136,6 +136,12 @@ int vcd_server_set_language(const char* language);
 
 int vcd_server_mgr_send_specific_engine_request(int pid, const char* engine_app_id, const char* event, const char* request);
 
+int vcd_server_request_tts(int pid, const char* text, const char* language, int to_vcm, int* utt_id);
+
+int vcd_server_cancel_tts(int pid, int utt_id);
+
+int vcd_server_get_tts_audio_format(int pid, int* rate, int* channel, int* audio_type);
+
 /*
 * For engine service
 */
@@ -175,6 +181,12 @@ int vcd_send_feedback_audio_format(int rate, vce_audio_channel_e channel, vce_au
 
 int vcd_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int len);
 
+int vcd_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data);
+
+int vcd_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data);
+
+int vcd_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data);
+
 
 #ifdef __cplusplus
 }
diff --git a/server/vcd_server_data.cpp b/server/vcd_server_data.cpp
new file mode 100644 (file)
index 0000000..2b636a9
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <list>
+#include <vector>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#include "vcd_main.h"
+#include "vcd_server_data.h"
+
+#define DATA_DEBUG
+
+using namespace std;
+
+std::list<vc_tts_text_data_s*> g_tts_text_data;
+
+static pthread_mutex_t g_tts_text_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+static int __data_show_text_list(void)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "----- Text list -----");
+
+       if (!g_tts_text_data.empty()) {
+               std::list<vc_tts_text_data_s*>::iterator iter;
+               for (iter = g_tts_text_data.begin(); (NULL != *iter && iter != g_tts_text_data.end()); ++iter) {
+                       SLOG(LOG_DEBUG, TAG_VCD, "[%p] uid(%d), pid(%d), utt_id(%d), text(%s), language(%s)",
+                               *iter, (*iter)->uid, (*iter)->pid, (*iter)->utt_id, (*iter)->text, (*iter)->language);
+               }
+       } else {
+               SLOG(LOG_DEBUG, TAG_VCD, "No Text Data");
+       }
+
+       SLOG(LOG_DEBUG, TAG_VCD, "---------------------");
+       return VCD_ERROR_NONE;
+}
+
+int vcd_data_add_tts_text_data(int uid, vc_tts_text_data_s* data)
+{
+       if (NULL == data) {
+               SLOG(LOG_ERROR, TAG_VCD, "[DATA ERROR] feedback data is NULL");
+               return VCD_ERROR_INVALID_PARAMETER;
+       }
+
+       /* mutex is locked */
+       pthread_mutex_lock(&g_tts_text_data_mutex);
+
+       std::list<vc_tts_text_data_s*>::iterator iter;
+
+       try {
+               iter = g_tts_text_data.insert(g_tts_text_data.end(), data);
+       } catch (const std::bad_alloc&) {
+               SLOG(LOG_ERROR, TAG_VCD, "[DATA][ERROR] Fail to insert tts_text_data (bad_alloc)");
+               pthread_mutex_unlock(&g_tts_text_data_mutex);
+
+               return VCD_ERROR_OUT_OF_MEMORY;
+       }
+       SLOG(LOG_ERROR, TAG_VCD, "[DATA][%p] uid(%d), pid(%d), utt_id(%d), text(%s), language(%s)",
+               *iter, (*iter)->uid, (*iter)->pid, (*iter)->utt_id, (*iter)->text, (*iter)->language);
+
+#ifdef DATA_DEBUG
+       __data_show_text_list();
+#endif
+       pthread_mutex_unlock(&g_tts_text_data_mutex);
+
+       return VCD_ERROR_NONE;
+}
+
+int vcd_data_clear_tts_text_data(vc_tts_text_data_s** tts_text_data)
+{
+       pthread_mutex_lock(&g_tts_text_data_mutex);
+
+       if (!g_tts_text_data.empty()) {
+               if (NULL != *tts_text_data) {
+                       SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] uid(%d), pid(%d), utt_id(%d), text(%s), language(%s)",
+                               (*tts_text_data)->uid, (*tts_text_data)->pid, (*tts_text_data)->utt_id, (*tts_text_data)->text, (*tts_text_data)->language);
+
+                       if (NULL != (*tts_text_data)->text) {
+                               free((*tts_text_data)->text);
+                               (*tts_text_data)->text = NULL;
+                       }
+                       if (NULL != (*tts_text_data)->language) {
+                               free((*tts_text_data)->language);
+                               (*tts_text_data)->language = NULL;
+                       }
+
+                       free(*tts_text_data);
+                       *tts_text_data = NULL;
+               }
+       }
+
+       pthread_mutex_unlock(&g_tts_text_data_mutex);
+
+       return VCD_ERROR_NONE;
+}
+
+int vcd_data_get_tts_text_data(int uid, vc_tts_text_data_s** data)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[DATA] Get tts text data : uid(%d)", uid);
+
+       /* mutex is locked */
+       pthread_mutex_lock(&g_tts_text_data_mutex);
+
+       if (0 == g_tts_text_data.size()) {
+               SLOG(LOG_ERROR, TAG_VCD, "[DATA ERROR] There is no tts_text data");
+               *data = NULL;
+               pthread_mutex_unlock(&g_tts_text_data_mutex);
+               return -1;
+       }
+
+       std::list<vc_tts_text_data_s*>::iterator iter;
+       for (iter = g_tts_text_data.begin(); (NULL != *iter && iter != g_tts_text_data.end()); ++iter) {
+               if (uid == (*iter)->uid) {
+                       *data = *iter;
+                       g_tts_text_data.erase(iter);
+               }
+       }
+
+#ifdef DATA_DEBUG
+       __data_show_text_list();
+#endif
+
+       pthread_mutex_unlock(&g_tts_text_data_mutex);
+
+       return VCD_ERROR_NONE;
+}
+
+int vcd_data_get_first_tts_text_data(vc_tts_text_data_s** data)
+{
+       SLOG(LOG_DEBUG, TAG_VCD, "[DATA] Get first tts text data");
+
+#ifdef DATA_DEBUG
+       __data_show_text_list();
+#endif
+
+       /* mutex is locked */
+       pthread_mutex_lock(&g_tts_text_data_mutex);
+
+       if (0 == g_tts_text_data.size()) {
+               SLOG(LOG_ERROR, TAG_VCD, "[DATA ERROR] There is no tts_text data");
+               *data = NULL;
+               pthread_mutex_unlock(&g_tts_text_data_mutex);
+               return -1;
+       }
+
+       std::list<vc_tts_text_data_s*>::iterator iter;
+
+       if (!g_tts_text_data.empty()) {
+               iter = g_tts_text_data.begin();
+               *data = *iter;
+               g_tts_text_data.pop_front();
+       }
+
+       pthread_mutex_unlock(&g_tts_text_data_mutex);
+
+       return VCD_ERROR_NONE;
+}
+
+int vcd_data_get_tts_text_data_size(void)
+{
+       /* mutex is locked */
+       pthread_mutex_lock(&g_tts_text_data_mutex);
+       int size = g_tts_text_data.size();
+
+       SLOG(LOG_DEBUG, TAG_VCD, "[DATA] get feedback data size(%d)", size);
+
+       /* mutex is unlocked */
+       pthread_mutex_unlock(&g_tts_text_data_mutex);
+
+       return size;
+}
diff --git a/server/vcd_server_data.h b/server/vcd_server_data.h
new file mode 100644 (file)
index 0000000..af2f055
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the License);
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an AS IS BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+
+#ifndef __VCD_SERVER_DATA_H__
+#define __VCD_SERVER_DATA_H__
+
+#include <tizen.h>
+#include <voice_control_common.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TAG_VCD     "vcd"       /* VC Daemon log tag */
+
+
+typedef struct {
+       int uid;
+       int pid;
+       int     utt_id;
+       char* text;
+       char* language;
+} vc_tts_text_data_s;
+
+
+int vcd_data_add_tts_text_data(int uid, vc_tts_text_data_s* data);
+
+int vcd_data_clear_tts_text_data(vc_tts_text_data_s** tts_text_data);
+
+int vcd_data_get_tts_text_data(int uid, vc_tts_text_data_s** data);
+
+int vcd_data_get_first_tts_text_data(vc_tts_text_data_s** data);
+
+int vcd_data_get_tts_text_data_size();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VCD_SERVER_DATA_H__ */
index 56ef2b2f48692384dd2c999e2733b9d1e7cf2f63..cfc93a8fe27ef652b2811a110c2ee92dda7a23a1 100644 (file)
@@ -532,7 +532,7 @@ int vce_unset_specific_engine_request_cb(void)
 
        int ret = vcd_set_specific_engine_request_cb(NULL);
        if (0 != ret) {
-               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set specific engine request cb");
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset specific engine request cb");
        }
 
        return ret;
@@ -585,3 +585,78 @@ int vce_send_feedback_streaming(vce_feedback_event_e event, char* buffer, int le
 
        return ret;
 }
+
+int vce_set_request_tts_cb(vce_request_tts_cb callback_func, void* user_data)
+{
+       if (NULL == callback_func) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Invalid parameter");
+               return VCE_ERROR_INVALID_PARAMETER;
+       }
+
+       int ret = vcd_set_request_tts_cb(callback_func, user_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set request tts cb");
+       }
+
+       return ret;
+}
+
+int vce_unset_request_tts_cb(void)
+{
+       int ret = vcd_set_request_tts_cb(NULL, NULL);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset request tts cb");
+       }
+
+       return ret;
+}
+
+int vce_set_cancel_tts_cb(vce_cancel_tts_cb callback_func, void* user_data)
+{
+       if (NULL == callback_func) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Invalid parameter");
+               return VCE_ERROR_INVALID_PARAMETER;
+       }
+
+       int ret = vcd_set_cancel_tts_cb(callback_func, user_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set cancel tts cb");
+       }
+
+       return ret;
+}
+
+int vce_unset_cancel_tts_cb(void)
+{
+       int ret = vcd_set_cancel_tts_cb(NULL, NULL);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset cancel tts cb");
+       }
+
+       return ret;
+}
+
+int vce_set_tts_audio_format_request_cb(vce_tts_audio_format_request_cb callback_func, void* user_data)
+{
+       if (NULL == callback_func) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Invalid parameter");
+               return VCE_ERROR_INVALID_PARAMETER;
+       }
+
+       int ret = vcd_set_tts_audio_format_request_cb(callback_func, user_data);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to set get tts audio format cb");
+       }
+
+       return ret;
+}
+
+int vce_unset_get_tts_audio_format_cb(void)
+{
+       int ret = vcd_set_tts_audio_format_request_cb(NULL, NULL);
+       if (0 != ret) {
+               SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to unset request tts cb");
+       }
+
+       return ret;
+}