--- /dev/null
+Sehwan Park <sehwan@samsung.com>
+WonNam Jang <wn.jang@samsung.com>
+Sooyeon Kim <sooyeon.kim@samsung.com>
+Suyeon Hwang <stom.hwang@samsung.com>
+Seongrae Jo <seongrae.jo@samsung.com>
--- /dev/null
+#
+# 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.
+#
+# @file CMakeLists.txt
+# @author Sooyeon Kim (sooyeon.kim@samsung.com)
+# @version 0.0.1
+# @brief
+
+# Check minimum CMake version
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+# Project name
+PROJECT(ma)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "${PREFIX}")
+SET(VERSION 0.0.1)
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+
+ADD_DEFINITIONS("-Werror")
+
+# pkg config tool
+INCLUDE(FindPkgConfig)
+
+## Include common directory ##
+INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/common")
+INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include")
+
+## Dependent packages ##
+INCLUDE(FindPkgConfig)
+IF("${_TV_PRODUCT}" STREQUAL "TRUE")
+pkg_check_modules(pkgs REQUIRED
+ capi-base-common capi-media-audio-io capi-media-sound-manager ecore-wayland
+ capi-network-bluetooth capi-network-bluetooth-tv capi-system-info cynara-client cynara-session dbus-1 dlog ecore glib-2.0 json-glib-1.0 libgum libtzplatform-config libxml-2.0 vconf
+)
+ELSE()
+pkg_check_modules(pkgs REQUIRED
+ capi-base-common capi-media-audio-io capi-media-sound-manager ecore-wayland
+ capi-system-info cynara-client cynara-session dbus-1 dlog ecore glib-2.0 json-glib-1.0 libgum libtzplatform-config libxml-2.0 vconf
+)
+ENDIF()
+
+
+## API ##
+ADD_SUBDIRECTORY(include)
+
+## Client library ##
+ADD_SUBDIRECTORY(client)
+
+## Server daemon ##
+#ADD_SUBDIRECTORY(server)
+
+## config ##
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/ma-config.xml DESTINATION ${TZ_SYS_RO_SHARE}/multiassistant/ma/1.0)
+
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/org.tizen.multiassistant.maclient.service DESTINATION ${TZ_SYS_RO_SHARE}/dbus-1/services)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/org.tizen.multiassistant.mauiclient.service DESTINATION ${TZ_SYS_RO_SHARE}/dbus-1/services)
+
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/ma-server.conf DESTINATION /etc/dbus-1/session.d)
+
--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
--- /dev/null
+Copyright (c) 2012-2015 Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
--- /dev/null
+SET(SRCS
+ ma.c
+ ma_client.c
+ ma_dbus.c
+ ../common/ma_config_mgr.c
+)
+
+SET(UI_SRCS
+ ma_ui.c
+ ma_ui_client.c
+ ma_ui_dbus.c
+ ../common/ma_config_mgr.c
+)
+
+FOREACH(flag ${pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+## multi assistant library ##
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
+
+## multi assistant ui library ##
+ADD_LIBRARY("${PROJECT_NAME}_ui" SHARED ${UI_SRCS})
+TARGET_LINK_LIBRARIES("${PROJECT_NAME}_ui" ${pkgs_LDFLAGS})
+
+## Install library files ##
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
+INSTALL(TARGETS "${PROJECT_NAME}_ui" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)
--- /dev/null
+/**
+ * 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.
+ */
+
+
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-session.h>
+#include <Ecore_Wayland.h>
+#include <system_info.h>
+
+
+#include "multi_assistant.h"
+#include "ma_dbus.h"
+#include "ma_client.h"
+#include "ma_main.h"
+#include "ma_defs.h"
+
+
+
+static ma_h g_ma = NULL;
+
+
+//static int g_feature_enabled = -1;
+static int g_privilege_allowed = -1;
+static cynara *p_cynara = NULL;
+
+static void __ma_notify_state_changed(void* data);
+static void __ma_notify_error(void* data);
+
+//static void __ma_lang_changed_cb(const char* previous_lang, const char* current_lang);
+
+static int __ma_get_feature_enabled()
+{
+ return 0;
+/*
+ if (0 == g_feature_enabled) {
+ //LCOV_EXCL_START
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Multi-assistant feature NOT supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ //LCOV_EXCL_STOP
+ } else if (-1 == g_feature_enabled) {
+ bool ma_supported = false;
+ bool mic_supported = false;
+ if (0 == system_info_get_platform_bool(MA_FEATURE_PATH, &ma_supported)) {
+ if (0 == system_info_get_platform_bool(MA_MIC_FEATURE_PATH, &mic_supported)) {
+ if (false == ma_supported || false == mic_supported) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Multi-assistant feature NOT supported");
+ g_feature_enabled = 0;
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ g_feature_enabled = 1;
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to get feature value"); //LCOV_EXCL_LINE
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to get feature value"); //LCOV_EXCL_LINE
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+ }
+*/
+ return 0;
+}
+
+static int __check_privilege_initialize()
+{
+ int ret = cynara_initialize(&p_cynara, NULL);
+ if (CYNARA_API_SUCCESS != ret)
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] fail to initialize"); //LCOV_EXCL_LINE
+
+ return ret == CYNARA_API_SUCCESS;
+}
+
+static int __check_privilege(const char* uid, const char * privilege)
+{
+ FILE *fp = NULL;
+ char label_path[1024] = "/proc/self/attr/current";
+ char smack_label[1024] = {'\0',};
+
+ if (!p_cynara) {
+ return false;
+ }
+
+ fp = fopen(label_path, "r");
+ if (fp != NULL) {
+ if (0 >= fread(smack_label, 1, sizeof(smack_label), fp))
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] fail to fread"); //LCOV_EXCL_LINE
+
+ fclose(fp);
+ }
+
+ pid_t pid = getpid();
+ char *session = cynara_session_from_pid(pid);
+ int ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client]cynara_check returned %d(%s)", ret, (CYNARA_API_ACCESS_ALLOWED == ret) ? "Allowed" : "Denied");
+ if (session)
+ free(session);
+
+ if (ret != CYNARA_API_ACCESS_ALLOWED)
+ return false;
+ return true;
+}
+
+static void __check_privilege_deinitialize()
+{
+ if (p_cynara)
+ cynara_finish(p_cynara);
+ p_cynara = NULL;
+}
+
+static int __ma_check_privilege()
+{
+ char uid[16];
+
+ if (0 == g_privilege_allowed) {
+ //LCOV_EXCL_START
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Permission is denied");
+ return MA_ERROR_PERMISSION_DENIED;
+ //LCOV_EXCL_STOP
+ } else if (-1 == g_privilege_allowed) {
+ if (false == __check_privilege_initialize()) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] privilege initialize is failed"); //LCOV_EXCL_LINE
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+ snprintf(uid, 16, "%d", getuid());
+ if (false == __check_privilege(uid, MA_PRIVILEGE)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Permission is denied");
+ g_privilege_allowed = 0;
+ __check_privilege_deinitialize();
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+ __check_privilege_deinitialize();
+ }
+
+ g_privilege_allowed = 1;
+ return MA_ERROR_NONE;
+}
+
+
+int ma_initialize(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Initialize");
+
+
+ /* check handle */
+ if (true == ma_client_is_valid(g_ma)) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Already initialized"); //LCOV_EXCL_LINE
+ return MA_ERROR_NONE; //LCOV_EXCL_LINE
+ }
+
+ if (0 < ma_client_get_count()) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Already initialized"); //LCOV_EXCL_LINE
+ return MA_ERROR_NONE; //LCOV_EXCL_LINE
+ }
+
+ if (0 != ma_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to open connection"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
+ }
+
+ if (0 != ma_client_create(&g_ma)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to create client!!!!!"); //LCOV_EXCL_LINE
+ return MA_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
+ }
+/*
+ int ret = ma_config_mgr_initialize(g_ma->handle);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to init config manager"); //LCOV_EXCL_LINE
+ ma_client_destroy(g_ma); //LCOV_EXCL_LINE
+ return ret; //LCOV_EXCL_LINE
+ }
+
+ ret = ma_config_mgr_set_lang_cb(g_ma->handle, __ma_lang_changed_cb);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to set config changed : %d", ret); //LCOV_EXCL_LINE
+ ma_config_mgr_deinitialize(g_ma->handle); //LCOV_EXCL_LINE
+ ma_client_destroy(g_ma); //LCOV_EXCL_LINE
+ return ret;
+ }
+*/
+ return MA_ERROR_NONE;
+}
+
+static void __ma_internal_unprepare(void)
+{
+ int ret = ma_dbus_request_deinitialize(g_ma->handle);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to request finalize"); //LCOV_EXCL_LINE
+ }
+
+ return;
+}
+
+int ma_deinitialize(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Deinitialize");
+
+ if (false == ma_client_is_valid(g_ma)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] NOT initialized");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_state_e state;
+ ma_client_get_client_state(g_ma, &state);
+
+ /* check state */
+ switch (state) {
+ case MA_STATE_READY:
+ __ma_internal_unprepare();
+ /* no break. need to next step*/
+ case MA_STATE_INITIALIZED:
+// ma_config_mgr_unset_lang_cb(g_ma->handle);
+// ma_config_mgr_deinitialize(g_ma->handle);
+
+ /* Free client resources */
+ ma_client_destroy(g_ma);
+ g_ma = NULL;
+ break;
+ case MA_STATE_NONE:
+ break;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "Success: destroy");
+
+ if (0 != ma_dbus_close_connection()) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to close connection"); //LCOV_EXCL_LINE
+ }
+
+ return MA_ERROR_NONE;
+}
+
+static Eina_Bool __ma_connect_daemon(void *data)
+{
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Connect daemon");
+
+ /* request initialization */
+ int ret = -1;
+ int ui_pid = -1;
+
+ /* check handle */
+ if (true == ma_client_is_valid(g_ma)) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] g_ma is valid");
+
+ ret = ma_dbus_request_initialize(g_ma->handle);
+ //LCOV_EXCL_START
+ if (MA_ERROR_ENGINE_NOT_FOUND == ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to initialize");
+
+ ma_client_set_error(g_ma, MA_ERROR_ENGINE_NOT_FOUND);
+ ecore_main_loop_thread_safe_call_async(__ma_notify_error, (void*)g_ma);
+
+ return EINA_FALSE;
+ //LCOV_EXCL_STOP
+ } else if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to initialize"); //LCOV_EXCL_LINE
+
+ ma_client_set_error(g_ma, MA_ERROR_TIMED_OUT);
+ ecore_main_loop_thread_safe_call_async(__ma_notify_error, (void*)g_ma);
+
+ return EINA_TRUE;
+ } else {
+ /* Success to connect */
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Success to connect daemon");
+ }
+
+ ma_client_set_client_state(g_ma, MA_STATE_READY);
+ ecore_main_loop_thread_safe_call_async(__ma_notify_state_changed, (void*)g_ma);
+
+ ma_client_set_ui_pid(g_ma, ui_pid);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "[Not ERROR] g_ma is not valid. It is destroyed."); //LCOV_EXCL_LINE
+ return EINA_FALSE;
+ }
+
+ return EINA_FALSE;
+}
+
+static void __start_prepare_thread(void *data, Ecore_Thread *thread)
+{
+ SLOG(LOG_ERROR, TAG_MAC, "[DEBUG] Start prepare thread");
+ int ret = -1;
+ int retry_count = 0;
+
+ /* Send hello */
+ while (0 != ret) {
+ if (retry_count == 10) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to request hello !!"); //LCOV_EXCL_LINE
+ return;
+ }
+
+ ret = ma_dbus_request_hello();
+ if (ret == 0) {
+ SLOG(LOG_DEBUG, TAG_MAC, "Success to request hello. retry count(%d)", retry_count);
+ break;
+ } else {
+ retry_count++;
+ }
+ }
+
+ ret = -1;
+ retry_count = 0;
+ while (0 != ret) {
+ if (retry_count == 10) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to connect daemon !!"); //LCOV_EXCL_LINE
+ return;
+ }
+ ret = __ma_connect_daemon(NULL);
+ if (ret == 0) {
+ SLOG(LOG_DEBUG, TAG_MAC, "Success to connect daemon. retry count(%d)", retry_count);
+ break;
+ } else {
+ retry_count++;
+ }
+ }
+
+ return;
+}
+
+static void __end_prepare_thread(void *data, Ecore_Thread *thread)
+{
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] End prepare thread");
+}
+
+int ma_prepare(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Prepare");
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ecore_thread_run(__start_prepare_thread, __end_prepare_thread, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_unprepare(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Unprepare");
+
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_READY) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'READY' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ __ma_internal_unprepare();
+
+ ma_client_set_client_state(g_ma, MA_STATE_INITIALIZED);
+ ecore_main_loop_thread_safe_call_async(__ma_notify_state_changed, (void*)g_ma);
+
+ return MA_ERROR_NONE;
+}
+
+static void __ma_notify_state_changed(void * data)
+{
+ ma_h ma = (ma_h)data;
+
+ ma_state_changed_cb callback = NULL;
+ void* user_data;
+
+ ma_client_get_state_changed_cb(ma, &callback, &user_data);
+
+ ma_state_e current_state;
+ ma_state_e previous_state;
+
+ ma_client_get_previous_state(ma, ¤t_state, &previous_state);
+
+ if (NULL != callback) {
+ ma_client_use_callback(ma);
+ callback(previous_state, current_state, user_data);
+ ma_client_not_use_callback(ma);
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] State changed callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[WARNING] State changed callback is NULL");
+ }
+}
+
+int __ma_cb_audio_streaming(int event, char* buffer, int len)
+{
+ ma_audio_streaming_cb callback = NULL;
+ void* user_data;
+
+ ma_client_get_audio_streaming_cb(g_ma, &callback, &user_data);
+
+ if (NULL != callback) {
+ ma_client_use_callback(g_ma);
+ callback((ma_audio_streaming_event_e)event, buffer, len, user_data);
+ ma_client_not_use_callback(g_ma);
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Audio streaming callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[WARNING] Audio streaming callback is NULL");
+ }
+
+ return 0;
+}
+
+int __ma_cb_error(int reason, char* msg)
+{
+ ma_state_e state;
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid client");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ /* check state */
+ if (state != MA_STATE_READY) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Current state is not 'READY'"); //LCOV_EXCL_LINE
+ if (MA_ERROR_SERVICE_RESET != reason) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] client is not connected yet");
+ return MA_ERROR_INVALID_STATE;
+ }
+ return MA_ERROR_NONE;
+ }
+
+ if (MA_ERROR_SERVICE_RESET == reason) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] multi-assistant service reset");
+
+ ma_client_set_client_state(g_ma, MA_STATE_INITIALIZED);
+ ecore_main_loop_thread_safe_call_async(__ma_notify_state_changed, (void*)g_ma);
+
+ if (0 != ma_prepare()) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to prepare");
+ }
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Error reason(%d), msg(%s)", reason, msg);
+
+ ma_client_set_error(g_ma, reason);
+ ecore_main_loop_thread_safe_call_async(__ma_notify_error, (void*)g_ma);
+
+ return MA_ERROR_NONE;
+}
+
+static void __ma_notify_error(void* data)
+{
+ ma_h ma = (ma_h)data;
+
+ ma_error_cb callback = NULL;
+ void* user_data;
+ int reason;
+
+ ma_client_get_error_cb(ma, &callback, &user_data);
+ ma_client_get_error(ma, &reason);
+
+ if (NULL != callback) {
+ ma_client_use_callback(ma);
+ callback(reason, user_data);
+ ma_client_not_use_callback(ma);
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Error callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[WARNING] Error callback is NULL");
+ }
+}
+
+/*
+static void __ma_lang_changed_cb(const char* previous_lang, const char* current_lang)
+{
+ ma_language_changed_cb callback = NULL;
+ void* user_data;
+
+ ma_client_get_lang_changed_cb(g_ma, &callback, user_data);
+
+ if (NULL != callback) {
+ ma_client_use_callback(g_ma);
+ callback(previous_lang, current_lang, user_data);
+ ma_client_not_use_callback(g_ma);
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Language changed callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[WARNING] Language changed callback is NULL");
+ }
+}
+*/
+
+int ma_get_state(ma_state_e* state)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Get current state");
+
+ if (NULL == state) {
+ SLOG(LOG_ERROR, TAG_MAC, "[Client ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+
+ ma_state_e tmp_state;
+ if (0 != ma_client_get_client_state(g_ma, &tmp_state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ *state = tmp_state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_get_current_language(char** language)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Get current language");
+
+
+ if (NULL == language) {
+ SLOG(LOG_ERROR, TAG_MAC, "[Client ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ int ret = -1;
+/* ret = ma_config_mgr_get_default_language(language);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[Client ERROR] Fail to get current language");
+ }
+*/
+ ret = 0;
+ return ret;
+}
+
+int ma_get_recording_audio_format(int *rate, ma_audio_channel_e *channel, ma_audio_type_e *audio_type)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ ma_state_e state;
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_READY) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'READY'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Get recording audio format");
+
+ int count = 0;
+ int ret = -1;
+ int pid = getpid();
+ do {
+ ret = ma_dbus_get_recording_audio_format(pid, rate, channel, audio_type);
+ if (0 != ret) {
+ if (MA_ERROR_TIMED_OUT != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to get audio format");
+ break;
+ } else {
+ SLOG(LOG_WARN, TAG_MAC, "[WARNING] Retry to get audio format");
+ usleep(10000);
+ count++;
+ if (MA_RETRY_COUNT == count) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to get audio format");
+ break;
+ }
+ }
+ }
+ } while (0 != ret);
+
+ return ret;
+}
+
+int ma_set_state_changed_cb(ma_state_changed_cb callback, void* user_data)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Set Multi-assistant client state changed cb");
+
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_state_changed_cb(g_ma, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_unset_state_changed_cb(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Unset Multi-assistant client state changed cb");
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_state_changed_cb(g_ma, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_set_error_cb(ma_error_cb callback, void* user_data)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Set Multi-assistant client error cb");
+
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_error_cb(g_ma, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_unset_error_cb(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Unset Multi-assistant client error cb");
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_error_cb(g_ma, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_set_language_changed_cb(ma_language_changed_cb callback, void* user_data)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Set Multi-assistant language changed cb");
+
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_lang_changed_cb(g_ma, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_unset_language_changed_cb(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Unset Multi-assistant language changed cb");
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_lang_changed_cb(g_ma, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_set_audio_streaming_cb(ma_audio_streaming_cb callback, void* user_data)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Set Multi-assistant audio streaming cb");
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized' (%d)", state); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_audio_streaming_cb(g_ma, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_unset_audio_streaming_cb(void)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Unset Multi-assistant audio streaming cb");
+
+ ma_state_e state;
+
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_client_set_audio_streaming_cb(g_ma, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_send_asr_result(ma_asr_result_event_e event, const char* asr_result)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ if (event < MA_ASR_RESULT_EVENT_FINAL_RESULT || event > MA_ASR_RESULT_EVENT_ERROR) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_READY) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'READY'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ if (NULL == asr_result) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Input parameter is NULL. (no result)");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Send ASR result to the Multi-assistant service");
+
+ int ret = -1;
+ int pid = getpid();
+ ret = ma_dbus_send_asr_result(pid, event, asr_result);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to send ASR result");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[ERROR] Success to send ASR result");
+ }
+
+ return ret;
+}
+
+int ma_send_result(const char* display_text, const char* utterance_text, const char* result_json)
+{
+ if (0 != __ma_get_feature_enabled()) {
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ ma_state_e state;
+ if (0 != ma_client_get_client_state(g_ma, &state)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_READY) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Invalid State: Current state is not 'READY'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Send result to the Multi-assistant");
+
+ if (NULL == display_text || NULL == utterance_text || NULL == result_json) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[Client DEBUG] Input parameter is NULL.");
+ }
+
+ int ret = -1;
+ int pid = getpid();
+ ret = ma_dbus_send_result(pid, display_text, utterance_text, result_json);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to send result");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[ERROR] Success to send result");
+ }
+
+ return ret;
+}
+
+
--- /dev/null
+/**
+ * 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.
+ */
+
+
+#include "ma_client.h"
+
+
+typedef struct {
+ /* base info */
+ ma_h ma;
+ int pid;
+ int uid; /*<< unique id = pid + handle */
+
+ ma_error_cb error_cb;
+ void* error_user_data;
+ ma_state_changed_cb state_changed_cb;
+ void* state_changed_user_data;
+ ma_language_changed_cb lang_changed_cb;
+ void* lang_changed_user_data;
+ ma_audio_streaming_cb audio_streaming_cb;
+ void* audio_streaming_user_data;
+
+ /* state */
+ ma_state_e previous_state;
+ ma_state_e current_state;
+
+ /* mutex */
+ int cb_ref_count;
+
+ /* error data */
+ int reason;
+
+ int ui_pid;
+} ma_client_s;
+
+/* client list */
+static GSList* g_client_list = NULL;
+
+
+
+static ma_client_s* __client_get(ma_h ma)
+{
+ if (NULL == ma) {
+ SLOG(LOG_ERROR, TAG_MAC, "[DEBUG] Handle is NULL");
+ return NULL;
+ }
+
+ ma_client_s* data = NULL;
+ int count = g_slist_length(g_client_list);
+ int i;
+
+ for (i = 0 ; i < count ; i++) {
+ data = g_slist_nth_data(g_client_list, i);
+
+ if (NULL != data) {
+ if (ma->handle == data->ma->handle) {
+ return data;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+int ma_client_create(ma_h* ma)
+{
+ ma_client_s* client = NULL;
+
+ client = (ma_client_s*)calloc(1, sizeof(ma_client_s));
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to allocate memory"); //LCOV_EXCL_LINE
+ return MA_ERROR_OUT_OF_MEMORY;
+ }
+
+ ma_h temp = (ma_h)calloc(1, sizeof(struct ma_s));
+ if (NULL == temp) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to allocate memory"); //LCOV_EXCL_LINE
+ free(client);
+ return MA_ERROR_OUT_OF_MEMORY;
+ }
+
+ temp->handle = getpid();
+
+ /* initialize client data */
+ client->ma = temp;
+ client->pid = getpid();
+ client->uid = temp->handle;
+
+ client->error_cb = NULL;
+ client->error_user_data = NULL;
+ client->state_changed_cb = NULL;
+ client->state_changed_user_data = NULL;
+ client->lang_changed_cb = NULL;
+ client->lang_changed_user_data = NULL;
+ client->audio_streaming_cb = NULL;
+ client->audio_streaming_user_data = NULL;
+
+ client->previous_state = MA_STATE_INITIALIZED;
+ client->current_state = MA_STATE_INITIALIZED;
+
+ client->cb_ref_count = 0;
+
+
+ g_client_list = g_slist_append(g_client_list, client);
+
+ *ma = temp;
+
+ return 0;
+}
+
+int ma_client_destroy(ma_h ma)
+{
+ if (ma == NULL) {
+ SLOG(LOG_ERROR, TAG_MAC, "Input parameter is NULL"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ ma_client_s *data = NULL;
+
+ int count = g_slist_length(g_client_list);
+ int i;
+
+ for (i = 0; i < count; i++) {
+ data = g_slist_nth_data(g_client_list, i);
+
+ if (NULL != data) {
+ if (ma->handle == data->ma->handle) {
+ g_client_list = g_slist_remove(g_client_list, data);
+
+ while (0 != data->cb_ref_count) {
+ /* wait for release callback function */
+ }
+ free(data);
+ free(ma);
+ data = NULL;
+ ma = NULL;
+ return 0;
+ }
+ }
+ }
+
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] client Not found");
+
+ return -1;
+}
+
+bool ma_client_is_valid(ma_h ma)
+{
+ ma_client_s* client = __client_get(ma);
+
+ /* check handle */
+ if (NULL == client) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] multi-assistant client is not valid");
+ return false;
+ }
+
+ return true;
+}
+
+int ma_client_get_count(void)
+{
+ return g_slist_length(g_client_list);
+}
+
+int ma_client_use_callback(ma_h ma)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->cb_ref_count++;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_not_use_callback(ma_h ma)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->cb_ref_count--;
+
+ return MA_ERROR_NONE;
+}
+
+
+int ma_client_set_client_state(ma_h ma, ma_state_e state)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->previous_state = client->current_state;
+ client->current_state = state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_client_state(ma_h ma, ma_state_e* state)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *state = client->current_state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_previous_state(ma_h ma, ma_state_e* current_state, ma_state_e* previous_state)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *current_state = client->current_state;
+ *previous_state = client->previous_state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_set_error(ma_h ma, ma_error_e reason)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->reason = reason;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_error(ma_h ma, ma_error_e* reason)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *reason = (ma_error_e)client->reason;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_set_ui_pid(ma_h ma, int pid)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->ui_pid = pid;
+
+ return MA_ERROR_NONE;
+}
+
+
+int ma_client_set_state_changed_cb(ma_h ma, ma_state_changed_cb callback, void* user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->state_changed_cb = callback;
+ client->state_changed_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_state_changed_cb(ma_h ma, ma_state_changed_cb* callback, void** user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->state_changed_cb;
+ *user_data = client->state_changed_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_set_lang_changed_cb(ma_h ma, ma_language_changed_cb callback, void* user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->lang_changed_cb = callback;
+ client->lang_changed_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_lang_changed_cb(ma_h ma, ma_language_changed_cb* callback, void** user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->lang_changed_cb;
+ *user_data = client->lang_changed_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_set_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb callback, void* user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->audio_streaming_cb = callback;
+ client->audio_streaming_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb* callback, void** user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->audio_streaming_cb;
+ *user_data = client->audio_streaming_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_set_error_cb(ma_h ma, ma_error_cb callback, void* user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->error_cb = callback;
+ client->error_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_client_get_error_cb(ma_h ma, ma_error_cb* callback, void** user_data)
+{
+ ma_client_s* client = __client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->error_cb;
+ *user_data = client->error_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+
--- /dev/null
+/**
+ * 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 __MA_CLIENT_H__
+#define __MA_CLIENT_H__
+
+#include "ma_main.h"
+#include "multi_assistant_common.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int ma_client_create(ma_h* ma);
+
+int ma_client_destroy(ma_h ma);
+
+bool ma_client_is_valid(ma_h ma);
+
+int ma_client_get_count(void);
+
+int ma_client_use_callback(ma_h ma);
+
+int ma_client_not_use_callback(ma_h ma);
+
+
+int ma_client_set_client_state(ma_h ma, ma_state_e state);
+
+int ma_client_get_client_state(ma_h ma, ma_state_e* state);
+
+int ma_client_get_previous_state(ma_h ma, ma_state_e* current_state, ma_state_e* previous_state);
+
+int ma_client_set_error(ma_h ma, ma_error_e reason);
+
+int ma_client_get_error(ma_h ma, ma_error_e* reason);
+
+int ma_client_set_ui_pid(ma_h ma, int pid);
+
+
+int ma_client_set_state_changed_cb(ma_h ma, ma_state_changed_cb callback, void* user_data);
+
+int ma_client_get_state_changed_cb(ma_h ma, ma_state_changed_cb* callback, void** user_data);
+
+int ma_client_set_lang_changed_cb(ma_h ma, ma_language_changed_cb callback, void* user_data);
+
+int ma_client_get_lang_changed_cb(ma_h ma, ma_language_changed_cb* callback, void** user_data);
+
+int ma_client_set_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb callback, void* user_data);
+
+int ma_client_get_audio_streaming_cb(ma_h ma, ma_audio_streaming_cb* callback, void** user_data);
+
+int ma_client_set_error_cb(ma_h ma, ma_error_cb callback, void* user_data);
+
+int ma_client_get_error_cb(ma_h ma, ma_error_cb* callback, void** user_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_CLIENT_H__ */
+
+
--- /dev/null
+/**
+ * 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.
+ */
+
+
+#include "ma_dbus.h"
+#include "ma_defs.h"
+#include "ma_main.h"
+#include "ma_client.h"
+
+
+static int g_waiting_time = 3000;
+
+static Ecore_Fd_Handler* g_fd_handler = NULL;
+
+static DBusConnection* g_conn_sender = NULL;
+static DBusConnection* g_conn_listener = NULL;
+
+extern int __ma_cb_error(int reason, char* msg);
+extern int __ma_cb_audio_streaming(int event, char* buffer, int len);
+
+static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler* fd_handler)
+{
+ if (NULL == g_conn_listener)
+ return ECORE_CALLBACK_RENEW;
+
+ dbus_connection_read_write_dispatch(g_conn_listener, 50);
+
+ while (1) {
+ DBusMessage* msg = NULL;
+ msg = dbus_connection_pop_message(g_conn_listener);
+
+ /* loop again if we haven't read a message */
+ if (NULL == msg) {
+ break;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ char if_name[64] = {0, };
+ snprintf(if_name, 64, "%s", MA_CLIENT_SERVICE_INTERFACE);
+
+ if (dbus_message_is_method_call(msg, if_name, MAS_METHOD_HELLO)) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Get Hello");
+ int pid = 0;
+ int response = -1;
+
+ dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (pid > 0) {
+ SLOG(LOG_DEBUG, TAG_MAC, "@@ ma client get hello : pid(%d) ", pid);
+ response = 1;
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ ma client get hello : invalid pid ");
+ }
+
+ DBusMessage* reply = NULL;
+ reply = dbus_message_new_method_return(msg);
+
+ if (NULL != reply) {
+ dbus_message_append_args(reply, DBUS_TYPE_INT32, &response, DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send(g_conn_listener, reply, NULL))
+ SLOG(LOG_ERROR, TAG_MAC, "@@ multi-assistant get hello : fail to send reply");
+ else
+ SLOG(LOG_DEBUG, TAG_MAC, "@@ multi-assistant get hello : result(%d)", response);
+
+ dbus_connection_flush(g_conn_listener);
+ dbus_message_unref(reply);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ multi-assistant get hello : fail to create reply message");
+ }
+
+ } /* MAS_METHOD_HELLO */
+
+ else if (dbus_message_is_method_call(msg, if_name, MAS_METHOD_SEND_SPEECH_DATA)) {
+ SLOG(LOG_INFO, TAG_MAC, "@@@ Send speech data");
+ int event;
+ char* buffer = NULL;
+ int len;
+
+ dbus_message_get_args(msg, &err,
+ DBUS_TYPE_INT32, &event,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+ &buffer, &len,
+ DBUS_TYPE_INVALID);
+
+ __ma_cb_audio_streaming(event, buffer, len);
+
+ SLOG(LOG_INFO, TAG_MAC, "@@@");
+ } /* MAS_METHOD_SEND_SPEECH_DATA */
+
+
+ else if (dbus_message_is_signal(msg, if_name, MAS_METHOD_ERROR)) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Get Error");
+ int reason;
+ char* err_msg;
+
+ dbus_message_get_args(msg, &err,
+ DBUS_TYPE_INT32, &reason,
+ DBUS_TYPE_STRING, &err_msg,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ multi-assistant Get Error message : Get arguments error (%s)", err.message);
+ dbus_error_free(&err);
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "@@ multi-assistant Get Error message : reason(%d), msg(%s)", reason, err_msg);
+ __ma_cb_error(reason, err_msg);
+ }
+
+ } /* MAS_METHOD_ERROR */
+
+ else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameOwnerChanged")) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] Owner Changed");
+ DBusError err;
+ dbus_error_init(&err);
+ /* remove a rule for daemon error */
+ char rule_err[256] = {0, };
+ snprintf(rule_err, 256, "sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',type='signal',arg0='%s'", MA_SERVER_SERVICE_INTERFACE);
+ dbus_bus_remove_match(g_conn_listener, rule_err, &err);
+ dbus_connection_flush(g_conn_listener);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Match Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ __ma_cb_error(MA_ERROR_SERVICE_RESET, "Daemon Reset");
+ } /* NameOwnerChanged */
+
+ else {
+ SLOG(LOG_DEBUG, TAG_MAC, "Message is NOT valid");
+ dbus_message_unref(msg);
+ break;
+ }
+
+ /* free the message */
+ dbus_message_unref(msg);
+ }
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void __ma_dbus_connection_free()
+{
+ if (NULL != g_conn_listener) {
+ dbus_connection_close(g_conn_listener);
+ dbus_connection_unref(g_conn_listener);
+ g_conn_listener = NULL;
+ }
+ if (NULL != g_conn_sender) {
+ dbus_connection_close(g_conn_sender);
+ dbus_connection_unref(g_conn_sender);
+ g_conn_sender = NULL;
+ }
+}
+
+int ma_dbus_open_connection()
+{
+ if (NULL != g_conn_sender && NULL != g_conn_listener) {
+ SLOG(LOG_WARN, TAG_MAC, "already existed connection "); //LCOV_EXCL_LINE
+ return 0;
+ }
+
+ DBusError err;
+ int ret;
+
+ /* initialize the error value */
+ dbus_error_init(&err);
+
+ /* connect to the DBUS system bus, and check for errors */
+ g_conn_sender = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Dbus Connection Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+
+ if (NULL == g_conn_sender) {
+ SLOG(LOG_ERROR, TAG_MAC, "Fail to get dbus connection "); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_connection_set_exit_on_disconnect(g_conn_sender, false);
+
+ g_conn_listener = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Dbus Connection Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+
+ if (NULL == g_conn_listener) {
+ SLOG(LOG_ERROR, TAG_MAC, "Fail to get dbus connection "); //LCOV_EXCL_LINE
+ __ma_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_connection_set_exit_on_disconnect(g_conn_listener, false);
+
+// int pid = getpid();
+
+ char service_name[64];
+ memset(service_name, '\0', 64);
+// snprintf(service_name, 64, "%s%d", MA_CLIENT_SERVICE_NAME, pid);
+ snprintf(service_name, 64, "%s", MA_CLIENT_SERVICE_NAME);
+
+ SLOG(LOG_DEBUG, TAG_MAC, "service name is %s", service_name);
+
+ /* register our name on the bus, and check for errors */
+ ret = dbus_bus_request_name(g_conn_listener, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Name Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+
+ if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
+ SLOG(LOG_ERROR, TAG_MAC, "fail dbus_bus_request_name()"); //LCOV_EXCL_LINE
+ __ma_dbus_connection_free();
+ return -2;
+ }
+
+ if (NULL != g_fd_handler) {
+ SLOG(LOG_WARN, TAG_MAC, "The handler already exists."); //LCOV_EXCL_LINE
+ __ma_dbus_connection_free();
+ return 0;
+ }
+
+ /* Flush messages which are received before fd event handler registration */
+ while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_get_dispatch_status(g_conn_listener)) {
+ listener_event_callback(NULL, NULL);
+ }
+
+ char rule[256] = {0, };
+ snprintf(rule, 256, "type='signal',interface='%s'", MA_CLIENT_SERVICE_INTERFACE);
+
+ /* add a rule for which messages we want to see */
+ dbus_bus_add_match(g_conn_listener, rule, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Match Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ __ma_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ int fd = 0;
+ if (1 != dbus_connection_get_unix_fd(g_conn_listener, &fd)) {
+ SLOG(LOG_ERROR, TAG_MAC, "fail to get fd from dbus "); //LCOV_EXCL_LINE
+ __ma_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "Get fd from dbus : %d", fd);
+ }
+
+ g_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)listener_event_callback, g_conn_listener, NULL, NULL);
+ if (NULL == g_fd_handler) {
+ SLOG(LOG_ERROR, TAG_MAC, "fail to get fd handler from ecore "); //LCOV_EXCL_LINE
+ __ma_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ return 0;}
+
+int ma_dbus_close_connection()
+{
+ DBusError err;
+ dbus_error_init(&err);
+
+ if (NULL != g_fd_handler) {
+ ecore_main_fd_handler_del(g_fd_handler);
+ g_fd_handler = NULL;
+ }
+
+ if (NULL != g_conn_listener) {
+// int pid = getpid();
+
+ char service_name[64];
+ memset(service_name, '\0', 64);
+// snprintf(service_name, 64, "%s%d", MA_CLIENT_SERVICE_NAME, pid);
+ snprintf(service_name, 64, "%s", MA_CLIENT_SERVICE_NAME);
+
+ dbus_bus_release_name(g_conn_listener, service_name, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Dbus Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+ }
+
+ __ma_dbus_connection_free();
+
+ return 0;
+}
+
+int ma_dbus_reconnect()
+{
+ if (!g_conn_sender || !g_conn_listener) {
+ ma_dbus_close_connection();
+
+ if (0 != ma_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to reconnect"); //LCOV_EXCL_LINE
+ return -1;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[DBUS] Reconnect"); //LCOV_EXCL_LINE
+ return 0;
+ }
+
+ bool sender_connected = dbus_connection_get_is_connected(g_conn_sender);
+ bool listener_connected = dbus_connection_get_is_connected(g_conn_listener);
+ SLOG(LOG_WARN, TAG_MAC, "[DBUS] Sender(%s) Listener(%s)",
+ sender_connected ? "Connected" : "Not connected", listener_connected ? "Connected" : "Not connected"); //LCOV_EXCL_LINE
+
+ if (false == sender_connected || false == listener_connected) {
+ ma_dbus_close_connection();
+
+ if (0 != ma_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Fail to reconnect"); //LCOV_EXCL_LINE
+ return -1;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "[DBUS] Reconnect"); //LCOV_EXCL_LINE
+ }
+
+ return 0;}
+
+static int __dbus_check()
+{
+ if (NULL == g_conn_sender) {
+ SLOG(LOG_ERROR, TAG_MAC, "[ERROR] Null connection"); //LCOV_EXCL_LINE
+ return ma_dbus_reconnect();
+ }
+
+ return MA_ERROR_NONE;
+}
+
+int ma_dbus_request_hello()
+{
+ if (0 != __dbus_check()) {
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_HELLO);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Request multi-assistant hello : Fail to make message"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage* result_msg = NULL;
+ int result = 0;
+
+ result_msg = dbus_connection_send_with_reply_and_block(g_conn_sender, msg, -1, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_DEBUG, TAG_MAC, "[ERROR] Dbus Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+
+ dbus_message_unref(msg);
+
+ if (NULL != result_msg) {
+ dbus_message_unref(result_msg);
+ result = 0;
+ } else {
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;}
+
+int ma_dbus_request_initialize(int pid)
+{
+ if (0 != __dbus_check()) {
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_INITIALIZE);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Request multi-assistant initialize : Fail to make message"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] multi-assistant initialize : pid(%d)", pid);
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INVALID);
+
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage* result_msg = NULL;
+ int result = MA_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_DEBUG, TAG_MAC, "[ERROR] Dbus Error (%s)", err.message); //LCOV_EXCL_LINE
+ 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_MAC, "@@ Get arguments error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ result = MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_message_unref(result_msg);
+
+ if (0 == result) {
+ /* add a rule for daemon error */
+ char rule[256] = {0, };
+ snprintf(rule, 256, "sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',type='signal',arg0='%s'", MA_SERVER_SERVICE_INTERFACE);
+ dbus_bus_add_match(g_conn_listener, rule, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Match Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAC, "@@ multi-assistant initialize : result = %d", result); //LCOV_EXCL_LINE
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ multi-assistant initialize : result = %d", result); //LCOV_EXCL_LINE
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Result message is NULL "); //LCOV_EXCL_LINE
+ ma_dbus_reconnect();
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
+
+int ma_dbus_request_deinitialize(int pid)
+{
+ if (0 != __dbus_check()) {
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ /* remove a rule for daemon error */
+ char rule[256] = {0, };
+ snprintf(rule, 256, "sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',type='signal',arg0='%s'", MA_SERVER_SERVICE_INTERFACE);
+ dbus_bus_remove_match(g_conn_listener, rule, &err);
+ dbus_connection_flush(g_conn_listener);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAC, "Match Error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_DEINITIALIZE);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Request multi-assistant deinitialize : Fail to make message"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] multi-assistant deinitialize : pid(%d)", pid);
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage* result_msg = NULL;
+ int result = MA_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_DEBUG, TAG_MAC, "[ERROR] Dbus Error (%s)", err.message); //LCOV_EXCL_LINE
+ 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_MAC, "@@ Get arguments error (%s)", err.message); //LCOV_EXCL_LINE
+ dbus_error_free(&err);
+ result = MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_message_unref(result_msg);
+
+ if (0 == result) {
+ SLOG(LOG_DEBUG, TAG_MAC, "@@ multi-assistant finalize : result = %d", result);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ multi-assistant finalize : result = %d", result);
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Result message is NULL "); //LCOV_EXCL_LINE
+ ma_dbus_reconnect();
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
+
+
+int ma_dbus_get_recording_audio_format(int pid, int *rate, ma_audio_channel_e *channel, ma_audio_type_e *audio_type)
+{
+ if (0 != __dbus_check()) {
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_GET_RECORDING_AUDIO_FORMAT);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Request multi-assistant recording audio format : Fail to make message"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] multi-assistant recording audio format");
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INVALID);
+
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage* result_msg = NULL;
+ int result = MA_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_DEBUG, TAG_MAC, "[ERROR] Dbus Error (%s)", err.message); //LCOV_EXCL_LINE
+ 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_MAC, "@@ Get arguments error (%s)", err.message);
+ dbus_error_free(&err);
+ result = MA_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_MAC, "@@ multi-assistant get recording audio format : result = %d, rate = %d, channel = %d, audio_type = %d", result, *rate, *channel, *audio_type);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ multi-assistant get recordingaudio format : result = %d", result);
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Result message is NULL");
+ ma_dbus_reconnect();
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
+
+int ma_dbus_send_asr_result(int pid, ma_asr_result_event_e event, const char* asr_result)
+{
+ if (0 != __dbus_check()) {
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_SEND_ASR_RESULT);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Request multi-assistant send ASR result : Fail to make message"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] multi-assistant send ASR result");
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INT32, &event,
+ DBUS_TYPE_STRING, &asr_result,
+ DBUS_TYPE_INVALID);
+
+ dbus_message_set_no_reply(msg, TRUE);
+
+ if (1 != dbus_connection_send(g_conn_sender, msg, NULL)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[Dbus ERROR] Fail to Send"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[Dbus DEBUG] Success to Send");
+ dbus_connection_flush(g_conn_sender);
+ }
+
+ dbus_message_unref(msg);
+
+ return 0;
+}
+
+int ma_dbus_send_result(int pid, const char* display_text, const char* utterance_text, const char* result_json)
+{
+ if (0 != __dbus_check()) {
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_SEND_RESULT);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAC, "@@ Request multi-assistant send result : Fail to make message"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[DEBUG] multi-assistant send result");
+ }
+
+ char* tmp_disp_text = NULL;
+ char* tmp_utt_text = NULL;
+ char* tmp_result_json = NULL;
+
+ if (NULL != display_text) {
+ tmp_disp_text = strdup(display_text);
+ } else {
+ tmp_disp_text = strdup("#NULL");
+ }
+
+ if (NULL != utterance_text) {
+ tmp_utt_text = strdup(utterance_text);
+ } else {
+ tmp_utt_text = strdup("#NULL");
+ }
+
+ if (NULL != result_json) {
+ tmp_result_json = strdup(result_json);
+ } else {
+ tmp_result_json = strdup("#NULL");
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_STRING, &tmp_disp_text,
+ DBUS_TYPE_STRING, &tmp_utt_text,
+ DBUS_TYPE_STRING, &tmp_result_json,
+ DBUS_TYPE_INVALID);
+
+ dbus_message_set_no_reply(msg, TRUE);
+
+ if (1 != dbus_connection_send(g_conn_sender, msg, NULL)) {
+ SLOG(LOG_ERROR, TAG_MAC, "[Dbus ERROR] Fail to Send"); //LCOV_EXCL_LINE
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAC, "[Dbus DEBUG] Success to Send");
+ dbus_connection_flush(g_conn_sender);
+ }
+
+ dbus_message_unref(msg);
+
+ if (NULL != tmp_disp_text) {
+ free(tmp_disp_text);
+ tmp_disp_text = NULL;
+ }
+ if (NULL != tmp_utt_text) {
+ free(tmp_utt_text);
+ tmp_utt_text = NULL;
+ }
+ if (NULL != tmp_result_json) {
+ free(tmp_result_json);
+ tmp_result_json = NULL;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/**
+ * 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 __MA_DBUS_H__
+#define __MA_DBUS_H__
+
+
+#include "multi_assistant_common.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int ma_dbus_open_connection();
+
+int ma_dbus_close_connection();
+
+
+int ma_dbus_request_hello();
+
+int ma_dbus_request_initialize(int pid);
+
+int ma_dbus_request_deinitialize(int pid);
+
+
+int ma_dbus_get_recording_audio_format(int pid, int *rate, ma_audio_channel_e *channel, ma_audio_type_e *audio_type);
+
+int ma_dbus_send_asr_result(int pid, ma_asr_result_event_e event, const char* asr_result);
+
+int ma_dbus_send_result(int pid, const char* display_text, const char* utterance_text, const char* result_json);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_DBUS_H__ */
+
--- /dev/null
+/**
+ * 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.
+ */
+
+
+
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-session.h>
+#include <Ecore_Wayland.h>
+#include <system_info.h>
+
+
+#include "multi_assistant_ui.h"
+#include "ma_ui_dbus.h"
+#include "ma_ui_client.h"
+#include "ma_main.h"
+#include "ma_defs.h"
+
+
+
+#define MA_UI_CONFIG_HANDLE 100000
+
+static ma_h g_ma_ui = NULL;
+
+//static int g_feature_enabled = -1;
+static int g_privilege_allowed = -1;
+static cynara *p_cynara = NULL;
+
+static Eina_Bool __ma_ui_notify_state_changed(void* data);
+static void __ma_ui_notify_error(void* data);
+
+//static void __ma_ui_lang_changed_cb(const char* previous_lang, const char* current_lang);
+
+static int __ma_ui_get_feature_enabled()
+{
+ return 0;
+/*
+ if (0 == g_feature_enabled) {
+ //LCOV_EXCL_START
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Multi-assistant feature NOT supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ //LCOV_EXCL_STOP
+ } else if (-1 == g_feature_enabled) {
+ bool ma_supported = false;
+ bool mic_supported = false;
+ if (0 == system_info_get_platform_bool(MA_FEATURE_PATH, &ma_supported)) {
+ if (0 == system_info_get_platform_bool(MA_MIC_FEATURE_PATH, &mic_supported)) {
+ if (false == ma_supported || false == mic_supported) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Multi-assistant feature NOT supported");
+ g_feature_enabled = 0;
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ g_feature_enabled = 1;
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to get feature value"); //LCOV_EXCL_LINE
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to get feature value"); //LCOV_EXCL_LINE
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+ }
+*/
+ return 0;
+}
+
+static int __check_privilege_initialize()
+{
+ int ret = cynara_initialize(&p_cynara, NULL);
+ if (CYNARA_API_SUCCESS != ret)
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] fail to initialize"); //LCOV_EXCL_LINE
+
+ return ret == CYNARA_API_SUCCESS;
+}
+
+static int __check_privilege(const char* uid, const char * privilege)
+{
+ FILE *fp = NULL;
+ char label_path[1024] = "/proc/self/attr/current";
+ char smack_label[1024] = {'\0',};
+
+ if (!p_cynara) {
+ return false;
+ }
+
+ fp = fopen(label_path, "r");
+ if (fp != NULL) {
+ if (0 >= fread(smack_label, 1, sizeof(smack_label), fp))
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] fail to fread"); //LCOV_EXCL_LINE
+
+ fclose(fp);
+ }
+
+ pid_t pid = getpid();
+ char *session = cynara_session_from_pid(pid);
+ int ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
+ SLOG(LOG_DEBUG, TAG_MAUI, "[Client]cynara_check returned %d(%s)", ret, (CYNARA_API_ACCESS_ALLOWED == ret) ? "Allowed" : "Denied");
+ if (session)
+ free(session);
+
+ if (ret != CYNARA_API_ACCESS_ALLOWED)
+ return false;
+ return true;
+}
+
+static void __check_privilege_deinitialize()
+{
+ if (p_cynara)
+ cynara_finish(p_cynara);
+ p_cynara = NULL;
+}
+
+static int __ma_ui_check_privilege()
+{
+ char uid[16];
+
+ if (0 == g_privilege_allowed) {
+ //LCOV_EXCL_START
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Permission is denied");
+ return MA_ERROR_PERMISSION_DENIED;
+ //LCOV_EXCL_STOP
+ } else if (-1 == g_privilege_allowed) {
+ if (false == __check_privilege_initialize()) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] privilege initialize is failed"); //LCOV_EXCL_LINE
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+ snprintf(uid, 16, "%d", getuid());
+ if (false == __check_privilege(uid, MA_PRIVILEGE)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Permission is denied");
+ g_privilege_allowed = 0;
+ __check_privilege_deinitialize();
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+ __check_privilege_deinitialize();
+ }
+
+ g_privilege_allowed = 1;
+ return MA_ERROR_NONE;
+}
+
+
+
+int ma_ui_initialize(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI] Initialize");
+
+
+ /* check handle */
+ if (true == ma_ui_client_is_valid(g_ma_ui)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Already initialized");
+ return MA_ERROR_NONE;
+ }
+
+ if (0 != ma_ui_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to open connection");
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ if (0 != ma_ui_client_create(&g_ma_ui)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to create client!!!!!");
+ return MA_ERROR_OUT_OF_MEMORY;
+ }
+/*
+ int ret = ma_config_mgr_initialize(g_ma_ui->handle + MA_UI_CONFIG_HANDLE);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to init config manager : %d", ret);
+ ma_ui_client_destroy(g_ma_ui);
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ ret = ma_config_mgr_set_lang_cb(g_ma_ui->handle + MA_UI_CONFIG_HANDLE, __ma_ui_lang_changed_cb);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to set callback : %d", ret);
+ ma_config_mgr_deinitialize(g_ma_ui->handle + MA_UI_CONFIG_HANDLE);
+ ma_ui_client_destroy(g_ma_ui);
+ return MA_ERROR_OPERATION_FAILED;
+ }
+*/
+ SLOG(LOG_ERROR, TAG_MAUI, "[Success] pid(%d)", g_ma_ui->handle);
+
+ return MA_ERROR_NONE;
+}
+
+static void __ma_ui_internal_unprepare(void)
+{
+ int ret = ma_ui_dbus_request_deinitialize(g_ma_ui->handle);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to request deinitialize");
+ }
+
+ return ;
+}
+
+int ma_ui_deinitialze(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_ERROR, TAG_MAUI, "@@@ [UI] Deinitialize");
+
+ if (false == ma_ui_client_is_valid(g_ma_ui)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] NOT initialized");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_state_e state;
+ ma_ui_client_get_client_state(g_ma_ui, &state);
+
+ /* check state */
+ switch (state) {
+ case MA_STATE_READY:
+ __ma_ui_internal_unprepare();
+ /* no break. need to next step*/
+ case MA_STATE_INITIALIZED:
+// ma_config_mgr_unset_lang_cb(g_ma_ui->handle + MA_UI_CONFIG_HANDLE);
+// ma_config_mgr_deinitialize(g_ma_ui->handle + MA_UI_CONFIG_HANDLE);
+
+ /* Free client resources */
+ ma_ui_client_destroy(g_ma_ui);
+ g_ma_ui = NULL;
+ break;
+ case MA_STATE_NONE:
+ break;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "Success: destroy");
+
+ if (0 != ma_ui_dbus_close_connection()) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to close connection");
+ }
+
+ SLOG(LOG_ERROR, TAG_MAUI, "@@@");
+
+ return MA_ERROR_NONE;
+}
+
+static Eina_Bool __ma_ui_connect_daemon(void *data)
+{
+ /* request initialization */
+ int ret = -1;
+
+ ret = ma_ui_dbus_request_initialize(g_ma_ui->handle);
+
+ if (MA_ERROR_ENGINE_NOT_FOUND == ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to initialize");
+
+ ma_ui_client_set_error(g_ma_ui, MA_ERROR_ENGINE_NOT_FOUND);
+ ecore_main_loop_thread_safe_call_async(__ma_ui_notify_error, (void*)g_ma_ui);
+
+ return EINA_FALSE;
+
+ } else if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[WARNING] Fail to connection. Retry to connect");
+ return EINA_TRUE;
+ } else {
+ /* Success to connect */
+ }
+
+
+ SLOG(LOG_ERROR, TAG_MAUI, "[SUCCESS] Connected daemon");
+
+ /* Set client state */
+ ma_ui_client_set_client_state(g_ma_ui, MA_STATE_READY);
+ void* user_data;
+
+ ma_state_changed_cb changed_callback = NULL;
+ ma_ui_client_get_state_changed_cb(g_ma_ui, &changed_callback, &user_data);
+
+ ma_state_e current_state;
+ ma_state_e previous_state;
+
+ ma_ui_client_get_previous_state(g_ma_ui, ¤t_state, &previous_state);
+
+ if (NULL != changed_callback) {
+ ma_ui_client_use_callback(g_ma_ui);
+ changed_callback(previous_state, current_state, user_data);
+ ma_ui_client_not_use_callback(g_ma_ui);
+ SLOG(LOG_DEBUG, TAG_MAUI, "State changed callback is called");
+ } else {
+ SLOG(LOG_WARN, TAG_MAUI, "[WARNING] State changed callback is null");
+ }
+
+ return EINA_FALSE;
+}
+
+static void __start_prepare_thread(void *data, Ecore_Thread *thread)
+{
+ SLOG(LOG_ERROR, TAG_MAUI, "@@@ Start prepare thread");
+ int ret = 1, retry_count = 0;
+
+ /* Send hello */
+ while (0 != ret) {
+ if (retry_count == 10) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to request hello !!");
+ return;
+ }
+
+ ret = ma_ui_dbus_request_hello();
+ if (ret == 0) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "Success to request hello. retry count(%d)", retry_count);
+ break;
+ } else {
+ retry_count++;
+ }
+ }
+
+ ret = 1;
+ retry_count = 0;
+ while (0 != ret) {
+ if (retry_count == 10) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to connect daemon !!");
+ return;
+ }
+ ret = __ma_ui_connect_daemon(NULL);
+ if (ret == 0)
+ break;
+ else
+ retry_count++;
+ }
+
+ return;
+}
+
+static void __end_prepare_thread(void *data, Ecore_Thread *thread)
+{
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ End prepare thread");
+}
+
+int ma_ui_prepare(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Prepare");
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED != state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ecore_thread_run(__start_prepare_thread, __end_prepare_thread, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_unprepare(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Unprepare");
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_READY != state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'READY' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ __ma_ui_internal_unprepare();
+
+ ma_ui_client_set_client_state(g_ma_ui, MA_STATE_INITIALIZED);
+ ecore_timer_add(0, __ma_ui_notify_state_changed, g_ma_ui);
+
+ return MA_ERROR_NONE;
+}
+
+static Eina_Bool __ma_ui_notify_state_changed(void* data)
+{
+ ma_state_changed_cb callback = NULL;
+ void* user_data;
+
+ ma_ui_client_get_state_changed_cb(g_ma_ui, &callback, &user_data);
+
+ ma_state_e current_state;
+ ma_state_e previous_state;
+
+ ma_ui_client_get_previous_state(g_ma_ui, ¤t_state, &previous_state);
+
+ if (NULL != callback) {
+ ma_ui_client_use_callback(g_ma_ui);
+ callback(previous_state, current_state, user_data);
+ ma_ui_client_not_use_callback(g_ma_ui);
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] State changed callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[WARNING] State changed callback is NULL");
+ }
+
+ return EINA_FALSE;
+}
+
+/*
+static void __ma_ui_lang_changed_cb(const char* previous_lang, const char* current_lang)
+{
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI DEBUG] Language changed: prev(%s) curr(%s)", previous_lang, current_lang);
+
+ ma_language_changed_cb callback = NULL;
+ void* user_data;
+
+ ma_ui_client_get_lang_changed_cb(g_ma_ui, &callback, &user_data);
+
+ if (NULL != callback) {
+ ma_ui_client_use_callback(g_ma_ui);
+ callback(previous_lang, current_lang, user_data);
+ ma_ui_client_not_use_callback(g_ma_ui);
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Lang changed callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[WARNING] Lang changed callback is NULL");
+ }
+}
+*/
+
+static void __ma_ui_notify_send_asr_result(ma_asr_result_event_e event, char* asr_result)
+{
+ ma_ui_asr_result_cb callback = NULL;
+ void* user_data;
+
+ ma_ui_client_get_asr_result_cb(g_ma_ui, &callback, &user_data);
+
+ if (NULL != callback) {
+ ma_ui_client_use_callback(g_ma_ui);
+ callback(event, asr_result, user_data);
+ ma_ui_client_not_use_callback(g_ma_ui);
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] asr result callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[WARNING] asr result callback is NULL");
+ }
+}
+
+int __ma_ui_cb_send_asr_result(int event, char* asr_result)
+{
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid client");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ /* check state */
+/* if (MA_STATE_READY != state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'READY' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+*/
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] send asr result, event(%d), asr_result(%s)", event, asr_result);
+
+ __ma_ui_notify_send_asr_result((ma_asr_result_event_e)event, asr_result);
+
+ return MA_ERROR_NONE;
+}
+
+static void __ma_ui_notify_send_result(const char* display_text, const char* utterance_text, const char* result_json)
+{
+ ma_ui_result_cb callback = NULL;
+ void* user_data;
+
+ ma_ui_client_get_result_cb(g_ma_ui, &callback, &user_data);
+
+ if (NULL != callback) {
+ ma_ui_client_use_callback(g_ma_ui);
+ callback(display_text, utterance_text, result_json, user_data);
+ ma_ui_client_not_use_callback(g_ma_ui);
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] result callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[WARNING] result callback is NULL");
+ }
+}
+
+int __ma_ui_cb_send_result(const char* display_text, const char* utterance_text, const char* result_json)
+{
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid client");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ /* check state */
+/* if (MA_STATE_READY != state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'READY' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+*/
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] send result, display_text(%s), utterance_text(%s), result_json(%s)", display_text, utterance_text, result_json);
+
+ __ma_ui_notify_send_result(display_text, utterance_text, result_json);
+
+ return MA_ERROR_NONE;
+}
+
+int __ma_ui_cb_error(int reason, char* msg)
+{
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid client");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ /* check state */
+ if (MA_STATE_READY != state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'READY' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ if (MA_ERROR_SERVICE_RESET == reason) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant service reset");
+ ma_ui_client_set_client_state(g_ma_ui, MA_STATE_INITIALIZED);
+ __ma_ui_notify_state_changed(g_ma_ui);
+
+ if (0 != ma_ui_prepare()) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to prepare");
+ }
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Error reason(%d), msg(%s)", reason, msg);
+
+ ma_ui_client_set_error(g_ma_ui, reason);
+ __ma_ui_notify_error(g_ma_ui);
+
+ return MA_ERROR_NONE;
+}
+
+static void __ma_ui_notify_error(void* data)
+{
+ ma_error_cb callback = NULL;
+ void* user_data;
+ ma_error_e reason;
+
+ ma_ui_client_get_error_cb(g_ma_ui, &callback, &user_data);
+ ma_ui_client_get_error(g_ma_ui, &reason);
+
+ if (NULL != callback) {
+ ma_ui_client_use_callback(g_ma_ui);
+ callback(reason, user_data);
+ ma_ui_client_not_use_callback(g_ma_ui);
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Error callback is called");
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[WARNING] Error callback is NULL");
+ }
+}
+
+int ma_ui_get_state(ma_state_e* state)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI DEBUG] Get current state");
+
+ if (NULL == state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[Client ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+
+ ma_state_e tmp_state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &tmp_state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ *state = tmp_state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_foreach_assistant_info(ma_ui_assistant_info_cb callback, void* user_data)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Get foreach assistant info");
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ int ret = -1;
+/* ret = ma_config_mgr_get_assistant_info(callback, user_data);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Fail to get assistant info");
+ }
+*/
+ ret = 0;
+ return ret;
+}
+
+int ma_ui_set_default_assistant(const char* app_id)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Set a default assistant");
+
+ if (NULL == app_id) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED!= state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ int ret = -1;
+/* ret = ma_config_mgr_set_default_assistant(app_id);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Fail to set default assistant")_;
+ }
+*/
+ ret = 0;
+ return ret;
+}
+
+int ma_ui_change_assistant(const char* app_id)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ if (0 != __ma_ui_check_privilege()) {
+ return MA_ERROR_PERMISSION_DENIED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Change a assistant");
+
+ if (NULL == app_id) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED!= state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ int ret = -1;
+/* ret = ma_config_mgr_change_assistant(app_id);
+ if (0 != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Fail to set default assistant")_;
+ }
+*/
+ ret = 0;
+ return ret;
+}
+
+
+int ma_ui_set_state_changed_cb(ma_state_changed_cb callback, void* user_data)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[Client DEBUG] Set Multi-assistant client state changed cb");
+
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_state_changed_cb(g_ma_ui, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_unset_state_changed_cb(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI DEBUG] Unset Multi-assistant client state changed cb");
+
+ ma_state_e state;
+
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_state_changed_cb(g_ma_ui, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_set_error_cb(ma_error_cb callback, void* user_data)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[Client DEBUG] Set Multi-assistant UI client error cb");
+
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid parameter"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_error_cb(g_ma_ui, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_unset_error_cb(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI DEBUG] Unset Multi-assistant UI client error cb");
+
+ ma_state_e state;
+
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] A handle is not available"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (state != MA_STATE_INITIALIZED) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Invalid State: Current state is not 'Initialized'"); //LCOV_EXCL_LINE
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_error_cb(g_ma_ui, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_set_asr_result_cb(ma_ui_asr_result_cb callback, void* user_data)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Set a ASR result callback");
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED!= state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_asr_result_cb(g_ma_ui, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_unset_asr_result_cb(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Set a default assistant");
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED!= state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_asr_result_cb(g_ma_ui, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_set_result_cb(ma_ui_result_cb callback, void* user_data)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Set a default assistant");
+
+ if (NULL == callback) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid parameter");
+ return MA_ERROR_INVALID_PARAMETER;
+ }
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED!= state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_result_cb(g_ma_ui, callback, user_data);
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_unset_result_cb(void)
+{
+ if (0 != __ma_ui_get_feature_enabled()) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "@@@ [UI] not supported");
+ return MA_ERROR_NOT_SUPPORTED;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[UI] Set a default assistant");
+
+ ma_state_e state;
+ if (0 != ma_ui_client_get_client_state(g_ma_ui, &state)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] A handle is not available");
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ /* check state */
+ if (MA_STATE_INITIALIZED!= state) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[UI ERROR] Invalid state: Current state is not 'Initialized' (%d)", state);
+ return MA_ERROR_INVALID_STATE;
+ }
+
+ ma_ui_client_set_result_cb(g_ma_ui, NULL, NULL);
+
+ return MA_ERROR_NONE;
+}
+
--- /dev/null
+/**
+ * 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.
+ */
+
+
+#include "ma_ui_client.h"
+
+
+typedef struct {
+ ma_h ma;
+ int pid;
+ int uid; /*<< unique id = pid + handle */
+
+ ma_ui_result_cb result_cb;
+ void* result_user_data;
+ ma_ui_asr_result_cb asr_result_cb;
+ void* asr_result_user_data;
+
+ ma_error_cb error_cb;
+ void* error_user_data;
+ ma_state_changed_cb state_changed_cb;
+ void* state_changed_user_data;
+ ma_language_changed_cb lang_changed_cb;
+ void* lang_changed_user_data;
+
+ /* ASR result */
+ ma_asr_result_event_e asr_result_event;
+ char* asr_result_text;
+
+ /* state */
+ ma_state_e previous_state;
+ ma_state_e current_state;
+
+ /* language */
+ char* previous_language;
+ char* current_language;
+
+ /* audio type */
+ char* audio_id;
+
+ /* mutex */
+ int cb_ref_count;
+
+ /* error data */
+ int reason;
+ char* err_msg;
+} ma_ui_client_s;
+
+static GSList* g_ui_client_list = NULL;
+
+static ma_ui_client_s* __ui_client_get(ma_h ma)
+{
+ if (NULL == ma) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Input parameter is NULL");
+ return NULL;
+ }
+
+ ma_ui_client_s* data = NULL;
+ int count = g_slist_length(g_ui_client_list);
+ int i;
+
+ for (i = 0 ; i < count ; i++) {
+ data = g_slist_nth_data(g_ui_client_list, i);
+
+ if (NULL != data) {
+ if (ma->handle == data->ma->handle) {
+ return data;
+ }
+ }
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Fail to get ui client");
+ return NULL;
+}
+
+int ma_ui_client_create(ma_h* ma)
+{
+ ma_ui_client_s *client = NULL;
+
+ client = (ma_ui_client_s*)calloc(1, sizeof(ma_ui_client_s));
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to allocate memory");
+ return MA_ERROR_OUT_OF_MEMORY;
+ }
+
+ ma_h temp = (ma_h)calloc(1, sizeof(struct ma_s));
+ if (NULL == temp) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to allocate memory");
+ free(client);
+ return MA_ERROR_OUT_OF_MEMORY;
+ }
+
+ temp->handle = getpid();
+
+ /* initialize client data */
+ client->ma = temp;
+ client->pid = getpid();
+ client->uid = temp->handle;
+
+ client->result_cb = NULL;
+ client->result_user_data = NULL;
+ client->asr_result_cb = NULL;
+ client->asr_result_user_data = NULL;
+
+ client->error_cb = NULL;
+ client->error_user_data = NULL;
+ client->state_changed_cb = NULL;
+ client->state_changed_user_data = NULL;
+ client->lang_changed_cb = NULL;
+ client->lang_changed_user_data = NULL;
+
+ client->asr_result_event = 0;
+ client->asr_result_text = NULL;
+
+ client->previous_state = MA_STATE_INITIALIZED;
+ client->current_state = MA_STATE_INITIALIZED;
+
+ client->previous_language = NULL;
+ client->current_language = NULL;
+
+ client->audio_id = NULL;
+
+ client->reason = 0;
+ client->err_msg = NULL;
+
+ client->cb_ref_count = 0;
+
+
+ g_ui_client_list = g_slist_append(g_ui_client_list, client);
+
+ *ma = temp;
+
+ return 0;}
+
+int ma_ui_client_destroy(ma_h ma)
+{
+ if (ma == NULL) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Input parameter is NULL");
+ return 0;
+ }
+
+ ma_ui_client_s *data = NULL;
+
+ int count = g_slist_length(g_ui_client_list);
+ int i;
+
+ for (i = 0; i < count; i++) {
+ data = g_slist_nth_data(g_ui_client_list, i);
+
+ if (NULL != data) {
+ if (ma->handle == data->ma->handle) {
+ g_ui_client_list = g_slist_remove(g_ui_client_list, data);
+
+ while (0 != data->cb_ref_count) {
+ /* wait for release callback function */
+ }
+
+ if (NULL != data->audio_id) {
+ free(data->audio_id);
+ }
+
+ if (NULL != data->asr_result_text) {
+ free(data->asr_result_text);
+ }
+
+ if (NULL != data->err_msg) {
+ free(data->err_msg);
+ }
+
+ free(data);
+ free(ma);
+
+ data = NULL;
+ ma = NULL;
+
+ return 0;
+ }
+ }
+ }
+
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] client Not found");
+
+ return -1;}
+
+bool ma_ui_client_is_valid(ma_h ma)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] ma handle is not valid");
+ return false;
+ }
+
+ return true;
+}
+
+int ma_ui_client_use_callback(ma_h ma)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->cb_ref_count++;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_not_use_callback(ma_h ma)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->cb_ref_count--;
+
+ return MA_ERROR_NONE;
+}
+
+
+int ma_ui_client_set_client_state(ma_h ma, ma_state_e state)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->previous_state = client->current_state;
+ client->current_state = state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_client_state(ma_h ma, ma_state_e* state)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *state = client->current_state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_previous_state(ma_h ma, ma_state_e* current_state, ma_state_e* previous_state)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *current_state = client->current_state;
+ *previous_state = client->previous_state;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_set_error(ma_h ma, ma_error_e reason)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->reason = reason;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_error(ma_h ma, ma_error_e* reason)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *reason = client->reason;
+
+ return MA_ERROR_NONE;
+}
+
+
+int ma_ui_client_set_asr_result_cb(ma_h ma, ma_ui_asr_result_cb callback, void* user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->asr_result_cb = callback;
+ client->asr_result_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_asr_result_cb(ma_h ma, ma_ui_asr_result_cb* callback, void** user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->asr_result_cb;
+ *user_data = client->asr_result_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_set_result_cb(ma_h ma, ma_ui_result_cb callback, void* user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->result_cb = callback;
+ client->result_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_result_cb(ma_h ma, ma_ui_result_cb* callback, void** user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->result_cb;
+ *user_data = client->result_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_set_error_cb(ma_h ma, ma_error_cb callback, void* user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->error_cb = callback;
+ client->error_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_error_cb(ma_h ma, ma_error_cb* callback, void** user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->error_cb;
+ *user_data = client->error_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_set_state_changed_cb(ma_h ma, ma_state_changed_cb callback, void* user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->state_changed_cb = callback;
+ client->state_changed_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_state_changed_cb(ma_h ma, ma_state_changed_cb* callback, void** user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->state_changed_cb;
+ *user_data = client->state_changed_user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_set_lang_changed_cb(ma_h ma, ma_language_changed_cb callback, void* user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ client->lang_changed_cb = callback;
+ client->lang_changed_user_data = user_data;
+
+ return MA_ERROR_NONE;
+}
+
+int ma_ui_client_get_lang_changed_cb(ma_h ma, ma_language_changed_cb* callback, void** user_data)
+{
+ ma_ui_client_s* client = __ui_client_get(ma);
+
+ if (NULL == client)
+ return MA_ERROR_INVALID_PARAMETER;
+
+ *callback = client->lang_changed_cb;
+ *user_data = client->lang_changed_user_data;
+
+ return MA_ERROR_NONE;
+}
+
--- /dev/null
+/**
+ * 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 __MA_UI_CLIENT_H__
+#define __MA_UI_CLIENT_H__
+
+#include "ma_main.h"
+#include "multi_assistant_common.h"
+#include "multi_assistant_ui.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+int ma_ui_client_create(ma_h* ma);
+
+int ma_ui_client_destroy(ma_h ma);
+
+bool ma_ui_client_is_valid(ma_h ma);
+
+int ma_ui_client_use_callback(ma_h ma);
+
+int ma_ui_client_not_use_callback(ma_h ma);
+
+
+int ma_ui_client_set_client_state(ma_h ma, ma_state_e state);
+
+int ma_ui_client_get_client_state(ma_h ma, ma_state_e* state);
+
+int ma_ui_client_get_previous_state(ma_h ma, ma_state_e* current_state, ma_state_e* previous_state);
+
+int ma_ui_client_set_error(ma_h ma, ma_error_e reason);
+
+int ma_ui_client_get_error(ma_h ma, ma_error_e* reason);
+
+
+int ma_ui_client_set_asr_result_cb(ma_h ma, ma_ui_asr_result_cb callback, void* user_data);
+
+int ma_ui_client_get_asr_result_cb(ma_h ma, ma_ui_asr_result_cb* callback, void** user_data);
+
+int ma_ui_client_set_result_cb(ma_h ma, ma_ui_result_cb callback, void* user_data);
+
+int ma_ui_client_get_result_cb(ma_h ma, ma_ui_result_cb* callback, void** user_data);
+
+int ma_ui_client_set_error_cb(ma_h ma, ma_error_cb callback, void* user_data);
+
+int ma_ui_client_get_error_cb(ma_h ma, ma_error_cb* callback, void** user_data);
+
+int ma_ui_client_set_state_changed_cb(ma_h ma, ma_state_changed_cb callback, void* user_data);
+
+int ma_ui_client_get_state_changed_cb(ma_h ma, ma_state_changed_cb* callback, void** user_data);
+
+int ma_ui_client_set_lang_changed_cb(ma_h ma, ma_language_changed_cb callback, void* user_data);
+
+int ma_ui_client_get_lang_changed_cb(ma_h ma, ma_language_changed_cb* callback, void** user_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_UI_CLIENT_H__ */
+
--- /dev/null
+/**
+ * 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.
+ */
+
+
+#include "ma_ui_dbus.h"
+#include "ma_defs.h"
+#include "ma_main.h"
+
+
+
+static int g_ui_waiting_time = 3000;
+
+static Ecore_Fd_Handler* g_ui_fd_handler = NULL;
+
+static DBusConnection* g_ui_conn_sender = NULL;
+static DBusConnection* g_ui_conn_listener = NULL;
+
+extern int __ma_ui_cb_error(int reason, char* msg);
+extern int __ma_ui_cb_send_asr_result(int event, char* asr_result);
+extern int __ma_ui_cb_send_result(const char* display_text, const char* utterance_text, const char* result_json);
+
+
+static Eina_Bool ma_ui_listener_event_callback(void* data, Ecore_Fd_Handler* fd_handler)
+{
+ if (NULL == g_ui_conn_listener)
+ return ECORE_CALLBACK_RENEW;
+
+ dbus_connection_read_write_dispatch(g_ui_conn_listener, 50);
+
+ while (1) {
+ DBusMessage* msg = NULL;
+ msg = dbus_connection_pop_message(g_ui_conn_listener);
+
+ /* loop again if we haven't read a message */
+ if (NULL == msg) {
+ break;
+ }
+
+ /* SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Message is arrived"); */
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ char if_name[64] = {0, };
+ snprintf(if_name, 64, "%s", MA_UI_CLIENT_SERVICE_INTERFACE);
+
+ if (dbus_message_is_method_call(msg, if_name, MAS_METHOD_HELLO)) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Get Hello");
+ int response = -1;
+
+ DBusMessage *reply = NULL;
+ reply = dbus_message_new_method_return(msg);
+
+ if (NULL != reply) {
+ dbus_message_append_args(reply, DBUS_TYPE_INT32, &response, DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send(g_ui_conn_listener, reply, NULL))
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] vc get hello : fail to send reply");
+ else
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] vc get hello : result(%d)", response);
+
+ dbus_connection_flush(g_ui_conn_listener);
+ dbus_message_unref(reply);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui get hello : fail to create reply message");
+ }
+
+ } /* MAS_METHOD_HELLO */
+
+ if (dbus_message_is_method_call(msg, if_name, MAS_UI_METHOD_SEND_ASR_RESULT)) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Send asr result");
+ int pid = 0;
+ int event = 0;
+ char* asr_result = NULL;
+
+ dbus_message_get_args(msg, &err,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INT32, &event,
+ DBUS_TYPE_STRING, &asr_result,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] multi-assistant ui Send ASR result : pid(%d), event(%d), asr_result(%s)", pid, event, asr_result);
+ char* temp_asr = NULL;
+ if (NULL != asr_result && strcmp("#NULL", asr_result)) {
+ temp_asr = strdup(asr_result);
+ }
+ __ma_ui_cb_send_asr_result(event, temp_asr);
+ if (NULL != temp_asr)
+ free(temp_asr);
+ }
+
+ } /* MAS_UI_METHOD_SEND_ASR_RESULT */
+
+ if (dbus_message_is_method_call(msg, if_name, MAS_UI_METHOD_SEND_RESULT)) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Send asr result");
+ int pid = 0;
+ char* display_text = NULL;
+ char* utterance_text = NULL;
+ char* result_json = NULL;
+
+ dbus_message_get_args(msg, &err,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_STRING, &display_text,
+ DBUS_TYPE_STRING, &utterance_text,
+ DBUS_TYPE_STRING, &result_json,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] multi-assistant ui Send result : pid(%d), display_text(%s), utterance_text(%s), result_json(%s)", pid, display_text, utterance_text, result_json);
+#if 0
+ __ma_ui_cb_send_result(display_text, utterance_text, result_json);
+#else
+ char* temp_display_text = NULL;
+ char* temp_utterance_text = NULL;
+ char* temp_result_json = NULL;
+ if (NULL != display_text && strcmp("#NULL", display_text))
+ temp_display_text = strdup(display_text);
+ if (NULL != utterance_text && strcmp("#NULL", utterance_text))
+ temp_utterance_text = strdup(utterance_text);
+ if (NULL != result_json && strcmp("#NULL", result_json))
+ temp_result_json = strdup(result_json);
+
+ __ma_ui_cb_send_result(temp_display_text, temp_utterance_text, temp_result_json);
+
+ if (NULL != temp_display_text)
+ free(temp_display_text);
+ if (NULL != temp_utterance_text)
+ free(temp_utterance_text);
+ if (NULL != temp_result_json)
+ free(temp_result_json);
+#endif
+ }
+
+ } /* MAS_UI_METHOD_SEND_RESULT */
+
+ else if (dbus_message_is_signal(msg, if_name, MAS_UI_METHOD_ERROR)) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Get Error");
+ int reason;
+ char* err_msg = NULL;
+
+ dbus_message_get_args(msg, &err,
+ DBUS_TYPE_INT32, &reason,
+ DBUS_TYPE_STRING, &err_msg,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui Get Error message : Get arguments error (%s)", err.message);
+ dbus_error_free(&err);
+ } else {
+ char* temp_msg = NULL;
+ if (NULL != err_msg && strcmp("#NULL", err_msg)) {
+ temp_msg = strdup(err_msg);
+ }
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui Get Error message : reason(%d), msg(%s)", reason, temp_msg);
+ __ma_ui_cb_error(reason, temp_msg);
+ if (NULL != temp_msg) {
+ free(temp_msg);
+ temp_msg = NULL;
+ }
+ }
+ } /* MAD_MANAGER_METHOD_ERROR */
+
+ else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameOwnerChanged")) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] Owner Changed");
+ /* remove a rule for daemon error */
+ DBusError err;
+ /* initialize the error value */
+ dbus_error_init(&err);
+ char rule_err[256] = {0, };
+ snprintf(rule_err, 256, "sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',type='signal',arg0='%s'", MA_SERVER_SERVICE_INTERFACE);
+ dbus_bus_remove_match(g_ui_conn_listener, rule_err, &err);
+ dbus_connection_flush(g_ui_conn_listener);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Match Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+ __ma_ui_cb_error(MA_ERROR_SERVICE_RESET, "Daemon Reset");
+ } /* NameOwnerChanged */
+
+ else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "Message is NOT valid");
+ dbus_message_unref(msg);
+ break;
+ }
+
+ /* free the message */
+ dbus_message_unref(msg);
+ } /* while(1) */
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void __ma_ui_dbus_connection_free()
+{
+ if (NULL != g_ui_conn_listener) {
+ dbus_connection_close(g_ui_conn_listener);
+ dbus_connection_unref(g_ui_conn_listener);
+ g_ui_conn_listener = NULL;
+ }
+ if (NULL != g_ui_conn_sender) {
+ dbus_connection_close(g_ui_conn_sender);
+ dbus_connection_unref(g_ui_conn_sender);
+ g_ui_conn_sender = NULL;
+ }
+}
+
+int ma_ui_dbus_open_connection()
+{
+ if (NULL != g_ui_conn_sender && NULL != g_ui_conn_listener) {
+ SLOG(LOG_WARN, TAG_MAUI, "already existed connection ");
+ return 0;
+ }
+
+ DBusError err;
+ int ret;
+
+ /* initialize the error value */
+ dbus_error_init(&err);
+
+ /* connect to the DBUS system bus, and check for errors */
+ g_ui_conn_sender = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Dbus Connection Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (NULL == g_ui_conn_sender) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Fail to get dbus connection ");
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_connection_set_exit_on_disconnect(g_ui_conn_sender, false);
+
+ /* connect to the DBUS system bus, and check for errors */
+ g_ui_conn_listener = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Dbus Connection Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (NULL == g_ui_conn_listener) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Fail to get dbus connection ");
+ __ma_ui_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_connection_set_exit_on_disconnect(g_ui_conn_listener, false);
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "service name is %s", MA_UI_CLIENT_SERVICE_NAME);
+
+ /* register our name on the bus, and check for errors */
+ ret = dbus_bus_request_name(g_ui_conn_listener, MA_UI_CLIENT_SERVICE_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Name Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "fail dbus_bus_request_name()");
+ __ma_ui_dbus_connection_free();
+ return -2;
+ }
+
+ if (NULL != g_ui_fd_handler) {
+ SLOG(LOG_WARN, TAG_MAUI, "The handler already exists.");
+ __ma_ui_dbus_connection_free();
+ return 0;
+ }
+
+ /* Flush messages which are received before fd event handler registration */
+ while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_get_dispatch_status(g_ui_conn_listener)) {
+ ma_ui_listener_event_callback(NULL, NULL);
+ }
+
+ char rule[128] = {0, };
+ snprintf(rule, 128, "type='signal',interface='%s'", MA_UI_CLIENT_SERVICE_INTERFACE);
+
+ /* add a rule for which messages we want to see */
+ dbus_bus_add_match(g_ui_conn_listener, rule, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Match Error (%s)", err.message);
+ dbus_error_free(&err);
+ __ma_ui_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ int fd = 0;
+ if (1 != dbus_connection_get_unix_fd(g_ui_conn_listener, &fd)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "fail to get fd from dbus ");
+ __ma_ui_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "Get fd from dbus : %d", fd);
+ }
+
+ g_ui_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)ma_ui_listener_event_callback, g_ui_conn_listener, NULL, NULL);
+
+ if (NULL == g_ui_fd_handler) {
+ SLOG(LOG_ERROR, TAG_MAUI, "fail to get fd handler from ecore ");
+ __ma_ui_dbus_connection_free();
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ return 0;}
+
+int ma_ui_dbus_close_connection()
+{
+ DBusError err;
+ dbus_error_init(&err);
+
+ if (NULL != g_ui_fd_handler) {
+ ecore_main_fd_handler_del(g_ui_fd_handler);
+ g_ui_fd_handler = NULL;
+ }
+
+ if (NULL != g_ui_conn_listener) {
+// int pid = getpid();
+
+ char service_name[64];
+ memset(service_name, '\0', 64);
+// snprintf(service_name, 64, "%s%d", MA_UI_CLIENT_SERVICE_NAME, pid);
+ snprintf(service_name, 64, "%s", MA_UI_CLIENT_SERVICE_NAME);
+
+ dbus_bus_release_name(g_ui_conn_listener, service_name, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+ }
+
+ __ma_ui_dbus_connection_free();
+
+ return 0;
+}
+
+int ma_ui_dbus_reconnect()
+{
+ if (!g_ui_conn_sender || !g_ui_conn_listener) {
+ ma_ui_dbus_close_connection();
+
+ if (0 != ma_ui_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to reconnect");
+ return -1;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DBUS] Reconnect");
+ return 0;
+ }
+
+ bool sender_connected = dbus_connection_get_is_connected(g_ui_conn_sender);
+ bool listener_connected = dbus_connection_get_is_connected(g_ui_conn_listener);
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DBUS] Sender(%s) Listener(%s)",
+ sender_connected ? "Connected" : "Not connected", listener_connected ? "Connected" : "Not connected");
+
+ if (false == sender_connected || false == listener_connected) {
+ ma_ui_dbus_close_connection();
+
+ if (0 != ma_ui_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to reconnect");
+ return -1;
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DBUS] Reconnect");
+ }
+
+ return 0;
+}
+
+int ma_ui_dbus_request_hello()
+{
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_METHOD_HELLO);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Request vc hello : Fail to make message");
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage* result_msg = NULL;
+ int result = 0;
+
+ result_msg = dbus_connection_send_with_reply_and_block(g_ui_conn_sender, msg, -1, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ dbus_message_unref(msg);
+
+ if (NULL != result_msg) {
+ dbus_message_unref(result_msg);
+ result = 0;
+ } else {
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
+
+static int __dbus_restore_daemon()
+{
+ int ret = -1;
+ int count = 0;
+ while (0 != ret) {
+ ret = ma_ui_dbus_request_hello();
+ if (0 != ret) {
+ if (MA_ERROR_TIMED_OUT != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to restore daemon");
+ break;
+ } else {
+ SLOG(LOG_WARN, TAG_MAUI, "[WARNING] retry restore daemon");
+ usleep(10000);
+ count++;
+ if (MA_RETRY_COUNT == count) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to request");
+ break;
+ }
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[SUCCESS] restore daemon");
+ }
+ }
+ return ret;
+}
+
+int ma_ui_dbus_request_initialize(int pid)
+{
+ DBusError err;
+ dbus_error_init(&err);
+
+ bool exist = dbus_bus_name_has_owner(g_ui_conn_sender, MA_SERVER_SERVICE_NAME, &err);
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ int ret;
+ if (false == exist) {
+ ret = __dbus_restore_daemon();
+ if (MA_ERROR_NONE != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to restore daemon");
+ return MA_ERROR_TIMED_OUT;
+ }
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_UI_METHOD_INITIALIZE);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui initialize : Fail to make message ");
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[ERROR] multi-assistant ui initialize : pid(%d)", pid);
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INVALID);
+
+ DBusMessage* result_msg;
+ int result = MA_ERROR_OPERATION_FAILED;
+
+ result_msg = dbus_connection_send_with_reply_and_block(g_ui_conn_sender, msg, g_ui_waiting_time, &err);
+ dbus_message_unref(msg);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[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_MAUI, "[ERROR] Get arguments error (%s)", err.message);
+ dbus_error_free(&err);
+ result = MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_message_unref(result_msg);
+
+ if (0 == result) {
+ /* add a rule for daemon error */
+ char rule_err[256] = {0, };
+ snprintf(rule_err, 256, "sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',type='signal',arg0='%s'", MA_SERVER_SERVICE_INTERFACE);
+ dbus_bus_add_match(g_ui_conn_listener, rule_err, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Match Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ SLOG(LOG_DEBUG, TAG_MAUI, "[ERROR] multi-assistant ui initialize : result = %d", result);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui initialize : result = %d", result);
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Result message is NULL ");
+ ma_ui_dbus_reconnect();
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;}
+
+int ma_ui_dbus_request_deinitialize(int pid)
+{
+ DBusError err;
+ dbus_error_init(&err);
+
+ bool exist = dbus_bus_name_has_owner(g_ui_conn_sender, MA_SERVER_SERVICE_NAME, &err);
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ int ret;
+ if (false == exist) {
+ ret = __dbus_restore_daemon();
+ if (MA_ERROR_NONE != ret) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Fail to restore daemon");
+ return MA_ERROR_TIMED_OUT;
+ }
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ /* remove a rule for daemon error */
+ char rule_err[256] = {0, };
+ snprintf(rule_err, 256, "sender='org.freedesktop.DBus',path='/org/freedesktop/DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged',type='signal',arg0='%s'", MA_SERVER_SERVICE_INTERFACE);
+ dbus_bus_remove_match(g_ui_conn_listener, rule_err, &err);
+ dbus_connection_flush(g_ui_conn_listener);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "Match Error (%s)", err.message);
+ dbus_error_free(&err);
+ return MA_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ MA_SERVER_SERVICE_NAME,
+ MA_SERVER_SERVICE_OBJECT_PATH,
+ MA_SERVER_SERVICE_INTERFACE,
+ MA_UI_METHOD_DEINITIALIZE);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui finalize : Fail to make message ");
+ return MA_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] multi-assistant ui finalize : pid(%d)", pid);
+ }
+
+ dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID);
+
+ DBusMessage* result_msg;
+ int result = MA_ERROR_OPERATION_FAILED;
+
+ result_msg = dbus_connection_send_with_reply_and_block(g_ui_conn_sender, msg, g_ui_waiting_time, &err);
+ dbus_message_unref(msg);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_MAUI, "[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_MAUI, "[ERROR] Get arguments error (%s)", err.message);
+ dbus_error_free(&err);
+ result = MA_ERROR_OPERATION_FAILED;
+ }
+
+ dbus_message_unref(result_msg);
+
+ if (0 == result) {
+ SLOG(LOG_DEBUG, TAG_MAUI, "[DEBUG] multi-assistant ui finalize : result = %d", result);
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] multi-assistant ui finalize : result = %d", result);
+ }
+ } else {
+ SLOG(LOG_ERROR, TAG_MAUI, "[ERROR] Result message is NULL ");
+ ma_ui_dbus_reconnect();
+ result = MA_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
+
--- /dev/null
+/**
+ * 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 __MA_UI_DBUS_H__
+#define __MA_UI_DBUS_H__
+
+#include "multi_assistant_common.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+int ma_ui_dbus_open_connection();
+
+int ma_ui_dbus_close_connection();
+
+
+int ma_ui_dbus_request_hello();
+
+int ma_ui_dbus_request_initialize(int pid);
+
+int ma_ui_dbus_request_deinitialize(int pid);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_UI_DBUS_H__ */
+
--- /dev/null
+/**
+ * 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.
+ */
+
+
+#include "ma_config_mgr.h"
+#include "ma_main.h"
+
+typedef struct {
+ int uid;
+ ma_config_lang_changed_cb lang_cb;
+} ma_config_client_s;
+
+
+//static GSList* g_config_client_list = NULL;
+
+//static pthread_mutex_t ma_config_mgr_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+int ma_config_mgr_initialize(int uid)
+{
+ return 0;
+}
+int ma_config_mgr_deinitialize(int uid)
+{
+ return 0;
+}
+
+int ma_config_mgr_get_default_language(char** language)
+{
+ return 0;
+}
+
+int ma_config_mgr_get_assistant_info(ma_ui_assistant_info_cb callback, void* user_data)
+{
+ return 0;
+}
+
+int ma_config_mgr_set_default_assistant(const char* app_id)
+{
+ return 0;
+}
+
+int ma_config_mgr_change_assistant(const char* app_id)
+{
+ return 0;
+}
+
+
+int ma_config_mgr_set_lang_cb(int uid, ma_config_lang_changed_cb lang_cb)
+{
+ return 0;
+}
+
+int ma_config_mgr_unset_lang_cb(int uid)
+{
+ return 0;
+}
+
--- /dev/null
+/**
+ * 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 __MA_CONFIG_MGR_H__
+#define __MA_CONFIG_MGR_H__
+
+#include "ma_defs.h"
+#include "multi_assistant_ui.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+typedef void (*ma_config_lang_changed_cb)(const char* previous_lang, const char* current_lang);
+
+int ma_config_mgr_initialize(int uid);
+
+int ma_config_mgr_deinitialize(int uid);
+
+int ma_config_mgr_get_default_language(char** language);
+
+int ma_config_mgr_get_assistant_info(ma_ui_assistant_info_cb callback, void* user_data);
+
+int ma_config_mgr_set_default_assistant(const char* app_id);
+
+int ma_config_mgr_change_assistant(const char* app_id);
+
+
+int ma_config_mgr_set_lang_cb(int uid, ma_config_lang_changed_cb lang_cb);
+
+int ma_config_mgr_unset_lang_cb(int uid);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_CONFIG_MGR_H__ */
+
--- /dev/null
+/**
+ * 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 __MA_DEFS_H__
+#define __MA_DEFS_H__
+
+#include <tzplatform_config.h>
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/**************************************************************************************
+ *** Definitions for configurations
+ *************************************************************************************/
+#define MA_FEATURE_PATH "tizen.org/feature/multi_assistant"
+#define MA_MIC_FEATURE_PATH "tizen.org/feature/microphone"
+
+#define MA_PRIVILEGE "http://tizen.org/privilege/recorder"
+
+#define MA_DEFAULT_BASE tzplatform_mkpath(tzplatform_getid("TZ_SYS_RO_SHARE"), "multiassistant/ma/1.0")
+#define MA_DEFAULT_CONFIG tzplatform_mkpath(tzplatform_getid("TZ_SYS_RO_SHARE"), "multiassistant/ma/1.0/ma-config.xml")
+#define MA_BASE tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.multiassistant");
+#define MA_CONFIG tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.multiassistant/ma-config.xml")
+
+/**************************************************************************************
+ *** Definitions for DBus
+ *************************************************************************************/
+#define MA_CLIENT_SERVICE_NAME "org.tizen.multiassistant.maclient"
+#define MA_CLIENT_SERVICE_OBJECT_PATH "/org/tizen/multiassistant/maclient"
+#define MA_CLIENT_SERVICE_INTERFACE "org.tizen.multiassistant.maclient"
+
+#define MA_UI_CLIENT_SERVICE_NAME "org.tizen.multiassistant.mauiclient"
+#define MA_UI_CLIENT_SERVICE_OBJECT_PATH "/org/tizen/multiassistant/mauiclient"
+#define MA_UI_CLIENT_SERVICE_INTERFACE "org.tizen.multiassistant.mauiclient"
+
+#define MA_SERVER_SERVICE_NAME "org.tizen.multiassistant.maserver"
+#define MA_SERVER_SERVICE_OBJECT_PATH "/org/tizen/multiassistant/maserver"
+#define MA_SERVER_SERVICE_INTERFACE "org.tizen.multiassistant.maserver"
+
+/**************************************************************************************
+ *** Definitions for DBus methods
+ *************************************************************************************/
+#define MA_METHOD_HELLO "ma_method_hello"
+
+#define MA_METHOD_INITIALIZE "ma_method_initialize"
+#define MA_METHOD_DEINITIALIZE "ma_method_deinitialize"
+#define MA_METHOD_GET_RECORDING_AUDIO_FORMAT "ma_method_get_recording_audio_format"
+#define MA_METHOD_SEND_ASR_RESULT "ma_method_send_asr_result"
+#define MA_METHOD_SEND_RESULT "ma_method_send_result"
+
+#define MA_UI_METHOD_INITIALIZE "ma_ui_method_initialize"
+#define MA_UI_METHOD_DEINITIALIZE "ma_ui_method_deinitialize"
+#define MA_UI_METHOD_CHANGE_ASSISTANT "ma_ui_method_change_assistant"
+
+#define MAS_METHOD_HELLO "mas_method_hello"
+#define MAS_METHOD_SEND_SPEECH_DATA "mas_method_send_speech_data"
+#define MAS_METHOD_ERROR "mas_method_error"
+
+#define MAS_UI_METHOD_HELLO "mas_ui_method_hello"
+#define MAS_UI_METHOD_SEND_ASR_RESULT "mas_ui_method_send_asr_result"
+#define MAS_UI_METHOD_SEND_RESULT "mas_ui_method_send_result"
+#define MAS_UI_METHOD_ERROR "mas_ui_method_error"
+
+
+/**************************************************************************************
+ *** Definitions for ETC
+ *************************************************************************************/
+#define MA_RETRY_COUNT 5
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_DEFS_H__ */
+
--- /dev/null
+/**
+ * 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 __MA_MAIN_H__
+#define __MA_MAIN_H__
+
+#include <dbus/dbus.h>
+#include <dlog.h>
+#include <Ecore.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/**************************************************************************************
+ *** Definitions for log tags
+ *************************************************************************************/
+#define TAG_MAC "mac" /* Multi-assistant client log tag */
+#define TAG_MAUI "maui" /* Multi-assistant UI client log tag */
+
+/**************************************************************************************
+ *** Structures for multi-assistant handle
+ *************************************************************************************/
+struct ma_s {
+ int handle;
+};
+
+typedef struct ma_s *ma_h;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __MA_MAIN_H__ */
+
--- /dev/null
+/**
+ * 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 __TIZEN_UIX_MULTI_ASSISTANT_DOC_H__
+#define __TIZEN_UIX_MULTI_ASSISTANT_DOC_H__
+
+
+/**
+ * @ingroup CAPI_UIX_FRAMEWORK
+ * @defgroup CAPI_UIX_MULTI_ASSISTANT_MODULE Multi assistant
+ * @brief The @ref CAPI_UIX_MULTI_ASSISTANT_MODULE provides functions for supporting users to use several assistants.
+ * @section CAPI_UIX_MULTI_ASSISTANT_MODULE_HEADER Required Header
+ * \#include <multi_assistant.h><br>
+ *
+ * @section CAPI_UIX_MULTI_ASSISTANT_MODULE_OVERVIEW Overview
+ * A main function of Voice Control API register command and gets notification for recognition result.
+ * Applications can add their own commands and be provided result when their command is recognized by user voice input.
+ * To use of Voice Control, use the following steps: <br>
+ * 1. Initialize <br>
+ * 2. Register callback functions for notifications <br>
+ * 3. Connect to voice control service asynchronously. The state should be changed to Ready <br>
+ * 4. Make command list as the following step and Step 4 is called repeatedly for each command which an application wants <br>
+ * 4-1. Create command list handle <br>
+ * 4-2. Create command handle <br>
+ * 4-3. Set command and type for command handle <br>
+ * 4-4. Add command handle to command list <br>
+ * 5. Set command list for recognition <br>
+ * 6. Set an invocation name for an application <br>
+ * 7. Get recognition results <br>
+ * 8. Request the dialogue <br>
+ * 9. If an application wants to finish voice control,<br>
+ * 9-1. Destroy command and command list handle <br>
+ * 9-2. Deinitialize <br>
+ * An application can obtain command handle from command list, and also get information from handle.
+ * The Voice Control API also notifies you (by callback mechanism) when the states of client and service are changed,
+ * command is recognized, current language is changed or error occurred.
+ * An application should register callback functions: vc_state_changed_cb(), vc_service_state_changed_cb(), vc_result_cb(),
+ * vc_current_language_changed_cb(), vc_error_cb().
+ *
+ * @section CAPI_UIX_MULTI_ASSISTANT_MODULE_STATE_DIAGRAM State Diagram
+ * The following diagram shows the life cycle and the states of the Voice Control.
+ *
+ * @image html capi_uix_voice_control_state_diagram.png "<State diagram> "
+ * The following diagram shows the states of Voice Control service.
+ *
+ * @image html capi_uix_voice_control_service_state_diagram.png "<Service state diagram>"
+ *
+ * @section CAPI_UIX_MULTI_ASSISTANT_MODULE_STATE_TRANSITIONS State Transitions
+ * <table>
+ * <tr>
+ * <th>FUNCTION</th>
+ * <th>PRE-STATE</th>
+ * <th>POST-STATE</th>
+ * <th>SYNC TYPE</th>
+ * </tr>
+ * <tr>
+ * <td>vc_initialize()</td>
+ * <td>None</td>
+ * <td>Initialized</td>
+ * <td>SYNC</td>
+ * </tr>
+ * <tr>
+ * <td>vc_deinitialize()</td>
+ * <td>Initialized</td>
+ * <td>None</td>
+ * <td>SYNC</td>
+ * </tr>
+ * <tr>
+ * <td>vc_prepare()</td>
+ * <td>Initialized</td>
+ * <td>Ready</td>
+ * <td>ASYNC</td>
+ * </tr>
+ * <tr>
+ * <td>vc_unprepare()</td>
+ * <td>Ready</td>
+ * <td>Initialized</td>
+ * <td>SYNC</td>
+* </tr>
+* </table>
+*
+* @section CAPI_UIX_MULTI_ASSISTANT_MODULE_STATE_DEPENDENT_FUNCTION_CALLS State Dependent Function Calls
+* The following table shows state-dependent function calls.
+* It is forbidden to call functions listed below in wrong states.
+* Violation of this rule may result in an unpredictable behavior.
+* <table>
+* <tr>
+* <th>FUNCTION</th>
+* <th>VALID STATES</th>
+* <th>DESCRIPTION</th>
+* </tr>
+* <tr>
+* <td>vc_initialize()</td>
+* <td>None</td>
+* <td>All functions must be called after vc_initialize()</td>
+* </tr>
+* <tr>
+* <td>vc_deinitialize()</td>
+* <td>Initialized, Ready</td>
+* <td>This function should be called when an application want to finalize voice control using</td>
+* </tr>
+* <tr>
+* <td>vc_prepare()</td>
+* <td>Initialized</td>
+* <td>This function works asynchronously. If service start is failed, application gets the error callback.</td>
+* </tr>
+* <tr>
+* <td>vc_unprepare()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_foreach_supported_languages()</td>
+* <td>Initialized, Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_get_current_language()</td>
+* <td>Initialized, Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_get_state()</td>
+* <td>Initialized, Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_get_service_state()</td>
+* <td>Initialized, Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_get_result()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_get_system_command_list()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_set_command_list()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_unset_command_list()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_set_invocation_name()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_set_server_dialog()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>vc_request_dialog()</td>
+* <td>Ready</td>
+* <td></td>
+* </tr>
+* <tr>
+* <td>
+* vc_set_result_cb()<br>
+* vc_unset_result_cb()<br>
+* vc_set_state_changed_cb()<br>
+* vc_unset_state_changed_cb()<br>
+* vc_set_service_state_changed_cb()<br>
+* vc_unset_service_state_changed_cb()<br>
+* vc_set_current_language_changed_cb()<br>
+* vc_unset_current_language_changed_cb()<br>
+* vc_set_error_cb()<br>
+* vc_unset_error_cb()</td>
+* <td>Initialized</td>
+* <td> All callback function should be registered in Initialized state </td>
+* </tr>
+* </table>
+*
+* @section CAPI_UIX_MULTI_ASSISTANT_MODULE_FEATURES Related Features
+* This API is related with the following features:<br>
+* - http://tizen.org/feature/microphone<br>
+* - http://tizen.org/feature/multi_assistant<br>
+* It is recommended to use features in your application for reliability.<br>
+* You can check if the device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, and control your application's actions accordingly.<br>
+* To ensure your application is running only on devices with specific features, please define the features in your manifest file using the manifest editor in the SDK.<br>
+* More details on using features in your application can be found in the <a href="https://developer.tizen.org/development/tizen-studio/native-tools/configuring-your-app/manifest-text-editor#feature"><b>feature element description</b></a>.
+*/
+
+
+#endif /* __TIZEN_UIX_MULTI_ASSISTANT_DOC_H__ */
+
--- /dev/null
+## configure pkgconfig files ##
+CONFIGURE_FILE(multi-assistant.pc.in multi-assistant.pc @ONLY)
+CONFIGURE_FILE(multi-assistant-ui.pc.in multi-assistant-ui.pc @ONLY)
+
+## Install pc files ##
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi-assistant.pc DESTINATION ${LIBDIR}/pkgconfig)
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi-assistant-ui.pc DESTINATION ${LIBDIR}/pkgconfig)
+
+## Install header files ##
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant.h DESTINATION ${INCLUDEDIR})
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_ui.h DESTINATION ${INCLUDEDIR})
+INSTALL(FILES ${CMAKE_BINARY_DIR}/include/multi_assistant_common.h DESTINATION ${INCLUDEDIR})
--- /dev/null
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: lib@PROJECT_NAME@_manager
+Description: Multi assistant UI client library
+Requires: glib-2.0 dbus-1 capi-base-common
+Version: @VERSION@
+Libs: -L${libdir} -l@PROJECT_NAME@_ui
+Cflags: -I${includedir}
--- /dev/null
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: lib@PROJECT_NAME@
+Description: Multi assistant client library
+Requires: glib-2.0 dbus-1 capi-base-common
+Version: @VERSION@
+Libs: -L${libdir} -l@PROJECT_NAME@
+Cflags: -I${includedir}
--- /dev/null
+/**
+ * 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 __TIZEN_UIFW_MULTI_ASSISTANT_H__
+#define __TIZEN_UIFW_MULTI_ASSISTANT_H__
+
+#include <multi_assistant_common.h>
+
+
+/**
+ * @defgroup CAPI_UIX_MULTI_ASSISTANT_CLIENT_MODULE Multi assistant client
+ * @ingroup CAPI_UIX_MULTI_ASSISTANT_MODULE
+ * @brief The @ref CAPI_UIX_MULTI_ASSISTANT_CLIENT_MODULE API provides functions for getting queries from multi assistant service and sending responses.
+ * @{
+ */
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+
+
+/**
+ * @brief Initializes multi-assistant client.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_OPERATION_FAILED Operation failed
+ * @retval #MA_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @post If this function is called, the state will be #MA_STATE_INITIALIZED.
+ * @see ma_deinitialize()
+ */
+int ma_initialize(void);
+
+/**
+ * @brief Deinitializes multi-assistant client.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @post If this function is called, the state will be #MA_STATE_NONE.
+ * @see ma_initialize()
+ */
+int ma_deinitialize(void);
+
+/**
+ * @brief Prepares multi-assistant client.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @post If this function is called, the state will be #MA_STATE_READY.
+ * @see ma_unprepare()
+ */
+int ma_prepare(void);
+
+/**
+ * @brief Unprepares multi-assistant client.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_READY.
+ * @post If this function is called, the state will be #MA_STATE_INITIALIZED.
+ * @see ma_prepare()
+ */
+int ma_unprepare(void);
+
+/**
+ * @brief Gets the current state of the multi-assistant client.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[out] state The current state
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int ma_get_state(ma_state_e* state);
+
+/**
+ * @brief Gets the current language of multi-assistant client.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @remarks The @a language should be released using free().
+ * @param[out] language The current language
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int ma_get_current_language(char** language);
+
+/**
+ * @brief Gets the recording audio format.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[out] rate The audio sampling rate
+ * @param[out] channel The audio channel
+ * @param[out] audio_type The audio type
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MA_ERROR_OPERATION_FAILED Operation failed
+ *
+ * @pre The state should be #MA_STATE_READY.
+ */
+int ma_get_recording_audio_format(int* rate, ma_audio_channel_e* channel, ma_audio_type_e* audio_type);
+
+/**
+ * @brief Sets a state changed callback.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_state_changed_cb()
+ * @see ma_unset_state_changed_cb()
+ */
+int ma_set_state_changed_cb(ma_state_changed_cb callback, void* user_data);
+
+/**
+ * @brief Unsets a state changed callback.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_state_changed_cb()
+ * @see ma_set_state_changed_cb()
+ */
+int ma_unset_state_changed_cb(void);
+
+/**
+ * @brief Sets an error callback.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_error_cb()
+ * @see ma_unset_errord_cb()
+ */
+int ma_set_error_cb(ma_error_cb callback, void* user_data);
+
+/**
+ * @brief Unsets an error callback.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_error_cb()
+ * @see ma_set_error_cb()
+ */
+int ma_unset_error_cb(void);
+
+/**
+ * @brief Sets a language changed callback.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_language_changed_cb()
+ * @see ma_unset_language_changed_cb()
+ */
+int ma_set_language_changed_cb(ma_language_changed_cb callback, void* user_data);
+
+/**
+ * @brief Unsets a language changed callback.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_language_changed_cb()
+ * @see ma_set_language_changed_cb()
+ */
+int ma_unset_language_changed_cb(void);
+
+/**
+ * @brief Sets an audio streaming callback.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_audio_streaming_cb()
+ * @see ma_unset_audio_streaming_cb()
+ */
+int ma_set_audio_streaming_cb(ma_audio_streaming_cb callback, void* user_data);
+
+/**
+ * @brief Unsets an audio streaming callback.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_audio_streaming_cb()
+ * @see ma_set_audio_streaming_cb()
+ */
+int ma_unset_audio_streaming_cb(void);
+
+/**
+ * @brief Sends ASR(auto speech recognition) results to the multi-assistant service.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[in] event The ASR result event (e.g. #MA_ASR_RESULT_EVENT_FINAL)
+ * @param[in] asr_result The ASR result text
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int ma_send_asr_result(ma_asr_result_event_e event, const char* asr_result);
+
+/**
+ * @brief Sends results to the multi-assistant service.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[in] display_text The text shown on the display
+ * @param[in] utterance_text The utterance text
+ * @param[in] result_json The result data (JSON format)
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int ma_send_result(const char* display_text, const char* utterance_text, const char* result_json);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __TIZEN_UIFW_MULTI_ASSISTANT_H__ */
--- /dev/null
+/**
+ * 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 __TIZEN_UIFW_MULTI_ASSISTANT_COMMON_H__
+#define __TIZEN_UIFW_MULTI_ASSISTANT_COMMON_H__
+
+#include <tizen.h>
+
+/**
+ * @addtogroup CAPI_UIX_MULTI_ASSISTANT_MODULE
+ * @{
+ */
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+/**
+ * @brief Enumerations for multi-assistant error codes.
+ * @since_tizen 5.0
+ */
+typedef enum {
+ MA_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+ MA_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of Memory */
+ MA_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */
+ MA_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ MA_ERROR_TIMED_OUT = TIZEN_ERROR_TIMED_OUT, /**< No answer from service */
+ MA_ERROR_RECORDER_BUSY = TIZEN_ERROR_RESOURCE_BUSY, /**< Busy recorder */
+ MA_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ MA_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Multi-assistant NOT supported */
+ MA_ERROR_INVALID_STATE = TIZEN_ERROR_MULTI_ASSISTANT | 0x011, /**< Invalid state */
+ MA_ERROR_INVALID_LANGUAGE = TIZEN_ERROR_MULTI_ASSISTANT | 0x012, /**< Invalid language */
+ MA_ERROR_ENGINE_NOT_FOUND = TIZEN_ERROR_MULTI_ASSISTANT | 0x013, /**< No available engine */
+ MA_ERROR_OPERATION_FAILED = TIZEN_ERROR_MULTI_ASSISTANT | 0x014, /**< Operation failed */
+ MA_ERROR_SERVICE_RESET = TIZEN_ERROR_MULTI_ASSISTANT | 0x015, /**< Service daemon reset */
+ MA_ERROR_NOT_SUPPORTED_FEATURE = TIZEN_ERROR_MULTI_ASSISTANT | 0x016 /**< Not supported feature of current engine */
+} ma_error_e;
+
+/**
+ * @brief Enumerations for multi-assistant client state.
+ * @since_tizen 5.0
+ */
+typedef enum {
+ MA_STATE_NONE = 0, /**< 'None' state */
+ MA_STATE_INITIALIZED = 1, /**< 'Initialized' state */
+ MA_STATE_READY = 2 /**< 'Ready' state */
+} ma_state_e;
+
+/**
+ * @brief Enumerations for multi-assistant audio streaming events.
+ * @since_tizen 5.0
+ */
+typedef enum {
+ MA_AUDIO_STREAMING_EVENT_FAIL = -1, /**< Failed */
+ MA_AUDIO_STREAMING_EVENT_START = 1, /**< Start event */
+ MA_AUDIO_STREAMING_EVENT_CONTINUE = 2, /**< Continue event */
+ MA_AUDIO_STREAMING_EVENT_FINISH = 3 /**< Finish event */
+} ma_audio_streaming_event_e;
+
+/**
+ * @brief Enumerations for audio types.
+ * @since_tizen 5.0
+ */
+typedef enum {
+ MA_AUDIO_TYPE_PCM_S16_LE = 0, /**< Signed 16bit audio type, Little endian */
+ MA_AUDIO_TYPE_PCM_U8 /**< Unsigned 8bit audio type */
+} ma_audio_type_e;
+
+/**
+ * @brief Enumerations for audio channels.
+ * @since_tizen 5.0
+ */
+typedef enum {
+ MA_AUDIO_CHANNEL_MONO = 0, /**< 1 channel, mono */
+ MA_AUDIO_CHANNEL_STEREO = 1 /**< 2 channels, stereo */
+} ma_audio_channel_e;
+
+/**
+ * @brief Enumerations for ASR result events.
+ * @since_tizen 5.0
+ */
+typedef enum {
+ MA_ASR_RESULT_EVENT_PARTIAL_RESULT = 0, /**< ASR result event for partial result */
+ MA_ASR_RESULT_EVENT_FINAL_RESULT, /**< ASR result event for final result */
+ MA_ASR_RESULT_EVENT_ERROR /**< ASR result event for error */
+} ma_asr_result_event_e;
+
+
+/**
+ * @brief Called when the client state is changed.
+ * @since_tizen 5.0
+ *
+ * @param[in] previous The previous state
+ * @param[in] current The current state
+ * @param[in] user_data The user data passed from the callback registration function
+ */
+typedef void (*ma_state_changed_cb)(ma_state_e previous, ma_state_e current, void* user_data);
+
+/**
+ * @brief Called when the error is occurred.
+ * @details The following error codes can be received: \n
+ * #MA_ERROR_NONE: Success \n
+ * #MA_ERROR_OUT_OF_MEMORY: Out of Memory \n
+ * #MA_ERROR_IO_ERROR: I/O error \n
+ * #MA_ERROR_INVALID_PARAMETER: Invalid parameter \n
+ * #MA_ERROR_TIMED_OUT: No answer from service \n
+ * #MA_ERROR_RECORDER_BUSY: Busy recorder \n
+ * #MA_ERROR_PERMISSION_DENIED: Permission denied \n
+ * #MA_ERROR_NOT_SUPPORTED: Multi-assistant NOT supported \n
+ * #MA_ERROR_INVALID_STATE: Invalid state \n
+ * #MA_ERROR_INVALID_LANGUAGE: Invalid language \n
+ * #MA_ERROR_ENGINE_NOT_FOUND: No available engine \n
+ * #MA_ERROR_OPERATION_FAILED: Operation failed \n
+ * #MA_ERROR_SERVICE_RESET: Service daemon reset \n
+ * #MA_ERROR_NOT_SUPPORTED_FEATURE: Not supported feature of current engine \n
+ * @since_tizen 5.0
+ *
+ * @param[in] reason The error reason
+ * @param[in] user_data The user data passed from the callback registration function
+ */
+typedef void (*ma_error_cb)(ma_error_e reason, void* user_data);
+
+/**
+ * @brief Called when the default language is changed.
+ * @since_tizen 5.0
+ * @remarks The @a previous can be used only in the callback. To use outside, make a copy.
+ * The @a current can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] previous The previous language
+ * @param[in] current The current language
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see ma_set_language_changed_cb()
+ * @see ma_unset_language_changed_cb()
+ */
+typedef void (*ma_language_changed_cb)(const char* previous, const char* current, void* user_data);
+
+/**
+ * @brief Called when the multi-assistant service sends audio streaming.
+ * @since_tizen 5.0
+ * @remarks The @a buffer should not be released and can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] event The audio streaming event
+ * @param[in] buffer The audio streaming data
+ * @param[in] len The length of the audio streaming data
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see ma_set_audio_streaming_cb()
+ * @see ma_unset_audio_streaming_cb()
+ */
+typedef void (*ma_audio_streaming_cb)(ma_audio_streaming_event_e event, char* buffer, int len, void* user_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __TIZEN_UIFW_MULTI_ASSISTANT_COMMON_H__ */
+
--- /dev/null
+/**
+ * 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 __TIZEN_UIFW_MULTI_ASSISTANT_UI_H__
+#define __TIZEN_UIFW_MULTI_ASSISTANT_UI_H__
+
+#include <multi_assistant_common.h>
+
+/**
+ * @addtogroup CAPI_UIX_MULTI_ASSISTANT_UI_MODULE
+ * @{
+ */
+
+/**
+ * @defgroup CAPI_UIX_MULTI_ASSISTANT_UI_MODULE Multi assistant UI
+ * @ingroup CAPI_UIX_MULTI_ASSISTANT_MODULE
+ * @brief The @ref CAPI_UIX_MULTI_ASSISTANT_UI_MODULE API provides functions for showing queries and responses sent from multi assistant service.
+ * @{
+ */
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/**
+ * @brief Called when the information of the assistants is requested.
+ * @since_tizen 5.0
+ * @remarks The @a app_id can be used only in the callback. To use outside, make a copy.
+ * The @a name can be used only in the callback. To use outside, make a copy.
+ * The @a icon_path can be used only in the callback. To use outside, make a copy.
+ * The @a wakeup_list can be used only in the callback. To use outside, make a copy.
+ * The @a supported_lang can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] app_id The app ID of the assistant
+ * @param[in] name The name of the assistant
+ * @param[in] icon_path The directory of the icon corresponding to the assistant
+ * @param[in] wakeup_list The list of wakeup words which invoke the assistant
+ * @param[in] cnt_wakeup The number of wakeup words
+ * @param[in] supported_lang The list of languages supported by the assistant
+ * @param[in] cnt_lang The number of languages supported by the assistant
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see ma_ui_foreach_assistant_info()
+ */
+typedef int (*ma_ui_assistant_info_cb)(const char* app_id, const char* name, const char* icon_path, const char* wakeup_list[], int cnt_wakeup, const char* supported_lang[], int cnt_lang, void* user_data);
+
+/**
+ * @brief Called when the multi-assistant service sends the ASR results for showing at UI.
+ * @since_tizen 5.0
+ * @remarks The @a asr_result can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] event The ASR result event
+ * @param[in] asr_result The ASR result text
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see ma_ui_set_asr_result_cb()
+ * @see ma_ui_unset_asr_result_cb()
+ */
+typedef void (*ma_ui_asr_result_cb)(ma_asr_result_event_e event, const char* asr_result, void* user_data);
+
+/**
+ * @brief Called when the multi-assistant service sends the results for showing at UI.
+ * @since_tizen 5.0
+ * @remarks The @a display_text can be used only in the callback. To use outside, make a copy.
+ * The @a utterance_text can be used only in the callback. To use outside, make a copy.
+ * The @a result_json can be used only in the callback. To use outside, make a copy.
+ *
+ * @param[in] display_text The text shown on the display
+ * @param[in] utterance_text The utterance text
+ * @param[in] result_json The result data (JSON format)
+ * @param[in] user_data The user data passed from the callback registration function
+ *
+ * @see ma_ui_set_asr_result_cb()
+ * @see ma_ui_unset_asr_result_cb()
+ */
+typedef void (*ma_ui_result_cb)(const char* display_text, const char* utterance_text, const char* result_json, void* user_data);
+
+
+/**
+ * @brief Initializes multi-assistant UI.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_OPERATION_FAILED Operation failed
+ * @retval #MA_ERROR_OUT_OF_MEMORY Out of memory
+ *
+ * @see ma_ui_deinitialize()
+ */
+int ma_ui_initialize(void);
+
+/**
+ * @brief Deinitializes multi-assistant UI.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @see ma_ui_initialize()
+ */
+int ma_ui_deinitialze(void);
+
+/**
+ * @brief Prepares multi-assistant UI.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @post If this function is called, the state will be #MA_STATE_READY.
+ * @see ma_ui_unprepare()
+ */
+int ma_ui_prepare(void);
+
+/**
+ * @brief Unprepares multi-assistant UI.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_READY.
+ * @post If this function is called, the state will be #MA_STATE_INITIALIZED.
+ * @see ma_ui_prepare()
+ */
+int ma_ui_unprepare(void);
+
+/**
+ * @brief Gets the current state of the multi-assistant UI.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[out] state The current state
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int ma_ui_get_state(ma_state_e* state);
+
+/**
+ * @brief Retreives the information for assistants.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[in] callback A callback for getting the information of the assistants
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see ma_ui_assistant_info_cb()
+ */
+int ma_ui_foreach_assistant_info(ma_ui_assistant_info_cb callback, void* user_data);
+
+/**
+ * @brief Sets the default assistant.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[in] app_id The app ID of the assistant
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ */
+int ma_ui_set_default_assistant(const char* app_id);
+
+/**
+ * @brief Changes the assistant.
+ * @since_tizen 5.0
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/recorder
+ *
+ * @param[in] app_id The app ID for the new assistant
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ */
+int ma_ui_change_assistant(const char* app_id);
+
+/**
+ * @brief Sets a state changed callback.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_state_changed_cb()
+ * @see ma_unset_state_changed_cb()
+ */
+int ma_ui_set_state_changed_cb(ma_state_changed_cb callback, void* user_data);
+
+/**
+ * @brief Unsets a state changed callback.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_state_changed_cb()
+ * @see ma_ui_set_state_changed_cb()
+ */
+int ma_ui_unset_state_changed_cb(void);
+
+/**
+ * @brief Sets an error callback.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_error_cb()
+ * @see ma_ui_unset_error_cb()
+ */
+int ma_ui_set_error_cb(ma_error_cb callback, void* user_data);
+
+/**
+ * @brief Unsets an error callback.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ * @see ma_error_cb()
+ * @see ma_ui_set_error_cb()
+ */
+int ma_ui_unset_error_cb(void);
+
+/**
+ * @brief Sets a callback for getting ASR result.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ */
+int ma_ui_set_asr_result_cb(ma_ui_asr_result_cb callback, void* user_data);
+
+/**
+ * @brief Unsets a callback for getting ASR result.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ */
+int ma_ui_unset_asr_result_cb(void);
+
+/**
+ * @brief Sets a callback for getting results.
+ * @since_tizen 5.0
+ *
+ * @param[in] callback The callback function
+ * @param[in] user_data The user data passed to the callback function
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ */
+int ma_ui_set_result_cb(ma_ui_result_cb callback, void* user_data);
+
+/**
+ * @brief Unsets a callback for getting results.
+ * @since_tizen 5.0
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #MA_ERROR_NONE Successful
+ * @retval #MA_ERROR_NOT_SUPPORTED Not supported
+ * @retval #MA_ERROR_INVALID_STATE Invalid state
+ *
+ * @pre The state should be #MA_STATE_INITIALIZED.
+ */
+int ma_ui_unset_result_cb(void);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* __TIZEN_UIFW_MULTI_ASSISTANT_UI_H__ */
+
--- /dev/null
+<?xml version="1.0"?>
+<multi-assistant-config>
+ <default-assistant>com.samsung.tizen.bixby-assistant</default-assistant>
+ <current-assistant>com.samsung.tizen.bixby-assistant</current-assistant>
+ <language>en_US</language>
+</multi-assistant-config>
--- /dev/null
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+<!-- root can own the service -->
+ <policy context="default">
+ <allow own_prefix="org.tizen.multiassistant.maclient"/>
+ <allow send_destination="org.tizen.multiassistant.maclient"/>
+
+ <allow own_prefix="org.tizen.multiassistant.mauiclient"/>
+ <allow send_destination="org.tizen.multiassistant.mauiclient"/>
+
+ <allow own="org.tizen.multiassistant.maserver"/>
+ <allow send_destination="org.tizen.multiassistant.maserver"/>
+ </policy>
+</busconfig>
--- /dev/null
+[D-BUS Service]
+Name=org.tizen.multiassistant.maclient
+#Exec=/usr/bin/vc-daemon
+Exec=/bin/sh -c "launch_app com.samsung.bixby-voice"
+#Exec=/bin/sh -c "vc_getengine get system db/voice/vc/engine/default | awk '{print$5}' | xargs -t -i launch_app {}"
--- /dev/null
+[D-BUS Service]
+Name=org.tizen.multiassistant.mauiclient
+#Exec=/usr/bin/vc-daemon
+Exec=/bin/sh -c "launch_app org.tizen.multi-assistant-panel"
+#Exec=/bin/sh -c "vc_getengine get system db/voice/vc/engine/default | awk '{print$5}' | xargs -t -i launch_app {}"
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_" />
+ </request>
+</manifest>
--- /dev/null
+Name: multi-assistant
+Summary: Multi Assistant client library and daemon
+Version: 0.0.1
+Release: 1
+Group: Graphics & UI Framework/Voice Framework
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source1001: %{name}.manifest
+Source1002: %{name}-devel.manifest
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+Requires: gawk
+BuildRequires: pkgconfig(capi-base-common)
+BuildRequires: pkgconfig(capi-media-audio-io)
+BuildRequires: pkgconfig(capi-media-sound-manager)
+BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-session)
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(ecore)
+BuildRequires: pkgconfig(ecore-wayland)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(json-glib-1.0)
+BuildRequires: pkgconfig(libgum)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(pkgmgr-installer)
+%if "%{tizen_profile_name}" == "tv"
+BuildRequires: pkgconfig(capi-network-bluetooth)
+BuildRequires: pkgconfig(capi-network-bluetooth-tv)
+BuildRequires: pkgconfig(msfapi)
+%endif
+BuildRequires: pkgconfig(vconf)
+BuildRequires: cmake
+
+%description
+Multi assistant client library and daemon
+
+
+%package devel
+Summary: Multi assistant header files for MA development
+Group: libdevel
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Multi assistant header files for MA development.
+
+
+%package ui-devel
+Summary: Multi assistant manager header files for MA development
+Group: libdevel
+Requires: %{name} = %{version}-%{release}
+
+%description ui-devel
+Multi assistant manager header files for MA development.
+
+
+%prep
+%setup -q -n %{name}-%{version}
+cp %{SOURCE1001} %{SOURCE1002} .
+
+
+%build
+%if "%{tizen_profile_name}" == "tv"
+export CFLAGS="$CFLAGS -DTV_PRODUCT"
+cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DBINDIR=%{_bindir} -DINCLUDEDIR=%{_includedir} \
+ -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE -D_TV_PRODUCT=TRUE -DTZ_SYS_BIN=%TZ_SYS_BIN
+%else
+cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DBINDIR=%{_bindir} -DINCLUDEDIR=%{_includedir} \
+ -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE -DTZ_SYS_BIN=%TZ_SYS_BIN
+%endif
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+
+%make_install
+
+%post
+/sbin/ldconfig
+
+mkdir -p %{_libdir}/multiassistant/ma
+
+%postun -p /sbin/ldconfig
+
+%files
+%license LICENSE
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libma.so
+%{_libdir}/libma_ui.so
+%{TZ_SYS_RO_SHARE}/multiassistant/ma/1.0/ma-config.xml
+%{TZ_SYS_RO_SHARE}/dbus-1/services/org.tizen.multiassistant*
+/etc/dbus-1/session.d/ma-server.conf
+
+%files devel
+%manifest %{name}-devel.manifest
+%defattr(-,root,root,-)
+%{_libdir}/pkgconfig/multi-assistant.pc
+%{_includedir}/multi_assistant.h
+%{_includedir}/multi_assistant_ui.h
+%{_includedir}/multi_assistant_common.h
+
+%files ui-devel
+%defattr(-,root,root,-)
+%{_libdir}/pkgconfig/multi-assistant-ui.pc
+%{_includedir}/multi_assistant_ui.h
+%{_includedir}/multi_assistant_common.h
+
+
--- /dev/null
+SET(SRCS
+# mad_server.c
+# mae.c
+)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
+INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include)
+
+FOREACH(flag ${pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+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")
+
+## Executable ##
+ADD_LIBRARY("${PROJECT_NAME}_engine" SHARED ${SRCS})
+TARGET_LINK_LIBRARIES("${PROJECT_NAME}_engine" -ldl ${pkgs_LDFLAGS})
+
+## Install
+INSTALL(TARGETS "${PROJECT_NAME}_engine" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries)