From 92a2891dbd1510a5bea35cecd624b5e36ca9d792 Mon Sep 17 00:00:00 2001 From: "ky85.kim" Date: Thu, 11 Jun 2015 19:16:03 +0900 Subject: [PATCH 02/11] Init commit from tizen 2.4 Change-Id: I9bdeee67d63fb2fedf5ea77944bf8f7000c88ba6 --- AUTHORS | 4 + CMakeLists.txt | 55 + LICENSE | 202 ++ NOTICE | 3 + changelog | 118 + client/CMakeLists.txt | 66 + client/vc.c | 1925 ++++++++++++++++ client/vc_client.c | 695 ++++++ client/vc_client.h | 127 ++ client/vc_dbus.c | 1194 ++++++++++ client/vc_dbus.h | 67 + client/vc_mgr.c | 2131 ++++++++++++++++++ client/vc_mgr_client.c | 912 ++++++++ client/vc_mgr_client.h | 138 ++ client/vc_mgr_dbus.c | 1487 ++++++++++++ client/vc_mgr_dbus.h | 68 + client/vc_setting.c | 398 ++++ client/vc_widget.c | 1330 +++++++++++ client/vc_widget_client.c | 628 ++++++ client/vc_widget_client.h | 114 + client/vc_widget_dbus.c | 754 +++++++ client/vc_widget_dbus.h | 51 + common/vc_command.c | 775 +++++++ common/vc_command.h | 141 ++ common/vc_config_mgr.c | 1654 ++++++++++++++ common/vc_config_mgr.h | 108 + common/vc_config_parser.c | 1085 +++++++++ common/vc_config_parser.h | 82 + common/vc_defs.h | 171 ++ common/vc_info_parser.c | 1611 +++++++++++++ common/vc_info_parser.h | 86 + common/vc_main.h | 60 + doc/doxyfile | 2373 ++++++++++++++++++++ ...api_uix_voice_control_service_state_diagram.png | Bin 0 -> 25657 bytes .../capi_uix_voice_control_state_diagram.png | Bin 0 -> 18945 bytes doc/uix_vc_doc.h | 199 ++ include/CMakeLists.txt | 25 + include/voice-control-engine.pc.in | 10 + include/voice-control-manager.pc.in | 10 + include/voice-control-setting.pc.in | 10 + include/voice-control-widget.pc.in | 10 + include/voice-control.pc.in | 10 + include/voice_control.h | 494 ++++ include/voice_control_authority.h | 188 ++ include/voice_control_command.h | 379 ++++ include/voice_control_command_expand.h | 141 ++ include/voice_control_common.h | 184 ++ include/voice_control_key_defines.h | 130 ++ include/voice_control_manager.h | 685 ++++++ include/voice_control_plugin_engine.h | 516 +++++ include/voice_control_setting.h | 245 ++ include/voice_control_widget.h | 527 +++++ packaging/voice-control-devel.manifest | 5 + packaging/voice-control.manifest | 5 + packaging/voice-control.spec | 157 ++ server/CMakeLists.txt | 33 + server/vcd_client_data.c | 1359 +++++++++++ server/vcd_client_data.h | 156 ++ server/vcd_config.c | 124 + server/vcd_config.h | 49 + server/vcd_dbus.c | 635 ++++++ server/vcd_dbus.h | 55 + server/vcd_dbus_server.c | 1441 ++++++++++++ server/vcd_dbus_server.h | 103 + server/vcd_engine_agent.c | 916 ++++++++ server/vcd_engine_agent.h | 89 + server/vcd_main.c | 86 + server/vcd_main.h | 86 + server/vcd_recorder.c | 650 ++++++ server/vcd_recorder.h | 61 + server/vcd_server.c | 1256 +++++++++++ server/vcd_server.h | 106 + vc-config.xml | 7 + 73 files changed, 31755 insertions(+) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 NOTICE create mode 100644 changelog create mode 100644 client/CMakeLists.txt create mode 100644 client/vc.c create mode 100644 client/vc_client.c create mode 100644 client/vc_client.h create mode 100644 client/vc_dbus.c create mode 100644 client/vc_dbus.h create mode 100644 client/vc_mgr.c create mode 100644 client/vc_mgr_client.c create mode 100644 client/vc_mgr_client.h create mode 100644 client/vc_mgr_dbus.c create mode 100644 client/vc_mgr_dbus.h create mode 100644 client/vc_setting.c create mode 100644 client/vc_widget.c create mode 100644 client/vc_widget_client.c create mode 100644 client/vc_widget_client.h create mode 100644 client/vc_widget_dbus.c create mode 100644 client/vc_widget_dbus.h create mode 100644 common/vc_command.c create mode 100644 common/vc_command.h create mode 100644 common/vc_config_mgr.c create mode 100644 common/vc_config_mgr.h create mode 100644 common/vc_config_parser.c create mode 100644 common/vc_config_parser.h create mode 100644 common/vc_defs.h create mode 100644 common/vc_info_parser.c create mode 100644 common/vc_info_parser.h create mode 100644 common/vc_main.h create mode 100644 doc/doxyfile create mode 100644 doc/images/capi_uix_voice_control_service_state_diagram.png create mode 100644 doc/images/capi_uix_voice_control_state_diagram.png create mode 100644 doc/uix_vc_doc.h create mode 100644 include/CMakeLists.txt create mode 100644 include/voice-control-engine.pc.in create mode 100644 include/voice-control-manager.pc.in create mode 100644 include/voice-control-setting.pc.in create mode 100644 include/voice-control-widget.pc.in create mode 100644 include/voice-control.pc.in create mode 100644 include/voice_control.h create mode 100644 include/voice_control_authority.h create mode 100644 include/voice_control_command.h create mode 100644 include/voice_control_command_expand.h create mode 100644 include/voice_control_common.h create mode 100644 include/voice_control_key_defines.h create mode 100644 include/voice_control_manager.h create mode 100644 include/voice_control_plugin_engine.h create mode 100644 include/voice_control_setting.h create mode 100644 include/voice_control_widget.h create mode 100644 packaging/voice-control-devel.manifest create mode 100644 packaging/voice-control.manifest create mode 100644 packaging/voice-control.spec create mode 100644 server/CMakeLists.txt create mode 100644 server/vcd_client_data.c create mode 100644 server/vcd_client_data.h create mode 100644 server/vcd_config.c create mode 100644 server/vcd_config.h create mode 100644 server/vcd_dbus.c create mode 100644 server/vcd_dbus.h create mode 100644 server/vcd_dbus_server.c create mode 100644 server/vcd_dbus_server.h create mode 100644 server/vcd_engine_agent.c create mode 100644 server/vcd_engine_agent.h create mode 100644 server/vcd_main.c create mode 100644 server/vcd_main.h create mode 100644 server/vcd_recorder.c create mode 100644 server/vcd_recorder.h create mode 100644 server/vcd_server.c create mode 100644 server/vcd_server.h create mode 100644 vc-config.xml diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..39d4ccc --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Dongyeol Lee +Kwangyoun Kim +Sehwan Park +WonNam Jang diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4807bfb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 2011-2015 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 Dongyeol Lee (dy3.lee@samsung.com) +# @version 0.1 +# @brief + +# Check minimum CMake version +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +# Project name +PROJECT(vc) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}") +SET(VERSION 0.2.7) + +# pkg config tool +INCLUDE(FindPkgConfig) + +## Include common directory ## +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/common") +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include") + +## Dependent packages ## +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + aul capi-base-common capi-media-audio-io capi-media-sound-manager capi-network-bluetooth + dbus-1 dlog ecore ecore-x glib-2.0 libprivilege-control libxml-2.0 vconf +) + +## API ## +ADD_SUBDIRECTORY(include) + +## Client library ## +ADD_SUBDIRECTORY(client) + +## Server daemon ## +ADD_SUBDIRECTORY(server) + +## config ## +INSTALL(FILES ${CMAKE_SOURCE_DIR}/vc-config.xml DESTINATION /usr/lib/voice/vc/1.0) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + 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. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..9424bf6 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +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. diff --git a/changelog b/changelog new file mode 100644 index 0000000..fa7af77 --- /dev/null +++ b/changelog @@ -0,0 +1,118 @@ +vc (0.2.7) -- Wed, 21 Jan 2015 + + * Add result message from engine (Wonnam Jang ) + * Change sequence for engine and recorder stop (Kwangyoun Kim ) + * Add authority feature (Kwangyoun Kim ) + +vc (0.2.6) -- Mon, 08 Dec 2014 + + * Update API (Dongyeol Lee ) + * Support Multi-results (Dongyeol Lee ) + * Improve command structure (Dongyeol Lee ) + * Add cancel by sound interrupt (Dongyeol Lee ) + +vc (0.2.5) -- Thu, 20 Sep 2014 + + * Add audio session (Dongyeol Lee ) + * Add new list command APIs (Dongyeol Lee ) + * Update command operation (Dongyeol Lee ) + * Apply list api for clients (Dongyeol Lee ) + +vc (0.2.4) -- Mon, 11 Aug 2014 + + * Add audio in type selection (Dongyeol Lee ) + * Add retry code for info files (Dongyeol Lee ) + * Add console app (Kwangyoun Kim ) + +vc (0.2.3) -- Thu, 24 Jul 2014 + + * Fix recognition cancel bug (Dongyeol Lee ) + +vc (0.2.2) -- Thu, 03 Jul 2014 + + * Update engine API for silence (Dongyeol Lee ) + * Support only text result (Dongyeol Lee ) + * Fix bug on default config valid check (Kwangyoun Kim ) + * Fix security issue (Kwangyoun Kim ) + +vc (0.2.1) -- Wed, 28 May 2014 + + * Fix crash issue of result (Dongyeol Lee ) + * Fix multi-language bug (Dongyeol Lee ) + * Update test app for multi-language (Dongyeol Lee ) + * Apply exclusive option (Kwangyoun Kim ) + +vc (0.2.0) -- Fri, 23 May 2014 + + * Add manager client(Dongyeol Lee ) + * Support to select conflict results by manager (Dongyeol Lee ) + * Support to add rule of client recognition request (Dongyeol Lee ) + * Update widget result callback (Dongyeol Lee ) + * Add sevice state (Dongyeol Lee ) + * Update XML file of runtime command and info(Dongyeol Lee ) + * Add exclusive command option (Dongyeol Lee ) + * Add system command group and remove interrupt command group (Dongyeol Lee ) + * Add non-fixed command type (Dongyeol Lee ) + * Remove trigger mode (Dongyeol Lee ) + * Remove wakeup command (Dongyeol Lee ) + * Remove speech-to-text feature (Dongyeol Lee ) + * Remove floating button (Dongyeol Lee ) + +vc (0.1.3-11) -- Fri, 07 Feb 2013 + + * Support wakeup command (Dongyeol Lee ) + * Support speech-to-text feature (Dongyeol Lee ) + * Add test application for voice control (Kwangyoun Kim ) + * Clean up CMakeList (Dongyeol Lee ) + +vc (0.1.3-10) -- Wed, 16 Oct 2013 + + * Clean up code (Dongyeol Lee ) + +vc (0.1.3-9) -- Tue, 10 Sep 2013 + + * Fix bug on floating button state (Kwangyoun Kim ) + +vc (0.1.3-8) -- Fri, 09 Aug 2013 + + * Add new trigger both floating button and continuous recongtion (Dongyeol Lee ) + +vc (0.1.3-7) -- Thu, 25 Jul 2013 + + * Fix to change to get commands from client (Dongyeol Lee ) + +vc (0.1.3-6) -- Tue, 09 Apr 2013 + + * Fix bug of request set command (Kwangyoun Kim ) + +vc (0.1.3-5) -- Thu, 04 Apr 2013 + + * Fix bug of recording fail (Dongyeol Lee ) + +vc (0.1.3-4) -- Wed, 03 Apr 2013 + + * Add time out in recording (Dongyeol Lee ) + +vc (0.1.3-3) -- Wed, 03 Apr 2013 + + * Add mute sound in recording state (Dongyeol Lee ) + +vc (0.1.3-2) -- Wed, 27 Mar 2013 + + * Fix bs issue to tranfer command from client to server (Dongyeol Lee ) + +vc (0.1.3-1) -- Thu, 14 Mar 2013 + + * Support key generation (Dongyeol Lee ) + +vc (0.1.3) -- Fri, 08 Mar 2013 + + * Support multi-language command (Dongyeol Lee ) + +vc (0.1.2) -- Thu, 28 Feb 2013 + + * Upload initial version (Kwangyoun Kim ) + +vc (0.1.1) -- Thu, 26 Apr 2012 + + * Initial Release (Dongyeol Lee ) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000..33c0e15 --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,66 @@ +SET(SRCS + vc.c + vc_client.c + vc_dbus.c + ../common/vc_command.c + ../common/vc_config_mgr.c + ../common/vc_config_parser.c + ../common/vc_info_parser.c +) + +SET(SETTING_SRCS + vc_setting.c + ../common/vc_config_mgr.c + ../common/vc_config_parser.c +) + +SET(WIDGET_SRCS + vc_widget.c + vc_widget_client.c + vc_widget_dbus.c + ../common/vc_command.c + ../common/vc_config_mgr.c + ../common/vc_config_parser.c + ../common/vc_info_parser.c +) + +SET(MANAGER_SRCS + vc_mgr.c + vc_mgr_client.c + vc_mgr_dbus.c + ../common/vc_command.c + ../common/vc_config_mgr.c + ../common/vc_config_parser.c + ../common/vc_info_parser.c +) + +#INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +#INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) +#INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +## voice control library ## +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) + +## voice control setting library ## +ADD_LIBRARY("${PROJECT_NAME}_setting" SHARED ${SETTING_SRCS}) +TARGET_LINK_LIBRARIES("${PROJECT_NAME}_setting" ${pkgs_LDFLAGS}) + +## voice control widget library ## +ADD_LIBRARY("${PROJECT_NAME}_widget" SHARED ${WIDGET_SRCS}) +TARGET_LINK_LIBRARIES("${PROJECT_NAME}_widget" ${pkgs_LDFLAGS}) + +## voice control manager library ## +ADD_LIBRARY("${PROJECT_NAME}_manager" SHARED ${MANAGER_SRCS}) +TARGET_LINK_LIBRARIES("${PROJECT_NAME}_manager" ${pkgs_LDFLAGS}) + +## Install library files ## +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries) +INSTALL(TARGETS "${PROJECT_NAME}_setting" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries) +INSTALL(TARGETS "${PROJECT_NAME}_widget" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries) +INSTALL(TARGETS "${PROJECT_NAME}_manager" DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries) diff --git a/client/vc.c b/client/vc.c new file mode 100644 index 0000000..a513569 --- /dev/null +++ b/client/vc.c @@ -0,0 +1,1925 @@ +/* +* Copyright (c) 2011-2015 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 "vc_client.h" +#include "vc_command.h" +#include "vc_config_mgr.h" +#include "vc_dbus.h" +#include "vc_info_parser.h" +#include "vc_main.h" +#include "voice_control.h" +#include "voice_control_authority.h" +#include "voice_control_command.h" +#include "voice_control_command_expand.h" + + +static bool g_is_daemon_started = false; + +static Ecore_Timer* g_connect_timer = NULL; + +static vc_h g_vc = NULL; + +static Ecore_Event_Handler* g_focus_in_hander = NULL; +static Ecore_Event_Handler* g_focus_out_hander = NULL; + +Eina_Bool __vc_notify_state_changed(void *data); +Eina_Bool __vc_notify_error(void *data); + + +static const char* __vc_get_error_code(vc_error_e err) +{ + switch(err) { + case VC_ERROR_NONE: return "VC_ERROR_NONE"; break; + case VC_ERROR_OUT_OF_MEMORY: return "VC_ERROR_OUT_OF_MEMORY"; break; + case VC_ERROR_IO_ERROR: return "VC_ERROR_IO_ERROR"; break; + case VC_ERROR_INVALID_PARAMETER: return "VC_ERROR_INVALID_PARAMETER"; break; + case VC_ERROR_TIMED_OUT: return "VC_ERROR_TIMED_OUT"; break; + case VC_ERROR_RECORDER_BUSY: return "VC_ERROR_RECORDER_BUSY"; break; + case VC_ERROR_INVALID_STATE: return "VC_ERROR_INVALID_STATE"; break; + case VC_ERROR_INVALID_LANGUAGE: return "VC_ERROR_INVALID_LANGUAGE"; break; + case VC_ERROR_ENGINE_NOT_FOUND: return "VC_ERROR_ENGINE_NOT_FOUND"; break; + case VC_ERROR_OPERATION_FAILED: return "VC_ERROR_OPERATION_FAILED"; break; + default: return "Invalid error code"; break; + } + return NULL; +} + +static int __vc_convert_config_error_code(vc_config_error_e code) +{ + if (code == VC_CONFIG_ERROR_NONE) return VC_ERROR_NONE; + if (code == VC_CONFIG_ERROR_OUT_OF_MEMORY) return VC_ERROR_OUT_OF_MEMORY; + if (code == VC_CONFIG_ERROR_IO_ERROR) return VC_ERROR_IO_ERROR; + if (code == VC_CONFIG_ERROR_INVALID_PARAMETER) return VC_ERROR_INVALID_PARAMETER; + if (code == VC_CONFIG_ERROR_INVALID_STATE) return VC_ERROR_INVALID_STATE; + if (code == VC_CONFIG_ERROR_INVALID_LANGUAGE) return VC_ERROR_INVALID_LANGUAGE; + if (code == VC_CONFIG_ERROR_ENGINE_NOT_FOUND) return VC_ERROR_ENGINE_NOT_FOUND; + if (code == VC_CONFIG_ERROR_OPERATION_FAILED) return VC_ERROR_OPERATION_FAILED; + + return VC_ERROR_NONE; +} + +static void __vc_lang_changed_cb(const char* before_lang, const char* current_lang) +{ + SECURE_SLOG(LOG_DEBUG, TAG_VCC, "Lang changed : Before lang(%s) Current lang(%s)", + before_lang, current_lang); + + vc_current_language_changed_cb callback; + void* lang_user_data; + vc_client_get_current_lang_changed_cb(g_vc, &callback, &lang_user_data); + + if (NULL != callback) { + vc_client_use_callback(g_vc); + callback(before_lang, current_lang, lang_user_data); + vc_client_not_use_callback(g_vc); + SLOG(LOG_DEBUG, TAG_VCC, "Language changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] Language changed callback is null"); + } + + return; +} + +static void __vc_service_state_changed_cb(int before_state, int current_state) +{ + SLOG(LOG_DEBUG, TAG_VCC, "Service State changed : Before(%d) Current(%d)", + before_state, current_state); + + /* Save service state */ + vc_client_set_service_state(g_vc, (vc_service_state_e)current_state); + + vc_service_state_changed_cb service_callback = NULL; + void* service_user_data; + vc_client_get_service_state_changed_cb(g_vc, &service_callback, &service_user_data); + + if (NULL != service_callback) { + vc_client_use_callback(g_vc); + service_callback((vc_service_state_e)before_state, (vc_service_state_e)current_state, service_user_data); + vc_client_not_use_callback(g_vc); + SLOG(LOG_DEBUG, TAG_VCC, "Service state changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] State changed callback is NULL"); + } + + return; +} + +int vc_initialize() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Initialize"); + + /* check handle */ + if (true == vc_client_is_valid(g_vc)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Already initialized"); + return VC_ERROR_INVALID_STATE; + } + + if (0 < vc_client_get_count()) { + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] Already initialized"); + return VC_ERROR_INVALID_STATE; + } + + if (0 != vc_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to open connection"); + return VC_ERROR_OPERATION_FAILED; + } + + if (0 != vc_client_create(&g_vc)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to create client!!!!!"); + return VC_ERROR_OUT_OF_MEMORY; + } + + int ret = vc_config_mgr_initialize(g_vc->handle); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to init config manager : %s", + __vc_get_error_code(__vc_convert_config_error_code(ret))); + vc_client_destroy(g_vc); + return __vc_convert_config_error_code(ret); + } + + ret = vc_config_mgr_set_lang_cb(g_vc->handle, __vc_lang_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set config changed : %d", ret); + vc_config_mgr_finalize(g_vc->handle); + vc_client_destroy(g_vc); + return __vc_convert_config_error_code(ret); + } + + ret = vc_config_mgr_set_service_state_cb(g_vc->handle, __vc_service_state_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set service change callback : %d", ret); + vc_config_mgr_unset_lang_cb(g_vc->handle); + vc_config_mgr_finalize(g_vc->handle); + vc_client_destroy(g_vc); + return __vc_convert_config_error_code(ret); + } + + int service_state = -1; + if (0 != vc_config_mgr_get_service_state(&service_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get service state"); + vc_config_mgr_finalize(g_vc->handle); + vc_client_destroy(g_vc); + return __vc_convert_config_error_code(ret); + } + + vc_client_set_service_state(g_vc, service_state); + + SLOG(LOG_DEBUG, TAG_VCC, "[Success] pid(%d)", g_vc->handle); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + +static void __vc_internal_unprepare() +{ + /* return authority */ + vc_auth_state_e state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get auth state"); + } + + if (VC_AUTH_STATE_NONE != state) { + if (0 != vc_auth_disable()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to auth disable"); + } + } + + int ret = vc_dbus_request_finalize(g_vc->handle); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request finalize : %s", __vc_get_error_code(ret)); + } + + g_is_daemon_started = false; + + ecore_event_handler_del(g_focus_in_hander); + ecore_event_handler_del(g_focus_out_hander); + + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_FOREGROUND); + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_BACKGROUND); + + return; +} + +int vc_deinitialize() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Deinitialize"); + + if (false == vc_client_is_valid(g_vc)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NOT initialized"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + vc_state_e state; + vc_client_get_client_state(g_vc, &state); + + /* check state */ + switch (state) { + case VC_STATE_READY: + __vc_internal_unprepare(); + /* no break. need to next step*/ + case VC_STATE_INITIALIZED: + if (NULL != g_connect_timer) { + SLOG(LOG_DEBUG, TAG_VCC, "Connect Timer is deleted"); + ecore_timer_del(g_connect_timer); + } + + vc_config_mgr_unset_service_state_cb(g_vc->handle); + vc_config_mgr_unset_lang_cb(g_vc->handle); + vc_config_mgr_finalize(g_vc->handle); + + /* Free client resources */ + vc_client_destroy(g_vc); + g_vc = NULL; + break; + case VC_STATE_NONE: + break; + default: + break; + } + + SLOG(LOG_DEBUG, TAG_VCC, "Success: destroy"); + + if (0 != vc_dbus_close_connection()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to close connection"); + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + +static Eina_Bool __notify_auth_changed_cb(void *data) +{ + vc_auth_state_changed_cb callback = NULL; + void* user_data; + + vc_client_get_auth_state_changed_cb(g_vc, &callback, &user_data); + + vc_auth_state_e before = -1; + vc_auth_state_e current = -1; + + vc_client_get_before_auth_state(g_vc, &before, ¤t); + + if (NULL != callback) { + vc_client_use_callback(g_vc); + callback(before, current, user_data); + vc_client_not_use_callback(g_vc); + SLOG(LOG_DEBUG, TAG_VCC, "Auth state changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] Auth state changed callback is null"); + } + + return EINA_FALSE; + + +} + +static Eina_Bool __vc_x_event_window_focus_in(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Focus_In *e; + + e = event; + + int xid = -1; + if (0 != vc_client_get_xid(g_vc, &xid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get current xid"); + return ECORE_CALLBACK_PASS_ON; + } + + if (e->win == (Ecore_X_Window)xid) { + SLOG(LOG_DEBUG, TAG_VCC, "Focus in : pid(%d) xid(%d)", getpid(), xid); + int ret = vc_config_mgr_set_foreground(getpid(), true); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set focus in : %s", __vc_get_error_code(ret)); + } + /* set authority valid */ + vc_auth_state_e state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get auth state"); + } + if (VC_AUTH_STATE_INVALID == state) { + vc_client_set_auth_state(g_vc, VC_AUTH_STATE_VALID); + + /* notify auth changed cb */ + ecore_timer_add(0, __notify_auth_changed_cb, NULL); + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool __vc_x_event_window_focus_out(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Focus_In *e; + + e = event; + + int xid = -1; + if (0 != vc_client_get_xid(g_vc, &xid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get current xid"); + return ECORE_CALLBACK_PASS_ON; + } + + if (e->win == (Ecore_X_Window)xid) { + SLOG(LOG_DEBUG, TAG_VCC, "Focus out : pid(%d) xid(%d)", getpid(), xid); + int ret = vc_config_mgr_set_foreground(getpid(), false); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set focus out : %s", __vc_get_error_code(ret)); + } + /* set authority valid */ + vc_auth_state_e state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get auth state"); + } + if (VC_AUTH_STATE_VALID == state) { + vc_client_set_auth_state(g_vc, VC_AUTH_STATE_INVALID); + + /* notify authority changed cb */ + ecore_timer_add(0, __notify_auth_changed_cb, NULL); + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +static void __vc_fork_vc_daemon() +{ + int pid, i; + pid = fork(); + + switch(pid) { + case -1: + SLOG(LOG_ERROR, TAG_VCC, "Fail to create daemon"); + break; + case 0: + setsid(); + for (i = 0;i < _NSIG;i++) + signal(i, SIG_DFL); + + execl(VC_DAEMON_PATH, VC_DAEMON_PATH, NULL); + break; + default: + break; + } + return; +} + +static Eina_Bool __vc_connect_daemon(void *data) +{ + /* Send hello */ + if (0 != vc_dbus_request_hello()) { + if (false == g_is_daemon_started) { + g_is_daemon_started = true; + __vc_fork_vc_daemon(); + } + return EINA_TRUE; + } + + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Connect daemon"); + + /* request initialization */ + int ret = -1; + int mgr_pid = -1; + ret = vc_dbus_request_initialize(g_vc->handle, &mgr_pid); + if (VC_ERROR_ENGINE_NOT_FOUND == ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to initialize : %s", __vc_get_error_code(ret)); + + vc_client_set_error(g_vc, VC_ERROR_ENGINE_NOT_FOUND); + ecore_timer_add(0, __vc_notify_error, g_vc); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return EINA_FALSE; + + } else if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to initialize :%s", __vc_get_error_code(ret)); + + vc_client_set_error(g_vc, VC_ERROR_TIMED_OUT); + ecore_timer_add(0, __vc_notify_error, g_vc); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return EINA_FALSE; + } else { + /* Success to connect */ + } + + g_connect_timer = NULL; + + g_focus_in_hander = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, __vc_x_event_window_focus_in, NULL); + g_focus_out_hander = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, __vc_x_event_window_focus_out, NULL); + + vc_client_set_client_state(g_vc, VC_STATE_READY); + ecore_timer_add(0, __vc_notify_state_changed, g_vc); + + vc_client_set_mgr_pid(g_vc, mgr_pid); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return EINA_FALSE; +} + +int vc_prepare() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Prepare"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'CREATED'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + g_is_daemon_started = false; + + g_connect_timer = ecore_timer_add(0, __vc_connect_daemon, NULL); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + +int vc_unprepare() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Unprepare"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + __vc_internal_unprepare(); + + vc_client_set_client_state(g_vc, VC_STATE_INITIALIZED); + ecore_timer_add(0, __vc_notify_state_changed, g_vc); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + +int vc_foreach_supported_languages(vc_supported_language_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Foreach Supported Language"); + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_config_mgr_get_language_list(callback, user_data); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get languages : %s", __vc_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + + +int vc_get_current_language(char** language) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Get Current Language"); + + if (NULL == language) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_config_mgr_get_default_language(language); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get current languages : %s", __vc_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_get_state(vc_state_e* state) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Get State"); + + if (NULL == state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e temp; + if (0 != vc_client_get_client_state(g_vc, &temp)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + *state = temp; + + switch(*state) { + case VC_STATE_NONE: SLOG(LOG_DEBUG, TAG_VCC, "Current state is 'None'"); break; + case VC_STATE_INITIALIZED: SLOG(LOG_DEBUG, TAG_VCC, "Current state is 'Created'"); break; + case VC_STATE_READY: SLOG(LOG_DEBUG, TAG_VCC, "Current state is 'Ready'"); break; + default: SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid state"); break; + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + +int vc_get_service_state(vc_service_state_e* state) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Get Service State"); + + if (NULL == state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e temp; + if (0 != vc_client_get_client_state(g_vc, &temp)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* get service state */ + vc_service_state_e service_state; + if (0 != vc_client_get_service_state(g_vc, &service_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get service state"); + return VC_ERROR_OPERATION_FAILED; + } + + *state = service_state; + + switch(*state) { + case VC_SERVICE_STATE_NONE: SLOG(LOG_DEBUG, TAG_VCC, "Current service state is 'None'"); break; + case VC_SERVICE_STATE_READY: SLOG(LOG_DEBUG, TAG_VCC, "Current service state is 'Ready'"); break; + case VC_SERVICE_STATE_RECORDING: SLOG(LOG_DEBUG, TAG_VCC, "Current service state is 'Recording'"); break; + case VC_SERVICE_STATE_PROCESSING: SLOG(LOG_DEBUG, TAG_VCC, "Current service state is 'Processing'"); break; + default: SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid state"); break; + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} + +#if 0 +int vc_set_window_id(int wid) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Set Window id"); + + if (0 >= wid) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is invalid"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + if (0 != vc_client_set_xid(g_vc, wid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check if current xid is top window */ + int ret = -1; + if ((Ecore_X_Window)wid == ecore_x_window_focus_get()) { + /* Set current pid */ + ret = vc_config_mgr_set_foreground(getpid(), true); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set focus in : %s", __vc_get_error_code(ret)); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_get_window_id(int* wid) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Get Window id"); + + if (NULL == wid) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + if (0 != vc_client_get_xid(g_vc, wid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} +#endif + +/** +* @brief Checks whether the command format is supported. +* @since_tizen 2.4 +* +* @param[in] format The command format +* @param[out] support The result status @c true = supported, @c false = not supported +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_ERROR_NONE Successful +* @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #VC_ERROR_OPERATION_FAILED Operation failure +* @retval #VC_ERROR_INVALID_STATE Invalid state +* +* @pre The state should be #VC_STATE_READY. +*/ +#if 0 +int vc_is_command_format_supported(vc_cmd_format_e format, bool* support) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Is command format supported"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check support */ + bool non_fixed_support = false; + if (0 != vc_config_mgr_get_nonfixed_support(&non_fixed_support)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get nonfixed support info"); + } + + switch (format) { + case VC_CMD_FORMAT_FIXED: *support = true; break; + case VC_CMD_FORMAT_FIXED_AND_EXTRA: *support = non_fixed_support; break; + case VC_CMD_FORMAT_EXTRA_AND_FIXED: *support = non_fixed_support; break; + default: *support = false; break; + } + + SLOG(LOG_ERROR, TAG_VCC, "[DEBUG] Format(%d) support(%s)", format, *support ? "true" : "false"); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return VC_ERROR_NONE; +} +#endif + +int vc_set_command_list(vc_cmd_list_h vc_cmd_list, int type) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Set Command list"); + + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check type */ + if ((VC_COMMAND_TYPE_FOREGROUND != type) && (VC_COMMAND_TYPE_BACKGROUND != type)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid command type: input type is %d", type); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + int ret = 0; + if (0 != vc_cmd_parser_save_file(getpid(), (vc_cmd_type_e)type, list->list)) { + ret = VC_ERROR_INVALID_PARAMETER; + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to save command list : %s", __vc_get_error_code(ret)); + } else { + int count = 0; + do { + ret = vc_dbus_request_set_command(g_vc->handle, (vc_cmd_type_e)type); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request set command to daemon : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request set command : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } + } while(0 != ret); + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_unset_command_list(int type) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Unset Command list"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int count = 0; + int ret = -1; + while (0 != ret) { + ret = vc_dbus_request_unset_command(g_vc->handle, (vc_cmd_type_e)type); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request unset command to daemon : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request unset command : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } + } + + ret = vc_cmd_parser_delete_file(getpid(), (vc_cmd_type_e)type); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] cmd_type(%d), Fail to delete command list : %s", type, __vc_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +#if 0 +int vc_get_exclusive_command_option(bool* value) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Get exclusive command"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = vc_client_get_exclusive_cmd(g_vc, value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set exclusive option : %d", ret); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return ret; + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_set_exclusive_command_option(bool value) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Set exclusive command"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = vc_client_set_exclusive_cmd(g_vc, value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set exclusive option : %d", ret); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return ret; + } + + /* Check if current xid is top window */ + int count = 0; + do { + ret = vc_dbus_request_set_exclusive_command(g_vc->handle, value); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request set exclusive command to daemon : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request set exclusive command : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } + } while (0 != ret); + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} +#endif + +#if 0 +int vc_request_start(bool stop_by_silence) +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Request start"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: client state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret; + int count = 0; + + /* Request */ + ret = -1; + count = 0; + while (0 != ret) { + ret = vc_dbus_request_start(g_vc->handle, stop_by_silence); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to start request start : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry start request start : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] start interrupt"); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_request_stop() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Request stop"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: client state is not 'Ready'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state is not 'RECORDING'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + int count = 0; + /* do request */ + while (0 != ret) { + ret = vc_dbus_request_stop(g_vc->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_DEBUG, TAG_VCC, "[ERROR] Fail to stop request : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry stop request : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Stop interrupt"); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_request_cancel() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Request cancel Interrupt"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'Ready'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING && service_state != VC_SERVICE_STATE_PROCESSING) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state is not 'RECORDING' or 'PROCESSING'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + int count = 0; + while (0 != ret) { + ret = vc_dbus_request_cancel(g_vc->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_DEBUG, TAG_VCC, "[ERROR] Fail to cancel request : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry cancel request : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Cancel interrupt"); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} +#endif + +Eina_Bool __vc_notify_error(void *data) +{ + vc_h vc = (vc_h)data; + + vc_error_cb callback = NULL; + void* user_data; + int reason; + + vc_client_get_error_cb(vc, &callback, &user_data); + vc_client_get_error(vc, &reason); + + if (NULL != callback) { + vc_client_use_callback(vc); + callback(reason, user_data); + vc_client_not_use_callback(vc); + SLOG(LOG_DEBUG, TAG_VCC, "Error callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] Error callback is null"); + } + + return EINA_FALSE; +} + +int __vc_cb_error(int pid, int reason) +{ + if (0 != vc_client_get_handle(pid, &g_vc)) { + SLOG(LOG_ERROR, TAG_VCC, "Handle is not valid"); + return -1; + } + + vc_client_set_error(g_vc, reason); + ecore_timer_add(0, __vc_notify_error, g_vc); + + return 0; +} + +Eina_Bool __vc_notify_state_changed(void *data) +{ + vc_h vc = (vc_h)data; + + vc_state_changed_cb changed_callback = NULL; + void* user_data; + + vc_client_get_state_changed_cb(vc, &changed_callback, &user_data); + + vc_state_e current_state; + vc_state_e before_state; + + vc_client_get_before_state(vc, ¤t_state, &before_state); + + if (NULL != changed_callback) { + vc_client_use_callback(vc); + changed_callback(before_state, current_state, user_data); + vc_client_not_use_callback(vc); + SLOG(LOG_DEBUG, TAG_VCC, "State changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] State changed callback is null"); + } + + return EINA_FALSE; +} + +static Eina_Bool __vc_notify_result(void *data) +{ + char* temp_text; + int event; + vc_cmd_list_h vc_cmd_list = NULL; + + vc_result_cb callback = NULL; + void* user_data = NULL; + + vc_client_get_result_cb(g_vc, &callback, &user_data); + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Client result callback is NULL"); + return EINA_FALSE; + } + + if (0 != vc_cmd_list_create(&vc_cmd_list)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to create command list"); + return EINA_FALSE; + } + + vc_info_parser_get_result(&temp_text, &event, NULL, getpid(), vc_cmd_list, false); + + SLOG(LOG_DEBUG, TAG_VCC, "Result info : result text(%s) event(%d)", temp_text, event); + + vc_cmd_print_list(vc_cmd_list); + + vc_client_use_callback(g_vc); + callback(event, vc_cmd_list, temp_text, user_data); + vc_client_not_use_callback(g_vc); + + SLOG(LOG_DEBUG, TAG_VCC, "Client result callback called"); + + vc_cmd_list_destroy(vc_cmd_list, true); + + /* Release result */ + if (NULL != temp_text) free(temp_text); + + return EINA_FALSE; +} + +void __vc_cb_result() +{ + ecore_timer_add(0, __vc_notify_result, NULL); + + return; +} + +int vc_set_result_cb(vc_result_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_result_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_unset_result_cb() +{ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_result_cb(g_vc, NULL, NULL); + + return 0; +} + +int vc_set_service_state_changed_cb(vc_service_state_changed_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_service_state_changed_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_unset_service_state_changed_cb() +{ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_service_state_changed_cb(g_vc, NULL, NULL); + + return 0; +} + +int vc_set_state_changed_cb(vc_state_changed_cb callback, void* user_data) +{ + if (callback == NULL) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_state_changed_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_unset_state_changed_cb() +{ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_state_changed_cb(g_vc, NULL, NULL); + + return 0; +} + +int vc_set_current_language_changed_cb(vc_current_language_changed_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set current language changed : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set current language changed : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_current_lang_changed_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_unset_current_language_changed_cb() +{ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset current language changed : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset current language changed : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_current_lang_changed_cb(g_vc, NULL, NULL); + + return 0; +} + +int vc_set_error_cb(vc_error_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set error callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Set error callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_error_cb(g_vc, callback, user_data); + + return 0; +} + +int vc_unset_error_cb() +{ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset error callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Unset error callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_client_set_error_cb(g_vc, NULL, NULL); + + return 0; +} + +/* Authority */ +int vc_auth_enable() +{ + /* check state */ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_STATE_READY != state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Current state is not 'READY'"); + return VC_ERROR_INVALID_STATE; + } + + /* check already authority */ + vc_auth_state_e auth_state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_AUTH_STATE_NONE != auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Already authority enabled"); + return VC_ERROR_INVALID_STATE; + } + + /* request authority */ + int mgr_pid = -1; + if (0 != vc_client_get_mgr_pid(g_vc, &mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get mgr info"); + return VC_ERROR_OPERATION_FAILED; + } + + if (0 != vc_dbus_request_auth_enable(g_vc->handle, mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to authority enabled"); + return VC_ERROR_OPERATION_FAILED; + } + + /* set authority into handle */ + int fg_pid = -1; + if (0 != vc_config_mgr_get_foreground(&fg_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get foreground"); + return VC_ERROR_OPERATION_FAILED; + } + + if (g_vc->handle == fg_pid) { + auth_state = VC_AUTH_STATE_VALID; + } else { + auth_state = VC_AUTH_STATE_INVALID; + } + + if (0 != vc_client_set_auth_state(g_vc, auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set auth state"); + return VC_ERROR_OPERATION_FAILED; + } + + ecore_timer_add(0, __notify_auth_changed_cb, NULL); + + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Auth enable"); + + return VC_ERROR_NONE; +} + +int vc_auth_disable() +{ + /* check state */ + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_STATE_READY != state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Current state is not 'READY'"); + return VC_ERROR_INVALID_STATE; + } + + /* check autority */ + vc_auth_state_e auth_state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_AUTH_STATE_NONE == auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] No authority"); + return VC_ERROR_INVALID_STATE; + } + + if (0 != vc_auth_unset_state_changed_cb()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to unset state changed cb"); + } + + /* request return authority by dbus */ + int mgr_pid = -1; + if (0 != vc_client_get_mgr_pid(g_vc, &mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get mgr info"); + return VC_ERROR_OPERATION_FAILED; + } + + if (0 != vc_dbus_request_auth_disable(g_vc->handle, mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to authority disble"); + return VC_ERROR_OPERATION_FAILED; + } + + /* unset authority from handle */ + if (0 != vc_client_set_auth_state(g_vc, VC_AUTH_STATE_NONE)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set auth state"); + return VC_ERROR_OPERATION_FAILED; + } + + ecore_timer_add(0, __notify_auth_changed_cb, NULL); + + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Auth disable"); + + return VC_ERROR_NONE; +} + +int vc_auth_get_state(vc_auth_state_e* state) +{ + /* check state */ + vc_state_e vc_state; + if (0 != vc_client_get_client_state(g_vc, &vc_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_STATE_READY != vc_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Current state is not 'READY'"); + return VC_ERROR_INVALID_STATE; + } + + /* get autority */ + vc_auth_state_e temp = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &temp)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + *state = temp; + + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Current auth state is %d", *state); + + return VC_ERROR_NONE; +} + +int vc_auth_set_state_changed_cb(vc_auth_state_changed_cb callback, void* user_data) +{ + /* check parameter */ + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] NULL Parameter"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* check auth */ + vc_auth_state_e auth_state; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_AUTH_STATE_NONE == auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Auth is not enabled"); + return VC_ERROR_INVALID_STATE; + } + + /* set cb into handle */ + if (0 != vc_client_set_auth_state_changed_cb(g_vc, callback, user_data)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to set auth state changed cb"); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Set auth state changed cb"); + + return VC_ERROR_NONE; +} + +int vc_auth_unset_state_changed_cb() +{ + /* check auth */ + vc_auth_state_e auth_state; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + if (VC_AUTH_STATE_NONE == auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Auto is not enabled"); + return VC_ERROR_INVALID_STATE; + } + + /* unset cb from handle */ + if (0 != vc_client_unset_auth_state_changed_cb(g_vc)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to unset auth state changed cb"); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] Unset auth state changed cb"); + + return VC_ERROR_NONE; +} + +int vc_auth_start() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Request start"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: client state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check authority */ + vc_auth_state_e auth_state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get auth state"); + return VC_ERROR_OPERATION_FAILED; + } + + if (VC_AUTH_STATE_VALID != auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Not auth valid"); + return VC_ERROR_OPERATION_FAILED; + } + + /* get mgr_pid */ + int mgr_pid = -1; + if (0 != vc_client_get_mgr_pid(g_vc, &mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get mgr info"); + return VC_ERROR_OPERATION_FAILED; + } + + int ret; + int count = 0; + /* Request */ + ret = -1; + count = 0; + while (0 != ret) { + ret = vc_dbus_request_auth_start(g_vc->handle, mgr_pid); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request auth start : %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request auth start : %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] request auth start"); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_auth_stop() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Request stop"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: client state is not 'Ready'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state is not 'RECORDING'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check authority */ + vc_auth_state_e auth_state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get auth state"); + return VC_ERROR_OPERATION_FAILED; + } + + if (VC_AUTH_STATE_VALID != auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Not auth valid"); + return VC_ERROR_OPERATION_FAILED; + } + + /* get mgr_pid */ + int mgr_pid = -1; + if (0 != vc_client_get_mgr_pid(g_vc, &mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get mgr info"); + return VC_ERROR_OPERATION_FAILED; + } + + int ret = -1; + int count = 0; + /* do request */ + while (0 != ret) { + ret = vc_dbus_request_auth_stop(g_vc->handle, mgr_pid); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_DEBUG, TAG_VCC, "[ERROR] Fail to request auth stop: %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request auth stop: %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] request auth stop"); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} + +int vc_auth_cancel() +{ + SLOG(LOG_DEBUG, TAG_VCC, "===== [Client] Request cancel"); + + vc_state_e state; + if (0 != vc_client_get_client_state(g_vc, &state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: Current state is not 'Ready'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_client_get_service_state(g_vc, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING && service_state != VC_SERVICE_STATE_PROCESSING) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Invalid State: service state is not 'RECORDING' or 'PROCESSING'"); + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check authority */ + vc_auth_state_e auth_state = VC_AUTH_STATE_NONE; + if (0 != vc_client_get_auth_state(g_vc, &auth_state)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get auth state"); + return VC_ERROR_OPERATION_FAILED; + } + + if (VC_AUTH_STATE_VALID != auth_state) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Not auth valid"); + return VC_ERROR_OPERATION_FAILED; + } + + /* get mgr_pid */ + int mgr_pid = -1; + if (0 != vc_client_get_mgr_pid(g_vc, &mgr_pid)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to get mgr info"); + return VC_ERROR_OPERATION_FAILED; + } + + int ret = -1; + int count = 0; + while (0 != ret) { + ret = vc_dbus_request_auth_cancel(g_vc->handle, mgr_pid); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_DEBUG, TAG_VCC, "[ERROR] Fail to request auth cancel: %s", __vc_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCC, "[WARNING] retry request auth cancel: %s", __vc_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "[SUCCESS] request auth cancel"); + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + return ret; +} diff --git a/client/vc_client.c b/client/vc_client.c new file mode 100644 index 0000000..430e89b --- /dev/null +++ b/client/vc_client.c @@ -0,0 +1,695 @@ +/* +* Copyright (c) 2011-2015 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 "vc_client.h" + +typedef struct { + /* base info */ + vc_h vc; + int pid; + int uid; /*<< unique id = pid + handle */ + int xid; /*<< main X window id */ + + vc_result_cb result_cb; + void* result_user_data; + vc_error_cb error_cb; + void* error_user_data; + vc_service_state_changed_cb service_state_changed_cb; + void* service_state_changed_user_data; + vc_state_changed_cb state_changed_cb; + void* state_changed_user_data; + vc_current_language_changed_cb current_lang_changed_cb; + void* current_lang_changed_user_data; + +#if 0 + /* exclusive option */ + bool exclusive_cmd; +#endif + + /* service state */ + vc_service_state_e service_state; + + /* state */ + vc_state_e before_state; + vc_state_e current_state; + + /* mutex */ + int cb_ref_count; + + /* error data */ + int reason; + + /* Authority */ + vc_auth_state_e auth_before_state; + vc_auth_state_e auth_current_state; + vc_auth_state_changed_cb auth_state_changed_cb; + void* auth_state_changed_user_data; + + int mgr_pid; +}vc_client_s; + +/* client list */ +static GSList *g_client_list = NULL; + + +static vc_client_s* __client_get(vc_h vc) +{ + if (vc == NULL) { + return NULL; + } + + vc_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 (vc->handle == data->vc->handle) { + return data; + } + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] Fail to get client by vc"); + + return NULL; +} + +int vc_client_create(vc_h* vc) +{ + vc_client_s *client = NULL; + + client = (vc_client_s*)calloc(1, sizeof(vc_client_s)); + if (NULL == client) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to allocate memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + vc_h temp = (vc_h)calloc(1, sizeof(struct vc_s)); + if (NULL == temp) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to allocate memory"); + free(client); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp->handle = getpid(); + + /* initialize client data */ + client->vc = temp; + client->pid = getpid(); + client->uid = temp->handle; + client->xid = -1; + + client->result_cb = NULL; + client->result_user_data = NULL; + client->service_state_changed_cb = NULL; + client->service_state_changed_user_data = NULL; + client->state_changed_cb = NULL; + client->state_changed_user_data = NULL; + client->current_lang_changed_cb = NULL; + client->current_lang_changed_user_data = NULL; + client->error_cb = NULL; + client->error_user_data = NULL; + +#if 0 + client->exclusive_cmd = false; +#endif + + client->service_state = -1; + + client->before_state = VC_STATE_INITIALIZED; + client->current_state = VC_STATE_INITIALIZED; + + client->cb_ref_count = 0; + + /* Authority */ + client->auth_before_state = VC_AUTH_STATE_NONE; + client->auth_current_state = VC_AUTH_STATE_NONE; + client->auth_state_changed_cb = NULL; + client->auth_state_changed_user_data = NULL; + + g_client_list = g_slist_append(g_client_list, client); + + *vc = temp; + + return 0; +} + +int vc_client_destroy(vc_h vc) +{ + if (vc == NULL) { + SLOG(LOG_ERROR, TAG_VCC, "Input parameter is NULL"); + return 0; + } + + vc_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 (vc->handle == data->vc->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(vc); + + return 0; + } + } + } + + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] client Not found"); + + return -1; +} + +bool vc_client_is_valid(vc_h vc) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) { + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] vc is not valid"); + return false; + } + + return true; +} + +bool vc_client_is_valid_by_uid(int uid) +{ + vc_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 (uid == data->vc->handle) + return true; + } + } + + SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] Fail to get client by vc"); + + return false; +} + +int vc_client_get_handle(int uid, vc_h* vc) +{ + vc_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 (uid == data->vc->handle) { + *vc = data->vc; + return 0; + } + } + } + + return -1; +} + +/* set/get callback function */ +int vc_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->result_cb = callback; + client->result_user_data = user_data; + + return 0; +} + +int vc_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->result_cb; + *user_data = client->result_user_data; + + return 0; +} + +int vc_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->service_state_changed_cb = callback; + client->service_state_changed_user_data = user_data; + + return 0; +} + +int vc_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->service_state_changed_cb; + *user_data = client->service_state_changed_user_data; + + return 0; +} + +int vc_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->state_changed_cb = callback; + client->state_changed_user_data = user_data; + + return 0; +} + +int vc_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->state_changed_cb; + *user_data = client->state_changed_user_data; + + return 0; +} + +int vc_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->current_lang_changed_cb = callback; + client->current_lang_changed_user_data = user_data; + + return 0; +} + +int vc_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->current_lang_changed_cb; + *user_data = client->current_lang_changed_user_data; + + return 0; +} + +int vc_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->error_cb = callback; + client->error_user_data = user_data; + + return 0; +} + +int vc_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->error_cb; + *user_data = client->error_user_data; + + return 0; +} + +/* set/get option */ +int vc_client_set_service_state(vc_h vc, vc_service_state_e state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->service_state = state; + + return 0; +} + +int vc_client_get_service_state(vc_h vc, vc_service_state_e* state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *state = client->service_state; + + return 0; +} + +int vc_client_set_client_state(vc_h vc, vc_state_e state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->before_state = client->current_state; + client->current_state = state; + + return 0; +} + +int vc_client_get_client_state(vc_h vc, vc_state_e* state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *state = client->current_state; + + return 0; +} + +int vc_client_get_client_state_by_uid(int uid, vc_state_e* state) +{ + vc_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 (uid == data->vc->handle) { + *state = data->current_state; + return 0; + } + } + } + + return -1; +} + +int vc_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *before_state = client->before_state; + *state = client->current_state; + + return 0; +} + +int vc_client_set_xid(vc_h vc, int xid) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->xid = xid; + + return 0; +} + +int vc_client_get_xid(vc_h vc, int* xid) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *xid = client->xid; + + return 0; +} + +#if 0 +int vc_client_set_exclusive_cmd(vc_h vc, bool value) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->exclusive_cmd = value; + + return 0; +} + +int vc_client_get_exclusive_cmd(vc_h vc, bool* value) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *value = client->exclusive_cmd; + + return 0; +} +#endif + +int vc_client_set_error(vc_h vc, int reason) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->reason = reason; + + return 0; +} + +int vc_client_get_error(vc_h vc, int* reason) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *reason = client->reason; + + return 0; +} + + +/* utils */ +int vc_client_get_count() +{ + return g_slist_length(g_client_list); +} + +int vc_client_use_callback(vc_h vc) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->cb_ref_count++; + return 0; +} + +int vc_client_not_use_callback(vc_h vc) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->cb_ref_count--; + return 0; +} + +/* Authority */ +int vc_client_set_auth_state_changed_cb(vc_h vc, vc_auth_state_changed_cb callback, void* user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->auth_state_changed_cb = callback; + client->auth_state_changed_user_data = user_data; + + return 0; +} + +int vc_client_get_auth_state_changed_cb(vc_h vc, vc_auth_state_changed_cb* callback, void** user_data) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->auth_state_changed_cb; + *user_data = client->auth_state_changed_user_data; + + return 0; +} + +int vc_client_unset_auth_state_changed_cb(vc_h vc) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->auth_state_changed_cb = NULL; + client->auth_state_changed_user_data = NULL; + + return 0; +} + +int vc_client_set_auth_state(vc_h vc, vc_auth_state_e state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->auth_before_state = client->auth_current_state; + client->auth_current_state = state; + + return 0; +} + +int vc_client_get_auth_state(vc_h vc, vc_auth_state_e* state) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *state = client->auth_current_state; + + return 0; +} + +int vc_client_get_before_auth_state(vc_h vc, vc_auth_state_e* before, vc_auth_state_e* current) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *before = client->auth_before_state; + *current = client->auth_current_state; + + return 0; +} + +int vc_client_set_mgr_pid(vc_h vc, int mgr_pid) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->mgr_pid = mgr_pid; + + return 0; +} + +int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid) +{ + vc_client_s* client = __client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *mgr_pid = client->mgr_pid; + + return 0; +} \ No newline at end of file diff --git a/client/vc_client.h b/client/vc_client.h new file mode 100644 index 0000000..6ae3c81 --- /dev/null +++ b/client/vc_client.h @@ -0,0 +1,127 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_CLIENT_H_ +#define __VC_CLIENT_H_ + +#include "vc_info_parser.h" +#include "vc_main.h" +#include "voice_control.h" +#include "voice_control_authority.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* Common function +*/ +int vc_client_create(vc_h* vc); + +int vc_client_destroy(vc_h vc); + +bool vc_client_is_valid(vc_h vc); + +bool vc_client_is_valid_by_uid(int uid); + +int vc_client_get_handle(int uid, vc_h* vc); + +/* +* set/get callback function +*/ +int vc_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data); + +int vc_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data); + +int vc_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data); + +int vc_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data); + +int vc_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data); + +int vc_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data); + +int vc_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data); + +int vc_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data); + +int vc_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data); + +int vc_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data); + + +/* +* set/get option +*/ +int vc_client_set_service_state(vc_h vc, vc_service_state_e state); + +int vc_client_get_service_state(vc_h vc, vc_service_state_e* state); + +int vc_client_set_client_state(vc_h vc, vc_state_e state); + +int vc_client_get_client_state(vc_h vc, vc_state_e* state); + +int vc_client_get_client_state_by_uid(int uid, vc_state_e* state); + +int vc_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state); + +int vc_client_set_xid(vc_h vc, int xid); + +int vc_client_get_xid(vc_h vc, int* xid); + +#if 0 +int vc_client_set_exclusive_cmd(vc_h vc, bool value); + +int vc_client_get_exclusive_cmd(vc_h vc, bool* value); +#endif + +int vc_client_set_error(vc_h vc, int reason); + +int vc_client_get_error(vc_h vc, int* reason); + + +/* utils */ +int vc_client_get_count(); + +int vc_client_use_callback(vc_h vc); + +int vc_client_not_use_callback(vc_h vc); + +/* Authority */ +int vc_client_set_auth_state_changed_cb(vc_h vc, vc_auth_state_changed_cb callback, void* user_data); + +int vc_client_get_auth_state_changed_cb(vc_h vc, vc_auth_state_changed_cb* callback, void** user_data); + +int vc_client_unset_auth_state_changed_cb(vc_h vc); + +int vc_client_set_auth_state(vc_h vc, vc_auth_state_e state); + +int vc_client_get_auth_state(vc_h vc, vc_auth_state_e* state); + +int vc_client_get_before_auth_state(vc_h vc, vc_auth_state_e* before, vc_auth_state_e* current); + +int vc_client_set_mgr_pid(vc_h vc, int mgr_pid); + +int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_CLIENT_H_ */ diff --git a/client/vc_dbus.c b/client/vc_dbus.c new file mode 100644 index 0000000..d88e0cd --- /dev/null +++ b/client/vc_dbus.c @@ -0,0 +1,1194 @@ +/* +* Copyright (c) 2011-2015 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 "vc_client.h" +#include "vc_dbus.h" +#include "vc_main.h" + + +static int g_waiting_time = 3000; + +static Ecore_Fd_Handler* g_fd_handler = NULL; + +static DBusConnection* g_conn = NULL; + + +extern int __vc_cb_error(int pid, int reason); + +extern void __vc_cb_result(); + + +static Eina_Bool listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler) +{ + DBusConnection* conn = (DBusConnection*)data; + DBusMessage* msg = NULL; + DBusMessage *reply = NULL; + + if (NULL == conn) + return ECORE_CALLBACK_RENEW; + + dbus_connection_read_write_dispatch(conn, 50); + + msg = dbus_connection_pop_message(conn); + + /* loop again if we haven't read a message */ + if (NULL == msg) { + return ECORE_CALLBACK_RENEW; + } + + DBusError err; + dbus_error_init(&err); + + char if_name[64]; + snprintf(if_name, 64, "%s%d", VC_CLIENT_SERVICE_INTERFACE, getpid()); + + if (dbus_message_is_method_call(msg, if_name, VCD_METHOD_HELLO)) { + SLOG(LOG_DEBUG, TAG_VCC, "===== 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_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (pid > 0) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc get hello : pid(%d) ", pid); + response = 1; + + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc get hello : invalid pid "); + } + + 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(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc get hello : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc get hello : result(%d)", response); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc get hello : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + } /* VCD_METHOD_HELLO */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_METHOD_RESULT)) { + SLOG(LOG_DEBUG, TAG_VCC, "===== Get Client Result"); + + __vc_cb_result(); + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc get result : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc get result"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc get result : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + + }/* VCD_METHOD_RESULT */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_METHOD_ERROR)) { + SLOG(LOG_DEBUG, TAG_VCC, "===== Get Error"); + int pid; + int reason; + char* err_msg; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &reason, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc Get Error message : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc Get Error message : pid(%d), reason(%d), msg(%s)", pid, reason, err_msg); + __vc_cb_error(pid, reason); + } + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc Error message : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc Error message"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc Error message : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCC, "====="); + SLOG(LOG_DEBUG, TAG_VCC, " "); + }/* VCD_METHOD_ERROR */ + + /* free the message */ + dbus_message_unref(msg); + + return ECORE_CALLBACK_PASS_ON; +} + +int vc_dbus_open_connection() +{ + if (NULL != g_conn) { + SLOG(LOG_WARN, TAG_VCC, "already existed connection "); + return 0; + } + + DBusError err; + int ret; + + /* initialise the error value */ + dbus_error_init(&err); + + /* connect to the DBUS system bus, and check for errors */ + g_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "Dbus Connection Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL == g_conn) { + SLOG(LOG_ERROR, TAG_VCC, "Fail to get dbus connection "); + return VC_ERROR_OPERATION_FAILED; + } + + int pid = getpid(); + + char service_name[64]; + memset(service_name, '\0', 64); + snprintf(service_name, 64, "%s%d", VC_CLIENT_SERVICE_NAME, pid); + + SLOG(LOG_DEBUG, TAG_VCC, "service name is %s", service_name); + + /* register our name on the bus, and check for errors */ + ret = dbus_bus_request_name(g_conn, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "Name Error (%s)", err.message); + dbus_error_free(&err); + } + + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + SLOG(LOG_ERROR, TAG_VCC, "fail dbus_bus_request_name()"); + return -2; + } + + if( NULL != g_fd_handler ) { + SLOG(LOG_WARN, TAG_VCC, "The handler already exists."); + return 0; + } + + char rule[128]; + snprintf(rule, 128, "type='signal',interface='%s%d'", VC_CLIENT_SERVICE_INTERFACE, pid); + + /* add a rule for which messages we want to see */ + dbus_bus_add_match(g_conn, rule, &err); + dbus_connection_flush(g_conn); + + if (dbus_error_is_set(&err)) + { + SLOG(LOG_ERROR, TAG_VCC, "Match Error (%s)", err.message); + dbus_error_free(&err); + return VC_ERROR_OPERATION_FAILED; + } + + int fd = 0; + if (1 != dbus_connection_get_unix_fd(g_conn, &fd)) { + SLOG(LOG_ERROR, TAG_VCC, "fail to get fd from dbus "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, "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, NULL, NULL); + + if (NULL == g_fd_handler) { + SLOG(LOG_ERROR, TAG_VCC, "fail to get fd handler from ecore "); + return VC_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int vc_dbus_close_connection() +{ + DBusError err; + dbus_error_init(&err); + + int pid = getpid(); + + char service_name[64]; + memset(service_name, '\0', 64); + snprintf(service_name, 64, "%s%d", VC_CLIENT_SERVICE_NAME, pid); + + dbus_bus_release_name (g_conn, service_name, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + dbus_connection_close(g_conn); + + g_fd_handler = NULL; + g_conn = NULL; + + return 0; +} + +int vc_dbus_reconnect() +{ + bool connected = dbus_connection_get_is_connected(g_conn); + SECURE_SLOG(LOG_DEBUG, TAG_VCC, "[DBUS] %s", connected ? "Connected" : "Not connected"); + + if (false == connected) { + vc_dbus_close_connection(); + + if (0 != vc_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to reconnect"); + return -1; + } + + SLOG(LOG_DEBUG, TAG_VCC, "[DBUS] Reconnect"); + } + return 0; +} + +int vc_dbus_request_hello() +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_HELLO); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> Request vc hello : Fail to make message"); + return VC_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, msg, 500, &err); + + if (dbus_error_is_set(&err)) { + dbus_error_free(&err); + } + + dbus_message_unref(msg); + + if (NULL != result_msg) { + dbus_message_unref(result_msg); + result = 0; + } else { + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + + +int vc_dbus_request_initialize(int pid, int* mgr_pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_INITIALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc initialize : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc 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; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + int tmp = -1; + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INT32, &tmp, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + + if (0 == result) { + *mgr_pid = tmp; + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc initialize : result = %d mgr = %d", result, *mgr_pid); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc initialize : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Result message is NULL "); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_finalize(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_FINALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc finalize : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc finalize : pid(%d)", pid); + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc finalize : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc finalize : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Result message is NULL "); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_set_exclusive_command(int pid, bool value) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_SET_EXCLUSIVE_CMD); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc set exclusive command : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc set exclusive command : pid(%d)", pid); + } + + int temp = value; + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &temp, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc set exclusive command : result = %d", result); + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc set exclusive command : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Result message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_set_command(int pid, vc_cmd_type_e cmd_type) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_SET_COMMAND); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc set command : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc set command : pid(%d)", pid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &cmd_type, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc set command : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc set command : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Result message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_unset_command(int pid, vc_cmd_type_e cmd_type) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_UNSET_COMMAND); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc unset command : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc unset command : pid(%d), type(%d)", pid, cmd_type); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &cmd_type, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc unset command : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc unset command : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Result message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +#if 0 +int vc_dbus_request_start(int pid, int silence) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_REQUEST_START); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc start : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc start : pid(%d), silence(%d)", pid, silence); + } + + DBusMessageIter args; + dbus_message_iter_init_append(msg, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(pid)); + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(silence)); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc start : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc start : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_stop(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_REQUEST_STOP); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc stop : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc stop : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc stop : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc stop : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_cancel(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + VC_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + VC_METHOD_REQUEST_CANCEL); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc cancel : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc cancel : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc cancel : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc cancel : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} +#endif + +/* Authority */ +int vc_dbus_request_auth_enable(int pid, int mgr_pid) +{ + DBusMessage* msg; + + char service_name[64] = {0,}; + char object_path[64] = {0,}; + char target_if_name[128] = {0,}; + + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, mgr_pid); + snprintf(object_path, 64, "%s", VC_MANAGER_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_MANAGER_SERVICE_INTERFACE, mgr_pid); + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + service_name, + object_path, /* object name of the signal */ + target_if_name, /* interface name of the signal */ + VC_METHOD_AUTH_ENABLE); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc auth enable : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc auth enable : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc auth enable : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc auth enable : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_auth_disable(int pid, int mgr_pid) +{ + DBusMessage* msg; + + char service_name[64] = {0,}; + char object_path[64] = {0,}; + char target_if_name[128] = {0,}; + + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, mgr_pid); + snprintf(object_path, 64, "%s", VC_MANAGER_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_MANAGER_SERVICE_INTERFACE, mgr_pid); + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + service_name, + object_path, /* object name of the signal */ + target_if_name, /* interface name of the signal */ + VC_METHOD_AUTH_DISABLE); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc auth disable : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc auth disable : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc auth disable : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc auth disable : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_auth_start(int pid, int mgr_pid) +{ + DBusMessage* msg; + + char service_name[64] = {0,}; + char object_path[64] = {0,}; + char target_if_name[128] = {0,}; + + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, mgr_pid); + snprintf(object_path, 64, "%s", VC_MANAGER_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_MANAGER_SERVICE_INTERFACE, mgr_pid); + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + service_name, + object_path, + target_if_name, + VC_METHOD_AUTH_START); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc auth start : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc auth start : pid(%d)", pid); + } + + DBusMessageIter args; + dbus_message_iter_init_append(msg, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(pid)); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc auth start : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc auth start : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_auth_stop(int pid, int mgr_pid) +{ + DBusMessage* msg; + + char service_name[64] = {0,}; + char object_path[64] = {0,}; + char target_if_name[128] = {0,}; + + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, mgr_pid); + snprintf(object_path, 64, "%s", VC_MANAGER_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_MANAGER_SERVICE_INTERFACE, mgr_pid); + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + service_name, + object_path, + target_if_name, + VC_METHOD_AUTH_STOP); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc auth stop : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc auth stop : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc auth stop : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc auth stop : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_dbus_request_auth_cancel(int pid, int mgr_pid) +{ + DBusMessage* msg; + + char service_name[64] = {0,}; + char object_path[64] = {0,}; + char target_if_name[128] = {0,}; + + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, mgr_pid); + snprintf(object_path, 64, "%s", VC_MANAGER_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_MANAGER_SERVICE_INTERFACE, mgr_pid); + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + service_name, + object_path, /* object name of the signal */ + target_if_name, /* interface name of the signal */ + VC_METHOD_AUTH_CANCEL); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCC, ">>>> vc auth cancel : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCC, ">>>> vc auth cancel : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_conn, msg, g_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL != result_msg) { + dbus_message_get_args(result_msg, &err, + DBUS_TYPE_INT32, &result, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCC, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< vc auth cancel : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCC, "<<<< vc auth cancel : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCC, "<<<< Result Message is NULL"); + vc_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} diff --git a/client/vc_dbus.h b/client/vc_dbus.h new file mode 100644 index 0000000..f8780a1 --- /dev/null +++ b/client/vc_dbus.h @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_DBUS_H_ +#define __VC_DBUS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +int vc_dbus_open_connection(); + +int vc_dbus_close_connection(); + + +int vc_dbus_request_hello(); + +int vc_dbus_request_initialize(int pid, int* mgr_pid); + +int vc_dbus_request_finalize(int pid); + +int vc_dbus_request_set_exclusive_command(int pid, bool value); + +int vc_dbus_request_set_command(int pid, vc_cmd_type_e cmd_type); + +int vc_dbus_request_unset_command(int pid, vc_cmd_type_e cmd_type); + +#if 0 +int vc_dbus_request_start(int pid, int silence); + +int vc_dbus_request_stop(int pid); + +int vc_dbus_request_cancel(int pid); +#endif + +/* Authority */ +int vc_dbus_request_auth_enable(int pid, int mgr_pid); + +int vc_dbus_request_auth_disable(int pid, int mgr_pid); + +int vc_dbus_request_auth_start(int pid, int mgr_pid); + +int vc_dbus_request_auth_stop(int pid, int mgr_pid); + +int vc_dbus_request_auth_cancel(int pid, int mgr_pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_DBUS_H_ */ diff --git a/client/vc_mgr.c b/client/vc_mgr.c new file mode 100644 index 0000000..f1d7121 --- /dev/null +++ b/client/vc_mgr.c @@ -0,0 +1,2131 @@ +/* +* Copyright (c) 2011-2015 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 + +#include "vc_info_parser.h" +#include "vc_config_mgr.h" +#include "vc_command.h" +#include "vc_main.h" +#include "vc_mgr_client.h" +#include "vc_mgr_dbus.h" +#include "voice_control.h" +#include "voice_control_command.h" +#include "voice_control_command_expand.h" +#include "voice_control_common.h" +#include "voice_control_manager.h" + + +#define VC_MANAGER_CONFIG_HANDLE 100000 + +static bool g_m_is_daemon_started = false; + +static Ecore_Timer* g_m_connect_timer = NULL; + +static vc_h g_vc_m = NULL; + +static GSList* g_demandable_client_list = NULL; + + +static Eina_Bool __vc_mgr_notify_state_changed(void *data); +static Eina_Bool __vc_mgr_notify_error(void *data); +static Eina_Bool __vc_mgr_notify_result(void *data); + +static const char* __vc_mgr_get_error_code(vc_error_e err) +{ + switch(err) { + case VC_ERROR_NONE: return "VC_ERROR_NONE"; break; + case VC_ERROR_OUT_OF_MEMORY: return "VC_ERROR_OUT_OF_MEMORY"; break; + case VC_ERROR_IO_ERROR: return "VC_ERROR_IO_ERROR"; break; + case VC_ERROR_INVALID_PARAMETER: return "VC_ERROR_INVALID_PARAMETER"; break; + case VC_ERROR_TIMED_OUT: return "VC_ERROR_TIMED_OUT"; break; + case VC_ERROR_RECORDER_BUSY: return "VC_ERROR_RECORDER_BUSY"; break; + case VC_ERROR_INVALID_STATE: return "VC_ERROR_INVALID_STATE"; break; + case VC_ERROR_INVALID_LANGUAGE: return "VC_ERROR_INVALID_LANGUAGE"; break; + case VC_ERROR_ENGINE_NOT_FOUND: return "VC_ERROR_ENGINE_NOT_FOUND"; break; + case VC_ERROR_OPERATION_FAILED: return "VC_ERROR_OPERATION_FAILED"; break; + default: return "Invalid error code"; break; + } + return NULL; +} + +static void __vc_mgr_lang_changed_cb(const char* before_lang, const char* current_lang) +{ + SECURE_SLOG(LOG_DEBUG, TAG_VCM, "Lang changed : Before lang(%s) Current lang(%s)", + before_lang, current_lang); + + vc_current_language_changed_cb callback = NULL; + void* lang_user_data; + vc_mgr_client_get_current_lang_changed_cb(g_vc_m, &callback, &lang_user_data); + + if (NULL != callback) { + vc_mgr_client_use_callback(g_vc_m); + callback(before_lang, current_lang, lang_user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "Language changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] Language changed callback is null"); + } + + return; +} + +static void __vc_mgr_service_state_changed_cb(int before_state, int current_state) +{ + SECURE_SLOG(LOG_DEBUG, TAG_VCM, "Service State changed : Before(%d) Current(%d)", + before_state, current_state); + + /* Save service state */ + vc_mgr_client_set_service_state(g_vc_m, (vc_service_state_e)current_state); + + vc_service_state_changed_cb callback = NULL; + void* service_user_data; + vc_mgr_client_get_service_state_changed_cb(g_vc_m, &callback, &service_user_data); + + if (NULL != callback) { + vc_mgr_client_use_callback(g_vc_m); + callback((vc_service_state_e)before_state, (vc_service_state_e)current_state, service_user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "Service state changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] Service state changed callback is null"); + } + + return; +} + +static void __vc_mgr_foreground_changed_cb(int previous, int current) +{ + SLOG(LOG_DEBUG, TAG_VCM, "Foreground changed : Before(%d) Current(%d)", previous, current); + + /* get authorized valid app */ + int pid; + if (0 != vc_mgr_client_get_valid_authorized_client(g_vc_m, &pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get authorized valid app"); + return; + } + + /* compare & set valid */ + if (current != pid) { + SLOG(LOG_DEBUG, TAG_VCM, "Authority(%d) changed to invalid", pid); + + /* set authorized valid */ + if (true == vc_mgr_client_is_authorized_client(g_vc_m, current)) { + SLOG(LOG_DEBUG, TAG_VCM, "Authority(%d) change to valid", current); + vc_mgr_client_set_valid_authorized_client(g_vc_m, current); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "No valid Authority"); + vc_mgr_client_set_valid_authorized_client(g_vc_m, -1); + } + } +} + +int vc_mgr_initialize() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Initialize"); + + /* check handle */ + if (true == vc_mgr_client_is_valid(g_vc_m)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Already initialized"); + return VC_ERROR_NONE; + } + + if (0 != vc_mgr_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to open connection"); + return VC_ERROR_OPERATION_FAILED; + } + + if (0 != vc_mgr_client_create(&g_vc_m)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to create client!!!!!"); + return VC_ERROR_OUT_OF_MEMORY; + } + + int ret = vc_config_mgr_initialize(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to init config manager : %d", ret); + vc_mgr_client_destroy(g_vc_m); + return VC_ERROR_OPERATION_FAILED; + } + + ret = vc_config_mgr_set_lang_cb(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE, __vc_mgr_lang_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set callback : %d", ret); + vc_config_mgr_finalize(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_mgr_client_destroy(g_vc_m); + return VC_ERROR_OPERATION_FAILED; + } + + ret = vc_config_mgr_set_service_state_cb(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE, __vc_mgr_service_state_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set service change callback : %d", ret); + vc_config_mgr_unset_lang_cb(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_config_mgr_finalize(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_mgr_client_destroy(g_vc_m); + return VC_ERROR_OPERATION_FAILED; + } + + ret = vc_config_mgr_set_foreground_cb(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE, __vc_mgr_foreground_changed_cb); + + int service_state = -1; + if (0 != vc_config_mgr_get_service_state(&service_state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get service state"); + vc_config_mgr_finalize(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_mgr_client_destroy(g_vc_m); + return VC_ERROR_OPERATION_FAILED; + } + + vc_mgr_client_set_service_state(g_vc_m, service_state); + + SLOG(LOG_DEBUG, TAG_VCM, "[Success] pid(%d)", g_vc_m->handle); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +static void __vc_mgr_internal_unprepare() +{ + int ret = vc_mgr_dbus_request_finalize(g_vc_m->handle); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request finalize : %s", __vc_mgr_get_error_code(ret)); + } + + g_m_is_daemon_started = false; + + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_SYSTEM); + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_EXCLUSIVE); + + return; +} + +int vc_mgr_deinitialize() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Deinitialize"); + + if (false == vc_mgr_client_is_valid(g_vc_m)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] NOT initialized"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + vc_state_e state; + vc_mgr_client_get_client_state(g_vc_m, &state); + + /* check state */ + switch (state) { + case VC_STATE_READY: + __vc_mgr_internal_unprepare(); + /* no break. need to next step*/ + case VC_STATE_INITIALIZED: + if (NULL != g_m_connect_timer) { + SLOG(LOG_DEBUG, TAG_VCM, "Connect Timer is deleted"); + ecore_timer_del(g_m_connect_timer); + } + + vc_config_mgr_unset_service_state_cb(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_config_mgr_unset_lang_cb(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + vc_config_mgr_finalize(g_vc_m->handle + VC_MANAGER_CONFIG_HANDLE); + + /* Free client resources */ + vc_mgr_client_destroy(g_vc_m); + g_vc_m = NULL; + break; + case VC_STATE_NONE: + break; + default: + break; + } + + SLOG(LOG_DEBUG, TAG_VCM, "Success: destroy"); + + if (0 != vc_mgr_dbus_close_connection()) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to close connection"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +static void* __fork_vc_daemon() +{ + int pid, i; + pid = fork(); + + switch(pid) { + case -1: + SLOG(LOG_ERROR, TAG_VCM, "Fail to create daemon"); + break; + case 0: + setsid(); + for (i = 0;i < _NSIG;i++) + signal(i, SIG_DFL); + + execl(VC_DAEMON_PATH, VC_DAEMON_PATH, NULL); + break; + default: + break; + } + + return (void*) 1; +} + +static Eina_Bool __vc_mgr_connect_daemon(void *data) +{ + /* Send hello */ + if (0 != vc_mgr_dbus_request_hello()) { + if (false == g_m_is_daemon_started) { + g_m_is_daemon_started = true; + + pthread_t thread; + int thread_id; + thread_id = pthread_create(&thread, NULL, __fork_vc_daemon, NULL); + if (thread_id < 0) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to make thread"); + g_m_connect_timer = NULL; + return EINA_FALSE; + } + + pthread_detach(thread); + } + return EINA_TRUE; + } + + g_m_connect_timer = NULL; + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Connect daemon"); + + /* request initialization */ + int ret = -1; + ret = vc_mgr_dbus_request_initialize(g_vc_m->handle); + + if (VC_ERROR_ENGINE_NOT_FOUND == ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to initialize : %s", __vc_mgr_get_error_code(ret)); + + vc_mgr_client_set_error(g_vc_m, VC_ERROR_ENGINE_NOT_FOUND); + ecore_timer_add(0, __vc_mgr_notify_error, g_vc_m); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return EINA_FALSE; + + } else if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[WARNING] Fail to connection. Retry to connect : %s", __vc_mgr_get_error_code(ret)); + return EINA_TRUE; + } else { + /* Success to connect */ + } + + SECURE_SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Connected daemon"); + + vc_mgr_client_set_client_state(g_vc_m, VC_STATE_READY); + + vc_state_changed_cb changed_callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_state_changed_cb(g_vc_m, &changed_callback, &user_data); + + vc_state_e current_state; + vc_state_e before_state; + + vc_mgr_client_get_before_state(g_vc_m, ¤t_state, &before_state); + + if (NULL != changed_callback) { + vc_mgr_client_use_callback(g_vc_m); + changed_callback(before_state, current_state, user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "State changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] State changed callback is null"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return EINA_FALSE; +} + +int vc_mgr_prepare() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Prepare"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'CREATED'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + g_m_is_daemon_started = false; + + g_m_connect_timer = ecore_timer_add(0, __vc_mgr_connect_daemon, NULL); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +int vc_mgr_unprepare() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Unprepare"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + __vc_mgr_internal_unprepare(); + + vc_mgr_client_set_client_state(g_vc_m, VC_STATE_INITIALIZED); + ecore_timer_add(0, __vc_mgr_notify_state_changed, g_vc_m); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +int vc_mgr_foreach_supported_languages(vc_supported_language_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Foreach Supported Language"); + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_config_mgr_get_language_list(callback, user_data); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get languages : %s", __vc_mgr_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +int vc_mgr_get_current_language(char** language) +{ + if (NULL == language) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_config_mgr_get_default_language(language); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get current languages : %s", __vc_mgr_get_error_code(ret)); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Get current language] language : %s", *language); + } + + return ret; +} + +int vc_mgr_get_state(vc_state_e* state) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Get State"); + + if (NULL == state) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e temp; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &temp)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + *state = temp; + + switch(*state) { + case VC_STATE_NONE: SLOG(LOG_DEBUG, TAG_VCM, "Current state is 'None'"); break; + case VC_STATE_INITIALIZED: SLOG(LOG_DEBUG, TAG_VCM, "Current state is 'Created'"); break; + case VC_STATE_READY: SLOG(LOG_DEBUG, TAG_VCM, "Current state is 'Ready'"); break; + default: SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid state"); break; + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +int vc_mgr_get_service_state(vc_service_state_e* state) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Get Service State"); + + if (NULL == state) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e client_state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &client_state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (client_state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Current state is not 'READY'"); + return VC_ERROR_INVALID_STATE; + } + + /* get service state */ + vc_service_state_e service_state; + if (0 != vc_mgr_client_get_service_state(g_vc_m, &service_state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get service state"); + return VC_ERROR_OPERATION_FAILED; + } + + *state = service_state; + + switch(*state) { + case VC_SERVICE_STATE_NONE: SLOG(LOG_DEBUG, TAG_VCM, "Current service state is 'None'"); break; + case VC_SERVICE_STATE_READY: SLOG(LOG_DEBUG, TAG_VCM, "Current service state is 'Ready'"); break; + case VC_SERVICE_STATE_RECORDING: SLOG(LOG_DEBUG, TAG_VCM, "Current service state is 'Recording'"); break; + case VC_SERVICE_STATE_PROCESSING: SLOG(LOG_DEBUG, TAG_VCM, "Current service state is 'Processing'"); break; + default: SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid state"); break; + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +int vc_mgr_set_demandable_client_rule(const char* rule) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Set Demandable client rule"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_info_parser_set_demandable_client(rule); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] rule is NOT valid"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + if (0 != vc_info_parser_get_demandable_clients(&g_demandable_client_list)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get demandable clients"); + return VC_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return 0; + + /* + int count = 0; + ret = -1; + while (0 != ret) { + ret = vc_mgr_dbus_request_demandable_client(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request set client rule to daemon : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry request set client rule : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return 0; + */ +} + +int vc_mgr_unset_demandable_client_rule() +{ + vc_info_parser_set_demandable_client(NULL); + + int count = 0; + int ret = -1; + while (0 != ret) { + ret = vc_mgr_dbus_request_demandable_client(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request unset client rule to daemon : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry request unset client rule : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } + } + + return 0; +} + +int vc_mgr_is_command_format_supported(vc_cmd_format_e format, bool* support) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Is command type supported"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check support */ + bool non_fixed_support = false; + if (0 != vc_config_mgr_get_nonfixed_support(&non_fixed_support)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get nonfixed support info"); + } + + switch (format) { + case VC_CMD_FORMAT_FIXED: *support = true; break; + case VC_CMD_FORMAT_FIXED_AND_EXTRA: *support = non_fixed_support; break; + case VC_CMD_FORMAT_EXTRA_AND_FIXED: *support = non_fixed_support; break; + default: *support = false; break; + } + + SLOG(LOG_ERROR, TAG_VCM, "[DEBUG] Format(%d) support(%s)", format, *support ? "true" : "false"); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return VC_ERROR_NONE; +} + +int vc_mgr_set_command_list(vc_cmd_list_h vc_cmd_list) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Set Command list"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + int system_ret = vc_cmd_parser_save_file(getpid(), VC_COMMAND_TYPE_SYSTEM, list->list); + int exclsive_ret = vc_cmd_parser_save_file(getpid(), VC_COMMAND_TYPE_EXCLUSIVE, list->list); + int ret = 0; + + if (0 != system_ret && 0 != exclsive_ret) { + ret = VC_ERROR_INVALID_PARAMETER; + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to save command group : %s", __vc_mgr_get_error_code(ret)); + } else { + int count = 0; + do { + ret = vc_mgr_dbus_request_set_command(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request set command to daemon : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry request set command : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } + } while(0 != ret); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return ret; +} + +int vc_mgr_unset_command_list() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Unset Command list"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Current state is not 'READY'"); + return VC_ERROR_INVALID_STATE; + } + + int count = 0; + int ret = -1; + while (0 != ret) { + ret = vc_mgr_dbus_request_unset_command(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request unset command to daemon : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry request unset command : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } + } + + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_SYSTEM); + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_EXCLUSIVE); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return 0; +} + +int vc_mgr_set_audio_type(const char* audio_id) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Set audio type"); + + if (NULL == audio_id) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret; + int count = 0; + + /* Request */ + ret = -1; + count = 0; + while (0 != ret) { + ret = vc_mgr_dbus_request_set_audio_type(g_vc_m->handle, audio_id); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set audio type : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry to set audio type : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Set audio type"); + /* Save */ + vc_mgr_client_set_audio_type(g_vc_m, audio_id); + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return ret; +} + +int vc_mgr_get_audio_type(char** audio_id) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Get audio type"); + + if (NULL == audio_id) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + char* temp = NULL; + + vc_mgr_client_get_audio_type(g_vc_m, &temp); + + if (NULL == temp) { + /* Not initiallized */ + int ret = -1; + int count = 0; + while (0 != ret) { + ret = vc_mgr_dbus_request_get_audio_type(g_vc_m->handle, &temp); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get audio type : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry to get audio type : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Get audio type : %s", temp); + /* Save */ + vc_mgr_client_set_audio_type(g_vc_m, temp); + } + } + } + + if (NULL != temp) { + *audio_id = strdup(temp); + free(temp); + temp = NULL; + } + + return 0; +} + +int vc_mgr_get_current_commands(vc_cmd_list_h* vc_cmd_list) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Foreach current commands"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid Parameter"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_h temp_list = NULL; + if (0 != vc_cmd_list_create(&temp_list)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to create list"); + return VC_ERROR_INVALID_PARAMETER; + } + + *vc_cmd_list = temp_list; + + int fg_pid = 0; + int mgr_pid = 0; + int count = 0; + int ret = -1; + + /* Get foreground pid */ + if (0 != vc_config_mgr_get_foreground(&fg_pid)) { + /* There is no foreground app for voice control */ + SLOG(LOG_WARN, TAG_VCM, "[Manager WARNING] No foreground pid for voice control"); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Foreground pid(%d)", fg_pid); + } + + if (0 != vc_mgr_client_get_pid(g_vc_m, &mgr_pid)) { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Fail to get manager pid"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Manager pid(%d)", mgr_pid); + } + + /* Get system command */ + ret = vc_cmd_parser_append_commands(mgr_pid, VC_COMMAND_TYPE_SYSTEM, temp_list); + if (0 != ret) { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] No system commands"); + } + + /* Request */ + ret = -1; + count = 0; + while (0 != ret) { + ret = vc_mgr_dbus_request_set_client_info(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set client info : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry to set client info : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Set client info"); + } + } + + GSList *iter = NULL; + GSList* client_info_list = NULL; + vc_client_info_s *client_info = NULL; + bool is_fgpid = false; + + if (0 != vc_info_parser_get_client_info(&client_info_list)) { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] No client"); + return 0; + } + + if (VC_NO_FOREGROUND_PID != fg_pid) { + iter = g_slist_nth(client_info_list, 0); + while (NULL != iter) { + client_info = iter->data; + if (NULL != client_info) { + if (fg_pid == client_info->pid) { + is_fgpid = true; + break; + } + } + iter = g_slist_next(iter); + } + } + + /* Get foreground commands and widget */ + if (true == is_fgpid) { + /* Get handle */ + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] fore cmd(%d)", client_info->fg_cmd); + + /* Get foreground command */ + if (true == client_info->fg_cmd) { + ret = vc_cmd_parser_append_commands(fg_pid, VC_COMMAND_TYPE_FOREGROUND, temp_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[Client Data ERROR] Fail to get the fg command list"); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] No foreground commands"); + } + + /* Check exclusive option */ + if (true == client_info->exclusive_cmd) { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Exclusive command is ON"); + + /* Set background command for exclusive option */ + if (true == client_info->bg_cmd) { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Set background command"); + ret = vc_cmd_parser_append_commands(client_info->pid, VC_COMMAND_TYPE_BACKGROUND, temp_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[Client Data ERROR] Fail to get the bg command list : pid(%d)", client_info->pid); + } + } + + /* need to release client info */ + iter = g_slist_nth(client_info_list, 0); + + while (NULL != iter) { + client_info = iter->data; + if (NULL != client_info) { + free(client_info); + } + client_info_list = g_slist_remove_link(client_info_list, iter); + iter = g_slist_nth(client_info_list, 0); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return 0; + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] No foreground app"); + } + + /* Get background commands */ + if (0 < g_slist_length(client_info_list)) { + iter = g_slist_nth(client_info_list, 0); + + while (NULL != iter) { + client_info = iter->data; + + if (NULL != client_info) { + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] Pid(%d) Back cmd(%d)", client_info->pid, client_info->bg_cmd); + if (true == client_info->bg_cmd) { + ret = vc_cmd_parser_append_commands(client_info->pid, VC_COMMAND_TYPE_BACKGROUND, temp_list); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[Client Data ERROR] Fail to get the bg command list : pid(%d)", client_info->pid); + } + } + free(client_info); + } + client_info_list = g_slist_remove_link(client_info_list, iter); + + iter = g_slist_nth(client_info_list, 0); + } + } else { + /* NO client */ + SLOG(LOG_DEBUG, TAG_VCM, "[Manager] No background commands"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return 0; +} + +int vc_mgr_start(bool stop_by_silence, bool exclusive_command_option) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Request start"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_exclusive_command(g_vc_m, exclusive_command_option); + + bool start_by_client = false; + if (0 != vc_mgr_client_get_start_by_client(g_vc_m, &start_by_client)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get start by client"); + } + + int ret; + int count = 0; + + /* Request */ + ret = -1; + count = 0; + while (0 != ret) { + ret = vc_mgr_dbus_request_start(g_vc_m->handle, stop_by_silence, exclusive_command_option, start_by_client); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to start request start : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry start request start : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + vc_mgr_client_set_exclusive_command(g_vc_m, false); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] start recognition"); + vc_mgr_client_set_service_state(g_vc_m, VC_SERVICE_STATE_RECORDING); + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return ret; +} + +int vc_mgr_stop() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Request stop"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: client state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'RECORDING'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + int count = 0; + /* do request */ + while (0 != ret) { + ret = vc_mgr_dbus_request_stop(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_DEBUG, TAG_VCM, "[ERROR] Fail to stop request : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry stop request : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Stop recognition"); + vc_mgr_client_set_service_state(g_vc_m, VC_SERVICE_STATE_PROCESSING); + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return ret; +} + +int vc_mgr_cancel() +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Request cancel"); + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: client state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING && service_state != VC_SERVICE_STATE_PROCESSING) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'RECORDING' or 'PROCESSING'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + int count = 0; + while (0 != ret) { + ret = vc_mgr_dbus_request_cancel(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_DEBUG, TAG_VCM, "[ERROR] Fail to cancel request : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry cancel request : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Cancel recognition"); + vc_mgr_client_set_service_state(g_vc_m, VC_SERVICE_STATE_READY); + } + } + + vc_mgr_client_set_exclusive_command(g_vc_m, false); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return ret; +} + +int vc_mgr_get_recording_volume(float* volume) +{ + if (NULL == volume) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_service_state_e service_state = -1; + if (0 != vc_mgr_client_get_service_state(g_vc_m, &service_state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (VC_SERVICE_STATE_RECORDING != service_state) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: Service state is not 'RECORDING'"); + return VC_ERROR_INVALID_STATE; + } + + FILE* fp = fopen(VC_RUNTIME_INFO_AUDIO_VOLUME, "rb"); + if (!fp) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to open Volume File"); + return VC_ERROR_OPERATION_FAILED; + } + + int readlen = fread((void*)volume, sizeof(*volume), 1, fp); + fclose(fp); + + if (0 == readlen) + *volume = 0.0f; + + return 0; +} + +int vc_mgr_set_selected_results(vc_cmd_list_h vc_cmd_list) +{ + SLOG(LOG_DEBUG, TAG_VCM, "===== [Manager] Select result"); + + vc_service_state_e service_state = -1; + vc_mgr_client_get_service_state(g_vc_m, &service_state); + if (service_state != VC_SERVICE_STATE_PROCESSING) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Invalid State: service state is not 'PROCESSING'"); + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL != vc_cmd_list) { + int event = 0; + char* result_text = NULL; + + vc_mgr_client_get_all_result(g_vc_m, &event, &result_text); + + vc_info_parser_set_result(result_text, event, NULL, vc_cmd_list, false); + + if (NULL != result_text) { + free(result_text); + result_text = NULL; + } + } + + int ret; + int count = 0; + + /* Request */ + ret = -1; + count = 0; + while (0 != ret) { + ret = vc_mgr_dbus_send_result_selection(g_vc_m->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to send result selection : %s", __vc_mgr_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] retry send result selection : %s", __vc_mgr_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to request"); + break; + } + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] result selection"); + } + } + + vc_mgr_client_unset_all_result(g_vc_m); + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + return 0; +} + +static Eina_Bool __vc_mgr_set_select_result(void *data) +{ + vc_mgr_set_selected_results(NULL); + return EINA_FALSE; +} + +static Eina_Bool __vc_mgr_notify_all_result(void *data) +{ + char* temp_text = NULL; + int event; + char* temp_message = NULL; + vc_cmd_list_h vc_cmd_list = NULL; + + vc_mgr_all_result_cb all_callback = NULL; + void* all_user_data = NULL; + + vc_mgr_client_get_all_result_cb(g_vc_m, &all_callback, &all_user_data); + if (NULL == all_callback) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] All result callback is NULL"); + return EINA_FALSE; + } + + if (0 != vc_cmd_list_create(&vc_cmd_list)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to create command list"); + return EINA_FALSE; + } + + vc_info_parser_get_result(&temp_text, &event, &temp_message, -1, vc_cmd_list, vc_mgr_client_get_exclusive_command(g_vc_m)); + + SLOG(LOG_DEBUG, TAG_VCM, "Result info : result text(%s) event(%d) result_message(%s)", temp_text, event, temp_message); + + vc_cmd_print_list(vc_cmd_list); + + bool cb_ret; + + vc_mgr_client_use_callback(g_vc_m); + cb_ret = all_callback(event, vc_cmd_list, temp_text, temp_message, all_user_data); + vc_mgr_client_not_use_callback(g_vc_m); + + if (true == vc_mgr_client_get_exclusive_command(g_vc_m)) { + /* exclusive */ + vc_result_cb callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_result_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Client result callback is NULL"); + return EINA_FALSE; + } + + vc_mgr_client_use_callback(g_vc_m); + callback(event, vc_cmd_list, temp_text, user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "Exclusive result callback called"); + + /* Release result */ + if (NULL != temp_text) free(temp_text); + + /* Release list */ + vc_cmd_list_destroy(vc_cmd_list, true); + + vc_mgr_client_set_exclusive_command(g_vc_m, false); + + return EINA_FALSE; + } + + int count = 0; + vc_cmd_list_get_count(vc_cmd_list, &count); + if (0 < count) { + if (true == cb_ret) { + SLOG(LOG_DEBUG, TAG_VCM, "Callback result is true"); + ecore_idler_add(__vc_mgr_set_select_result, NULL); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "Callback result is false"); + /* need to select conflicted result */ + + vc_mgr_client_set_all_result(g_vc_m, event, temp_text); + } + } else { + ecore_idler_add(__vc_mgr_set_select_result, NULL); + vc_mgr_client_set_exclusive_command(g_vc_m, false); + vc_mgr_client_unset_all_result(g_vc_m); + } + + /* Release result */ + if (NULL != temp_text) free(temp_text); + + /* Release list */ + vc_cmd_list_destroy(vc_cmd_list, true); + + return EINA_FALSE; +} + +static Eina_Bool __vc_mgr_notify_result(void *data) +{ + char* temp_text; + int event; + vc_cmd_list_h vc_cmd_list = NULL; + + vc_result_cb callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_result_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Client result callback is NULL"); + return EINA_FALSE; + } + + if (0 != vc_cmd_list_create(&vc_cmd_list)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to create command list"); + return EINA_FALSE; + } + + vc_info_parser_get_result(&temp_text, &event, NULL, getpid(), vc_cmd_list, false); + + SLOG(LOG_DEBUG, TAG_VCM, "Result : result text(%s) event(%d)", temp_text, event); + + vc_cmd_print_list(vc_cmd_list); + + vc_mgr_client_use_callback(g_vc_m); + callback(event, vc_cmd_list, temp_text, user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "Result callback called"); + + vc_cmd_list_destroy(vc_cmd_list, true); + + /* Release result */ + if (NULL != temp_text) free(temp_text); + + return EINA_FALSE; +} + +void __vc_mgr_cb_all_result() +{ + if (false == vc_mgr_client_get_exclusive_command(g_vc_m)) { + __vc_mgr_notify_all_result(NULL); + } else { + __vc_mgr_notify_result(0); + } + + return; +} + +void __vc_mgr_cb_system_result() +{ + __vc_mgr_notify_result(NULL); + return; +} + +static Eina_Bool __vc_mgr_speech_detected(void *data) +{ + vc_mgr_begin_speech_detected_cb callback = NULL; + void* user_data = NULL; + + vc_mgr_client_get_speech_detected_cb(g_vc_m, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Client speech detected callback is NULL"); + return EINA_FALSE; + } + + vc_mgr_client_use_callback(g_vc_m); + callback(user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "Speech detected callback called"); + + return EINA_FALSE; +} + +void __vc_mgr_cb_speech_detected() +{ + __vc_mgr_speech_detected(NULL); + + return; +} + +int vc_mgr_set_all_result_cb(vc_mgr_all_result_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_all_result_cb(g_vc_m, callback, user_data); + + SLOG(LOG_DEBUG, TAG_VCM, "[SUCCESS] Set all result callback"); + + return 0; +} + +int vc_mgr_unset_all_result_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_all_result_cb(g_vc_m, NULL, NULL); + + return 0; +} + +int vc_mgr_set_result_cb(vc_result_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_result_cb(g_vc_m, callback, user_data); + + return 0; +} + +int vc_mgr_unset_result_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset result callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset result callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_result_cb(g_vc_m, NULL, NULL); + + return 0; +} + +static Eina_Bool __vc_mgr_notify_error(void *data) +{ + vc_h vc_m = (vc_h)data; + + vc_error_cb callback = NULL; + void* user_data = NULL; + int reason; + + vc_mgr_client_get_error_cb(vc_m, &callback, &user_data); + vc_mgr_client_get_error(vc_m, &reason); + + if (NULL != callback) { + vc_mgr_client_use_callback(vc_m); + callback(reason, user_data); + vc_mgr_client_not_use_callback(vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "Error callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] Error callback is null"); + } + + return EINA_FALSE; +} + +int __vc_mgr_cb_error(int pid, int reason) +{ + if (0 != vc_mgr_client_get_handle(pid, &g_vc_m)) { + SLOG(LOG_ERROR, TAG_VCM, "Handle is not valid"); + return -1; + } + + vc_mgr_client_set_error(g_vc_m, reason); + __vc_mgr_notify_error(g_vc_m); + + return 0; +} + +static Eina_Bool __vc_mgr_notify_state_changed(void *data) +{ + vc_state_changed_cb changed_callback = NULL; + void* user_data; + + vc_mgr_client_get_state_changed_cb(g_vc_m, &changed_callback, &user_data); + + vc_state_e current_state; + vc_state_e before_state; + + vc_mgr_client_get_before_state(g_vc_m, ¤t_state, &before_state); + + if (NULL != changed_callback) { + vc_mgr_client_use_callback(g_vc_m); + changed_callback(before_state, current_state, user_data); + vc_mgr_client_not_use_callback(g_vc_m); + SLOG(LOG_DEBUG, TAG_VCM, "State changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] State changed callback is null"); + } + + return EINA_FALSE; +} + +int vc_mgr_set_state_changed_cb(vc_state_changed_cb callback, void* user_data) +{ + if (callback == NULL) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_state_changed_cb(g_vc_m, callback, user_data); + + return 0; +} + +int vc_mgr_unset_state_changed_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_state_changed_cb(g_vc_m, NULL, NULL); + + return 0; +} + +int vc_mgr_set_service_state_changed_cb(vc_service_state_changed_cb callback, void* user_data) +{ + if (callback == NULL) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_service_state_changed_cb(g_vc_m, callback, user_data); + + return 0; +} + +int vc_mgr_unset_service_state_changed_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_service_state_changed_cb(g_vc_m, NULL, NULL); + return 0; +} + +int vc_mgr_set_speech_detected_cb(vc_mgr_begin_speech_detected_cb callback, void* user_data) +{ + if (callback == NULL) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set speech detected callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_speech_detected_cb(g_vc_m, callback, user_data); + + return 0; +} + +int vc_mgr_unset_speech_detected_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset state changed callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset state changed callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_speech_detected_cb(g_vc_m, NULL, NULL); + return 0; +} + +int vc_mgr_set_current_language_changed_cb(vc_current_language_changed_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set current language changed : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set current language changed : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_current_lang_changed_cb(g_vc_m, callback, user_data); + + return 0; +} + +int vc_mgr_unset_current_language_changed_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset current language changed : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset current language changed : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_current_lang_changed_cb(g_vc_m, NULL, NULL); + + return 0; +} + +int vc_mgr_set_error_cb(vc_error_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set error callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Set error callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_error_cb(g_vc_m, callback, user_data); + + return 0; +} + +int vc_mgr_unset_error_cb() +{ + vc_state_e state; + if (0 != vc_mgr_client_get_client_state(g_vc_m, &state)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset error callback : A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Unset error callback : Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_mgr_client_set_error_cb(g_vc_m, NULL, NULL); + + return 0; +} + +static bool __vc_mgr_check_demandable_client(int pid) +{ + if (0 == g_slist_length(g_demandable_client_list)) { + SLOG(LOG_WARN, TAG_VCM, "[WARNING] No demandable clients"); + return false; + } + + char appid[128] = {'\0', }; + aul_app_get_appid_bypid(pid, appid, sizeof(appid)); + + if (0 >= strlen(appid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] No appid"); + return false; + } + SLOG(LOG_DEBUG, TAG_VCM, "[CHECK] Appid - %s", appid); + + GSList *iter = NULL; + vc_demandable_client_s* temp_client; + iter = g_slist_nth(g_demandable_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->appid) { + if (!strcmp(temp_client->appid, appid)) { + SLOG(LOG_DEBUG, TAG_VCM, "pid(%d) is available", pid); + return true; + } + } + } + + iter = g_slist_next(iter); + } + + return false; +} + +/* Authority */ +int __vc_mgr_request_auth_enable(int pid) +{ + if (false == __vc_mgr_check_demandable_client(pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Not demandable client"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* check already authorized */ + if (true == vc_mgr_client_is_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Already authorized"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* add authorized list */ + if (0 != vc_mgr_client_add_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to add authorized client"); + return VC_ERROR_OPERATION_FAILED; + } + + /* foreground check */ + int fore_pid = 0; + if (0 != vc_config_mgr_get_foreground(&fore_pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to get foreground"); + return VC_ERROR_OPERATION_FAILED; + } + + if (pid == fore_pid) { + vc_mgr_client_set_valid_authorized_client(g_vc_m, pid); + } + + return 0; +} + +int __vc_mgr_request_auth_disable(int pid) +{ + /* check authorized */ + if (false == vc_mgr_client_is_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] No authorized"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* remove authorized list */ + if (0 != vc_mgr_client_remove_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to remove authorized client"); + return VC_ERROR_OPERATION_FAILED; + } + + /* check authority valid */ + if (true == vc_mgr_client_is_valid_authorized_client(g_vc_m, pid)) { + SLOG(LOG_DEBUG, TAG_VCM, "Valid authorized client is removed"); + if (0 != vc_mgr_client_set_valid_authorized_client(g_vc_m, -1)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set valid authorized client"); + return VC_ERROR_OPERATION_FAILED; + } + } + + return 0; +} + +static Eina_Bool __request_auth_start(void* data) +{ + SLOG(LOG_DEBUG, TAG_VCM, "Request Start"); + + if (0 != vc_mgr_client_set_start_by_client(g_vc_m, true)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set start by client"); + } + + if (0 != vc_mgr_start(true, false)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Request start is failed"); + /* TODO - Error handling? */ + } + + if (0 != vc_mgr_client_set_start_by_client(g_vc_m, false)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to set start by client"); + } + + + return EINA_FALSE; +} + +int __vc_mgr_request_auth_start(int pid) +{ + /* check authorized */ + if (false == vc_mgr_client_is_valid_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] No valid authorized client"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* add timer for start recording */ + ecore_timer_add(0, __request_auth_start, NULL); + + return 0; +} + +static Eina_Bool __request_auth_stop(void* data) +{ + SLOG(LOG_DEBUG, TAG_VCM, "Request Stop"); + + if (0 != vc_mgr_stop()) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Request stop is failed"); + /* TODO - Error handling? */ + } + + return EINA_FALSE; +} + +int __vc_mgr_request_auth_stop(int pid) +{ + /* check authorized */ + if (false == vc_mgr_client_is_valid_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] No valid authorized client"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* add timer for start recording */ + ecore_timer_add(0, __request_auth_stop, NULL); + + return 0; +} + +static Eina_Bool __request_auth_cancel(void* data) +{ + SLOG(LOG_DEBUG, TAG_VCM, "Request Cancel"); + + if (0 != vc_mgr_cancel()) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Request cancel is failed"); + /* TODO - Error handling? */ + } + + return EINA_FALSE; +} + +int __vc_mgr_request_auth_cancel(int pid) +{ + /* check authorized */ + if (false == vc_mgr_client_is_valid_authorized_client(g_vc_m, pid)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] No valid authorized client"); + return VC_ERROR_INVALID_PARAMETER; + } + + /* add timer for start recording */ + ecore_timer_add(0, __request_auth_cancel, NULL); + + return 0; +} \ No newline at end of file diff --git a/client/vc_mgr_client.c b/client/vc_mgr_client.c new file mode 100644 index 0000000..234c81e --- /dev/null +++ b/client/vc_mgr_client.c @@ -0,0 +1,912 @@ +/* +* Copyright (c) 2011-2015 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 "vc_main.h" +#include "vc_mgr_client.h" + +typedef struct { + /* base info */ + vc_h vc; + int pid; + int uid; /*<< unique id = pid + handle */ + + vc_mgr_all_result_cb all_result_cb; + void* all_result_user_data; + vc_result_cb result_cb; + void* result_user_data; + + vc_error_cb error_cb; + void* error_user_data; + vc_service_state_changed_cb service_state_changed_cb; + void* service_state_changed_user_data; + vc_state_changed_cb state_changed_cb; + void* state_changed_user_data; + vc_mgr_begin_speech_detected_cb speech_detected_cb; + void* speech_detected_user_data; + vc_current_language_changed_cb current_lang_changed_cb; + void* current_lang_changed_user_data; + + /* All result */ + vc_result_event_e all_result_event; + char* all_result_text; + + /* exclusive command flag */ + bool exclusive_cmd_option; + + /* system result */ + int result_event; + char* result_text; + + /* service state */ + vc_service_state_e service_state; + + /* state */ + vc_state_e before_state; + vc_state_e current_state; + + /* language */ + char* before_language; + char* current_language; + + /* audio type */ + char* audio_id; + + /* mutex */ + int cb_ref_count; + + /* error data */ + int reason; + + /* Authorized */ + GSList* authorized_client_list; + int valid_authorized_pid; + bool start_by_client; +}vc_mgr_client_s; + +typedef struct { + int pid; +}vc_authorized_client_s; + +static GSList *g_mgr_client_list = NULL; + +static vc_mgr_client_s* __mgr_client_get(vc_h vc) +{ + if (vc == NULL) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Input parameter is NULL"); + return NULL; + } + + vc_mgr_client_s *data = NULL; + + int count = g_slist_length(g_mgr_client_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_mgr_client_list, i); + + if (NULL != data) { + if (vc->handle == data->vc->handle) { + return data; + } + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] Fail to get client by vc"); + + return NULL; +} + +int vc_mgr_client_create(vc_h* vc) +{ + vc_mgr_client_s *client = NULL; + + client = (vc_mgr_client_s*)calloc(1, sizeof(vc_mgr_client_s)); + if (NULL == client) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to allocate memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + vc_h temp = (vc_h)calloc(1, sizeof(struct vc_s)); + if (NULL == temp) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to allocate memory"); + free(client); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp->handle = getpid(); + + /* initialize client data */ + client->vc = temp; + client->pid = getpid(); + client->uid = temp->handle; + + client->all_result_cb = NULL; + client->all_result_user_data = NULL; + client->result_cb = NULL; + client->result_user_data = NULL; + + client->error_cb = NULL; + client->error_user_data = NULL; + client->service_state_changed_cb = NULL; + client->service_state_changed_user_data = NULL; + client->state_changed_cb = NULL; + client->state_changed_user_data = NULL; + client->speech_detected_cb = NULL; + client->speech_detected_user_data = NULL; + client->current_lang_changed_cb = NULL; + client->current_lang_changed_user_data = NULL; + + client->exclusive_cmd_option = false; + + client->all_result_event = 0; + client->all_result_text = NULL; + + client->result_event = -1; + client->result_text = NULL; + + client->service_state = -1; + + client->before_state = VC_STATE_INITIALIZED; + client->current_state = VC_STATE_INITIALIZED; + + client->before_language = NULL; + client->current_language = NULL; + + client->audio_id = NULL; + + client->cb_ref_count = 0; + + /* Authoriry */ + client->authorized_client_list = NULL; + client->valid_authorized_pid = -1; + client->start_by_client = false; + + g_mgr_client_list = g_slist_append(g_mgr_client_list, client); + + *vc = temp; + + return 0; +} + +int vc_mgr_client_destroy(vc_h vc) +{ + if (vc == NULL) { + SLOG(LOG_ERROR, TAG_VCM, "Input parameter is NULL"); + return 0; + } + + vc_mgr_client_s *data = NULL; + + int count = g_slist_length(g_mgr_client_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_mgr_client_list, i); + + if (NULL != data) { + if (vc->handle == data->vc->handle) { + g_mgr_client_list = g_slist_remove(g_mgr_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->all_result_text) { + free(data->all_result_text); + } + + free(data); data = NULL; + free(vc); vc = NULL; + + return 0; + } + } + } + + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] client Not found"); + + return -1; +} + +bool vc_mgr_client_is_valid(vc_h vc) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] vc is not valid"); + return false; + } + + return true; +} + +bool vc_mgr_client_is_valid_by_uid(int uid) +{ + vc_mgr_client_s *data = NULL; + + int count = g_slist_length(g_mgr_client_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_mgr_client_list, i); + + if (NULL != data) { + if (uid == data->vc->handle) + return true; + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] Fail to get client by vc"); + + return false; +} + +int vc_mgr_client_get_handle(int uid, vc_h* vc) +{ + vc_mgr_client_s *data = NULL; + + int count = g_slist_length(g_mgr_client_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_mgr_client_list, i); + + if (NULL != data) { + if (uid == data->vc->handle) { + *vc = data->vc; + return 0; + } + } + } + + return -1; +} + +int vc_mgr_client_get_pid(vc_h vc, int* pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) { + SLOG(LOG_DEBUG, TAG_VCM, "[DEBUG] vc is not valid"); + return -1; + } + + *pid = client->pid; + return 0; +} + +/* set/get callback function */ +int vc_mgr_client_set_all_result_cb(vc_h vc, vc_mgr_all_result_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->all_result_cb = callback; + client->all_result_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_all_result_cb(vc_h vc, vc_mgr_all_result_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->all_result_cb; + *user_data = client->all_result_user_data; + + return 0; +} + +int vc_mgr_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->result_cb = callback; + client->result_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->result_cb; + *user_data = client->result_user_data; + + return 0; +} + +int vc_mgr_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->service_state_changed_cb = callback; + client->service_state_changed_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->service_state_changed_cb; + *user_data = client->service_state_changed_user_data; + + return 0; +} + +int vc_mgr_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->state_changed_cb = callback; + client->state_changed_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->state_changed_cb; + *user_data = client->state_changed_user_data; + + return 0; +} + +int vc_mgr_client_set_speech_detected_cb(vc_h vc, vc_mgr_begin_speech_detected_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->speech_detected_cb = callback; + client->speech_detected_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_speech_detected_cb(vc_h vc, vc_mgr_begin_speech_detected_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->speech_detected_cb; + *user_data = client->speech_detected_user_data; + + return 0; +} + +int vc_mgr_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->current_lang_changed_cb = callback; + client->current_lang_changed_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->current_lang_changed_cb; + *user_data = client->current_lang_changed_user_data; + + return 0; +} + +int vc_mgr_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->error_cb = callback; + client->error_user_data = user_data; + + return 0; +} + +int vc_mgr_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *callback = client->error_cb; + *user_data = client->error_user_data; + + return 0; +} + + +/* set/get option */ +int vc_mgr_client_set_service_state(vc_h vc, vc_service_state_e state) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->service_state = state; + + return 0; +} + +int vc_mgr_client_get_service_state(vc_h vc, vc_service_state_e* state) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *state = client->service_state; + + return 0; +} + +int vc_mgr_client_set_client_state(vc_h vc, vc_state_e state) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->before_state = client->current_state; + client->current_state = state; + + return 0; +} + +int vc_mgr_client_get_client_state(vc_h vc, vc_state_e* state) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *state = client->current_state; + + return 0; +} + +int vc_mgr_client_get_client_state_by_uid(int uid, vc_state_e* state) +{ + vc_mgr_client_s *data = NULL; + + int count = g_slist_length(g_mgr_client_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_mgr_client_list, i); + + if (NULL != data) { + if (uid == data->vc->handle) { + *state = data->current_state; + return 0; + } + } + } + + return -1; +} + +int vc_mgr_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *before_state = client->before_state; + *state = client->current_state; + + return 0; +} + +int vc_mgr_client_set_error(vc_h vc, int reason) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->reason = reason; + + return 0; +} + +int vc_mgr_client_get_error(vc_h vc, int* reason) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *reason = client->reason; + + return 0; +} + +int vc_mgr_client_set_exclusive_command(vc_h vc, bool value) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->exclusive_cmd_option = value; + + return 0; +} + +bool vc_mgr_client_get_exclusive_command(vc_h vc) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + return client->exclusive_cmd_option; +} + +int vc_mgr_client_set_all_result(vc_h vc, int event, const char* result_text) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->all_result_event = event; + + if (NULL != client->all_result_text) { + free(client->all_result_text); + } + client->all_result_text = strdup(result_text); + + return 0; +} + +int vc_mgr_client_get_all_result(vc_h vc, int* event, char** result_text) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *event = client->all_result_event; + if (NULL != result_text) { + if (NULL != client->all_result_text) { + *result_text = strdup(client->all_result_text); + } + } + + return 0; +} + +int vc_mgr_client_unset_all_result(vc_h vc) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->all_result_event = -1; + + if (NULL != client->all_result_text) { + free(client->all_result_text); + client->all_result_text = NULL; + } + + return 0; +} + +int vc_mgr_client_set_audio_type(vc_h vc, const char* audio_id) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + if (NULL != audio_id) { + if (NULL != client->audio_id) { + free(client->audio_id); + client->audio_id = NULL; + } + client->audio_id = strdup(audio_id); + } + + return 0; +} + +int vc_mgr_client_get_audio_type(vc_h vc, char** audio_id) +{ + if (NULL == audio_id) { + return -1; + } + + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + if (NULL != client->audio_id) + *audio_id = strdup(client->audio_id); + else + *audio_id = NULL; + + return 0; +} + +/* utils */ +int vc_mgr_client_get_count() +{ + return g_slist_length(g_mgr_client_list); +} + +int vc_mgr_client_use_callback(vc_h vc) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->cb_ref_count++; + return 0; +} + +int vc_mgr_client_not_use_callback(vc_h vc) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->cb_ref_count--; + return 0; +} + +/* Authority */ +int vc_mgr_client_add_authorized_client(vc_h vc, int pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + vc_authorized_client_s *authorized_client = NULL; + + authorized_client = (vc_authorized_client_s*)calloc(1, sizeof(vc_authorized_client_s)); + if (NULL == authorized_client) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to make authorized client"); + return VC_ERROR_OPERATION_FAILED; + } + + authorized_client->pid = pid; + + client->authorized_client_list = g_slist_append(client->authorized_client_list, authorized_client); + + SLOG(LOG_DEBUG, TAG_VCM, "Add authorized client - %d", pid); + + return 0; +} + +int vc_mgr_client_remove_authorized_client(vc_h vc, int pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + vc_authorized_client_s *data = NULL; + + int count = g_slist_length(client->authorized_client_list); + int i; + + for (i = 0; i < count; i++) { + data = g_slist_nth_data(client->authorized_client_list, i); + + if (NULL != data) { + if (pid == data->pid) { + client->authorized_client_list = g_slist_remove(client->authorized_client_list, data); + + free(data); + data = NULL; + + SLOG(LOG_DEBUG, TAG_VCM, "Remove authorized client - %d", pid); + return 0; + } + } + } + + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] client Not found"); + + return VC_ERROR_OPERATION_FAILED; +} + +bool vc_mgr_client_is_authorized_client(vc_h vc, int pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + vc_authorized_client_s *data = NULL; + + int count = g_slist_length(client->authorized_client_list); + int i; + + for (i = 0; i < count; i++) { + data = g_slist_nth_data(client->authorized_client_list, i); + + if (NULL != data) { + if (pid == data->pid) { + SLOG(LOG_DEBUG, TAG_VCM, "Authorized client - %d", pid); + return true; + } + } + } + + SLOG(LOG_DEBUG, TAG_VCM, "Un-Authorized client - %d", pid); + + return false; +} + +int vc_mgr_client_set_valid_authorized_client(vc_h vc, int pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->valid_authorized_pid = pid; + + return 0; +} + +int vc_mgr_client_get_valid_authorized_client(vc_h vc, int* pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *pid = client->valid_authorized_pid; + + return 0; +} + +bool vc_mgr_client_is_valid_authorized_client(vc_h vc, int pid) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + if (pid == client->valid_authorized_pid) + return true; + else + return false; +} + +int vc_mgr_client_set_start_by_client(vc_h vc, bool option) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + client->start_by_client = option; + + return 0; +} + +int vc_mgr_client_get_start_by_client(vc_h vc, bool* option) +{ + vc_mgr_client_s* client = __mgr_client_get(vc); + + /* check handle */ + if (NULL == client) + return VC_ERROR_INVALID_PARAMETER; + + *option = client->start_by_client; + + return 0; +} \ No newline at end of file diff --git a/client/vc_mgr_client.h b/client/vc_mgr_client.h new file mode 100644 index 0000000..d30ab97 --- /dev/null +++ b/client/vc_mgr_client.h @@ -0,0 +1,138 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_MANAGER_CLIENT_H_ +#define __VC_MANAGER_CLIENT_H_ + + +#include "vc_info_parser.h" +#include "voice_control_manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* Common function +*/ +int vc_mgr_client_create(vc_h* vc); + +int vc_mgr_client_destroy(vc_h vc); + +bool vc_mgr_client_is_valid(vc_h vc); + +bool vc_mgr_client_is_valid_by_uid(int uid); + +int vc_mgr_client_get_handle(int uid, vc_h* vc); + +int vc_mgr_client_get_pid(vc_h vc, int* pid); + +/* +* set/get callback function +*/ +int vc_mgr_client_set_all_result_cb(vc_h vc, vc_mgr_all_result_cb callback, void* user_data); + +int vc_mgr_client_get_all_result_cb(vc_h vc, vc_mgr_all_result_cb* callback, void** user_data); + +int vc_mgr_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data); + +int vc_mgr_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data); + +int vc_mgr_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data); + +int vc_mgr_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data); + +int vc_mgr_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data); + +int vc_mgr_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data); + +int vc_mgr_client_set_speech_detected_cb(vc_h vc, vc_mgr_begin_speech_detected_cb callback, void* user_data); + +int vc_mgr_client_get_speech_detected_cb(vc_h vc, vc_mgr_begin_speech_detected_cb* callback, void** user_data); + +int vc_mgr_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data); + +int vc_mgr_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data); + +int vc_mgr_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data); + +int vc_mgr_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data); + + +/* +* set/get option +*/ +int vc_mgr_client_set_service_state(vc_h vc, vc_service_state_e state); + +int vc_mgr_client_get_service_state(vc_h vc, vc_service_state_e* state); + +int vc_mgr_client_set_client_state(vc_h vc, vc_state_e state); + +int vc_mgr_client_get_client_state(vc_h vc, vc_state_e* state); + +int vc_mgr_client_get_client_state_by_uid(int uid, vc_state_e* state); + +int vc_mgr_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state); + +int vc_mgr_client_set_error(vc_h vc, int reason); + +int vc_mgr_client_get_error(vc_h vc, int* reason); + +int vc_mgr_client_set_exclusive_command(vc_h vc, bool value); + +bool vc_mgr_client_get_exclusive_command(vc_h vc); + +int vc_mgr_client_set_all_result(vc_h vc, int event, const char* result_text); + +int vc_mgr_client_get_all_result(vc_h vc, int* event, char** result_text); + +int vc_mgr_client_unset_all_result(vc_h vc); + +int vc_mgr_client_set_audio_type(vc_h vc, const char* audio_id); + +int vc_mgr_client_get_audio_type(vc_h vc, char** audio_id); + + +/* utils */ +int vc_mgr_client_get_count(); + +int vc_mgr_client_use_callback(vc_h vc); + +int vc_mgr_client_not_use_callback(vc_h vc); + +/* Authority */ +int vc_mgr_client_add_authorized_client(vc_h vc, int pid); + +int vc_mgr_client_remove_authorized_client(vc_h vc, int pid); + +bool vc_mgr_client_is_authorized_client(vc_h vc, int pid); + +int vc_mgr_client_set_valid_authorized_client(vc_h vc, int pid); + +int vc_mgr_client_get_valid_authorized_client(vc_h vc, int* pid); + +bool vc_mgr_client_is_valid_authorized_client(vc_h vc, int pid); + +int vc_mgr_client_set_start_by_client(vc_h vc, bool option); + +int vc_mgr_client_get_start_by_client(vc_h vc, bool* option); + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_MANAGER_CLIENT_H_ */ diff --git a/client/vc_mgr_dbus.c b/client/vc_mgr_dbus.c new file mode 100644 index 0000000..be13390 --- /dev/null +++ b/client/vc_mgr_dbus.c @@ -0,0 +1,1487 @@ +/* +* Copyright (c) 2011-2015 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 "vc_main.h" +#include "vc_mgr_client.h" +#include "vc_mgr_dbus.h" +#include "vc_command.h" + + +static int g_m_waiting_time = 3000; + +static Ecore_Fd_Handler* g_m_fd_handler = NULL; + +static DBusConnection* g_m_conn = NULL; + + +extern void __vc_mgr_cb_all_result(); + +extern void __vc_mgr_cb_system_result(); + +extern void __vc_mgr_cb_speech_detected(); + +extern int __vc_mgr_cb_error(int pid, int reason); + +/* Authority */ +extern int __vc_mgr_request_auth_enable(int pid); + +extern int __vc_mgr_request_auth_disable(int pid); + +extern int __vc_mgr_request_auth_start(int pid); + +extern int __vc_mgr_request_auth_stop(int pid); + +extern int __vc_mgr_request_auth_cancel(int pid); + +static Eina_Bool vc_mgr_listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler) +{ + DBusConnection* conn = (DBusConnection*)data; + DBusMessage* msg = NULL; + DBusMessage *reply = NULL; + + if (NULL == conn) + return ECORE_CALLBACK_RENEW; + + dbus_connection_read_write_dispatch(conn, 50); + + msg = dbus_connection_pop_message(conn); + + /* loop again if we haven't read a message */ + if (NULL == msg) { + return ECORE_CALLBACK_RENEW; + } + + DBusError err; + dbus_error_init(&err); + + char if_name[64]; + snprintf(if_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, getpid()); + + if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_HELLO)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== 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_VCM, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (pid > 0) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc get hello : pid(%d) ", pid); + response = 1; + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc get hello : invalid pid "); + } + + 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(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc get hello : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc get hello : result(%d)", response); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc get hello : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + } /* VCD_METHOD_HELLO */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_SPEECH_DETECTED)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get Speech detected"); + + __vc_mgr_cb_speech_detected(); + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get speech detected : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr get speech detected"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get speech detected : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + }/* VCD_MANAGER_METHOD_SPEECH_DETECTED */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_ALL_RESULT)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get All Result"); + + __vc_mgr_cb_all_result(); + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get all result : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr get all result"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get all result : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + }/* VCD_MANAGER_METHOD_ALL_RESULT */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_RESULT)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get System Result"); + + __vc_mgr_cb_system_result(); + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get system result : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr get system result"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get system result : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + + }/* VCD_MANAGER_METHOD_RESULT */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_MANAGER_METHOD_ERROR)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get Error"); + int pid; + int reason; + char* err_msg; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &reason, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc Get Error message : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc Get Error message : pid(%d), reason(%d), msg(%s)", pid, reason, err_msg); + __vc_mgr_cb_error(pid, reason); + } + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc Error message : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc Error message"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc Error message : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + }/* VCD_MANAGER_METHOD_ERROR */ + + /* Authority */ + else if (dbus_message_is_method_call(msg, if_name, VC_METHOD_AUTH_ENABLE)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get request auth enable"); + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc request auth enable : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc request auth enable : pid(%d)", pid); + ret = __vc_mgr_request_auth_enable(pid); + } + + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + if (!dbus_connection_send(conn, reply ,NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth enable : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc request auth enable : ret(%d)", ret); + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth enable : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + }/* VC_METHOD_AUTH_ENABLE */ + + else if (dbus_message_is_method_call(msg, if_name, VC_METHOD_AUTH_DISABLE)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get request auth disable"); + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc request auth disable : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc request auth disable : pid(%d)", pid); + ret = __vc_mgr_request_auth_disable(pid); + } + + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth disable : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc request auth disable : ret(%d)", ret); + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth disable : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + }/* VC_METHOD_AUTH_DISABLE */ + + else if (dbus_message_is_method_call(msg, if_name, VC_METHOD_AUTH_START)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get request auth start"); + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc request auth start : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc request auth start : pid(%d)", pid); + ret = __vc_mgr_request_auth_start(pid); + } + + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth start : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc request auth start : ret(%d)", ret); + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth start : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + }/* VC_METHOD_AUTH_START */ + + else if (dbus_message_is_method_call(msg, if_name, VC_METHOD_AUTH_STOP)) { + SLOG(LOG_DEBUG,TAG_VCM, "===== Get request auth stop"); + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc request auth stop : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc request auth stop : pid(%d)", pid); + ret = __vc_mgr_request_auth_stop(pid); + } + + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth stop : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc request auth stop : ret(%d)", ret); + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth stop : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + }/* VC_METHOD_AUTH_STOP */ + + else if (dbus_message_is_method_call(msg, if_name, VC_METHOD_AUTH_CANCEL)) { + SLOG(LOG_DEBUG, TAG_VCM, "===== Get request auth cancel"); + int pid; + int ret = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc request auth cancel : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc request auth cancel : pid(%d)", pid); + ret = __vc_mgr_request_auth_cancel(pid); + } + + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + dbus_message_append_args(reply, + DBUS_TYPE_INT32, &ret, + DBUS_TYPE_INVALID); + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth cancel : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc request auth cancel : ret(%d)", ret); + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc request auth cancel : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCM, "====="); + SLOG(LOG_DEBUG, TAG_VCM, " "); + }/* VC_METHOD_AUTH_CANCEL */ + + /* free the message */ + dbus_message_unref(msg); + + return ECORE_CALLBACK_PASS_ON; +} + +int vc_mgr_dbus_open_connection() +{ + if (NULL != g_m_conn) { + SLOG(LOG_WARN, TAG_VCM, "already existed connection "); + return 0; + } + + DBusError err; + int ret; + + /* initialise the error value */ + dbus_error_init(&err); + + /* connect to the DBUS system bus, and check for errors */ + g_m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "Dbus Connection Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL == g_m_conn) { + SLOG(LOG_ERROR, TAG_VCM, "Fail to get dbus connection "); + return VC_ERROR_OPERATION_FAILED; + } + + int pid = getpid(); + + char service_name[64]; + memset(service_name, '\0', 64); + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, pid); + + SLOG(LOG_DEBUG, TAG_VCM, "service name is %s", service_name); + + /* register our name on the bus, and check for errors */ + ret = dbus_bus_request_name(g_m_conn, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "Name Error (%s)", err.message); + dbus_error_free(&err); + } + + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + SLOG(LOG_ERROR, TAG_VCM, "fail dbus_bus_request_name()"); + return -2; + } + + if (NULL != g_m_fd_handler) { + SLOG(LOG_WARN, TAG_VCM, "The handler already exists."); + return 0; + } + + char rule[128]; + snprintf(rule, 128, "type='signal',interface='%s%d'", VC_MANAGER_SERVICE_INTERFACE, pid); + + /* add a rule for which messages we want to see */ + dbus_bus_add_match(g_m_conn, rule, &err); + dbus_connection_flush(g_m_conn); + + if (dbus_error_is_set(&err)) + { + SLOG(LOG_ERROR, TAG_VCM, "Match Error (%s)", err.message); + dbus_error_free(&err); + return VC_ERROR_OPERATION_FAILED; + } + + int fd = 0; + if (1 != dbus_connection_get_unix_fd(g_m_conn, &fd)) { + SLOG(LOG_ERROR, TAG_VCM, "fail to get fd from dbus "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "Get fd from dbus : %d", fd); + } + + g_m_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)vc_mgr_listener_event_callback, g_m_conn, NULL, NULL); + + if (NULL == g_m_fd_handler) { + SLOG(LOG_ERROR, TAG_VCM, "fail to get fd handler from ecore "); + return VC_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int vc_mgr_dbus_close_connection() +{ + DBusError err; + dbus_error_init(&err); + + int pid = getpid(); + + char service_name[64]; + memset(service_name, '\0', 64); + snprintf(service_name, 64, "%s%d", VC_MANAGER_SERVICE_NAME, pid); + + dbus_bus_release_name (g_m_conn, service_name, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + dbus_connection_close(g_m_conn); + + g_m_fd_handler = NULL; + g_m_conn = NULL; + + return 0; +} + +int vc_mgr_dbus_reconnect() +{ + bool connected = dbus_connection_get_is_connected(g_m_conn); + SECURE_SLOG(LOG_DEBUG, TAG_VCM, "[DBUS] %s", connected ? "Connected" : "Not connected"); + + if (false == connected) { + vc_mgr_dbus_close_connection(); + + if (0 != vc_mgr_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_VCM, "[ERROR] Fail to reconnect"); + return -1; + } + + SLOG(LOG_DEBUG, TAG_VCM, "[DBUS] Reconnect"); + } + return 0; +} + +int vc_mgr_dbus_request_hello() +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_HELLO); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> Request vc hello : Fail to make message"); + return VC_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_m_conn, msg, 500, &err); + + if (dbus_error_is_set(&err)) { + dbus_error_free(&err); + } + + dbus_message_unref(msg); + + if (NULL != result_msg) { + dbus_message_unref(result_msg); + result = 0; + } else { + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + + +int vc_mgr_dbus_request_initialize(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_INITIALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr initialize : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr 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; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr initialize : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr initialize : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< Result message is NULL "); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_finalize(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_FINALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr finalize : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr finalize : pid(%d)", pid); + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr finalize : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr finalize : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< Result message is NULL "); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_set_command(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_SET_COMMAND); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr set command : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr set command : pid(%d)", pid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr set command : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr set command : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< Result message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_unset_command(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_UNSET_COMMAND); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr unset command : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr unset command : pid(%d)", pid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr unset command : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr unset command : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< Result message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_demandable_client(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_SET_DEMANDABLE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr set demandable client : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr set demandable client : pid(%d)", pid); + } + + dbus_message_append_args( msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr set demandable client : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr set demandable client : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< Result message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_set_audio_type(int pid, const char* audio_type) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_SET_AUDIO_TYPE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr set audio type : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr set audio type : pid(%d), audio type(%s)", pid, audio_type); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_STRING, &(audio_type), + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr set audio type : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr set audio type : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_get_audio_type(int pid, char** audio_type) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_GET_AUDIO_TYPE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr get audio type : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr get audio type : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + char* temp = NULL; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_STRING, &temp, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + if (NULL != audio_type && NULL != temp) { + *audio_type = strdup(temp); + } + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr get audio type : result = %d audio type = %s", result, temp); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr get audio type : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_set_client_info(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_SET_CLIENT_INFO); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr set client info : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr set client info : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr set client info : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr set client info : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +#if 0 +int vc_mgr_dbus_request_start(int pid, int silence, bool exclusive_command_option) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_START); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr start : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr start : pid(%d), silence(%d) exclusive(%d)", + pid, silence, exclusive_command_option); + } + + int temp = exclusive_command_option; + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &(silence), + DBUS_TYPE_INT32, &(temp), + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr start : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr start : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} +#endif + +int vc_mgr_dbus_request_start(int pid, int silence, bool exclusive_command_option, bool start_by_client) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_START); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr start : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr start : pid(%d), silence(%d) exclusive(%d) start by client(%d)", + pid, silence, exclusive_command_option, start_by_client); + } + + int exclusive = exclusive_command_option; + int by = start_by_client; + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &(silence), + DBUS_TYPE_INT32, &(exclusive), + DBUS_TYPE_INT32, &(by), + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr start : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr start : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_stop(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_MANAGER_METHOD_STOP); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc mgr stop : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc mgr stop : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc mgr stop : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc mgr stop : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_mgr_dbus_request_cancel(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + VC_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + VC_MANAGER_METHOD_CANCEL); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc cancel : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc cancel : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc cancel : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc cancel : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +static DBusMessage* __get_message(int pid, const char* method, int type) +{ + char service_name[64]; + char object_path[64]; + char target_if_name[128]; + + memset(service_name, '\0', 64); + memset(object_path, '\0', 64); + memset(target_if_name, '\0', 128); + + if (VC_COMMAND_TYPE_FOREGROUND == type || VC_COMMAND_TYPE_BACKGROUND == type) { + snprintf(service_name, 64, "%s%d", VC_CLIENT_SERVICE_NAME, pid); + snprintf(object_path, 64, "%s", VC_CLIENT_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_CLIENT_SERVICE_NAME, pid); + } else if (VC_COMMAND_TYPE_WIDGET == type) { + snprintf(service_name, 64, "%s%d", VC_WIDGET_SERVICE_NAME, pid); + snprintf(object_path, 64, "%s", VC_WIDGET_SERVICE_OBJECT_PATH); + snprintf(target_if_name, 128, "%s%d", VC_WIDGET_SERVICE_INTERFACE, pid); + } else { + return NULL; + } + + SLOG(LOG_DEBUG, TAG_VCM, "[Dbus] Service(%s) object(%s) if(%s)", service_name, object_path, target_if_name); + + return dbus_message_new_method_call(service_name, object_path, target_if_name, method); +} + +int vc_mgr_dbus_send_result(int pid, int cmd_type, int result_id) +{ + DBusMessage* msg = NULL; + + switch (cmd_type) { + case VC_COMMAND_TYPE_FOREGROUND: + case VC_COMMAND_TYPE_BACKGROUND: + msg = __get_message(pid, VCD_METHOD_RESULT, cmd_type); + break; + case VC_COMMAND_TYPE_WIDGET: + msg = __get_message(pid, VCD_WIDGET_METHOD_RESULT, cmd_type); + break; + default: + SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Command type is NOT valid(%d)", cmd_type); + return -1; + } + + if (NULL == msg) + SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Message is NULL"); + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &result_id, DBUS_TYPE_INVALID); + + dbus_message_set_no_reply(msg, TRUE); + + /* send the message and flush the connection */ + if (!dbus_connection_send(g_m_conn, msg, NULL)) { + SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Fail to send result message"); + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Dbus] Success to send result"); + + dbus_connection_flush(g_m_conn); + } + + dbus_message_unref(msg); + + return 0; +} + +int vc_mgr_dbus_send_result_selection(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + VC_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + VC_MANAGER_METHOD_RESULT_SELECTION); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCM, ">>>> vc result selection : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCM, ">>>> vc result selection : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + dbus_message_set_no_reply(msg, TRUE); + + if (1 != dbus_connection_send(g_m_conn, msg, NULL)) { + SLOG(LOG_ERROR, TAG_VCM, "[Dbus ERROR] Fail to Send"); + return -1; + } else { + SLOG(LOG_DEBUG, TAG_VCM, "[Dbus] SUCCESS Send"); + dbus_connection_flush(g_m_conn); + return 0; + } + + /* + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_m_conn, msg, g_m_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCM, "[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_VCM, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< vc result selection : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCM, "<<<< vc result selection : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCM, "<<<< Result Message is NULL"); + vc_mgr_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; + */ +} diff --git a/client/vc_mgr_dbus.h b/client/vc_mgr_dbus.h new file mode 100644 index 0000000..e5bce76 --- /dev/null +++ b/client/vc_mgr_dbus.h @@ -0,0 +1,68 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_DBUS_H_ +#define __VC_DBUS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +int vc_mgr_dbus_open_connection(); + +int vc_mgr_dbus_close_connection(); + + +int vc_mgr_dbus_request_hello(); + +int vc_mgr_dbus_request_initialize(int pid); + +int vc_mgr_dbus_request_finalize(int pid); + +int vc_mgr_dbus_request_set_command(int pid); + +int vc_mgr_dbus_request_unset_command(int pid); + +int vc_mgr_dbus_request_demandable_client(int pid); + +int vc_mgr_dbus_request_set_audio_type(int pid, const char* audio_type); + +int vc_mgr_dbus_request_get_audio_type(int pid, char** audio_type); + +int vc_mgr_dbus_request_set_client_info(int pid); + +#if 0 +int vc_mgr_dbus_request_start(int pid, int silence, bool exclusive_command_option); +#endif + +int vc_mgr_dbus_request_start(int pid, int silence, bool exclusive_command_option, bool start_by_client); + +int vc_mgr_dbus_request_stop(int pid); + +int vc_mgr_dbus_request_cancel(int pid); + +int vc_mgr_dbus_send_result(int pid, int cmd_type, int result_id); + +int vc_mgr_dbus_send_result_selection(int pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_DBUS_H_ */ diff --git a/client/vc_setting.c b/client/vc_setting.c new file mode 100644 index 0000000..7ae5467 --- /dev/null +++ b/client/vc_setting.c @@ -0,0 +1,398 @@ +/* +* Copyright (c) 2011-2015 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 "vc_config_mgr.h" +#include "vc_main.h" +#include "voice_control_common.h" +#include "voice_control_setting.h" + +/** +* @brief Enumerations of mode. +*/ +typedef enum { + VC_SETTING_STATE_NONE = 0, + VC_SETTING_STATE_READY +}vc_setting_state_e; + +#define VC_SETTING_CONFIG_HANDLE 300000 + +static vc_setting_state_e g_state = VC_SETTING_STATE_NONE; + +static vc_setting_enabled_changed_cb g_callback; + +static void* g_user_data; + + +const char* vc_tag() +{ + return TAG_VCS; +} + +void __config_lang_changed_cb(const char* before_lang, const char* current_lang) +{ + SLOG(LOG_DEBUG, TAG_VCS, "Lang changed : before(%s) current(%s)", before_lang, current_lang); +} + +void __vc_setting_state_changed_cb(int before_state, int current_state, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCS, "Service State changed : Before(%d) Current(%d)", + before_state, current_state); + return; +} + +void __vc_setting_enabled_changed_cb(bool enabled) +{ + SLOG(LOG_DEBUG, TAG_VCS, "Service enabled changed : %s", enabled ? "on" : "off"); + + if (NULL != g_callback) { + g_callback(enabled, g_user_data); + } + + return; +} + +int vc_setting_initialize(void) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Initialize VC Setting"); + + if (VC_SETTING_STATE_READY == g_state) { + SLOG(LOG_WARN, TAG_VCS, "[WARNING] VC Setting has already been initialized."); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_NONE; + } + + int ret = vc_config_mgr_initialize(getpid() + VC_SETTING_CONFIG_HANDLE); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Fail to initialize config manager"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_OPERATION_FAILED; + } + + ret = vc_config_mgr_set_lang_cb(getpid() + VC_SETTING_CONFIG_HANDLE, __config_lang_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Fail to initialize config manager"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_OPERATION_FAILED; + } + + ret = vc_config_mgr_set_enabled_cb(getpid() + VC_SETTING_CONFIG_HANDLE, __vc_setting_enabled_changed_cb); + + g_state = VC_SETTING_STATE_READY; + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return VC_ERROR_NONE; +} + +//int vc_setting_finalize() +//{ +// SLOG(LOG_DEBUG, TAG_VCS, "===== Finalize VC Setting"); +// +// vc_config_mgr_unset_lang_cb(getpid() + VC_SETTING_CONFIG_HANDLE); +// vc_config_mgr_finalize(getpid() + VC_SETTING_CONFIG_HANDLE); +// +// g_state = VC_SETTING_STATE_NONE; +// +// SLOG(LOG_DEBUG, TAG_VCS, "====="); +// SLOG(LOG_DEBUG, TAG_VCS, " "); +// +// return VC_ERROR_NONE; +//} + +int vc_setting_deinitialize() +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Deinitialize VC Setting"); + + vc_config_mgr_unset_lang_cb(getpid() + VC_SETTING_CONFIG_HANDLE); + vc_config_mgr_finalize(getpid() + VC_SETTING_CONFIG_HANDLE); + + g_state = VC_SETTING_STATE_NONE; + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return VC_ERROR_NONE; +} + +int vc_setting_foreach_supported_languages(vc_setting_supported_language_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Foreach supported languages"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_get_language_list((vc_supported_language_cb)callback, user_data); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Foreach supported languages"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return ret; +} + +int vc_setting_get_language(char** language) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Get default language"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == language) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_get_default_language(language); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Get default language"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return ret; +} + +int vc_setting_set_language(const char* language) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Set default language"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == language) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_set_default_language(language); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Set default language"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return ret; +} + +int vc_setting_set_auto_language(bool value) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Set auto voice"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (value != true && value != false) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Invalid value"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_set_auto_language(value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Set auto language (%s)", value ? "on" : "off"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return ret; +} + +int vc_setting_get_auto_language(bool* value) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Get auto language"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == value) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_get_auto_language(value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Get auto language (%s)", *value ? "true":"false"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return 0; +} + +int vc_setting_set_enabled(bool value) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Set service enabled"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (value != true && value != false) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Invalid value"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_set_enabled(value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Set service enabled (%s)", value ? "on" : "off"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return ret; +} + +int vc_setting_get_enabled(bool* value) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Get service enabled"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == value) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + int ret = vc_config_mgr_get_enabled(value); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Result : %d", ret); + } else { + /* Copy value */ + SLOG(LOG_DEBUG, TAG_VCS, "[SUCCESS] Get service enabled (%s)", *value ? "on" : "off"); + } + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return ret; +} + +int vc_setting_set_enabled_changed_cb(vc_setting_enabled_changed_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Set service enabled callback"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Param is NULL"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + g_callback = callback; + g_user_data = user_data; + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return 0; +} + +int vc_setting_unset_enabled_changed_cb() +{ + SLOG(LOG_DEBUG, TAG_VCS, "===== Unset service enabled callback"); + + if (VC_SETTING_STATE_NONE == g_state) { + SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Not initialized"); + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + return VC_ERROR_INVALID_STATE; + } + + g_callback = NULL; + g_user_data = NULL; + + SLOG(LOG_DEBUG, TAG_VCS, "====="); + SLOG(LOG_DEBUG, TAG_VCS, " "); + + return 0; +} \ No newline at end of file diff --git a/client/vc_widget.c b/client/vc_widget.c new file mode 100644 index 0000000..d04a545 --- /dev/null +++ b/client/vc_widget.c @@ -0,0 +1,1330 @@ +/* +* Copyright (c) 2011-2015 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 "vc_command.h" +#include "vc_config_mgr.h" +#include "vc_info_parser.h" +#include "vc_main.h" +#include "vc_widget_client.h" +#include "vc_widget_dbus.h" +#include "voice_control_command.h" +#include "voice_control_command_expand.h" +#include "voice_control_widget.h" + + +#define VC_WIDGET_CONFIG_HANDLE 200000 + +static bool g_w_is_daemon_started = false; + +static Ecore_Timer* g_w_connect_timer = NULL; + +static Ecore_Timer* g_w_start_timer = NULL; +static Ecore_Timer* g_w_tooltip_timer = NULL; + +static vc_h g_vc_w = NULL; + +static Eina_Bool __vc_widget_notify_state_changed(void *data); +static Eina_Bool __vc_widget_notify_error(void *data); + +const char* vc_tag() +{ + return TAG_VCW; +} + +static const char* __vc_widget_get_error_code(vc_error_e err) +{ + switch(err) { + case VC_ERROR_NONE: return "VC_ERROR_NONE"; break; + case VC_ERROR_OUT_OF_MEMORY: return "VC_ERROR_OUT_OF_MEMORY"; break; + case VC_ERROR_IO_ERROR: return "VC_ERROR_IO_ERROR"; break; + case VC_ERROR_INVALID_PARAMETER:return "VC_ERROR_INVALID_PARAMETER"; break; + case VC_ERROR_TIMED_OUT: return "VC_ERROR_TIMED_OUT"; break; + case VC_ERROR_INVALID_STATE: return "VC_ERROR_INVALID_STATE"; break; + case VC_ERROR_ENGINE_NOT_FOUND: return "VC_ERROR_ENGINE_NOT_FOUND"; break; + case VC_ERROR_OPERATION_FAILED: return "VC_ERROR_OPERATION_FAILED"; break; + default: return "Invalid error code"; break; + } + return NULL; +} + +static int __vc_widget_convert_config_error_code(vc_config_error_e code) +{ + if (code == VC_CONFIG_ERROR_NONE) return VC_ERROR_NONE; + if (code == VC_CONFIG_ERROR_OUT_OF_MEMORY) return VC_ERROR_OUT_OF_MEMORY; + if (code == VC_CONFIG_ERROR_IO_ERROR) return VC_ERROR_IO_ERROR; + if (code == VC_CONFIG_ERROR_INVALID_PARAMETER) return VC_ERROR_INVALID_PARAMETER; + if (code == VC_CONFIG_ERROR_INVALID_STATE) return VC_ERROR_INVALID_STATE; + if (code == VC_CONFIG_ERROR_INVALID_LANGUAGE) return VC_ERROR_INVALID_LANGUAGE; + if (code == VC_CONFIG_ERROR_ENGINE_NOT_FOUND) return VC_ERROR_ENGINE_NOT_FOUND; + if (code == VC_CONFIG_ERROR_OPERATION_FAILED) return VC_ERROR_OPERATION_FAILED; + + return VC_ERROR_NONE; +} + +static void __vc_widget_lang_changed_cb(const char* before_lang, const char* current_lang) +{ + SECURE_SLOG(LOG_DEBUG, TAG_VCW, "Lang changed : Before lang(%s) Current lang(%s)", + before_lang, current_lang); + + vc_current_language_changed_cb callback; + void* lang_user_data; + vc_widget_client_get_current_lang_changed_cb(g_vc_w, &callback, &lang_user_data); + + if (NULL != callback) { + vc_widget_client_use_callback(g_vc_w); + callback(before_lang, current_lang, lang_user_data); + vc_widget_client_not_use_callback(g_vc_w); + SLOG(LOG_DEBUG, TAG_VCW, "Language changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] Language changed callback is null"); + } + + return; +} + +static void __vc_widget_service_state_changed_cb(int before_state, int current_state) +{ + SECURE_SLOG(LOG_DEBUG, TAG_VCW, "Service State changed : Before(%d) Current(%d)", + before_state, current_state); + + /* Save service state */ + vc_widget_client_set_service_state(g_vc_w, (vc_service_state_e)current_state); + + vc_service_state_changed_cb service_callback = NULL; + void* service_user_data; + vc_widget_client_get_service_state_changed_cb(g_vc_w, &service_callback, &service_user_data); + + if (NULL != service_callback) { + vc_widget_client_use_callback(g_vc_w); + service_callback((vc_service_state_e)before_state, (vc_service_state_e)current_state, service_user_data); + vc_widget_client_not_use_callback(g_vc_w); + SLOG(LOG_DEBUG, TAG_VCW, "Service state changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] State changed callback is null"); + } + + return; +} + +int vc_widget_initialize() +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Initialize"); + + /* check handle */ + if (true == vc_widget_client_is_valid(g_vc_w)) { + SLOG(LOG_ERROR, TAG_VCW, "[WARNING] Already initialized"); + return VC_ERROR_NONE; + } + + if (0 == vc_widget_client_get_count()) { + if (0 != vc_widget_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to open connection"); + return VC_ERROR_OPERATION_FAILED; + } + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARN] Already initialized"); + return VC_ERROR_NONE; + } + + if (0 != vc_widget_client_create(&g_vc_w)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to create client!!!!!"); + return VC_ERROR_OUT_OF_MEMORY; + } + + int ret = vc_config_mgr_initialize(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to init config manager : %s", + __vc_widget_get_error_code(__vc_widget_convert_config_error_code(ret))); + vc_widget_client_destroy(g_vc_w); + return __vc_widget_convert_config_error_code(ret); + } + + ret = vc_config_mgr_set_lang_cb(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE, __vc_widget_lang_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to set config changed : %d", ret); + vc_config_mgr_finalize(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + vc_widget_client_destroy(g_vc_w); + return __vc_widget_convert_config_error_code(ret); + } + + ret = vc_config_mgr_set_service_state_cb(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE, __vc_widget_service_state_changed_cb); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to set service state callback : %d", ret); + vc_config_mgr_unset_lang_cb(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + vc_config_mgr_finalize(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + vc_widget_client_destroy(g_vc_w); + return __vc_widget_convert_config_error_code(ret); + } + + int service_state = -1; + if (0 != vc_config_mgr_get_service_state(&service_state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get service state"); + vc_config_mgr_finalize(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + vc_widget_client_destroy(g_vc_w); + return __vc_widget_convert_config_error_code(ret); + } + + vc_widget_client_set_service_state(g_vc_w, service_state); + + SLOG(LOG_DEBUG, TAG_VCW, "[Success] pid(%d)", g_vc_w->handle); + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +static void __vc_widget_internal_unprepare() +{ + int ret = vc_widget_dbus_request_finalize(g_vc_w->handle); + if (0 != ret) { + SLOG(LOG_WARN, TAG_VCW, "[ERROR] Fail to request finalize : %s", __vc_widget_get_error_code(ret)); + } + + g_w_is_daemon_started = false; + + vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_WIDGET); + + return; +} + +int vc_widget_deinitialize() +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Deinitialize"); + + if (false == vc_widget_client_is_valid(g_vc_w)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] NOT initialized"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + vc_state_e state; + vc_widget_client_get_state(g_vc_w, &state); + + /* check state */ + switch (state) { + case VC_STATE_READY: + __vc_widget_internal_unprepare(); + /* no break. need to next step*/ + case VC_STATE_INITIALIZED: + if (NULL != g_w_connect_timer) { + SLOG(LOG_DEBUG, TAG_VCW, "Connect Timer is deleted"); + ecore_timer_del(g_w_connect_timer); + } + + vc_config_mgr_unset_service_state_cb(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + vc_config_mgr_unset_lang_cb(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + vc_config_mgr_finalize(g_vc_w->handle + VC_WIDGET_CONFIG_HANDLE); + + /* Free resources */ + vc_widget_client_destroy(g_vc_w); + g_vc_w = NULL; + break; + case VC_STATE_NONE: + break; + default: + break; + } + + SLOG(LOG_DEBUG, TAG_VCW, "Success: destroy"); + + if (0 != vc_widget_dbus_close_connection()) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to close connection"); + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +static void __vc_widget_fork_vc_daemon() +{ + int pid, i; + pid = fork(); + + switch(pid) { + case -1: + SLOG(LOG_ERROR, TAG_VCW, "Fail to create daemon"); + break; + case 0: + setsid(); + for (i = 0;i < _NSIG;i++) + signal(i, SIG_DFL); + + execl(VC_DAEMON_PATH, VC_DAEMON_PATH, NULL); + break; + default: + break; + } + return; +} + +static Eina_Bool __vc_widget_connect_daemon(void *data) +{ + /* Send hello */ + if (0 != vc_widget_dbus_request_hello()) { + if (false == g_w_is_daemon_started) { + g_w_is_daemon_started = true; + __vc_widget_fork_vc_daemon(); + } + return EINA_TRUE; + } + + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Connect daemon"); + + /* request initialization */ + int ret = -1; + ret = vc_widget_dbus_request_initialize(g_vc_w->handle); + + if (VC_ERROR_ENGINE_NOT_FOUND == ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to initialize : %s", __vc_widget_get_error_code(ret)); + + vc_widget_client_set_error(g_vc_w, VC_ERROR_ENGINE_NOT_FOUND); + ecore_timer_add(0, __vc_widget_notify_error, g_vc_w); + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return EINA_FALSE; + + } else if (VC_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to initialize : %s", __vc_widget_get_error_code(ret)); + + vc_widget_client_set_error(g_vc_w, VC_ERROR_TIMED_OUT); + ecore_timer_add(0, __vc_widget_notify_error, g_vc_w); + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return EINA_FALSE; + } + + vc_widget_client_set_state(g_vc_w, VC_STATE_READY); + ecore_timer_add(0, __vc_widget_notify_state_changed, g_vc_w); + + g_w_connect_timer = NULL; + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return EINA_FALSE; +} + +int vc_widget_prepare() +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Prepare"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + g_w_is_daemon_started = false; + + g_w_connect_timer = ecore_timer_add(0, __vc_widget_connect_daemon, NULL); + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +int vc_widget_unprepare() +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Unprepare"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + __vc_widget_internal_unprepare(); + + vc_widget_client_set_state(g_vc_w, VC_STATE_INITIALIZED); + ecore_timer_add(0, __vc_widget_notify_state_changed, g_vc_w); + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +int vc_widget_foreach_supported_languages(vc_supported_language_cb callback, void* user_data) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Foreach Supported Language"); + + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_config_mgr_get_language_list(callback, user_data); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get languages : %s", __vc_widget_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +int vc_widget_get_current_language(char** language) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Get Current Language"); + + if (NULL == language) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Input parameter is NULL"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = -1; + ret = vc_config_mgr_get_default_language(language); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get current languages : %s", __vc_widget_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return ret; +} + +int vc_widget_get_state(vc_state_e* state) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Get State"); + + if (NULL == state) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e temp; + if (0 != vc_widget_client_get_state(g_vc_w, &temp)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + *state = temp; + + switch(*state) { + case VC_STATE_NONE: SLOG(LOG_DEBUG, TAG_VCW, "Current state is 'None'"); break; + case VC_STATE_INITIALIZED: SLOG(LOG_DEBUG, TAG_VCW, "Current state is 'Created'"); break; + case VC_STATE_READY: SLOG(LOG_DEBUG, TAG_VCW, "Current state is 'Ready'"); break; + default: SLOG(LOG_ERROR, TAG_VCW, "Invalid state"); break; + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +int vc_widget_get_service_state(vc_service_state_e* state) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Get Service State"); + + if (NULL == state) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_state_e temp; + if (0 != vc_widget_client_get_state(g_vc_w, &temp)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + if (temp != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* get service state */ + vc_service_state_e service_state; + if (0 != vc_widget_client_get_service_state(g_vc_w, &service_state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get service state"); + return VC_ERROR_OPERATION_FAILED; + } + + *state = service_state; + + switch(*state) { + case VC_SERVICE_STATE_NONE: SLOG(LOG_DEBUG, TAG_VCW, "Current service state is 'None'"); break; + case VC_SERVICE_STATE_READY: SLOG(LOG_DEBUG, TAG_VCW, "Current service state is 'Ready'"); break; + case VC_SERVICE_STATE_RECORDING: SLOG(LOG_DEBUG, TAG_VCW, "Current service state is 'Recording'"); break; + case VC_SERVICE_STATE_PROCESSING: SLOG(LOG_DEBUG, TAG_VCW, "Current service state is 'Processing'"); break; + default: SLOG(LOG_ERROR, TAG_VCW, "Invalid service state"); break; + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} + +int vc_widget_set_foreground(bool value) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Set foreground state"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + SLOG(LOG_DEBUG, TAG_VCW, "Set foreground : pid(%d) value(%s)", getpid(), value ? "true" : "false"); + int ret = vc_config_mgr_set_foreground(getpid(), value); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to set foreground : %s", __vc_widget_get_error_code(ret)); + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} +#if 0 +int vc_widget_is_format_supported(vc_cmd_format_e format, bool* support) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Is command type supported"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not valid"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check support */ + bool non_fixed_support = false; + if (0 != vc_config_mgr_get_nonfixed_support(&non_fixed_support)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get nonfixed support info"); + } + + switch (format) { + case VC_CMD_FORMAT_FIXED: *support = true; break; + case VC_CMD_FORMAT_FIXED_AND_EXTRA: *support = non_fixed_support; break; + case VC_CMD_FORMAT_EXTRA_AND_FIXED: *support = non_fixed_support; break; + default: *support = false; break; + } + + SLOG(LOG_ERROR, TAG_VCW, "[DEBUG] Format(%d) support(%s)", format, *support ? "true" : "false"); + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} +#endif +/** +* @brief Starts recognition. +* +* @param[in] stop_by_silence Silence detection option +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_ERROR_NONE Successful +* @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter. +* @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_OPERATION_FAILED Operation failure +* +* @pre The state should be #VC_STATE_READY. +* @post It will invoke vc_state_changed_cb(), if you register a callback with vc_state_changed_cb(). \n +* If this function succeeds, the state will be #VC_STATE_RECORDING. +* +* @see vc_widget_stop() +* @see vc_widget_cancel() +* @see vc_state_changed_cb() +*/ +#if 0 +int vc_widget_start(bool stop_by_silence, vc_cmd_group_h vc_group) +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Start"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_widget_client_get_service_state(g_vc_w, &service_state); + if (service_state != VC_SERVICE_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: service state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = vc_widget_client_set_command_group(g_vc_w, vc_group); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to set command to client : %d", ret); + return ret; + } + + GSList* list = NULL; + if (0 > vc_cmd_group_get_cmd_list(vc_group, &list)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to get command list : %d", ret); + return ret; + } + + ret = vc_cmd_parser_save_file(getpid(), VC_COMMAND_GROUP_TYPE_WIDGET, list); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to save command group : %s", __vc_widget_get_error_code(ret)); + } else { + int count = 0; + do { + ret = vc_widget_dbus_request_start(g_vc_w->handle, stop_by_silence); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request start : %s", __vc_widget_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] retry request start : %s", __vc_widget_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request"); + break; + } + } + } + } while(0 != ret); + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + return VC_ERROR_NONE; +} +#endif + +/** +* @brief Stop interrupt. +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_ERROR_NONE Successful +* @retval #VC_ERROR_INVALID_STATE Invalid state +* @retval #VC_ERROR_OPERATION_FAILED Operation failure +* +* @pre The state should be #VC_STATE_RECORDING. +* @post It will invoke vc_state_changed_cb(), if you register a callback with vc_state_changed_cb(). \n +* If this function succeeds, the state will be #VC_STATE_READY and vc_widget_result_cb() is called. +* +* @see vc_widget_start() +* @see vc_widget_cancel() +* @see vc_state_changed_cb() +*/ +#if 0 +int vc_widget_stop() +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Stop"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_widget_client_get_service_state(g_vc_w, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: service state is not 'RECORDING'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = vc_widget_client_set_command_group(g_vc_w, NULL); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to set command to client : %d", ret); + return ret; + } + + ret = vc_cmd_parser_delete_file(getpid(), VC_COMMAND_GROUP_TYPE_WIDGET); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to delete command group : %s", __vc_widget_get_error_code(ret)); + } + + int count = 0; + do { + ret = vc_widget_dbus_request_stop(g_vc_w->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request stop : %s", __vc_widget_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] retry request stop : %s", __vc_widget_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request"); + break; + } + } + } + } while(0 != ret); + + return 0; +} +#endif + +#if 0 +int vc_widget_cancel() +{ + SLOG(LOG_DEBUG, TAG_VCW, "===== [Widget] Cancel Recognition"); + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_READY) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'READY'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + /* Check service state */ + vc_service_state_e service_state = -1; + vc_widget_client_get_service_state(g_vc_w, &service_state); + if (service_state != VC_SERVICE_STATE_RECORDING && service_state != VC_SERVICE_STATE_PROCESSING) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: service state is not 'RECORDING' or 'PROCESSING'"); + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + return VC_ERROR_INVALID_STATE; + } + + int ret = vc_widget_client_set_command_group(g_vc_w, NULL); + if (0 != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to set command to client : %d", ret); + return ret; + } + + ret = vc_cmd_parser_delete_file(getpid(), VC_COMMAND_TYPE_WIDGET); + if (0 != ret) { + ret = vc_config_convert_error_code((vc_config_error_e)ret); + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to delete command group : %s", __vc_widget_get_error_code(ret)); + } + + int count = 0; + do { + ret = vc_widget_dbus_request_cancel(g_vc_w->handle); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request cancel : %s", __vc_widget_get_error_code(ret)); + break; + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] retry request cancel : %s", __vc_widget_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request"); + break; + } + } + } + } while(0 != ret); + + return 0; +} +#endif + +static Eina_Bool __vc_widget_notify_error(void *data) +{ + vc_error_cb callback = NULL; + void* user_data; + int reason; + + vc_widget_client_get_error_cb(g_vc_w, &callback, &user_data); + vc_widget_client_get_error(g_vc_w, &reason); + + if (NULL != callback) { + vc_widget_client_use_callback(g_vc_w); + callback(reason, user_data); + vc_widget_client_not_use_callback(g_vc_w); + SLOG(LOG_DEBUG, TAG_VCW, "[Error] callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] Error callback is null"); + } + + return EINA_FALSE; +} + +int __vc_widget_cb_error(int pid, int reason) +{ + if (0 != vc_widget_client_get_handle(pid, &g_vc_w)) { + SLOG(LOG_ERROR, TAG_VCW, "Handle is not valid"); + return -1; + } + + vc_widget_client_set_error(g_vc_w, reason); + ecore_timer_add(0, __vc_widget_notify_error, g_vc_w); + + return 0; +} + +static Eina_Bool __vc_widget_start_recording(void *data) +{ + if (NULL != g_w_start_timer) { + ecore_timer_del(g_w_start_timer); + g_w_start_timer = NULL; + } + + vc_widget_send_current_command_list_cb send_command_list_cb = NULL; + void* send_command_user_data = NULL; + vc_cmd_list_h vc_cmd_list = NULL; + + vc_widget_client_get_send_command_list_cb(g_vc_w, &send_command_list_cb, &send_command_user_data); + + if (NULL != send_command_list_cb) { + vc_widget_client_use_callback(g_vc_w); + send_command_list_cb(&vc_cmd_list, send_command_user_data); + vc_widget_client_not_use_callback(g_vc_w); + SLOG(LOG_DEBUG, TAG_VCW, "client result callback called"); + + } else { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] User show tooltip callback is NULL"); + } + + bool widget_command = false; + int ret; + + if (NULL != vc_cmd_list) { + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + ret = vc_cmd_parser_save_file(getpid(), VC_COMMAND_TYPE_WIDGET, list->list); + if (0 == ret) { + /* widget command is valid */ + widget_command = true; + SLOG(LOG_DEBUG, TAG_VCW, "Widget command is valid"); + } else { + ret = VC_ERROR_OPERATION_FAILED; + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to save command group : %s", __vc_widget_get_error_code(ret)); + } + } + + ret = -1; + int count = 0; + while (0 != ret) { + ret = vc_widget_dbus_request_start_recording(g_vc_w->handle, widget_command); + if (0 != ret) { + if (VC_ERROR_TIMED_OUT != ret) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request start recording to daemon : %s", __vc_widget_get_error_code(ret)); + return EINA_FALSE; + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] retry start recording : %s", __vc_widget_get_error_code(ret)); + usleep(10000); + count++; + if (VC_RETRY_COUNT == count) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to request"); + return EINA_FALSE; + } + } + } + } + + return EINA_FALSE; +} + +static Eina_Bool __vc_widget_notify_tooltip(void *data) +{ + if (NULL != g_w_tooltip_timer) { + ecore_timer_del(g_w_tooltip_timer); + g_w_tooltip_timer = NULL; + } + + vc_widget_show_tooltip_cb callback; + void* user_data; + bool show; + + vc_widget_client_get_show_tooltip_cb(g_vc_w, &callback, &user_data); + vc_widget_client_get_show_tooltip(g_vc_w, &show); + + if (NULL != callback) { + vc_widget_client_use_callback(g_vc_w); + callback(show, user_data); + vc_widget_client_not_use_callback(g_vc_w); + SLOG(LOG_DEBUG, TAG_VCW, "client result callback called"); + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] Show tooltip callback is NULL"); + } + + if (true == show) { + g_w_start_timer = ecore_timer_add(0, __vc_widget_start_recording, NULL); + } + + return EINA_FALSE; +} + +void __vc_widget_cb_show_tooltip(int pid, bool show) +{ + if (0 != vc_widget_client_get_handle(pid, &g_vc_w)) { + SLOG(LOG_ERROR, TAG_VCW, "Handle is not valid"); + return; + } + + vc_widget_client_set_show_tooltip(g_vc_w, show); + g_w_tooltip_timer = ecore_timer_add(0, __vc_widget_notify_tooltip, NULL); + + return; +} + +static Eina_Bool __vc_widget_notify_result(void *data) +{ + char* temp_text; + int event; + vc_cmd_list_h vc_cmd_list = NULL; + + vc_result_cb callback = NULL; + void* user_data = NULL; + + vc_widget_client_get_result_cb(g_vc_w, &callback, &user_data); + if (NULL == callback) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Client result callback is NULL"); + return EINA_FALSE; + } + + if (0 != vc_cmd_list_create(&vc_cmd_list)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to create command list"); + return EINA_FALSE; + } + + vc_info_parser_get_result(&temp_text, &event, NULL, getpid(), vc_cmd_list, false); + + SLOG(LOG_DEBUG, TAG_VCW, "Result info : result text(%s) event(%d)", temp_text, event); + + vc_cmd_print_list(vc_cmd_list); + + vc_widget_client_use_callback(g_vc_w); + callback(event, vc_cmd_list, temp_text, user_data); + vc_widget_client_not_use_callback(g_vc_w); + + SLOG(LOG_DEBUG, TAG_VCW, "Widget result callback called"); + + /* Release result */ + if (NULL != temp_text) free(temp_text); + + vc_cmd_list_destroy(vc_cmd_list, true); + + return EINA_FALSE; +} + +void __vc_widget_cb_result() +{ + ecore_timer_add(0, __vc_widget_notify_result, NULL); + + return; +} + +static Eina_Bool __vc_widget_notify_state_changed(void *data) +{ + vc_state_changed_cb changed_callback = NULL; + void* user_data; + + vc_widget_client_get_state_changed_cb(g_vc_w, &changed_callback, &user_data); + + vc_state_e current_state; + vc_state_e before_state; + + vc_widget_client_get_before_state(g_vc_w, ¤t_state, &before_state); + + if (NULL != changed_callback) { + vc_widget_client_use_callback(g_vc_w); + changed_callback(before_state, current_state, user_data); + vc_widget_client_not_use_callback(g_vc_w); + SLOG(LOG_DEBUG, TAG_VCW, "State changed callback is called"); + } else { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] State changed callback is null"); + } + + return EINA_FALSE; +} + +int vc_widget_set_result_cb(vc_result_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_result_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unset_result_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_result_cb(g_vc_w, NULL, NULL); + + return 0; +} + +int vc_widget_set_show_tooltip_cb(vc_widget_show_tooltip_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_show_tooltip_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unset_show_tooltip_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_show_tooltip_cb(g_vc_w, NULL, NULL); + + return 0; +} + +int vc_widget_set_send_current_command_list_cb(vc_widget_send_current_command_list_cb callback, void* user_data) +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_send_command_list_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unsset_send_current_command_list_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_send_command_list_cb(g_vc_w, NULL, NULL); + + return 0; +} + +int vc_widget_set_service_state_changed_cb(vc_service_state_changed_cb callback, void* user_data) +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_service_state_changed_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unset_service_state_changed_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_service_state_changed_cb(g_vc_w, NULL, NULL); + + return 0; +} + +int vc_widget_set_state_changed_cb(vc_state_changed_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_state_changed_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unset_state_changed_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_state_changed_cb(g_vc_w, NULL, NULL); + + return 0; +} + +int vc_widget_set_current_language_changed_cb(vc_current_language_changed_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_current_lang_changed_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unset_current_language_changed_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_current_lang_changed_cb(g_vc_w, NULL, NULL); + + return 0; +} + +int vc_widget_set_error_cb(vc_error_cb callback, void* user_data) +{ + if (NULL == callback) + return VC_ERROR_INVALID_PARAMETER; + + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_error_cb(g_vc_w, callback, user_data); + + return 0; +} + +int vc_widget_unset_error_cb() +{ + vc_state_e state; + if (0 != vc_widget_client_get_state(g_vc_w, &state)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] A handle is not available"); + return VC_ERROR_INVALID_STATE; + } + + /* check state */ + if (state != VC_STATE_INITIALIZED) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Invalid State: Current state is not 'Initialized'"); + return VC_ERROR_INVALID_STATE; + } + + vc_widget_client_set_error_cb(g_vc_w, NULL, NULL); + + return 0; +} + diff --git a/client/vc_widget_client.c b/client/vc_widget_client.c new file mode 100644 index 0000000..a48d3d3 --- /dev/null +++ b/client/vc_widget_client.c @@ -0,0 +1,628 @@ +/* +* Copyright (c) 2011-2015 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 "vc_main.h" +#include "vc_widget_client.h" +#include "voice_control_command.h" +#include "voice_control_common.h" + + +typedef struct { + /* base info */ + vc_h vc; + int pid; + int uid; /*<< unique id = pid + handle */ + int xid; /*<< main X window id */ + + vc_result_cb result_cb; + void* result_user_data; + vc_error_cb error_cb; + void* error_user_data; + vc_service_state_changed_cb service_state_changed_cb; + void* service_state_changed_user_data; + vc_state_changed_cb state_changed_cb; + void* state_changed_user_data; + vc_widget_show_tooltip_cb show_tooltip_cb; + void* show_tooltip_user_data; + vc_current_language_changed_cb current_lang_changed_cb; + void* current_lang_changed_user_data; + + vc_widget_send_current_command_list_cb send_command_list_cb; + void* send_command_list_user_data; + + /* tooltip */ + bool show_tooltip; + + /* service state */ + vc_service_state_e service_state; + + /* state */ + vc_state_e before_state; + vc_state_e current_state; + + /* mutex */ + int cb_ref_count; + + /* error data */ + int reason; +}vc_widget_s; + + +/* widget list */ +static GSList *g_widget_list = NULL; + +static vc_widget_s* __widget_get(vc_h vc) +{ + if (vc == NULL) { + SLOG(LOG_WARN, TAG_VCW, "[WARNING] Input parameter is NULL"); + return NULL; + } + + vc_widget_s *data = NULL; + + int count = g_slist_length(g_widget_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_widget_list, i); + + if (NULL != data) { + if (vc->handle == data->vc->handle) { + return data; + } + } + } + + SLOG(LOG_DEBUG, TAG_VCW, "[DEBUG] Fail to get widget by vc"); + + return NULL; +} + +int vc_widget_client_create(vc_h* vc) +{ + vc_widget_s *widget = NULL; + + widget = (vc_widget_s*)calloc(1, sizeof(vc_widget_s)); + if (NULL == widget) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to allocate memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + vc_h temp = (vc_h)calloc(1, sizeof(struct vc_s)); + if (NULL == temp) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to allocate memory"); + free(widget); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp->handle = getpid(); + + /* initialize widget data */ + widget->vc = temp; + widget->pid = getpid(); + widget->uid = temp->handle; + widget->xid = -1; + + widget->result_cb = NULL; + widget->result_user_data = NULL; + widget->service_state_changed_cb = NULL; + widget->service_state_changed_user_data = NULL; + widget->state_changed_cb = NULL; + widget->state_changed_user_data = NULL; + widget->show_tooltip_cb = NULL; + widget->show_tooltip_user_data = NULL; + widget->error_cb = NULL; + widget->error_user_data = NULL; + + widget->before_state = VC_STATE_INITIALIZED; + widget->current_state = VC_STATE_INITIALIZED; + + widget->cb_ref_count = 0; + + g_widget_list = g_slist_append(g_widget_list, widget); + + *vc = temp; + + return 0; +} + +int vc_widget_client_destroy(vc_h vc) +{ + if (vc == NULL) { + SLOG(LOG_ERROR, TAG_VCW, "Input parameter is NULL"); + return 0; + } + + vc_widget_s *data = NULL; + + int count = g_slist_length(g_widget_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_widget_list, i); + + if (NULL != data) { + if (vc->handle == data->vc->handle) { + g_widget_list = g_slist_remove(g_widget_list, data); + + while (0 != data->cb_ref_count) + { + /* wait for release callback function */ + } + free(data); + free(vc); + + return 0; + } + } + } + + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] widget Not found"); + + return -1; +} + +bool vc_widget_client_is_valid(vc_h vc) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) { + SLOG(LOG_DEBUG, TAG_VCW, "[DEBUG] vc is not valid"); + return false; + } + + return true; +} + +bool vc_widget_client_is_valid_by_uid(int uid) +{ + vc_widget_s *data = NULL; + + int count = g_slist_length(g_widget_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_widget_list, i); + + if (NULL != data) { + if (uid == data->vc->handle) + return true; + } + } + + SLOG(LOG_DEBUG, TAG_VCW, "[DEBUG] Fail to get widget by vc"); + + return false; +} + +int vc_widget_client_get_handle(int uid, vc_h* vc) +{ + vc_widget_s *data = NULL; + + int count = g_slist_length(g_widget_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_widget_list, i); + + if (NULL != data) { + if (uid == data->vc->handle) { + *vc = data->vc; + return 0; + } + } + } + + return -1; +} + +/* set/get callback function */ +int vc_widget_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->result_cb = callback; + widget->result_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->result_cb; + *user_data = widget->result_user_data; + + return 0; +} + +int vc_widget_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->service_state_changed_cb = callback; + widget->service_state_changed_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->service_state_changed_cb; + *user_data = widget->service_state_changed_user_data; + + return 0; +} + +int vc_widget_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->state_changed_cb = callback; + widget->state_changed_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->state_changed_cb; + *user_data = widget->state_changed_user_data; + + return 0; +} + +int vc_widget_client_set_show_tooltip_cb(vc_h vc, vc_widget_show_tooltip_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->show_tooltip_cb = callback; + widget->show_tooltip_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_show_tooltip_cb(vc_h vc, vc_widget_show_tooltip_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->show_tooltip_cb; + *user_data = widget->show_tooltip_user_data; + + return 0; +} + +int vc_widget_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->current_lang_changed_cb = callback; + widget->current_lang_changed_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->current_lang_changed_cb; + *user_data = widget->current_lang_changed_user_data; + + return 0; +} + +int vc_widget_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->error_cb = callback; + widget->error_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->error_cb; + *user_data = widget->error_user_data; + + return 0; +} + +int vc_widget_client_set_send_command_list_cb(vc_h vc, vc_widget_send_current_command_list_cb callback, void* user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->send_command_list_cb = callback; + widget->send_command_list_user_data = user_data; + + return 0; +} + +int vc_widget_client_get_send_command_list_cb(vc_h vc, vc_widget_send_current_command_list_cb* callback, void** user_data) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *callback = widget->send_command_list_cb; + *user_data = widget->send_command_list_user_data; + + return 0; +} + + +/* set/get option */ +int vc_widget_client_set_service_state(vc_h vc, vc_service_state_e state) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->service_state = state; + + return 0; +} + +int vc_widget_client_get_service_state(vc_h vc, vc_service_state_e* state) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *state = widget->service_state; + + return 0; +} + + +int vc_widget_client_set_state(vc_h vc, vc_state_e state) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->before_state = widget->current_state; + widget->current_state = state; + + return 0; +} + +int vc_widget_client_get_state(vc_h vc, vc_state_e* state) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *state = widget->current_state; + + return 0; +} + +int vc_widget_client_get_state_by_uid(int uid, vc_state_e* state) +{ + vc_widget_s *data = NULL; + + int count = g_slist_length(g_widget_list); + int i; + + for (i = 0;i < count;i++) { + data = g_slist_nth_data(g_widget_list, i); + + if (NULL != data) { + if (uid == data->vc->handle) { + *state = data->current_state; + return 0; + } + } + } + + return -1; +} + +int vc_widget_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *before_state = widget->before_state; + *state = widget->current_state; + + return 0; +} + +int vc_widget_client_set_xid(vc_h vc, int xid) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->xid = xid; + + return 0; +} + +int vc_widget_cilent_get_xid(vc_h vc, int* xid) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *xid = widget->xid; + + return 0; +} + +int vc_widget_client_set_error(vc_h vc, int reason) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->reason = reason; + + return 0; +} + +int vc_widget_client_get_error(vc_h vc, int* reason) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *reason = widget->reason; + + return 0; +} + +int vc_widget_client_set_show_tooltip(vc_h vc, bool show) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->show_tooltip = show; + + return 0; +} + +int vc_widget_client_get_show_tooltip(vc_h vc, bool* show) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + *show = widget->show_tooltip; + + return 0; +} + +int vc_widget_client_get_count() +{ + return g_slist_length(g_widget_list); +} + +int vc_widget_client_use_callback(vc_h vc) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->cb_ref_count++; + return 0; +} + +int vc_widget_client_not_use_callback(vc_h vc) +{ + vc_widget_s* widget = __widget_get(vc); + + /* check handle */ + if (NULL == widget) + return VC_ERROR_INVALID_PARAMETER; + + widget->cb_ref_count--; + return 0; +} + diff --git a/client/vc_widget_client.h b/client/vc_widget_client.h new file mode 100644 index 0000000..828038c --- /dev/null +++ b/client/vc_widget_client.h @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_WIDGET_CLIENT_H_ +#define __VC_WIDGET_CLIENT_H_ + +#include "voice_control_common.h" +#include "voice_control_widget.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* Common function +*/ +int vc_widget_client_create(vc_h* vc); + +int vc_widget_client_destroy(vc_h vc); + +bool vc_widget_client_is_valid(vc_h vc); + +bool vc_widget_client_is_valid_by_uid(int uid); + +int vc_widget_client_get_handle(int uid, vc_h* vc); + +/* +* set/get callback function +*/ +int vc_widget_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data); + +int vc_widget_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data); + +int vc_widget_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data); + +int vc_widget_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data); + +int vc_widget_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data); + +int vc_widget_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data); + +int vc_widget_client_set_show_tooltip_cb(vc_h vc, vc_widget_show_tooltip_cb callback, void* user_data); + +int vc_widget_client_get_show_tooltip_cb(vc_h vc, vc_widget_show_tooltip_cb* callback, void** user_data); + +int vc_widget_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data); + +int vc_widget_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data); + +int vc_widget_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data); + +int vc_widget_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data); + +int vc_widget_client_set_send_command_list_cb(vc_h vc, vc_widget_send_current_command_list_cb callback, void* user_data); + +int vc_widget_client_get_send_command_list_cb(vc_h vc, vc_widget_send_current_command_list_cb* callback, void** user_data); + + + +/* +* set/get option +*/ +int vc_widget_client_set_service_state(vc_h vc, vc_service_state_e state); + +int vc_widget_client_get_service_state(vc_h vc, vc_service_state_e* state); + +int vc_widget_client_set_state(vc_h vc, vc_state_e state); + +int vc_widget_client_get_state(vc_h vc, vc_state_e* state); + +int vc_widget_client_get_state_by_uid(int uid, vc_state_e* state); + +int vc_widget_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state); + +int vc_widget_client_set_xid(vc_h vc, int xid); + +int vc_widget_cilent_get_xid(vc_h vc, int* xid); + +int vc_widget_client_set_error(vc_h vc, int reason); + +int vc_widget_client_get_error(vc_h vc, int* reason); + +int vc_widget_client_set_show_tooltip(vc_h vc, bool show); + +int vc_widget_client_get_show_tooltip(vc_h vc, bool* show); + + +/* utils */ +int vc_widget_client_get_count(); + +int vc_widget_client_use_callback(vc_h vc); + +int vc_widget_client_not_use_callback(vc_h vc); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_WIDGET_CLIENT_H_ */ diff --git a/client/vc_widget_dbus.c b/client/vc_widget_dbus.c new file mode 100644 index 0000000..0b1a11d --- /dev/null +++ b/client/vc_widget_dbus.c @@ -0,0 +1,754 @@ +/* +* Copyright (c) 2011-2015 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 "vc_main.h" +#include "vc_widget_client.h" +#include "vc_widget_dbus.h" + + +static int g_w_waiting_time = 3000; + +static Ecore_Fd_Handler* g_w_fd_handler = NULL; + +static DBusConnection* g_w_conn = NULL; + + +extern int __vc_widget_cb_error(int pid, int reason); + +extern void __vc_widget_cb_show_tooltip(int pid, bool show); + +extern void __vc_widget_cb_result(); + + +static Eina_Bool widget_listener_event_callback(void* data, Ecore_Fd_Handler *fd_handler) +{ + DBusConnection* conn = (DBusConnection*)data; + DBusMessage* msg = NULL; + DBusMessage *reply = NULL; + + if (NULL == conn) + return ECORE_CALLBACK_RENEW; + + dbus_connection_read_write_dispatch(conn, 50); + + msg = dbus_connection_pop_message(conn); + + /* loop again if we haven't read a message */ + if (NULL == msg) { + return ECORE_CALLBACK_RENEW; + } + + DBusError err; + dbus_error_init(&err); + + char if_name[64]; + snprintf(if_name, 64, "%s%d", VC_WIDGET_SERVICE_INTERFACE, getpid()); + + if (dbus_message_is_method_call(msg, if_name, VCD_WIDGET_METHOD_HELLO)) { + SLOG(LOG_DEBUG, TAG_VCW, "===== Get widget 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_VCW, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (pid > 0) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget get hello : pid(%d) ", pid); + response = 1; + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget get hello : invalid pid "); + } + + 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(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget get hello : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget get hello : result(%d)", response); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget get hello : fail to create reply message"); + } + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + } /* VCD_WIDGET_METHOD_HELLO */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_WIDGET_METHOD_SHOW_TOOLTIP)) { + SLOG(LOG_DEBUG, TAG_VCW, "===== Show / Hide tooltip"); + int pid = 0; + int show = 0; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &show, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + if (pid > 0) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget show tooltip : pid(%d), show(%d)", pid, show); + + __vc_widget_cb_show_tooltip(pid, (bool)show); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget show tooltip : invalid pid"); + } + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget show tooltip : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget show tooltip"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget show tooltip : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + } /* VCD_WIDGET_METHOD_SHOW_TOOLTIP */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_WIDGET_METHOD_RESULT)) { + SLOG(LOG_DEBUG, TAG_VCW, "===== Get widget result"); + + __vc_widget_cb_result(); + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget get result : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget get result"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget get result : fail to create reply message"); + + */ + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + + } /* VCD_WIDGET_METHOD_RESULT */ + + else if (dbus_message_is_method_call(msg, if_name, VCD_WIDGET_METHOD_ERROR)) { + SLOG(LOG_DEBUG, TAG_VCW, "===== Get widget error"); + int pid; + int reason; + char* err_msg; + + dbus_message_get_args(msg, &err, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &reason, + DBUS_TYPE_STRING, &err_msg, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget get error message : Get arguments error (%s)", err.message); + dbus_error_free(&err); + } else { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget get error message : pid(%d), reason(%d), msg(%s)", pid, reason, err_msg); + __vc_widget_cb_error(pid, reason); + } + + /* + reply = dbus_message_new_method_return(msg); + + if (NULL != reply) { + if (!dbus_connection_send(conn, reply, NULL)) + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget error message : fail to send reply"); + else + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget error message"); + + dbus_connection_flush(conn); + dbus_message_unref(reply); + } else { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget error message : fail to create reply message"); + } + */ + + SLOG(LOG_DEBUG, TAG_VCW, "====="); + SLOG(LOG_DEBUG, TAG_VCW, " "); + } /* VCD_WIDGET_METHOD_ERROR */ + + /* free the message */ + dbus_message_unref(msg); + + return ECORE_CALLBACK_PASS_ON; +} + +int vc_widget_dbus_open_connection() +{ + if (NULL != g_w_conn) { + SLOG(LOG_WARN, TAG_VCW, "Already existed connection "); + return 0; + } + + DBusError err; + int ret; + + /* initialise the error value */ + dbus_error_init(&err); + + /* connect to the DBUS system bus, and check for errors */ + g_w_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "Dbus Connection Error (%s)", err.message); + dbus_error_free(&err); + } + + if (NULL == g_w_conn) { + SLOG(LOG_ERROR, TAG_VCW, "Fail to get dbus connection "); + return VC_ERROR_OPERATION_FAILED; + } + + int pid = getpid(); + + char service_name[64]; + memset(service_name, '\0', 64); + snprintf(service_name, 64, "%s%d", VC_WIDGET_SERVICE_NAME, pid); + + SLOG(LOG_DEBUG, TAG_VCW, "service name is %s", service_name); + + /* register our name on the bus, and check for errors */ + ret = dbus_bus_request_name(g_w_conn, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "Name Error (%s)", err.message); + dbus_error_free(&err); + } + + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + SLOG(LOG_ERROR, TAG_VCW, "fail dbus_bus_request_name()"); + return -2; + } + + if( NULL != g_w_fd_handler ) { + SLOG(LOG_WARN, TAG_VCW, "The handler already exists."); + return 0; + } + + char rule[128]; + snprintf(rule, 128, "type='signal',interface='%s%d'", VC_WIDGET_SERVICE_INTERFACE, pid); + + /* add a rule for which messages we want to see */ + dbus_bus_add_match(g_w_conn, rule, &err); + dbus_connection_flush(g_w_conn); + + if (dbus_error_is_set(&err)) + { + SLOG(LOG_ERROR, TAG_VCW, "Match Error (%s)", err.message); + dbus_error_free(&err); + return VC_ERROR_OPERATION_FAILED; + } + + int fd = 0; + if (1 != dbus_connection_get_unix_fd(g_w_conn, &fd)) { + SLOG(LOG_ERROR, TAG_VCW, "fail to get fd from dbus "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, "Get fd from dbus : %d", fd); + } + + g_w_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)widget_listener_event_callback, g_w_conn, NULL, NULL); + + if (NULL == g_w_fd_handler) { + SLOG(LOG_ERROR, TAG_VCW, "fail to get fd handler from ecore "); + return VC_ERROR_OPERATION_FAILED; + } + + return 0; +} + +int vc_widget_dbus_close_connection() +{ + DBusError err; + dbus_error_init(&err); + + int pid = getpid(); + + char service_name[64]; + memset(service_name, '\0', 64); + snprintf(service_name, 64, "%s%d", VC_WIDGET_SERVICE_NAME, pid); + + dbus_bus_release_name (g_w_conn, service_name, &err); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Dbus Error (%s)", err.message); + dbus_error_free(&err); + } + + dbus_connection_close(g_w_conn); + + g_w_fd_handler = NULL; + g_w_conn = NULL; + + return 0; +} + +int vc_widget_dbus_reconnect() +{ + bool connected = dbus_connection_get_is_connected(g_w_conn); + SECURE_SLOG(LOG_DEBUG, TAG_VCW, "[DBUS] %s", connected ? "Connected" : "Not connected"); + + if (false == connected) { + vc_widget_dbus_close_connection(); + + if (0 != vc_widget_dbus_open_connection()) { + SLOG(LOG_ERROR, TAG_VCW, "[ERROR] Fail to reconnect"); + return -1; + } + + SLOG(LOG_DEBUG, TAG_VCW, "[DBUS] Reconnect"); + } + return 0; +} + +int vc_widget_dbus_request_hello() +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_METHOD_HELLO); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> Request vc hello : Fail to make message"); + return VC_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_w_conn, msg, 500, &err); + + if (dbus_error_is_set(&err)) { + dbus_error_free(&err); + } + + dbus_message_unref(msg); + + if (NULL != result_msg) { + dbus_message_unref(result_msg); + result = 0; + } else { + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + + +int vc_widget_dbus_request_initialize(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_WIDGET_METHOD_INITIALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget initialize : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget 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; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_w_conn, msg, g_w_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[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_VCW, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget initialize : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget initialize : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< Result message is NULL "); + vc_widget_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_widget_dbus_request_finalize(int pid) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_WIDGET_METHOD_FINALIZE); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget finalize : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget finalize : pid(%d)", pid); + } + + dbus_message_append_args(msg, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_w_conn, msg, g_w_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[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_VCW, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget finalize : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget finalize : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< Result message is NULL "); + vc_widget_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_widget_dbus_request_start_recording(int pid, bool command) +{ + DBusMessage* msg; + + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_WIDGET_METHOD_START_RECORDING); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget start recording : Fail to make message"); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget start recording : pid(%d)", pid); + } + + int temp = (int)command; + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INT32, &temp, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_w_conn, msg, g_w_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[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_VCW, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget start recording : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget start recording : result = %d", result); + } + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< Result message is NULL"); + vc_widget_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_widget_dbus_request_start(int pid, int silence) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_WIDGET_METHOD_START); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget start : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget start : pid(%d), silence(%d)", pid, silence); + } + + DBusMessageIter args; + dbus_message_iter_init_append(msg, &args); + + /* Append result*/ + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(pid)); + dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &(silence)); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_w_conn, msg, g_w_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[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_VCW, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget start : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget start : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< Result Message is NULL"); + vc_widget_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_widget_dbus_request_stop(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, + VC_SERVER_SERVICE_INTERFACE, + VC_WIDGET_METHOD_STOP); + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget stop : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget stop : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_w_conn, msg, g_w_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[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_VCW, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget stop : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget stop : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< Result Message is NULL"); + vc_widget_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} + +int vc_widget_dbus_request_cancel(int pid) +{ + DBusMessage* msg; + + /* create a signal & check for errors */ + msg = dbus_message_new_method_call( + VC_SERVER_SERVICE_NAME, + VC_SERVER_SERVICE_OBJECT_PATH, /* object name of the signal */ + VC_SERVER_SERVICE_INTERFACE, /* interface name of the signal */ + VC_WIDGET_METHOD_CANCEL); /* name of the signal */ + + if (NULL == msg) { + SLOG(LOG_ERROR, TAG_VCW, ">>>> vc widget cancel : Fail to make message "); + return VC_ERROR_OPERATION_FAILED; + } else { + SLOG(LOG_DEBUG, TAG_VCW, ">>>> vc widget cancel : pid(%d)", pid); + } + + dbus_message_append_args(msg, + DBUS_TYPE_INT32, &pid, + DBUS_TYPE_INVALID); + + DBusError err; + dbus_error_init(&err); + + DBusMessage* result_msg; + int result = VC_ERROR_OPERATION_FAILED; + + result_msg = dbus_connection_send_with_reply_and_block(g_w_conn, msg, g_w_waiting_time, &err); + dbus_message_unref(msg); + + if (dbus_error_is_set(&err)) { + SLOG(LOG_ERROR, TAG_VCW, "[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_VCW, "<<<< Get arguments error (%s)", err.message); + dbus_error_free(&err); + result = VC_ERROR_OPERATION_FAILED; + } + dbus_message_unref(result_msg); + + if (0 == result) { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< vc widget cancel : result = %d", result); + } else { + SLOG(LOG_ERROR, TAG_VCW, "<<<< vc widget cancel : result = %d", result); + } + } else { + SLOG(LOG_DEBUG, TAG_VCW, "<<<< Result Message is NULL"); + vc_widget_dbus_reconnect(); + result = VC_ERROR_TIMED_OUT; + } + + return result; +} \ No newline at end of file diff --git a/client/vc_widget_dbus.h b/client/vc_widget_dbus.h new file mode 100644 index 0000000..65d0c56 --- /dev/null +++ b/client/vc_widget_dbus.h @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_WIDGET_DBUS_H_ +#define __VC_WIDGET_DBUS_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +int vc_widget_dbus_open_connection(); + +int vc_widget_dbus_close_connection(); + + +int vc_widget_dbus_request_hello(); + +int vc_widget_dbus_request_initialize(int pid); + +int vc_widget_dbus_request_finalize(int pid); + +int vc_widget_dbus_request_start_recording(int pid, bool command); + + +int vc_widget_dbus_request_start(int pid, int silence); + +int vc_widget_dbus_request_stop(int pid); + +int vc_widget_dbus_request_cancel(int pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_WIDGET_DBUS_H_ */ diff --git a/common/vc_command.c b/common/vc_command.c new file mode 100644 index 0000000..fd501da --- /dev/null +++ b/common/vc_command.c @@ -0,0 +1,775 @@ +/* +* Copyright (c) 2011-2015 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 +#include + +#include "vc_command.h" +#include "vc_main.h" +#include "voice_control_command.h" +#include "voice_control_command_expand.h" +#include "voice_control_common.h" +#include "voice_control_key_defines.h" + + +int vc_cmd_list_create(vc_cmd_list_h* vc_cmd_list) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = (vc_cmd_list_s*)calloc(1, sizeof(vc_cmd_list_s)); + + if (NULL == list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Not enough memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + list->index = -1; + list->list = NULL; + + *vc_cmd_list = (vc_cmd_list_h)list; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list(%p)", *vc_cmd_list); + + return VC_ERROR_NONE; +} + +int vc_cmd_list_destroy(vc_cmd_list_h vc_cmd_list, bool release_command) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_remove_all(vc_cmd_list, release_command); + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list(%p)", list); + + if (NULL != list) { + free(list); + list = NULL; + } + + return VC_ERROR_NONE; +} + +int vc_cmd_list_get_count(vc_cmd_list_h vc_cmd_list, int* count) +{ + if (NULL == vc_cmd_list || NULL == count) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Get command count : Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + *count = g_slist_length(list->list); + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list(%p), count(%d)", list, *count); + + return VC_ERROR_NONE; +} + +int vc_cmd_list_add(vc_cmd_list_h vc_cmd_list, vc_cmd_h vc_command) +{ + if (NULL == vc_cmd_list || NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + list->list = g_slist_append(list->list, cmd); + + if (1 == g_slist_length(list->list)) { + list->index = 0; + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list(%p), command(%p)", list, cmd); + + return VC_ERROR_NONE; +} + +int vc_cmd_list_remove(vc_cmd_list_h vc_cmd_list, vc_cmd_h vc_command) +{ + if (NULL == vc_cmd_list || NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list(%p), command(%p)", list, cmd); + + vc_cmd_s* temp_cmd = NULL; + GSList *iter = NULL; + + iter = g_slist_nth(list->list, 0); + + while (NULL != iter) { + temp_cmd = iter->data; + + if (NULL != temp_cmd && cmd == temp_cmd) { + list->list = g_slist_remove(list->list, temp_cmd); + /* + if (true == release_command) { + SLOG(LOG_DEBUG, TAG_VCCMD, "Release command data"); + if (NULL != temp_cmd->command) free(temp_cmd->command); + if (NULL != temp_cmd->parameter) free(temp_cmd->parameter); + free(temp_cmd); + temp_cmd = NULL; + } + */ + } + + iter = g_slist_next(iter); + } + + int count = g_slist_length(list->list); + + if (0 == count) { + list->index = -1; + } else if (list->index == count) { + list->index = count - 1; + } + + return VC_ERROR_NONE; +} + +int vc_cmd_list_remove_all(vc_cmd_list_h vc_cmd_list, bool release_command) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "===== Destroy all command"); + + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list (%p), release command (%s)" + , list, release_command ? "true" : "false"); + + int count = g_slist_length(list->list); + + int i ; + vc_cmd_s *temp_cmd; + + for (i = 0;i < count ;i++) { + temp_cmd = g_slist_nth_data(list->list, 0); + + if (NULL != temp_cmd) { + list->list = g_slist_remove(list->list, temp_cmd); + + if (true == release_command) { + SLOG(LOG_DEBUG, TAG_VCCMD, "Free command(%p)", temp_cmd); + if (NULL != temp_cmd->command) free(temp_cmd->command); + if (NULL != temp_cmd->parameter) free(temp_cmd->parameter); + free(temp_cmd); + temp_cmd = NULL; + } + } + } + + list->index = -1; + + SLOG(LOG_DEBUG, TAG_VCCMD, "====="); + SLOG(LOG_DEBUG, TAG_VCCMD, " "); + + return VC_ERROR_NONE; +} + +int vc_cmd_list_foreach_commands(vc_cmd_list_h vc_cmd_list, vc_cmd_list_cb callback, void* user_data) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + int count = g_slist_length(list->list); + int i ; + + GSList *iter = NULL; + vc_cmd_s *temp_cmd; + + iter = g_slist_nth(list->list, 0); + + for (i = 0;i < count;i++) { + temp_cmd = iter->data; + + if (NULL != temp_cmd) { + if (false == callback((vc_cmd_h)temp_cmd, user_data)) { + break; + } + + } + iter = g_slist_next(iter); + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "===== Foreach commands Done"); + + return VC_ERROR_NONE; +} + +int vc_cmd_list_first(vc_cmd_list_h vc_cmd_list) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + if (0 == g_slist_length(list->list)) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] List is empty"); + return VC_ERROR_EMPTY; + } + + list->index = 0; + + return VC_ERROR_NONE; +} + +int vc_cmd_list_last(vc_cmd_list_h vc_cmd_list) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + int count = g_slist_length(list->list); + + if (0 == count) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] List is empty"); + return VC_ERROR_EMPTY; + } else { + list->index = count - 1; + SLOG(LOG_DEBUG, TAG_VCCMD, "[DEBUG] List index : %d", list->index); + } + + return VC_ERROR_NONE; +} + +int vc_cmd_list_next(vc_cmd_list_h vc_cmd_list) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + int count = g_slist_length(list->list); + + if (list->index < count - 1) { + list->index = list->index + 1; + SLOG(LOG_DEBUG, TAG_VCCMD, "[DEBUG] List index : %d", list->index); + } else { + SLOG(LOG_DEBUG, TAG_VCCMD, "[DEBUG] List index : %d", list->index); + return VC_ERROR_ITERATION_END; + } + + return VC_ERROR_NONE; +} + +int vc_cmd_list_prev(vc_cmd_list_h vc_cmd_list) +{ + if (NULL == vc_cmd_list) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + if (list->index > 0) { + list->index = list->index - 1; + SLOG(LOG_DEBUG, TAG_VCCMD, "[DEBUG] List index : %d", list->index); + } else { + SLOG(LOG_DEBUG, TAG_VCCMD, "[DEBUG] List index : %d", list->index); + return VC_ERROR_ITERATION_END; + } + + return VC_ERROR_NONE; +} + +int vc_cmd_list_get_current(vc_cmd_list_h vc_cmd_list, vc_cmd_h* vc_command) +{ + if (NULL == vc_cmd_list || NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list (%p), index (%d)", list, list->index); + + if (0 == g_slist_length(list->list)) { + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] list is empty"); + *vc_command = NULL; + return VC_ERROR_EMPTY; + } + + vc_cmd_s *temp_cmd = NULL; + temp_cmd = g_slist_nth_data(list->list, list->index); + + *vc_command = (vc_cmd_h)temp_cmd; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[List] Get current command (%p)", *vc_command); + + return VC_ERROR_NONE; +} + + +int vc_cmd_create(vc_cmd_h* vc_command) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* command = (vc_cmd_s*)calloc(1, sizeof(vc_cmd_s)); + + if (NULL == command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Not enough memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + command->pid = 0; + command->id = 0; + command->index = 0; + command->type = VC_COMMAND_TYPE_NONE; + command->format = VC_CMD_FORMAT_FIXED; + command->command = NULL; + command->parameter = NULL; + command->domain = 0; + command->key = VC_KEY_NONE; + command->modifier = VC_MODIFIER_NONE; + + *vc_command = (vc_cmd_h)command; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Create command][%p]", *vc_command); + + return VC_ERROR_NONE; +} + +int vc_cmd_destroy(vc_cmd_h vc_command) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Input parameter is NULL"); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* command = NULL; + command = (vc_cmd_s*)vc_command; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Destroy command][%p]", command); + + if (NULL != command) { + if (NULL != command->command) free(command->command); + if (NULL != command->parameter) free(command->parameter); + free(command); + command = NULL; + } + + return VC_ERROR_NONE; +} + +int vc_cmd_set_id(vc_cmd_h vc_command, int id) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + if (NULL != cmd) { + cmd->id = id; + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set id][%p] id(%d)", vc_command, cmd->id); + } + + return 0; +} + +int vc_cmd_get_id(vc_cmd_h vc_command, int* id) +{ + if (NULL == vc_command || NULL == id) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid handle "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + if (NULL != cmd) { + *id = cmd->id; + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get id][%p] id(%d)", vc_command, *id); + } + + return 0; +} + +int vc_cmd_set_command(vc_cmd_h vc_command, const char* command) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + if (NULL != cmd->command) { + free(cmd->command); + } + + cmd->command = NULL; + + if (NULL != command) { + cmd->command = strdup(command); + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set command][%p] Command(%s)", vc_command, cmd->command); + + return 0; +} + +int vc_cmd_get_command(vc_cmd_h vc_command, char** command) +{ + if (NULL == vc_command || NULL == command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid handle "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + if (NULL != cmd->command) { + *command = strdup(gettext(cmd->command)); + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get command][%p] Command(%s)", vc_command, *command); + + return 0; +} + +int vc_cmd_set_unfixed_command(vc_cmd_h vc_command, const char* command) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + if (NULL != cmd->parameter) { + free(cmd->parameter); + } + + cmd->parameter = NULL; + + if (NULL != command) { + cmd->parameter = strdup(command); + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set parameter][%p] parameter(%s)", vc_command, cmd->parameter); + } + + return 0; +} + +int vc_cmd_get_unfixed_command(vc_cmd_h vc_command, char** command) +{ + if (NULL == vc_command || NULL == command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid handle "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + if (NULL != cmd->parameter) { + *command = strdup(gettext(cmd->parameter)); + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get nonfixed command][%p] nonfixed command(%s)", vc_command, *command); + } + + return 0; +} + +//int vc_cmd_set_type(vc_cmd_h vc_command, vc_cmd_type_e type) +int vc_cmd_set_type(vc_cmd_h vc_command, int type) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + cmd->type = type; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set type][%p] type(%d)", vc_command, cmd->type); + + return 0; +} + +int vc_cmd_get_type(vc_cmd_h vc_command, int* type) +{ + if (NULL == vc_command || NULL == type) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + *type = cmd->type; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get type][%p] type(%d)", vc_command, *type); + + return 0; +} + +int vc_cmd_set_format(vc_cmd_h vc_command, vc_cmd_format_e format) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + cmd->format = format; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set format][%p] format(%d)", vc_command, format); + + return 0; +} + +int vc_cmd_get_format(vc_cmd_h vc_command, vc_cmd_format_e* format) +{ + if (NULL == vc_command || NULL == format) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + *format = cmd->format; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get format][%p] format(%d)", vc_command, *format); + + return 0; +} + +int vc_cmd_set_pid(vc_cmd_h vc_command, int pid) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + cmd->pid = pid; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set pid][%p] pid(%d)", vc_command, cmd->pid); + + return 0; +} + +int vc_cmd_get_pid(vc_cmd_h vc_command, int* pid) +{ + if (NULL == vc_command || NULL == pid) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + *pid = cmd->pid; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get pid][%p] pid(%d)", vc_command, *pid); + + return 0; +} + +int vc_cmd_set_domain(vc_cmd_h vc_command, int domain) +{ + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + cmd->domain = domain; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Set domain] domain : %d", domain); + + return 0; +} + +int vc_cmd_get_domain(vc_cmd_h vc_command, int* domain) +{ + if (NULL == vc_command || NULL == domain) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + *domain = cmd->domain; + + SLOG(LOG_DEBUG, TAG_VCCMD, "[Get domain] domain : %d", *domain); + + return 0; +} + +/** +* @brief Sets key value of command. +* +* @param[in] vc_command Command handle +* @param[in] key key value +* @param[in] modifier modifier value +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_ERROR_NONE Successful +* @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see vc_cmd_get_result_key() +*/ +int vc_cmd_set_result_key(vc_cmd_h vc_command, int key, int modifier) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "===== Set result key"); + + if (NULL == vc_command) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + SLOG(LOG_DEBUG, TAG_VCCMD, "key : %d, modifier : %d", key, modifier); + + cmd->key = key; + cmd->modifier = modifier; + + SLOG(LOG_DEBUG, TAG_VCCMD, "====="); + SLOG(LOG_DEBUG, TAG_VCCMD, " "); + + return 0; +} + +/** +* @brief Gets key value of command. +* +* @param[in] vc_command Command handle +* @param[out] key key value +* @param[out] modifier modifier value +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_ERROR_NONE Successful +* @retval #VC_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see vc_cmd_add_result_key() +*/ +int vc_cmd_get_result_key(vc_cmd_h vc_command, int* key, int* modifier) +//int vc_command_get_result_key(vc_cmd_h vc_command, int* key, int* modifier) +{ + SLOG(LOG_DEBUG, TAG_VCCMD, "===== Get result key"); + + if (NULL == vc_command || NULL == key || NULL == modifier) { + SLOG(LOG_ERROR, TAG_VCCMD, "[ERROR] Invalid parameter "); + return VC_ERROR_INVALID_PARAMETER; + } + + vc_cmd_s* cmd = NULL; + cmd = (vc_cmd_s*)vc_command; + + *key = cmd->key; + *modifier = cmd->modifier; + + SLOG(LOG_DEBUG, TAG_VCCMD, "====="); + SLOG(LOG_DEBUG, TAG_VCCMD, " "); + + return 0; +} + +int vc_cmd_print_list(vc_cmd_list_h vc_cmd_list) +{ + if (NULL == vc_cmd_list) { + return -1; + } + + vc_cmd_list_s* list = NULL; + list = (vc_cmd_list_s*)vc_cmd_list; + + SLOG(LOG_DEBUG, TAG_VCCMD, "=== Command List ==="); + SLOG(LOG_DEBUG, TAG_VCCMD, "[List][%p]", list); + + int count = g_slist_length(list->list); + + int i; + vc_cmd_s *temp_cmd = NULL; + + for (i = 0;i < count ;i++) { + temp_cmd = g_slist_nth_data(list->list, i); + + if (NULL != temp_cmd) { + SLOG(LOG_DEBUG, TAG_VCCMD, " [%d][%p] PID(%d) ID(%d) Type(%d) Format(%d) Domain(%d) Command(%s) Param(%s)", + i, temp_cmd, temp_cmd->pid, temp_cmd->index, temp_cmd->type, temp_cmd->format, temp_cmd->domain, temp_cmd->command, temp_cmd->parameter); + } + } + + SLOG(LOG_DEBUG, TAG_VCCMD, "=================="); + SLOG(LOG_DEBUG, TAG_VCCMD, " "); + + return 0; +} diff --git a/common/vc_command.h b/common/vc_command.h new file mode 100644 index 0000000..b490f34 --- /dev/null +++ b/common/vc_command.h @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2011-2015 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 __VOICE_CONTROL_INTERNAL_COMMAND_h_ +#define __VOICE_CONTROL_INTERNAL_COMMAND_h_ + +#include + +#include "voice_control_command.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _command_s{ + int pid; + int id; + int index; + int type; + int format; + int domain; + char* command; + char* parameter; + + /* not used */ + int key; + int modifier; +}vc_cmd_s; + +typedef struct { + int index; + GSList* list; +}vc_cmd_list_s; + +/** +* @brief Enumerations of command type. +* @since_tizen 2.4 +*/ +typedef enum { + VC_COMMAND_TYPE_NONE = 0, /**< No command position */ + VC_COMMAND_TYPE_FOREGROUND = 1, /**< Foreground command by client*/ + VC_COMMAND_TYPE_BACKGROUND = 2, /**< Background command by client */ + VC_COMMAND_TYPE_WIDGET = 3, /**< Widget command by widget client */ + VC_COMMAND_TYPE_SYSTEM = 4, /**< System command by manager client */ + VC_COMMAND_TYPE_EXCLUSIVE = 5 /**< exclusive command by manager client */ +}vc_cmd_type_e; + + +int vc_cmd_set_id(vc_cmd_h vc_command, int id); + +int vc_cmd_get_id(vc_cmd_h vc_command, int* id); + +int vc_cmd_print_list(vc_cmd_list_h vc_cmd_list); + +/** +* @brief Remove all commands from command list. +* @since_tizen 2.4 +* +* @param[in] vc_cmd_list The command list handle +* @param[in] free_command The command free option @c true = release each commands in list, +* @c false = remove command from list +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_CMD_ERROR_NONE Successful +* @retval #VC_CMD_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #VC_CMD_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_CMD_ERROR_NOT_SUPPORTED Not supported feature +* +* @see vc_cmd_list_add() +*/ +int vc_cmd_list_remove_all(vc_cmd_list_h vc_cmd_list, bool free_command); + +/** +* @brief Sets extra unfixed command. +* @since_tizen 2.4 +* +* @param[in] vc_command The command handle +* @param[in] command The unfixed command +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_CMD_ERROR_NONE Successful +* @retval #VC_CMD_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #VC_CMD_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_CMD_ERROR_NOT_SUPPORTED Not supported feature +* +* @see vc_cmd_get_non_fixed_command() +*/ +int vc_cmd_set_unfixed_command(vc_cmd_h vc_command, const char* command); + +/** +* @brief Sets pid. +* @since_tizen 2.4 +* +* @param[in] vc_command The command handle +* @param[in] pid process id +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_CMD_ERROR_NONE Successful +* @retval #VC_CMD_ERROR_INVALID_PARAMETER Invalid parameter +* +* @see vc_cmd_set_pid() +*/ +int vc_cmd_set_pid(vc_cmd_h vc_command, int pid); + +/** +* @brief Sets command domain +* @since_tizen 2.4 +* +* @param[in] vc_command The command handle +* @param[in] domain domain +* +* @return 0 on success, otherwise a negative error value +* @retval #VC_CMD_ERROR_NONE Successful +* @retval #VC_CMD_ERROR_INVALID_PARAMETER Invalid parameter +* @retval #VC_CMD_ERROR_PERMISSION_DENIED Permission denied +* @retval #VC_CMD_ERROR_NOT_SUPPORTED Not supported feature +* +* @see vc_cmd_get_domain() +*/ +int vc_cmd_get_pid(vc_cmd_h vc_command, int* pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VOICE_CONTROL_INTERNAL_COMMAND_h_ */ diff --git a/common/vc_config_mgr.c b/common/vc_config_mgr.c new file mode 100644 index 0000000..153d7ef --- /dev/null +++ b/common/vc_config_mgr.c @@ -0,0 +1,1654 @@ +/* +* Copyright (c) 2011-2015 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vc_config_mgr.h" +#include "vc_defs.h" +#include "vc_config_parser.h" +#include "vc_main.h" +#include "voice_control_command.h" + +#define EVENT_SIZE (sizeof(struct inotify_event)) +#define BUF_LEN (EVENT_SIZE + 16) + +typedef struct { + int uid; + vc_config_lang_changed_cb lang_cb; + vc_config_foreground_changed_cb foreground_cb; + vc_config_state_changed_cb state_cb; + vc_config_enabled_cb enabled_cb; +}vc_config_client_s; + + +const char* vc_config_tag() +{ + return TAG_VCCONFIG; +} + +static GSList* g_engine_list = NULL; + +static GSList* g_config_client_list = NULL; + +static vc_config_s* g_config_info; + +static int g_service_state; + +static int g_foreground_pid; + +static int g_lang_ref_count; +static Ecore_Fd_Handler* g_fd_handler_lang = NULL; +static int g_fd_lang; +static int g_wd_lang; + +static int g_state_ref_count; +static Ecore_Fd_Handler* g_fd_handler_state = NULL; +static int g_fd_state; +static int g_wd_state; + +static int g_fore_ref_count; +static Ecore_Fd_Handler* g_fd_handler_fore = NULL; +static int g_fd_fore; +static int g_wd_fore; + + +int __vc_config_mgr_print_engine_info(); + +int __vc_config_mgr_print_client_info(); + +int vc_config_convert_error_code(vc_config_error_e code) +{ + if (code == VC_CONFIG_ERROR_NONE) return VC_ERROR_NONE; + if (code == VC_CONFIG_ERROR_OPERATION_FAILED) return VC_ERROR_OPERATION_FAILED; + if (code == VC_CONFIG_ERROR_INVALID_PARAMETER) return VC_ERROR_INVALID_PARAMETER; + if (code == VC_CONFIG_ERROR_ENGINE_NOT_FOUND) return VC_ERROR_ENGINE_NOT_FOUND; + if (code == VC_CONFIG_ERROR_INVALID_STATE) return VC_ERROR_INVALID_STATE; + if (code == VC_CONFIG_ERROR_INVALID_LANGUAGE) return VC_ERROR_INVALID_LANGUAGE; + if (code == VC_CONFIG_ERROR_IO_ERROR) return VC_ERROR_IO_ERROR; + if (code == VC_CONFIG_ERROR_OUT_OF_MEMORY) return VC_ERROR_OUT_OF_MEMORY; + + return VC_CONFIG_ERROR_NONE; +} + +int __vc_config_mgr_check_engine_is_valid(const char* engine_id) +{ + if (NULL == engine_id) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + if (0 >= g_slist_length(g_engine_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!"); + return -1; + } + + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine info is NULL"); + return -1; + } + + if (NULL == engine_info->uuid) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine id is NULL"); + return -1; + } + + if (!strcmp(engine_id, engine_info->uuid)) { + SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is valid : %s", engine_id); + return 0; + } + + iter = g_slist_next(iter); + } + + iter = g_slist_nth(g_engine_list, 0); + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine info is NULL"); + return -1; + } + + if (NULL == engine_info->uuid) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine id is NULL"); + return -1; + } + + if (NULL == g_config_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Config info is NULL"); + return -1; + } + + if (NULL != g_config_info->engine_id) + free(g_config_info->engine_id); + + g_config_info->engine_id = strdup(engine_info->uuid); + + SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is changed : %s", g_config_info->engine_id); + if (0 != vc_parser_set_engine(g_config_info->engine_id)) { + SLOG(LOG_ERROR, vc_config_tag(), " Fail to save config"); + return -1; + } + + return 0; +} + +bool __vc_config_mgr_check_lang_is_valid(const char* engine_id, const char* language) +{ + if (NULL == engine_id || NULL == language) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return false; + } + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + if (0 >= g_slist_length(g_engine_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!"); + return false; + } + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine info is NULL"); + return false; + } + + if (0 != strcmp(engine_id, engine_info->uuid)) { + iter = g_slist_next(iter); + continue; + } + + GSList *iter_lang = NULL; + char* engine_lang; + if (g_slist_length(engine_info->languages) > 0) { + /* Get a first item */ + iter_lang = g_slist_nth(engine_info->languages, 0); + + int i = 1; + while (NULL != iter_lang) { + /*Get handle data from list*/ + engine_lang = iter_lang->data; + + SLOG(LOG_DEBUG, vc_config_tag(), " [%dth] %s", i, engine_lang); + + if (0 == strcmp(language, engine_lang)) { + return true; + } + + /*Get next item*/ + iter_lang = g_slist_next(iter_lang); + i++; + } + } + break; + } + + return false; +} + +int __vc_config_mgr_select_lang(const char* engine_id, char** language) +{ + if (NULL == engine_id || NULL == language) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return false; + } + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + if (0 >= g_slist_length(g_engine_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!"); + return false; + } + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "engine info is NULL"); + return false; + } + + if (0 != strcmp(engine_id, engine_info->uuid)) { + iter = g_slist_next(iter); + continue; + } + + GSList *iter_lang = NULL; + char* engine_lang = NULL; + if (g_slist_length(engine_info->languages) > 0) { + /* Get a first item */ + iter_lang = g_slist_nth(engine_info->languages, 0); + + while (NULL != iter_lang) { + engine_lang = iter_lang->data; + if (NULL != engine_lang) { + /* Check base language */ + if (0 == strcmp(VC_BASE_LANGUAGE, engine_lang)) { + *language = strdup(engine_lang); + SLOG(LOG_DEBUG, vc_config_tag(), "Selected language : %s", *language); + return 0; + } + } + + iter_lang = g_slist_next(iter_lang); + } + + /* Not support base language */ + if (NULL != engine_lang) { + *language = strdup(engine_lang); + SLOG(LOG_DEBUG, vc_config_tag(), "Selected language : %s", *language); + return 0; + } + } + break; + } + + return -1; +} + +Eina_Bool vc_config_mgr_inotify_event_cb(void* data, Ecore_Fd_Handler *fd_handler) +{ + SLOG(LOG_DEBUG, vc_config_tag(), "===== Config changed callback event"); + + int length; + struct inotify_event event; + memset(&event, '\0', sizeof(struct inotify_event)); + + length = read(g_fd_lang, &event, sizeof(struct inotify_event)); + + if (0 > length) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty Inotify event"); + SLOG(LOG_DEBUG, vc_config_tag(), "====="); + SLOG(LOG_DEBUG, vc_config_tag(), " "); + return ECORE_CALLBACK_PASS_ON; + } + + if (IN_CLOSE_WRITE == event.mask) { + int auto_lang = -1; + char* lang = NULL; + int enabled = -1; + + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + if (0 != vc_parser_find_config_changed(&auto_lang, &lang, &enabled)) + return ECORE_CALLBACK_PASS_ON; + + if (-1 != auto_lang) { + g_config_info->auto_lang = auto_lang; + } + + /* Only language changed */ + if (NULL != lang) { + char* before_lang = NULL; + + before_lang = strdup(g_config_info->language); + + if (NULL != g_config_info->language) free(g_config_info->language); + g_config_info->language = strdup(lang); + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->lang_cb) { + temp_client->lang_cb(before_lang, lang); + } + } + + iter = g_slist_next(iter); + } + + if (NULL != before_lang) free(before_lang); + } + + if (NULL != lang) free(lang); + + if (-1 != enabled) { + g_config_info->enabled = enabled; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->enabled_cb) { + temp_client->enabled_cb(enabled); + } + } + + iter = g_slist_next(iter); + } + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Undefined event"); + } + + SLOG(LOG_DEBUG, vc_config_tag(), "====="); + SLOG(LOG_DEBUG, vc_config_tag(), " "); + + return ECORE_CALLBACK_PASS_ON; +} + +int __vc_config_set_auto_language() +{ + char candidate_lang[6] = {'\0', }; + char* value = NULL; + + value = vconf_get_str(VCONFKEY_LANGSET); + if (NULL == value) { + SLOG(LOG_ERROR, vc_config_tag(), "[Config ERROR] Fail to get display language"); + return -1; + } + + strncpy(candidate_lang, value, 5); + free(value); + + SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Display language : %s", candidate_lang); + + /* Check current language */ + if (0 == strncmp(g_config_info->language, candidate_lang, 5)) { + SLOG(LOG_DEBUG, vc_config_tag(), "[Config] VC language(%s) is same with display language", g_config_info->language); + return 0; + } + + if (true == __vc_config_mgr_check_lang_is_valid(g_config_info->engine_id, candidate_lang)) { + /* stt default language change */ + if (NULL == g_config_info->language) { + SLOG(LOG_ERROR, vc_config_tag(), "Current config language is NULL"); + return -1; + } + + char* before_lang = NULL; + if (0 != vc_parser_set_language(candidate_lang)) { + SLOG(LOG_ERROR, vc_config_tag(), "Fail to save default language"); + return -1; + } + + before_lang = strdup(g_config_info->language); + + free(g_config_info->language); + g_config_info->language = strdup(candidate_lang); + + SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Default language change : before(%s) current(%s)", + before_lang, g_config_info->language); + + /* Call all callbacks of client*/ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->lang_cb) { + temp_client->lang_cb(before_lang, g_config_info->language); + } + } + + iter = g_slist_next(iter); + } + + if (NULL != before_lang) free(before_lang); + } else { + /* Candidate language is not valid */ + char* tmp_language = NULL; + if (0 != __vc_config_mgr_select_lang(g_config_info->engine_id, &tmp_language)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to select language"); + return -1; + } + + if (NULL == tmp_language) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Selected language is NULL"); + return -1; + } + + char* before_lang = NULL; + if (0 != vc_parser_set_language(tmp_language)) { + free(tmp_language); + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config"); + return -1; + } + + before_lang = strdup(g_config_info->language); + + if (NULL != g_config_info->language) { + free(g_config_info->language); + g_config_info->language = strdup(tmp_language); + } + free(tmp_language); + + SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Default language change : before(%s) current(%s)", + before_lang, g_config_info->language); + + /* Call all callbacks of client*/ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->lang_cb) { + temp_client->lang_cb(before_lang, g_config_info->language); + } + } + + iter = g_slist_next(iter); + } + + if (NULL != before_lang) free(before_lang); + } + + return 0; +} + +void __vc_config_language_changed_cb(keynode_t *key, void *data) +{ + if (true == g_config_info->auto_lang) { + /* Get voice input vconf key */ + __vc_config_set_auto_language(); + } + + return; +} + +int vc_config_mgr_initialize(int uid) +{ + GSList *iter = NULL; + int* get_uid; + vc_config_client_s* temp_client = NULL; + + if (0 < g_slist_length(g_config_client_list)) { + /* Check uid */ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + get_uid = iter->data; + + if (uid == *get_uid) { + SLOG(LOG_WARN, vc_config_tag(), "[CONFIG] uid(%d) has already registered", uid); + return 0; + } + + iter = g_slist_next(iter); + } + + temp_client = (vc_config_client_s*)calloc(1, sizeof(vc_config_client_s)); + if (NULL == temp_client) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp_client->uid = uid; + + /* Add uid */ + g_config_client_list = g_slist_append(g_config_client_list, temp_client); + + SLOG(LOG_WARN, vc_config_tag(), "[CONFIG] Add uid(%d) but config has already initialized", uid); + + __vc_config_mgr_print_client_info(); + return 0; + } + + /* Get file name from default engine directory */ + DIR *dp = NULL; + int ret = -1; + struct dirent entry; + struct dirent *dirp = NULL; + + g_engine_list = NULL; + + dp = opendir(VC_DEFAULT_ENGINE_INFO); + if (NULL != dp) { + do { + ret = readdir_r(dp, &entry, &dirp); + if (0 != ret) { + SLOG(LOG_ERROR, vc_config_tag(), "[File ERROR] Fail to read directory"); + break; + } + + if (NULL != dirp) { + if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name)) + continue; + + vc_engine_info_s* info = NULL; + char* filepath = NULL; + int filesize = 0; + + filesize = strlen(VC_DEFAULT_ENGINE_INFO) + strlen(dirp->d_name) + 5; + filepath = (char*)calloc(filesize, sizeof(char)); + + if (NULL != filepath) { + snprintf(filepath, filesize, "%s/%s", VC_DEFAULT_ENGINE_INFO, dirp->d_name); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[Engine Agent ERROR] Memory not enough!!"); + continue; + } + + if (0 == vc_parser_get_engine_info(filepath, &info)) { + g_engine_list = g_slist_append(g_engine_list, info); + } + + if (NULL != filepath) { + free(filepath); + filepath = NULL; + } + } + } while (NULL != dirp); + + closedir(dp); + } else { + SLOG(LOG_WARN, vc_config_tag(), "[Engine Agent WARNING] Fail to open default directory"); + } + + __vc_config_mgr_print_engine_info(); + + if (0 != vc_parser_load_config(&g_config_info)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse configure information"); + return -1; + } + + if (0 != __vc_config_mgr_check_engine_is_valid(g_config_info->engine_id)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get default engine"); + return VC_CONFIG_ERROR_ENGINE_NOT_FOUND; + } + + if (true == g_config_info->auto_lang) { + /* Check language with display language */ + __vc_config_set_auto_language(); + } else { + if (false == __vc_config_mgr_check_lang_is_valid(g_config_info->engine_id, g_config_info->language)) { + /* Default language is not valid */ + char* tmp_language; + if (0 != __vc_config_mgr_select_lang(g_config_info->engine_id, &tmp_language)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to select language"); + return -1; + } + + if (NULL != tmp_language) { + if (NULL != g_config_info->language) { + free(g_config_info->language); + g_config_info->language = strdup(tmp_language); + } + + if (0 != vc_parser_set_language(tmp_language)) { + free(tmp_language); + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config"); + return -1; + } + + free(tmp_language); + } + } + } + + /* print daemon config */ + SLOG(LOG_DEBUG, vc_config_tag(), "== Daemon config =="); + SLOG(LOG_DEBUG, vc_config_tag(), " engine : %s", g_config_info->engine_id); + SLOG(LOG_DEBUG, vc_config_tag(), " auto language : %s", g_config_info->auto_lang ? "on" : "off"); + SLOG(LOG_DEBUG, vc_config_tag(), " language : %s", g_config_info->language); + SLOG(LOG_DEBUG, vc_config_tag(), "==================="); + + /* Get service state */ + if (0 != vc_parser_get_service_state(&g_service_state)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get state"); + return VC_CONFIG_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, vc_config_tag(), "Current service state : %d", g_service_state); + + if (0 != vc_parser_get_foreground(&g_foreground_pid)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get foreground pid"); + return VC_CONFIG_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_DEBUG, vc_config_tag(), "Current foreground pid : %d", g_foreground_pid); + + g_lang_ref_count = 0; + g_state_ref_count = 0; + g_fore_ref_count = 0; + + /* Register to detect display language change */ + vconf_notify_key_changed(VCONFKEY_LANGSET, __vc_config_language_changed_cb, NULL); + + temp_client = (vc_config_client_s*)calloc(1, sizeof(vc_config_client_s)); + if (NULL == temp_client) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp_client->uid = uid; + + SLOG(LOG_DEBUG, vc_config_tag(), "uid(%d) temp_uid(%d)", uid, temp_client->uid); + + /* Add uid */ + g_config_client_list = g_slist_append(g_config_client_list, temp_client); + + __vc_config_mgr_print_client_info(); + + return 0; +} + +int vc_config_mgr_finalize(int uid) +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + if (0 < g_slist_length(g_config_client_list)) { + /* Check uid */ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + g_config_client_list = g_slist_remove(g_config_client_list, temp_client); + free(temp_client); + break; + } + } + + iter = g_slist_next(iter); + } + } + + if (0 < g_slist_length(g_config_client_list)) { + SLOG(LOG_DEBUG, vc_config_tag(), "Client count (%d)", g_slist_length(g_config_client_list)); + return 0; + } + + vc_engine_info_s *engine_info = NULL; + + if (0 < g_slist_length(g_engine_list)) { + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL != engine_info) { + g_engine_list = g_slist_remove(g_engine_list, engine_info); + + vc_parser_free_engine_info(engine_info); + } + + iter = g_slist_nth(g_engine_list, 0); + } + } + + vconf_ignore_key_changed(VCONFKEY_LANGSET, __vc_config_language_changed_cb); + + vc_parser_unload_config(g_config_info); + + SLOG(LOG_DEBUG, vc_config_tag(), "[Success] Finalize config"); + + return 0; +} + + +int __vc_config_mgr_register_lang_event() +{ + if (0 == g_lang_ref_count) { + /* get file notification handler */ + int fd; + int wd; + + fd = inotify_init(); + if (fd < 0) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail get inotify fd"); + return -1; + } + g_fd_lang = fd; + + wd = inotify_add_watch(fd, VC_CONFIG, IN_CLOSE_WRITE); + g_wd_lang = wd; + + g_fd_handler_lang = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)vc_config_mgr_inotify_event_cb, NULL, NULL, NULL); + if (NULL == g_fd_handler_lang) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get handler_noti"); + return -1; + } + + /* Set non-blocking mode of file */ + int value; + value = fcntl(fd, F_GETFL, 0); + value |= O_NONBLOCK; + + if (0 > fcntl(fd, F_SETFL, value)) { + SLOG(LOG_WARN, vc_config_tag(), "[WARNING] Fail to set non-block mode"); + } + } + g_lang_ref_count++; + + return 0; +} + +int __vc_config_mgr_unregister_config_event() +{ + if (0 == g_lang_ref_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Lang ref count is 0"); + return VC_CONFIG_ERROR_INVALID_STATE; + } + + g_lang_ref_count--; + if (0 == g_lang_ref_count) { + /* delete inotify variable */ + ecore_main_fd_handler_del(g_fd_handler_lang); + inotify_rm_watch(g_fd_lang, g_wd_lang); + close(g_fd_lang); + + vconf_ignore_key_changed(VCONFKEY_LANGSET, __vc_config_language_changed_cb); + } + + return 0; +} + +int vc_config_mgr_set_lang_cb(int uid, vc_config_lang_changed_cb lang_cb) +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->lang_cb = lang_cb; + if (0 != __vc_config_mgr_register_lang_event()) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register config event"); + return VC_CONFIG_ERROR_OPERATION_FAILED; + } + } + } + iter = g_slist_next(iter); + } + + return 0; +} + +int vc_config_mgr_unset_lang_cb(int uid) +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->lang_cb = NULL; + __vc_config_mgr_unregister_config_event(); + } + } + iter = g_slist_next(iter); + } + + return 0; +} + +Eina_Bool vc_config_mgr_inotify_state_cb(void* data, Ecore_Fd_Handler *fd_handler) +{ + SLOG(LOG_DEBUG, vc_config_tag(), "===== State changed callback event"); + + int length; + struct inotify_event event; + memset(&event, '\0', sizeof(struct inotify_event)); + + length = read(g_fd_state, &event, sizeof(struct inotify_event)); + if (0 > length) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty Inotify event"); + SLOG(LOG_DEBUG, vc_config_tag(), "====="); + SLOG(LOG_DEBUG, vc_config_tag(), " "); + return ECORE_CALLBACK_PASS_ON; + } + + if (IN_CLOSE_WRITE == event.mask) { + int state = -1; + if (0 != vc_parser_get_service_state(&state)) { + SLOG(LOG_ERROR, vc_config_tag(), "Fail to get state"); + return ECORE_CALLBACK_PASS_ON; + } + + SLOG(LOG_DEBUG, vc_config_tag(), "Previous state(%d) Current state(%d)", g_service_state, state); + + /* If state is not changed */ + if (g_service_state != state) { + int previous_state = g_service_state; + g_service_state = state; + + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->state_cb) { + temp_client->state_cb(previous_state, g_service_state); + } + } + + iter = g_slist_next(iter); + } + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Undefined event"); + } + + SLOG(LOG_DEBUG, vc_config_tag(), "====="); + SLOG(LOG_DEBUG, vc_config_tag(), " "); + + return ECORE_CALLBACK_PASS_ON; +} + +int __vc_config_mgr_register_state_event() +{ + if (0 == g_state_ref_count) { + /* get file notification handler */ + int fd; + int wd; + + fd = inotify_init(); + if (fd < 0) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail get inotify fd"); + return -1; + } + g_fd_state = fd; + + wd = inotify_add_watch(fd, VC_RUNTIME_INFO_SERVICE_STATE, IN_CLOSE_WRITE); + g_wd_state = wd; + + g_fd_handler_state = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)vc_config_mgr_inotify_state_cb, NULL, NULL, NULL); + if (NULL == g_fd_handler_state) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get handler for state"); + return -1; + } + } + g_state_ref_count++; + + return 0; +} + +int __vc_config_mgr_unregister_state_event() +{ + if (0 == g_state_ref_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] State ref count is 0"); + return VC_CONFIG_ERROR_INVALID_STATE; + } + + g_state_ref_count--; + if (0 == g_state_ref_count) { + /* delete inotify variable */ + ecore_main_fd_handler_del(g_fd_handler_state); + inotify_rm_watch(g_fd_state, g_wd_state); + close(g_fd_state); + } + return 0; +} + +int vc_config_mgr_set_service_state_cb(int uid, vc_config_state_changed_cb state_cb) +{ + if (NULL == state_cb) { + SLOG(LOG_ERROR, vc_config_tag(), "State changed cb is NULL : uid(%d) ", uid); + return VC_CONFIG_ERROR_INVALID_PARAMETER; + } + + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->state_cb = state_cb; + __vc_config_mgr_register_state_event(); + return VC_CONFIG_ERROR_NONE; + } + } + iter = g_slist_next(iter); + } + + return VC_CONFIG_ERROR_INVALID_PARAMETER; +} + +int vc_config_mgr_unset_service_state_cb(int uid) +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->state_cb = NULL; + __vc_config_mgr_unregister_state_event(); + return 0; + } + } + iter = g_slist_next(iter); + } + + return VC_CONFIG_ERROR_INVALID_PARAMETER; +} + +Eina_Bool vc_config_mgr_inotify_foreground_cb(void* data, Ecore_Fd_Handler *fd_handler) +{ + SLOG(LOG_DEBUG, vc_config_tag(), "===== Foreground changed callback event"); + + int length; + struct inotify_event event; + memset(&event, '\0', sizeof(struct inotify_event)); + + length = read(g_fd_fore, &event, sizeof(struct inotify_event)); + if (0 > length) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty Inotify event"); + SLOG(LOG_DEBUG, vc_config_tag(), "====="); + SLOG(LOG_DEBUG, vc_config_tag(), " "); + return ECORE_CALLBACK_PASS_ON; + } + + if (IN_CLOSE_WRITE == event.mask) { + int foreground_pid = -1; + if (0 != vc_parser_get_foreground(&foreground_pid)) { + SLOG(LOG_ERROR, vc_config_tag(), "Fail to get state"); + return ECORE_CALLBACK_PASS_ON; + } + + SLOG(LOG_DEBUG, vc_config_tag(), "foreground pid (%d)", foreground_pid); + + /* If foreground pid is changed */ + if (g_foreground_pid != foreground_pid) { + int previous_pid = g_foreground_pid; + g_foreground_pid = foreground_pid; + + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (NULL != temp_client->foreground_cb) { + temp_client->foreground_cb(previous_pid, g_foreground_pid); + } + } + + iter = g_slist_next(iter); + } + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Undefined event"); + } + + SLOG(LOG_DEBUG, vc_config_tag(), "====="); + SLOG(LOG_DEBUG, vc_config_tag(), " "); + + return ECORE_CALLBACK_PASS_ON; +} + +int __vc_config_mgr_register_foreground_event() +{ + if (0 == g_fore_ref_count) { + /* get file notification handler */ + int fd; + int wd; + + fd = inotify_init(); + if (fd < 0) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail get inotify fd"); + return -1; + } + g_fd_fore = fd; + + wd = inotify_add_watch(g_fd_fore, VC_RUNTIME_INFO_FOREGROUND, IN_CLOSE_WRITE); + g_wd_fore = wd; + + g_fd_handler_fore = ecore_main_fd_handler_add(g_fd_fore, ECORE_FD_READ, + (Ecore_Fd_Cb)vc_config_mgr_inotify_foreground_cb, NULL, NULL, NULL); + if (NULL == g_fd_handler_fore) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get handler for foreground"); + return -1; + } + } + g_fore_ref_count++; + + return 0; +} + +int __vc_config_mgr_unregister_foreground_event() +{ + if (0 == g_fore_ref_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Foreground ref count is 0"); + return VC_CONFIG_ERROR_INVALID_STATE; + } + + g_fore_ref_count--; + + if (0 == g_fore_ref_count) { + /* delete inotify variable */ + ecore_main_fd_handler_del(g_fd_handler_fore); + inotify_rm_watch(g_fd_fore, g_wd_fore); + close(g_fd_fore); + } + + return 0; +} + +int vc_config_mgr_set_foreground_cb(int uid, vc_config_foreground_changed_cb foreground_cb) +{ + if (NULL == foreground_cb) { + SLOG(LOG_ERROR, vc_config_tag(), "Foreground changed cb is NULL : uid(%d) ", uid); + return VC_CONFIG_ERROR_INVALID_PARAMETER; + } + + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->foreground_cb = foreground_cb; + __vc_config_mgr_register_foreground_event(); + return VC_CONFIG_ERROR_NONE; + } + } + iter = g_slist_next(iter); + } + + return VC_CONFIG_ERROR_INVALID_PARAMETER; +} + +int vc_config_mgr_unset_foreground_cb(int uid) +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->foreground_cb = NULL; + __vc_config_mgr_unregister_foreground_event(); + return 0; + } + } + iter = g_slist_next(iter); + } + + return VC_CONFIG_ERROR_INVALID_PARAMETER; +} + +int vc_config_mgr_set_enabled_cb(int uid, vc_config_enabled_cb enabled_cb) +{ + if (NULL == enabled_cb) { + SLOG(LOG_ERROR, vc_config_tag(), "enabled cb is NULL : uid(%d) ", uid); + return VC_CONFIG_ERROR_INVALID_PARAMETER; + } + + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->enabled_cb = enabled_cb; + return VC_CONFIG_ERROR_NONE; + } + } + iter = g_slist_next(iter); + } + + return VC_CONFIG_ERROR_INVALID_PARAMETER; +} + +int vc_config_mgr_unset_enabled_cb(int uid) +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + /* Call all callbacks of client*/ + iter = g_slist_nth(g_config_client_list, 0); + + while (NULL != iter) { + temp_client = iter->data; + + if (NULL != temp_client) { + if (uid == temp_client->uid) { + temp_client->enabled_cb = NULL; + return 0; + } + } + iter = g_slist_next(iter); + } + + return VC_CONFIG_ERROR_INVALID_PARAMETER; +} + +int vc_config_mgr_get_auto_language(bool* value) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == value) { + return -1; + } + + *value = g_config_info->auto_lang; + + return 0; +} + +int vc_config_mgr_set_auto_language(bool value) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (g_config_info->auto_lang != value) { + /* Check language is valid */ + if (0 != vc_parser_set_auto_lang(value)) { + SLOG(LOG_ERROR, vc_config_tag(), "Fail to save engine id"); + return -1; + } + g_config_info->auto_lang = value; + + if (true == g_config_info->auto_lang) { + __vc_config_set_auto_language(); + } + } + + return 0; +} + +int vc_config_mgr_get_language_list(vc_supported_language_cb callback, void* user_data) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (0 >= g_slist_length(g_engine_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "There is no engine"); + return -1; + } + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] engine info is NULL"); + return -1; + } + + if (0 != strcmp(g_config_info->engine_id, engine_info->uuid)) { + iter = g_slist_next(iter); + continue; + } + + GSList *iter_lang = NULL; + char* lang; + + /* Get a first item */ + iter_lang = g_slist_nth(engine_info->languages, 0); + + while (NULL != iter_lang) { + /*Get handle data from list*/ + lang = iter_lang->data; + + SLOG(LOG_DEBUG, vc_config_tag(), " %s", lang); + if (NULL != lang) { + if (false == callback(lang, user_data)) + break; + } + + /*Get next item*/ + iter_lang = g_slist_next(iter_lang); + } + break; + } + + return 0; +} + +int vc_config_mgr_get_default_language(char** language) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == language) { + return -1; + } + + if (NULL != g_config_info->language) { + *language = strdup(g_config_info->language); + } else { + SLOG(LOG_ERROR, vc_config_tag(), " language is NULL"); + return -1; + } + + return 0; +} + +int vc_config_mgr_set_default_language(const char* language) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == language) { + return -1; + } + + /* Check language is valid */ + if (NULL != g_config_info->language) { + if (0 != vc_parser_set_language(language)) { + SLOG(LOG_ERROR, vc_config_tag(), "Fail to save engine id"); + return -1; + } + free(g_config_info->language); + g_config_info->language = strdup(language); + } else { + SLOG(LOG_ERROR, vc_config_tag(), " language is NULL"); + return -1; + } + + return 0; +} + +int vc_config_mgr_get_enabled(bool* value) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == value) { + return -1; + } + + *value = g_config_info->enabled; + + return 0; +} + +int vc_config_mgr_set_enabled(bool value) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (0 != vc_parser_set_enabled(value)) { + SLOG(LOG_ERROR, vc_config_tag(), "Fail to set enabled"); + return -1; + } + + g_config_info->enabled = value; + + return 0; +} + +int vc_config_mgr_get_nonfixed_support(bool* value) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == value) { + SLOG(LOG_ERROR, vc_config_tag(), "Input parameter is NULL"); + return -1; + } + + if (0 >= g_slist_length(g_engine_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "There is no engine"); + return -1; + } + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] engine info is NULL"); + return -1; + } + + if (0 != strcmp(g_config_info->engine_id, engine_info->uuid)) { + iter = g_slist_next(iter); + continue; + } + + *value = engine_info->non_fixed_support; + + break; + } + + return 0; +} + +bool vc_config_check_default_engine_is_valid(const char* engine) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == engine) { + return false; + } + + if (0 >= g_slist_length(g_engine_list)) + return false; + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL != engine_info) { + if (0 == strcmp(engine, engine_info->uuid)) { + return true; + } + } + iter = g_slist_next(iter); + } + + return false; +} + +bool vc_config_check_default_language_is_valid(const char* language) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + if (NULL == language) { + return false; + } + + if (NULL == g_config_info->engine_id) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Default engine id is NULL"); + return false; + } + + if (0 >= g_slist_length(g_engine_list)) + return false; + + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + while (NULL != iter) { + engine_info = iter->data; + + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine info is NULL"); + iter = g_slist_next(iter); + continue; + } + + if (0 == strcmp(g_config_info->engine_id, engine_info->uuid)) { + iter = g_slist_next(iter); + continue; + } + + GSList *iter_lang = NULL; + char* lang; + + /* Get a first item */ + iter_lang = g_slist_nth(engine_info->languages, 0); + + while (NULL != iter_lang) { + lang = iter_lang->data; + + if (0 == strcmp(language, lang)) + return true; + + /*Get next item*/ + iter_lang = g_slist_next(iter_lang); + } + break; + } + + return false; +} + +int vc_config_mgr_set_service_state(int state) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + return vc_parser_set_service_state(state); +} + +int vc_config_mgr_get_service_state(int* state) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + return vc_parser_get_service_state(state); +} + +int vc_config_mgr_set_foreground(int pid, bool value) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + return vc_parser_set_foreground(pid, value); +} + +int vc_config_mgr_get_foreground(int* pid) +{ + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); + return -1; + } + + return vc_parser_get_foreground(pid); +} + + + +int __vc_config_mgr_print_engine_info() +{ + GSList *iter = NULL; + vc_engine_info_s *engine_info = NULL; + + if (0 >= g_slist_length(g_engine_list)) { + SLOG(LOG_DEBUG, vc_config_tag(), "-------------- engine list -----------------"); + SLOG(LOG_DEBUG, vc_config_tag(), " No Engine in engine directory"); + SLOG(LOG_DEBUG, vc_config_tag(), "--------------------------------------------"); + return 0; + } + + /* Get a first item */ + iter = g_slist_nth(g_engine_list, 0); + + SLOG(LOG_DEBUG, vc_config_tag(), "--------------- engine list -----------------"); + + int i = 1; + while (NULL != iter) { + engine_info = iter->data; + + SLOG(LOG_DEBUG, vc_config_tag(), "[%dth]", i); + SLOG(LOG_DEBUG, vc_config_tag(), " name : %s", engine_info->name); + SLOG(LOG_DEBUG, vc_config_tag(), " id : %s", engine_info->uuid); + + + SLOG(LOG_DEBUG, vc_config_tag(), " languages"); + GSList *iter_lang = NULL; + char* lang; + if (g_slist_length(engine_info->languages) > 0) { + /* Get a first item */ + iter_lang = g_slist_nth(engine_info->languages, 0); + + int j = 1; + while (NULL != iter_lang) { + /*Get handle data from list*/ + lang = iter_lang->data; + + SLOG(LOG_DEBUG, vc_config_tag(), " [%dth] %s", j, lang); + + /*Get next item*/ + iter_lang = g_slist_next(iter_lang); + j++; + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), " language is NONE"); + } + SLOG(LOG_DEBUG, vc_config_tag(), " "); + iter = g_slist_next(iter); + i++; + } + SLOG(LOG_DEBUG, vc_config_tag(), "--------------------------------------------"); + + return 0; +} + +int __vc_config_mgr_print_client_info() +{ + GSList *iter = NULL; + vc_config_client_s* temp_client = NULL; + + if (0 >= g_slist_length(g_config_client_list)) { + SLOG(LOG_DEBUG, vc_config_tag(), "-------------- Client list -----------------"); + SLOG(LOG_DEBUG, vc_config_tag(), " No Client"); + SLOG(LOG_DEBUG, vc_config_tag(), "--------------------------------------------"); + return 0; + } + + /* Get a first item */ + iter = g_slist_nth(g_config_client_list, 0); + + SLOG(LOG_DEBUG, vc_config_tag(), "--------------- Client list -----------------"); + + int i = 1; + while (NULL != iter) { + temp_client = iter->data; + + SLOG(LOG_DEBUG, vc_config_tag(), "[%dth] uid(%d)", i, temp_client->uid); + + iter = g_slist_next(iter); + i++; + } + SLOG(LOG_DEBUG, vc_config_tag(), "--------------------------------------------"); + + return 0; +} \ No newline at end of file diff --git a/common/vc_config_mgr.h b/common/vc_config_mgr.h new file mode 100644 index 0000000..171e0e2 --- /dev/null +++ b/common/vc_config_mgr.h @@ -0,0 +1,108 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_CONFIG_MANAGER_H_ +#define __VC_CONFIG_MANAGER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + VC_CONFIG_ERROR_NONE = TIZEN_ERROR_NONE, /**< Success, No error */ + VC_CONFIG_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of Memory */ + VC_CONFIG_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */ + VC_CONFIG_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + VC_CONFIG_ERROR_INVALID_STATE = TIZEN_ERROR_VOICE_CONTROL | 0x011, /**< Invalid state */ + VC_CONFIG_ERROR_INVALID_LANGUAGE = TIZEN_ERROR_VOICE_CONTROL | 0x012, /**< Invalid voice */ + VC_CONFIG_ERROR_ENGINE_NOT_FOUND = TIZEN_ERROR_VOICE_CONTROL | 0x013, /**< No available VC-engine */ + VC_CONFIG_ERROR_OPERATION_FAILED = TIZEN_ERROR_VOICE_CONTROL | 0x014 /**< Operation failed */ +}vc_config_error_e; + + +typedef void (*vc_config_lang_changed_cb)(const char* before_lang, const char* current_lang); + +typedef void (*vc_config_foreground_changed_cb)(int previous, int current); + +typedef void (*vc_config_state_changed_cb)(int previous, int current); + +typedef void (*vc_config_enabled_cb)(bool enable); + + +int vc_config_mgr_initialize(int uid); + +int vc_config_mgr_finalize(int uid); + + +/* Set / Unset callback */ +int vc_config_mgr_set_lang_cb(int uid, vc_config_lang_changed_cb lang_cb); + +int vc_config_mgr_unset_lang_cb(int uid); + +int vc_config_mgr_set_service_state_cb(int uid, vc_config_state_changed_cb state_cb); + +int vc_config_mgr_unset_service_state_cb(int uid); + +int vc_config_mgr_set_foreground_cb(int uid, vc_config_foreground_changed_cb foreground_cb); + +int vc_config_mgr_unset_foreground_cb(int uid); + +int vc_config_mgr_set_enabled_cb(int uid, vc_config_enabled_cb enabled_cb); + +int vc_config_mgr_unset_enabled_cb(int uid); + + +int vc_config_mgr_get_auto_language(bool* value); + +int vc_config_mgr_set_auto_language(bool value); + +int vc_config_mgr_get_language_list(vc_supported_language_cb callback, void* user_data); + +int vc_config_mgr_get_default_language(char** language); + +int vc_config_mgr_set_default_language(const char* language); + +int vc_config_mgr_get_enabled(bool* value); + +int vc_config_mgr_set_enabled(bool value); + + +int vc_config_mgr_get_nonfixed_support(bool* value); + +bool vc_config_check_default_language_is_valid(const char* language); + +int vc_config_convert_error_code(vc_config_error_e code); + + +int vc_config_mgr_set_service_state(int state); + +int vc_config_mgr_get_service_state(int* state); + + +int vc_config_mgr_set_foreground(int pid, bool value); + +int vc_config_mgr_get_foreground(int* pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_CONFIG_MANAGER_H_ */ diff --git a/common/vc_config_parser.c b/common/vc_config_parser.c new file mode 100644 index 0000000..7dd47e3 --- /dev/null +++ b/common/vc_config_parser.c @@ -0,0 +1,1085 @@ +/* +* Copyright (c) 2011-2015 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 +#include +#include +#include +#include + +#include "vc_defs.h" +#include "vc_main.h" +#include "vc_config_parser.h" + + +#define VC_TAG_ENGINE_BASE_TAG "voice-control-engine" +#define VC_TAG_ENGINE_NAME "name" +#define VC_TAG_ENGINE_ID "id" +#define VC_TAG_ENGINE_LANGUAGE_SET "languages" +#define VC_TAG_ENGINE_LANGUAGE "lang" +#define VC_TAG_ENGINE_NON_FIXED_SUPPORT "non-fixed-support" + +#define VC_TAG_CONFIG_BASE_TAG "voice-control-config" +#define VC_TAG_CONFIG_ENGINE_ID "engine" +#define VC_TAG_CONFIG_AUTO_LANGUAGE "auto" +#define VC_TAG_CONFIG_LANGUAGE "language" +#define VC_TAG_CONFIG_ENABLED "enabled" + +#define VC_TAG_INFO_BASE_TAG "vc_info_option" +#define VC_TAG_INFO_SERVICE_STATE "service_state" +#define VC_TAG_INFO_FOREGROUND "foreground_pid" + + +extern char* vc_config_tag(); + +static xmlDocPtr g_config_doc = NULL; + +static int __vc_config_parser_set_file_mode(const char* filename) +{ + if (NULL == filename) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Invalid parameter"); + return -1; + } + + if (0 > chmod(filename, 0666)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to change file mode"); + return -1; + } + + if (0 > chown(filename, 5000, 5000)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to change file owner"); + return -1; + } + + return 0; +} + +int vc_parser_get_engine_info(const char* path, vc_engine_info_s** engine_info) +{ + if (NULL == path || NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(path); + if (doc == NULL) { + SLOG(LOG_WARN, vc_config_tag(), "[WARNING] Fail to parse file error : %s", path); + return -1; + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_ENGINE_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT 'voice-control-engine'"); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + /* alloc engine info */ + vc_engine_info_s* temp; + temp = (vc_engine_info_s*)calloc(1, sizeof(vc_engine_info_s)); + if (NULL == temp) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory"); + xmlFreeDoc(doc); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp->name = NULL; + temp->uuid = NULL; + temp->languages = NULL; + temp->non_fixed_support = false; + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_ENGINE_NAME)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + // SLOG(LOG_DEBUG, vc_config_tag(), "Engine name : %s", (char *)key); + if (NULL != temp->name) free(temp->name); + temp->name = strdup((char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] <%s> has no content", VC_TAG_ENGINE_ID); + } + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_ENGINE_ID)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + // SLOG(LOG_DEBUG, vc_config_tag(), "Engine uuid : %s", (char *)key); + if (NULL != temp->uuid) free(temp->uuid); + temp->uuid = strdup((char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] <%s> has no content", VC_TAG_ENGINE_ID); + } + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_ENGINE_LANGUAGE_SET)) { + xmlNodePtr lang_node = NULL; + char* temp_lang = NULL; + + lang_node = cur->xmlChildrenNode; + + while (lang_node != NULL) { + if (0 == xmlStrcmp(lang_node->name, (const xmlChar *)VC_TAG_ENGINE_LANGUAGE)){ + key = xmlNodeGetContent(lang_node); + if (NULL != key) { + // SLOG(LOG_DEBUG, vc_config_tag(), "language : %s", (char *)key); + temp_lang = strdup((char*)key); + temp->languages = g_slist_append(temp->languages, temp_lang); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] <%s> has no content", VC_TAG_ENGINE_LANGUAGE); + } + } + + lang_node = lang_node->next; + } + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_ENGINE_NON_FIXED_SUPPORT)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + // SLOG(LOG_DEBUG, vc_config_tag(), "Engine uuid : %s", (char *)key); + + if (0 == xmlStrcmp(key, (const xmlChar *)"true")) { + temp->non_fixed_support = true; + } else if (0 == xmlStrcmp(key, (const xmlChar *)"false")) { + temp->non_fixed_support = false; + } else { + SLOG(LOG_ERROR, vc_config_tag(), "Auto voice is wrong"); + temp->non_fixed_support = false; + } + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] <%s> has no content", VC_TAG_ENGINE_NON_FIXED_SUPPORT); + } + } else { + + } + + cur = cur->next; + } + + xmlFreeDoc(doc); + + if (NULL == temp->uuid || NULL == temp->languages) { + /* Invalid engine */ + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Invalid engine : %s", path); + vc_parser_free_engine_info(temp); + return -1; + } + + *engine_info = temp; + + return 0; +} + +int vc_parser_free_engine_info(vc_engine_info_s* engine_info) +{ + if (NULL == engine_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + if (NULL != engine_info->name) free(engine_info->name); + if (NULL != engine_info->uuid) free(engine_info->uuid); + + int count = g_slist_length(engine_info->languages); + + int i ; + char *temp_lang; + + for (i = 0;i < count ;i++) { + temp_lang = g_slist_nth_data(engine_info->languages, 0); + + if (NULL != temp_lang) { + engine_info->languages = g_slist_remove(engine_info->languages, temp_lang); + + if (NULL != temp_lang) + free(temp_lang); + } + } + + if (NULL != engine_info) free(engine_info); + + return 0; +} + +int vc_parser_print_engine_info(vc_engine_info_s* engine_info) +{ + if (NULL == engine_info) + return -1; + + SLOG(LOG_DEBUG, vc_config_tag(), "== engine info =="); + SLOG(LOG_DEBUG, vc_config_tag(), " id : %s", engine_info->uuid); + + SLOG(LOG_DEBUG, vc_config_tag(), " languages"); + GSList *iter = NULL; + char* lang; + if (g_slist_length(engine_info->languages) > 0) { + /* Get a first item */ + iter = g_slist_nth(engine_info->languages, 0); + + int i = 1; + while (NULL != iter) { + /*Get handle data from list*/ + lang = iter->data; + + SLOG(LOG_DEBUG, vc_config_tag(), " [%dth] %s", i, lang); + + /*Get next item*/ + iter = g_slist_next(iter); + i++; + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), " language is NONE"); + } + SLOG(LOG_DEBUG, vc_config_tag(), "====================="); + + return 0; +} + +int vc_parser_load_config(vc_config_s** config_info) +{ + if (NULL == config_info) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + bool is_default_open = false; + + if (0 != access(VC_CONFIG, F_OK)) { + doc = xmlParseFile(VC_CONFIG_DEFAULT); + if (doc == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_CONFIG_DEFAULT); + return -1; + } + SLOG(LOG_DEBUG, vc_config_tag(), "Use default config : %s", VC_CONFIG_DEFAULT); + is_default_open = true; + } else { + int retry_count = 0; + + while (NULL == doc) { + doc = xmlParseFile(VC_CONFIG); + if (NULL != doc) { + break; + } + retry_count++; + usleep(10000); + + if (VC_RETRY_COUNT == retry_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_CONFIG); + return -1; + } + } + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) VC_TAG_CONFIG_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_CONFIG_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + /* alloc engine info */ + vc_config_s* temp; + temp = (vc_config_s*)calloc(1, sizeof(vc_config_s)); + if (NULL == temp) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory"); + xmlFreeDoc(doc); + return VC_ERROR_OUT_OF_MEMORY; + } + + temp->engine_id = NULL; + temp->language = NULL; + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_ENGINE_ID)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_config_tag(), "Engine id : %s", (char *)key); + if (NULL != temp->engine_id) free(temp->engine_id); + temp->engine_id = strdup((char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enable is NULL"); + } + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_AUTO_LANGUAGE)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_config_tag(), "Auto language : %s", (char *)key); + + if (0 == xmlStrcmp(key, (const xmlChar *)"on")) { + temp->auto_lang = true; + } else if (0 == xmlStrcmp(key, (const xmlChar *)"off")) { + temp->auto_lang = false; + } else { + SLOG(LOG_ERROR, vc_config_tag(), "Auto voice is wrong"); + temp->auto_lang = false; + } + + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] voice type is NULL"); + } + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_LANGUAGE)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_config_tag(), "language : %s", (char *)key); + if (NULL != temp->language) free(temp->language); + temp->language = strdup((char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] language is NULL"); + } + } else if (0 == xmlStrcmp(cur->name, (const xmlChar*)VC_TAG_CONFIG_ENABLED)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_config_tag(), "Enabled service : %s", (char *)key); + + if (0 == xmlStrcmp(key, (const xmlChar *)"on")) { + temp->enabled = true; + } + else if (0 == xmlStrcmp(key, (const xmlChar *)"off")) { + temp->enabled = false; + } + else { + SLOG(LOG_ERROR, vc_config_tag(), "Enabled service is wrong"); + temp->enabled = false; + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Enabled service is NULL"); + } + } else { + + } + + cur = cur->next; + } + + *config_info = temp; + g_config_doc = doc; + + if (is_default_open) { + xmlSaveFile(VC_CONFIG, g_config_doc); + if (0 != __vc_config_parser_set_file_mode(VC_CONFIG)) + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set file mode - %s", VC_CONFIG); + } + + return 0; +} + +int vc_parser_unload_config(vc_config_s* config_info) +{ + if (NULL != g_config_doc) xmlFreeDoc(g_config_doc); + + if (NULL != config_info) { + if (NULL != config_info->engine_id) free(config_info->engine_id); + if (NULL != config_info->language) free(config_info->language); + free(config_info); + } + + return 0; +} + +int vc_parser_set_engine(const char* engine_id) +{ + if (NULL == engine_id) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + xmlNodePtr cur = NULL; + cur = xmlDocGetRootElement(g_config_doc); + if (NULL == cur) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) VC_TAG_CONFIG_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_CONFIG_BASE_TAG); + return -1; + } + + cur = cur->xmlChildrenNode; + if (NULL == cur) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + while (NULL != cur) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_ENGINE_ID)) { + xmlNodeSetContent(cur, (const xmlChar *)engine_id); + } + + cur = cur->next; + } + + int ret = xmlSaveFile(VC_CONFIG, g_config_doc); + if (0 > ret) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Save result : %d", ret); + } + + return 0; +} + +int vc_parser_set_auto_lang(bool value) +{ + if (NULL == g_config_doc) + return -1; + + xmlNodePtr cur = NULL; + cur = xmlDocGetRootElement(g_config_doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) VC_TAG_CONFIG_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_CONFIG_BASE_TAG); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_AUTO_LANGUAGE)) { + if (true == value) { + xmlNodeSetContent(cur, (const xmlChar *)"on"); + } else if (false == value) { + xmlNodeSetContent(cur, (const xmlChar *)"off"); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong value of auto voice"); + return -1; + } + break; + } + cur = cur->next; + } + + int ret = xmlSaveFile(VC_CONFIG, g_config_doc); + SLOG(LOG_DEBUG, vc_config_tag(), "Save result : %d", ret); + + return 0; +} + +int vc_parser_set_language(const char* language) +{ + if (NULL == g_config_doc || NULL == language) + return -1; + + xmlNodePtr cur = NULL; + cur = xmlDocGetRootElement(g_config_doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) VC_TAG_CONFIG_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_CONFIG_BASE_TAG); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_LANGUAGE)) { + xmlNodeSetContent(cur, (const xmlChar *)language); + } + + cur = cur->next; + } + + int ret = xmlSaveFile(VC_CONFIG, g_config_doc); + SLOG(LOG_DEBUG, vc_config_tag(), "Save result : %d", ret); + + return 0; +} + +int vc_parser_set_enabled(bool value) +{ + if (NULL == g_config_doc) + return -1; + + xmlNodePtr cur = NULL; + cur = xmlDocGetRootElement(g_config_doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_CONFIG_BASE_TAG); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CONFIG_ENABLED)) { + xmlNodeSetContent(cur, (const xmlChar *)(value ? "on" : "off")); + } + + cur = cur->next; + } + + int ret = xmlSaveFile(VC_CONFIG, g_config_doc); + SLOG(LOG_DEBUG, vc_config_tag(), "Save result : %d", ret); + + return 0; +} + +int vc_parser_find_config_changed(int* auto_lang, char** language, int* enabled) +{ + if (NULL == auto_lang || NULL == language) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + xmlDocPtr doc = NULL; + xmlNodePtr cur_new = NULL; + xmlNodePtr cur_old = NULL; + + xmlChar *key_new; + xmlChar *key_old; + + int retry_count = 0; + + while (NULL == doc) { + doc = xmlParseFile(VC_CONFIG); + if (NULL != doc) { + break; + } + retry_count++; + usleep(10000); + + if (VC_RETRY_COUNT == retry_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_CONFIG); + return -1; + } + } + + cur_new = xmlDocGetRootElement(doc); + cur_old = xmlDocGetRootElement(g_config_doc); + if (cur_new == NULL || cur_old == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur_new->name, (const xmlChar*)VC_TAG_CONFIG_BASE_TAG) || xmlStrcmp(cur_old->name, (const xmlChar*)VC_TAG_CONFIG_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_CONFIG_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur_new = cur_new->xmlChildrenNode; + cur_old = cur_old->xmlChildrenNode; + if (cur_new == NULL || cur_old == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + *language = NULL; + while (cur_new != NULL && cur_old != NULL) { + + // SLOG(LOG_DEBUG, vc_config_tag(), "cur_new->name(%s), cur_old->name(%s)", (char*)cur_new->name, (char*)cur_old->name); + + if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)VC_TAG_CONFIG_AUTO_LANGUAGE)) { + if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)VC_TAG_CONFIG_AUTO_LANGUAGE)) { + key_old = xmlNodeGetContent(cur_old); + if (NULL != key_old) { + key_new = xmlNodeGetContent(cur_new); + if (NULL != key_new) { + if (0 != xmlStrcmp(key_old, key_new)) { + SLOG(LOG_DEBUG, vc_config_tag(), "Old auto lang(%s), New auto lang(%s)", (char*)key_old, (char*)key_new); + if (0 == xmlStrcmp(key_new, (const xmlChar*)"on")) { + *auto_lang = 1; + } else { + *auto_lang = 0; + } + } + xmlFree(key_new); + } + xmlFree(key_old); + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Old config and new config are different"); + } + } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)VC_TAG_CONFIG_LANGUAGE)) { + if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)VC_TAG_CONFIG_LANGUAGE)) { + key_old = xmlNodeGetContent(cur_old); + if (NULL != key_old) { + key_new = xmlNodeGetContent(cur_new); + if (NULL != key_new) { + if (0 != xmlStrcmp(key_old, key_new)) { + SLOG(LOG_DEBUG, vc_config_tag(), "Old language(%s), New language(%s)", (char*)key_old, (char*)key_new); + if (NULL != *language) free(*language); + *language = strdup((char*)key_new); + } + xmlFree(key_new); + } + xmlFree(key_old); + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] old config and new config are different"); + } + } else if (0 == xmlStrcmp(cur_new->name, (const xmlChar*)VC_TAG_CONFIG_ENABLED)) { + if (0 == xmlStrcmp(cur_old->name, (const xmlChar*)VC_TAG_CONFIG_ENABLED)) { + key_old = xmlNodeGetContent(cur_old); + if (NULL != key_old) { + key_new = xmlNodeGetContent(cur_new); + if (NULL != key_new) { + if (0 != xmlStrcmp(key_old, key_new)) { + SLOG(LOG_DEBUG, vc_config_tag(), "Old enabled(%s), New enabled(%s)", (char*)key_old, (char*)key_new); + if (0 == xmlStrcmp(key_new, (const xmlChar*)"on")) { + *enabled = 1; + } else { + *enabled = 0; + } + } + xmlFree(key_new); + } + xmlFree(key_old); + } + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] old config and new config are different"); + } + } else { + + } + + cur_new = cur_new->next; + cur_old = cur_old->next; + } + + xmlFreeDoc(g_config_doc); + g_config_doc = doc; + + return 0; +} + +int vc_parser_init_service_state() +{ + if (0 != access(VC_RUNTIME_INFO_SERVICE_STATE, R_OK | W_OK)) { + /* make file */ + xmlDocPtr doc; + xmlNodePtr root_node; + xmlNodePtr info_node; + + doc = xmlNewDoc((const xmlChar*)"1.0"); + doc->encoding = (const xmlChar*)"utf-8"; + doc->charset = 1; + + root_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_INFO_BASE_TAG); + xmlDocSetRootElement(doc,root_node); + + /* Make new command node */ + info_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_INFO_SERVICE_STATE); + xmlNodeSetContent(info_node, (const xmlChar *)"0"); + xmlAddChild(root_node, info_node); + + int ret = xmlSaveFormatFile(VC_RUNTIME_INFO_SERVICE_STATE, doc, 1); + SLOG(LOG_DEBUG, vc_config_tag(), "Save service state info file : %d", ret); + + if (0 != __vc_config_parser_set_file_mode(VC_RUNTIME_INFO_SERVICE_STATE)) + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set file mode - %s", VC_RUNTIME_INFO_SERVICE_STATE); + } + + return 0; +} + +int vc_parser_set_service_state(int state) +{ + /* Set service state */ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + + int retry_count = 0; + + while (NULL == doc) { + doc = xmlParseFile(VC_RUNTIME_INFO_SERVICE_STATE); + if (NULL != doc) { + break; + } + retry_count++; + usleep(10000); + + if (VC_RETRY_COUNT == retry_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_RUNTIME_INFO_SERVICE_STATE); + return -1; + } + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) VC_TAG_INFO_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_INFO_BASE_TAG); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_INFO_SERVICE_STATE)) { + char temp[16]; + memset(temp, 0, 16); + snprintf(temp, 16, "%d", state); + + xmlNodeSetContent(cur, (const xmlChar *)temp); + break; + } + + cur = cur->next; + } + + int ret = xmlSaveFile(VC_RUNTIME_INFO_SERVICE_STATE, doc); + if (0 >= ret) { + SLOG(LOG_DEBUG, vc_config_tag(), "[ERROR] Fail to save service state info file : %d", ret); + return -1; + } + SLOG(LOG_DEBUG, vc_config_tag(), "[Success] Save service state info file : state(%d)", state); + + return 0; +} + +int vc_parser_get_service_state(int* state) +{ + if (NULL == state) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + if (0 != access(VC_RUNTIME_INFO_SERVICE_STATE, F_OK)) { + /* make file */ + xmlDocPtr doc; + xmlNodePtr root_node; + xmlNodePtr info_node; + + doc = xmlNewDoc((const xmlChar*)"1.0"); + doc->encoding = (const xmlChar*)"utf-8"; + doc->charset = 1; + + root_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_INFO_BASE_TAG); + xmlDocSetRootElement(doc, root_node); + + /* Make new command node */ + info_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_INFO_SERVICE_STATE); + xmlNodeSetContent(info_node, (const xmlChar *)"0"); + xmlAddChild(root_node, info_node); + + int ret = xmlSaveFormatFile(VC_RUNTIME_INFO_SERVICE_STATE, doc, 1); + SLOG(LOG_DEBUG, vc_config_tag(), "Save runtime info file : %d", ret); + + if (0 != __vc_config_parser_set_file_mode(VC_RUNTIME_INFO_SERVICE_STATE)) + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set file mode - %s", VC_RUNTIME_INFO_SERVICE_STATE); + + *state = 0; + return 0; + } + + /* Check file */ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + int retry_count = 0; + + while (NULL == doc) { + doc = xmlParseFile(VC_RUNTIME_INFO_SERVICE_STATE); + if (NULL != doc) { + break; + } + retry_count++; + usleep(10000); + + if (VC_RETRY_COUNT == retry_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_RUNTIME_INFO_SERVICE_STATE); + return -1; + } + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_INFO_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_INFO_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_INFO_SERVICE_STATE)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_config_tag(), "Service state : %s", (char *)key); + *state = atoi((char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enable is NULL"); + } + } + cur = cur->next; + } + + xmlFreeDoc(doc); + + return 0; +} + +int vc_parser_set_foreground(int pid, bool value) +{ + int cur_pid = 0; + /* Get foreground pid */ + if (0 != vc_parser_get_foreground(&cur_pid)) { + SLOG(LOG_DEBUG, vc_config_tag(), "Fail to get pid from info file"); + return -1; + } + + if (true == value) { + /* Focus in */ + if (cur_pid == pid) { + return 0; + } + SLOG(LOG_DEBUG, vc_config_tag(), "Current foreground pid (%d)", cur_pid); + } else { + /* Focus out */ + if (VC_NO_FOREGROUND_PID != cur_pid) { + if (cur_pid != pid) { + SLOG(LOG_DEBUG, vc_config_tag(), "Input pid(%d) is NOT different from the saved pid(%d)", pid, cur_pid); + return 0; + } + } + } + + /* Set foreground pid */ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + + int retry_count = 0; + + while (NULL == doc) { + doc = xmlParseFile(VC_RUNTIME_INFO_FOREGROUND); + if (NULL != doc) { + break; + } + retry_count++; + usleep(10000); + + if (VC_RETRY_COUNT == retry_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_RUNTIME_INFO_FOREGROUND); + return -1; + } + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) VC_TAG_INFO_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT %s", VC_TAG_INFO_BASE_TAG); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_INFO_FOREGROUND)) { + char temp[16]; + memset(temp, 0, 16); + if (true == value) { + snprintf(temp, 16, "%d", pid); + } else { + snprintf(temp, 16, "%d", VC_NO_FOREGROUND_PID); + } + + xmlNodeSetContent(cur, (const xmlChar *)temp); + break; + } + + cur = cur->next; + } + + int ret = xmlSaveFile(VC_RUNTIME_INFO_FOREGROUND, doc); + if (0 >= ret) { + SLOG(LOG_DEBUG, vc_config_tag(), "[ERROR] Fail to save foreground info : %d", ret); + return -1; + } + SLOG(LOG_DEBUG, vc_config_tag(), "[Success] Save foreground info pid(%d)", pid); + + return 0; +} + +int vc_parser_get_foreground(int* pid) +{ + if (NULL == pid) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + int ret; + + if (0 != access(VC_RUNTIME_INFO_FOREGROUND, F_OK)) { + /* make file */ + xmlDocPtr doc; + xmlNodePtr root_node; + xmlNodePtr info_node; + + doc = xmlNewDoc((const xmlChar*)"1.0"); + doc->encoding = (const xmlChar*)"utf-8"; + doc->charset = 1; + + root_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_INFO_BASE_TAG); + xmlDocSetRootElement(doc,root_node); + + /* Make new command node */ + info_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_INFO_FOREGROUND); + xmlNodeSetContent(info_node, (const xmlChar *)"0"); + xmlAddChild(root_node, info_node); + + ret = xmlSaveFormatFile(VC_RUNTIME_INFO_FOREGROUND, doc, 1); + SLOG(LOG_DEBUG, vc_config_tag(), "Save runtime info file : %d", ret); + + *pid = 0; + + if (0 != __vc_config_parser_set_file_mode(VC_RUNTIME_INFO_FOREGROUND)) + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set file mode - %s", VC_RUNTIME_INFO_FOREGROUND); + } else { + /* Check file */ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + int retry_count = 0; + + while (NULL == doc) { + doc = xmlParseFile(VC_RUNTIME_INFO_FOREGROUND); + if (NULL != doc) { + break; + } + retry_count++; + usleep(10000); + + if (VC_RETRY_COUNT == retry_count) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse file error : %s", VC_RUNTIME_INFO_FOREGROUND); + return -1; + } + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_INFO_BASE_TAG)) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_INFO_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_INFO_FOREGROUND)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_config_tag(), "Foreground pid : %s", (char *)key); + *pid = atoi((char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enable is NULL"); + } + } + cur = cur->next; + } + + xmlFreeDoc(doc); + } + + return 0; +} \ No newline at end of file diff --git a/common/vc_config_parser.h b/common/vc_config_parser.h new file mode 100644 index 0000000..8760d06 --- /dev/null +++ b/common/vc_config_parser.h @@ -0,0 +1,82 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_CONFIG_PARSER_H_ +#define __VC_CONFIG_PARSER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char* name; + char* uuid; + GSList* languages; + bool non_fixed_support; +}vc_engine_info_s; + +typedef struct { + char* engine_id; + bool auto_lang; + char* language; + bool enabled; +}vc_config_s; + + +/* Get engine information */ +int vc_parser_get_engine_info(const char* path, vc_engine_info_s** engine_info); + +int vc_parser_free_engine_info(vc_engine_info_s* engine_info); + + +int vc_parser_load_config(vc_config_s** config_info); + +int vc_parser_unload_config(vc_config_s* config_info); + +int vc_parser_set_engine(const char* engine_id); + +int vc_parser_set_auto_lang(bool value); + +int vc_parser_set_language(const char* language); + +int vc_parser_set_enabled(bool value); + +int vc_parser_find_config_changed(int* auto_lang, char** language, int* enabled); + + +/* Set / Get service state */ +int vc_parser_init_service_state(); + +int vc_parser_set_service_state(int state); + +int vc_parser_get_service_state(int* state); + + +/* Set / Get foreground info */ +int vc_parser_set_foreground(int pid, bool value); + +int vc_parser_get_foreground(int* pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_CONFIG_PARSER_H_ */ diff --git a/common/vc_defs.h b/common/vc_defs.h new file mode 100644 index 0000000..cc3cd54 --- /dev/null +++ b/common/vc_defs.h @@ -0,0 +1,171 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_DEFS_H__ +#define __VC_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +/****************************************************************************************** +* Definition for Dbus +*******************************************************************************************/ + +#define VC_CLIENT_SERVICE_NAME "org.tizen.voice.vcclient" +#define VC_CLIENT_SERVICE_OBJECT_PATH "/org/tizen/voice/vcclient" +#define VC_CLIENT_SERVICE_INTERFACE "org.tizen.voice.vcclient" + +#define VC_WIDGET_SERVICE_NAME "org.tizen.voice.vcwidget" +#define VC_WIDGET_SERVICE_OBJECT_PATH "/org/tizen/voice/vcwidget" +#define VC_WIDGET_SERVICE_INTERFACE "org.tizen.voice.vcwidget" + +#define VC_MANAGER_SERVICE_NAME "org.tizen.voice.vcmanager" +#define VC_MANAGER_SERVICE_OBJECT_PATH "/org/tizen/voice/vcmanager" +#define VC_MANAGER_SERVICE_INTERFACE "org.tizen.voice.vcmanager" + +#define VC_SERVER_SERVICE_NAME "service.connect.vcserver" +#define VC_SERVER_SERVICE_OBJECT_PATH "/org/tizen/voice/vcserver" +#define VC_SERVER_SERVICE_INTERFACE "org.tizen.voice.vcserver" + + +/****************************************************************************************** +* Message Definition for all +*******************************************************************************************/ + +#define VC_METHOD_HELLO "vc_method_hello" + +/****************************************************************************************** +* Message Definition for Client +*******************************************************************************************/ + +#define VC_METHOD_INITIALIZE "vc_method_initialize" +#define VC_METHOD_FINALIZE "vc_method_finalilze" + +#define VC_METHOD_SET_EXCLUSIVE_CMD "vc_method_set_exclusive_cmd" +#define VC_METHOD_SET_COMMAND "vc_method_set_command" +#define VC_METHOD_UNSET_COMMAND "vc_method_unset_command" + +#define VCD_METHOD_RESULT "vcd_method_result" +#define VCD_METHOD_ERROR "vcd_method_error" +#define VCD_METHOD_HELLO "vcd_method_hello" + +/* Authority */ +#if 0 +#define VC_METHOD_OBTAIN_AUTHORITY "vc_method_obtain_authority" +#define VC_METHOD_RETURN_AUTHORITY "vc_method_return_authority" + +#define VC_METHOD_REQUEST_START "vc_method_request_start" +#define VC_METHOD_REQUEST_STOP "vc_method_request_stop" +#define VC_METHOD_REQUEST_CANCEL "vc_method_request_cancel" +#endif + +#define VC_METHOD_AUTH_ENABLE "vc_method_auth_enable" +#define VC_METHOD_AUTH_DISABLE "vc_method_auth_disable" + +#define VC_METHOD_AUTH_START "vc_method_auth_start" +#define VC_METHOD_AUTH_STOP "vc_method_auth_stop" +#define VC_METHOD_AUTH_CANCEL "vc_method_auth_cancel" + +/****************************************************************************************** +* Message Definition for widget +*******************************************************************************************/ + +#define VC_WIDGET_METHOD_INITIALIZE "vc_widget_method_initialize" +#define VC_WIDGET_METHOD_FINALIZE "vc_widget_method_finalilze" + +#define VC_WIDGET_METHOD_START_RECORDING "vc_widget_method_start_recording" + +#define VC_WIDGET_METHOD_START "vc_widget_method_start" +#define VC_WIDGET_METHOD_STOP "vc_widget_method_stop" +#define VC_WIDGET_METHOD_CANCEL "vc_widget_method_cancel" + +#define VCD_WIDGET_METHOD_RESULT "vcd_widget_method_result" +#define VCD_WIDGET_METHOD_ERROR "vcd_widget_method_error" +#define VCD_WIDGET_METHOD_HELLO "vcd_widget_method_hello" +#define VCD_WIDGET_METHOD_SHOW_TOOLTIP "vcd_widget_method_show_tooltip" + + +/****************************************************************************************** +* Message Definition for manager +*******************************************************************************************/ + +#define VC_MANAGER_METHOD_INITIALIZE "vc_manager_method_initialize" +#define VC_MANAGER_METHOD_FINALIZE "vc_manager_method_finalilze" + +#define VC_MANAGER_METHOD_SET_COMMAND "vc_manager_method_set_command" +#define VC_MANAGER_METHOD_UNSET_COMMAND "vc_manager_method_unset_command" +#define VC_MANAGER_METHOD_SET_DEMANDABLE "vc_manager_method_set_demandable_client" +#define VC_MANAGER_METHOD_SET_AUDIO_TYPE "vc_manager_method_set_audio_type" +#define VC_MANAGER_METHOD_GET_AUDIO_TYPE "vc_manager_method_get_audio_type" +#define VC_MANAGER_METHOD_SET_CLIENT_INFO "vc_manager_method_set_client_info" + +#define VC_MANAGER_METHOD_START "vc_manager_method_request_start" +#define VC_MANAGER_METHOD_STOP "vc_manager_method_request_stop" +#define VC_MANAGER_METHOD_CANCEL "vc_manager_method_request_cancel" +#define VC_MANAGER_METHOD_RESULT_SELECTION "vc_manager_method_result_selection" + +#define VCD_MANAGER_METHOD_HELLO "vcd_manager_method_hello" +#define VCD_MANAGER_METHOD_SPEECH_DETECTED "vcd_manager_method_speech_detected" +#define VCD_MANAGER_METHOD_ALL_RESULT "vcd_manager_method_all_result" +#define VCD_MANAGER_METHOD_RESULT "vcd_manager_method_result" + +#define VCD_MANAGER_METHOD_ERROR "vcd_manager_method_error" + + +/****************************************************************************************** +* Defines for configuration +*******************************************************************************************/ + +#define VC_DAEMON_PATH "/usr/bin/vc-daemon" + +#define VC_CONFIG_DEFAULT "/usr/lib/voice/vc/1.0/vc-config.xml" + +#define VC_CONFIG "/opt/home/app/.voice/vc-config.xml" + +#define VC_DEFAULT_ENGINE_INFO "/usr/lib/voice/vc/1.0/engine-info" + +#define VC_NO_FOREGROUND_PID 0 + +#define VC_BASE_LANGUAGE "en_US" + +#define VC_RETRY_COUNT 5 + + +#define VC_RUNTIME_INFO_ROOT "/opt/home/app/.voice/vc" + +#define VC_RUNTIME_INFO_AUDIO_VOLUME VC_RUNTIME_INFO_ROOT"/vc_vol" + +#define VC_RUNTIME_INFO_FOREGROUND VC_RUNTIME_INFO_ROOT"/vc-info-foreground.xml" + +#define VC_RUNTIME_INFO_SERVICE_STATE VC_RUNTIME_INFO_ROOT"/vc-info-state.xml" + +#define VC_RUNTIME_INFO_DEMANDABLE_LIST VC_RUNTIME_INFO_ROOT"/vc-demandable-client.xml" + +#define VC_RUNTIME_INFO_RESULT VC_RUNTIME_INFO_ROOT"/vc-result.xml" + +#define VC_RUNTIME_INFO_EX_RESULT VC_RUNTIME_INFO_ROOT"/vc-ex-result.xml" + +#define VC_RUNTIME_INFO_CLIENT VC_RUNTIME_INFO_ROOT"/vc-client-info.xml" + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_DEFS_H__ */ diff --git a/common/vc_info_parser.c b/common/vc_info_parser.c new file mode 100644 index 0000000..e8093ae --- /dev/null +++ b/common/vc_info_parser.c @@ -0,0 +1,1611 @@ +/* +* Copyright (c) 2011-2015 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 +#include +#include +#include + +#include "vc_defs.h" +#include "vc_info_parser.h" +#include "vc_main.h" +#include "voice_control_command.h" +#include "voice_control_command_expand.h" +#include "voice_control_common.h" + + +#define VC_TAG_CMD_BASE_TAG "vc_commands" + +#define VC_TAG_CMD_COMMAND "command" +#define VC_TAG_CMD_ID "cmd_id" +#define VC_TAG_CMD_PID "cmd_pid" +#define VC_TAG_CMD_TYPE "cmd_type" +#define VC_TAG_CMD_FORMAT "cmd_format" +#define VC_TAG_CMD_COMMAND_TEXT "cmd_cmd_text" +#define VC_TAG_CMD_PARAMETER_TEXT "cmd_param_text" +#define VC_TAG_CMD_DOMAIN "cmd_domain" +#define VC_TAG_CMD_KEY "cmd_key" +#define VC_TAG_CMD_MODIFIER "cmd_modifier" + +#define VC_TAG_RESULT_BASE_TAG "vc_results" +#define VC_TAG_RESULT_TEXT "result_text" +#define VC_TAG_RESULT_EVENT "result_event" +#define VC_TAG_RESULT_MESSAGE "result_message" + +#define VC_TAG_INFO_BASE_TAG "vc_info_option" +#define VC_TAG_INFO_FOREGROUND "foreground_pid" + +#define VC_TAG_DEMANDABLE_CLIENT_BASE_TAG "vc_demandable_client" +#define VC_TAG_DEMANDABLE_CLIENT_APPID "appid" + +#define VC_TAG_CLIENT_BASE_TAG "vc_client_info" +#define VC_TAG_CLIENT_CLIENT "client" +#define VC_TAG_CLIENT_PID "pid" +#define VC_TAG_CLIENT_FGCMD "fgcmd" +#define VC_TAG_CLIENT_BGCMD "bgcmd" +#define VC_TAG_CLIENT_EXCMD "excmd" + + +const char* vc_info_tag() +{ + return TAG_VCINFO; +} + +int __vc_cmd_parser_print_commands(GSList* cmd_list); + + +static int __vc_info_parser_set_file_mode(const char* filename) +{ + if (NULL == filename) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Invalid parameter"); + return -1; + } + + if (0 > chmod(filename, 0666)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to change file mode"); + return -1; + } + + if (0 > chown(filename, 5000, 5000)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to change file owner"); + return -1; + } + + return 0; +} + +int __vc_cmd_parser_make_filepath(int pid, vc_cmd_type_e type, char** path) +{ + if (NULL == path) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + *path = (char*)calloc(256, sizeof(char)); + if (NULL == *path) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to allocate memory"); + return VC_ERROR_OUT_OF_MEMORY; + } + + snprintf(*path, 256, "%s/vc_%d_%d.xml", VC_RUNTIME_INFO_ROOT, (int)type, pid); + + return 0; +} + +int vc_cmd_parser_save_file(int pid, vc_cmd_type_e type, GSList* cmd_list) +{ + if (0 >= g_slist_length(cmd_list)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Command list is invalid"); + return -1; + } + + /* Check file */ + char* filepath = NULL; + __vc_cmd_parser_make_filepath(pid, type, &filepath); + + if (NULL == filepath) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to create file path"); + return -1; + } + + remove(filepath); + + xmlDocPtr doc; + xmlNodePtr root_node; + xmlNodePtr cmd_node; + xmlNodePtr tmp_node; + + doc = xmlNewDoc((const xmlChar*)"1.0"); + doc->encoding = (const xmlChar*)"utf-8"; + doc->charset = 1; + + root_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_BASE_TAG); + xmlDocSetRootElement(doc,root_node); + + GSList *iter = NULL; + vc_cmd_s *temp_cmd; + + int i; + int count = g_slist_length(cmd_list); + iter = g_slist_nth(cmd_list, 0); + + SLOG(LOG_DEBUG, vc_info_tag(), "list count : %d", count); + char temp[16]; + int selected_count = 0; + + for (i = 0;i < count;i++) { + temp_cmd = iter->data; + + if (NULL == temp_cmd) { + SLOG(LOG_ERROR, vc_info_tag(), "comamnd is NULL"); + break; + } + + if (type == temp_cmd->type) { + SLOG(LOG_DEBUG, vc_info_tag(), "[%dth] type(%d) format(%d) domain(%d) cmd(%s) param(%s)", + i, temp_cmd->type, temp_cmd->format, temp_cmd->domain, temp_cmd->command, temp_cmd->parameter); + + /* Make new command node */ + cmd_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_COMMAND); + + /* ID */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", i); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_ID); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* PID */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", getpid()); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_PID); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* TYPE */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->type); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_TYPE); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* FORMAT */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->format); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_FORMAT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* DOMAIN */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->domain); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_DOMAIN); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* COMMAND */ + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_COMMAND_TEXT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp_cmd->command); + xmlAddChild(cmd_node, tmp_node); + + /* PARAMETER */ + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_PARAMETER_TEXT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp_cmd->parameter); + xmlAddChild(cmd_node, tmp_node); + + xmlAddChild(root_node, cmd_node); + + selected_count++; + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Command type(%d) is NOT valid : request type(%d)", temp_cmd->type, type); + } + iter = g_slist_next(iter); + } + + if (0 < selected_count) { + int ret = xmlSaveFormatFile(filepath, doc, 1); + if (0 >= ret) { + SLOG(LOG_DEBUG, vc_info_tag(), "[ERROR] Fail to save command file : %d", ret); + free(filepath); + return -1; + } + + if (0 != __vc_info_parser_set_file_mode(filepath)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to set file mode - %s", filepath); + } else { + SLOG(LOG_DEBUG, vc_info_tag(), "[Success] Save command file"); + } + free(filepath); + } else { + free(filepath); + + SLOG(LOG_DEBUG, vc_info_tag(), "No command"); + return -1; + } + + + return 0; +} + +int vc_cmd_parser_delete_file(int pid, vc_cmd_type_e type) +{ + /* Check file */ + char* filepath = NULL; + __vc_cmd_parser_make_filepath(pid, type, &filepath); + + if (NULL != filepath) { + remove(filepath); + free(filepath); + } + return 0; +} + +int vc_cmd_parser_get_commands(int pid, vc_cmd_type_e type, GSList** cmd_list) +{ + /* Check file */ + char* filepath = NULL; + __vc_cmd_parser_make_filepath(pid, type, &filepath); + + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(filepath); + if (doc == NULL) { + SECURE_SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", filepath); + return -1; + } + if (NULL != filepath) free(filepath); + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CMD_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_CMD_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + GSList* temp_cmd_list = NULL; + + while (cur != NULL) { + cur = cur->next; + + if (NULL == cur) { + break; + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)"text")) { + continue; + } + + xmlNodePtr command_node = NULL; + command_node = cur->xmlChildrenNode; + command_node = command_node->next; + + vc_cmd_s* temp_cmd; + temp_cmd = (vc_cmd_s*)calloc(1, sizeof(vc_cmd_s)); + + if (NULL == temp_cmd) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Memory alloc error!!"); + return -1; + } + + /* ID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_ID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "ID : %s", (char *)key); + temp_cmd->index = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_ID); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* PID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "PID : %s", (char *)key); + temp_cmd->pid = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PID); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Type */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_TYPE)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Type : %s", (char *)key); + temp_cmd->type = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_TYPE); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Format */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_FORMAT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Format : %s", (char *)key); + temp_cmd->format = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_FORMAT); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Domain */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_DOMAIN)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Domain : %s", (char *)key); + temp_cmd->domain = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_DOMAIN); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Command */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_COMMAND_TEXT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Command : %s", (char *)key); + if (0 < xmlStrlen(key)) { + temp_cmd->command = strdup((char*)key); + } else { + temp_cmd->command = NULL; + } + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_COMMAND_TEXT); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Parameter */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PARAMETER_TEXT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Parameter : %s", (char *)key); + if (0 < xmlStrlen(key)) { + temp_cmd->parameter = strdup((char*)key); + } else { + temp_cmd->parameter = NULL; + } + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PARAMETER_TEXT); + if (NULL != temp_cmd->command) free(temp_cmd->command); + free(temp_cmd); + break; + } + } + + if (type == temp_cmd->type) { + temp_cmd_list = g_slist_append(temp_cmd_list, temp_cmd); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Command type(%d) is NOT valid : request type(%d)", temp_cmd->type, type); + vc_cmd_destroy((vc_cmd_h)temp_cmd); + } + } + + xmlFreeDoc(doc); + + *cmd_list = temp_cmd_list; + + __vc_cmd_parser_print_commands(temp_cmd_list); + + return 0; +} + +int vc_cmd_parser_append_commands(int pid, vc_cmd_type_e type, vc_cmd_list_h vc_cmd_list) +{ + /* Check file */ + char* filepath = NULL; + __vc_cmd_parser_make_filepath(pid, type, &filepath); + + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(filepath); + if (doc == NULL) { + SECURE_SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", filepath); + return -1; + } + if (NULL != filepath) free(filepath); + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CMD_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_CMD_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + vc_cmd_h temp_command = NULL; + + while (cur != NULL) { + cur = cur->next; + + if (NULL == cur) { + break; + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)"text")) { + continue; + } + + xmlNodePtr command_node = NULL; + command_node = cur->xmlChildrenNode; + command_node = command_node->next; + + if (0 != vc_cmd_create(&temp_command)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to create command!!"); + return -1; + } + + /* ID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_ID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "ID : %s", (char *)key); + vc_cmd_set_id(temp_command, atoi((char*)key)); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_ID); + vc_cmd_destroy(temp_command); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* PID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "PID : %s", (char *)key); + vc_cmd_set_pid(temp_command, atoi((char*)key)); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PID); + vc_cmd_destroy(temp_command); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* TYPE */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_TYPE)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "Type : %s", (char *)key); + vc_cmd_set_type(temp_command, atoi((char*)key)); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_TYPE); + vc_cmd_destroy(temp_command); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* FORMAT */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_FORMAT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "Format : %s", (char *)key); + vc_cmd_set_format(temp_command, atoi((char*)key)); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_FORMAT); + vc_cmd_destroy(temp_command); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* DOMAIN */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_DOMAIN)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "Domain : %s", (char *)key); + vc_cmd_set_domain(temp_command, atoi((char*)key)); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_DOMAIN); + vc_cmd_destroy(temp_command); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Command */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_COMMAND_TEXT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "Command : %s, size : %d", (char *)key, strlen(key)); + vc_cmd_set_command(temp_command, (char*)key); + + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_COMMAND_TEXT); + vc_cmd_destroy(temp_command); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Parameter */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PARAMETER_TEXT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + //SLOG(LOG_DEBUG, vc_info_tag(), "Parameter : %s , size : %d", (char *)key, strlen(key)); + //vc_cmd_set_parameter(temp_command, (char*)key); + vc_cmd_set_unfixed_command(temp_command, (char*)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PARAMETER_TEXT); + vc_cmd_destroy(temp_command); + break; + } + } + + if (0 != vc_cmd_list_add(vc_cmd_list, temp_command)) { + SLOG(LOG_DEBUG, vc_info_tag(), "Fail to add command to list"); + vc_cmd_destroy(temp_command); + vc_cmd_list_destroy(vc_cmd_list, true); + return -1; + } + } + + xmlFreeDoc(doc); + + vc_cmd_print_list(vc_cmd_list); + + return 0; +} + +int vc_info_parser_get_demandable_clients(GSList** client_list) +{ + /* Check file */ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(VC_RUNTIME_INFO_DEMANDABLE_LIST); + if (doc == NULL) { + SECURE_SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", VC_RUNTIME_INFO_FOREGROUND); + return -1; + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_DEMANDABLE_CLIENT_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + GSList* temp_client_list = NULL; + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_APPID)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "App id : %s", (char *)key); + + vc_demandable_client_s* temp_client; + temp_client = (vc_demandable_client_s*)calloc(1, sizeof(vc_demandable_client_s)); + + if (NULL == temp_client) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Memory alloc error!!"); + return -1; + } + + if (0 < xmlStrlen(key)) { + temp_client->appid = strdup((char*)key); + } else { + /* NULL for appid is available */ + temp_client->appid = NULL; + } + xmlFree(key); + + temp_client_list = g_slist_append(temp_client_list, temp_client); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] enable is NULL"); + } + } + cur = cur->next; + } + + xmlFreeDoc(doc); + + *client_list = temp_client_list; + + remove(VC_RUNTIME_INFO_DEMANDABLE_LIST); + + return 0; +} + +int vc_info_parser_set_demandable_client(const char* filepath) +{ + if (NULL == filepath) { + remove(VC_RUNTIME_INFO_DEMANDABLE_LIST); + return 0; + } + + /* Check file */ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(filepath); + if (doc == NULL) { + SECURE_SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", filepath); + return -1; + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_DEMANDABLE_CLIENT_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + while (cur != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_APPID)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "App id : %s", (char *)key); + xmlFree(key); + } else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] enable is NULL"); + xmlFreeDoc(doc); + return -1; + } + } + cur = cur->next; + } + + int ret = xmlSaveFormatFile(VC_RUNTIME_INFO_DEMANDABLE_LIST, doc, 1); + SLOG(LOG_DEBUG, vc_info_tag(), "Save demandable file info : %d", ret); + + return 0; +} + +int vc_info_parser_set_result(const char* result_text, int event, const char* msg, vc_cmd_list_h vc_cmd_list, bool exclusive) +{ + char filepath[256] = {'\0',}; + + if (false == exclusive) { + snprintf(filepath, 256, "%s", VC_RUNTIME_INFO_RESULT); + } else { + snprintf(filepath, 256, "%s", VC_RUNTIME_INFO_EX_RESULT); + } + + SLOG(LOG_DEBUG, vc_info_tag(), "Result file path : %s", filepath); + + /* Check file */ + remove(filepath); + + xmlDocPtr doc; + xmlNodePtr root_node; + xmlNodePtr cmd_node; + xmlNodePtr tmp_node; + char temp[16]; + int ret = 0; + + doc = xmlNewDoc((const xmlChar*)"1.0"); + doc->encoding = (const xmlChar*)"utf-8"; + doc->charset = 1; + + root_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_RESULT_BASE_TAG); + xmlDocSetRootElement(doc,root_node); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_RESULT_TEXT); + xmlNodeSetContent(tmp_node, (const xmlChar *)result_text); + xmlAddChild(root_node, tmp_node); + + memset(temp, 0, 16); + snprintf(temp, 16, "%d", event); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_RESULT_EVENT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(root_node, tmp_node); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_RESULT_MESSAGE); + xmlNodeSetContent(tmp_node, (const xmlChar *)msg); + xmlAddChild(root_node, tmp_node); + + /* Make client list node */ + vc_cmd_h vc_command = NULL; + + vc_cmd_list_first(vc_cmd_list); + + while (VC_ERROR_ITERATION_END != ret) { + if (0 != vc_cmd_list_get_current(vc_cmd_list, &vc_command)) { + LOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to get command"); + break; + } + + if (NULL == vc_command) { + break; + } + + vc_cmd_s* temp_cmd = NULL; + temp_cmd = (vc_cmd_s*)vc_command; + + /* Make new command node */ + cmd_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CMD_COMMAND); + + SLOG(LOG_DEBUG, vc_info_tag(), "[Result info] ID(%d) PID(%d) type(%d) format(%d) domain(%d) cmd(%s) param(%s)", + temp_cmd->id, temp_cmd->pid, temp_cmd->type, temp_cmd->format, temp_cmd->domain, temp_cmd->command, temp_cmd->parameter); + + + /* ID */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->id); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_ID); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* PID */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->pid); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_PID); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* TYPE */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->type); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_TYPE); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* FORMAT */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->format); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_FORMAT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* DOMAIN */ + memset(temp, 0, 16); + snprintf(temp, 16, "%d", temp_cmd->domain); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_DOMAIN); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(cmd_node, tmp_node); + + /* COMMAND */ + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_COMMAND_TEXT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp_cmd->command); + xmlAddChild(cmd_node, tmp_node); + + /* PARAMETER */ + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CMD_PARAMETER_TEXT); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp_cmd->parameter); + xmlAddChild(cmd_node, tmp_node); + + xmlAddChild(root_node, cmd_node); + + ret = vc_cmd_list_next(vc_cmd_list); + } + + ret = xmlSaveFormatFile(filepath, doc, 1); + if (0 >= ret) { + SLOG(LOG_DEBUG, vc_info_tag(), "[ERROR] Fail to save result command file : %d", ret); + return -1; + } + + SLOG(LOG_DEBUG, vc_info_tag(), "[Success] Save result command file"); + + return 0; +} + +int vc_info_parser_get_result(char** result_text, int* event, char** result_message, int pid, vc_cmd_list_h vc_cmd_list, bool exclusive) +{ + if (NULL == result_text || NULL == event || NULL == vc_cmd_list) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Input parameter is NULL"); + return -1; + } + + char filepath[256] = {'\0',}; + + if (false == exclusive) { + snprintf(filepath, 256, "%s", VC_RUNTIME_INFO_RESULT); + } else { + snprintf(filepath, 256, "%s", VC_RUNTIME_INFO_EX_RESULT); + } + + SLOG(LOG_DEBUG, vc_info_tag(), "Result file path : %s", filepath); + + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(filepath); + if (doc == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[WARNING] Fail to parse file error : %s", filepath); + return -1; + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_RESULT_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_RESULT_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->next; + if (NULL == cur) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + /* Result text */ + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_RESULT_TEXT)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Result text : %s", (char *)key); + *result_text = strdup((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_RESULT_TEXT); + return -1; + } + } + + cur = cur->next; + cur = cur->next; + if (NULL == cur) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + /* Result event */ + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_RESULT_EVENT)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Result event : %s", (char *)key); + *event = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_RESULT_EVENT); + return -1; + } + } + + cur = cur->next; + cur = cur->next; + if (NULL == cur) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + /* Result Message */ + if (result_message != NULL) { + if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_RESULT_MESSAGE)) { + key = xmlNodeGetContent(cur); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Result message : %s", (char *)key); + *result_message = strdup((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_RESULT_MESSAGE); + return -1; + } + } + } + + vc_cmd_h vc_command = NULL; + + while (cur != NULL) { + + cur = cur->next; + if (NULL == cur) { + break; + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)"text")) { + continue; + } + + SLOG(LOG_ERROR, vc_info_tag(), "111 : %s", cur->name); + + /* Check Command tag */ + if (0 != xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CMD_COMMAND)) { + break; + } + + if (0 != vc_cmd_create(&vc_command)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to create command!!"); + return -1; + } + + vc_cmd_s* temp_cmd = NULL; + temp_cmd = (vc_cmd_s*)vc_command; + + if (NULL == temp_cmd) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Memory alloc error!!"); + return -1; + } + + xmlNodePtr command_node = NULL; + command_node = cur->xmlChildrenNode; + command_node = command_node->next; + + + SLOG(LOG_ERROR, vc_info_tag(), "222 : %s", command_node->name); + + /* ID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_ID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "ID : %s", (char *)key); + temp_cmd->id = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_ID); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* PID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "PID : %s", (char *)key); + temp_cmd->pid = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PID); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Type */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_TYPE)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Type : %s", (char *)key); + temp_cmd->type = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_TYPE); + free(temp_cmd); + return -1; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Format */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_FORMAT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Format : %s", (char *)key); + temp_cmd->format = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_FORMAT); + free(temp_cmd); + return -1; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Domain */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_DOMAIN)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Command domain : %s", (char *)key); + temp_cmd->domain = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_DOMAIN); + free(temp_cmd); + return -1; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Command */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_COMMAND_TEXT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Command text : %s, size : %d", (char *)key, xmlStrlen(key)); + if (0 < xmlStrlen(key)) { + temp_cmd->command = strdup((char*)key); + } else { + temp_cmd->command = NULL; + } + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_COMMAND_TEXT); + free(temp_cmd); + return -1; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Parameter */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PARAMETER_TEXT)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Parameter text : %s , size : %d", (char *)key, xmlStrlen(key)); + if (0 < xmlStrlen(key)) { + temp_cmd->parameter = strdup((char*)key); + } else { + temp_cmd->parameter = NULL; + } + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PARAMETER_TEXT); + if (NULL != temp_cmd->command) free(temp_cmd->command); + free(temp_cmd); + return -1; + } + } + + if (0 < pid && pid != temp_cmd->pid) { + SLOG(LOG_DEBUG, vc_info_tag(), "Current command is NOT valid"); + vc_cmd_destroy(vc_command); + } else { + if (0 != vc_cmd_list_add(vc_cmd_list, vc_command)) { + SLOG(LOG_DEBUG, vc_info_tag(), "Fail to add command to list"); + vc_cmd_destroy(vc_command); + return -1; + } + } + } + + xmlFreeDoc(doc); + + return 0; +} + +int vc_info_parser_unset_result(bool exclusive) +{ + if (false == exclusive) { + remove(VC_RUNTIME_INFO_RESULT); + } else { + remove(VC_RUNTIME_INFO_EX_RESULT); + } + + return 0; +} + +int vc_info_parser_get_result_pid_list(GSList** pid_list) +{ + char filepath[256] = {'\0', }; + snprintf(filepath, 256, "%s", VC_RUNTIME_INFO_RESULT); + + SLOG(LOG_DEBUG, vc_info_tag(), "Result file path : %s", filepath); + + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(filepath); + if (doc == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[WARNING] Fail to parse file error : %s", filepath); + return -1; + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_RESULT_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_RESULT_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + cur = cur->next; + + cur = cur->next; + cur = cur->next; + + cur = cur->next; + cur = cur->next; + + GSList* iter = NULL; + vc_cmd_s* temp_cmd = NULL; + vc_cmd_s* check_cmd = NULL; + + while (cur != NULL) { + + cur = cur->next; + if (NULL == cur) { + break; + } + else if (0 == xmlStrcmp(cur->name, (const xmlChar *)"text")) { + continue; + } + + /* Check Command tag */ + if (0 != xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CMD_COMMAND)) { + break; + } + + temp_cmd = (vc_cmd_s*)calloc(1, sizeof(vc_cmd_s)); + if (NULL == temp_cmd) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to alloc command"); + break; + } + + xmlNodePtr command_node = NULL; + command_node = cur->xmlChildrenNode; + command_node = command_node->next; + + /* ID */ + if (0 != xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_ID)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_ID); + free(temp_cmd); + break; + } + + command_node = command_node->next; + command_node = command_node->next; + + /* PID */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_PID)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "PID : %s", (char *)key); + temp_cmd->pid = atoi((char*)key); + xmlFree(key); + } + else { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_PID); + free(temp_cmd); + break; + } + } + + command_node = command_node->next; + command_node = command_node->next; + + /* Type */ + if (0 == xmlStrcmp(command_node->name, (const xmlChar *)VC_TAG_CMD_TYPE)) { + key = xmlNodeGetContent(command_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "Type : %s", (char *)key); + temp_cmd->type = atoi((char*)key); + xmlFree(key); + } + else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_TYPE); + free(temp_cmd); + return -1; + } + } + + /* check pid in gslist */ + iter = g_slist_nth(*pid_list, 0); + while (NULL != iter) { + check_cmd = iter->data; + + if (NULL == check_cmd) { + free(temp_cmd); + temp_cmd = NULL; + break; + } + + if (check_cmd->pid == temp_cmd->pid && check_cmd->type == temp_cmd->type) { + free(temp_cmd); + temp_cmd = NULL; + break; + } + iter = g_slist_next(iter); + } + + if (NULL != temp_cmd) { + /* add pid to gslist */ + *pid_list = g_slist_append(*pid_list, temp_cmd); + } + } + + xmlFreeDoc(doc); + + return 0; +} + +int vc_info_parser_set_client_info(GSList* client_info_list) +{ + if (0 >= g_slist_length(client_info_list)) { + SLOG(LOG_WARN, vc_info_tag(), "[WARNING] client list is empty"); + return 0; + } + + /* Remove file */ + remove(VC_RUNTIME_INFO_CLIENT); + + xmlDocPtr doc; + xmlNodePtr root_node; + xmlNodePtr client_node; + xmlNodePtr tmp_node; + + doc = xmlNewDoc((const xmlChar*)"1.0"); + doc->encoding = (const xmlChar*)"utf-8"; + doc->charset = 1; + + root_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CLIENT_BASE_TAG); + xmlDocSetRootElement(doc, root_node); + + GSList *iter = NULL; + vc_client_info_s *client = NULL; + + int i; + int count = g_slist_length(client_info_list); + iter = g_slist_nth(client_info_list, 0); + + SLOG(LOG_DEBUG, vc_info_tag(), "client count : %d", count); + char temp[16] = {0, }; + + for (i = 0;i < count;i++) { + client = iter->data; + + if (NULL != client) { + SLOG(LOG_DEBUG, vc_info_tag(), "[%dth] pid(%d) fgcmd(%d) bgcmd(%d) excmd(%d)", + i, client->pid, client->fg_cmd, client->bg_cmd, client->exclusive_cmd); + + /* Make new client node */ + client_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CLIENT_CLIENT); + + memset(temp, 0, 16); + snprintf(temp, 16, "%d", client->pid); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CLIENT_PID); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(client_node, tmp_node); + + memset(temp, 0, 16); + snprintf(temp, 16, "%d", client->fg_cmd); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CLIENT_FGCMD); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(client_node, tmp_node); + + memset(temp, 0, 16); + snprintf(temp, 16, "%d", client->bg_cmd); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CLIENT_BGCMD); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(client_node, tmp_node); + + memset(temp, 0, 16); + snprintf(temp, 16, "%d", client->exclusive_cmd); + + tmp_node = xmlNewNode(NULL,(const xmlChar*)VC_TAG_CLIENT_EXCMD); + xmlNodeSetContent(tmp_node, (const xmlChar *)temp); + xmlAddChild(client_node, tmp_node); + + xmlAddChild(root_node, client_node); + } + iter = g_slist_next(iter); + } + + int ret = xmlSaveFormatFile(VC_RUNTIME_INFO_CLIENT, doc, 1); + //xmlFreeDoc(doc); + if (0 >= ret) { + SLOG(LOG_DEBUG, vc_info_tag(), "[ERROR] Fail to save client file : %d", ret); + return -1; + } + + SLOG(LOG_DEBUG, vc_info_tag(), "[Success] Save client file"); + + return 0; +} + +int vc_info_parser_get_client_info(GSList** client_info_list) +{ + xmlDocPtr doc = NULL; + xmlNodePtr cur = NULL; + xmlChar *key; + + doc = xmlParseFile(VC_RUNTIME_INFO_CLIENT); + if (doc == NULL) { + SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", VC_RUNTIME_INFO_CLIENT); + return -1; + } + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CLIENT_BASE_TAG)) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_CLIENT_BASE_TAG); + xmlFreeDoc(doc); + return -1; + } + + cur = cur->xmlChildrenNode; + if (cur == NULL) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document"); + xmlFreeDoc(doc); + return -1; + } + + GSList* temp_client_list = NULL; + + while (cur != NULL) { + cur = cur->next; + + if (NULL == cur) { + break; + } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)"text")) { + continue; + } + + xmlNodePtr client_node = NULL; + client_node = cur->xmlChildrenNode; + client_node = client_node->next; + + vc_client_info_s *client = NULL; + client = (vc_client_info_s*)calloc(1, sizeof(vc_client_info_s)); + + if (NULL == client) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Memory alloc error!!"); + return -1; + } + + /* PID */ + if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CLIENT_PID)) { + key = xmlNodeGetContent(client_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "pid : %s", (char *)key); + client->pid = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CLIENT_PID); + free(client); + break; + } + } + + client_node = client_node->next; + client_node = client_node->next; + + /* Foreground command */ + if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CLIENT_FGCMD)) { + key = xmlNodeGetContent(client_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "fgcmd : %s", (char *)key); + client->fg_cmd = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CLIENT_FGCMD); + free(client); + break; + } + } + + client_node = client_node->next; + client_node = client_node->next; + + /* Background command */ + if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CLIENT_BGCMD)) { + key = xmlNodeGetContent(client_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "bgcmd : %s", (char *)key); + client->bg_cmd = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CLIENT_BGCMD); + free(client); + break; + } + } + + client_node = client_node->next; + client_node = client_node->next; + + /* Text */ + if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CMD_COMMAND_TEXT)) { + key = xmlNodeGetContent(client_node); + if (NULL != key) { + SLOG(LOG_DEBUG, vc_info_tag(), "excmd : %s", (char *)key); + client->exclusive_cmd = atoi((char*)key); + xmlFree(key); + } else { + SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_COMMAND_TEXT); + free(client); + break; + } + } + + temp_client_list = g_slist_append(temp_client_list, client); + } + + xmlFreeDoc(doc); + + *client_info_list = temp_client_list; + + return 0; +} + +int __vc_cmd_parser_print_commands(GSList* cmd_list) +{ + int count = g_slist_length(cmd_list); + int i ; + GSList *iter = NULL; + vc_cmd_s *temp_cmd; + + iter = g_slist_nth(cmd_list, 0); + + for (i = 0;i < count;i++) { + temp_cmd = iter->data; + + if (NULL == temp_cmd) { + SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] NULL data from command list"); + iter = g_slist_next(iter); + continue; + } + + SLOG(LOG_DEBUG, vc_info_tag(), " [%d][%p] PID(%d) ID(%d) Type(%d) Format(%d) Domain(%d) Command(%s) Param(%s)", + i, temp_cmd, temp_cmd->pid, temp_cmd->index, temp_cmd->type, temp_cmd->format, temp_cmd->domain, + temp_cmd->command, temp_cmd->parameter); + + iter = g_slist_next(iter); + + if (NULL == iter) + break; + } + + return 0; +} diff --git a/common/vc_info_parser.h b/common/vc_info_parser.h new file mode 100644 index 0000000..14a7ed8 --- /dev/null +++ b/common/vc_info_parser.h @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_CMD_PARSER_H_ +#define __VC_CMD_PARSER_H_ + +#include + +#include "vc_command.h" +#include "voice_control_command.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct _demandable_client_s{ + char* appid; +}vc_demandable_client_s; + +typedef struct _client_s{ + int pid; + bool fg_cmd; + bool bg_cmd; + bool exclusive_cmd; +}vc_client_info_s; + + +int vc_cmd_parser_save_file(int pid, vc_cmd_type_e type, GSList* cmd_list); + +int vc_cmd_parser_delete_file(int pid, vc_cmd_type_e type); + +int vc_cmd_parser_get_commands(int pid, vc_cmd_type_e type, GSList** cmd_list); + +int vc_cmd_parser_get_command_info(int pid, vc_cmd_type_e type, int index, vc_cmd_s** info); + +int vc_cmd_parser_append_commands(int pid, vc_cmd_type_e type, vc_cmd_list_h vc_cmd_list); + + +/* client request rule */ +int vc_info_parser_set_demandable_client(const char* filepath); + +int vc_info_parser_get_demandable_clients(GSList** client_list); + + +/* Result info */ +int vc_info_parser_set_result(const char* result_text, int event, const char* msg, vc_cmd_list_h vc_cmd_list, bool exclusive); + +int vc_info_parser_get_result(char** result_text, int* event, char** result_message, int pid, vc_cmd_list_h vc_cmd_list, bool exclusive); + +int vc_info_parser_unset_result(bool exclusive); + +int vc_info_parser_get_result_pid_list(GSList** pid_list); + + +/* Client info */ +int vc_info_parser_set_client_info(GSList* client_info_list); + +int vc_info_parser_get_client_info(GSList** client_info_list); + + +/* for debug */ +int __vc_cmd_parser_print_commands(GSList* cmd_list); + +int __vc_info_parser_print_results(GSList* result_list); + + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_CMD_PARSER_H_ */ diff --git a/common/vc_main.h b/common/vc_main.h new file mode 100644 index 0000000..b94c446 --- /dev/null +++ b/common/vc_main.h @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the License); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#ifndef __VC_MAIN_H_ +#define __VC_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vc_defs.h" +#include "voice_control_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG_VCC "vcc" /* Normal client log tag */ +#define TAG_VCW "vcw" /* Widget client log tag */ +#define TAG_VCM "vcm" /* Manager client log tag */ +#define TAG_VCS "vcsetting" /* Setting client log tag */ +#define TAG_VCINFO "vcinfo" /* info lib log tag */ +#define TAG_VCCONFIG "vcinfo" /* config lib log tag */ +#define TAG_VCCMD "vccmd" /* Command log tag */ + +/** +* @brief A structure of handle for identification +*/ +struct vc_s { + int handle; +}; + +typedef struct vc_s *vc_h; + +#ifdef __cplusplus +} +#endif + +#endif /* __VC_CLIENT_H_ */ diff --git a/doc/doxyfile b/doc/doxyfile new file mode 100644 index 0000000..68061dd --- /dev/null +++ b/doc/doxyfile @@ -0,0 +1,2373 @@ +# Doxyfile 1.8.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = VoiceControl + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../include/voice_control.h \ + ../include/voice_control_command.h \ + ../include/voice_control_common.h \ + uix_vc_doc.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = images/capi_uix_voice_control_state_diagram.png \ + images/capi_uix_voice_control_service_state_diagram.png + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /