'mmi-node-source.h',
'mmi-node-processor.h',
'mmi-node-logic.h',
+ 'mmi-node-controller.h',
+ 'mmi-node-action.h',
'mmi-port.h',
'mmi-signal.h',
'mmi-defines.h',
'mmi-plugin-module.h',
'mmi-plugin-storage.h',
'mmi.h',
+ 'mmi-config-parser.h',
)
#define __TIZEN_UIX_MMI_ATTRIBUTE_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <stdlib.h>
#include <mmi-primitive-value.h>
--- /dev/null
+/*
+ * Copyright © 2023 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef __MMI_CONFIG_PARSER_H_
+#define __MMI_CONFIG_PARSER_H_
+
+#include <glib.h>
+#include <libxml/parser.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct {
+ float confidence;
+} mmi_config_s;
+
+int mmi_parser_initialize(void);
+int mmi_parser_deinitialize(void);
+int mmi_parser_get_confidence(float *confidence);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MMI_CONFIG_PARSER_H_ */
#define __TIZEN_UIX_MMI_DATA_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <stdlib.h>
MMI_DATA_TYPE_USER_IDENTIFICATION,
MMI_DATA_TYPE_AUDIO,
MMI_DATA_TYPE_VIDEO,
+ MMI_DATA_TYPE_COORDINATE,
MMI_DATA_TYPE_BOUNDING_BOX,
MMI_DATA_TYPE_ARRAY,
MMI_DATA_TYPE_STRUCT,
- MMI_DATA_INTEGER
data : pointer to a signed integer type
- datalen : 4 byte
+ datalen : 4 bytes
description : cast 'data' to a 32-bit signed integer (e.g. int)
- MMI_DATA_FLOAT
data : pointer to a floating-point type
- datalen : 4 byte
+ datalen : 4 bytes
description : cast 'data' to a 32-bit floating-point type (e.g. float)
- MMI_DATA_TEXT
}
description : video frame data
+- MMI_DATA_COORDINATE
+ data : pointer to an array of 2 signed integers
+ datalen : 8 bytes
+ description : data is composed in below order
+ [ x , y ]
+
- MMI_DATA_BOUNDING_BOX
- data : pointer to json string
- datalen : length of the json string
- description : data is composed in below json format
- {
- "x":300,
- "y":150,
- "w":200,
- "h":200
- }
+ data : pointer to an array of 4 signed integers
+ datalen : 16 bytes
+ description : data is composed in below order
+ [ x , y , w , h ]
- MMI_DATA_ARRAY
data : pointer to an array of mmi_data_h struct
int mmi_data_create_user_identification(const void *ptr, size_t len, mmi_data_h *data);
+int mmi_data_create_coordinate(int x, int y, mmi_data_h *data);
+
+int mmi_data_create_bounding_box(int x, int y, int w, int h, mmi_data_h *data);
+
int mmi_data_create_array(mmi_data_h *array_handle);
int mmi_data_add_array_element(mmi_data_h array_handle, mmi_data_h element);
int mmi_data_get_user_identification(mmi_data_h data, const void **ptr, size_t *len);
+int mmi_data_get_coordinate(mmi_data_h data, int *x, int *y);
+
+int mmi_data_get_bounding_box(mmi_data_h data, int *x, int *y, int *w, int *h);
+
int mmi_data_get_array_count(mmi_data_h array, size_t *count);
int mmi_data_get_array_element(mmi_data_h array, size_t index, mmi_data_h *element);
#define __TIZEN_UIX_MMI_ERROR_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
/**
#endif
-#define TIZEN_ERROR_MMI -0x030F0000
-
typedef enum {
- MMI_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
- MMI_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of Memory */
- MMI_ERROR_IO_ERROR = TIZEN_ERROR_IO_ERROR, /**< I/O error */
- MMI_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
- MMI_ERROR_OUT_OF_NETWORK = TIZEN_ERROR_NETWORK_DOWN, /**< Network is down */
- MMI_ERROR_TIMED_OUT = TIZEN_ERROR_TIMED_OUT, /**< No answer from the daemon */
- MMI_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */
- MMI_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< MMI NOT supported */
- MMI_ERROR_OPERATION_FAILED = TIZEN_ERROR_MMI | 0x01, /**< Operation failed */
- MMI_ERROR_RESOURCE_BUSY = TIZEN_ERROR_MMI | 0x02, /**< Resource busy */
+ MMI_ERROR_NONE = PLATFORM_ERROR_NONE, /**< Successful */
+ MMI_ERROR_OUT_OF_MEMORY = PLATFORM_ERROR_OUT_OF_MEMORY, /**< Out of Memory */
+ MMI_ERROR_IO_ERROR = PLATFORM_ERROR_IO_ERROR, /**< I/O error */
+ MMI_ERROR_INVALID_PARAMETER = PLATFORM_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ MMI_ERROR_TIMED_OUT = PLATFORM_ERROR_TIMED_OUT, /**< No answer from the daemon */
+ MMI_ERROR_PERMISSION_DENIED = PLATFORM_ERROR_PERMISSION_DENIED, /**< Permission denied */
+ MMI_ERROR_NOT_SUPPORTED = PLATFORM_ERROR_NOT_SUPPORTED, /**< MMI NOT supported */
+ MMI_ERROR_OPERATION_FAILED = PLATFORM_ERROR_OPERATION_FAILED, /**< Operation failed */
+ MMI_ERROR_RESOURCE_BUSY = PLATFORM_ERROR_RESOURCE_BUSY, /**< Resource busy */
} mmi_error_e;
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef __TIZEN_UIX_MMI_NODE_ACTION_H__
+#define __TIZEN_UIX_MMI_NODE_ACTION_H__
+
+
+
+#include <mmi-node.h>
+
+/**
+* @file mmi-node-action.h
+*/
+
+
+/**
+* @addtogroup CAPI_UIX_MMI_MODULE
+* @{
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum mmi_standard_node_action_type_e {
+ MMI_STANDARD_NODE_ACTION_TYPE_NONE,
+
+ /* - Description : Emits a mouse event
+ - Attributes :
+ - "EVENT" : string
+ Default : "CLICK"
+ Description : The type of mouse event to emit
+ Supported values are : "CLICK", "DOWN", "UP"
+ - Input Port 1
+ Name : "COORDINATE"
+ Data Type : MMI_DATA_TYPE_COORDINATE
+ Description : When a coordinate data is received, emits a mouse event
+ */
+ MMI_STANDARD_NODE_ACTION_TYPE_MOUSE_EVENT,
+
+ MMI_STANDARD_NODE_ACTION_TYPE_KEY_EVENT,
+};
+
+int mmi_standard_node_create_action(mmi_standard_node_action_type_e type, mmi_node_h *node);
+
+int mmi_standard_node_get_action_type(mmi_node_h node, mmi_standard_node_action_type_e *type);
+
+int mmi_standard_node_register_action(mmi_standard_node_action_type_e type, mmi_node_callbacks *callbacks, mmi_node_h node);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/**
+ * @}
+ */
+
+
+#endif /* __TIZEN_UIX_MMI_NODE_LOGIC_H__ */
/*
- Attributes : None
- Input Port 1
+ Name : "VIDEO_IN"
+ Data Type : MMI_DATA_TYPE_VIDEO
+ - Output Port 1
+ Name : "VIDEO_OUT"
+ Data Type : MMI_DATA_TYPE_VIDEO
+ */
+ MMI_STANDARD_NODE_PROCESSOR_TYPE_VIDEO_CONVERTER,
+
+ /*
+ - Attributes : None
+ - Input Port 1
Name : "VIDEO"
Data Type : MMI_DATA_TYPE_VIDEO
- Output Port 1
#define __TIZEN_UIX_MMI_NODE_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <mmi-attribute.h>
#include <mmi-data.h>
MMI_STANDARD_NODE_TYPE_PROCESSOR,
MMI_STANDARD_NODE_TYPE_LOGIC,
MMI_STANDARD_NODE_TYPE_CONTROLLER,
+ MMI_STANDARD_NODE_TYPE_ACTION,
};
typedef void* mmi_node_instance_h;
#include <mmi-node-processor.h>
#include <mmi-node-logic.h>
#include <mmi-node-controller.h>
+#include <mmi-node-action.h>
#include <mmi-workflow.h>
/**
#define __TIZEN_UIX_MMI_PORT_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <mmi-data.h>
#include <mmi-defines.h>
#define __TIZEN_UIX_MMI_PRIMITIVE_VALUE_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <stdlib.h>
#define __TIZEN_UIX_MMI_SIGNAL_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <stdlib.h>
#include <string.h>
#define __TIZEN_UIX_MMI_WORKFLOW_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
#include <mmi-attribute.h>
#include <mmi-data.h>
} mmi_workflow_attribute_default_value_info_s;
typedef struct {
+ char signal_name[MMI_NAME_MAX_LENGTH];
+ char target_node_name[MMI_NAME_MAX_LENGTH];
+ char target_signal_name[MMI_NAME_MAX_LENGTH];
+} mmi_workflow_signal_assignment_info_s;
+
+typedef struct {
char output_name[MMI_NAME_MAX_LENGTH];
char from_node_name[MMI_NAME_MAX_LENGTH];
char from_port_name[MMI_NAME_MAX_LENGTH];
size_t attribute_assignment_info_count;
mmi_workflow_attribute_default_value_info_s *attribute_default_value_infos;
size_t attribute_default_value_info_count;
+ mmi_workflow_signal_assignment_info_s *signal_assignment_infos;
+ size_t signal_assignment_info_count;
mmi_workflow_output_assignment_info_s *output_assignment_infos;
size_t output_assignment_info_count;
} mmi_workflow_s;
int mmi_workflow_attribute_set_default_value(mmi_workflow_h workflow, mmi_attribute_h default_value);
/* Assign a signal of a workflow to a signal of a specific node in a workflow prototype */
-int mmi_workflow_signal_assign(mmi_workflow_h workflow, const char *workflow_signal, mmi_node_h node, const char *node_signal);
+int mmi_workflow_signal_assign(mmi_workflow_h workflow, const char *signal_name, const char *target_node_name, const char *target_signal_name);
/* Assign an output of a workflow to a OUT port of a specific node in a workflow prototype */
/* FIXME: It would be better to use handles instead of names. */
int mmi_workflow_instance_set_attribute(mmi_workflow_instance_h instance, mmi_attribute_h attribute);
/* Emit a signal to a workflow instance */
-// int mmi_workflow_instance_signal_emit(mmi_workflow_instance_h instance, mmi_signal_h signal);
+int mmi_workflow_instance_emit_signal(mmi_workflow_instance_h instance, mmi_signal_h signal);
/* Set a callback function to receive workflow output */
int mmi_workflow_instance_set_output_callback(mmi_workflow_instance_h instance, const char *name, mmi_workflow_output_cb callback, void *user_data);
#ifndef __MMI_H__
#define __MMI_H__
-#include <tizen.h>
+#include "mmi-platform-config.h"
+
#define MMI_API __attribute__ ((visibility("default")))
#include <mmi-defines.h>
--- /dev/null
+// __ __ _ ______ _____
+// | \/ | (_) | ____| / ____|_ _
+// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
+// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
+// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
+// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
+// __/ | https://github.com/Neargye/magic_enum
+// |___/ version 0.9.5
+//
+// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef NEARGYE_MAGIC_ENUM_HPP
+#define NEARGYE_MAGIC_ENUM_HPP
+
+#define MAGIC_ENUM_VERSION_MAJOR 0
+#define MAGIC_ENUM_VERSION_MINOR 9
+#define MAGIC_ENUM_VERSION_PATCH 5
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <limits>
+#include <type_traits>
+#include <utility>
+
+#if defined(MAGIC_ENUM_CONFIG_FILE)
+# include MAGIC_ENUM_CONFIG_FILE
+#endif
+
+#if !defined(MAGIC_ENUM_USING_ALIAS_OPTIONAL)
+# include <optional>
+#endif
+#if !defined(MAGIC_ENUM_USING_ALIAS_STRING)
+# include <string>
+#endif
+#if !defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW)
+# include <string_view>
+#endif
+
+#if defined(MAGIC_ENUM_NO_ASSERT)
+# define MAGIC_ENUM_ASSERT(...) static_cast<void>(0)
+#else
+# include <cassert>
+# define MAGIC_ENUM_ASSERT(...) assert((__VA_ARGS__))
+#endif
+
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunknown-warning-option"
+# pragma clang diagnostic ignored "-Wenum-constexpr-conversion"
+# pragma clang diagnostic ignored "-Wuseless-cast" // suppresses 'static_cast<char_type>('\0')' for char_type = char (common on Linux).
+#elif defined(__GNUC__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" // May be used uninitialized 'return {};'.
+# pragma GCC diagnostic ignored "-Wuseless-cast" // suppresses 'static_cast<char_type>('\0')' for char_type = char (common on Linux).
+#elif defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable : 26495) // Variable 'static_str<N>::chars_' is uninitialized.
+# pragma warning(disable : 28020) // Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value.
+# pragma warning(disable : 26451) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call.
+# pragma warning(disable : 4514) // Unreferenced inline function has been removed.
+#endif
+
+// Checks magic_enum compiler compatibility.
+#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1910 || defined(__RESHARPER__)
+# undef MAGIC_ENUM_SUPPORTED
+# define MAGIC_ENUM_SUPPORTED 1
+#endif
+
+// Checks magic_enum compiler aliases compatibility.
+#if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920
+# undef MAGIC_ENUM_SUPPORTED_ALIASES
+# define MAGIC_ENUM_SUPPORTED_ALIASES 1
+#endif
+
+// Enum value must be greater or equals than MAGIC_ENUM_RANGE_MIN. By default MAGIC_ENUM_RANGE_MIN = -128.
+// If need another min range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN.
+#if !defined(MAGIC_ENUM_RANGE_MIN)
+# define MAGIC_ENUM_RANGE_MIN -128
+#endif
+
+// Enum value must be less or equals than MAGIC_ENUM_RANGE_MAX. By default MAGIC_ENUM_RANGE_MAX = 128.
+// If need another max range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MAX.
+#if !defined(MAGIC_ENUM_RANGE_MAX)
+# define MAGIC_ENUM_RANGE_MAX 127
+#endif
+
+// Improve ReSharper C++ intellisense performance with builtins, avoiding unnecessary template instantiations.
+#if defined(__RESHARPER__)
+# undef MAGIC_ENUM_GET_ENUM_NAME_BUILTIN
+# undef MAGIC_ENUM_GET_TYPE_NAME_BUILTIN
+# if __RESHARPER__ >= 20230100
+# define MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V) __rscpp_enumerator_name(V)
+# define MAGIC_ENUM_GET_TYPE_NAME_BUILTIN(T) __rscpp_type_name<T>()
+# else
+# define MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V) nullptr
+# define MAGIC_ENUM_GET_TYPE_NAME_BUILTIN(T) nullptr
+# endif
+#endif
+
+namespace magic_enum {
+
+// If need another optional type, define the macro MAGIC_ENUM_USING_ALIAS_OPTIONAL.
+#if defined(MAGIC_ENUM_USING_ALIAS_OPTIONAL)
+MAGIC_ENUM_USING_ALIAS_OPTIONAL
+#else
+using std::optional;
+#endif
+
+// If need another string_view type, define the macro MAGIC_ENUM_USING_ALIAS_STRING_VIEW.
+#if defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW)
+MAGIC_ENUM_USING_ALIAS_STRING_VIEW
+#else
+using std::string_view;
+#endif
+
+// If need another string type, define the macro MAGIC_ENUM_USING_ALIAS_STRING.
+#if defined(MAGIC_ENUM_USING_ALIAS_STRING)
+MAGIC_ENUM_USING_ALIAS_STRING
+#else
+using std::string;
+#endif
+
+using char_type = string_view::value_type;
+static_assert(std::is_same_v<string_view::value_type, string::value_type>, "magic_enum::customize requires same string_view::value_type and string::value_type");
+static_assert([] {
+ if constexpr (std::is_same_v<char_type, wchar_t>) {
+ constexpr const char c[] = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
+ constexpr const wchar_t wc[] = L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789|";
+ static_assert(std::size(c) == std::size(wc), "magic_enum::customize identifier characters are multichars in wchar_t.");
+
+ for (std::size_t i = 0; i < std::size(c); ++i) {
+ if (c[i] != wc[i]) {
+ return false;
+ }
+ }
+ }
+ return true;
+} (), "magic_enum::customize wchar_t is not compatible with ASCII.");
+
+namespace customize {
+
+// Enum value must be in range [MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]. By default MAGIC_ENUM_RANGE_MIN = -128, MAGIC_ENUM_RANGE_MAX = 128.
+// If need another range for all enum types by default, redefine the macro MAGIC_ENUM_RANGE_MIN and MAGIC_ENUM_RANGE_MAX.
+// If need another range for specific enum type, add specialization enum_range for necessary enum type.
+template <typename E>
+struct enum_range {
+ static_assert(std::is_enum_v<E>, "magic_enum::customize::enum_range requires enum type.");
+ static constexpr int min = MAGIC_ENUM_RANGE_MIN;
+ static constexpr int max = MAGIC_ENUM_RANGE_MAX;
+ static_assert(max > min, "magic_enum::customize::enum_range requires max > min.");
+};
+
+static_assert(MAGIC_ENUM_RANGE_MAX > MAGIC_ENUM_RANGE_MIN, "MAGIC_ENUM_RANGE_MAX must be greater than MAGIC_ENUM_RANGE_MIN.");
+static_assert((MAGIC_ENUM_RANGE_MAX - MAGIC_ENUM_RANGE_MIN) < (std::numeric_limits<std::uint16_t>::max)(), "MAGIC_ENUM_RANGE must be less than UINT16_MAX.");
+
+namespace detail {
+
+enum class customize_tag {
+ default_tag,
+ invalid_tag,
+ custom_tag
+};
+
+} // namespace magic_enum::customize::detail
+
+class customize_t : public std::pair<detail::customize_tag, string_view> {
+ public:
+ constexpr customize_t(string_view srt) : std::pair<detail::customize_tag, string_view>{detail::customize_tag::custom_tag, srt} {}
+ constexpr customize_t(const char_type* srt) : customize_t{string_view{srt}} {}
+ constexpr customize_t(detail::customize_tag tag) : std::pair<detail::customize_tag, string_view>{tag, string_view{}} {
+ MAGIC_ENUM_ASSERT(tag != detail::customize_tag::custom_tag);
+ }
+};
+
+// Default customize.
+inline constexpr auto default_tag = customize_t{detail::customize_tag::default_tag};
+// Invalid customize.
+inline constexpr auto invalid_tag = customize_t{detail::customize_tag::invalid_tag};
+
+// If need custom names for enum, add specialization enum_name for necessary enum type.
+template <typename E>
+constexpr customize_t enum_name(E) noexcept {
+ return default_tag;
+}
+
+// If need custom type name for enum, add specialization enum_type_name for necessary enum type.
+template <typename E>
+constexpr customize_t enum_type_name() noexcept {
+ return default_tag;
+}
+
+} // namespace magic_enum::customize
+
+namespace detail {
+
+template <typename T>
+struct supported
+#if defined(MAGIC_ENUM_SUPPORTED) && MAGIC_ENUM_SUPPORTED || defined(MAGIC_ENUM_NO_CHECK_SUPPORT)
+ : std::true_type {};
+#else
+ : std::false_type {};
+#endif
+
+template <auto V, typename E = std::decay_t<decltype(V)>, std::enable_if_t<std::is_enum_v<E>, int> = 0>
+using enum_constant = std::integral_constant<E, V>;
+
+template <typename... T>
+inline constexpr bool always_false_v = false;
+
+template <typename T, typename = void>
+struct has_is_flags : std::false_type {};
+
+template <typename T>
+struct has_is_flags<T, std::void_t<decltype(customize::enum_range<T>::is_flags)>> : std::bool_constant<std::is_same_v<bool, std::decay_t<decltype(customize::enum_range<T>::is_flags)>>> {};
+
+template <typename T, typename = void>
+struct range_min : std::integral_constant<int, MAGIC_ENUM_RANGE_MIN> {};
+
+template <typename T>
+struct range_min<T, std::void_t<decltype(customize::enum_range<T>::min)>> : std::integral_constant<decltype(customize::enum_range<T>::min), customize::enum_range<T>::min> {};
+
+template <typename T, typename = void>
+struct range_max : std::integral_constant<int, MAGIC_ENUM_RANGE_MAX> {};
+
+template <typename T>
+struct range_max<T, std::void_t<decltype(customize::enum_range<T>::max)>> : std::integral_constant<decltype(customize::enum_range<T>::max), customize::enum_range<T>::max> {};
+
+struct str_view {
+ const char* str_ = nullptr;
+ std::size_t size_ = 0;
+};
+
+template <std::uint16_t N>
+class static_str {
+ public:
+ constexpr explicit static_str(str_view str) noexcept : static_str{str.str_, std::make_integer_sequence<std::uint16_t, N>{}} {
+ MAGIC_ENUM_ASSERT(str.size_ == N);
+ }
+
+ constexpr explicit static_str(string_view str) noexcept : static_str{str.data(), std::make_integer_sequence<std::uint16_t, N>{}} {
+ MAGIC_ENUM_ASSERT(str.size() == N);
+ }
+
+ constexpr const char_type* data() const noexcept { return chars_; }
+
+ constexpr std::uint16_t size() const noexcept { return N; }
+
+ constexpr operator string_view() const noexcept { return {data(), size()}; }
+
+ private:
+ template <std::uint16_t... I>
+ constexpr static_str(const char* str, std::integer_sequence<std::uint16_t, I...>) noexcept : chars_{static_cast<char_type>(str[I])..., static_cast<char_type>('\0')} {}
+
+ template <std::uint16_t... I>
+ constexpr static_str(string_view str, std::integer_sequence<std::uint16_t, I...>) noexcept : chars_{str[I]..., static_cast<char_type>('\0')} {}
+
+ char_type chars_[static_cast<std::size_t>(N) + 1];
+};
+
+template <>
+class static_str<0> {
+ public:
+ constexpr explicit static_str() = default;
+
+ constexpr explicit static_str(str_view) noexcept {}
+
+ constexpr explicit static_str(string_view) noexcept {}
+
+ constexpr const char_type* data() const noexcept { return nullptr; }
+
+ constexpr std::uint16_t size() const noexcept { return 0; }
+
+ constexpr operator string_view() const noexcept { return {}; }
+};
+
+template <typename Op = std::equal_to<>>
+class case_insensitive {
+ static constexpr char_type to_lower(char_type c) noexcept {
+ return (c >= static_cast<char_type>('A') && c <= static_cast<char_type>('Z')) ? static_cast<char_type>(c + (static_cast<char_type>('a') - static_cast<char_type>('A'))) : c;
+ }
+
+ public:
+ template <typename L, typename R>
+ constexpr auto operator()(L lhs, R rhs) const noexcept -> std::enable_if_t<std::is_same_v<std::decay_t<L>, char_type> && std::is_same_v<std::decay_t<R>, char_type>, bool> {
+ return Op{}(to_lower(lhs), to_lower(rhs));
+ }
+};
+
+constexpr std::size_t find(string_view str, char_type c) noexcept {
+#if defined(__clang__) && __clang_major__ < 9 && defined(__GLIBCXX__) || defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
+// https://stackoverflow.com/questions/56484834/constexpr-stdstring-viewfind-last-of-doesnt-work-on-clang-8-with-libstdc
+// https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html
+ constexpr bool workaround = true;
+#else
+ constexpr bool workaround = false;
+#endif
+
+ if constexpr (workaround) {
+ for (std::size_t i = 0; i < str.size(); ++i) {
+ if (str[i] == c) {
+ return i;
+ }
+ }
+
+ return string_view::npos;
+ } else {
+ return str.find(c);
+ }
+}
+
+template <typename BinaryPredicate>
+constexpr bool is_default_predicate() noexcept {
+ return std::is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<string_view::value_type>> ||
+ std::is_same_v<std::decay_t<BinaryPredicate>, std::equal_to<>>;
+}
+
+template <typename BinaryPredicate>
+constexpr bool is_nothrow_invocable() {
+ return is_default_predicate<BinaryPredicate>() ||
+ std::is_nothrow_invocable_r_v<bool, BinaryPredicate, char_type, char_type>;
+}
+
+template <typename BinaryPredicate>
+constexpr bool cmp_equal(string_view lhs, string_view rhs, [[maybe_unused]] BinaryPredicate&& p) noexcept(is_nothrow_invocable<BinaryPredicate>()) {
+#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
+ // https://developercommunity.visualstudio.com/content/problem/360432/vs20178-regression-c-failed-in-test.html
+ // https://developercommunity.visualstudio.com/content/problem/232218/c-constexpr-string-view.html
+ constexpr bool workaround = true;
+#else
+ constexpr bool workaround = false;
+#endif
+
+ if constexpr (!is_default_predicate<BinaryPredicate>() || workaround) {
+ if (lhs.size() != rhs.size()) {
+ return false;
+ }
+
+ const auto size = lhs.size();
+ for (std::size_t i = 0; i < size; ++i) {
+ if (!p(lhs[i], rhs[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ } else {
+ return lhs == rhs;
+ }
+}
+
+template <typename L, typename R>
+constexpr bool cmp_less(L lhs, R rhs) noexcept {
+ static_assert(std::is_integral_v<L> && std::is_integral_v<R>, "magic_enum::detail::cmp_less requires integral type.");
+
+ if constexpr (std::is_signed_v<L> == std::is_signed_v<R>) {
+ // If same signedness (both signed or both unsigned).
+ return lhs < rhs;
+ } else if constexpr (std::is_same_v<L, bool>) { // bool special case
+ return static_cast<R>(lhs) < rhs;
+ } else if constexpr (std::is_same_v<R, bool>) { // bool special case
+ return lhs < static_cast<L>(rhs);
+ } else if constexpr (std::is_signed_v<R>) {
+ // If 'right' is negative, then result is 'false', otherwise cast & compare.
+ return rhs > 0 && lhs < static_cast<std::make_unsigned_t<R>>(rhs);
+ } else {
+ // If 'left' is negative, then result is 'true', otherwise cast & compare.
+ return lhs < 0 || static_cast<std::make_unsigned_t<L>>(lhs) < rhs;
+ }
+}
+
+template <typename I>
+constexpr I log2(I value) noexcept {
+ static_assert(std::is_integral_v<I>, "magic_enum::detail::log2 requires integral type.");
+
+ if constexpr (std::is_same_v<I, bool>) { // bool special case
+ return MAGIC_ENUM_ASSERT(false), value;
+ } else {
+ auto ret = I{0};
+ for (; value > I{1}; value >>= I{1}, ++ret) {}
+
+ return ret;
+ }
+}
+
+#if defined(__cpp_lib_array_constexpr) && __cpp_lib_array_constexpr >= 201603L
+# define MAGIC_ENUM_ARRAY_CONSTEXPR 1
+#else
+template <typename T, std::size_t N, std::size_t... I>
+constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N], std::index_sequence<I...>) noexcept {
+ return {{a[I]...}};
+}
+#endif
+
+template <typename T>
+inline constexpr bool is_enum_v = std::is_enum_v<T> && std::is_same_v<T, std::decay_t<T>>;
+
+template <typename E>
+constexpr auto n() noexcept {
+ static_assert(is_enum_v<E>, "magic_enum::detail::n requires enum type.");
+
+ if constexpr (supported<E>::value) {
+#if defined(MAGIC_ENUM_GET_TYPE_NAME_BUILTIN)
+ constexpr auto name_ptr = MAGIC_ENUM_GET_TYPE_NAME_BUILTIN(E);
+ constexpr auto name = name_ptr ? str_view{name_ptr, std::char_traits<char>::length(name_ptr)} : str_view{};
+#elif defined(__clang__)
+ str_view name;
+ if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
+ static_assert(always_false_v<E>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
+ return str_view{};
+ } else {
+ name.size_ = sizeof(__PRETTY_FUNCTION__) - 36;
+ name.str_ = __PRETTY_FUNCTION__ + 34;
+ }
+#elif defined(__GNUC__)
+ auto name = str_view{__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1};
+ if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
+ static_assert(always_false_v<E>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
+ return str_view{};
+ } else if (name.str_[name.size_ - 1] == ']') {
+ name.size_ -= 50;
+ name.str_ += 49;
+ } else {
+ name.size_ -= 40;
+ name.str_ += 37;
+ }
+#elif defined(_MSC_VER)
+ // CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
+ str_view name;
+ name.str_ = __FUNCSIG__;
+ name.str_ += 40;
+ name.size_ += sizeof(__FUNCSIG__) - 57;
+#else
+ auto name = str_view{};
+#endif
+ std::size_t p = 0;
+ for (std::size_t i = name.size_; i > 0; --i) {
+ if (name.str_[i] == ':') {
+ p = i + 1;
+ break;
+ }
+ }
+ if (p > 0) {
+ name.size_ -= p;
+ name.str_ += p;
+ }
+ return name;
+ } else {
+ return str_view{}; // Unsupported compiler or Invalid customize.
+ }
+}
+
+template <typename E>
+constexpr auto type_name() noexcept {
+ [[maybe_unused]] constexpr auto custom = customize::enum_type_name<E>();
+ static_assert(std::is_same_v<std::decay_t<decltype(custom)>, customize::customize_t>, "magic_enum::customize requires customize_t type.");
+ if constexpr (custom.first == customize::detail::customize_tag::custom_tag) {
+ constexpr auto name = custom.second;
+ static_assert(!name.empty(), "magic_enum::customize requires not empty string.");
+ return static_str<name.size()>{name};
+ } else if constexpr (custom.first == customize::detail::customize_tag::invalid_tag) {
+ return static_str<0>{};
+ } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) {
+ constexpr auto name = n<E>();
+ return static_str<name.size_>{name};
+ } else {
+ static_assert(always_false_v<E>, "magic_enum::customize invalid.");
+ }
+}
+
+template <typename E>
+inline constexpr auto type_name_v = type_name<E>();
+
+template <auto V>
+constexpr auto n() noexcept {
+ static_assert(is_enum_v<decltype(V)>, "magic_enum::detail::n requires enum type.");
+
+ if constexpr (supported<decltype(V)>::value) {
+#if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
+ constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
+ auto name = name_ptr ? str_view{name_ptr, std::char_traits<char>::length(name_ptr)} : str_view{};
+#elif defined(__clang__)
+ str_view name;
+ if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
+ static_assert(always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
+ return str_view{};
+ } else {
+ name.size_ = sizeof(__PRETTY_FUNCTION__) - 36;
+ name.str_ = __PRETTY_FUNCTION__ + 34;
+ }
+ if (name.size_ > 22 && name.str_[0] == '(' && name.str_[1] == 'a' && name.str_[10] == ' ' && name.str_[22] == ':') {
+ name.size_ -= 23;
+ name.str_ += 23;
+ }
+ if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
+ name = str_view{};
+ }
+#elif defined(__GNUC__)
+ auto name = str_view{__PRETTY_FUNCTION__, sizeof(__PRETTY_FUNCTION__) - 1};
+ if constexpr (sizeof(__PRETTY_FUNCTION__) == sizeof(__FUNCTION__)) {
+ static_assert(always_false_v<decltype(V)>, "magic_enum::detail::n requires __PRETTY_FUNCTION__.");
+ return str_view{};
+ } else if (name.str_[name.size_ - 1] == ']') {
+ name.size_ -= 55;
+ name.str_ += 54;
+ } else {
+ name.size_ -= 40;
+ name.str_ += 37;
+ }
+ if (name.str_[0] == '(') {
+ name = str_view{};
+ }
+#elif defined(_MSC_VER)
+ str_view name;
+ if ((__FUNCSIG__[5] == '_' && __FUNCSIG__[35] != '(') || (__FUNCSIG__[5] == 'c' && __FUNCSIG__[41] != '(')) {
+ // CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
+ name.str_ = __FUNCSIG__;
+ name.str_ += 35;
+ name.size_ = sizeof(__FUNCSIG__) - 52;
+ }
+#else
+ auto name = str_view{};
+#endif
+ std::size_t p = 0;
+ for (std::size_t i = name.size_; i > 0; --i) {
+ if (name.str_[i] == ':') {
+ p = i + 1;
+ break;
+ }
+ }
+ if (p > 0) {
+ name.size_ -= p;
+ name.str_ += p;
+ }
+ return name;
+ } else {
+ return str_view{}; // Unsupported compiler or Invalid customize.
+ }
+}
+
+#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER < 1920
+# define MAGIC_ENUM_VS_2017_WORKAROUND 1
+#endif
+
+#if defined(MAGIC_ENUM_VS_2017_WORKAROUND)
+template <typename E, E V>
+constexpr auto n() noexcept {
+ static_assert(is_enum_v<E>, "magic_enum::detail::n requires enum type.");
+
+# if defined(MAGIC_ENUM_GET_ENUM_NAME_BUILTIN)
+ constexpr auto name_ptr = MAGIC_ENUM_GET_ENUM_NAME_BUILTIN(V);
+ auto name = name_ptr ? str_view{name_ptr, std::char_traits<char>::length(name_ptr)} : str_view{};
+# else
+ // CLI/C++ workaround (see https://github.com/Neargye/magic_enum/issues/284).
+ str_view name;
+ name.str_ = __FUNCSIG__;
+ name.size_ = sizeof(__FUNCSIG__) - 17;
+ std::size_t p = 0;
+ for (std::size_t i = name.size_; i > 0; --i) {
+ if (name.str_[i] == ',' || name.str_[i] == ':') {
+ p = i + 1;
+ break;
+ }
+ }
+ if (p > 0) {
+ name.size_ -= p;
+ name.str_ += p;
+ }
+ if (name.str_[0] == '(' || name.str_[0] == '-' || (name.str_[0] >= '0' && name.str_[0] <= '9')) {
+ name = str_view{};
+ }
+ return name;
+# endif
+}
+#endif
+
+template <typename E, E V>
+constexpr auto enum_name() noexcept {
+ [[maybe_unused]] constexpr auto custom = customize::enum_name<E>(V);
+ static_assert(std::is_same_v<std::decay_t<decltype(custom)>, customize::customize_t>, "magic_enum::customize requires customize_t type.");
+ if constexpr (custom.first == customize::detail::customize_tag::custom_tag) {
+ constexpr auto name = custom.second;
+ static_assert(!name.empty(), "magic_enum::customize requires not empty string.");
+ return static_str<name.size()>{name};
+ } else if constexpr (custom.first == customize::detail::customize_tag::invalid_tag) {
+ return static_str<0>{};
+ } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) {
+#if defined(MAGIC_ENUM_VS_2017_WORKAROUND)
+ constexpr auto name = n<E, V>();
+#else
+ constexpr auto name = n<V>();
+#endif
+ return static_str<name.size_>{name};
+ } else {
+ static_assert(always_false_v<E>, "magic_enum::customize invalid.");
+ }
+}
+
+template <typename E, E V>
+inline constexpr auto enum_name_v = enum_name<E, V>();
+
+template <typename E, auto V>
+constexpr bool is_valid() noexcept {
+#if defined(__clang__) && __clang_major__ >= 16
+ // https://reviews.llvm.org/D130058, https://reviews.llvm.org/D131307
+ constexpr E v = __builtin_bit_cast(E, V);
+#else
+ constexpr E v = static_cast<E>(V);
+#endif
+ [[maybe_unused]] constexpr auto custom = customize::enum_name<E>(v);
+ static_assert(std::is_same_v<std::decay_t<decltype(custom)>, customize::customize_t>, "magic_enum::customize requires customize_t type.");
+ if constexpr (custom.first == customize::detail::customize_tag::custom_tag) {
+ constexpr auto name = custom.second;
+ static_assert(!name.empty(), "magic_enum::customize requires not empty string.");
+ return name.size() != 0;
+ } else if constexpr (custom.first == customize::detail::customize_tag::default_tag) {
+#if defined(MAGIC_ENUM_VS_2017_WORKAROUND)
+ return n<E, v>().size_ != 0;
+#else
+ return n<v>().size_ != 0;
+#endif
+ } else {
+ return false;
+ }
+}
+
+enum class enum_subtype {
+ common,
+ flags
+};
+
+template <typename E, int O, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr U ualue(std::size_t i) noexcept {
+ if constexpr (std::is_same_v<U, bool>) { // bool special case
+ static_assert(O == 0, "magic_enum::detail::ualue requires valid offset.");
+
+ return static_cast<U>(i);
+ } else if constexpr (S == enum_subtype::flags) {
+ return static_cast<U>(U{1} << static_cast<U>(static_cast<int>(i) + O));
+ } else {
+ return static_cast<U>(static_cast<int>(i) + O);
+ }
+}
+
+template <typename E, int O, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr E value(std::size_t i) noexcept {
+ return static_cast<E>(ualue<E, O, S>(i));
+}
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr int reflected_min() noexcept {
+ if constexpr (S == enum_subtype::flags) {
+ return 0;
+ } else {
+ constexpr auto lhs = range_min<E>::value;
+ constexpr auto rhs = (std::numeric_limits<U>::min)();
+
+ if constexpr (cmp_less(rhs, lhs)) {
+ return lhs;
+ } else {
+ return rhs;
+ }
+ }
+}
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr int reflected_max() noexcept {
+ if constexpr (S == enum_subtype::flags) {
+ return std::numeric_limits<U>::digits - 1;
+ } else {
+ constexpr auto lhs = range_max<E>::value;
+ constexpr auto rhs = (std::numeric_limits<U>::max)();
+
+ if constexpr (cmp_less(lhs, rhs)) {
+ return lhs;
+ } else {
+ return rhs;
+ }
+ }
+}
+
+#define MAGIC_ENUM_FOR_EACH_256(T) \
+ T( 0)T( 1)T( 2)T( 3)T( 4)T( 5)T( 6)T( 7)T( 8)T( 9)T( 10)T( 11)T( 12)T( 13)T( 14)T( 15)T( 16)T( 17)T( 18)T( 19)T( 20)T( 21)T( 22)T( 23)T( 24)T( 25)T( 26)T( 27)T( 28)T( 29)T( 30)T( 31) \
+ T( 32)T( 33)T( 34)T( 35)T( 36)T( 37)T( 38)T( 39)T( 40)T( 41)T( 42)T( 43)T( 44)T( 45)T( 46)T( 47)T( 48)T( 49)T( 50)T( 51)T( 52)T( 53)T( 54)T( 55)T( 56)T( 57)T( 58)T( 59)T( 60)T( 61)T( 62)T( 63) \
+ T( 64)T( 65)T( 66)T( 67)T( 68)T( 69)T( 70)T( 71)T( 72)T( 73)T( 74)T( 75)T( 76)T( 77)T( 78)T( 79)T( 80)T( 81)T( 82)T( 83)T( 84)T( 85)T( 86)T( 87)T( 88)T( 89)T( 90)T( 91)T( 92)T( 93)T( 94)T( 95) \
+ T( 96)T( 97)T( 98)T( 99)T(100)T(101)T(102)T(103)T(104)T(105)T(106)T(107)T(108)T(109)T(110)T(111)T(112)T(113)T(114)T(115)T(116)T(117)T(118)T(119)T(120)T(121)T(122)T(123)T(124)T(125)T(126)T(127) \
+ T(128)T(129)T(130)T(131)T(132)T(133)T(134)T(135)T(136)T(137)T(138)T(139)T(140)T(141)T(142)T(143)T(144)T(145)T(146)T(147)T(148)T(149)T(150)T(151)T(152)T(153)T(154)T(155)T(156)T(157)T(158)T(159) \
+ T(160)T(161)T(162)T(163)T(164)T(165)T(166)T(167)T(168)T(169)T(170)T(171)T(172)T(173)T(174)T(175)T(176)T(177)T(178)T(179)T(180)T(181)T(182)T(183)T(184)T(185)T(186)T(187)T(188)T(189)T(190)T(191) \
+ T(192)T(193)T(194)T(195)T(196)T(197)T(198)T(199)T(200)T(201)T(202)T(203)T(204)T(205)T(206)T(207)T(208)T(209)T(210)T(211)T(212)T(213)T(214)T(215)T(216)T(217)T(218)T(219)T(220)T(221)T(222)T(223) \
+ T(224)T(225)T(226)T(227)T(228)T(229)T(230)T(231)T(232)T(233)T(234)T(235)T(236)T(237)T(238)T(239)T(240)T(241)T(242)T(243)T(244)T(245)T(246)T(247)T(248)T(249)T(250)T(251)T(252)T(253)T(254)T(255)
+
+template <typename E, enum_subtype S, std::size_t Size, int Min, std::size_t I>
+constexpr void valid_count(bool* valid, std::size_t& count) noexcept {
+#define MAGIC_ENUM_V(O) \
+ if constexpr ((I + O) < Size) { \
+ if constexpr (is_valid<E, ualue<E, Min, S>(I + O)>()) { \
+ valid[I + O] = true; \
+ ++count; \
+ } \
+ }
+
+ MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_V)
+
+ if constexpr ((I + 256) < Size) {
+ valid_count<E, S, Size, Min, I + 256>(valid, count);
+ }
+#undef MAGIC_ENUM_V
+}
+
+template <std::size_t N>
+struct valid_count_t {
+ std::size_t count = 0;
+ bool valid[N] = {};
+};
+
+template <typename E, enum_subtype S, std::size_t Size, int Min>
+constexpr auto valid_count() noexcept {
+ valid_count_t<Size> vc;
+ valid_count<E, S, Size, Min, 0>(vc.valid, vc.count);
+ return vc;
+}
+
+template <typename E, enum_subtype S, std::size_t Size, int Min>
+constexpr auto values() noexcept {
+ constexpr auto vc = valid_count<E, S, Size, Min>();
+
+ if constexpr (vc.count > 0) {
+#if defined(MAGIC_ENUM_ARRAY_CONSTEXPR)
+ std::array<E, vc.count> values = {};
+#else
+ E values[vc.count] = {};
+#endif
+ for (std::size_t i = 0, v = 0; v < vc.count; ++i) {
+ if (vc.valid[i]) {
+ values[v++] = value<E, Min, S>(i);
+ }
+ }
+#if defined(MAGIC_ENUM_ARRAY_CONSTEXPR)
+ return values;
+#else
+ return to_array(values, std::make_index_sequence<vc.count>{});
+#endif
+ } else {
+ return std::array<E, 0>{};
+ }
+}
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr auto values() noexcept {
+ constexpr auto min = reflected_min<E, S>();
+ constexpr auto max = reflected_max<E, S>();
+ constexpr auto range_size = max - min + 1;
+ static_assert(range_size > 0, "magic_enum::enum_range requires valid size.");
+ static_assert(range_size < (std::numeric_limits<std::uint16_t>::max)(), "magic_enum::enum_range requires valid size.");
+
+ return values<E, S, range_size, min>();
+}
+
+template <typename E, typename U = std::underlying_type_t<E>>
+constexpr enum_subtype subtype(std::true_type) noexcept {
+ if constexpr (std::is_same_v<U, bool>) { // bool special case
+ return enum_subtype::common;
+ } else if constexpr (has_is_flags<E>::value) {
+ return customize::enum_range<E>::is_flags ? enum_subtype::flags : enum_subtype::common;
+ } else {
+#if defined(MAGIC_ENUM_AUTO_IS_FLAGS)
+ constexpr auto flags_values = values<E, enum_subtype::flags>();
+ constexpr auto default_values = values<E, enum_subtype::common>();
+ if (flags_values.size() == 0 || default_values.size() > flags_values.size()) {
+ return enum_subtype::common;
+ }
+ for (std::size_t i = 0; i < default_values.size(); ++i) {
+ const auto v = static_cast<U>(default_values[i]);
+ if (v != 0 && (v & (v - 1)) != 0) {
+ return enum_subtype::common;
+ }
+ }
+ return enum_subtype::flags;
+#else
+ return enum_subtype::common;
+#endif
+ }
+}
+
+template <typename T>
+constexpr enum_subtype subtype(std::false_type) noexcept {
+ // For non-enum type return default common subtype.
+ return enum_subtype::common;
+}
+
+template <typename E, typename D = std::decay_t<E>>
+inline constexpr auto subtype_v = subtype<D>(std::is_enum<D>{});
+
+template <typename E, enum_subtype S>
+inline constexpr auto values_v = values<E, S>();
+
+template <typename E, enum_subtype S, typename D = std::decay_t<E>>
+using values_t = decltype((values_v<D, S>));
+
+template <typename E, enum_subtype S>
+inline constexpr auto count_v = values_v<E, S>.size();
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+inline constexpr auto min_v = (count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.front()) : U{0};
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+inline constexpr auto max_v = (count_v<E, S> > 0) ? static_cast<U>(values_v<E, S>.back()) : U{0};
+
+template <typename E, enum_subtype S, std::size_t... I>
+constexpr auto names(std::index_sequence<I...>) noexcept {
+ constexpr auto names = std::array<string_view, sizeof...(I)>{{enum_name_v<E, values_v<E, S>[I]>...}};
+ return names;
+}
+
+template <typename E, enum_subtype S>
+inline constexpr auto names_v = names<E, S>(std::make_index_sequence<count_v<E, S>>{});
+
+template <typename E, enum_subtype S, typename D = std::decay_t<E>>
+using names_t = decltype((names_v<D, S>));
+
+template <typename E, enum_subtype S, std::size_t... I>
+constexpr auto entries(std::index_sequence<I...>) noexcept {
+ constexpr auto entries = std::array<std::pair<E, string_view>, sizeof...(I)>{{{values_v<E, S>[I], enum_name_v<E, values_v<E, S>[I]>}...}};
+ return entries;
+}
+
+template <typename E, enum_subtype S>
+inline constexpr auto entries_v = entries<E, S>(std::make_index_sequence<count_v<E, S>>{});
+
+template <typename E, enum_subtype S, typename D = std::decay_t<E>>
+using entries_t = decltype((entries_v<D, S>));
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr bool is_sparse() noexcept {
+ if constexpr (count_v<E, S> == 0) {
+ return false;
+ } else if constexpr (std::is_same_v<U, bool>) { // bool special case
+ return false;
+ } else {
+ constexpr auto max = (S == enum_subtype::flags) ? log2(max_v<E, S>) : max_v<E, S>;
+ constexpr auto min = (S == enum_subtype::flags) ? log2(min_v<E, S>) : min_v<E, S>;
+ constexpr auto range_size = max - min + 1;
+
+ return range_size != count_v<E, S>;
+ }
+}
+
+template <typename E, enum_subtype S = subtype_v<E>>
+inline constexpr bool is_sparse_v = is_sparse<E, S>();
+
+template <typename E, enum_subtype S, typename U = std::underlying_type_t<E>>
+constexpr U values_ors() noexcept {
+ static_assert(S == enum_subtype::flags, "magic_enum::detail::values_ors requires valid subtype.");
+
+ auto ors = U{0};
+ for (std::size_t i = 0; i < count_v<E, S>; ++i) {
+ ors |= static_cast<U>(values_v<E, S>[i]);
+ }
+
+ return ors;
+}
+
+template <bool, typename R>
+struct enable_if_enum {};
+
+template <typename R>
+struct enable_if_enum<true, R> {
+ using type = R;
+ static_assert(supported<R>::value, "magic_enum unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility).");
+};
+
+template <typename T, typename R, typename BinaryPredicate = std::equal_to<>, typename D = std::decay_t<T>>
+using enable_if_t = typename enable_if_enum<std::is_enum_v<D> && std::is_invocable_r_v<bool, BinaryPredicate, char_type, char_type>, R>::type;
+
+template <typename T, std::enable_if_t<std::is_enum_v<std::decay_t<T>>, int> = 0>
+using enum_concept = T;
+
+template <typename T, bool = std::is_enum_v<T>>
+struct is_scoped_enum : std::false_type {};
+
+template <typename T>
+struct is_scoped_enum<T, true> : std::bool_constant<!std::is_convertible_v<T, std::underlying_type_t<T>>> {};
+
+template <typename T, bool = std::is_enum_v<T>>
+struct is_unscoped_enum : std::false_type {};
+
+template <typename T>
+struct is_unscoped_enum<T, true> : std::bool_constant<std::is_convertible_v<T, std::underlying_type_t<T>>> {};
+
+template <typename T, bool = std::is_enum_v<std::decay_t<T>>>
+struct underlying_type {};
+
+template <typename T>
+struct underlying_type<T, true> : std::underlying_type<std::decay_t<T>> {};
+
+#if defined(MAGIC_ENUM_ENABLE_HASH) || defined(MAGIC_ENUM_ENABLE_HASH_SWITCH)
+
+template <typename Value, typename = void>
+struct constexpr_hash_t;
+
+template <typename Value>
+struct constexpr_hash_t<Value, std::enable_if_t<is_enum_v<Value>>> {
+ constexpr auto operator()(Value value) const noexcept {
+ using U = typename underlying_type<Value>::type;
+ if constexpr (std::is_same_v<U, bool>) { // bool special case
+ return static_cast<std::size_t>(value);
+ } else {
+ return static_cast<U>(value);
+ }
+ }
+ using secondary_hash = constexpr_hash_t;
+};
+
+template <typename Value>
+struct constexpr_hash_t<Value, std::enable_if_t<std::is_same_v<Value, string_view>>> {
+ static constexpr std::uint32_t crc_table[256] {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
+ 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
+ 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
+ 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
+ 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
+ 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
+ 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
+ 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
+ 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
+ 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
+ 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
+ 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
+ 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
+ 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
+ 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
+ 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
+ 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
+ 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
+ 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
+ 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
+ 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
+ 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
+ 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
+ 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
+ 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
+ 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
+ };
+ constexpr std::uint32_t operator()(string_view value) const noexcept {
+ auto crc = static_cast<std::uint32_t>(0xffffffffL);
+ for (const auto c : value) {
+ crc = (crc >> 8) ^ crc_table[(crc ^ static_cast<std::uint32_t>(c)) & 0xff];
+ }
+ return crc ^ 0xffffffffL;
+ }
+
+ struct secondary_hash {
+ constexpr std::uint32_t operator()(string_view value) const noexcept {
+ auto acc = static_cast<std::uint64_t>(2166136261ULL);
+ for (const auto c : value) {
+ acc = ((acc ^ static_cast<std::uint64_t>(c)) * static_cast<std::uint64_t>(16777619ULL)) & (std::numeric_limits<std::uint32_t>::max)();
+ }
+ return static_cast<std::uint32_t>(acc);
+ }
+ };
+};
+
+template <typename Hash>
+inline constexpr Hash hash_v{};
+
+template <auto* GlobValues, typename Hash>
+constexpr auto calculate_cases(std::size_t Page) noexcept {
+ constexpr std::array values = *GlobValues;
+ constexpr std::size_t size = values.size();
+
+ using switch_t = std::invoke_result_t<Hash, typename decltype(values)::value_type>;
+ static_assert(std::is_integral_v<switch_t> && !std::is_same_v<switch_t, bool>);
+ const std::size_t values_to = (std::min)(static_cast<std::size_t>(256), size - Page);
+
+ std::array<switch_t, 256> result{};
+ auto fill = result.begin();
+ {
+ auto first = values.begin() + static_cast<std::ptrdiff_t>(Page);
+ auto last = values.begin() + static_cast<std::ptrdiff_t>(Page + values_to);
+ while (first != last) {
+ *fill++ = hash_v<Hash>(*first++);
+ }
+ }
+
+ // dead cases, try to avoid case collisions
+ for (switch_t last_value = result[values_to - 1]; fill != result.end() && last_value != (std::numeric_limits<switch_t>::max)(); *fill++ = ++last_value) {
+ }
+
+ {
+ auto it = result.begin();
+ auto last_value = (std::numeric_limits<switch_t>::min)();
+ for (; fill != result.end(); *fill++ = last_value++) {
+ while (last_value == *it) {
+ ++last_value, ++it;
+ }
+ }
+ }
+
+ return result;
+}
+
+template <typename R, typename F, typename... Args>
+constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>) {
+ if constexpr (std::is_void_v<R>) {
+ std::forward<F>(f)(std::forward<Args>(args)...);
+ } else {
+ return static_cast<R>(std::forward<F>(f)(std::forward<Args>(args)...));
+ }
+}
+
+enum class case_call_t {
+ index,
+ value
+};
+
+template <typename T = void>
+inline constexpr auto default_result_type_lambda = []() noexcept(std::is_nothrow_default_constructible_v<T>) { return T{}; };
+
+template <>
+inline constexpr auto default_result_type_lambda<void> = []() noexcept {};
+
+template <auto* Arr, typename Hash>
+constexpr bool has_duplicate() noexcept {
+ using value_t = std::decay_t<decltype((*Arr)[0])>;
+ using hash_value_t = std::invoke_result_t<Hash, value_t>;
+ std::array<hash_value_t, Arr->size()> hashes{};
+ std::size_t size = 0;
+ for (auto elem : *Arr) {
+ hashes[size] = hash_v<Hash>(elem);
+ for (auto i = size++; i > 0; --i) {
+ if (hashes[i] < hashes[i - 1]) {
+ auto tmp = hashes[i];
+ hashes[i] = hashes[i - 1];
+ hashes[i - 1] = tmp;
+ } else if (hashes[i] == hashes[i - 1]) {
+ return false;
+ } else {
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+#define MAGIC_ENUM_CASE(val) \
+ case cases[val]: \
+ if constexpr ((val) + Page < size) { \
+ if (!pred(values[val + Page], searched)) { \
+ break; \
+ } \
+ if constexpr (CallValue == case_call_t::index) { \
+ if constexpr (std::is_invocable_r_v<result_t, Lambda, std::integral_constant<std::size_t, val + Page>>) { \
+ return detail::invoke_r<result_t>(std::forward<Lambda>(lambda), std::integral_constant<std::size_t, val + Page>{}); \
+ } else if constexpr (std::is_invocable_v<Lambda, std::integral_constant<std::size_t, val + Page>>) { \
+ MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
+ } \
+ } else if constexpr (CallValue == case_call_t::value) { \
+ if constexpr (std::is_invocable_r_v<result_t, Lambda, enum_constant<values[val + Page]>>) { \
+ return detail::invoke_r<result_t>(std::forward<Lambda>(lambda), enum_constant<values[val + Page]>{}); \
+ } else if constexpr (std::is_invocable_r_v<result_t, Lambda, enum_constant<values[val + Page]>>) { \
+ MAGIC_ENUM_ASSERT(false && "magic_enum::detail::constexpr_switch wrong result type."); \
+ } \
+ } \
+ break; \
+ } else [[fallthrough]];
+
+template <auto* GlobValues,
+ case_call_t CallValue,
+ std::size_t Page = 0,
+ typename Hash = constexpr_hash_t<typename std::decay_t<decltype(*GlobValues)>::value_type>,
+ typename BinaryPredicate = std::equal_to<>,
+ typename Lambda,
+ typename ResultGetterType>
+constexpr decltype(auto) constexpr_switch(
+ Lambda&& lambda,
+ typename std::decay_t<decltype(*GlobValues)>::value_type searched,
+ ResultGetterType&& def,
+ BinaryPredicate&& pred = {}) {
+ using result_t = std::invoke_result_t<ResultGetterType>;
+ using hash_t = std::conditional_t<has_duplicate<GlobValues, Hash>(), Hash, typename Hash::secondary_hash>;
+ static_assert(has_duplicate<GlobValues, hash_t>(), "magic_enum::detail::constexpr_switch duplicated hash found, please report it: https://github.com/Neargye/magic_enum/issues.");
+ constexpr std::array values = *GlobValues;
+ constexpr std::size_t size = values.size();
+ constexpr std::array cases = calculate_cases<GlobValues, hash_t>(Page);
+
+ switch (hash_v<hash_t>(searched)) {
+ MAGIC_ENUM_FOR_EACH_256(MAGIC_ENUM_CASE)
+ default:
+ if constexpr (size > 256 + Page) {
+ return constexpr_switch<GlobValues, CallValue, Page + 256, Hash>(std::forward<Lambda>(lambda), searched, std::forward<ResultGetterType>(def));
+ }
+ break;
+ }
+ return def();
+}
+
+#undef MAGIC_ENUM_CASE
+
+#endif
+
+} // namespace magic_enum::detail
+
+// Checks is magic_enum supported compiler.
+inline constexpr bool is_magic_enum_supported = detail::supported<void>::value;
+
+template <typename T>
+using Enum = detail::enum_concept<T>;
+
+// Checks whether T is an Unscoped enumeration type.
+// Provides the member constant value which is equal to true, if T is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration) type. Otherwise, value is equal to false.
+template <typename T>
+struct is_unscoped_enum : detail::is_unscoped_enum<T> {};
+
+template <typename T>
+inline constexpr bool is_unscoped_enum_v = is_unscoped_enum<T>::value;
+
+// Checks whether T is an Scoped enumeration type.
+// Provides the member constant value which is equal to true, if T is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) type. Otherwise, value is equal to false.
+template <typename T>
+struct is_scoped_enum : detail::is_scoped_enum<T> {};
+
+template <typename T>
+inline constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value;
+
+// If T is a complete enumeration type, provides a member typedef type that names the underlying type of T.
+// Otherwise, if T is not an enumeration type, there is no member type. Otherwise (T is an incomplete enumeration type), the program is ill-formed.
+template <typename T>
+struct underlying_type : detail::underlying_type<T> {};
+
+template <typename T>
+using underlying_type_t = typename underlying_type<T>::type;
+
+template <auto V>
+using enum_constant = detail::enum_constant<V>;
+
+// Returns type name of enum.
+template <typename E>
+[[nodiscard]] constexpr auto enum_type_name() noexcept -> detail::enable_if_t<E, string_view> {
+ constexpr string_view name = detail::type_name_v<std::decay_t<E>>;
+ static_assert(!name.empty(), "magic_enum::enum_type_name enum type does not have a name.");
+
+ return name;
+}
+
+// Returns number of enum values.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_count() noexcept -> detail::enable_if_t<E, std::size_t> {
+ return detail::count_v<std::decay_t<E>, S>;
+}
+
+// Returns enum value at specified index.
+// No bounds checking is performed: the behavior is undefined if index >= number of enum values.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_value(std::size_t index) noexcept -> detail::enable_if_t<E, std::decay_t<E>> {
+ using D = std::decay_t<E>;
+
+ if constexpr (detail::is_sparse_v<D, S>) {
+ return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::values_v<D, S>[index];
+ } else {
+ constexpr auto min = (S == detail::enum_subtype::flags) ? detail::log2(detail::min_v<D, S>) : detail::min_v<D, S>;
+
+ return MAGIC_ENUM_ASSERT(index < detail::count_v<D, S>), detail::value<D, min, S>(index);
+ }
+}
+
+// Returns enum value at specified index.
+template <typename E, std::size_t I, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_value() noexcept -> detail::enable_if_t<E, std::decay_t<E>> {
+ using D = std::decay_t<E>;
+ static_assert(I < detail::count_v<D, S>, "magic_enum::enum_value out of range.");
+
+ return enum_value<D, S>(I);
+}
+
+// Returns std::array with enum values, sorted by enum value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_values() noexcept -> detail::enable_if_t<E, detail::values_t<E, S>> {
+ return detail::values_v<std::decay_t<E>, S>;
+}
+
+// Returns integer value from enum value.
+template <typename E>
+[[nodiscard]] constexpr auto enum_integer(E value) noexcept -> detail::enable_if_t<E, underlying_type_t<E>> {
+ return static_cast<underlying_type_t<E>>(value);
+}
+
+// Returns underlying value from enum value.
+template <typename E>
+[[nodiscard]] constexpr auto enum_underlying(E value) noexcept -> detail::enable_if_t<E, underlying_type_t<E>> {
+ return static_cast<underlying_type_t<E>>(value);
+}
+
+// Obtains index in enum values from enum value.
+// Returns optional with index.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
+ using D = std::decay_t<E>;
+ using U = underlying_type_t<D>;
+
+ if constexpr (detail::count_v<D, S> == 0) {
+ static_cast<void>(value);
+ return {}; // Empty enum.
+ } else if constexpr (detail::is_sparse_v<D, S> || (S == detail::enum_subtype::flags)) {
+#if defined(MAGIC_ENUM_ENABLE_HASH)
+ return detail::constexpr_switch<&detail::values_v<D, S>, detail::case_call_t::index>(
+ [](std::size_t i) { return optional<std::size_t>{i}; },
+ value,
+ detail::default_result_type_lambda<optional<std::size_t>>);
+#else
+ for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
+ if (enum_value<D, S>(i) == value) {
+ return i;
+ }
+ }
+ return {}; // Invalid value or out of range.
+#endif
+ } else {
+ const auto v = static_cast<U>(value);
+ if (v >= detail::min_v<D, S> && v <= detail::max_v<D, S>) {
+ return static_cast<std::size_t>(v - detail::min_v<D, S>);
+ }
+ return {}; // Invalid value or out of range.
+ }
+}
+
+// Obtains index in enum values from enum value.
+// Returns optional with index.
+template <detail::enum_subtype S, typename E>
+[[nodiscard]] constexpr auto enum_index(E value) noexcept -> detail::enable_if_t<E, optional<std::size_t>> {
+ using D = std::decay_t<E>;
+
+ return enum_index<D, S>(value);
+}
+
+// Obtains index in enum values from static storage enum variable.
+template <auto V, detail::enum_subtype S = detail::subtype_v<std::decay_t<decltype(V)>>>
+[[nodiscard]] constexpr auto enum_index() noexcept -> detail::enable_if_t<decltype(V), std::size_t> {
+ constexpr auto index = enum_index<std::decay_t<decltype(V)>, S>(V);
+ static_assert(index, "magic_enum::enum_index enum value does not have a index.");
+
+ return *index;
+}
+
+// Returns name from static storage enum variable.
+// This version is much lighter on the compile times and is not restricted to the enum_range limitation.
+template <auto V>
+[[nodiscard]] constexpr auto enum_name() noexcept -> detail::enable_if_t<decltype(V), string_view> {
+ constexpr string_view name = detail::enum_name_v<std::decay_t<decltype(V)>, V>;
+ static_assert(!name.empty(), "magic_enum::enum_name enum value does not have a name.");
+
+ return name;
+}
+
+// Returns name from enum value.
+// If enum value does not have name or value out of range, returns empty string.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_name(E value) noexcept -> detail::enable_if_t<E, string_view> {
+ using D = std::decay_t<E>;
+
+ if (const auto i = enum_index<D, S>(value)) {
+ return detail::names_v<D, S>[*i];
+ }
+ return {};
+}
+
+// Returns name from enum value.
+// If enum value does not have name or value out of range, returns empty string.
+template <detail::enum_subtype S, typename E>
+[[nodiscard]] constexpr auto enum_name(E value) -> detail::enable_if_t<E, string_view> {
+ using D = std::decay_t<E>;
+
+ return enum_name<D, S>(value);
+}
+
+// Returns std::array with names, sorted by enum value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_names() noexcept -> detail::enable_if_t<E, detail::names_t<E, S>> {
+ return detail::names_v<std::decay_t<E>, S>;
+}
+
+// Returns std::array with pairs (value, name), sorted by enum value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_entries() noexcept -> detail::enable_if_t<E, detail::entries_t<E, S>> {
+ return detail::entries_v<std::decay_t<E>, S>;
+}
+
+// Allows you to write magic_enum::enum_cast<foo>("bar", magic_enum::case_insensitive);
+inline constexpr auto case_insensitive = detail::case_insensitive<>{};
+
+// Obtains enum value from integer value.
+// Returns optional with enum value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_cast(underlying_type_t<E> value) noexcept -> detail::enable_if_t<E, optional<std::decay_t<E>>> {
+ using D = std::decay_t<E>;
+
+ if constexpr (detail::count_v<D, S> == 0) {
+ static_cast<void>(value);
+ return {}; // Empty enum.
+ } else {
+ if constexpr (detail::is_sparse_v<D, S> || (S == detail::enum_subtype::flags)) {
+#if defined(MAGIC_ENUM_ENABLE_HASH)
+ return detail::constexpr_switch<&detail::values_v<D, S>, detail::case_call_t::value>(
+ [](D v) { return optional<D>{v}; },
+ static_cast<D>(value),
+ detail::default_result_type_lambda<optional<D>>);
+#else
+ for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
+ if (value == static_cast<underlying_type_t<D>>(enum_value<D, S>(i))) {
+ return static_cast<D>(value);
+ }
+ }
+ return {}; // Invalid value or out of range.
+#endif
+ } else {
+ if (value >= detail::min_v<D, S> && value <= detail::max_v<D, S>) {
+ return static_cast<D>(value);
+ }
+ return {}; // Invalid value or out of range.
+ }
+ }
+}
+
+// Obtains enum value from name.
+// Returns optional with enum value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>, typename BinaryPredicate = std::equal_to<>>
+[[nodiscard]] constexpr auto enum_cast(string_view value, [[maybe_unused]] BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable<BinaryPredicate>()) -> detail::enable_if_t<E, optional<std::decay_t<E>>, BinaryPredicate> {
+ using D = std::decay_t<E>;
+
+ if constexpr (detail::count_v<D, S> == 0) {
+ static_cast<void>(value);
+ return {}; // Empty enum.
+#if defined(MAGIC_ENUM_ENABLE_HASH)
+ } else if constexpr (detail::is_default_predicate<BinaryPredicate>()) {
+ return detail::constexpr_switch<&detail::names_v<D, S>, detail::case_call_t::index>(
+ [](std::size_t i) { return optional<D>{detail::values_v<D, S>[i]}; },
+ value,
+ detail::default_result_type_lambda<optional<D>>,
+ [&p](string_view lhs, string_view rhs) { return detail::cmp_equal(lhs, rhs, p); });
+#endif
+ } else {
+ for (std::size_t i = 0; i < detail::count_v<D, S>; ++i) {
+ if (detail::cmp_equal(value, detail::names_v<D, S>[i], p)) {
+ return enum_value<D, S>(i);
+ }
+ }
+ return {}; // Invalid value or out of range.
+ }
+}
+
+// Checks whether enum contains value with such value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_t<E, bool> {
+ using D = std::decay_t<E>;
+ using U = underlying_type_t<D>;
+
+ return static_cast<bool>(enum_cast<D, S>(static_cast<U>(value)));
+}
+
+// Checks whether enum contains value with such value.
+template <detail::enum_subtype S, typename E>
+[[nodiscard]] constexpr auto enum_contains(E value) noexcept -> detail::enable_if_t<E, bool> {
+ using D = std::decay_t<E>;
+ using U = underlying_type_t<D>;
+
+ return static_cast<bool>(enum_cast<D, S>(static_cast<U>(value)));
+}
+
+// Checks whether enum contains value with such integer value.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>>
+[[nodiscard]] constexpr auto enum_contains(underlying_type_t<E> value) noexcept -> detail::enable_if_t<E, bool> {
+ using D = std::decay_t<E>;
+
+ return static_cast<bool>(enum_cast<D, S>(value));
+}
+
+// Checks whether enum contains enumerator with such name.
+template <typename E, detail::enum_subtype S = detail::subtype_v<E>, typename BinaryPredicate = std::equal_to<>>
+[[nodiscard]] constexpr auto enum_contains(string_view value, BinaryPredicate p = {}) noexcept(detail::is_nothrow_invocable<BinaryPredicate>()) -> detail::enable_if_t<E, bool, BinaryPredicate> {
+ using D = std::decay_t<E>;
+
+ return static_cast<bool>(enum_cast<D, S>(value, std::move(p)));
+}
+
+template <bool AsFlags = true>
+inline constexpr auto as_flags = AsFlags ? detail::enum_subtype::flags : detail::enum_subtype::common;
+
+template <bool AsFlags = true>
+inline constexpr auto as_common = AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags;
+
+namespace bitwise_operators {
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E operator~(E rhs) noexcept {
+ return static_cast<E>(~static_cast<underlying_type_t<E>>(rhs));
+}
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E operator|(E lhs, E rhs) noexcept {
+ return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) | static_cast<underlying_type_t<E>>(rhs));
+}
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E operator&(E lhs, E rhs) noexcept {
+ return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) & static_cast<underlying_type_t<E>>(rhs));
+}
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E operator^(E lhs, E rhs) noexcept {
+ return static_cast<E>(static_cast<underlying_type_t<E>>(lhs) ^ static_cast<underlying_type_t<E>>(rhs));
+}
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E& operator|=(E& lhs, E rhs) noexcept {
+ return lhs = (lhs | rhs);
+}
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E& operator&=(E& lhs, E rhs) noexcept {
+ return lhs = (lhs & rhs);
+}
+
+template <typename E, detail::enable_if_t<E, int> = 0>
+constexpr E& operator^=(E& lhs, E rhs) noexcept {
+ return lhs = (lhs ^ rhs);
+}
+
+} // namespace magic_enum::bitwise_operators
+
+} // namespace magic_enum
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# pragma GCC diagnostic pop
+#elif defined(_MSC_VER)
+# pragma warning(pop)
+#endif
+
+#undef MAGIC_ENUM_GET_ENUM_NAME_BUILTIN
+#undef MAGIC_ENUM_GET_TYPE_NAME_BUILTIN
+#undef MAGIC_ENUM_VS_2017_WORKAROUND
+#undef MAGIC_ENUM_ARRAY_CONSTEXPR
+#undef MAGIC_ENUM_FOR_EACH_256
+
+#endif // NEARGYE_MAGIC_ENUM_HPP
default_options : ['b_pie=true', 'cpp_std=c++17']
)
+# Here we read variables from platform-specific meson file
+subdir('platform')
+
mmi_version = meson.project_version().split('.')
mmi_prefix = get_option('prefix')
mmi_prefix_bindir = join_paths(mmi_prefix, get_option('bindir'))
mmi_prefix_plugindir = join_paths(mmi_prefix, get_option('datadir'), 'mmi', 'plugins')
mmi_prefix_scriptdir = join_paths(mmi_prefix, get_option('datadir'), 'mmi', 'scripts')
+mmi_extra_flags = ''.join(['-DMMI_INSTALL_PREFIX="', mmi_prefix, '"'])
+add_global_arguments(mmi_extra_flags, language : ['c', 'cpp'])
+
pkgconfig = import('pkgconfig')
subdir('capi')
subdir('src')
-subdir('plugins')
subdir('tests')
+subdir('plugins')
+
+foreach platform_specific_sub_directory : mmi_platform_specific_sub_directories
+ message('Platform Specific Sub Directory : ' + platform_specific_sub_directory)
+ subdir(platform_specific_sub_directory)
+endforeach
--- /dev/null
+option('platform_option', type : 'string', value : 'linux', description : 'An option for specifying target platform')
-%define USE_GCOV 0
-
Name: mmi
Version: 2.0.1
Release: 0
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(rpc-port)
BuildRequires: pkgconfig(ecore)
-BuildRequires: pkgconfig(capi-media-audio-io)
-BuildRequires: pkgconfig(capi-media-sound-manager)
-BuildRequires: pkgconfig(capi-media-camera)
-BuildRequires: pkgconfig(libaurum)
BuildRequires: pkgconfig(vconf)
-BuildRequires: pkgconfig(json-glib-1.0)
-BuildRequires: pkgconfig(capi-media-vision)
-BuildRequires: pkgconfig(capi-media-image-util)
-BuildRequires: pkgconfig(opencv)
+BuildRequires: pkgconfig(libxml-2.0)
+
#Build dependencies for tests
BuildRequires: pkgconfig(gmock)
+%if 0%{?gcov:1}
+BuildRequires: lcov
+BuildRequires: zip
+%endif
+
%description
MMI(Multi-modal Interaction) Framework
%description devel
Development package for MMI Framework
+%if 0%{?gcov:1}
+%package gcov
+Summary: MMI Framework (gcov)
+%description gcov
+MMI Framework gcov objects
+%endif
+
%package tests
Summary: Testcases for MMI Framework
Group: System/Libraries
mv mmi_stub.* src/mmi-manager
%build
-%if "%{USE_GCOV}" == "1"
+%if 0%{?gcov:1}
CFLAGS+=" -fprofile-arcs -ftest-coverage -DTIZEN_TEST_GCOV"
CXXFLAGS+=" -fprofile-arcs -ftest-coverage -DTIZEN_TEST_GCOV"
LDFLAGS+=" -lgcov"
--libdir %{_libdir} \
--datadir %{_datadir} \
builddir
+meson configure -Dplatform_option=tizen builddir
ninja -C builddir all
%install
DESTDIR=%{buildroot} ninja -C builddir install
+%if 0%{?gcov:1}
+builddir=$(basename $PWD)
+gcno_obj_dir=%{buildroot}%{_datadir}/gcov/obj/%{name}/"$builddir"
+mkdir -p "$gcno_obj_dir"
+find ./builddir/tests/ -name '*.gcno' -exec rm {} \;
+find ./builddir/plugins/ -name '*.gcno' -exec rm {} \;
+find ./builddir/src/mmi-cli/ -name '*.gcno' -exec rm {} \;
+find . -name '*proxy*.gcno' -exec rm {} \;
+find . -name '*_stub*.gcno' -exec rm {} \;
+find . -name '*tidl*.gcno' -exec rm {} \;
+find . -name '*-port-instance*.gcno' -exec rm {} \;
+find . -name 'mmi-data-gateway*.gcno' -exec rm {} \;
+find . -name 'mmi-node-controller*.gcno' -exec rm {} \;
+find . -name 'mmi-signal*.gcno' -exec rm {} \;
+find . -name 'mmi-workflow-script*.gcno' -exec rm {} \;
+find . -name 'mmi-plugin*.gcno' -exec rm {} \;
+find . -name 'mmi-workflow-output-event*.gcno' -exec rm {} \;
+find ./builddir/meson-private/ -name '*.gcno' -exec rm {} \;
+find . -name '*.gcno' -exec cp --parents '{}' "$gcno_obj_dir" ';'
+%endif
+
%check
%if "%{_mmi_test_enable}" == "true"
ninja -C builddir test
+%if 0%{?gcov:1}
+lcov -c --ignore-errors graph --no-external -q -d . -o gcov.info
+genhtml gcov.info
+%endif
%endif
-%post -p /sbin/ldconfig
+%post
+/sbin/ldconfig
+echo %{_bindir}/mmi-manager
+chsmack -e "System" %{_bindir}/mmi-manager
+
%postun -p /sbin/ldconfig
%files
%license COPYING
%{_datadir}/mmi/plugins/*.so*
%{_datadir}/mmi/scripts/*.mws
-%{_datadir}/face_recognition/*
%files cli
%manifest %{name}.manifest
%license COPYING
%{_bindir}/mmi-cli
%{_bindir}/mmi-cli-node-tester
+#%{TZ_SYS_RO_SHARE}/mmi/configs/mmi-config.xml
%files devel
%manifest %{name}.manifest
%{_includedir}/mmi*.h
%{_libdir}/pkgconfig/*
+%if 0%{?gcov:1}
+%files gcov
+%{_datadir}/gcov/obj/*
+%endif
+
%files tests
%defattr(-,root,root,-)
%license COPYING
%{_bindir}/mmi-tests
%{_bindir}/mmi-manager-tests
-
--- /dev/null
+mmi_platform = 'linux'
+
+mmi_platform_specific_dependencies = ['ecore-ipc']
+mmi_platform_specific_client_files = ['mmi-ipc-ecore.cpp']
+mmi_platform_specific_manager_files = ['mmi-ipc-ecore.cpp']
+mmi_platform_specific_sub_directories = []
+mmi_platform_specific_include_directory = 'platform/linux'
+
+install_headers(
+ 'mmi-platform-config.h'
+ )
--- /dev/null
+#pragma once
+
+#include <memory.h>
+#include <stdio.h>
+
+#define EXPORT_API
+static char *get_error_message(int err) { return "Unknown"; }
+
+#define MMI_DEFAULT_CONFIG "/usr/local/mmi/configs/mmi-config.xml"
+
+#define MMI_LOG(fmt, ...) \
+ do { \
+ printf("%s: %s(%d) > " fmt "\n", \
+ strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__, \
+ __func__, __LINE__, \
+ ##__VA_ARGS__); \
+ } \
+ while (0);
+
+#ifndef _E
+#define _E LOGE
+#endif
+
+#ifndef _D
+#define _D LOGD
+#endif
+
+#ifndef _I
+#define _I LOGI
+#endif
+
+#ifndef _W
+#define _W LOGW
+#endif
+
+#ifndef LOGE
+#define LOGE MMI_LOG
+#endif
+
+#ifndef LOGD
+#define LOGD MMI_LOG
+#endif
+
+#ifndef LOGI
+#define LOGI MMI_LOG
+#endif
+
+#ifndef LOGW
+#define LOGW MMI_LOG
+#endif
+
+#define PLATFORM_ERROR_MMI -0x030F0000
+
+#define PLATFORM_ERROR_NONE (0)
+#define PLATFORM_ERROR_OUT_OF_MEMORY (-1)
+#define PLATFORM_ERROR_IO_ERROR (-2)
+#define PLATFORM_ERROR_INVALID_PARAMETER (-3)
+#define PLATFORM_ERROR_OUT_OF_NETWORK (-4)
+#define PLATFORM_ERROR_TIMED_OUT (-5)
+#define PLATFORM_ERROR_PERMISSION_DENIED (-6)
+#define PLATFORM_ERROR_NOT_SUPPORTED (-7)
+#define PLATFORM_ERROR_OPERATION_FAILED (-8)
+#define PLATFORM_ERROR_RESOURCE_BUSY (-9)
--- /dev/null
+mmi_platform_option = get_option('platform_option')
+subdir(mmi_platform_option)
--- /dev/null
+mmi_platform = 'tizen'
+
+mmi_platform_specific_dependencies = ['bundle', 'rpc-port', 'dlog', 'libtzplatform-config']
+mmi_platform_specific_client_files = ['mmi_proxy.c', 'mmi-ipc-tidl.cpp']
+mmi_platform_specific_manager_files = ['mmi_stub.c', 'mmi-ipc-tidl.cpp']
+mmi_platform_specific_sub_directories = []
+mmi_platform_specific_include_directory = 'platform/tizen'
+
+install_headers(
+ 'mmi-platform-config.h'
+ )
--- /dev/null
+#pragma once
+
+#include <tizen.h>
+#include <dlog.h>
+#include <bundle.h>
+#include <tzplatform_config.h>
+
+#define MMI_DEFAULT_CONFIG tzplatform_mkpath(tzplatform_getid("TZ_SYS_RO_SHARE"), "/mmi/configs/mmi-config.xml")
+
+#define TIZEN_ERROR_MMI -0x030F0000
+
+#define PLATFORM_ERROR_NONE (TIZEN_ERROR_NONE)
+#define PLATFORM_ERROR_OUT_OF_MEMORY (TIZEN_ERROR_OUT_OF_MEMORY)
+#define PLATFORM_ERROR_IO_ERROR (TIZEN_ERROR_IO_ERROR)
+#define PLATFORM_ERROR_INVALID_PARAMETER (TIZEN_ERROR_INVALID_PARAMETER)
+#define PLATFORM_ERROR_OUT_OF_NETWORK (TIZEN_ERROR_NETWORK_DOWN)
+#define PLATFORM_ERROR_TIMED_OUT (TIZEN_ERROR_TIMED_OUT)
+#define PLATFORM_ERROR_PERMISSION_DENIED (TIZEN_ERROR_PERMISSION_DENIED)
+#define PLATFORM_ERROR_NOT_SUPPORTED (TIZEN_ERROR_NOT_SUPPORTED)
+#define PLATFORM_ERROR_OPERATION_FAILED (TIZEN_ERROR_MMI | 0x01)
+#define PLATFORM_ERROR_RESOURCE_BUSY (TIZEN_ERROR_MMI | 0x02)
+
+#ifndef _E
+#define _E LOGE
+#endif
+
+#ifndef _D
+#define _D LOGD
+#endif
+
+#ifndef _I
+#define _I LOGI
+#endif
+
+#ifndef _W
+#define _W LOGW
+#endif
+
-subdir('nodes')
subdir('workflows')
+++ /dev/null
-mmi_module_camera_library_srcs = [
- 'mmi-module-camera.cpp',
- 'mmi-module-camera-preview.cpp',
- 'mmi-module-camera-preview.h',
- ]
-
-dlog_dep = dependency('dlog', method : 'pkg-config')
-camera_dep = dependency('capi-media-camera', method : 'pkg-config')
-
-mmi_module_camera_deps = [
- mmi_declared_dep,
- dlog_dep,
- camera_dep,
- ]
-
-mmi_module_camera_include_dirs = include_directories(
- '.',
- '../../../capi/',
- )
-
-mmi_module_camera_library = library('mmi_module_camera',
- mmi_module_camera_library_srcs,
- include_directories : [ mmi_module_camera_include_dirs ],
- dependencies : [mmi_module_camera_deps],
- install_dir : mmi_prefix_plugindir,
- install : true
- )
+++ /dev/null
-/*
- * Copyright (c) 2023 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 <mmi-node.h>
-#include "mmi-module-camera-preview.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-CAMERA"
-
-int Camera::frame_num = 0;
-
-Camera::Camera()
-{
-}
-
-Camera::~Camera()
-{
-}
-
-int Camera::initialize()
-{
- if (CAMERA_ERROR_NONE != camera_create(CAMERA_DEVICE_CAMERA0, &m_camera)) {
- _E("[Camera] Fail to create camera");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- if (CAMERA_ERROR_NONE != camera_set_display(m_camera, CAMERA_DISPLAY_TYPE_NONE, NULL)){
- _E("[Camera] Fail to set display");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- camera_set_preview_format(m_camera, CAMERA_PIXEL_FORMAT_I420);
- camera_set_preview_resolution(m_camera, 640, 480);
- camera_attr_set_preview_fps(m_camera, CAMERA_ATTR_FPS_15);
- camera_set_state_changed_cb(m_camera, _camera_state_changed_cb, this);
- camera_set_preview_cb(m_camera, _camera_preview_cb, this);
-
- return MMI_ERROR_NONE;
-}
-
-int Camera::deinitialize()
-{
-
- camera_unset_preview_cb(m_camera);
-
- if (CAMERA_ERROR_NONE != camera_destroy(m_camera)) {
- _E("[Camera] Fail to distroy camera");
- return MMI_ERROR_OPERATION_FAILED;
- }
- return MMI_ERROR_NONE;
-}
-
-int Camera::start()
-{
- int width = 0;
- int height = 0;
- camera_attr_fps_e fps;
-
- _D("Camera::start()");
-
- if (CAMERA_ERROR_NONE != camera_start_preview(m_camera)) {
- _E("[Camera] Fail to start preview");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- camera_attr_get_preview_fps(m_camera, &fps);
- camera_get_preview_resolution(m_camera, &width, &height);
-
- _I("camera info -> fps :%d, width : %d, height : %d", fps, width, height);
-
- return MMI_ERROR_NONE;
-}
-
-int Camera::stop()
-{
- _D("Camera::stop()");
-
- if (CAMERA_ERROR_NONE != camera_stop_preview(m_camera)) {
- _E("[Camera] Fail to stop preview");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- return MMI_ERROR_NONE;
-}
-
-void Camera::set_preview_callback(camera_data_callback callback)
-{
- m_camera_callback = callback;
-}
-
-void Camera::set_node_instance(mmi_node_instance_h node_instance)
-{
- m_node_instance = node_instance;
-}
-
-void Camera::_camera_preview_cb(camera_preview_data_s *frame, void *user_data)
-{
- int size = 0;
- unsigned long timestamp = 0;
- unsigned char *pData = nullptr;
-
- Camera *camera = static_cast<Camera *>(user_data);
- camera_attr_get_preview_frame_timestamp(camera->m_camera, ×tamp);
-
- switch (frame->format) {
- case CAMERA_PIXEL_FORMAT_NV12:
- _D("NV12 p[%p,%p], size[%u,%u]", frame->data.double_plane.y, frame->data.double_plane.uv,
- frame->data.double_plane.y_size, frame->data.double_plane.uv_size);
- pData = frame->data.double_plane.y;
- size = frame->data.double_plane.y_size + frame->data.double_plane.uv_size;
-
- break;
- case CAMERA_PIXEL_FORMAT_I420:
- _D("I420 p[%p,%p,%p], size[%u,%u,%u]", frame->data.triple_plane.y, frame->data.triple_plane.u, frame->data.triple_plane.v,
- frame->data.triple_plane.y_size, frame->data.triple_plane.u_size, frame->data.triple_plane.v_size);
- pData = frame->data.triple_plane.y;
- size = frame->data.triple_plane.y_size + frame->data.triple_plane.u_size + frame->data.triple_plane.v_size;
-
- break;
- default:
- _E("invalid format : %u", frame->format);
- break;
-
- }
- Camera::frame_num++;
-
- if (camera->m_camera_callback && (Camera::frame_num % 3 == 0) && pData) {
- camera->m_camera_callback(pData, size, timestamp, camera->m_node_instance);
- }
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2023 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.
- *
- */
-
-#pragma once
-
-#include <mmi-log.h>
-#include <functional>
-
-#include <mmi-node.h>
-#include <camera_internal.h>
-
-using camera_data_callback = std::function<void(void *, size_t, unsigned long, void *)>;
-
-class Camera {
-public:
- static int frame_num;
-
- Camera();
- ~Camera();
-
- int initialize();
- int deinitialize();
- int start();
- int stop();
-
- void set_preview_callback(camera_data_callback callback);
- void set_node_instance(mmi_node_instance_h node_instance);
-
- static void _camera_state_changed_cb(camera_state_e previous, camera_state_e current, bool by_policy, void *user_data)
- {
- _D("camera state changed %d -> %d", previous, current);
- }
-
- static void _camera_interrupted_cb(camera_policy_e policy, camera_state_e previous, camera_state_e current,
- void *user_data)
- {
- _D("camera interrupted callback called[state %d -> %d, policy %d]", previous, current, policy);
- }
-
-private:
- camera_h m_camera{nullptr};
- camera_data_callback m_camera_callback{nullptr};
- mmi_node_instance_h m_node_instance{nullptr};
- static void _camera_preview_cb(camera_preview_data_s *frame, void *user_data);
-};
+++ /dev/null
-#include <mmi.h>
-#include <mmi-plugin-storage.h>
-#include <mmi-node.h>
-#include <mmi-log.h>
-
-#include <string>
-#include <map>
-#include <camera_internal.h>
-#include "mmi-module-camera-preview.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-CAMERA"
-
-static std::map<mmi_node_instance_h, Camera *> g_camera_map;
-
-void feed_preview_callback(void *data, size_t size, unsigned long timestamp, void *user_data)
-{
- mmi_node_instance_h instance = (mmi_node_instance_h)user_data;
- mmi_port_instance_h port_instance = nullptr;
- mmi_data_h output_data = nullptr;
-
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, "VIDEO", &port_instance);
- mmi_data_create_video(data, size, &output_data);
- mmi_port_instance_generate_output(port_instance, output_data);
- mmi_data_destroy(output_data);
- _D("frame num : %d, timestamp : %lu", Camera::frame_num, timestamp);
-}
-
-static int node_initialized_cb(mmi_node_instance_h instance)
-{
- _D("[Camera] Node initialize callback is called for %p", instance);
-
- if (nullptr == instance) {
- _E("[Camera] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
- Camera *camera = new(std::nothrow) Camera();
- if (nullptr == camera) {
- _E("[ERROR] Failed to create instance");
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- camera->initialize();
- camera->set_node_instance(instance);
- camera->set_preview_callback(feed_preview_callback);
- g_camera_map.insert(std::pair<mmi_node_instance_h, Camera *>(instance, camera));
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deinitialized_cb(mmi_node_instance_h instance)
-{
- _D("[Camera] Node deinitialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[Camera] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- Camera *camera = g_camera_map[instance];
- camera->deinitialize();
- g_camera_map.erase(instance);
- delete camera;
- } catch (std::out_of_range &e) {
- _E("[Camera] failed to find recorder instance");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_attribute_set_cb(mmi_node_instance_h instance, mmi_attribute_h attribute)
-{
- _D("Node attribute set callback is called for %p", instance);
-
- if (nullptr == instance) {
- _E("[CAMERA] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- if (nullptr == attribute) {
- _E("[Camera] attribute is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- // TODO: set attribute "UNFOCUSED_ONLY"
-
- return MMI_ERROR_NONE;
-}
-
-static int node_activated_cb(mmi_node_instance_h instance)
-{
- _D("[Camera] Node activate callback is called for %p", instance);
-
- if (nullptr == instance) {
- _E("[Camera] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- Camera *camera = g_camera_map[instance];
- camera->start();
- } catch (std::out_of_range &e) {
- _E("[Camera] failed to find recorder instance");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deactivated_cb(mmi_node_instance_h instance)
-{
- _D("[Camera] Node deactivate callback is called for %p", instance);
-
- if (nullptr == instance) {
- _E("[Camera] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- Camera *camera = g_camera_map[instance];
- camera->stop();
- } catch (std::out_of_range &e) {
- _E("[Camera] failed to find recorder instance");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_signal_received_cb(mmi_node_instance_h instance, mmi_signal_h signal)
-{
- _D("Node signal received callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-static int port_output_format_requested_cb(mmi_port_instance_h instance, const char *format) {
- _D("Port output format request callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-// TODO: It must be determined how to receive input data from the client
-static int port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data) {
- _D("Port input data callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-extern "C" {
-
- EXPORT_API void mmi_plugin_module_get_node_list()
- {
- mmi_node_callbacks node_callbacks {
- node_initialized_cb,
- node_deinitialized_cb,
- node_attribute_set_cb,
- node_activated_cb,
- node_deactivated_cb,
- node_signal_received_cb
- };
-
- mmi_port_callbacks camera_port_callbacks {
- port_output_format_requested_cb,
- port_input_data_received_cb
- };
-
- mmi_port_h camera_port = nullptr;
- mmi_port_create(&camera_port);
- mmi_port_set_name(camera_port, "VIDEO");
- mmi_port_set_type(camera_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(camera_port, MMI_DATA_TYPE_VIDEO);
- mmi_port_set_callbacks(camera_port, camera_port_callbacks);
-
- mmi_node_h camera_node = nullptr;
- mmi_standard_node_create_source(MMI_STANDARD_NODE_SOURCE_TYPE_CAMERA, &camera_node);
- mmi_node_add_port(camera_node, camera_port);
- mmi_node_set_callbacks(camera_node, node_callbacks);
-
- mmi_node_register(camera_node);
-
- mmi_node_destroy(camera_node);
- }
-
-} // extern "C"
+++ /dev/null
-{
- "maxFaceCount": 2,
- "faceInfo": [
- {
- "faceId": "test4",
- "faceName": "test4",
- "enrollFilePath": "/usr/share/face_recognition/enroll/soo_1.jpg"
- },
- {
- "faceId": "test2",
- "faceName": "test2",
- "enrollFilePath": "/usr/share/face_recognition/enroll/soo_4.jpg"
- }
- ]
-}
\ No newline at end of file
+++ /dev/null
-mmi_module_fr_library_srcs = [
- 'mmi-module-fr.cpp',
- 'mmi-module-fr-data-manager.h',
- 'mmi-module-fr-data-manager.cpp'
- ]
-
-dlog_dep = dependency('dlog', method : 'pkg-config')
-ecore_dep = dependency('ecore', method : 'pkg-config')
-json_dep = dependency('json-glib-1.0', method : 'pkg-config')
-media_vision_dep = dependency('capi-media-vision', method : 'pkg-config')
-image_util_dep = dependency('capi-media-image-util', method : 'pkg-config')
-opencv_dep = dependency('opencv', method : 'pkg-config')
-
-mmi_module_fr_deps = [
- mmi_declared_dep,
- dlog_dep,
- ecore_dep,
- json_dep,
- media_vision_dep,
- image_util_dep,
- opencv_dep,
- ]
-
-mmi_module_fr_include_dirs = include_directories(
- '.',
- '../../../capi/',
- )
-
-mmi_module_fr_library = library('mmi_module_fr',
- mmi_module_fr_library_srcs,
- include_directories : [ mmi_module_fr_include_dirs ],
- dependencies : [mmi_module_fr_deps],
- install_dir : mmi_prefix_plugindir,
- install : true
- )
-
-install_data('data/recognizerInfo.json', install_dir : '/usr/share/face_recognition/')
+++ /dev/null
-/*
- * Copyright (c) 2023 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.
- *
- */
-
-// FIXME: temporary module for testing
-// FIXME: remove this module after register/recognize fw/app is ready
-#include <json-glib-1.0/json-glib/json-glib.h>
-#include <mmi-log.h>
-
-#include "mmi-module-fr-data-manager.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-FACE-RECOGNITION"
-
-DataManager::DataManager()
-{
- m_info_file_path = std::string("/usr/share/face_recognition/recognizerInfo.json");
- m_mutex = new(std::nothrow) std::mutex();
- if (nullptr == m_mutex) {
- _E("[FR DATAMGR] Failed to create mutex");
- return;
- }
- load_info();
-}
-
-DataManager::~DataManager()
-{
- delete m_mutex;
- m_mutex = nullptr;
-}
-
-void DataManager::load_info()
-{
- _D("[FR DATAMGR] load info ");
- std::lock_guard <std::mutex> lock(*m_mutex);
-
- JsonParser *parser = nullptr;
- parser = json_parser_new();
- if (nullptr == parser) {
- _E("[FR DATAMGR] Failed to create json parser");
- return;
- }
-
- GError *error = nullptr;
- if (!json_parser_load_from_file(parser, m_info_file_path.c_str(), &error)) {
- _E("[FR DATAMGR] Failed to load json file: %s", error->message);
- g_error_free(error);
- return;
- }
-
- JsonObject *recognizer_info = json_node_get_object(json_parser_get_root(parser));
- if (nullptr == recognizer_info) {
- _E("[FR DATAMGR] Failed to get root object");
- g_object_unref(parser);
- parser = nullptr;
- return;
- }
-
- m_max_face_count = json_object_get_int_member(recognizer_info, "maxFaceCount");
- _D("[FR DATAMGR] max face count is %d", m_max_face_count);
-
- JsonArray *face_info = json_object_get_array_member(recognizer_info, "faceInfo");
- if (nullptr == face_info) {
- _E("[FR DATAMGR] Failed to get faceInfo object");
- g_object_unref(parser);
- parser = nullptr;
- return;
- }
-
- for (int i = 0; i < json_array_get_length(face_info); i++) {
- JsonObject *face = json_array_get_object_element(face_info, i);
- if (nullptr == face) {
- _E("[FR DATAMGR] Failed to get face object");
- g_object_unref(parser);
- parser = nullptr;
- return;
- }
-
- const gchar *id = json_object_get_string_member(face, "faceId");
- const gchar *name = json_object_get_string_member(face, "faceName");
- const gchar *file_path = json_object_get_string_member(face, "enrollFilePath");
-
- FaceInfo info;
- info.id = std::string(id);
- info.name = std::string(name);
- info.file_path = std::string(file_path);
- _D("[FR DATAMGR] face info: id: %s, name: %s, file_path: %s", info.id.c_str(), info.name.c_str(), info.file_path.c_str());
- m_face_list.push_back(info);
- }
-
- g_object_unref(parser);
- parser = nullptr;
-}
-
-void DataManager::save_info()
-{
- _D("[FR DATAMGR] save info");
- std::lock_guard <std::mutex> lock(*m_mutex);
- JsonBuilder *builder = json_builder_new();
-
- json_builder_begin_object(builder);
-
- json_builder_set_member_name(builder, "maxFaceCount");
- json_builder_add_int_value(builder, m_max_face_count);
-
- json_builder_set_member_name(builder, "faceInfo");
-
- json_builder_begin_array(builder);
- for (int i = 0; i < m_face_list.size(); i++) {
- json_builder_begin_object(builder);
- json_builder_set_member_name(builder, "faceId");
- json_builder_add_string_value(builder, m_face_list[i].id.c_str());
- json_builder_set_member_name(builder, "faceName");
- json_builder_add_string_value(builder, m_face_list[i].name.c_str());
- json_builder_set_member_name(builder, "enrollFilePath");
- json_builder_add_string_value(builder, m_face_list[i].file_path.c_str());
- json_builder_end_object(builder);
- }
- json_builder_end_array(builder);
-
- json_builder_end_object(builder);
-
- JsonGenerator *generator = json_generator_new();
- json_generator_set_root(generator, json_builder_get_root(builder));
- json_generator_set_pretty(generator, TRUE);
-
- // save file and check return value
- gboolean ret = json_generator_to_file(generator, m_info_file_path.c_str(), NULL);
- if (FALSE == ret) {
- _E("[FR DATAMGR] Failed to save json file");
- }
-
- if (builder) {
- g_object_unref(builder);
- builder = nullptr;
- }
- if (generator) {
- g_object_unref(generator);
- generator = nullptr;
- }
-}
-
-void DataManager::add_face(FaceInfo info)
-{
- _D("[FR DATAMGR] add face info");
- {
- std::lock_guard <std::mutex> lock(*m_mutex);
- m_face_list.push_back(info);
- for (auto &i : m_face_list) {
- _D("[FR DATAMGR] face info: id: %s, name: %s, model: %s", i.id.c_str(), i.name.c_str(), i.file_path.c_str());
- }
- }
-
- save_info();
-}
-
-void DataManager::delete_face(std::string id)
-{
- _D("[FR DATAMGR] delete face info");
- {
- std::lock_guard <std::mutex> lock(*m_mutex);
- for (int i = 0; i < m_face_list.size(); i++) {
- if (m_face_list[i].id == id) {
- m_face_list.erase(m_face_list.begin() + i);
- break;
- }
- }
- }
- save_info();
-}
-
-void DataManager::update_face(FaceInfo info)
-{
- _D("[FR DATAMGR] update face info");
- {
- std::lock_guard <std::mutex> lock(*m_mutex);
- for (int i = 0; i < m_face_list.size(); i++) {
- if (m_face_list[i].id == info.id) {
- m_face_list[i].name = info.name;
- m_face_list[i].file_path = info.file_path;
- break;
- }
- }
- }
-
- save_info();
-}
-
-int DataManager::get_face_count()
-{
- _D("[FR DATAMGR] get face count");
- std::lock_guard <std::mutex> lock(*m_mutex);
- int count = m_face_list.size();
- return count;
-}
-
-FaceInfo DataManager::get_face_info(std::string id)
-{
- _D("[FR DATAMGR] get face info");
- std::lock_guard <std::mutex> lock(*m_mutex);
- FaceInfo info;
- for (int i = 0; i < m_face_list.size(); i++) {
- if (m_face_list[i].id == id) {
- info = m_face_list[i];
- break;
- }
- }
-
- return info;
-}
-
-std::vector<FaceInfo> DataManager::get_face_list()
-{
- _D("[FR DATAMGR] get face list");
- std::lock_guard <std::mutex> lock(*m_mutex);
-
- std::vector<FaceInfo> list = m_face_list;
- return list;
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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.
- *
- */
-
-#pragma once
-
-#include <mutex>
-#include <string>
-#include <vector>
-
-struct FaceInfo {
- std::string id;
- std::string name;
- std::string file_path;
-};
-
-class DataManager {
-private:
- void load_info();
- void save_info();
-
-public:
- DataManager();
- ~DataManager();
- static DataManager& get_instance() {
- static DataManager instance;
- return instance;
- }
-
- std::vector<FaceInfo> get_face_list();
- FaceInfo get_face_info(std::string id);
- int get_face_count();
- void add_face(FaceInfo info);
- void delete_face(std::string id);
- void update_face(FaceInfo info);
-
-private:
- static DataManager m_instance;
- std::vector<FaceInfo> m_face_list;
- int m_max_face_count{0};
- std::string m_info_file_path{};
- std::mutex* m_mutex{nullptr};
-};
+++ /dev/null
-#include <mmi.h>
-#include <mmi-attribute.h>
-#include <mmi-node.h>
-#include <mmi-node-processor.h>
-#include <mmi-log.h>
-#include <mmi-error.h>
-
-#include <mv_face.h>
-#include <mv_common.h>
-#include <mv_inference.h>
-#include <mv_face_recognition.h>
-#include "mv_face_recognition_internal.h"
-#include <image_util.h>
-
-#include <string>
-#include <map>
-
-#include <dirent.h>
-#include <dlfcn.h>
-#include <dlog.h>
-#include <Ecore.h>
-
-#include "mmi-module-fr-data-manager.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-FACE-RECOGNITION"
-
-#define FRAME_WIDTH 640
-#define FRAME_HEIGHT 480
-
-static const char *INPUT_PORT_NAME_VIDEO = "VIDEO";
-static const char *OUTPUT_PORT_NAME_MATCHED_FACES = "MATCHED_FACES";
-static const char *OUTPUT_RESULT_ELEMENT_NODE = "fromNode";
-static const char *OUTPUT_RESULT_NODE_NAME = "FACE_RECOGNITION";
-static const char *OUTPUT_RESULT_ELEMENT_CANDIDATE = "recognizedCandidates";
-
-static mv_face_recognition_h g_face_recog_h = nullptr;
-static DataManager *g_data_manager = nullptr;
-
-struct _facedata_s
-{
- unsigned char *id;
- unsigned int width;
- unsigned int height;
- unsigned int channel;
- unsigned int size;
- unsigned char *data;
-};
-
-typedef struct _facedata_s facedata_s;
-static std::map<char *, facedata_s *> g_registered_faces_map;
-static std::map<mmi_port_instance_h, mmi_node_instance_h> g_input_port_to_instance_map;
-
-int register_face_from_file(const char *file_path, const char *file_name)
-{
- unsigned char *data_buffer = NULL;
- size_t buffer_size = 0;
- unsigned int width = FRAME_WIDTH;
- unsigned int height = FRAME_HEIGHT;
- image_util_decode_h img_decoder = NULL;
- image_util_image_h decoded_img = NULL;
- mv_source_h mv_src = NULL;
- image_util_colorspace_e colorspace;
-
- int ret = -1;
-
- /* Get image from filepath, Decode image and Fill the image data to mv_source handle */
- ret = image_util_decode_create(&img_decoder);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to cretae image decoder");
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- ret = image_util_decode_set_input_path(img_decoder, file_path);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to set input path");
- image_util_decode_destroy(img_decoder);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_decode_set_colorspace(img_decoder, IMAGE_UTIL_COLORSPACE_RGB888);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to image_util_decode_set_colorspace");
- image_util_decode_destroy(img_decoder);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_decode_set_output_buffer(img_decoder, &data_buffer);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to set output buffer");
- image_util_decode_destroy(img_decoder);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_decode_run2(img_decoder, &decoded_img);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to run decoder");
- image_util_decode_destroy(img_decoder);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_get_image(decoded_img, &width, &height, &colorspace, &data_buffer, &buffer_size);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to get image (%d)", ret);
- image_util_decode_destroy(img_decoder);
- image_util_destroy_image(decoded_img);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_destroy_image(decoded_img);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to destroy image (%d)", ret);
- image_util_decode_destroy(img_decoder);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_decode_destroy(img_decoder);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to destroy decoder");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = mv_create_source(&mv_src);
- if (ret != MEDIA_VISION_ERROR_NONE) {
- _E("[FR] Fail to create mv source");
- return MMI_ERROR_OUT_OF_MEMORY;
- }
- ret = mv_source_fill_by_buffer(mv_src, data_buffer, (unsigned int)buffer_size,
- (unsigned int)width, (unsigned int)height, MEDIA_VISION_COLORSPACE_RGB888);
- if (ret != MEDIA_VISION_ERROR_NONE) {
- free(data_buffer);
- _E("[FR] Fail to fill mv source by buffer");
- mv_destroy_source(mv_src);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = mv_face_recognition_register(g_face_recog_h, mv_src, file_name);
- if (ret != MEDIA_VISION_ERROR_NONE) {
- _E("Fail to register the detected face = %d", ret);
- if (ret == MEDIA_VISION_ERROR_INVALID_PARAMETER)
- _E("Fail to register the detected face = %d(MEDIA_VISION_ERROR_INVALID_PARAMETER)", ret);
- else if (ret == MEDIA_VISION_ERROR_INVALID_OPERATION)
- _E("Fail to register the detected face = %d(MEDIA_VISION_ERROR_INVALID_OPERATION)", ret);
- else if (ret == MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT)
- _E("Fail to register the detected face = %d(MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT)", ret);
- else if (ret == MEDIA_VISION_ERROR_OUT_OF_MEMORY)
- _E("Fail to register the detected face = %d(MEDIA_VISION_ERROR_OUT_OF_MEMORY)", ret);
- else if (ret == MEDIA_VISION_ERROR_INTERNAL)
- _E("Fail to register the detected face = %d(MEDIA_VISION_ERROR_INTERNAL)", ret);
-
- mv_destroy_source(mv_src);
-
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- mv_destroy_source(mv_src);
-
- return MMI_ERROR_NONE;
-}
-
-int register_faces(void)
-{
- std::vector<FaceInfo> face_list = g_data_manager->get_face_list();
- for (auto it = face_list.begin(); it != face_list.end(); it++) {
- std::string face_id = it->id;
- std::string face_name = it->name;
- std::string face_file_path = it->file_path;
-
- register_face_from_file(face_file_path.c_str(), face_name.c_str());
- }
-
- return MMI_ERROR_NONE;
-}
-
-int unregister_faces(void)
-{
- int ret = -1;
- std::vector<FaceInfo> face_list = g_data_manager->get_face_list();
- for (auto it = face_list.begin(); it != face_list.end(); it++) {
- std::string face_name = it->name;
-
- ret = mv_face_recognition_unregister(g_face_recog_h, face_name.c_str());
- if (ret != MEDIA_VISION_ERROR_NONE) {
- _E("Fail to unregister the detected face = %d", ret);
- if (ret == MEDIA_VISION_ERROR_INVALID_PARAMETER)
- _E("Fail to unregister the detected face = %d(MEDIA_VISION_ERROR_INVALID_PARAMETER)", ret);
- else if (ret == MEDIA_VISION_ERROR_INVALID_OPERATION)
- _E("Fail to unregister the detected face = %d(MEDIA_VISION_ERROR_INVALID_OPERATION)", ret);
- else if (ret == MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT)
- _E("Fail to unregister the detected face = %d(MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT)", ret);
- else if (ret == MEDIA_VISION_ERROR_OUT_OF_MEMORY)
- _E("Fail to unregister the detected face = %d(MEDIA_VISION_ERROR_OUT_OF_MEMORY)", ret);
- else if (ret == MEDIA_VISION_ERROR_INTERNAL)
- _E("Fail to unregister the detected face = %d(MEDIA_VISION_ERROR_INTERNAL)", ret);
- }
- }
-
- _D("[FR] Finish to unregister faces");
-
- return MMI_ERROR_NONE;
-}
-
-static int node_initialized_cb(mmi_node_instance_h instance)
-{
- _D("[FR] Node initialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[FR] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_port_instance_h input_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_IN, INPUT_PORT_NAME_VIDEO, &input_port);
- if (nullptr == input_port) {
- _E("[FR] Input port(video) is null. %p", input_port);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- g_input_port_to_instance_map[input_port] = instance;
- _D("[FR] Input port is found. %p", input_port);
-
- try {
- /* TODO: initialize face recognition */
- int ret = -1;
- if (nullptr == g_face_recog_h) {
- ret = mv_face_recognition_create(&g_face_recog_h);
- if (MEDIA_VISION_ERROR_NONE != ret || nullptr == g_face_recog_h) {
- _E("[FR] Fail to create face recognition handle");
- throw ret;
- }
- }
-
- ret = mv_face_recognition_prepare(g_face_recog_h);
- if (MEDIA_VISION_ERROR_NONE != ret) {
- _E("[FR] Fail to prepare face recognition handle");
- throw ret;
- }
-
- /* register facial images */
- g_data_manager = new DataManager();
- ret = register_faces();
- } catch (std::bad_alloc &e) {
- _E("[FR] Fail to allocate memory. %s", e.what());
- return MMI_ERROR_OUT_OF_MEMORY;
- } catch (std::exception &e) {
- _E("[FR] Fail to initialize face recognition. %s", e.what());
- return MMI_ERROR_OPERATION_FAILED;
- } catch (int e) {
- _E("[FR] Fail to initialize face recognition (%d)", e);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deinitialized_cb(mmi_node_instance_h instance)
-{
- _D("[FR] Node deinitialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[FR] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_port_instance_h input_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_IN, INPUT_PORT_NAME_VIDEO, &input_port);
- if (nullptr == input_port) {
- _E("[FR] Input port is null. %p", input_port);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- g_input_port_to_instance_map.erase(input_port);
-
- /* TODO: deinitialize face recognition */
- unregister_faces();
-
- delete g_data_manager;
-
- if (nullptr != g_face_recog_h) {
- mv_face_recognition_destroy(g_face_recog_h);
- g_face_recog_h = nullptr;
- }
-
-
- return MMI_ERROR_NONE;
-}
-
-static int node_attribute_set_cb(mmi_node_instance_h instance, mmi_attribute_h attribute)
-{
- _D("[FR] Node attribute set callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-static int node_activated_cb(mmi_node_instance_h instance)
-{
- _D("[FR] Node activate callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[FR] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- _D("[FR] Node activate callback is finished for %p", instance);
-
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deactivated_cb(mmi_node_instance_h instance)
-{
- _D("[FR] Node deactivate callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[FR] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- _D("[FR] Node deactivate callback is finished for %p", instance);
-
-
- return MMI_ERROR_NONE;
-}
-
-static int node_signal_received_cb(mmi_node_instance_h instance, mmi_signal_h signal)
-{
- _D("[FR] Node signal received callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-static int port_output_format_requested_cb(mmi_port_instance_h instance, const char *format)
-{
- _D("[FR] Port output format request callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-static void set_float_to_struct(mmi_data_h struct_data, const char *name, float value)
-{
- mmi_data_h data = nullptr;
- mmi_data_create_float(value, &data);
- mmi_data_set_struct_element(struct_data, name, data);
-}
-
-static void set_text_to_struct(mmi_data_h struct_data, const char *name, const char *value)
-{
- mmi_data_h data = nullptr;
- mmi_data_create_text(value, &data);
- mmi_data_set_struct_element(struct_data, name, data);
-}
-
-static void add_array_element(mmi_data_h array_data, const char *id, const char *name, float confidence)
-{
- mmi_data_h struct_data = nullptr;
- mmi_data_create_struct(&struct_data);
- if (nullptr == struct_data) {
- _E("[FR] Fail to create struct data");
- return ;
- }
-
- set_text_to_struct(struct_data, "id", id);
- set_text_to_struct(struct_data, "name", name);
- set_float_to_struct(struct_data, "confidence", confidence);
-
- mmi_data_add_array_element(array_data, struct_data);
-}
-
-static int port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data)
-{
- /* Video input will be received. Recognize input data. */
- _D("[FR] Port input data callback is called for %p", instance);
-
- auto iterator = g_input_port_to_instance_map.find(instance);
- if (g_input_port_to_instance_map.end() == iterator) {
- _E("[FR] Fail to find proper node instance. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- auto node_instance = iterator->second; // a value of a map (first = a key of a map)
- _D("[FR] Node instance is %p", node_instance);
-
-
- const void *ptr = nullptr;
- size_t len = 0;
- int ret = 0;
-
- if (mmi_data_get_video(data, &ptr, &len) != MMI_ERROR_NONE) {
- _E("[FR] Failed to get video data");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- _D("[FR] Video input data callback is called: %p %zu", node_instance, len);
-
- /* TODO: check video format... currently, use fixed values */
- /* current video format : I420 */
- unsigned char *data_buffer = NULL;
- size_t buffer_size = 0;
- image_util_image_h img_src = NULL;
- image_util_image_h img_dst = NULL;
- unsigned int width = FRAME_WIDTH;
- unsigned int height = FRAME_HEIGHT;
- transformation_h transform_h;
-
- ret = image_util_create_image(width, height, IMAGE_UTIL_COLORSPACE_I420, (const unsigned char *)ptr, len, &img_src);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to create image (%d)", ret);
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- ret = image_util_transform_create(&transform_h);
- if (IMAGE_UTIL_ERROR_NONE != ret) {
- _E("[FR] Fail to create image util transform handle");
- image_util_destroy_image(img_src);
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- ret = image_util_transform_set_colorspace(transform_h, IMAGE_UTIL_COLORSPACE_RGB888);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to set colorspace(%d)", ret);
- image_util_destroy_image(img_src);
- image_util_transform_destroy(transform_h);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_transform_run2(transform_h, img_src, &img_dst); // img_src: YUYV image, img_dst: RGB888 image
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to transform image (%d)", ret);
- image_util_destroy_image(img_src);
- image_util_transform_destroy(transform_h);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- if (nullptr != transform_h) {
- image_util_transform_destroy(transform_h);
- transform_h = nullptr;
- }
-
- /* get image data */
- image_util_colorspace_e colorspace;
- unsigned int converted_width;
- unsigned int converted_height;
- unsigned char *image; // RGB888로 변환된 image
- size_t image_size;
-
- ret = image_util_get_image(img_dst, &converted_width, &converted_height, &colorspace, &image, &image_size);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to get image (%d)", ret);
- image_util_destroy_image(img_src);
- image_util_destroy_image(img_dst);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = image_util_destroy_image(img_src);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to destroy image(src) (%d)", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
- ret = image_util_destroy_image(img_dst);
- if (ret != IMAGE_UTIL_ERROR_NONE) {
- _E("[FR] Fail to destroy image(dst) (%d)", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
-
- mv_source_h source;
- mv_colorspace_e src_color = MEDIA_VISION_COLORSPACE_RGB888;
-
- /* TODO: recognize face */
- ret = mv_create_source(&source);
- if (MEDIA_VISION_ERROR_NONE != ret) {
- _E("[FR ERROR] Fail to create source");
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- ret = mv_source_fill_by_buffer(source, (unsigned char *)image, image_size, converted_width, converted_height, src_color);
- if (MEDIA_VISION_ERROR_NONE != ret) {
- _E("[FR ERROR] Fail to fill source by buffer");
- mv_destroy_source(source);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = mv_face_recognition_inference(g_face_recog_h, source);
- if (MEDIA_VISION_ERROR_NONE != ret) {
- _W("[FR ERROR] Fail to inference. ret(%d)", ret);
- // mv_destroy_source(source);
- // return MMI_ERROR_OPERATION_FAILED;
- }
-
- const char *out_label = NULL;
- ret = mv_face_recognition_get_label(g_face_recog_h, &out_label);
- if (MEDIA_VISION_ERROR_NONE != ret) {
- _E("[FR ERROR] Fail to get label");
- mv_destroy_source(source);
- return MMI_ERROR_OPERATION_FAILED;
- } else {
- _I("[FR Result] recognized label(%s)", out_label);
- }
-
-
- /* TODO: generate result struct to output port */
- mmi_port_instance_h output_port_instance = nullptr;
- mmi_node_instance_find_port(node_instance, MMI_PORT_TYPE_OUT, OUTPUT_PORT_NAME_MATCHED_FACES, &output_port_instance);
- if (nullptr == output_port_instance) {
- _E("[FR] Fail to get matched faces port from node. %p", node_instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- mmi_data_h result_data = nullptr;
- mmi_data_create_struct(&result_data);
- if (nullptr == result_data) {
- _E("[FR] Fail to create result data");
- return MMI_ERROR_OUT_OF_MEMORY;
- }
- mmi_data_h elem_data = nullptr;
- mmi_data_create_text(OUTPUT_RESULT_NODE_NAME, &elem_data);
- mmi_data_set_struct_element(result_data, OUTPUT_RESULT_ELEMENT_NODE, elem_data);
-
- mmi_data_h result_array_data = nullptr;
- mmi_data_create_array(&result_array_data);
- if (nullptr == result_array_data) {
- _E("[FR] Fail to create result array data");
- mmi_data_destroy(result_data);
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- const float out_confidence = 0.0;
- size_t num_of_confidences = 0;
- const float *out_confidences = nullptr;
- ret = mv_face_recognition_get_confidence(g_face_recog_h, &out_confidences, &num_of_confidences);
- if (MEDIA_VISION_ERROR_NONE == ret) {
- _D("[FR] Success to get confidences");
- const char *label;
- for (int i = 0 ; i < num_of_confidences ; i++) {
- mv_face_recognition_get_label_with_index(g_face_recog_h, i, &label);
- _D("[%d] label(%s), confidence(%lf)", i, label, out_confidences[i] + 1.35f);
- add_array_element(result_array_data, label, label, out_confidences[i] + 1.35f);
- }
- }
-
- mmi_data_set_struct_element(result_data, OUTPUT_RESULT_ELEMENT_CANDIDATE, result_array_data);
-
- // TODO: call "mmi_data_add_array_element()" ??
-
- ret = mmi_port_instance_generate_output(output_port_instance, result_data);
- if (MMI_ERROR_NONE != ret) {
- _E("[FR] Fail to generate output. %d", ret);
- }
-
- mmi_data_destroy(result_data);
- mv_destroy_source(source);
-
- return MMI_ERROR_NONE;
-}
-
-extern "C" {
-
- EXPORT_API void mmi_plugin_module_get_node_list()
- {
- mmi_node_callbacks node_callbacks {
- node_initialized_cb,
- node_deinitialized_cb,
- node_attribute_set_cb,
- node_activated_cb,
- node_deactivated_cb,
- node_signal_received_cb
- };
-
- mmi_port_callbacks video_port_callbacks {
- port_output_format_requested_cb,
- port_input_data_received_cb
- };
-
- mmi_port_h fr_video_port = nullptr;
- mmi_port_create(&fr_video_port);
- mmi_port_set_name(fr_video_port, INPUT_PORT_NAME_VIDEO);
- mmi_port_set_type(fr_video_port, MMI_PORT_TYPE_IN);
- mmi_port_set_data_type(fr_video_port, MMI_DATA_TYPE_VIDEO);
- mmi_port_set_callbacks(fr_video_port, video_port_callbacks);
-
- mmi_port_h fr_matched_faces_port = nullptr;
- mmi_port_create(&fr_matched_faces_port);
- mmi_port_set_name(fr_matched_faces_port, OUTPUT_PORT_NAME_MATCHED_FACES);
- mmi_port_set_type(fr_matched_faces_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(fr_matched_faces_port, MMI_DATA_TYPE_STRUCT);
- // mmi_port_set_data_type(fr_matched_faces_port, MMI_DATA_TYPE_BOUNDING_BOX); // bounding box type?
-
- /* Callbacks for OUT ports are not needed for now */
-
- mmi_node_h fr_node = nullptr;
- mmi_standard_node_create_processor(MMI_STANDARD_NODE_PROCESSOR_TYPE_FACE_RECOGNITION, &fr_node);
- mmi_node_add_port(fr_node, fr_video_port);
- mmi_node_add_port(fr_node, fr_matched_faces_port);
- mmi_node_set_callbacks(fr_node, node_callbacks);
- mmi_node_register(fr_node);
-
- mmi_node_destroy(fr_node);
- }
-
-} // extern "C"
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __TIZEN_MEDIAVISION_MV_FACE_RECOGNITION_INTERNAL_H__
-#define __TIZEN_MEDIAVISION_MV_FACE_RECOGNITION_INTERNAL_H__
-
-#include <mv_common.h>
-#include <mv_face_recognition_type.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * @internal
- * @brief Gets confidences after a given face image is recognized.
- * @details Use this function to get the confidences calling @ref mv_face_recognition_inference().
- *
- * @since_tizen 8.0
- *
- * @remarks The @a num_of_confidences and @a confidences must NOT be released using free()
- *
- * @param[in] handle The handle to the face recognition object.
- * @param[out] confidences The array pointer to the confidence table which contains a confidence value of each class.
- * This function returns memory pointer containing actual confidence values to @a confidences.
- * And please note that @a confidences is valid only while handle is alive.
- * @param[out] num_of_confidences A number of confidences to the classes registered.
- *
- * @return @c 0 on success, otherwise a negative error value
- * @retval #MEDIA_VISION_ERROR_NONE Successful
- * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
- * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
- *
- * @pre Request an inference by calling @ref mv_face_recognition_inference()
- */
-int mv_face_recognition_get_confidence(mv_face_recognition_h handle, const float **confidences,
- size_t *num_of_confidences);
-
-/**
- * @internal
- * @brief Gets a label name corresponding to a given index.
- * @details Use this function to get the label name calling @ref mv_face_recognition_get_confidence().
- *
- * @since_tizen 8.0
- *
- * @remarks The @a num_of_confidences and @a confidences must NOT be released using free()
- *
- * @param[in] handle The handle to the face recognition object.
- * @param[in] index A label index pointing to the offset of label file.
- * @param[out] label The array pointer for the label name to be stored.
- * This function returns memory pointer containing actual label string to @a label.
- * So do not free @a label. And please note that @a label is valid only while handle is alive.
- *
- * @return @c 0 on success, otherwise a negative error value
- * @retval #MEDIA_VISION_ERROR_NONE Successful
- * @retval #MEDIA_VISION_ERROR_INVALID_PARAMETER Invalid parameter
- * @retval #MEDIA_VISION_ERROR_INVALID_OPERATION Invalid operation
- *
- * @pre Request an inference by calling @ref mv_face_recognition_get_confidence()
- */
-int mv_face_recognition_get_label_with_index(mv_face_recognition_h handle, const unsigned int index,
- const char **label);
-
-/**
- * @}
- */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __TIZEN_MEDIAVISION_MV_FACE_RECOGNITION_INTERNAL_H__ */
+++ /dev/null
-mmi_module_match_library_srcs = [
- 'mmi-module-match.cpp',
- 'mmi-module-match-text-candidates.h',
- 'mmi-module-match-text-candidates.cpp',
- ]
-
-dlog_dep = dependency('dlog', method : 'pkg-config')
-ecore_dep = dependency('ecore', method : 'pkg-config')
-
-mmi_module_match_deps = [
- mmi_declared_dep,
- dlog_dep,
- ecore_dep,
- ]
-
-mmi_module_match_include_dirs = include_directories(
- '.',
- '../../../capi/',
- )
-
-mmi_module_match_library = library('mmi_module_match',
- mmi_module_match_library_srcs,
- include_directories : [ mmi_module_match_include_dirs ],
- dependencies : [mmi_module_match_deps],
- install_dir : mmi_prefix_plugindir,
- install : true
- )
+++ /dev/null
-/*
- * Copyright (c) 2023 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 <mmi-log.h>
-
-#include <algorithm>
-
-#include "mmi-module-match-text-candidates.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-MATCH"
-
-
-using namespace std;
-
-
-TextCandidates::TextCandidates()
-{
- _I("[MATCH] Construct TextCandidates");
- m_candidates.clear();
-}
-
-TextCandidates::~TextCandidates()
-{
- _I("[MATCH] Destruct TextCandidates");
- m_candidates.clear();
-}
-
-void TextCandidates::append_candidate(const char *candidate)
-{
- if (nullptr == candidate) {
- _W("[MATCH] Candidate text is null. Skip appending");
- return;
- }
-
- _I("[MATCH] Append candidate(%s)", candidate);
- m_candidates.push_back(candidate);
- _D("[MATCH] The current number of candidates (%zu)", m_candidates.size());
-}
-
-bool TextCandidates::is_exist(const char *candidate)
-{
- _I("[MATCH] Is candidate exist. candidate(%s)", candidate);
-
- auto element = std::find(m_candidates.begin(), m_candidates.end(), candidate);
- if (element == m_candidates.end()) {
- _E("[MATCH] There no matched command");
- return false;
- }
-
- _I("[MATCH] Success To find candidate(%s)", candidate);
- return true;
-}
-
-void TextCandidates::clear_candidates()
-{
- _I("[MATCH] Clear current candidates");
- m_candidates.clear();
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_MATCH_TEXT_CANDIDATES_H__
-#define __MMI_MODULE_MATCH_TEXT_CANDIDATES_H__
-
-
-#include <vector>
-#include <string>
-
-
-class TextCandidates {
-public:
- TextCandidates();
- ~TextCandidates();
-
- void append_candidate(const char *candidate);
- bool is_exist(const char *candidate);
- void clear_candidates();
-
-private:
- std::vector<std::string> m_candidates;
-};
-
-#endif /* __MMI_MODULE_MATCH_TEXT_CANDIDATES_H__ */
+++ /dev/null
-#include <mmi-attribute.h>
-#include <mmi-node.h>
-#include <mmi-node-logic.h>
-#include <mmi-log.h>
-
-#include <map>
-#include <memory>
-
-#include "mmi-module-match-text-candidates.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-MATCH"
-
-
-static const char *INPUT_PORT_NAME_TEXT = "TEXT";
-static const char *OUTPUT_PORT_NAME_MATCHED_CANDIDATE = "MATCHED_CANDIDATE";
-static const char *OUTPUT_PORT_NAME_REJECTED = "REJECTED";
-static const char *ATTRIBUTE_NAME_CANDIDATES = "CANDIDATES";
-
-
-static std::map<mmi_node_instance_h, std::shared_ptr<TextCandidates>> g_node_to_text_candidates_map;
-static std::map<mmi_port_instance_h, mmi_node_instance_h> g_input_port_to_node_map;
-
-
-static int node_initialized_cb(mmi_node_instance_h instance)
-{
- _D("[MATCH] Node initialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[MATCH] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_port_instance_h input_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_IN, INPUT_PORT_NAME_TEXT, &input_port);
- if (nullptr == input_port) {
- _E("[MATCH] Fail to get port from node. %p", instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- g_input_port_to_node_map[input_port] = instance;
-
- try {
- auto text_candidates = std::make_shared<TextCandidates>();
- g_node_to_text_candidates_map[instance] = text_candidates;
- } catch (std::bad_alloc &e) {
- _E("[MATCH] Fail to allocate memory for node instance. %p", instance);
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static bool is_node_instance_valid(mmi_node_instance_h instance)
-{
- if (nullptr == instance) {
- _E("[MATCH] Node instance is null %p", instance);
- return false;
- }
-
- auto iterator = g_node_to_text_candidates_map.find(instance);
- if (iterator == g_node_to_text_candidates_map.end()) {
- _E("[MATCH] No instance %p", instance);
- return false;
- }
-
- return true;
-}
-
-static int node_deinitialized_cb(mmi_node_instance_h instance)
-{
- _D("[MATCH] Node deinitialize callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_port_instance_h input_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_IN, INPUT_PORT_NAME_TEXT, &input_port);
- if (nullptr == input_port) {
- _E("[MATCH] Fail to get port from node. %p", instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- g_input_port_to_node_map.erase(input_port);
- g_node_to_text_candidates_map.erase(instance);
-
- return MMI_ERROR_NONE;
-}
-
-static int node_attribute_set_cb(mmi_node_instance_h instance, mmi_attribute_h attribute)
-{
- _D("[MATCH] Node attribute set callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- char *name = nullptr;
- mmi_attribute_get_name(attribute, &name);
- if (nullptr == name) {
- _E("[MATCH] Fail to get attribute name");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- std::string attribute_name(name);
- free(name);
- name = nullptr;
-
- if (0 != attribute_name.compare(ATTRIBUTE_NAME_CANDIDATES)) {
- _E("[MATCH] Attribute name is not same as expected one. (%s)", attribute_name.c_str());
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_primitive_value_h value = nullptr;
- mmi_primitive_value_type_e type = MMI_PRIMITIVE_VALUE_TYPE_INT;
- mmi_attribute_get_value(attribute, &value);
- mmi_primitive_value_get_type(value, &type);
- if (MMI_PRIMITIVE_VALUE_TYPE_ARRAY != type) {
- mmi_primitive_value_destroy(value);
- _E("[MATCH] Invalid type of attribute : %d", type);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- size_t count = 0;
- mmi_primitive_value_get_array_count(value, &count);
-
- auto text_candidates = g_node_to_text_candidates_map[instance];
- text_candidates->clear_candidates();
-
- for (size_t i = 0; i < count; i++) {
- mmi_primitive_value_h element = nullptr;
- mmi_primitive_value_get_array_element(value, i, &element);
-
- mmi_primitive_value_type_e element_type;
- mmi_primitive_value_get_type(element, &element_type);
-
- if (MMI_PRIMITIVE_VALUE_TYPE_STRING != element_type) {
- mmi_primitive_value_destroy(value);
- _E("[MATCH] Invalid element type of attribute : %d", element_type);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- const char *element_value = nullptr;
- if (MMI_ERROR_NONE == mmi_primitive_value_get_string(element, &element_value)) {
- _D("[MATCH] Attribute value : %zu %s", i, element_value);
- text_candidates->append_candidate(element_value);
- }
- }
- mmi_primitive_value_destroy(value);
-
- return MMI_ERROR_NONE;
-}
-
-static int node_activated_cb(mmi_node_instance_h instance)
-{
- _D("[MATCH] Node activate callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deactivated_cb(mmi_node_instance_h instance)
-{
- _D("[MATCH] Node deactivate callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_signal_received_cb(mmi_node_instance_h instance, mmi_signal_h signal)
-{
- _D("[MATCH] Node signal received callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int port_output_format_requested_cb(mmi_port_instance_h instance, const char *format)
-{
- _D("[MATCH] Port output format request callback is called for %p", instance);
-
- return MMI_ERROR_NONE;
-}
-
-static int generate_output(mmi_node_instance_h instance, const char *output_name, mmi_data_h data)
-{
- mmi_port_instance_h output_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, output_name, &output_port);
- if (nullptr == output_port) {
- _E("[MATCH] Fail to get output port. %p", instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- int ret = mmi_port_instance_generate_output(output_port, data);
- if (MMI_ERROR_NONE != ret) {
- _E("[MATCH] Fail to generate output. error(%d / %s)", ret, get_error_message(ret));
- return ret;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data)
-{
- _D("[MATCH] Text input data callback is called: %p", instance);
- auto iterator = g_input_port_to_node_map.find(instance);
- if (iterator == g_input_port_to_node_map.end()) {
- _E("[MATCH] Fail to find proper node instance. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- auto node_instance = iterator->second;
- if (false == is_node_instance_valid(node_instance)) {
- _E("[MATCH] Node instance is not valid. %p", node_instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- const char *text = nullptr;
- mmi_data_get_text(data, &text);
- if (nullptr == text) {
- _E("[MATCH] Fail to get text from data");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- int ret = MMI_ERROR_NONE;
- auto text_candidates = g_node_to_text_candidates_map[node_instance];
- if (text_candidates->is_exist(text)) {
- ret = generate_output(node_instance, OUTPUT_PORT_NAME_MATCHED_CANDIDATE, data);
- } else {
- ret = generate_output(node_instance, OUTPUT_PORT_NAME_REJECTED, data);
- }
-
- if (MMI_ERROR_NONE != ret) {
- _E("[MATCH] Fail to generate output");
- return ret;
- }
-
- return MMI_ERROR_NONE;
-}
-
-
-extern "C" {
-
- EXPORT_API void mmi_plugin_module_get_node_list()
- {
- mmi_node_callbacks node_callbacks {
- node_initialized_cb,
- node_deinitialized_cb,
- node_attribute_set_cb,
- node_activated_cb,
- node_deactivated_cb,
- node_signal_received_cb
- };
-
- mmi_port_callbacks text_port_callbacks {
- port_output_format_requested_cb,
- port_input_data_received_cb
- };
-
- mmi_port_h match_text_port = nullptr;
- mmi_port_create(&match_text_port);
- mmi_port_set_name(match_text_port, INPUT_PORT_NAME_TEXT);
- mmi_port_set_type(match_text_port, MMI_PORT_TYPE_IN);
- mmi_port_set_data_type(match_text_port, MMI_DATA_TYPE_TEXT);
- mmi_port_set_callbacks(match_text_port, text_port_callbacks);
-
- mmi_port_h match_candidate_port = nullptr;
- mmi_port_create(&match_candidate_port);
- mmi_port_set_name(match_candidate_port, OUTPUT_PORT_NAME_MATCHED_CANDIDATE);
- mmi_port_set_type(match_candidate_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(match_candidate_port, MMI_DATA_TYPE_TEXT);
-
- mmi_port_h match_rejected_port = nullptr;
- mmi_port_create(&match_rejected_port);
- mmi_port_set_name(match_rejected_port, OUTPUT_PORT_NAME_REJECTED);
- mmi_port_set_type(match_rejected_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(match_rejected_port, MMI_DATA_TYPE_TEXT);
- /* Callbacks for OUT ports are not needed for now */
-
- mmi_node_h match_node = nullptr;
- mmi_standard_node_create_logic(MMI_STANDARD_NODE_LOGIC_TYPE_FIXED_STRING_MATCH, &match_node);
- mmi_node_add_port(match_node, match_text_port);
- mmi_node_add_port(match_node, match_candidate_port);
- mmi_node_add_port(match_node, match_rejected_port);
- mmi_node_set_callbacks(match_node, node_callbacks);
- mmi_node_register(match_node);
-
- mmi_node_destroy(match_node);
- }
-
-} // extern "C"
+++ /dev/null
-subdir('mic')
-subdir('camera')
-subdir('match')
-subdir('regex-match')
-subdir('face-recognition')
-subdir('voice-touch')
+++ /dev/null
-mmi_module_mic_library_srcs = [
- 'mmi-module-mic.cpp',
- 'mmi-module-mic-recorder.cpp',
- 'mmi-module-mic-recorder.h',
- ]
-
-dlog_dep = dependency('dlog', method : 'pkg-config')
-ecore_dep = dependency('ecore', method : 'pkg-config')
-audio_dep = dependency('capi-media-audio-io', method : 'pkg-config')
-sound_manager_dep = dependency('capi-media-sound-manager', method : 'pkg-config')
-
-mmi_module_mic_deps = [
- mmi_declared_dep,
- dlog_dep,
- ecore_dep,
- audio_dep,
- sound_manager_dep,
- ]
-
-mmi_module_mic_include_dirs = include_directories(
- '.',
- '../../../capi/',
- )
-
-mmi_module_mic_library = library('mmi_module_mic',
- mmi_module_mic_library_srcs,
- include_directories : [ mmi_module_mic_include_dirs ],
- dependencies : [mmi_module_mic_deps],
- install_dir : mmi_prefix_plugindir,
- install : true
- )
+++ /dev/null
-/*
- * Copyright (c) 2023 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 <mmi-module-mic-recorder.h>
-#include <mmi-node.h>
-#include <mmi-log.h>
-
-#include "mmi-module-mic-recorder.h"
-
-#define BUFFER_LENGTH 640
-
-Recorder::Recorder()
-{
-}
-
-Recorder::~Recorder()
-{
-}
-
-int Recorder::initialize()
-{
- if (0 != sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_RECOGNITION, NULL, NULL, &m_stream_info)) {
- _E("[Recorder] Fail to create stream info");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- int ret = AUDIO_IO_ERROR_NONE;
- ret = audio_in_create(16000, AUDIO_CHANNEL_MONO, AUDIO_SAMPLE_TYPE_S16_LE, &m_audio_in);
- if (ret != AUDIO_IO_ERROR_NONE) {
- _E("[Recorder] audio_in_create() failed with error code %d", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- return MMI_ERROR_NONE;
-}
-
-int Recorder::deinitialize()
-{
- int ret = AUDIO_IO_ERROR_NONE;
- ret = audio_in_destroy(m_audio_in);
- if (AUDIO_IO_ERROR_NONE != ret) {
- _E("[Recorder] audio_in_destroy() failed with error code %d", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- if (0 != sound_manager_destroy_stream_information(m_stream_info)) {
- _E("[Recorder] Fail to destroy stream info");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- return MMI_ERROR_NONE;
-}
-
-int Recorder::start()
-{
- _D("Recorder::start()");
-
- if (nullptr == m_audio_callback) {
- _E("[Recorder] callback not set");
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- int ret = AUDIO_IO_ERROR_NONE;
-
- ret = audio_in_set_sound_stream_info(m_audio_in, m_stream_info);
- if (AUDIO_IO_ERROR_NONE != ret) {
- _E("[Recorder] audio_in_set_sound_stream_info() failed with error code %d", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = audio_in_prepare(m_audio_in);
- if (AUDIO_IO_ERROR_NONE != ret) {
- _E("[Recorder] audio_in_prepare() failed with error code %d", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- if (nullptr != m_timer) {
- ecore_timer_del(m_timer);
- m_timer = nullptr;
- }
-
- m_timer = ecore_timer_add(0.0, audio_in_callback, this);
- if (nullptr == m_timer) {
- _E("[Recorder] ecore_timer_add() failed");
- stop();
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- return MMI_ERROR_NONE;
-}
-
-int Recorder::stop()
-{
- _D("Recorder::stop()");
-
- int ret = AUDIO_IO_ERROR_NONE;
-
- ret = audio_in_flush(m_audio_in);
- if (AUDIO_IO_ERROR_NONE != ret) {
- _E("[Recorder] audio_in_flush() failed with error code %d", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- ret = audio_in_unprepare(m_audio_in);
- if (AUDIO_IO_ERROR_NONE != ret) {
- _E("[Recorder] audio_in_unprepare() failed with error code %d", ret);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- if (nullptr != m_timer) {
- ecore_timer_del(m_timer);
- m_timer = nullptr;
- }
-
- return MMI_ERROR_NONE;
-}
-
-void Recorder::set_feed_audio_callback(audio_data_callback callback)
-{
- m_audio_callback = callback;
-}
-
-void Recorder::set_node_instance(mmi_node_instance_h node_instance)
-{
- m_node_instance = node_instance;
-}
-
-Eina_Bool Recorder::audio_in_callback(void *user_data)
-{
- Recorder *recorder = static_cast<Recorder*>(user_data);
- int read_byte = -1;
- static char buffer[BUFFER_LENGTH];
-
- read_byte = audio_in_read(recorder->m_audio_in, buffer, BUFFER_LENGTH);
-
- if (0 > read_byte) {
- _E("audio_in_read() failed with error code %d", read_byte);
- return EINA_FALSE;
- }
-
- if (recorder->m_audio_callback) {
- recorder->m_audio_callback(buffer, (size_t)read_byte, recorder->m_node_instance);
- }
-
- return EINA_TRUE;
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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.
- *
- */
-
-#pragma once
-
-#include <functional>
-
-#include <Ecore.h>
-#include <sound_manager.h>
-#include <audio_io.h>
-
-#include <mmi-node.h>
-
-using audio_data_callback = std::function<void(void *, size_t, void *)>;
-
-class Recorder {
-public:
- Recorder();
- ~Recorder();
-
- int initialize();
- int deinitialize();
- int start();
- int stop();
-
- void set_feed_audio_callback(audio_data_callback callback);
- void set_node_instance(mmi_node_instance_h node_instance);
-
- static Eina_Bool audio_in_callback(void *data);
-
-private:
- audio_in_h m_audio_in{nullptr};
- sound_stream_info_h m_stream_info{nullptr};
- audio_data_callback m_audio_callback{nullptr};
- mmi_node_instance_h m_node_instance{nullptr};
-
- Ecore_Timer *m_timer{nullptr};
-};
+++ /dev/null
-#include <mmi.h>
-#include <mmi-plugin-storage.h>
-#include <mmi-node.h>
-#include <mmi-log.h>
-
-#include <string>
-#include <map>
-
-#include "mmi-module-mic-recorder.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-MIC"
-
-static const char *OUTPUT_PORT_NAME_AUDIO = "AUDIO";
-
-static std::map<mmi_node_instance_h, Recorder *> g_recorder_map;
-
-static char pcm_dump_file_name[128] = {'\0',};
-static FILE* pcm_dump_fp = nullptr;
-static int g_cnt = 0;
-static size_t buffer_size = 0;
-
-void feed_audio_callback(void *data, size_t len, void *user_data)
-{
- _D("[MIC] feed_audio_callback is called, size: %zu", len);
-
- mmi_node_instance_h instance = (mmi_node_instance_h)user_data;
-
- mmi_port_instance_h port_instance = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, OUTPUT_PORT_NAME_AUDIO, &port_instance);
-
- mmi_data_h output_data = nullptr;
-
-
- if (pcm_dump_fp) {
- buffer_size += len;
- fwrite(data, 1, len, pcm_dump_fp);
- }
-
- mmi_data_create_audio(data, len, &output_data);
-
- mmi_port_instance_generate_output(port_instance, output_data);
-
- mmi_data_destroy(output_data);
-}
-
-static int node_initialized_cb(mmi_node_instance_h instance)
-{
- _D("[MIC] Node initialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[MIC] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- Recorder *recorder = new Recorder();
- recorder->initialize();
- recorder->set_node_instance(instance);
- recorder->set_feed_audio_callback(feed_audio_callback);
- g_recorder_map.insert(std::pair<mmi_node_instance_h, Recorder *>(instance, recorder));
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deinitialized_cb(mmi_node_instance_h instance)
-{
- _D("[MIC] Node deinitialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[MIC] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- Recorder *recorder = g_recorder_map[instance];
- recorder->deinitialize();
- g_recorder_map.erase(instance);
- delete recorder;
- } catch (std::out_of_range &e) {
- _E("[MIC] failed to find recorder instance");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_attribute_set_cb(mmi_node_instance_h instance, mmi_attribute_h attribute)
-{
- _D("Node attribute set callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[MIC] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- if (nullptr == attribute) {
- _E("[MIC] attribute is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- // TODO: set attribute "UNFOCUSED_ONLY"
-
- return MMI_ERROR_NONE;
-}
-
-static int node_activated_cb(mmi_node_instance_h instance)
-{
- _D("[MIC] Node activate callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[MIC] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- Recorder *recorder = g_recorder_map[instance];
- recorder->start();
- } catch (std::out_of_range &e) {
- _E("[MIC] failed to find recorder instance");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- snprintf(pcm_dump_file_name, sizeof(pcm_dump_file_name), "/tmp/mmi_mic_node_%d_%d", getpid(), g_cnt);
- g_cnt++;
-
- pcm_dump_fp = fopen(pcm_dump_file_name, "wb+x");
- if (!pcm_dump_fp) {
- _E("[SPEAKER RECOGNITION] File not found!");
- return -1;
- }
- buffer_size = 0;
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deactivated_cb(mmi_node_instance_h instance)
-{
- _D("[MIC] Node deactivate callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[MIC] node instance is null");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- Recorder *recorder = g_recorder_map[instance];
- recorder->stop();
- } catch (std::out_of_range &e) {
- _E("[MIC] failed to find recorder instance");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- if (pcm_dump_fp)
- fclose(pcm_dump_fp);
- pcm_dump_fp = nullptr;
- buffer_size = 0;
-
- return MMI_ERROR_NONE;
-}
-
-static int node_signal_received_cb(mmi_node_instance_h instance, mmi_signal_h signal)
-{
- _D("Node signal received callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-static int port_output_format_requested_cb(mmi_port_instance_h instance, const char *format) {
- _D("Port output format request callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-// TODO: It must be determined how to receive input data from the client
-static int port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data) {
- _D("Port input data callback is called for %p", instance);
- return MMI_ERROR_NONE;
-}
-
-extern "C" {
-
- EXPORT_API void mmi_plugin_module_get_node_list()
- {
- mmi_node_callbacks node_callbacks {
- node_initialized_cb,
- node_deinitialized_cb,
- node_attribute_set_cb,
- node_activated_cb,
- node_deactivated_cb,
- node_signal_received_cb
- };
-
- mmi_port_callbacks audio_port_callbacks {
- port_output_format_requested_cb,
- port_input_data_received_cb
- };
-
- mmi_port_h mic_audio_port = nullptr;
- mmi_port_create(&mic_audio_port);
- mmi_port_set_name(mic_audio_port, "AUDIO");
- mmi_port_set_type(mic_audio_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(mic_audio_port, MMI_DATA_TYPE_AUDIO);
- mmi_port_set_callbacks(mic_audio_port, audio_port_callbacks);
-
- mmi_node_h mic_node = nullptr;
- mmi_standard_node_create_source(MMI_STANDARD_NODE_SOURCE_TYPE_MIC_AMBIENT, &mic_node);
- mmi_node_add_port(mic_node, mic_audio_port);
- mmi_node_set_callbacks(mic_node, node_callbacks);
-
- mmi_node_register(mic_node);
-
- mmi_node_destroy(mic_node);
- }
-
-} // extern "C"
+++ /dev/null
-mmi_module_regex_match_library_srcs = [
- 'mmi-module-regex-match.cpp',
- 'mmi-module-regex-match-regex-candidates.h',
- 'mmi-module-regex-match-regex-candidates.cpp',
- ]
-
-dlog_dep = dependency('dlog', method : 'pkg-config')
-ecore_dep = dependency('ecore', method : 'pkg-config')
-
-mmi_module_regex_match_deps = [
- mmi_declared_dep,
- dlog_dep,
- ecore_dep,
- ]
-
-mmi_module_regex_match_include_dirs = include_directories(
- '.',
- '../../../capi/',
- )
-
-mmi_module_regex_match_library = library('mmi_module_regex_match',
- mmi_module_regex_match_library_srcs,
- include_directories : [ mmi_module_regex_match_include_dirs ],
- dependencies : [mmi_module_regex_match_deps],
- install_dir : mmi_prefix_plugindir,
- install : true
- )
+++ /dev/null
-/*
- * Copyright (c) 2023 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 <mmi-log.h>
-
-#include "mmi-module-regex-match-regex-candidates.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-REGEX-MATCH"
-
-
-RegExCandidates::RegExCandidates()
-{
- _I("[REGEX MATCH] Construct RegExCandidates");
- m_candidates.clear();
-}
-
-RegExCandidates::~RegExCandidates()
-{
- _I("[REGEX MATCH] Destruct RegExCandidates");
- m_candidates.clear();
-}
-
-void RegExCandidates::append_candidate(const char *regex_name, const char *regex_pattern)
-{
- if (nullptr == regex_name ||nullptr == regex_pattern) {
- _W("[REGEX MATCH] Regex name or pattern is null. Skip appending");
- return;
- }
-
- _I("[REGEX MATCH] Append candidate(%s/%s)", regex_pattern, regex_name);
- m_candidates.push_back(std::make_pair(std::regex(regex_pattern), std::string(regex_name)));
- _D("[REGEX MATCH] The current number of candidates (%zu)", m_candidates.size());
-}
-
-std::optional<std::string> RegExCandidates::find_matched_candidate(const char *text)
-{
- if (nullptr == text) {
- _E("[REGEX MATCH] text is null.");
- return std::nullopt;
- }
-
- _I("[REGEX MATCH] Find matched candidate. text(%s)", text);
-
- try {
- for (auto &candidate : m_candidates) {
- auto ®ex = candidate.first;
- if (std::regex_match(text, regex)) {
- _I("Result : text(%s), result(%s)", text, candidate.second.c_str());
- return candidate.second;
- }
- }
- } catch (std::exception &e) {
- _E("Exception occurs. (%s)", e.what());
- return std::nullopt;
- }
-
- _E("[REGEX MATCH] There no matched candidate");
- return std::nullopt;
-}
-
-void RegExCandidates::clear_candidates()
-{
- _I("[REGEX MATCH] Clear current candidates");
- m_candidates.clear();
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_REGEX_MATCH_REGEX_CANDIDATES_H__
-#define __MMI_MODULE_REGEX_MATCH_REGEX_CANDIDATES_H__
-
-
-#include <vector>
-#include <string>
-#include <regex>
-#include <optional>
-
-class RegExCandidates {
-public:
- RegExCandidates();
- ~RegExCandidates();
-
- void append_candidate(const char *regex_name, const char *regex_pattern);
- std::optional<std::string> find_matched_candidate(const char *text);
- void clear_candidates();
-
-private:
- std::vector<std::pair<std::regex, std::string>> m_candidates;
-};
-
-#endif /* __MMI_MODULE_REGEX_MATCH_REGEX_CANDIDATES_H__ */
+++ /dev/null
-#include <mmi-attribute.h>
-#include <mmi-node.h>
-#include <mmi-node-logic.h>
-#include <mmi-log.h>
-
-#include <map>
-#include <memory>
-
-#include "mmi-module-regex-match-regex-candidates.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-REGEX-MATCH"
-
-
-static const char *INPUT_PORT_NAME_TEXT = "TEXT";
-static const char *OUTPUT_PORT_NAME_MATCHED_CANDIDATE = "MATCHED_CANDIDATE";
-static const char *OUTPUT_PORT_NAME_REJECTED = "REJECTED";
-static const char *ATTRIBUTE_NAME_CANDIDATES = "CANDIDATES";
-
-
-static std::map<mmi_node_instance_h, std::shared_ptr<RegExCandidates>> g_node_to_regex_candidates_map;
-static std::map<mmi_port_instance_h, mmi_node_instance_h> g_input_port_to_node_map;
-
-
-static int node_initialized_cb(mmi_node_instance_h instance)
-{
- _D("[REGEX MATCH] Node initialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[REGEX MATCH] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_port_instance_h input_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_IN, INPUT_PORT_NAME_TEXT, &input_port);
- if (nullptr == input_port) {
- _E("[REGEX MATCH] Fail to get port from node. %p", instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- g_input_port_to_node_map[input_port] = instance;
-
- try {
- auto text_candidates = std::make_shared<RegExCandidates>();
- g_node_to_regex_candidates_map[instance] = text_candidates;
- } catch (std::bad_alloc &e) {
- _E("[REGEX MATCH] Fail to allocate memory for node instance. %p", instance);
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static bool is_node_instance_valid(mmi_node_instance_h instance)
-{
- if (nullptr == instance) {
- _E("[REGEX MATCH] Node instance is null %p", instance);
- return false;
- }
-
- auto iterator = g_node_to_regex_candidates_map.find(instance);
- if (iterator == g_node_to_regex_candidates_map.end()) {
- _E("[REGEX MATCH] No instance %p", instance);
- return false;
- }
-
- return true;
-}
-
-static int node_deinitialized_cb(mmi_node_instance_h instance)
-{
- _D("[REGEX MATCH] Node deinitialize callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[REGEX MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_port_instance_h input_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_IN, INPUT_PORT_NAME_TEXT, &input_port);
- if (nullptr == input_port) {
- _E("[REGEX MATCH] Fail to get port from node. %p", instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- g_input_port_to_node_map.erase(input_port);
- g_node_to_regex_candidates_map.erase(instance);
-
- return MMI_ERROR_NONE;
-}
-
-static int node_attribute_set_cb(mmi_node_instance_h instance, mmi_attribute_h attribute)
-{
- _D("[REGEX MATCH] Node attribute set callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[REGEX MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- char *name = nullptr;
- mmi_attribute_get_name(attribute, &name);
- if (nullptr == name) {
- _E("[REGEX MATCH] Fail to get attribute name");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- std::string attribute_name(name);
- free(name);
- name = nullptr;
-
- if (0 != attribute_name.compare(ATTRIBUTE_NAME_CANDIDATES)) {
- _E("[REGEX MATCH] Attribute name is not same as expected one. (%s)", attribute_name.c_str());
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_primitive_value_h value = nullptr;
- mmi_primitive_value_type_e type = MMI_PRIMITIVE_VALUE_TYPE_INT;
- mmi_attribute_get_value(attribute, &value);
- mmi_primitive_value_get_type(value, &type);
- if (MMI_PRIMITIVE_VALUE_TYPE_STRING != type) {
- mmi_primitive_value_destroy(value);
- _E("[REGEX MATCH] Invalid type of attribute : %d", type);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- // TODO: Check the efficient way to set attribute for regex candidates.
- size_t count = 0;
- mmi_primitive_value_get_array_count(value, &count);
-
- auto regex_candidates = g_node_to_regex_candidates_map[instance];
- regex_candidates->clear_candidates();
-
- for (size_t i = 0; i < count; i += 2) {
- mmi_primitive_value_h regex_name = nullptr;
- mmi_primitive_value_get_array_element(value, i, ®ex_name);
-
- mmi_primitive_value_h regex_pattern = nullptr;
- mmi_primitive_value_get_array_element(value, i + 1, ®ex_pattern);
-
- const char *regex_name_value = nullptr;
- mmi_primitive_value_get_string(regex_name, ®ex_name_value);
-
- const char *regex_pattern_value = nullptr;
- mmi_primitive_value_get_string(regex_pattern, ®ex_pattern_value);
-
- if (nullptr != regex_name_value && nullptr != regex_pattern_value) {
- _D("[REGEX MATCH] Attribute value : %zu, %s, %s", i, regex_name_value, regex_pattern_value);
- regex_candidates->append_candidate(regex_name_value, regex_pattern_value);
- } else {
- _W("[REGEX MATCH] Fail to get string. Please check error. index(%zu)", i);
- }
- }
- mmi_primitive_value_destroy(value);
-
- return MMI_ERROR_NONE;
-}
-
-static int node_activated_cb(mmi_node_instance_h instance)
-{
- _D("[REGEX MATCH] Node activate callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[REGEX MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deactivated_cb(mmi_node_instance_h instance)
-{
- _D("[REGEX MATCH] Node deactivate callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[REGEX MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_signal_received_cb(mmi_node_instance_h instance, mmi_signal_h signal)
-{
- _D("[REGEX MATCH] Node signal received callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[REGEX MATCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int port_output_format_requested_cb(mmi_port_instance_h instance, const char *format)
-{
- _D("[REGEX MATCH] Port output format request callback is called for %p", instance);
-
- return MMI_ERROR_NONE;
-}
-
-static int generate_output(mmi_node_instance_h instance, const char *output_name, mmi_data_h data)
-{
- mmi_port_instance_h output_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, output_name, &output_port);
- if (nullptr == output_port) {
- _E("[REGEX MATCH] Fail to get output port. %p", instance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- int ret = mmi_port_instance_generate_output(output_port, data);
- if (MMI_ERROR_NONE != ret) {
- _E("[REGEX MATCH] Fail to generate output. error(%d / %s)", ret, get_error_message(ret));
- return ret;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data)
-{
- _D("[REGEX MATCH] Text input data callback is called: %p", instance);
- auto iterator = g_input_port_to_node_map.find(instance);
- if (iterator == g_input_port_to_node_map.end()) {
- _E("[REGEX MATCH] Fail to find proper node instance. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- auto node_instance = iterator->second;
- if (false == is_node_instance_valid(node_instance)) {
- _E("[REGEX MATCH] Node instance is not valid. %p", node_instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- const char *text = nullptr;
- mmi_data_get_text(data, &text);
- if (nullptr == text) {
- _E("[REGEX MATCH] Fail to get text from data");
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- int ret = MMI_ERROR_NONE;
- auto text_candidates = g_node_to_regex_candidates_map[node_instance];
- auto result = text_candidates->find_matched_candidate(text);
- if (result) {
- mmi_data_h matched_candidate = nullptr;
- mmi_data_create_text(result->c_str(), &matched_candidate);
- ret = generate_output(node_instance, OUTPUT_PORT_NAME_MATCHED_CANDIDATE, matched_candidate);
- mmi_data_destroy(matched_candidate);
- } else {
- ret = generate_output(node_instance, OUTPUT_PORT_NAME_REJECTED, data);
- }
-
- if (MMI_ERROR_NONE != ret) {
- _E("[REGEX MATCH] Fail to generate output");
- return ret;
- }
-
- return MMI_ERROR_NONE;
-}
-
-
-extern "C" {
-
- EXPORT_API void mmi_plugin_module_get_node_list()
- {
- mmi_node_callbacks node_callbacks {
- node_initialized_cb,
- node_deinitialized_cb,
- node_attribute_set_cb,
- node_activated_cb,
- node_deactivated_cb,
- node_signal_received_cb
- };
-
- mmi_port_callbacks text_port_callbacks {
- port_output_format_requested_cb,
- port_input_data_received_cb
- };
-
- mmi_port_h match_text_port = nullptr;
- mmi_port_create(&match_text_port);
- mmi_port_set_name(match_text_port, INPUT_PORT_NAME_TEXT);
- mmi_port_set_type(match_text_port, MMI_PORT_TYPE_IN);
- mmi_port_set_data_type(match_text_port, MMI_DATA_TYPE_TEXT);
- mmi_port_set_callbacks(match_text_port, text_port_callbacks);
-
- mmi_port_h match_candidate_port = nullptr;
- mmi_port_create(&match_candidate_port);
- mmi_port_set_name(match_candidate_port, OUTPUT_PORT_NAME_MATCHED_CANDIDATE);
- mmi_port_set_type(match_candidate_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(match_candidate_port, MMI_DATA_TYPE_TEXT);
-
- mmi_port_h match_rejected_port = nullptr;
- mmi_port_create(&match_rejected_port);
- mmi_port_set_name(match_rejected_port, OUTPUT_PORT_NAME_REJECTED);
- mmi_port_set_type(match_rejected_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(match_rejected_port, MMI_DATA_TYPE_TEXT);
- /* Callbacks for OUT ports are not needed for now */
-
- mmi_node_h match_node = nullptr;
- mmi_standard_node_create_logic(MMI_STANDARD_NODE_LOGIC_TYPE_REGEX_STRING_MATCH, &match_node);
- mmi_node_add_port(match_node, match_text_port);
- mmi_node_add_port(match_node, match_candidate_port);
- mmi_node_add_port(match_node, match_rejected_port);
- mmi_node_set_callbacks(match_node, node_callbacks);
- mmi_node_register(match_node);
-
- mmi_node_destroy(match_node);
- }
-
-} // extern "C"
+++ /dev/null
-mmi_module_node_voice_touch_library_srcs = [
- 'mmi-module-voice-touch.cpp',
- 'mmi-module-voice-touch-common.h',
- 'mmi-module-voice-touch-candidates.h',
- 'mmi-module-voice-touch-candidates.cpp',
- 'mmi-module-voice-touch-string-utility.h',
- 'mmi-module-voice-touch-string-utility.cpp',
- 'mmi-module-voice-touch-screen-info.h',
- 'mmi-module-voice-touch-screen-info.cpp',
- 'mmi-module-voice-touch-data-utility.h',
- 'mmi-module-voice-touch-data-utility.cpp',
- 'mmi-module-voice-touch-primitive-utility.h',
- 'mmi-module-voice-touch-primitive-utility.cpp',
- ]
-
-dlog_dep = dependency('dlog', method : 'pkg-config')
-ecore_dep = dependency('ecore', method : 'pkg-config')
-
-mmi_module_node_voice_touch_deps = [
- mmi_declared_dep,
- dlog_dep,
- ecore_dep,
- ]
-
-mmi_module_node_voice_touch_include_dirs = include_directories(
- '.',
- '../../../capi/',
- )
-
-mmi_module_node_voice_touch_library = library('mmi_module_node_voice_touch',
- mmi_module_node_voice_touch_library_srcs,
- include_directories : [ mmi_module_node_voice_touch_include_dirs ],
- dependencies : [mmi_module_node_voice_touch_deps],
- install_dir : mmi_prefix_plugindir,
- install : true
- )
+++ /dev/null
-/*
- * Copyright (c) 2023 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 <mmi-log.h>
-
-#include <algorithm>
-#include <numeric>
-
-#include "mmi-module-voice-touch-candidates.h"
-#include "mmi-module-voice-touch-string-utility.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-VOICE-TOUCH"
-
-
-static constexpr double WORD_MATCHING_RATE = 0.3;
-static constexpr double CHAR_MATCHING_RATE = 0.35;
-static constexpr size_t MIN_WORD_SIZE = 3;
-
-
-VoiceTouchCandidates::VoiceTouchCandidates()
-{
- _I("[VOICE TOUCH] Construct VoiceTouchCandidates");
- m_candidates.clear();
-}
-
-VoiceTouchCandidates::~VoiceTouchCandidates()
-{
- _I("[VOICE TOUCH] Destruct VoiceTouchCandidates");
- m_candidates.clear();
-}
-
-void VoiceTouchCandidates::set_candidates(const std::vector<voice_touch_candidate_s> &candidates)
-{
- _I("[VOICE TOUCH] Set candidates(%zu)", candidates.size());
- m_candidates.clear();
- m_candidates = candidates;
- _D("[VOICE TOUCH] The current number of candidates (%zu)", m_candidates.size());
-}
-
-std::optional<voice_touch_candidate_s> VoiceTouchCandidates::find_matched_candidate(size_t index)
-{
- _I("[VOICE TOUCH] Find matched candidate. index(%zu)", index);
- std::optional<voice_touch_candidate_s> result = find_matched_candidate_by_index(index);
- if (result) {
- _I("[VOICE TOUCH] Success To find voice touch candidate(%zu)", index);
- return result;
- }
-
- return std::nullopt;
-}
-
-std::optional<voice_touch_candidate_s> VoiceTouchCandidates::find_matched_candidate_by_index(size_t index)
-{
- _I("[VOICE TOUCH] Find matched candidate by index (%zu)", index);
-
- if (index > m_candidates.size()) {
- _E("[VOICE TOUCH] Invalid index. %zu", index);
- return std::nullopt;
- }
-
- for (auto &candidate : m_candidates) {
- if (candidate.index == index) {
- _I("[VOICE TOUCH] result candidate(%s)", candidate.label.c_str());
- return candidate;
- }
- }
-
- return std::nullopt;
-}
-
-std::optional<voice_touch_candidate_s> VoiceTouchCandidates::find_matched_candidate(const char *text)
-{
- _I("[VOICE TOUCH] Find matched candidate. text(%s)", text);
- auto lower_cased_text = StringUtility::make_lower_case(std::string(text));
- auto splited_text = StringUtility::split_text(lower_cased_text, ' ');
-
- std::optional<voice_touch_candidate_s> result;
- result = find_matched_candidate_by_text(splited_text);
- if (result) {
- _I("[VOICE TOUCH] Success To find voice touch candidate(%s)", text);
- return result;
- }
-
- result = find_matched_candidate_by_word(splited_text);
- if (result) {
- _I("[VOICE TOUCH] Success To find voice touch candidate(%s)", text);
- return result;
- }
-
- result = find_matched_candidate_by_char(splited_text);
- if (result) {
- _I("[VOICE TOUCH] Success To find voice touch candidate(%s)", text);
- return result;
- }
-
- _I("[VOICE TOUCH] There is no matched candidate by text. Try to find by index. text(%s)", text);
- size_t index = 0;
- try {
- index = std::stoull(lower_cased_text);
- } catch (std::exception &e) {
- _E("[VOICE TOUCH] Fail string to int conversion. (%s)", e.what());
- return std::nullopt;
- }
-
- result = find_matched_candidate_by_index(index);
- if (result) {
- _I("[VOICE TOUCH] Success To find voice touch candidate(%zu)", index);
- return result;
- }
-
- return std::nullopt;
-}
-
-std::optional<voice_touch_candidate_s> VoiceTouchCandidates::find_matched_candidate_by_text(const std::vector<std::string> &splited_text)
-{
- _I("[VOICE TOUCH] Find matched candidate by full text.");
-
- for (auto &candidate : m_candidates) {
- std::string label = StringUtility::make_lower_case(candidate.label);
-
- bool is_valid = true;
- for (auto &word : splited_text) {
- if (label.find(word) == std::string::npos) {
- is_valid = false;
- break;
- }
- }
-
- if (is_valid) {
- _I("[VOICE TOUCH] Success To find voice touch candidate(%s)", candidate.label.c_str());
- return candidate;
- }
- }
-
- return std::nullopt;
-}
-
-std::optional<voice_touch_candidate_s> VoiceTouchCandidates::find_matched_candidate_by_word(const std::vector<std::string> &splited_text)
-{
- _I("[VOICE TOUCH] Find matched candidate by word.");
-
- size_t max_matching_word_num = static_cast<size_t>(splited_text.size() * WORD_MATCHING_RATE);
- if (0 == max_matching_word_num) {
- max_matching_word_num = 1;
- }
- _I("[VOICE TOUCH] Threshold of matching word number (%zu)", max_matching_word_num);
-
- std::optional<voice_touch_candidate_s> result;
- for (auto &candidate : m_candidates) {
- std::string label = StringUtility::make_lower_case(candidate.label);
-
- size_t matching_word_num = 0;
- for (auto &word : splited_text) {
- if (label.find(word) != std::string::npos) {
- matching_word_num++;
- }
- }
-
- if (matching_word_num >= max_matching_word_num) {
- max_matching_word_num = matching_word_num;
- result = candidate;
- }
- }
-
- if (result) {
- _I("[VOICE TOUCH] Success To find voice touch candidate which has highest matching rate(%s)", result->label.c_str());
- return result;
- }
-
- return std::nullopt;
-}
-
-std::optional<voice_touch_candidate_s> VoiceTouchCandidates::find_matched_candidate_by_char(const std::vector<std::string> &splited_text)
-{
- _I("[VOICE TOUCH] Find matched candidate by character.");
-
- auto filter_splited_text = [](std::string x) -> bool {
- return x.size() >= MIN_WORD_SIZE;
- };
- std::vector<std::string> filtered_words;
- std::copy_if(splited_text.begin(), splited_text.end(), std::back_inserter(filtered_words), filter_splited_text);
-
- // TODO: Current algorithm doesn't consider the original order of the words. It can affect the total score.
- std::optional<voice_touch_candidate_s> result;
- size_t result_score = std::numeric_limits<size_t>::max();
- for (auto &candidate : m_candidates) {
- auto candidate_label = StringUtility::make_lower_case(candidate.label);
- auto candidate_words = StringUtility::split_text(candidate_label, ' ');
-
- std::vector<std::string> filtered_candidate_words;
- std::copy_if(candidate_words.begin(), candidate_words.end(), std::back_inserter(filtered_candidate_words), filter_splited_text);
- _D("[VOICE TOUCH] candidate(%s)", candidate_label.c_str());
-
- size_t score = 0;
- for (auto &word : filtered_words) {
- const size_t MIN_THRESHOLD = static_cast<size_t>(word.size() * CHAR_MATCHING_RATE) + 1;
- size_t min_score = MIN_THRESHOLD;
- _D("[VOICE TOUCH] Minimum matching character number (%zu)", MIN_THRESHOLD);
-
- for (auto &candidate_word : filtered_candidate_words) {
- size_t edit_distance = calcualte_edit_distance(candidate_word, word);
-
- if (min_score > edit_distance) {
- min_score = edit_distance;
- }
- }
-
- score += (min_score < MIN_THRESHOLD ? min_score : word.size());
- _D("[VOICE TOUCH] word(%s), label word(%s), minscore(%zu), score(%zu)", word.c_str(), candidate_label.c_str(), min_score, score);
- }
-
- _D("[VOICE TOUCH] result score(%zu), score(%zu)", result_score, score);
- if (result_score > score) {
- result_score = score;
- result = candidate;
- }
- }
-
- auto accumulate_size = [](size_t sum, std::string word) -> size_t
- {
- return sum + word.size();
- };
- size_t threshold = std::accumulate(filtered_words.begin(), filtered_words.end(), static_cast<size_t>(0), accumulate_size);
- if (threshold > result_score) {
- _I("[VOICE TOUCH] result candidate(%s)", result->label.c_str());
- return result;
- }
-
- return std::nullopt;
-}
-
-size_t VoiceTouchCandidates::calcualte_edit_distance(const std::string &text1, const std::string &text2)
-{
- // INFO: This is for calculating Levenshtein distance(a.k.a edit distance) as similarity matric.
- std::string long_str;
- std::string short_str;
- if (text1.size() > text2.size()) {
- long_str = text1;
- short_str = text2;
- } else {
- long_str = text2;
- short_str = text1;
- }
-
- size_t long_str_size = long_str.size();
- size_t short_str_size = short_str.size();
-
- size_t cost_array1[long_str_size + 1]{};
- size_t cost_array2[long_str_size + 1]{};
-
- size_t *cost = cost_array1;
- size_t *ncost = cost_array2;
-
- for (size_t l = 0; l <= long_str_size; l++) {
- cost[l] = l;
- }
-
- for (size_t s = 1; s <= short_str_size; s++) {
- ncost[0] = s;
-
- for (size_t l = 1; l <= long_str_size; l++) {
- size_t match = (short_str[s - 1] == long_str[l - 1] ? 0 : 1);
-
- size_t rep = cost[l - 1] + match;
- size_t ins = cost[l] + 1;
- size_t del = ncost[l - 1] + 1;
-
- ncost[l] = std::min({rep, ins, del});
- }
-
- std::swap(ncost, cost);
- }
-
- return cost[long_str_size];
-}
-
-void VoiceTouchCandidates::clear_candidates()
-{
- _I("[VOICE TOUCH] Clear current candidates");
- m_candidates.clear();
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_VOICE_TOUCH_CANDIDATES_H__
-#define __MMI_MODULE_VOICE_TOUCH_CANDIDATES_H__
-
-
-#include <vector>
-#include <string>
-#include <functional>
-#include <optional>
-
-#include "mmi-module-voice-touch-common.h"
-
-
-class VoiceTouchCandidates {
-public:
- VoiceTouchCandidates();
- ~VoiceTouchCandidates();
-
- void set_candidates(const std::vector<voice_touch_candidate_s> &candidates);
- std::optional<voice_touch_candidate_s> find_matched_candidate(size_t index);
- std::optional<voice_touch_candidate_s> find_matched_candidate(const char *text);
- void clear_candidates();
-
-private:
- std::optional<voice_touch_candidate_s> find_matched_candidate_by_index(size_t index);
- std::optional<voice_touch_candidate_s> find_matched_candidate_by_text(const std::vector<std::string> &splited_text);
- std::optional<voice_touch_candidate_s> find_matched_candidate_by_word(const std::vector<std::string> &splited_text);
- std::optional<voice_touch_candidate_s> find_matched_candidate_by_char(const std::vector<std::string> &splited_text);
- size_t calcualte_edit_distance(const std::string &text1, const std::string &text2);
-
-private:
- std::vector<voice_touch_candidate_s> m_candidates;
-};
-
-#endif /* __MMI_MODULE_VOICE_TOUCH_CANDIDATES_H__ */
+++ /dev/null
-
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_VOICE_TOUCH_COMMON_H__
-#define __MMI_MODULE_VOICE_TOUCH_COMMON_H__
-
-
-#include <string>
-
-
-enum voice_touch_mode_e {
- VOICE_TOUCH_MODE_TEXT,
- VOICE_TOUCH_MODE_INDEX,
- VOICE_TOUCH_MODE_GRID
-};
-
-struct area_coordinates_s {
- int x{};
- int y{};
- int w{};
- int h{};
-};
-
-struct voice_touch_candidate_s {
- voice_touch_mode_e mode{VOICE_TOUCH_MODE_TEXT};
- area_coordinates_s candidate_area{};
- size_t index{};
- std::string object_id{};
- std::string label{};
-};
-
-struct screen_element_s {
- area_coordinates_s element_area{};
- std::string object_id{};
- std::string label{};
- std::string role{};
-};
-
-struct grid_information_s {
- size_t col_count{};
- size_t row_count{};
-};
-
-
-#endif /* __MMI_MODULE_VOICE_TOUCH_COMMON_H__ */
+++ /dev/null
-/*
- * Copyright (c) 2022 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 <mmi-error.h>
-#include <mmi-log.h>
-
-#include "mmi-module-voice-touch-data-utility.h"
-
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-VOICE-TOUCH"
-
-#define NAME_OF_VARIABLE(x) (#x)
-
-
-MmiDataHelper::MmiDataHelper(mmi_data_h data, bool ownership) noexcept
-{
- _I("[VOICE TOUCH] Construct helper class for wrapping existing data(%p). ownership(%s)", data, ownership ? "True" : "False");
- m_handle = data;
- m_ownership = ownership;
-}
-
-MmiDataHelper::MmiDataHelper(const std::vector<voice_touch_candidate_s> &candidates) noexcept
-{
- _I("[VOICE TOUCH] Construct helper class for candidates output data");
- m_handle = make_internal_mmi_data(candidates);
- m_ownership = true;
-}
-
-MmiDataHelper::MmiDataHelper(const voice_touch_candidate_s &candidate, const screen_element_s &element) noexcept
-{
- _I("[VOICE TOUCH] Construct helper class for matched result output data");
- m_handle = make_internal_mmi_data(candidate, element);
- m_ownership = true;
-}
-
-MmiDataHelper::MmiDataHelper(const char *text) noexcept
-{
- _I("[VOICE TOUCH] Construct helper class for rejected output data");
- m_handle = make_internal_mmi_data(text);
- m_ownership = true;
-}
-
-MmiDataHelper::~MmiDataHelper()
-{
- if (m_ownership) {
- mmi_data_destroy(m_handle);
- }
-}
-
-mmi_data_h MmiDataHelper::get_handle() const
-{
- return m_handle;
-}
-
-mmi_data_type_e MmiDataHelper::get_type() const
-{
- mmi_data_type_e type = MMI_DATA_TYPE_ANY;
- int ret = mmi_data_get_type(m_handle, &type);
- if (MMI_ERROR_NONE != ret) {
- _E("[VOICE TOUCH] Fail to get type. ret(%d)", ret);
- throw ret;
- }
-
- return type;
-}
-
-int MmiDataHelper::get_integer_struct_member(const char *name) const
-{
- mmi_data_h member_data = nullptr;
- mmi_data_get_struct_element(m_handle, name, &member_data);
-
- int value = 0;
- int ret = mmi_data_get_int(member_data, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- return value;
-}
-
-const char *MmiDataHelper::get_text_struct_member(const char *name) const
-{
- mmi_data_h member_data = nullptr;
- mmi_data_get_struct_element(m_handle, name, &member_data);
-
- const char *value = nullptr;
- int ret = mmi_data_get_text(member_data, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- return value;
-}
-
-size_t MmiDataHelper::get_array_count() const
-{
- _I("[VOICE TOUCH] Get integer value from handle.");
- size_t value = 0;
- int ret = mmi_data_get_array_count(m_handle, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- return value;
-}
-
-MmiDataHelper MmiDataHelper::get_array_element(size_t index) const
-{
- _I("[VOICE TOUCH] Get array element on index(%zu) from handle.", index);
- mmi_data_h value = nullptr;
- int ret = mmi_data_get_array_element(m_handle, index, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- if (nullptr == value) {
- throw MMI_ERROR_OPERATION_FAILED;
- }
-
- return MmiDataHelper(value);
-}
-
-mmi_data_h MmiDataHelper::make_internal_mmi_data(const std::vector<voice_touch_candidate_s> &candidates)
-{
- mmi_data_h output_data = nullptr;
- mmi_data_create_array(&output_data);
- if (nullptr == output_data) {
- _E("[VOICE TOUCH] Fail to allocate memory for output");
- return nullptr;
- }
-
- for (auto &candidate : candidates) {
- mmi_data_h candidate_info = nullptr;
- mmi_data_create_struct(&candidate_info);
- if (nullptr == output_data) {
- _E("[VOICE TOUCH] Fail to allocate memory for output");
- mmi_data_destroy(output_data);
- return nullptr;
- }
-
- set_integer_struct_member(candidate_info, "mode", candidate.mode);
- set_integer_struct_member(candidate_info, "coord_x", candidate.candidate_area.x);
- set_integer_struct_member(candidate_info, "coord_y", candidate.candidate_area.y);
- set_integer_struct_member(candidate_info, "width", candidate.candidate_area.w);
- set_integer_struct_member(candidate_info, "height", candidate.candidate_area.h);
- set_text_struct_member(candidate_info, "label", candidate.label.c_str());
-
- mmi_data_add_array_element(output_data, candidate_info);
- }
-
- return output_data;
-}
-
-mmi_data_h MmiDataHelper::make_internal_mmi_data(const voice_touch_candidate_s &candidate, const screen_element_s &element)
-{
- mmi_data_h output_data = nullptr;
- mmi_data_h candidate_info = nullptr;
- mmi_data_h click_info = nullptr;
- mmi_data_create_struct(&output_data);
- mmi_data_create_struct(&candidate_info);
- mmi_data_create_struct(&click_info);
- if (nullptr == output_data || nullptr == candidate_info || nullptr == click_info) {
- mmi_data_destroy(output_data);
- mmi_data_destroy(candidate_info);
- mmi_data_destroy(click_info);
- _E("[VOICE TOUCH] Fail to allocate memory for data.");
- return nullptr;
- }
-
- set_integer_struct_member(candidate_info, "mode", candidate.mode);
- set_integer_struct_member(candidate_info, "coord_x", candidate.candidate_area.x);
- set_integer_struct_member(candidate_info, "coord_y", candidate.candidate_area.y);
- set_integer_struct_member(candidate_info, "width", candidate.candidate_area.w);
- set_integer_struct_member(candidate_info, "height", candidate.candidate_area.h);
- set_text_struct_member(candidate_info, "label", candidate.label.c_str());
-
- auto &element_area = element.element_area;
- set_integer_struct_member(click_info, "x", element_area.x + element_area.w / 2);
- set_integer_struct_member(click_info, "y", element_area.y + element_area.h / 2);
- set_text_struct_member(click_info, "object_id", element.object_id.c_str());
-
- mmi_data_set_struct_element(output_data, NAME_OF_VARIABLE(candidate_info), candidate_info);
- mmi_data_set_struct_element(output_data, NAME_OF_VARIABLE(click_info), click_info);
-
- return output_data;
-}
-
-mmi_data_h MmiDataHelper::make_internal_mmi_data(const char *text)
-{
- mmi_data_h output_data = nullptr;
- mmi_data_create_text(text, &output_data);
- if (nullptr == output_data) {
- _E("[VOICE TOUCH] Fail to allocate memory for output");
- return nullptr;
- }
-
- return output_data;
-}
-
-void MmiDataHelper::set_integer_struct_member(mmi_data_h struct_data, const char *member_name, int value)
-{
- mmi_data_h member_data = nullptr;
- mmi_data_create_int(value, &member_data);
- if (nullptr == member_data) {
- _E("[VOICE TOUCH] Fail to allocate memory for data.");
- return;
- }
-
- if (MMI_ERROR_NONE != mmi_data_set_struct_element(struct_data, member_name, member_data)) {
- _E("[VOICE TOUCH] Fail to set struct integer type member. name(%s). value(%d)", member_name, value);
- mmi_data_destroy(member_data);
- }
-}
-
-void MmiDataHelper::set_text_struct_member(mmi_data_h struct_data, const char *member_name, const char *value)
-{
- mmi_data_h member_data = nullptr;
- mmi_data_create_text(value, &member_data);
- if (nullptr == member_data) {
- _E("[VOICE TOUCH] Fail to allocate memory for data.");
- return;
- }
-
- if (MMI_ERROR_NONE != mmi_data_set_struct_element(struct_data, member_name, member_data)) {
- _E("[VOICE TOUCH] Fail to set struct text type member. name(%s). value(%s)", member_name, value);
- mmi_data_destroy(member_data);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_VOICE_TOUCH_DATA_UTILITY_H__
-#define __MMI_MODULE_VOICE_TOUCH_DATA_UTILITY_H__
-
-
-#include <vector>
-
-#include <mmi-data.h>
-#include "mmi-module-voice-touch-common.h"
-
-class MmiDataHelper {
-public:
- MmiDataHelper(mmi_data_h data, bool ownership = false) noexcept;
- MmiDataHelper(const std::vector<voice_touch_candidate_s> &candidates) noexcept;
- MmiDataHelper(const voice_touch_candidate_s &candidate, const screen_element_s &element) noexcept;
- MmiDataHelper(const char *text) noexcept;
- ~MmiDataHelper();
-
- // For common
- mmi_data_h get_handle() const;
- mmi_data_type_e get_type() const;
-
- // For struct type
- int get_integer_struct_member(const char *name) const;
- const char *get_text_struct_member(const char *name) const;
-
- // For array type
- size_t get_array_count() const;
- MmiDataHelper get_array_element(size_t index) const;
-
-private:
- mmi_data_h make_internal_mmi_data(const std::vector<voice_touch_candidate_s> &candidates);
- mmi_data_h make_internal_mmi_data(const voice_touch_candidate_s &candidate, const screen_element_s &element);
- mmi_data_h make_internal_mmi_data(const char *text);
-
- void set_integer_struct_member(mmi_data_h struct_data, const char *member_name, int value);
- void set_text_struct_member(mmi_data_h struct_data, const char *member_name, const char *value);
-
-private:
- mmi_data_h m_handle;
- bool m_ownership;
-};
-
-#endif /* __MMI_MODULE_VOICE_TOUCH_DATA_UTILITY_H__ */
+++ /dev/null
-/*
- * Copyright (c) 2022 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 <mmi-error.h>
-#include <mmi-log.h>
-
-#include "mmi-module-voice-touch-primitive-utility.h"
-
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-VOICE-TOUCH"
-
-
-MmiPrimitiveHelper::MmiPrimitiveHelper(mmi_primitive_value_h handle, bool ownership) noexcept
-{
- _I("[VOICE TOUCH] Construct helper class for primitive value handle");
- m_handle = handle;
- m_ownership = ownership;
-}
-
-MmiPrimitiveHelper::~MmiPrimitiveHelper()
-{
- _I("[VOICE TOUCH] Destruct helper class for primitive value handle");
- if (m_ownership) {
- mmi_primitive_value_destroy(m_handle);
- }
-}
-
-mmi_primitive_value_h MmiPrimitiveHelper::get_handle() const
-{
- _I("[VOICE TOUCH] Get raw primitive value handle. (%p)", m_handle);
- return m_handle;
-}
-
-mmi_primitive_value_type_e MmiPrimitiveHelper::get_type() const
-{
- _I("[VOICE TOUCH] Get type from handle.");
- mmi_primitive_value_type_e type = MMI_PRIMITIVE_VALUE_TYPE_BOOL;
- int ret = mmi_primitive_value_get_type(m_handle, &type);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- return type;
-}
-
-int MmiPrimitiveHelper::get_integer_value() const
-{
- _I("[VOICE TOUCH] Get integer value from handle.");
- int value = -1;
- int ret = mmi_primitive_value_get_int(m_handle, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- return value;
-}
-
-size_t MmiPrimitiveHelper::get_array_count() const
-{
- _I("[VOICE TOUCH] Get integer value from handle.");
- size_t value = 0;
- int ret = mmi_primitive_value_get_array_count(m_handle, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- return value;
-}
-
-MmiPrimitiveHelper MmiPrimitiveHelper::get_array_element(size_t index) const
-{
- _I("[VOICE TOUCH] Get array element on index(%zu) from handle.", index);
- mmi_primitive_value_h value = nullptr;
- int ret = mmi_primitive_value_get_array_element(m_handle, index, &value);
- if (MMI_ERROR_NONE != ret) {
- throw ret;
- }
-
- if (nullptr == value) {
- throw MMI_ERROR_OPERATION_FAILED;
- }
-
- return MmiPrimitiveHelper(value);
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_VOICE_TOUCH_PRIMITIVE_UTILITY_H__
-#define __MMI_MODULE_VOICE_TOUCH_PRIMITIVE_UTILITY_H__
-
-
-#include <mmi-primitive-value.h>
-
-class MmiPrimitiveHelper {
-public:
- MmiPrimitiveHelper(mmi_primitive_value_h handle, bool ownership = false) noexcept;
- ~MmiPrimitiveHelper();
-
- // For common
- mmi_primitive_value_h get_handle() const;
- mmi_primitive_value_type_e get_type() const;
-
- // For integer value
- int get_integer_value() const;
-
- // For array value
- size_t get_array_count() const;
- MmiPrimitiveHelper get_array_element(size_t index) const;
-
-private:
-
-private:
- mmi_primitive_value_h m_handle;
- bool m_ownership;
-};
-
-#endif /* __MMI_MODULE_VOICE_TOUCH_PRIMITIVE_UTILITY_H__ */
+++ /dev/null
-/*
- * Copyright (c) 2023 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 <mmi-log.h>
-#include <mmi-error.h>
-
-#include <algorithm>
-#include <numeric>
-
-#include "mmi-module-voice-touch-screen-info.h"
-#include "mmi-module-voice-touch-data-utility.h"
-
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-VOICE-TOUCH"
-
-
-static const double WORD_MATCHING_RATE = 0.3;
-static const double CHAR_MATCHING_RATE = 0.35;
-static const size_t MIN_WORD_SIZE = 3;
-
-
-ScreenElements::ScreenElements()
-{
- _I("[VOICE TOUCH] Construct ScreenElements");
- m_screen_width = 1920;
- m_screen_height = 1080;
- m_grid_depth = 0;
- m_parent_grid_area = {
- .x = 0,
- .y = 0,
- .w = m_screen_width,
- .h = m_screen_height
- };
-
- m_grid_informations.clear();
- m_grid_informations.push_back(grid_information_s{
- .col_count = 7,
- .row_count = 5
- });
- m_grid_informations.push_back(grid_information_s{
- .col_count = 4,
- .row_count = 3
- });
-
- m_screen_elements.clear();
-}
-
-ScreenElements::~ScreenElements()
-{
- _I("[VOICE TOUCH] Destruct ScreenElements");
- m_screen_width = 1920;
- m_screen_height = 1080;
- m_grid_depth = 0;
- m_parent_grid_area = {
- .x = 0,
- .y = 0,
- .w = m_screen_width,
- .h = m_screen_height
- };
- m_grid_informations.clear();
- m_screen_elements.clear();
-}
-
-void ScreenElements::set_screen_size(int width, int height)
-{
- _I("[VOICE TOUCH] Set screen size information. w(%d), h(%d)", width, height);
- m_screen_width = width;
- m_screen_height = height;
-}
-
-void ScreenElements::set_grid_informations(const std::vector<grid_information_s> &grid_informations)
-{
- _I("[VOICE TOUCH] Set grid information according to each depth. maximum depth(%zu)", grid_informations.size());
- m_grid_informations = grid_informations;
-}
-
-void ScreenElements::set_screen_elements(const MmiDataHelper &screen_elements)
-{
- _I("[VOICE TOUCH] Set screen elements from mmi data");
- try {
- size_t counts = screen_elements.get_array_count();
-
- m_screen_elements.clear();
- for (size_t i = 0; i < counts; i++) {
- auto element = screen_elements.get_array_element(i);
- m_screen_elements.push_back(make_screen_element(element));
- }
- } catch (mmi_error_e &error) {
- _E("[VOICE TOUCH] Fail to make screen element. (%d)", error);
- return;
- }
-
- _D("[VOICE TOUCH] The current number of elements (%zu)", m_screen_elements.size());
-}
-
-screen_element_s ScreenElements::make_screen_element(MmiDataHelper &data)
-{
- area_coordinates_s element_area{
- .x = data.get_integer_struct_member("coord_x"),
- .y = data.get_integer_struct_member("coord_y"),
- .w = data.get_integer_struct_member("width"),
- .h = data.get_integer_struct_member("height")
- };
-
- screen_element_s screen_element{
- .element_area = element_area,
- .object_id = std::string(data.get_text_struct_member("object_id")),
- .label = std::string(data.get_text_struct_member("label")),
- .role = std::string(data.get_text_struct_member("role"))
- };
-
- return screen_element;
-}
-
-void ScreenElements::set_grid_area(const area_coordinates_s &grid_area)
-{
- _I("[VOICE TOUCH] Set screen area information x(%d) / y(%d) / w(%d)/ h(%d)",
- grid_area.x, grid_area.y, grid_area.w, grid_area.h);
- m_parent_grid_area = grid_area;
-}
-
-void ScreenElements::increase_grid_depth()
-{
- m_grid_depth++;
- _I("[VOICE TOUCH] Increase current grid depth. (%zu)", m_grid_depth);
-}
-
-void ScreenElements::reset_grid_depth()
-{
- _I("[VOICE TOUCH] Reset current grid depth.");
- m_grid_depth = 0;
- m_parent_grid_area = area_coordinates_s{
- .x = 0,
- .y = 0,
- .w = m_screen_width,
- .h = m_screen_height
- };
-}
-
-bool ScreenElements::is_maximum_grid_depth()
-{
- bool result = (m_grid_depth == m_grid_informations.size());
- _I("[VOICE TOUCH] Check current grid depth reaches to maximum. current(%zu) / max(%zu). result(%s)",
- m_grid_depth, m_grid_informations.size(), result ? "True" : "False");
-
- return result;
-}
-
-std::vector<voice_touch_candidate_s> ScreenElements::make_voice_touch_candidates(voice_touch_mode_e mode)
-{
- _I("[VOICE TOUCH] Make voice touch candidates according to the mode. (%d)", mode);
- std::vector<voice_touch_candidate_s> candidates;
-
- switch (mode)
- {
- case VOICE_TOUCH_MODE_TEXT:
- fill_text_label_candidates(candidates);
- break;
-
- case VOICE_TOUCH_MODE_INDEX:
- fill_index_label_candidates(candidates);
- break;
-
- case VOICE_TOUCH_MODE_GRID:
- fill_grid_label_candidates(candidates);
- break;
-
- default:
- _E("[VOICE TOUCH] Invalid voice touch mode (%d)", mode);
- break;
- }
-
- return candidates;
-}
-
-void ScreenElements::fill_grid_label_candidates(std::vector<voice_touch_candidate_s> &candidates)
-{
- if (m_grid_depth >= m_grid_informations.size()) {
- _E("[VOICE TOUCH] Current grid depth is out of range (%zu) / (%zu)", m_grid_depth, m_grid_informations.size());
- return;
- }
-
- size_t col_count = m_grid_informations.at(m_grid_depth).col_count;
- size_t row_count = m_grid_informations.at(m_grid_depth).row_count;
-
- size_t grid_width = m_parent_grid_area.w / col_count;
- size_t grid_height = m_parent_grid_area.h / row_count;
-
- size_t remain_width = m_parent_grid_area.w % col_count;
- size_t remain_height = m_parent_grid_area.h % row_count;
-
- // TODO: Enhance the calculation to uniformly seperate the grid
- size_t index = 1;
- for (size_t y = 0; y < row_count; y++) {
- for (size_t x = 0; x < col_count; x++) {
- area_coordinates_s candidate_area{
- .x = static_cast<int>(m_parent_grid_area.x + (x * grid_width)),
- .y = static_cast<int>(m_parent_grid_area.y + (y * grid_height)),
- .w = static_cast<int>((x == col_count - 1 ? grid_width + remain_width : grid_width)),
- .h = static_cast<int>((y == row_count - 1 ? grid_height + remain_height : grid_height))
- };
-
- voice_touch_candidate_s candidate{
- .mode = VOICE_TOUCH_MODE_GRID,
- .candidate_area = candidate_area,
- .index = index,
- .object_id = std::string(),
- .label = std::to_string(index)
- };
-
- candidates.push_back(candidate);
- index++;
- }
- }
-}
-
-void ScreenElements::fill_index_label_candidates(std::vector<voice_touch_candidate_s> &candidates)
-{
- size_t index = 1;
- for (auto &element : m_screen_elements) {
- voice_touch_candidate_s candidate{
- .mode = VOICE_TOUCH_MODE_INDEX,
- .candidate_area = element.element_area,
- .index = index,
- .object_id = element.object_id,
- .label = std::to_string(index)
- };
-
- candidates.push_back(candidate);
- index++;
- }
-}
-
-void ScreenElements::fill_text_label_candidates(std::vector<voice_touch_candidate_s> &candidates)
-{
- size_t index = 1;
- for (auto &element : m_screen_elements) {
- voice_touch_candidate_s candidate{
- .mode = VOICE_TOUCH_MODE_TEXT,
- .candidate_area = element.element_area,
- .index = index,
- .object_id = element.object_id,
- .label = (element.label.empty() ? std::to_string(index) : element.label)
- };
-
- candidates.push_back(candidate);
- index++;
- }
-}
-
-std::optional<screen_element_s> ScreenElements::find_related_screen_element(const voice_touch_candidate_s &candidate)
-{
- switch (candidate.mode)
- {
- case VOICE_TOUCH_MODE_TEXT:
- case VOICE_TOUCH_MODE_INDEX:
- return find_exact_element_by_object_id(candidate.object_id);
-
- case VOICE_TOUCH_MODE_GRID:
- return find_best_element_in_grid(candidate.candidate_area);
-
- default:
- _E("[VOICE TOUCH] Invalid voice touch mode (%d)", candidate.mode);
- break;
- }
-
- return std::nullopt;
-}
-
-std::optional<screen_element_s> ScreenElements::find_exact_element_by_object_id(const std::string &object_id)
-{
- auto is_same_element = [object_id](const screen_element_s &element) -> bool {
- return element.object_id == object_id;
- };
-
- auto result = std::find_if(m_screen_elements.begin(), m_screen_elements.end(), is_same_element);
- if (result == m_screen_elements.end()) {
- _E("[VOICE TOUCH] No candidates which has object id(%s)", object_id.c_str());
- return std::nullopt;
- }
-
- _I("[VOICE TOUCH] Result. object Id(%s)", object_id.c_str());
- return *result;
-}
-
-std::optional<screen_element_s> ScreenElements::find_best_element_in_grid(const area_coordinates_s &grid_area)
-{
- int grid_x1 = grid_area.x;
- int grid_x2 = grid_area.x + grid_area.w;
- int grid_y1 = grid_area.y;
- int grid_y2 = grid_area.y + grid_area.h;
-
- auto is_in_area = [grid_x1, grid_x2, grid_y1, grid_y2](const screen_element_s &element) -> bool {
- auto &area = element.element_area;
- if (area.x >= grid_x2 || area.x + area.w <= grid_x1 || area.y > grid_y2 || area.y + area.h <= grid_y1) {
- return false;
- }
-
- return true;
- };
-
- std::vector<screen_element_s> filtered_elements;
- std::copy_if(m_screen_elements.begin(), m_screen_elements.end(), std::back_inserter(filtered_elements), is_in_area);
- if (filtered_elements.empty()) {
- _E("[VOICE TOUCH] No candidates in grid (%d, %d / %d, %d)", grid_x1, grid_y1, grid_x2, grid_y2);
- return std::nullopt;
- }
-
- std::optional<screen_element_s> result;
- int maximum_area_size = -1;
- for (auto &element : filtered_elements) {
- auto &area = element.element_area;
- int dx = std::min(grid_x2, area.x + area.w) - std::max(grid_x1, area.x);
- int dy = std::min(grid_y2, area.y + area.h) - std::max(grid_y1, area.y);
-
- int area_size = dx * dy;
- if (maximum_area_size < area_size) {
- maximum_area_size = area_size;
- result = element;
- }
- }
-
- _I("[VOICE TOUCH] Result. object Id(%s)", result->object_id.c_str());
- return result;
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_VOICE_TOUCH_SCREEN_INFO_H__
-#define __MMI_MODULE_VOICE_TOUCH_SCREEN_INFO_H__
-
-
-#include <vector>
-#include <string>
-#include <functional>
-#include <optional>
-
-#include "mmi-module-voice-touch-common.h"
-#include "mmi-module-voice-touch-data-utility.h"
-
-
-class ScreenElements {
-public:
- ScreenElements();
- ~ScreenElements();
-
- void set_screen_size(int width, int height);
- void set_grid_informations(const std::vector<grid_information_s> &grid_informations);
- void set_screen_elements(const MmiDataHelper &screen_elements);
- void set_grid_area(const area_coordinates_s &grid_area);
-
- void increase_grid_depth();
- void reset_grid_depth();
- bool is_maximum_grid_depth();
-
- std::vector<voice_touch_candidate_s> make_voice_touch_candidates(voice_touch_mode_e mode);
- std::optional<screen_element_s> find_related_screen_element(const voice_touch_candidate_s &candidate);
-
-private:
- screen_element_s make_screen_element(MmiDataHelper &data);
-
- void fill_grid_label_candidates(std::vector<voice_touch_candidate_s> &candidates);
- void fill_index_label_candidates(std::vector<voice_touch_candidate_s> &candidates);
- void fill_text_label_candidates(std::vector<voice_touch_candidate_s> &candidates);
-
- std::optional<screen_element_s> find_exact_element_by_object_id(const std::string &object_id);
- std::optional<screen_element_s> find_best_element_in_grid(const area_coordinates_s &grid_area);
-
-private:
- // Screen information
- int m_screen_width;
- int m_screen_height;
-
- // Grid information
- std::vector<grid_information_s> m_grid_informations;
- area_coordinates_s m_parent_grid_area;
- size_t m_grid_depth;
-
- // Current screen elements
- std::vector<screen_element_s> m_screen_elements;
-};
-
-#endif /* __MMI_MODULE_VOICE_TOUCH_SCREEN_INFO_H__ */
+++ /dev/null
-/*
- * Copyright (c) 2022 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 <algorithm>
-#include <sstream>
-
-#include "mmi-module-voice-touch-string-utility.h"
-
-
-std::string StringUtility::make_lower_case(std::string text)
-{
- transform(text.begin(), text.end(), text.begin(), ::tolower);
- return text;
-}
-
-std::vector<std::string> StringUtility::split_text(std::string text, char delimiter)
-{
- std::vector<std::string> result;
- std::istringstream ss{text};
- std::string temp;
-
- while (getline(ss, temp, delimiter)) {
- result.push_back(temp);
- }
-
- return result;
-}
+++ /dev/null
-/*
- * Copyright (c) 2023 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 __MMI_MODULE_VOICE_TOUCH_STRING_UTILITY_H__
-#define __MMI_MODULE_VOICE_TOUCH_STRING_UTILITY_H__
-
-
-#include <vector>
-#include <string>
-
-class StringUtility {
-public:
- static std::string make_lower_case(std::string text);
- static std::vector<std::string> split_text(std::string text, char delimeter);
-};
-
-#endif /* __MMI_MODULE_VOICE_TOUCH_STRING_UTILITY_H__ */
+++ /dev/null
-#include <mmi-attribute.h>
-#include <mmi-node.h>
-#include <mmi-node-processor.h>
-#include <mmi-log.h>
-
-#include <map>
-#include <memory>
-
-#include "mmi-module-voice-touch-candidates.h"
-#include "mmi-module-voice-touch-screen-info.h"
-#include "mmi-module-voice-touch-data-utility.h"
-#include "mmi-module-voice-touch-primitive-utility.h"
-
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "MMI-MODULE-VOICE-TOUCH"
-
-
-struct voice_touch_helper_s
-{
- VoiceTouchCandidates voice_touch_candidates;
- ScreenElements screen_elements;
- voice_touch_mode_e mode{VOICE_TOUCH_MODE_TEXT};
-};
-
-
-static const char *INPUT_PORT_NAME_SCREEN_INFO = "SCREEN_INFO";
-static const char *INPUT_PORT_NAME_MODE_COMMANDS = "MODE_COMMANDS";
-static const char *INPUT_PORT_NAME_UTTERANCE = "UTTERANCE";
-
-static const char *OUTPUT_PORT_NAME_MATCHED_RESULT = "MATCHED_RESULT";
-static const char *OUTPUT_PORT_NAME_REJECTED = "REJECTED";
-static const char *OUTPUT_PORT_NAME_CANDIDATES = "CANDIDATES";
-
-static const char *ATTRIBUTE_NAME_GRID_CONFIGURATION = "GRID_CONFIGURATION";
-
-static const char *MODE_COMMAND_SHOW_INDEX = "숫자 보여줘";
-static const char *MODE_COMMAND_SHOW_TEXT = "텍스트 보여줘";
-static const char *MODE_COMMAND_SHOW_GRID = "그리드 보여줘";
-
-
-static std::map<mmi_node_instance_h, std::shared_ptr<voice_touch_helper_s>> g_node_to_helper_map;
-
-
-static int node_initialized_cb(mmi_node_instance_h instance)
-{
- _D("[VOICE TOUCH] Node initialize callback is called for %p", instance);
- if (nullptr == instance) {
- _E("[VOICE TOUCH] Instance is null. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- try {
- auto helper_instance = std::make_shared<voice_touch_helper_s>();
- g_node_to_helper_map[instance] = helper_instance;
- } catch (std::bad_alloc &e) {
- _E("[VOICE TOUCH] Fail to allocate memory for node instance. %p", instance);
- return MMI_ERROR_OUT_OF_MEMORY;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static bool is_node_instance_valid(mmi_node_instance_h instance)
-{
- if (nullptr == instance) {
- _E("[VOICE TOUCH] Node instance is null %p", instance);
- return false;
- }
-
- auto iterator = g_node_to_helper_map.find(instance);
- if (iterator == g_node_to_helper_map.end()) {
- _E("[VOICE TOUCH] No instance %p", instance);
- return false;
- }
-
- return true;
-}
-
-static int node_deinitialized_cb(mmi_node_instance_h instance)
-{
- _D("[VOICE TOUCH] Node deinitialize callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[VOICE TOUCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- g_node_to_helper_map.erase(instance);
- return MMI_ERROR_NONE;
-}
-
-static int node_attribute_set_cb(mmi_node_instance_h instance, mmi_attribute_h attribute)
-{
- _D("[VOICE TOUCH] Node attribute set callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[VOICE TOUCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- char *name = nullptr;
- mmi_attribute_get_name(attribute, &name);
- if (nullptr == name) {
- _E("[VOICE TOUCH] Fail to get name from attribute. %p", attribute);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- std::string attribute_name(name);
- free(name);
- name = nullptr;
-
- if (0 != attribute_name.compare(ATTRIBUTE_NAME_GRID_CONFIGURATION)) {
- _E("[VOICE TOUCH] Attribute name is not same as expected one. (%s)", attribute_name.c_str());
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- mmi_primitive_value_h value = nullptr;
- mmi_attribute_get_value(attribute, &value);
- if (nullptr == value) {
- _E("[VOICE TOUCH] Fail to get primitive value from attribute. %p", attribute);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- MmiPrimitiveHelper attribute_value(value, true);
- value = nullptr;
- if (MMI_PRIMITIVE_VALUE_TYPE_ARRAY != attribute_value.get_type()) {
- _E("[VOICE TOUCH] Fail to get primitive value from attribute. %p", attribute);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- auto &screen_elements = g_node_to_helper_map[instance]->screen_elements;
-
- // TODO: Check the efficient way to set attribute for voice touch.
- try {
- auto screen_w = attribute_value.get_array_element(0).get_integer_value();
- auto screen_h = attribute_value.get_array_element(1).get_integer_value();
-
- _D("[VOICE TOUCH] Screen size : %d, %d", screen_w, screen_h);
- screen_elements.set_screen_size(screen_w, screen_h);
- } catch (mmi_error_e &error) {
- _E("[VOICE TOUCH] Fail to get screen size. %p", attribute);
- return error;
- }
-
- size_t count = attribute_value.get_array_count();
- std::vector<grid_information_s> grid_informations;
- for (size_t i = 2; i < count; i += 2) {
- try {
- grid_information_s grid_information{
- .col_count = static_cast<size_t>(attribute_value.get_array_element(i).get_integer_value()),
- .row_count = static_cast<size_t>(attribute_value.get_array_element(i + 1).get_integer_value())
- };
-
- _D("[VOICE TOUCH] Grid information : col(%zu), row(%zu)", grid_information.col_count, grid_information.row_count);
- grid_informations.push_back(grid_information);
- } catch (mmi_error_e &error) {
- _E("[VOICE TOUCH] Fail to get data. Please check error. index(%zu). error(%d)", i, error);
- return error;
- }
- }
-
- screen_elements.set_grid_informations(grid_informations);
- return MMI_ERROR_NONE;
-}
-
-static int node_activated_cb(mmi_node_instance_h instance)
-{
- _D("[VOICE TOUCH] Node activate callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[VOICE TOUCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int node_deactivated_cb(mmi_node_instance_h instance)
-{
- _D("[VOICE TOUCH] Node deactivate callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[VOICE TOUCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int utterance_port_output_format_requested_cb(mmi_port_instance_h instance, const char *format)
-{
- _D("[VOICE TOUCH] Port output format request callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[VOICE TOUCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static void generate_output_for_rejected_port(mmi_node_instance_h instance, const char *text)
-{
- mmi_port_instance_h rejected_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, OUTPUT_PORT_NAME_REJECTED, &rejected_port);
- if (nullptr == rejected_port) {
- _E("[VOICE TOUCH] Fail to get output port. name(%s). node instance(%p)", OUTPUT_PORT_NAME_REJECTED, instance);
- return;
- }
-
- MmiDataHelper output_data(text);
- if (nullptr == output_data.get_handle()) {
- _E("[VOICE TOUCH] Fail to allocate memory for output data. name(%s). node instance(%p)", OUTPUT_PORT_NAME_MATCHED_RESULT, instance);
- return;
- }
-
- mmi_port_instance_generate_output(rejected_port, output_data.get_handle());
-}
-
-static void generate_output_for_matched_result_port(mmi_node_instance_h instance, const voice_touch_candidate_s &candidate, const screen_element_s &element)
-{
- mmi_port_instance_h matched_result_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, OUTPUT_PORT_NAME_MATCHED_RESULT, &matched_result_port);
- if (nullptr == matched_result_port) {
- _E("[VOICE TOUCH] Fail to get output port. name(%s). node instance(%p)", OUTPUT_PORT_NAME_MATCHED_RESULT, instance);
- return;
- }
-
- MmiDataHelper output_data(candidate, element);
- if (nullptr == output_data.get_handle()) {
- _E("[VOICE TOUCH] Fail to allocate memory for output data. name(%s). node instance(%p)", OUTPUT_PORT_NAME_MATCHED_RESULT, instance);
- return;
- }
-
- mmi_port_instance_generate_output(matched_result_port, output_data.get_handle());
-}
-
-static void generate_output_for_candidates_port(mmi_node_instance_h instance, const std::vector<voice_touch_candidate_s> &candidates)
-{
- mmi_port_instance_h candidates_port = nullptr;
- mmi_node_instance_find_port(instance, MMI_PORT_TYPE_OUT, OUTPUT_PORT_NAME_CANDIDATES, &candidates_port);
- if (nullptr == candidates_port) {
- _E("[VOICE TOUCH] Fail to get output port. name(%s). node instance(%p)", OUTPUT_PORT_NAME_CANDIDATES, instance);
- return;
- }
-
- MmiDataHelper output_data(candidates);
- if (nullptr == output_data.get_handle()) {
- _E("[VOICE TOUCH] Fail to allocate memory for output data. name(%s). node instance(%p)", OUTPUT_PORT_NAME_CANDIDATES, instance);
- return;
- }
-
- mmi_port_instance_generate_output(candidates_port, output_data.get_handle());
-}
-
-static mmi_error_e handle_utterance_input_as_text(mmi_node_instance_h instance, const char *utterance)
-{
- auto &voice_touch_candidates = g_node_to_helper_map[instance]->voice_touch_candidates;
- auto &screen_elements = g_node_to_helper_map[instance]->screen_elements;
-
- auto matched_candidate = voice_touch_candidates.find_matched_candidate(utterance);
- if (matched_candidate.has_value() == false) {
- _I("[VOICE TOUCH] There is no proper candidate in the screen. utterance(%s)", utterance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- auto matched_element = screen_elements.find_related_screen_element(*matched_candidate);
- if (matched_element.has_value() == false) {
- _I("[VOICE TOUCH] There is no proper screen element in the screen. utterance(%s)", utterance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- _I("[VOICE TOUCH] Success to find the candidate. utterance(%s)", utterance);
- generate_output_for_matched_result_port(instance, *matched_candidate, *matched_element);
-
- return MMI_ERROR_NONE;
-}
-
-static mmi_error_e handle_utterance_input_as_index(mmi_node_instance_h instance, const char *utterance)
-{
- auto &voice_touch_candidates = g_node_to_helper_map[instance]->voice_touch_candidates;
- auto &screen_elements = g_node_to_helper_map[instance]->screen_elements;
-
- int index = -1;
- try {
- index = std::stoi(utterance);
- } catch (std::exception &e) {
- _I("[VOICE TOUCH] There is no number in utterance. utterance(%s). exception(%s)", utterance, e.what());
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- auto matched_candidate = voice_touch_candidates.find_matched_candidate(index);
- if (matched_candidate.has_value() == false) {
- _I("[VOICE TOUCH] There is no proper candidate in the screen. utterance(%s)", utterance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- auto matched_element = screen_elements.find_related_screen_element(*matched_candidate);
- if (matched_element.has_value() == false) {
- _I("[VOICE TOUCH] There is no proper screen element in the screen. utterance(%s)", utterance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- _I("[VOICE TOUCH] Success to find the candidate. utterance(%s)", utterance);
- generate_output_for_matched_result_port(instance, *matched_candidate, *matched_element);
-
- return MMI_ERROR_NONE;
-}
-
-static mmi_error_e handle_utterance_input_as_grid(mmi_node_instance_h instance, const char *utterance)
-{
- auto &voice_touch_candidates = g_node_to_helper_map[instance]->voice_touch_candidates;
- auto &screen_elements = g_node_to_helper_map[instance]->screen_elements;
-
- int index = -1;
- try {
- index = std::stoi(utterance);
- } catch (std::exception &e) {
- _I("[VOICE TOUCH] There is no number in utterance. utterance(%s). exception(%s)", utterance, e.what());
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- auto matched_candidate = voice_touch_candidates.find_matched_candidate(index);
- if (matched_candidate.has_value() == false) {
- _I("[VOICE TOUCH] There is no proper candidate in the screen. utterance(%s)", utterance);
- return MMI_ERROR_OPERATION_FAILED;
- }
-
- screen_elements.increase_grid_depth();
- if (screen_elements.is_maximum_grid_depth() == false) {
- _I("[VOICE TOUCH] Make candidate for next grid depth.");
- screen_elements.set_grid_area(matched_candidate->candidate_area);
-
- auto candidates = screen_elements.make_voice_touch_candidates(VOICE_TOUCH_MODE_GRID);
- voice_touch_candidates.set_candidates(candidates);
- generate_output_for_candidates_port(instance, candidates);
- return MMI_ERROR_NONE;
- }
-
- auto matched_element = screen_elements.find_related_screen_element(*matched_candidate);
- if (matched_element.has_value() == false) {
- _I("[VOICE TOUCH] There is no proper screen element in the screen. utterance(%s)", utterance);
- _I("[VOICE TOUCH] Make output for center of grid");
- matched_element = screen_element_s{
- .element_area = matched_candidate->candidate_area,
- .object_id = std::string(),
- .label = matched_candidate->label,
- .role = std::string()
- };
- } else {
- _I("[VOICE TOUCH] Success to find the candidate. utterance(%s)", utterance);
- }
-
- screen_elements.reset_grid_depth();
- generate_output_for_matched_result_port(instance, *matched_candidate, *matched_element);
-
- return MMI_ERROR_NONE;
-}
-
-static std::optional<mmi_node_instance_h> find_node_instance(mmi_port_instance_h port_instance, const char *port_name)
-{
- if (nullptr == port_instance || nullptr == port_name) {
- return std::nullopt;
- }
-
- for (auto &element : g_node_to_helper_map) {
- mmi_port_instance_h candidate_port = nullptr;
- mmi_node_instance_find_port(element.first, MMI_PORT_TYPE_IN, port_name, &candidate_port);
-
- if (candidate_port == port_instance) {
- return element.first;
- }
- }
-
- return std::nullopt;
-}
-
-static int utterance_port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data)
-{
- _D("[VOICE TOUCH] Text input data callback is called: %p", instance);
- auto node_instance = find_node_instance(instance, INPUT_PORT_NAME_UTTERANCE);
- if (node_instance.has_value() == false) {
- _E("[VOICE TOUCH] There is no proper node instance: %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- const char *utterance = nullptr;
- mmi_data_get_text(data, &utterance);
- if (nullptr == utterance) {
- _E("[VOICE TOUCH] Fail to get text from the data: %p", data);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- voice_touch_mode_e mode = g_node_to_helper_map[*node_instance]->mode;
- mmi_error_e ret = MMI_ERROR_NONE;
- switch (mode) {
- case VOICE_TOUCH_MODE_TEXT:
- ret = handle_utterance_input_as_text(*node_instance, utterance);
- break;
-
- case VOICE_TOUCH_MODE_INDEX:
- ret = handle_utterance_input_as_index(*node_instance, utterance);
- break;
-
- case VOICE_TOUCH_MODE_GRID:
- ret = handle_utterance_input_as_grid(*node_instance, utterance);
- break;
- }
-
- if (MMI_ERROR_NONE != ret) {
- _I("[VOICE TOUCH] Generate reject output. utterance(%s)", utterance);
- generate_output_for_rejected_port(*node_instance, utterance);
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int mode_commands_port_output_format_requested_cb(mmi_port_instance_h instance, const char *format)
-{
- _D("[VOICE TOUCH] Port output format request callback is called for %p", instance);
-
- return MMI_ERROR_NONE;
-}
-
-static int mode_commands_port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data)
-{
- _D("[VOICE TOUCH] Text input data callback is called: %p", instance);
- auto node_instance = find_node_instance(instance, INPUT_PORT_NAME_MODE_COMMANDS);
- if (node_instance.has_value() == false) {
- _E("[VOICE TOUCH] There is no proper node instance: %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- const char *text = nullptr;
- mmi_data_get_text(data, &text);
- if (nullptr == text) {
- _E("[VOICE TOUCH] Fail to get text from the data: %p", data);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- std::string mode_str = text;
- text = nullptr;
-
- voice_touch_mode_e mode = VOICE_TOUCH_MODE_TEXT;
- if (mode_str.compare(MODE_COMMAND_SHOW_TEXT) == 0) {
- mode = VOICE_TOUCH_MODE_TEXT;
- } else if (mode_str.compare(MODE_COMMAND_SHOW_INDEX) == 0) {
- mode = VOICE_TOUCH_MODE_INDEX;
- } else if (mode_str.compare(MODE_COMMAND_SHOW_GRID) == 0) {
- mode = VOICE_TOUCH_MODE_GRID;
- } else {
- _E("[VOICE TOUCH] Invalid mode command: %s", mode_str.c_str());
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- auto &node_helper = g_node_to_helper_map[*node_instance];
- auto &voice_touch_candidates = node_helper->voice_touch_candidates;
- auto &screen_elements = node_helper->screen_elements;
-
- node_helper->mode = mode;
- auto candidates = screen_elements.make_voice_touch_candidates(node_helper->mode);
- voice_touch_candidates.set_candidates(candidates);
-
- generate_output_for_candidates_port(*node_instance, candidates);
-
- return MMI_ERROR_NONE;
-}
-
-static int screen_info_port_output_format_requested_cb(mmi_port_instance_h instance, const char *format)
-{
- _D("[VOICE TOUCH] Port output format request callback is called for %p", instance);
- if (false == is_node_instance_valid(instance)) {
- _E("[VOICE TOUCH] Instance is not valid. %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- return MMI_ERROR_NONE;
-}
-
-static int screen_info_port_input_data_received_cb(mmi_port_instance_h instance, mmi_data_h data)
-{
- _D("[VOICE TOUCH] Text input data callback is called: %p", instance);
- auto node_instance = find_node_instance(instance, INPUT_PORT_NAME_SCREEN_INFO);
- if (node_instance.has_value() == false) {
- _E("[VOICE TOUCH] There is no proper node instance: %p", instance);
- return MMI_ERROR_INVALID_PARAMETER;
- }
-
- const MmiDataHelper data_helper(data);
- try {
- mmi_data_type_e type = data_helper.get_type();
- if (MMI_DATA_TYPE_ARRAY != type) {
- _E("[VOICE TOUCH] Type is not valid. data(%p). type(%d)", data, type);
- return MMI_ERROR_INVALID_PARAMETER;
- }
- } catch (mmi_error_e &error) {
- return error;
- }
-
- auto &node_helper = g_node_to_helper_map[*node_instance];
- auto &voice_touch_candidates = node_helper->voice_touch_candidates;
- auto &screen_elements = node_helper->screen_elements;
-
- screen_elements.set_screen_elements(data_helper);
- auto candidates = screen_elements.make_voice_touch_candidates(node_helper->mode);
- voice_touch_candidates.set_candidates(candidates);
- generate_output_for_candidates_port(*node_instance, candidates);
-
- return MMI_ERROR_NONE;
-}
-
-static mmi_port_h create_input_port(const char *name, mmi_data_type_e type, mmi_port_callbacks callbacks)
-{
- mmi_port_h input_port = nullptr;
- mmi_port_create(&input_port);
- if (nullptr == input_port) {
- return nullptr;
- }
-
- mmi_port_set_name(input_port, name);
- mmi_port_set_type(input_port, MMI_PORT_TYPE_IN);
- mmi_port_set_data_type(input_port, type);
- mmi_port_set_callbacks(input_port, callbacks);
-
- return input_port;
-}
-
-static mmi_port_h create_output_port(const char *name, mmi_data_type_e type)
-{
- mmi_port_h output_port = nullptr;
- mmi_port_create(&output_port);
- if (nullptr == output_port) {
- return nullptr;
- }
-
- mmi_port_set_name(output_port, name);
- mmi_port_set_type(output_port, MMI_PORT_TYPE_OUT);
- mmi_port_set_data_type(output_port, type);
-
- return output_port;
-}
-
-
-extern "C" {
-
- EXPORT_API void mmi_plugin_module_get_node_list()
- {
- mmi_node_callbacks node_callbacks {
- node_initialized_cb,
- node_deinitialized_cb,
- node_attribute_set_cb,
- node_activated_cb,
- node_deactivated_cb,
- nullptr
- };
-
- mmi_port_callbacks utterance_port_callbacks {
- utterance_port_output_format_requested_cb,
- utterance_port_input_data_received_cb
- };
-
- mmi_port_callbacks mode_commands_port_callbacks {
- mode_commands_port_output_format_requested_cb,
- mode_commands_port_input_data_received_cb
- };
-
- mmi_port_callbacks screen_info_port_callbacks {
- screen_info_port_output_format_requested_cb,
- screen_info_port_input_data_received_cb
- };
-
- mmi_port_h utterance_input_port = create_input_port(
- INPUT_PORT_NAME_UTTERANCE,
- MMI_DATA_TYPE_TEXT,
- utterance_port_callbacks);
-
- mmi_port_h mode_commands_input_port = create_input_port(
- INPUT_PORT_NAME_MODE_COMMANDS,
- MMI_DATA_TYPE_TEXT,
- mode_commands_port_callbacks);
-
- // TODO: check the type of input
- mmi_port_h screen_info_input_port = create_input_port(
- INPUT_PORT_NAME_SCREEN_INFO,
- MMI_DATA_TYPE_ARRAY,
- screen_info_port_callbacks);
-
- mmi_port_h candidates_output_port = create_output_port(
- OUTPUT_PORT_NAME_CANDIDATES,
- MMI_DATA_TYPE_ARRAY);
-
- mmi_port_h matched_result_output_port = create_output_port(
- OUTPUT_PORT_NAME_MATCHED_RESULT,
- MMI_DATA_TYPE_STRUCT);
-
- mmi_port_h rejected_output_port = create_output_port(
- OUTPUT_PORT_NAME_REJECTED,
- MMI_DATA_TYPE_TEXT);
-
- mmi_node_h voice_touch_node = nullptr;
- mmi_standard_node_create_processor(MMI_STANDARD_NODE_PROCESSOR_TYPE_VOICE_TOUCH, &voice_touch_node);
-
- // Add input ports
- mmi_node_add_port(voice_touch_node, utterance_input_port);
- mmi_node_add_port(voice_touch_node, mode_commands_input_port);
- mmi_node_add_port(voice_touch_node, screen_info_input_port);
-
- // Add output ports
- mmi_node_add_port(voice_touch_node, candidates_output_port);
- mmi_node_add_port(voice_touch_node, matched_result_output_port);
- mmi_node_add_port(voice_touch_node, rejected_output_port);
-
- mmi_node_set_callbacks(voice_touch_node, node_callbacks);
- mmi_node_register(voice_touch_node);
-
- mmi_node_destroy(voice_touch_node);
- }
-
-} // extern "C"
'mmi-module-script-parser.cpp',
]
-dlog_dep = dependency('dlog', method : 'pkg-config')
ecore_dep = dependency('ecore', method : 'pkg-config')
mmi_module_script_parser_deps = [
mmi_declared_dep,
- dlog_dep,
ecore_dep,
]
#include <string>
#include <vector>
-#include <dlog.h>
#include <Ecore.h>
extern "C" {
EXPORT_API void mmi_plugin_module_get_workflow_list()
{
- const std::string plugin_module_path{"/usr/share/mmi/scripts"};
+ const std::string plugin_module_path{MMI_INSTALL_PREFIX "/share/mmi/scripts"};
for (const auto & entry : std::filesystem::directory_iterator(plugin_module_path)) {
auto const pos = entry.path().string().find_last_of(".");
if (pos != std::string::npos) {
@node-list
[Source] MIC_AMBIENT as MIC
[Source] CAMERA as CAMERA
+[Processor] VIDEO_CONVERTER as VIDEO_CONVERTER
[Processor] FACE_RECOGNITION as FACE_RECOGNITION
[Processor] SPEAKER_RECOGNITION as SPEAKER_RECOGNITION
[Logic] USER_COMPARISON as USER_COMPARISON
@link-list
-CAMERA.VIDEO -> FACE_RECOGNITION.VIDEO
+CAMERA.VIDEO -> VIDEO_CONVERTER.VIDEO_IN
+VIDEO_CONVERTER.VIDEO_OUT -> FACE_RECOGNITION.VIDEO
FACE_RECOGNITION.MATCHED_FACES -> USER_COMPARISON.PORT1
MIC.AUDIO -> SPEAKER_RECOGNITION.AUDIO
SPEAKER_RECOGNITION.MATCHED_SPEAKERS -> USER_COMPARISON.PORT2
'mmi-module-voice-touch.cpp',
]
-dlog_dep = dependency('dlog', method : 'pkg-config')
ecore_dep = dependency('ecore', method : 'pkg-config')
mmi_module_voice_touch_deps = [
mmi_declared_dep,
- dlog_dep,
ecore_dep,
]
#include <mmi.h>
+#include <mmi-log.h>
#include <mmi-plugin-storage.h>
#include <mmi-workflow.h>
#include <string>
#include <map>
-#include <dlog.h>
#include <Ecore.h>
#ifdef LOG_TAG
mmi_workflow_link_nodes_by_names(workflow, NODE_NAME_MIC, "AUDIO", NODE_NAME_ASR, "AUDIO");
+#ifdef ENABLE_TEMP_RESCAN
+ mmi_workflow_link_nodes_by_names(workflow, NODE_NAME_ASR, "FINAL_ASR", "TEMP_RESCAN", "TEXT");
+ mmi_workflow_link_nodes_by_names(workflow, "TEMP_RESCAN", "REJECTED", NODE_NAME_MATCH_MODE_COMMANDS, "TEXT");
+#elif
mmi_workflow_link_nodes_by_names(workflow, NODE_NAME_ASR, "FINAL_ASR", NODE_NAME_MATCH_MODE_COMMANDS, "TEXT");
+#endif
mmi_workflow_link_nodes_by_names(workflow, NODE_NAME_MATCH_MODE_COMMANDS, "MATCHED_CANDIDATE", NODE_NAME_VOICE_TOUCH_PROCESSOR, "MODE_COMMANDS");
mmi_workflow_link_nodes_by_names(workflow, NODE_NAME_MATCH_MODE_COMMANDS, "REJECTED", NODE_NAME_MATCH_PREDEFINED_COMMANDS, "TEXT");
#ifdef ENABLE_TEMP_RESCAN
/* These are temporary links for rescanning the screen, it will be removed when the signal mechanism is ready */
- mmi_workflow_link_nodes_by_names(workflow, NODE_NAME_ASR, "FINAL_ASR", "TEMP_RESCAN", "TEXT");
mmi_workflow_link_nodes_by_names(workflow, "TEMP_RESCAN", "MATCHED_CANDIDATE", NODE_NAME_SCREEN_ANALYZER, "RESCAN");
#endif
+ // INFO: Attribute assigning
mmi_workflow_attribute_assign(workflow, "PREDEFINED_COMMANDS", NODE_NAME_MATCH_PREDEFINED_COMMANDS, "CANDIDATES");
-
+ mmi_workflow_attribute_assign(workflow, "__MODE_COMMANDS", NODE_NAME_MATCH_MODE_COMMANDS, "CANDIDATES");
mmi_workflow_attribute_assign(workflow, "GRID_CONFIGURATION", NODE_NAME_VOICE_TOUCH_PROCESSOR, "GRID_CONFIGURATION");
+ mmi_workflow_attribute_assign(workflow, "ASR_STOP_METHOD", NODE_NAME_ASR, "STOP_METHOD");
#ifdef ENABLE_TEMP_RESCAN
/* These are temporary attributes for rescanning the screen, it will be removed when the signal mechanism is ready */
mmi_workflow_output_assign(workflow, "PARTIAL_RESULT", NODE_NAME_ASR, "PARTIAL_ASR");
mmi_workflow_output_assign(workflow, "FINAL_RESULT", NODE_NAME_ASR, "FINAL_ASR");
- mmi_workflow_output_assign(workflow, "MATCHED_CANDIDATE", NODE_NAME_MATCH_PREDEFINED_COMMANDS, "MATCHED_COMMAND");
+ mmi_workflow_output_assign(workflow, "MATCHED_COMMAND", NODE_NAME_MATCH_PREDEFINED_COMMANDS, "MATCHED_CANDIDATE");
mmi_workflow_output_assign(workflow, "REJECTED", NODE_NAME_VOICE_TOUCH_PROCESSOR, "REJECTED");
mmi_workflow_output_assign(workflow, "CANDIDATES", NODE_NAME_VOICE_TOUCH_PROCESSOR, "CANDIDATES");
mmi_workflow_output_assign(workflow, "MATCHED_RESULT", NODE_NAME_VOICE_TOUCH_PROCESSOR, "MATCHED_RESULT");
- mmi_primitive_value_h primitive_array = nullptr;
- mmi_primitive_value_create_array(&primitive_array);
-
- mmi_primitive_value_h predefined_command_grid = nullptr;
- mmi_primitive_value_create_string("Grid", &predefined_command_grid);
- mmi_primitive_value_add_array_element(primitive_array, predefined_command_grid);
-
- mmi_primitive_value_h predefined_command_number = nullptr;
- mmi_primitive_value_create_string("Number", &predefined_command_number);
- mmi_primitive_value_add_array_element(primitive_array, predefined_command_number);
+ const char *modes[] = {
+ "숫자 보여줘",
+ "텍스트 보여줘",
+ "그리드 보여줘",
+ };
mmi_attribute_h attribute = nullptr;
- mmi_attribute_create(primitive_array, "PREDEFINED_COMMANDS", &attribute);
-
+ mmi_attribute_create_string_array("__MODE_COMMANDS", modes, sizeof(modes) / sizeof(const char *), &attribute);
mmi_workflow_attribute_set_default_value(workflow, attribute);
-
mmi_attribute_destroy(attribute);
- mmi_primitive_value_destroy(primitive_array);
#ifdef ENABLE_TEMP_RESCAN
/* This is a temporary attribute for rescanning the screen, it will be removed when the signal mechanism is ready */
- mmi_primitive_value_h temp_rescan_command = nullptr;
- mmi_primitive_value_create_string("Rescan", &temp_rescan_command);
+ const char *rescans[] = {
+ "새로고침",
+ "새로 고침",
+ };
+
mmi_attribute_h temp_attribute = nullptr;
- mmi_attribute_create(temp_rescan_command, "TEMP_RESCAN_COMMAND", &temp_attribute);
+ mmi_attribute_create_string_array("TEMP_RESCAN_COMMAND", rescans, sizeof(rescans) / sizeof(const char *), &temp_attribute);
mmi_workflow_attribute_set_default_value(workflow, temp_attribute);
mmi_attribute_destroy(temp_attribute);
- mmi_primitive_value_destroy(temp_rescan_command);
#endif
mmi_standard_workflow_register(workflow);
+++ /dev/null
-@workflow
-name : VoiceTouch
-
-@node-list
-[Source] MIC_AMBIENT as MIC
-[Processor] ASR as ASR
-[Logic] FIXED_STRING_MATCH as MATCH
-[Logic] FIXED_STRING_MATCH as DUMMY
-
-@link-list
-MIC.AUDIO -> ASR.AUDIO
-ASR.FINAL_RESULT -> MATCH.TEXT
-ASR.FINAL_RESULT -> DUMMY.TEXT
-
-@attribute-list
-MATCH.CANDIDATES as COMMANDS
-
-@output-list
-MATCH.MATCHED_CANDIDATE as COMMAND
'mmi-module-wakeupless-command.cpp',
]
-dlog_dep = dependency('dlog', method : 'pkg-config')
ecore_dep = dependency('ecore', method : 'pkg-config')
mmi_module_wakeupless_command_deps = [
mmi_declared_dep,
- dlog_dep,
ecore_dep,
]
#include <mmi.h>
+#include <mmi-log.h>
#include <mmi-plugin-storage.h>
#include <mmi-workflow.h>
#include <string>
#include <map>
-#include <dlog.h>
#include <Ecore.h>
#ifdef LOG_TAG
#endif
#define LOG_TAG "MMI-MODULE-WAKEUPLESS-COMMAND"
-#define MMI_MODULE_LOG_(prio, tag, fmt, arg...) \
- ({ do { \
- dlog_print(prio, tag, "%s: %s(%d) > " fmt, __MODULE__, __func__, __LINE__, ##arg); \
- } while (0); })
-
-#define _D(fmt, args...) MMI_MODULE_LOG_(DLOG_DEBUG, LOG_TAG, fmt, ##args)
-#define _I(fmt, args...) MMI_MODULE_LOG_(DLOG_INFO, LOG_TAG, fmt, ##args)
-#define _W(fmt, args...) MMI_MODULE_LOG_(DLOG_WARN, LOG_TAG, fmt, ##args)
-#define _E(fmt, args...) MMI_MODULE_LOG_(DLOG_ERROR, LOG_TAG, fmt, ##args)
-
extern "C" {
EXPORT_API void mmi_plugin_module_get_workflow_list()
mmi_workflow_output_assign(workflow, "UTTERANCE", "ASR", "PARTIAL_ASR");
mmi_workflow_output_assign(workflow, "UTTERANCE", "ASR", "FINAL_ASR");
+ mmi_workflow_signal_assign(workflow, "CONTROL", "ASR", "CONTROL");
+
mmi_standard_workflow_register(workflow);
mmi_node_destroy(node_mic);
--- /dev/null
+meson setup --prefix=/usr/local/mmi \
+ --bindir /usr/local/mmi/bin \
+ --libdir /usr/local/mmi/lib \
+ --datadir /usr/local/mmi/share \
+ ./linux_build
virtual int send(Message *message) = 0;
};
+// LCOV_EXCL_START
class CommunicationChannelManager : public CommunicationChannel,
public SimpleEventObserver<WORKFLOW_OUTPUT_EVENT_TYPE> {
public:
CommunicationChannelClient() = default;
virtual ~CommunicationChannelClient() = default;
};
+// LCOV_EXCL_STOP
struct CommunicationChannelManagerFactory {
CommunicationChannelManagerFactory() = default;
virtual ~CommunicationChannelManagerFactory() = default;
- virtual std::shared_ptr<CommunicationChannelManager> create_channel() = 0;
+ virtual std::shared_ptr<CommunicationChannelManager> create_channel();
};
+// LCOV_EXCL_START
struct CommunicationChannelClientFactory {
CommunicationChannelClientFactory() = default;
virtual ~CommunicationChannelClientFactory() = default;
- virtual std::shared_ptr<CommunicationChannelClient> create_channel() = 0;
+ virtual std::shared_ptr<CommunicationChannelClient> create_channel();
};
+// LCOV_EXCL_STOP
}; // namespace communication
#include <vector>
#include <functional>
-#include <bundle.h>
-
#include "mmi.h"
namespace mmi {
WORKFLOW_INSTANCE_CREATE,
WORKFLOW_INSTANCE_DESTROY,
WORKFLOW_INSTANCE_SET_ATTRIBUTE,
+ WORKFLOW_INSTANCE_EMIT_SIGNAL,
WORKFLOW_INSTANCE_ACTIVATE,
WORKFLOW_INSTANCE_DEACTIVATE,
/* Manager to Client */
+ WORKFLOW_INSTANCE_OUTPUT,
};
struct Message {
mmi_attribute_h attribute{nullptr};
};
+struct ClientMessageWorkflowInstanceEmitSignal : public ClientMessage {
+ ClientMessageWorkflowInstanceEmitSignal() : ClientMessage{CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_EMIT_SIGNAL} {}
+ int local_workflow_instance_id{0};
+ mmi_signal_h signal{nullptr};
+};
+
struct ClientMessageWorkflowInstanceActivate : public ClientMessage {
ClientMessageWorkflowInstanceActivate() : ClientMessage{CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_ACTIVATE} {}
int local_workflow_instance_id{0};
int local_workflow_instance_id{0};
};
+struct ClientMessageWorkflowInstanceOutput : public ClientMessage {
+ ClientMessageWorkflowInstanceOutput() : ClientMessage{CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_OUTPUT} {}
+ int local_workflow_instance_id{0};
+ std::string source_name;
+ mmi_data_h data{nullptr};
+};
+
}; // namespace communication
}; // namespace mmi
#pragma once
+#include "mmi-platform-config.h"
#include "mmi-event-observer.h"
#include <memory>
-#include <bundle.h>
namespace mmi {
WorkflowOutputEventOutputGenerated() : WorkflowOutputEvent(WORKFLOW_OUTPUT_EVENT_TYPE::OUTPUT_GENERATED) {}
virtual ~WorkflowOutputEventOutputGenerated() {}
- bundle *data{nullptr};
std::string source_name;
std::string client_id;
int local_workflow_instance_id{0};
+
+ unsigned char *data_bytes{nullptr};
+ size_t data_size{0};
};
}; // namespace mmi
-dlog_dep = dependency('dlog', method : 'pkg-config')
ecore_dep = dependency('ecore', method : 'pkg-config')
-rpc_port_dep = dependency('rpc-port')
+dl_dep = meson.get_compiler('c').find_library('dl', required : true)
mmi_cli_deps = [
mmi_declared_dep,
- dlog_dep,
ecore_dep,
- rpc_port_dep,
+ dl_dep,
]
+foreach platform_specific_dependency : mmi_platform_specific_dependencies
+ message('Platform Specific Dependency : ' + platform_specific_dependency)
+ extra_dep = dependency(platform_specific_dependency, method : 'pkg-config')
+ mmi_cli_deps += extra_dep
+endforeach
+
+mmi_extra_include_dir = ''.join(['../../', mmi_platform_specific_include_directory])
mmi_cli_include_dirs = include_directories(
'.',
'../common/',
'../../capi/',
'../../external/',
+ mmi_extra_include_dir,
)
mmi_cli_declared_dep = declare_dependency(
executable('mmi-cli',
mmi_cli_program_srcs,
- include_directories : [ mmi_cli_include_dirs ],
+ include_directories : [ mmi_cli_include_dirs],
dependencies : [mmi_cli_program_deps],
install_dir : mmi_prefix_bindir,
install : true,
mmi_plugin_module_node_list_s m_node_list;
std::map<int, NodeInstance*> m_node_instance_map;
- int m_node_instance_index{0};
+ size_t m_node_instance_index{0};
};
static Program g_program;
}
}
if (entry_index == static_cast<size_t>(AttributeTestType::MaxCount)) {
- _E("Failed to find attribute type: %d", type);
+ _E("Failed to find attribute type: %zu", static_cast<size_t>(type));
return;
}
g_attribute_test_entries[entry_index].attribute_generator(this, &attribute);
mmi_attribute_destroy(attribute);
mmi_primitive_value_destroy(stop_method_value);
}
+ void emit_signal() {
+ if (!m_instance) {
+ std::cout << "No instance to set attribute" << std::endl;
+ return;
+ }
+
+ std::cout << "Emitting signal " << std::endl;
+
+ mmi_primitive_value_h signal_parameter_value_1 = nullptr;
+ mmi_signal_parameter_h signal_parameter_1 = nullptr;
+ mmi_primitive_value_h signal_parameter_value_2 = nullptr;
+ mmi_signal_parameter_h signal_parameter_2 = nullptr;
+ mmi_signal_h signal = nullptr;
+ mmi_primitive_value_create_int(6, &signal_parameter_value_1);
+ mmi_signal_parameter_create(signal_parameter_value_1,
+ "signal_parameter_1", &signal_parameter_1);
+ mmi_primitive_value_create_int(3, &signal_parameter_value_2);
+ mmi_signal_parameter_create(signal_parameter_value_2,
+ "signal_parameter_2", &signal_parameter_2);
+ mmi_signal_create("CONTROL", &signal);
+ mmi_signal_add_parameter(signal, signal_parameter_1);
+ mmi_signal_add_parameter(signal, signal_parameter_2);
+ mmi_workflow_instance_emit_signal(m_instance, signal);
+ mmi_signal_destroy(signal);
+ mmi_signal_parameter_destroy(signal_parameter_1);
+ mmi_primitive_value_destroy(signal_parameter_value_1);
+ mmi_signal_parameter_destroy(signal_parameter_2);
+ mmi_primitive_value_destroy(signal_parameter_value_2);
+ }
+
static int state_changed_cb(mmi_state_e state, void *user_data) {
Program *program = static_cast<Program*>(user_data);
},
"Set attributes for the current workflow instance");
+ rootMenu->Insert("emit_signal", [](std::ostream& out) {
+ g_program.emit_signal();
+ },
+ "Set attributes for the current workflow instance");
+
rootMenu->Insert("activate", [](std::ostream& out) {
g_program.activate_instance();
},
#include <Ecore.h>
#include "mmi-manager.h"
-#include "mmi-ipc-tidl.h"
#include "mmi-self-container.h"
#include "adishavit/argh.h"
-struct CommunicationChannelFactoryTIDL :
- public mmi::communication::CommunicationChannelManagerFactory {
- std::shared_ptr<mmi::communication::CommunicationChannelManager> create_channel() override {
- return std::make_shared<mmi::communication::CommunicationChannelTIDL>();
- }
-};
-
static Ecore_Event_Handler *exit_signal_event_handler = nullptr;
static Eina_Bool
plugin_module_proxy_factory = std::make_shared<mmi::PluginModuleProxyFactoryDefault>();
}
- communication_channel_factory = std::make_shared<CommunicationChannelFactoryTIDL>();
+ communication_channel_factory = std::make_shared<mmi::communication::CommunicationChannelManagerFactory>();
mmi::Manager manager(communication_channel_factory, plugin_module_proxy_factory);
mmi_manager_library_srcs = [
'mmi-manager.cpp',
- 'mmi-ipc-tidl.cpp',
'mmi-client.cpp',
'mmi-common.cpp',
'mmi-data-gateway.cpp',
'mmi-plugin-module-proxy.cpp',
'mmi-plugin-module-registry.cpp',
'mmi-self-container.cpp',
- 'mmi_stub.c',
]
-bundle_dep = dependency('bundle', method : 'pkg-config')
-dlog_dep = dependency('dlog', method : 'pkg-config')
+foreach platform_specific_manager_file : mmi_platform_specific_manager_files
+ message('Platform Specific File : ' + platform_specific_manager_file)
+ mmi_manager_library_srcs += platform_specific_manager_file
+endforeach
+
ecore_dep = dependency('ecore', method : 'pkg-config')
glib_dep = dependency('glib-2.0', method : 'pkg-config')
-rpc_port_dep = dependency('rpc-port')
-libtzplatform_config_dep = dependency('libtzplatform-config')
+dl_dep = meson.get_compiler('c').find_library('dl', required : true)
mmi_manager_deps = [
mmi_declared_dep,
- bundle_dep,
- dlog_dep,
ecore_dep,
glib_dep,
- rpc_port_dep,
- libtzplatform_config_dep,
+ dl_dep,
]
+foreach platform_specific_dependency : mmi_platform_specific_dependencies
+ message('Platform Specific Dependency : ' + platform_specific_dependency)
+ extra_dep = dependency(platform_specific_dependency, method : 'pkg-config')
+ mmi_manager_deps += extra_dep
+endforeach
+
+mmi_extra_include_dir = ''.join(['../../', mmi_platform_specific_include_directory])
mmi_manager_include_dirs = include_directories(
'.',
'../common/',
'../../capi/',
'../../external/',
+ mmi_extra_include_dir,
)
mmi_manager_library = library('mmi_manager',
mmi_manager_library_srcs,
- include_directories : [ mmi_manager_include_dirs ],
+ include_directories : [mmi_manager_include_dirs],
dependencies : [mmi_manager_deps],
install_dir : mmi_prefix_libdir,
- install : true
+ install : true,
)
mmi_manager_declared_dep = declare_dependency(
mmi_manager_declared_dep
]
+message('prefix')
+message(mmi_prefix)
executable('mmi-manager',
mmi_manager_program_srcs,
- include_directories : [ mmi_manager_include_dirs ],
+ include_directories : [ mmi_manager_include_dirs],
dependencies : [mmi_manager_program_deps],
install_dir : mmi_prefix_bindir,
install : true,
- pie : true
+ pie : true,
)
install_data('mmi-manager.xml', install_dir:'/usr/share/packages/')
#include "mmi-client.h"
#include "mmi-common.h"
#include "mmi-manager-log.h"
-#include "mmi_stub.h"
namespace mmi {
ClientManager::~ClientManager() {
}
+// LCOV_EXCL_START
void ClientManager::on_observer_event(
const COMMUNICATION_CHANNEL_EVENT_TYPE &event, std::any data) {
try {
LOGE("Failed to cast message data: %s", e.what());
}
}
+// LCOV_EXCL_STOP
int ClientManager::initialize() {
return MMI_ERROR_NONE;
#include "mmi-common.h"
#include "mmi-communication-channel.h"
-#include "mmi_stub.h"
namespace mmi {
#define __MMI_COMMON_H__
#include <stdbool.h>
-#include <tizen.h>
+#include "mmi-platform-config.h"
#ifndef MMI_API
#define MMI_API __attribute__ ((visibility("default")))
--- /dev/null
+#include "mmi-ipc-ecore.h"
+
+#include <sstream>
+
+namespace mmi {
+
+namespace communication {
+
+std::shared_ptr<mmi::communication::CommunicationChannelManager>
+mmi::communication::CommunicationChannelManagerFactory::create_channel() {
+ return std::make_shared<CommunicationChannelEcoreIPC>();
+}
+
+CommunicationChannelEcoreIPC::CommunicationChannelEcoreIPC() {
+ if (!ecore_ipc_init()) {
+ _E("Ecore IPC init failed");
+ }
+}
+
+CommunicationChannelEcoreIPC::~CommunicationChannelEcoreIPC() {
+ if (!ecore_ipc_shutdown()) {
+ _E("Ecore IPC shutdown failed");
+ }
+}
+
+int CommunicationChannelEcoreIPC::connect() {
+ if (m_server) {
+ return MMI_ERROR_OPERATION_FAILED;
+ }
+ m_server = ecore_ipc_server_add(ECORE_IPC_REMOTE_SYSTEM, "localhost", 9999, this);
+ ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD, handler_client_add, this);
+ ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL, handler_client_del, this);
+ ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA, handler_client_data, this);
+ return 0;
+}
+
+int CommunicationChannelEcoreIPC::disconnect(void) {
+ if (m_server) {
+ ecore_ipc_server_del(m_server);
+ m_server = nullptr;
+ }
+ return 0;
+}
+
+int CommunicationChannelEcoreIPC::send(Message *message) {
+ if (!message) {
+ _E("Message object is NULL");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ auto client = m_clients.find(message->sender);
+ if (client != m_clients.end()) {
+ const char *msg = "test message from server";
+ ecore_ipc_client_send(client->second, 0, 0, 0, 0, 0, msg, strlen(msg));
+ } else {
+ _E("Client with sender information %s does not exist", message->sender.c_str())
+ }
+ return 0;
+}
+
+void CommunicationChannelEcoreIPC::on_observer_event(
+ const WORKFLOW_OUTPUT_EVENT_TYPE &event, std::any data)
+{
+ try {
+ WorkflowOutputEventOutputGenerated *output_generated = std::any_cast<WorkflowOutputEventOutputGenerated*>(data);
+ if (!output_generated) {
+ LOGE("Failed to get output generated data !");
+ return;
+ }
+ size_t byte_size = 0;
+ byte_size += sizeof(int); // local_workflow_instance_id
+ byte_size += sizeof(size_t); // source_name_length
+ byte_size += output_generated->source_name.length(); // source_name
+ byte_size += sizeof(size_t); // data_size
+ byte_size += output_generated->data_size; // data_bytes
+
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ int index = 0;
+ memcpy(bytes + index, &(output_generated->local_workflow_instance_id), sizeof(int));
+ index += sizeof(int);
+
+ size_t source_name_length = output_generated->source_name.length();
+ memcpy(bytes + index, &source_name_length, sizeof(size_t));
+ index += sizeof(size_t);
+ memcpy(bytes + index, output_generated->source_name.c_str(), source_name_length);
+ index += source_name_length;
+
+ memcpy(bytes + index, &(output_generated->data_size), sizeof(size_t));
+ index += sizeof(size_t);
+ memcpy(bytes + index, output_generated->data_bytes, output_generated->data_size);
+ index += output_generated->data_size;
+
+ const auto &client = m_clients.find(output_generated->client_id);
+ if (client != m_clients.end()) {
+ ecore_ipc_client_send(client->second, 0, 0, 0, 0, 0, bytes, byte_size);
+ }
+
+ free(bytes);
+ } catch (const std::bad_any_cast &e) {
+ LOGE("Failed to cast message data: %s", e.what());
+ }
+}
+
+Eina_Bool CommunicationChannelEcoreIPC::handler_client_add(void *data, int ev_type, void *ev)
+{
+ Ecore_Ipc_Event_Client_Add *e = (Ecore_Ipc_Event_Client_Add *)ev;
+ _I("Client Added : %p", e->client);
+
+ CommunicationChannelEcoreIPC *channel = static_cast<CommunicationChannelEcoreIPC*>(data);
+ if (channel) {
+ channel->on_client_added(e->client);
+ }
+
+ return EINA_TRUE;
+}
+
+void CommunicationChannelEcoreIPC::on_client_added(Ecore_Ipc_Client *client)
+{
+ std::stringstream ss;
+ ss << client;
+ std::string sender = ss.str();
+ auto exists = m_clients.find(sender);
+ if (exists != m_clients.end()) {
+ _E("Client with same sender string exists!!!, overwriting : %s", sender.c_str());
+ }
+ m_clients[sender] = client;
+ m_connected = true;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::CONNECTED,
+ sender);
+}
+
+Eina_Bool CommunicationChannelEcoreIPC::handler_client_del(void *data, int ev_type, void *ev)
+{
+ Ecore_Ipc_Event_Client_Del *e = (Ecore_Ipc_Event_Client_Del *)ev;
+ LOGI("Client Deleted : %p", e->client);
+
+ CommunicationChannelEcoreIPC *channel = static_cast<CommunicationChannelEcoreIPC*>(data);
+ if (channel) {
+ channel->on_client_deleted(e->client);
+ }
+ return EINA_TRUE;
+}
+
+void CommunicationChannelEcoreIPC::on_client_deleted(Ecore_Ipc_Client *client)
+{
+ std::stringstream ss;
+ ss << client;
+ std::string sender = ss.str();
+ m_clients.erase(sender);
+ m_connected = false;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::DISCONNECTED,
+ sender);
+}
+
+Eina_Bool CommunicationChannelEcoreIPC::handler_client_data(void *data, int ev_type, void *ev)
+{
+ Ecore_Ipc_Event_Client_Data *e = (Ecore_Ipc_Event_Client_Data*)ev;
+ LOGI("Client Data Received : %p", e->client);
+
+ CommunicationChannelEcoreIPC *channel = static_cast<CommunicationChannelEcoreIPC*>(data);
+ if (channel) {
+ channel->on_client_message(e->client, e->data, e->size);
+ }
+ return EINA_TRUE;
+}
+
+void CommunicationChannelEcoreIPC::on_client_message(Ecore_Ipc_Client *client, void *data, int size)
+{
+ if (size < sizeof(CLIENT_MESSAGE_TYPE)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+
+ std::stringstream ss;
+ ss << client;
+ std::string sender = ss.str();
+
+ CLIENT_MESSAGE_TYPE type;
+ memcpy(&type, data, sizeof(CLIENT_MESSAGE_TYPE));
+
+ switch(type)
+ {
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_CREATE:
+ {
+ struct workflow_instance_create_payload {
+ int local_workflow_instance_id;
+ mmi_standard_workflow_type_e workflow_type;
+ } payload;
+ if (size < sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+ memcpy(&payload, data + sizeof(CLIENT_MESSAGE_TYPE), sizeof(payload));
+ ClientMessageWorkflowInstanceCreate message;
+ message.sender = sender;
+ message.local_workflow_instance_id = payload.local_workflow_instance_id;
+ message.workflow_type = payload.workflow_type;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_DESTROY:
+ {
+ struct workflow_instance_destroy_payload {
+ int local_workflow_instance_id;
+ } payload;
+ if (size < sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+ memcpy(&payload, data + sizeof(CLIENT_MESSAGE_TYPE), sizeof(payload));
+ ClientMessageWorkflowInstanceDestroy message;
+ message.sender = sender;
+ message.local_workflow_instance_id = payload.local_workflow_instance_id;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_SET_ATTRIBUTE:
+ {
+ struct workflow_instance_set_attribute_payload {
+ int local_workflow_instance_id;
+ char attribute_name[MMI_NAME_MAX_LENGTH];
+ size_t value_size;
+ } payload;
+ if (size < sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+
+ memcpy(&payload, data + sizeof(CLIENT_MESSAGE_TYPE), sizeof(payload));
+ mmi_primitive_value_h value = nullptr;
+ int index = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload);
+ mmi_primitive_value_from_bytes((unsigned char *)data + index, payload.value_size, &value);
+
+ mmi_attribute_h attribute = nullptr;
+ mmi_attribute_create(value, payload.attribute_name, &attribute);
+
+ ClientMessageWorkflowInstanceSetAttribute message;
+ message.sender = sender;
+ message.local_workflow_instance_id = payload.local_workflow_instance_id;
+ message.attribute = attribute;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+
+ mmi_attribute_destroy(attribute);
+ mmi_primitive_value_destroy(value);
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_EMIT_SIGNAL:
+ {
+ struct workflow_instance_emit_signal_payload {
+ int local_workflow_instance_id;
+ char signal_name[MMI_NAME_MAX_LENGTH];
+ int signal_parameter_count;
+ } payload;
+ if (size < sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+ memcpy(&payload, data + sizeof(CLIENT_MESSAGE_TYPE), sizeof(payload));
+ int index = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload);
+ _D("Signal Name %s, Parameter Count : %d", payload.signal_name, payload.signal_parameter_count);
+
+ mmi_signal_h signal;
+ mmi_signal_create(payload.signal_name, &signal);
+
+ for (int loop = 0;loop < payload.signal_parameter_count;loop++) {
+ char parameter_name[MMI_NAME_MAX_LENGTH];
+ memcpy(parameter_name, data + index, MMI_NAME_MAX_LENGTH);
+ index += MMI_NAME_MAX_LENGTH;
+
+ _D("Parameter Name : %s", parameter_name);
+
+ int value_size = 0;
+ memcpy(&value_size, data + index, sizeof(int));
+ index += sizeof(int);
+
+ mmi_primitive_value_h value;
+ mmi_primitive_value_from_bytes((unsigned char*)data + index, value_size, &value);
+ index += value_size;
+
+ mmi_signal_parameter_h parameter;
+ mmi_signal_parameter_create(value, parameter_name, ¶meter);
+
+ mmi_signal_add_parameter(signal, parameter);
+
+ mmi_signal_parameter_destroy(parameter);
+ mmi_primitive_value_destroy(value);
+ }
+
+ ClientMessageWorkflowInstanceEmitSignal message;
+ message.sender = sender;
+ message.local_workflow_instance_id = payload.local_workflow_instance_id;
+ message.signal = signal;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+
+ mmi_signal_destroy(signal);
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_ACTIVATE:
+ {
+ struct workflow_instance_activate_payload {
+ int local_workflow_instance_id;
+ } payload;
+ if (size < sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+ memcpy(&payload, data + sizeof(CLIENT_MESSAGE_TYPE), sizeof(payload));
+ ClientMessageWorkflowInstanceActivate message;
+ message.sender = sender;
+ message.local_workflow_instance_id = payload.local_workflow_instance_id;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_DEACTIVATE:
+ {
+ struct workflow_instance_deactivate_payload {
+ int local_workflow_instance_id;
+ } payload;
+ if (size < sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload)) {
+ _E("Data Size too small : %d", size)
+ return;
+ }
+ memcpy(&payload, data + sizeof(CLIENT_MESSAGE_TYPE), sizeof(payload));
+ ClientMessageWorkflowInstanceDeactivate message;
+ message.sender = sender;
+ message.local_workflow_instance_id = payload.local_workflow_instance_id;
+ notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+ }
+ break;
+ }
+}
+
+}; // namespace communication
+
+}; // namespace mmi
+
--- /dev/null
+#pragma once
+
+#include <map>
+
+#include <Ecore.h>
+#include <Ecore_Ipc.h>
+
+#include "mmi-communication-channel.h"
+
+namespace mmi {
+
+namespace communication {
+
+class CommunicationChannelEcoreIPC : public CommunicationChannelManager {
+public:
+ CommunicationChannelEcoreIPC();
+ ~CommunicationChannelEcoreIPC();
+
+ int connect() override;
+ int disconnect(void) override;
+ int send(Message *message) override;
+
+ void on_observer_event(
+ const WORKFLOW_OUTPUT_EVENT_TYPE &event, std::any data) override;
+private:
+ static Eina_Bool handler_client_add(void *data, int ev_type, void *ev);
+ static Eina_Bool handler_client_del(void *data, int ev_type, void *ev);
+ static Eina_Bool handler_client_data(void *data, int ev_type, void *ev);
+
+ void on_client_added(Ecore_Ipc_Client *client);
+ void on_client_deleted(Ecore_Ipc_Client *client);
+ void on_client_message(Ecore_Ipc_Client *client, void* data, int size);
+
+private:
+ Ecore_Ipc_Server *m_server{nullptr};
+ bool m_connected{false};
+ std::map<std::string, Ecore_Ipc_Client*> m_clients;
+};
+
+}; // namespace communication
+
+}; // namespace mmi
+
namespace communication {
+std::shared_ptr<CommunicationChannelManager> CommunicationChannelManagerFactory ::create_channel() {
+ return std::make_shared<mmi::communication::CommunicationChannelTIDL>();
+}
+
CommunicationChannelTIDL::CommunicationChannelTIDL() {
}
CommunicationChannelTIDL::~CommunicationChannelTIDL() {
}
+// LCOV_EXCL_START
int CommunicationChannelTIDL::connect() {
int r;
LOGD("mmi_api_handler_initialize");
workflow_instance_create,
workflow_instance_destroy,
workflow_instance_set_attribute,
+ workflow_instance_emit_signal,
workflow_instance_activate,
workflow_instance_deactivate,
workflow_instance_register_result_callback,
return MMI_ERROR_NONE;
}
+int CommunicationChannelTIDL::workflow_instance_emit_signal(rpc_port_stub_mmi_context_h context,
+ int local_workflow_instance_id, bundle *signal, void *user_data) {
+ CommunicationChannelTIDL *channel = static_cast<CommunicationChannelTIDL*>(user_data);
+
+ std::string sender;
+ if (!get_sender_string(context, channel, sender))
+ return MMI_ERROR_INVALID_PARAMETER;
+
+ char *name = nullptr;
+ bundle_get_str(signal, "name", &name);
+
+ int *parameter_count = nullptr;
+ size_t byte_size;
+ bundle_get_byte(signal, "parameter_count", (void**)¶meter_count, &byte_size);
+
+ mmi_signal_h restored_signal;
+ mmi_signal_create(name, &restored_signal);
+
+ for (int loop = 0; loop < *parameter_count; loop++)
+ {
+ std::string name_string = std::string("parameter_name_") + std::to_string(loop);
+
+ char *parameter_name;
+ bundle_get_str(signal, name_string.c_str(), ¶meter_name);
+
+ _D("Parameter Name : %s", parameter_name);
+
+ std::string size_string = std::string("parameter_size_") + std::to_string(loop);
+
+ size_t *value_size = nullptr;
+ bundle_get_byte(signal, size_string.c_str(), (void **)&value_size, &byte_size);
+
+ std::string data_string = std::string("parameter_data_") + std::to_string(loop);
+
+ unsigned char *value_bytes = nullptr;
+ bundle_get_byte(signal, data_string.c_str(), (void **)&value_bytes, &byte_size);
+
+ mmi_primitive_value_h value;
+ mmi_primitive_value_from_bytes(value_bytes, *value_size, &value);
+
+ mmi_signal_parameter_h parameter;
+ mmi_signal_parameter_create(value, parameter_name, ¶meter);
+
+ mmi_signal_add_parameter(restored_signal, parameter);
+
+ mmi_signal_parameter_destroy(parameter);
+ mmi_primitive_value_destroy(value);
+ }
+
+ ClientMessageWorkflowInstanceEmitSignal msg;
+ msg.sender = sender;
+ msg.local_workflow_instance_id = local_workflow_instance_id;
+ msg.signal = restored_signal;
+
+ notify_message_received(channel, static_cast<Message*>(&msg));
+
+ mmi_signal_destroy(restored_signal);
+
+ return MMI_ERROR_NONE;
+}
+
int CommunicationChannelTIDL::workflow_instance_activate(rpc_port_stub_mmi_context_h context,
int local_workflow_instance_id, void *user_data) {
CommunicationChannelTIDL *channel = static_cast<CommunicationChannelTIDL*>(user_data);
const WORKFLOW_OUTPUT_EVENT_TYPE &event, std::any data) {
try {
WorkflowOutputEventOutputGenerated *output_generated = std::any_cast<WorkflowOutputEventOutputGenerated*>(data);
-
+ if (!output_generated) {
+ LOGE("Failed to get output generated data !");
+ return;
+ }
+
rpc_port_stub_mmi_result_cb_h callback = get_invoke_callbacks(output_generated->client_id, output_generated->local_workflow_instance_id);
std::string source_name = output_generated->source_name;
- bundle *data_b = reinterpret_cast<bundle*>(output_generated->data);
- int ret = rpc_port_stub_mmi_result_cb_invoke(callback, source_name.c_str(), data_b);
+ bundle *encoded = bundle_create();
+ bundle_add_byte(encoded, "data", output_generated->data_bytes, output_generated->data_size);
+
+ int ret = rpc_port_stub_mmi_result_cb_invoke(callback, source_name.c_str(), encoded);
if (ret != RPC_PORT_ERROR_NONE) {
LOGE("Failed to send result to client !");
}
+
+ bundle_free(encoded);
} catch (const std::bad_any_cast &e) {
LOGE("Failed to cast message data: %s", e.what());
}
}
m_invoke_callbacks.clear();
}
+// LCOV_EXCL_STOP
} // namespace communication
//
static void on_terminate(rpc_port_stub_mmi_context_h context, void *user_data);
static int workflow_instance_create(rpc_port_stub_mmi_context_h context,
- int local_workflow_instance_id, int workflow_type, void *user_data);
+ int local_workflow_instance_id, int workflow_type, void *user_data);
static int workflow_instance_destroy(rpc_port_stub_mmi_context_h context,
- int local_workflow_instance_id, void *user_data);
+ int local_workflow_instance_id, void *user_data);
static int workflow_instance_set_attribute(rpc_port_stub_mmi_context_h context,
- int workflow_instance, bundle *attribute, void *user_data);
+ int workflow_instance, bundle *attribute, void *user_data);
+ static int workflow_instance_emit_signal(rpc_port_stub_mmi_context_h context,
+ int workflow_instance, bundle *signal, void *user_data);
static int workflow_instance_activate(rpc_port_stub_mmi_context_h context,
- int local_workflow_instance_id, void *user_data);
+ int local_workflow_instance_id, void *user_data);
static int workflow_instance_deactivate(rpc_port_stub_mmi_context_h context,
- int local_workflow_instance_id, void *user_data);
+ int local_workflow_instance_id, void *user_data);
static int workflow_instance_register_result_callback(rpc_port_stub_mmi_context_h context,
- int local_workflow_instance_id, rpc_port_stub_mmi_result_cb_h callback, void *user_data);
+ int local_workflow_instance_id, rpc_port_stub_mmi_result_cb_h callback, void *user_data);
void set_invoke_callbacks(std::string appid, int local_workflow_instance_id,
rpc_port_stub_mmi_result_cb_h callback);
#ifndef __MMI_MANAGER_LOG_H__
#define __MMI_MANAGER_LOG_H__
-#include <dlog.h>
+#include "mmi-platform-config.h"
+
+#include "magic_enum/magic_enum.hpp"
#ifdef LOG_TAG
#undef LOG_TAG
#define _W LOGW
#endif
+template <typename T>
+static std::string enum_to_string(T value) {
+ return std::string(magic_enum::enum_name(value));
+}
+
#endif // __MMI_MANAGER_LOG_H__
return ret;
}
+// LCOV_EXCL_START
bool NodeInstanceManager::destroy_node_instance(
std::shared_ptr<NodeInstance> node_instance) {
if (node_instance) {
return true;
}
+// LCOV_EXCL_STOP
void NodeInstanceManager::initialize() {
}
m_plugin_module_proxy_provider = plugin_module_proxy_provider;
}
+// LCOV_EXCL_START
void NodeInstanceManager::set_port_instance_manager(
std::shared_ptr<IPortInstanceManager> port_instance_manager) {
m_port_instance_manager = port_instance_manager;
if (output_generated) {
PortInstance *port_instance = reinterpret_cast<PortInstance*>(output_generated->port_instance);
if (port_instance) {
- _D("Output generated for %p : %p", port_instance, output_generated->data);
port_instance->on_output_data_generated(output_generated->data);
}
}
LOGE("Failed to cast message data: %s", e.what());
}
}
+// LCOV_EXCL_STOP
} // namespace mmi
mmi_standard_node_sub_type_e node_sub_type)
: m_node_type(node_type)
, m_node_sub_type(node_sub_type) {
- _D("Node instance is created : %d %d", m_node_type, to_int(m_node_sub_type));
+ _D("Node instance is created : %s %s",
+ enum_to_string(m_node_type).c_str(), to_string(m_node_sub_type).c_str());
}
NodeInstance::~NodeInstance() {
- _D("Node instance is destroyed : %d %d", m_node_type, to_int(m_node_sub_type));
+ _D("Node instance is destroyed : %s %s",
+ enum_to_string(m_node_type).c_str(), to_string(m_node_sub_type).c_str());
}
static bool node_type_and_subtype_matches(
mmi_standard_node_controller_type_e controller_type;
mmi_standard_node_get_controller_type(node, &controller_type);
return controller_type == std::get<mmi_standard_node_controller_type_e>(node_sub_type);
+ } else if (node_type == MMI_STANDARD_NODE_TYPE_ACTION) {
+ mmi_standard_node_action_type_e action_type;
+ mmi_standard_node_get_action_type(node, &action_type);
+ return action_type == std::get<mmi_standard_node_action_type_e>(node_sub_type);
}
} catch (const std::bad_variant_access &e) {
_E("Failed to get node sub type : %s", e.what());
}
}
- _D("Node instance is initialized for %d %d",
- m_node_type, to_int(m_node_sub_type));
+ _D("Node instance is initialized for %s %s",
+ enum_to_string(m_node_type).c_str(), to_string(m_node_sub_type).c_str());
if (m_port_instance_manager == nullptr) {
_E("Port instance manager is not set");
return false;
}
+// LCOV_EXCL_START
mmi_plugin_module_node_instance_info_s plugin_module_node_instance_info;
plugin_module_node_instance_info.node = static_cast<mmi_node_instance_h>(this);
plugin_module_node_instance_info.port_info_count = 0;
if (m_callbacks.initialized_cb != nullptr) {
m_callbacks.initialized_cb(static_cast<mmi_node_instance_h>(this));
}
+// LCOV_EXCL_STOP
return true;
}
m_callbacks.deinitialized_cb(static_cast<mmi_node_instance_h>(this));
}
- m_plugin_module_proxy->remove_node_instance_info(static_cast<mmi_node_instance_h>(this));
+ if (m_plugin_module_proxy) {
+ m_plugin_module_proxy->remove_node_instance_info(static_cast<mmi_node_instance_h>(this));
+ }
return true;
}
return m_plugin_module_proxy;
}
+// LCOV_EXCL_START
bool NodeInstance::set_attribute(mmi_attribute_h attribute)
{
char *name = nullptr;
m_callbacks.attribute_set_cb(static_cast<mmi_node_instance_h>(this), attribute);
return true;
}
+// LCOV_EXCL_STOP
+
+bool NodeInstance::handle_signal(mmi_signal_h signal)
+{
+ char *name = nullptr;
+ mmi_signal_get_name(signal, &name);
+ _D("Set signal : %s [%p]", name, signal);
+ free(name);
+ if (m_callbacks.signal_received_cb == nullptr) {
+ _E("Set signal callback is not set");
+ return false;
+ }
+ m_callbacks.signal_received_cb(static_cast<mmi_node_instance_h>(this), signal);
+ return true;
+}
} // namespace mmi
std::shared_ptr<PortInstance> get_port_instance(std::string name);
std::shared_ptr<IPluginModuleProxy> get_plugin_module_proxy();
- bool set_attribute(mmi_attribute_h attribute);
+ virtual bool set_attribute(mmi_attribute_h attribute);
+ virtual bool handle_signal(mmi_signal_h signal);
protected:
std::shared_ptr<INodePrototypeStore> m_prototype_store;
std::shared_ptr<IPluginModuleProxyProvider> m_plugin_module_proxy_provider;
std::get<mmi_standard_node_controller_type_e>(m_sub_type.value());
valid = true;
}
+ break;
+ case mmi_standard_node_type_e::MMI_STANDARD_NODE_TYPE_ACTION: {
+ auto subclass =
+ std::get<mmi_standard_node_action_type_e>(m_sub_type.value());
+ valid = true;
+ }
+ break;
}
} catch (const std::bad_variant_access& e) {
_E("[std::bad_variant_access] Failed to create node prototype: %s", e.what());
#include "mmi-node-processor.h"
#include "mmi-node-logic.h"
#include "mmi-node-controller.h"
+#include "mmi-node-action.h"
#include "mmi-plugin-module-proxy.h"
+#include "mmi-manager-log.h"
#include <memory>
#include <optional>
mmi_standard_node_source_type_e,
mmi_standard_node_processor_type_e,
mmi_standard_node_logic_type_e,
- mmi_standard_node_controller_type_e
+ mmi_standard_node_controller_type_e,
+ mmi_standard_node_action_type_e
> mmi_standard_node_sub_type_e;
-static int to_int(mmi_standard_node_sub_type_e sub_type) {
+static std::string to_string(mmi_standard_node_sub_type_e sub_type) {
try {
- return std::visit([](auto&& arg) -> int {
+ return std::visit([](auto&& arg) -> std::string {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::monostate>)
- return -1;
+ return std::string("Unknown");
else
- return static_cast<int>(arg);
+ return enum_to_string(arg);
}, sub_type);
} catch (std::bad_variant_access&) {
- return -1;
+ return std::string("Unknown");
}
}
namespace mmi {
+// LCOV_EXCL_START
static void port_instance_output_handler(mmi_port_instance_h port, mmi_data_h data, void *user_data) {
PluginModuleProxySharedLibrary* proxy = static_cast<PluginModuleProxySharedLibrary*>(user_data);
if (proxy == nullptr) {
void PluginModuleProxySharedLibrary::remove_node_instance_info(mmi_node_instance_h node_instance) {
mmi_plugin_storage_remove_node_instance_info(node_instance);
}
+// LCOV_EXCL_STOP
} // namespace mmi
class PluginModuleProxyFactoryDefault : public IPluginModuleProxyFactory {
public:
virtual std::vector<PluginModuleInfo> get_plugin_module_list() override {
- const std::string plugin_module_path{"/usr/share/mmi/plugins"};
+ const std::string plugin_module_path{MMI_INSTALL_PREFIX "/share/mmi/plugins"};
std::vector<PluginModuleInfo> plugin_module_list;
for (const auto & entry : std::filesystem::directory_iterator(plugin_module_path)) {
PluginModuleInfo info{mmi_plugin_module_type_e::SHARED_LIBRARY, entry.path().string()};
prototype->set_sub_type(controller_type);
break;
}
+ case MMI_STANDARD_NODE_TYPE_ACTION: {
+ mmi_standard_node_action_type_e action_type;
+ mmi_standard_node_get_action_type(node, &action_type);
+ prototype->set_sub_type(action_type);
+ break;
+ }
}
size_t port_count;
if (prototype) {
prototype->set_plugin_module_info(plugin_module_info);
bool ret = m_node_prototype_store->add_node_prototype(prototype);
- _D("Add Node Prototype ret(%d): %d %d %s", ret, prototype->get_type(), to_int(prototype->get_sub_type()), plugin_module_info.plugin_module_identifier.c_str());
+ _D("Add Node Prototype ret(%d): %s %s %s", ret,
+ enum_to_string(prototype->get_type()).c_str(),
+ to_string(prototype->get_sub_type()).c_str(),
+ plugin_module_info.plugin_module_identifier.c_str());
}
}
} else {
node_info.node_sub_type = controller_type;
}
break;
+ case MMI_STANDARD_NODE_TYPE_ACTION: {
+ mmi_standard_node_action_type_e action_type;
+ mmi_standard_node_get_action_type(workflow_info->node_infos[i].node, &action_type);
+ node_info.node_sub_type = action_type;
+ }
+ break;
default: {
_E("Invalid node type");
return nullptr;
attribute_default_value_info.default_value = default_value;
prototype->add_attribute_default_value_info(attribute_default_value_info);
+
+ mmi_attribute_destroy(default_value);
+ }
+
+ for (size_t i = 0; i < workflow_info->signal_assignment_info_count; i++) {
+ SignalAssignmentInfo signal_assignment_info;
+ signal_assignment_info.signal_name = workflow_info->signal_assignment_infos[i].signal_name;
+ signal_assignment_info.target_node_name = workflow_info->signal_assignment_infos[i].target_node_name;
+ signal_assignment_info.target_signal_name = workflow_info->signal_assignment_infos[i].target_signal_name;
+
+ prototype->add_signal_assignment_info(signal_assignment_info);
}
for (size_t i = 0; i < workflow_info->output_assignment_info_count; i++) {
}
void PortInstance::on_output_data_generated(mmi_data_h data) {
- _D("Data generated : this[%p] data[%p]", this, data);
-
for (auto it = m_data_gateways.begin(); it != m_data_gateways.end(); ++it) {
(*it)->send_data(data);
}
}
void PortInstance::on_output_data_received(mmi_data_h data) {
- _D("Data received : this[%p] data[%p] input_data_received_cb[%p]",
- this, data, m_callbacks.input_data_received_cb);
if (m_callbacks.input_data_received_cb) {
m_callbacks.input_data_received_cb(static_cast<mmi_port_instance_h>(this), data);
}
namespace mmi {
+// LCOV_EXCL_START
std::map<mmi_port_instance_h, mmi_plugin_module_node_instance_info_s> g_node_instance_info_map;
TestNodePluginModule::TestNodePluginModule() {
}
}
}
+// LCOV_EXCL_STOP
} // namespace mmi
return nullptr;
}
+// LCOV_EXCL_START
void WorkflowInstanceManager::on_observer_event(
const COMMUNICATION_CHANNEL_EVENT_TYPE &event, std::any data) {
try {
handle_set_attribute(msg);
}
break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_EMIT_SIGNAL: {
+ auto *msg = static_cast<ClientMessageWorkflowInstanceEmitSignal*>(message);
+ handle_emit_signal(msg);
+ }
+ break;
case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_ACTIVATE: {
auto *msg = static_cast<ClientMessageWorkflowInstanceActivate*>(message);
handle_activate(msg);
}
}
+void WorkflowInstanceManager::handle_emit_signal(
+ ClientMessageWorkflowInstanceEmitSignal *message) {
+ if (nullptr == message) {
+ LOGE("Message is null");
+ return;
+ }
+
+ std::shared_ptr<WorkflowInstance> instance =
+ get_workflow_instance(message->sender, message->local_workflow_instance_id);
+ if (instance) {
+ instance->handle_signal(message->signal);
+ }
+}
+
void WorkflowInstanceManager::handle_activate(
ClientMessageWorkflowInstanceActivate *message) {
if (nullptr == message) {
instance->deactivate();
}
}
+// LCOV_EXCL_STOP
} // namespace mmi
void handle_create(ClientMessageWorkflowInstanceCreate *message);
void handle_destroy(ClientMessageWorkflowInstanceDestroy *message);
void handle_set_attribute(ClientMessageWorkflowInstanceSetAttribute *message);
+ void handle_emit_signal(ClientMessageWorkflowInstanceEmitSignal *message);
void handle_activate(ClientMessageWorkflowInstanceActivate *message);
void handle_deactivate(ClientMessageWorkflowInstanceDeactivate *message);
protected:
#include "mmi-manager-log.h"
#include "mmi-workflow-output-event.h"
-#include <bundle.h>
namespace mmi {
WorkflowInstance::WorkflowInstance() {
mmi_data_transfer_callback callback = [this](mmi_data_h data, std::string name) {
_D("Data received from Data Gateway");
unsigned char *data_bytes = nullptr;
- size_t data_byte_size = 0;
- mmi_data_to_bytes(data, &data_bytes, &data_byte_size);
-
- bundle *encoded = bundle_create();
- bundle_add_byte(encoded, "data", data_bytes, data_byte_size);
+ size_t data_size = 0;
+ mmi_data_to_bytes(data, &data_bytes, &data_size);
WorkflowOutputEventOutputGenerated event;
event.source_name = name;
- event.data = encoded;
event.client_id = get_client_id();
+ event.data_bytes = data_bytes;
+ event.data_size = data_size;
event.local_workflow_instance_id = get_local_workflow_instance_id();
this->notify_observers(WORKFLOW_OUTPUT_EVENT_TYPE::OUTPUT_GENERATED, &event);
+
+ free(data_bytes);
};
output_data_gateway->set_callback(callback);
m_node_instance_manager->destroy_node_instance(node_instance.second);
}
m_node_instances.clear();
+ m_state = WORKFLOW_INSTANCE_STATE::NONE;
}
+// LCOV_EXCL_START
void WorkflowInstance::activate() {
if (WORKFLOW_INSTANCE_STATE::INITIALIZED != m_state) {
_E("Workflow instance state is not INITIALIZED");
m_state = WORKFLOW_INSTANCE_STATE::INITIALIZED;
}
+// LCOV_EXCL_STOP
bool WorkflowInstance::set_attribute(mmi_attribute_h attribute) {
_D("Setting attribute : %p", attribute);
std::shared_ptr<NodeInstance> target_node_instance =
m_node_instances.at(it->target_node_name);
if (target_node_instance) {
- mmi_attribute_set_name(attribute, it->target_attribute_name.c_str());
- target_node_instance->set_attribute(attribute);
+ mmi_attribute_h cloned = nullptr;
+ mmi_attribute_clone(attribute, &cloned);
+ mmi_attribute_set_name(cloned, it->target_attribute_name.c_str());
+ target_node_instance->set_attribute(cloned);
+ mmi_attribute_destroy(cloned);
} else {
_E("Could not find target node instance : %s", it->target_node_name.c_str());
}
return true;
}
+bool WorkflowInstance::handle_signal(mmi_signal_h signal) {
+ _D("Handling Signal : %p", signal);
+
+ std::shared_ptr<WorkflowPrototype> prototype = m_prototype_store->get_workflow_prototype(m_type);
+ if (nullptr == prototype) {
+ _E("Could not find prototype information from store");
+ return false;
+ }
+
+ char *name = nullptr;
+ if (MMI_ERROR_NONE == mmi_signal_get_name(signal, &name)) {
+ std::vector<SignalAssignmentInfo> signal_assignment_infos =
+ prototype->get_signal_assignment_infos();
+
+ if (!name) {
+ _E("Signal name is null");
+ return false;
+ }
+ auto it = std::find_if(signal_assignment_infos.begin(), signal_assignment_infos.end(),
+ [name](const SignalAssignmentInfo& info) {
+ return (info.signal_name.compare(name) == 0);
+ });
+ if (it != signal_assignment_infos.end()) {
+ _D("Found signal assignment info : %s", name);
+ try {
+ std::shared_ptr<NodeInstance> target_node_instance =
+ m_node_instances.at(it->target_node_name);
+ if (target_node_instance) {
+ target_node_instance->handle_signal(signal);
+ } else {
+ _E("Could not find target node instance : %s", it->target_node_name.c_str());
+ }
+ } catch (std::out_of_range& e) {
+ _E("Failed to find node instance : %s", it->target_node_name.c_str());
+ }
+ } else {
+ _E("Could not find signal assignment info : %s", name);
+ }
+ }
+ free(name);
+
+ return true;
+}
+
+// LCOV_EXCL_START
void WorkflowInstance::on_observer_event(
const PLUGIN_MODULE_EVENT_TYPE &event, std::any data) {
try {
LOGE("Failed to cast message data: %s", e.what());
}
}
+// LCOV_EXCL_STOP
bool WorkflowInstance::set_attribute_default_values() {
_D("Setting attribute default value");
bool set_attribute(mmi_attribute_h attribute);
bool set_attribute_default_values();
+ bool handle_signal(mmi_signal_h signal);
+
void on_observer_event(
const PLUGIN_MODULE_EVENT_TYPE &event, std::any data) override;
private:
return true;
}
+// LCOV_EXCL_START
std::shared_ptr<WorkflowPrototype> WorkflowPrototypeManager::get_workflow_prototype(
mmi_standard_workflow_type_e type) {
std::shared_ptr<WorkflowPrototype> ret;
void WorkflowPrototypeManager::deinitialize() {
}
+// LCOV_EXCL_STOP
} // namespace mmi
}
bool WorkflowPrototype::add_attribute_default_value_info(AttributeDefaultValueInfo attribute_default_value_info) {
- m_attribute_default_value_infos.push_back(attribute_default_value_info);
+ AttributeDefaultValueInfo cloned_info;
+ mmi_attribute_clone(attribute_default_value_info.default_value, &(cloned_info.default_value));
+
+ m_attribute_default_value_infos.push_back(cloned_info);
+ return true;
+}
+
+bool WorkflowPrototype::add_signal_assignment_info(SignalAssignmentInfo signal_assignment_info) {
+ m_signal_assignment_infos.push_back(signal_assignment_info);
return true;
}
return m_link_infos;
}
+// LCOV_EXCL_START
std::vector<AttributeAssignmentInfo> WorkflowPrototype::get_attribute_assignment_infos() {
return m_attribute_assignment_infos;
}
std::vector<AttributeDefaultValueInfo> WorkflowPrototype::get_attribute_default_value_infos() {
return m_attribute_default_value_infos;
}
+// LCOV_EXCL_STOP
+
+std::vector<SignalAssignmentInfo> WorkflowPrototype::get_signal_assignment_infos() {
+ return m_signal_assignment_infos;
+}
std::vector<OutputAssignmentInfo> WorkflowPrototype::get_output_assignment_infos() {
return m_output_assignment_infos;
} AttributeDefaultValueInfo;
typedef struct {
+ std::string signal_name;
+ std::string target_node_name;
+ std::string target_signal_name;
+} SignalAssignmentInfo;
+
+typedef struct {
std::string output_name;
std::string from_node_name;
std::string from_port_name;
bool add_link_info(LinkInfo link_info);
bool add_attribute_assignment_info(AttributeAssignmentInfo attribute_assignment_info);
bool add_attribute_default_value_info(AttributeDefaultValueInfo attribute_default_value_info);
+ bool add_signal_assignment_info(SignalAssignmentInfo signal_assignment_info);
bool add_output_assignment_info(OutputAssignmentInfo output_assignment_info);
mmi_standard_workflow_type_e get_type();
std::vector<LinkInfo> get_link_infos();
std::vector<AttributeAssignmentInfo> get_attribute_assignment_infos();
std::vector<AttributeDefaultValueInfo> get_attribute_default_value_infos();
+ std::vector<SignalAssignmentInfo> get_signal_assignment_infos();
std::vector<OutputAssignmentInfo> get_output_assignment_infos();
private:
PluginModuleInfo m_plugin_module_info;
std::vector<LinkInfo> m_link_infos;
std::vector<AttributeAssignmentInfo> m_attribute_assignment_infos;
std::vector<AttributeDefaultValueInfo> m_attribute_default_value_infos;
+ std::vector<SignalAssignmentInfo> m_signal_assignment_infos;
std::vector<OutputAssignmentInfo> m_output_assignment_infos;
};
'mmi-workflow.cpp',
'mmi-workflow-instance.cpp',
'mmi-workflow-script.cpp',
- 'mmi-ipc-tidl.h',
- 'mmi-ipc-tidl.cpp',
'mmi-log.h',
- 'mmi_proxy.h',
- 'mmi_proxy.c',
'mmi-primitive-value.cpp',
'mmi-data.cpp',
'mmi-attribute.cpp',
'mmi-node-processor.cpp',
'mmi-node-logic.cpp',
'mmi-node-controller.cpp',
+ 'mmi-node-action.cpp',
'mmi-port.cpp',
'mmi-signal.cpp',
'mmi-plugin-storage.cpp',
+ 'mmi-config-parser.cpp',
]
+foreach platform_specific_client_file : mmi_platform_specific_client_files
+ message('Platform Specific File : ' + platform_specific_client_file)
+ mmi_srcs += platform_specific_client_file
+endforeach
+
glib_dep = dependency('glib-2.0', method : 'pkg-config')
gio_dep = dependency('gio-2.0', method : 'pkg-config')
-bundle_dep = dependency('bundle', method : 'pkg-config')
-dlog_dep = dependency('dlog', method : 'pkg-config')
-rpc_port_dep = dependency('rpc-port', method : 'pkg-config')
-libtzplatform_config_dep = dependency('libtzplatform-config')
ecore_dep = dependency('ecore', method : 'pkg-config')
+xml_dep = dependency('libxml-2.0', method : 'pkg-config')
mmi_deps = [
ecore_dep,
glib_dep,
gio_dep,
- bundle_dep,
- dlog_dep,
- rpc_port_dep,
- libtzplatform_config_dep]
+ xml_dep
+ ]
+
+foreach platform_specific_dependency : mmi_platform_specific_dependencies
+ message('Platform Specific Dependency : ' + platform_specific_dependency)
+ extra_dep = dependency(platform_specific_dependency, method : 'pkg-config')
+ mmi_deps += extra_dep
+endforeach
+mmi_extra_include_dir = ''.join(['../../', mmi_platform_specific_include_directory])
mmi_include_dirs = include_directories(
'.',
'../common',
- '../../capi'
+ '../../capi',
+ mmi_extra_include_dir,
)
mmi_lib = shared_library(
class ClientManager : public SimpleEventObserver<COMMUNICATION_CHANNEL_EVENT_TYPE> {
public:
ClientManager(
- ICommunicationChannelFactory *factory,
+ CommunicationChannelClientFactory *factory,
SimpleEventObserver<COMMUNICATION_CHANNEL_EVENT_TYPE> *observer)
: m_communication_channel_factory(factory),
m_communication_channel_observer(observer) {
if (m_reference_count == 0) {
if (m_communication_channel) {
m_communication_channel->disconnect();
- m_communication_channel_factory->destroy_channel(m_communication_channel);
+ m_communication_channel.reset();
}
m_communication_channel = nullptr;
return true;
}
- CommunicationChannel* get_communication_channel() {
+// LCOV_EXCL_START
+ std::shared_ptr<CommunicationChannelClient> get_communication_channel() {
return m_communication_channel;
}
WorkflowInstanceManager* get_workflow_instance_manager() {
void on_observer_event(
const COMMUNICATION_CHANNEL_EVENT_TYPE &event, std::any data) override {
+ if (event == COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED) {
+ try {
+ Message *message = std::any_cast<Message*>(data);
+ if (message->message_group != MESSAGE_GROUP::CLIENT) {
+ LOGE("Message Group is not CLIENT");
+ return;
+ }
+ auto client_message = static_cast<ClientMessage*>(message);
+ switch (client_message->message_type) {
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_OUTPUT: {
+ handle_output(static_cast<ClientMessageWorkflowInstanceOutput*>(message));
+ }
+ break;
+ }
+ } catch (const std::bad_any_cast &e) {
+ LOGE("Failed to cast message data: %s", e.what());
+ }
+ }
+ }
+
+ void handle_output(ClientMessageWorkflowInstanceOutput *message) {
+ if (message) {
+ LOGI("Output message received");
+ WorkflowInstance *instance = m_workflow_instance_manager.get(message->local_workflow_instance_id);
+ if (instance) {
+ instance->call_output_callback(message->source_name, message->data);
+ }
+ }
}
+// LCOV_EXCL_STOP
private:
- ICommunicationChannelFactory* m_communication_channel_factory{nullptr};
- CommunicationChannel *m_communication_channel{nullptr};
- SimpleEventObserver<COMMUNICATION_CHANNEL_EVENT_TYPE>
- *m_communication_channel_observer;
+ CommunicationChannelClientFactory *m_communication_channel_factory{nullptr};
+ std::shared_ptr<CommunicationChannelClient> m_communication_channel;
+ SimpleEventObserver<COMMUNICATION_CHANNEL_EVENT_TYPE> *m_communication_channel_observer;
WorkflowInstanceManager m_workflow_instance_manager;
int m_reference_count{0};
--- /dev/null
+/*
+ * Copyright © 2023 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+#include <Ecore.h>
+#include <fcntl.h>
+#include "mmi-config-parser.h"
+#include "mmi-log.h"
+
+
+#define MMI_TAG_CONFIG_BASE_TAG "mmi-config"
+#define MMI_TAG_CONFIG_CONFIDENCE "confidence"
+
+static Ecore_Fd_Handler* g_config_fd_handler_noti = NULL;
+static int g_config_fd_noti;
+static int g_config_wd_noti;
+
+static xmlDocPtr g_config_doc = NULL;
+static mmi_config_s* g_config_info = NULL;
+
+
+static int mmi_parser_load_config(void)
+{
+ xmlDocPtr doc = NULL;
+ xmlNodePtr cur = NULL;
+
+ /* For Thread safety */
+ xmlInitParser();
+
+ if (0 == access(MMI_DEFAULT_CONFIG, F_OK)) {
+ doc = xmlParseFile(MMI_DEFAULT_CONFIG);
+ if (doc == NULL) {
+ LOGE("[ERROR] Fail to parse file error : %s", MMI_DEFAULT_CONFIG);
+ xmlCleanupParser();
+ return -1;
+ }
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ LOGE("[ERROR] Empty document(%p)", doc);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ xmlCleanupParser();
+ return -1;
+ }
+
+ if (xmlStrcmp(cur->name, (const xmlChar *) MMI_TAG_CONFIG_BASE_TAG)) {
+ LOGE("[ERROR] The wrong type, root node is NOT %s. doc(%p)", MMI_TAG_CONFIG_BASE_TAG, doc);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ xmlCleanupParser();
+ return -1;
+ }
+
+ cur = cur->xmlChildrenNode;
+ if (cur == NULL) {
+ LOGE("[ERROR] Empty document(%p)", doc);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ xmlCleanupParser();
+ return -1;
+ }
+
+ mmi_config_s* temp;
+ temp = (mmi_config_s*)calloc(1, sizeof(mmi_config_s));
+ if (NULL == temp) {
+ LOGE("[ERROR] Out of memory(%p)", doc);
+ xmlFreeDoc(doc);
+ doc = NULL;
+ xmlCleanupParser();
+ return -1;
+ }
+
+ while (cur != NULL) {
+ if (0 == xmlStrcmp(cur->name, (const xmlChar *)MMI_TAG_CONFIG_CONFIDENCE)) {
+ xmlChar *key = xmlNodeGetContent(cur);
+ if (NULL != key) {
+ temp->confidence = atof((char*)key);
+ xmlFree(key);
+ key = NULL;
+ } else {
+ LOGD("[ERROR] confidence is NULL");
+ }
+ }
+ cur = cur->next;
+ }
+
+ g_config_info = temp;
+ g_config_doc = doc;
+
+ return 0;
+}
+
+static int mmi_parser_unload_config(void)
+{
+ if (NULL != g_config_doc) {
+ LOGD("[DEBUG] Free g_config_doc(%p)", g_config_doc);
+ xmlFreeDoc(g_config_doc);
+ g_config_doc = NULL;
+ }
+
+ if (NULL != g_config_info) {
+ LOGE("[DEBUG] Free config_info(%p)", g_config_info);
+ free(g_config_info);
+ g_config_info = NULL;
+ }
+
+ xmlCleanupParser();
+ return 0;
+}
+
+static Eina_Bool mmi_config_mgr_inotify_event_cb(void* data, Ecore_Fd_Handler *fd_handler)
+{
+ LOGD("into mmi_config_mgr_inotify_event_cb");
+
+ int length;
+ struct inotify_event event;
+ memset(&event, '\0', sizeof(struct inotify_event));
+
+ length = read(g_config_fd_noti, &event, sizeof(struct inotify_event));
+ if (0 > length) {
+ LOGE("[ERROR] Empty Inotify event");
+ return ECORE_CALLBACK_DONE;
+ }
+
+ if (IN_CLOSE_WRITE == event.mask) {
+ /* check config changed state */
+ if (0 != mmi_parser_load_config())
+ return ECORE_CALLBACK_PASS_ON;
+
+ } else if (IN_DELETE_SELF == event.mask) {
+ LOGE("[ERROR] IN_DELETE_SELF event");
+
+ mmi_parser_unload_config();
+ mmi_parser_load_config();
+ } else {
+ LOGE("[ERROR] Undefined event (0x%x)", event.mask);
+ }
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static int mmi_config_mgr_register_config_event()
+{
+ /* get file notification handler */
+ int fd;
+ int wd;
+
+ fd = inotify_init();
+ if (fd < 0) {
+ LOGE("[ERROR] Fail get inotify fd");
+ return -1;
+ }
+ g_config_fd_noti = fd;
+
+ wd = inotify_add_watch(fd, MMI_DEFAULT_CONFIG, IN_CLOSE_WRITE|IN_DELETE_SELF);
+ g_config_wd_noti = wd;
+
+ g_config_fd_handler_noti = ecore_main_fd_handler_add(fd, ECORE_FD_READ,
+ (Ecore_Fd_Cb)mmi_config_mgr_inotify_event_cb, NULL, NULL, NULL);
+ if (NULL == g_config_fd_handler_noti) {
+ LOGE("[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)) {
+ LOGE("[WARNING] Fail to set non-block mode");
+ }
+
+ return 0;
+}
+
+static int mmi_config_mgr_unregister_config_event()
+{
+ /* delete inotify variable */
+ ecore_main_fd_handler_del(g_config_fd_handler_noti);
+ inotify_rm_watch(g_config_fd_noti, g_config_wd_noti);
+ close(g_config_fd_noti);
+
+ return 0;
+}
+
+int mmi_parser_initialize(void)
+{
+ if (0 != mmi_config_mgr_register_config_event()) {
+ LOGE("Fail to mmi_config_mgr_register_config_event");
+ }
+
+ if (0 != mmi_parser_load_config()) {
+ LOGE("Fail to mmi_parser_load_config");
+ }
+ return 0;
+}
+
+int mmi_parser_deinitialize(void)
+{
+ if (0 != mmi_config_mgr_unregister_config_event()) {
+ LOGE("Fail to mmi_config_mgr_unregister_config_event");
+ }
+
+ if (0 != mmi_parser_unload_config()) {
+ LOGE("Fail to mmi_parser_unload_config");
+ }
+ return 0;
+}
+
+int mmi_parser_get_confidence(float *confidence)
+{
+ LOGD("[DEBUG] Get confidence");
+
+ if (g_config_info) {
+ *confidence = g_config_info->confidence;
+ } else {
+ LOGE("[ERROR] g_config_info is NULL");
+ return -1;
+ }
+
+ return 0;
+}
return get_element_pointer_in_array(struct_handle, index * 2 + 1);
}
-
+// LCOV_EXCL_START
int mmi_data_create_bool(bool value, mmi_data_h *data) {
if (nullptr == data) {
_E("[ERROR] Some parameters are invalid");
*data = new_data;
- _D("[DEBUG] Success to create for bool(%d)", value);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
int mmi_data_create_int(int value, mmi_data_h *data) {
if (nullptr == data) {
*data = new_data;
- _D("[DEBUG] Success to create for int(%d)", value);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_data_create_float(float value, mmi_data_h *data) {
if (nullptr == data) {
_E("[ERROR] Some parameters are invalid");
*data = new_data;
- _D("[DEBUG] Success to create for float(%f)", value);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
int mmi_data_create_text(const char *value, mmi_data_h *data) {
if (nullptr == data || nullptr == value) {
*data = new_data;
- _D("[DEBUG] Success to create for string(%s)", value);
return MMI_ERROR_NONE;
}
*data = new_data;
- _D("[DEBUG] Success to create for audio data. len(%zu)", len);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_data_create_video(const void *ptr, size_t len, mmi_data_h *data) {
if (nullptr == data || nullptr == ptr || 0 == len) {
_E("[ERROR] Some parameters are invalid");
*data = new_data;
- _D("[DEBUG] Success to create for video data. len(%zu)", len);
return MMI_ERROR_NONE;
}
*data = new_data;
- _D("[DEBUG] Success to create for user identification data. len(%zu)", len);
+ return MMI_ERROR_NONE;
+}
+// LCOV_EXCL_STOP
+
+int mmi_data_create_coordinate(int x, int y, mmi_data_h *data) {
+ if (nullptr == data) {
+ _E("[ERROR] Some parameters are invalid");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ auto new_data = reinterpret_cast<mmi_data_s *>(malloc(sizeof(mmi_data_s)));
+ if (nullptr == new_data) {
+ _E("[ERROR] Fail to allocate memory for mmi data");
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
+
+ new_data->type = MMI_DATA_TYPE_COORDINATE;
+ new_data->data = malloc(sizeof(int) * 2);
+ if (nullptr == new_data->data) {
+ _E("[ERROR] Fail to allocate memory for raw data");
+ free(new_data);
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
+
+ (reinterpret_cast<int *>(new_data->data))[0] = x;
+ (reinterpret_cast<int *>(new_data->data))[1] = y;
+ new_data->datalen = sizeof(int) * 2;
+
+ *data = new_data;
+
+ return MMI_ERROR_NONE;
+}
+
+int mmi_data_create_bounding_box(int x, int y, int w, int h, mmi_data_h *data) {
+ if (nullptr == data) {
+ _E("[ERROR] Some parameters are invalid");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ auto new_data = reinterpret_cast<mmi_data_s *>(malloc(sizeof(mmi_data_s)));
+ if (nullptr == new_data) {
+ _E("[ERROR] Fail to allocate memory for mmi data");
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
+
+ new_data->type = MMI_DATA_TYPE_BOUNDING_BOX;
+ new_data->data = malloc(sizeof(int) * 4);
+ if (nullptr == new_data->data) {
+ _E("[ERROR] Fail to allocate memory for raw data");
+ free(new_data);
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
+
+ (reinterpret_cast<int *>(new_data->data))[0] = x;
+ (reinterpret_cast<int *>(new_data->data))[1] = y;
+ (reinterpret_cast<int *>(new_data->data))[2] = w;
+ (reinterpret_cast<int *>(new_data->data))[3] = h;
+ new_data->datalen = sizeof(int) * 4;
+
+ *data = new_data;
+
return MMI_ERROR_NONE;
}
*data = new_data;
- _D("[DEBUG] Success to create empty array");
return MMI_ERROR_NONE;
}
return MMI_ERROR_OUT_OF_MEMORY;
}
- _D("[DEBUG] Success to add element(%zu)", get_count_of_elements(array));
return MMI_ERROR_NONE;
}
*struct_handle = new_data;
- _D("[DEBUG] Success to create empty array");
return MMI_ERROR_NONE;
}
return MMI_ERROR_OUT_OF_MEMORY;
}
- _D("[DEBUG] Success to add element with name(%s)", name);
return MMI_ERROR_NONE;
}
*type = data->type;
- _D("[DEBUG] Success to get type(%d)", *type);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_data_get_bool(mmi_data_h data, bool *value) {
if (nullptr == data || nullptr == value) {
_E("[ERROR] Some parameters are invalid");
*value = *(reinterpret_cast<bool *>(data->data));
- _D("[DEBUG] Success to get value: bool(%d)", *value);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
int mmi_data_get_int(mmi_data_h data, int *value) {
if (nullptr == data || nullptr == value) {
*value = *(reinterpret_cast<int *>(data->data));
- _D("[DEBUG] Success to get value: int(%d)", *value);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_data_get_float(mmi_data_h data, float *value) {
if (nullptr == data || nullptr == value) {
_E("[ERROR] Some parameters are invalid");
*value = *(reinterpret_cast<float *>(data->data));
- _D("[DEBUG] Success to get value: float(%f)", *value);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
int mmi_data_get_text(mmi_data_h data, const char **string) {
if (nullptr == data || nullptr == string) {
*string = reinterpret_cast<char *>(data->data);
- _D("[DEBUG] Success to get value: string(%s)", *string);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_data_get_audio(mmi_data_h data, const void **ptr, size_t *len) {
if (nullptr == data || nullptr == ptr || nullptr == len) {
_E("[ERROR] Some parameters are invalid");
*len = data->datalen;
*ptr = data->data;
- _D("[DEBUG] Success to get value: audio(%zu)", *len);
return MMI_ERROR_NONE;
}
*len = data->datalen;
*ptr = data->data;
- _D("[DEBUG] Success to get value: video(%zu)", *len);
return MMI_ERROR_NONE;
}
*len = data->datalen;
*ptr = data->data;
- _D("[DEBUG] Success to get value: user_identification(%zu)", *len);
+ return MMI_ERROR_NONE;
+}
+// LCOV_EXCL_STOP
+
+int mmi_data_get_coordinate(mmi_data_h data, int *x, int *y) {
+ if (nullptr == data || nullptr == x || nullptr == y) {
+ _E("[ERROR] Some parameters are invalid");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ if (data->type != MMI_DATA_TYPE_COORDINATE) {
+ _E("[ERROR] Data type is not matched");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ int *array = (reinterpret_cast<int *>(data->data));
+ if (nullptr == array || data->datalen != (sizeof(int) * 2)) {
+ _E("[ERROR] The parameter contains invalid data");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ *x = array[0];
+ *y = array[1];
+
+ return MMI_ERROR_NONE;
+}
+
+int mmi_data_get_bounding_box(mmi_data_h data, int *x, int *y, int *w, int *h) {
+ if (nullptr == data || nullptr == x || nullptr == y || nullptr == w || nullptr == h) {
+ _E("[ERROR] Some parameters are invalid");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ if (data->type != MMI_DATA_TYPE_BOUNDING_BOX) {
+ _E("[ERROR] Data type is not matched");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ int *array = (reinterpret_cast<int *>(data->data));
+ if (nullptr == array || data->datalen != (sizeof(int) * 4)) {
+ _E("[ERROR] The parameter contains invalid data");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ *x = array[0];
+ *y = array[1];
+ *w = array[2];
+ *h = array[3];
+
return MMI_ERROR_NONE;
}
*count = get_count_of_elements(array);
- _D("[DEBUG] Success to get array count(%zu)", *count);
return MMI_ERROR_NONE;
}
*element = *(get_element_pointer_in_array(array, index));
- _D("[DEBUG] Success to get array element on index(%zu)", index);
return MMI_ERROR_NONE;
}
*element = target_element;
- _D("[DEBUG] Success to get element on name(%s)", name);
return MMI_ERROR_NONE;
}
*count = get_count_of_struct_elements(struct_handle);
- _D("[DEBUG] Success to get struct count(%zu)", *count);
return MMI_ERROR_NONE;
}
mmi_data_h *element = get_element_name_pointer_in_struct(struct_handle, index);
mmi_data_get_text(*element, string);
- _D("[DEBUG] Success to get struct element name on index(%zu)", index);
return MMI_ERROR_NONE;
}
*element = *(get_element_value_pointer_in_struct(struct_handle, index));
- _D("[DEBUG] Success to get struct element value on index(%zu)", index);
return MMI_ERROR_NONE;
}
data->type = MMI_DATA_TYPE_ANY;
free(data);
- _D("[DEBUG] Success to destroy");
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_data_get_node_timestamp(mmi_data_h data, mmi_data_timestamp_h *timestamp) {
if (nullptr == data || nullptr == timestamp) {
return MMI_ERROR_INVALID_PARAMETER;
*length = total_size;
}
- _D("[DEBUG] Success to convert data to bytes");
-
return MMI_ERROR_NONE;
}
*data = value;
}
- _D("[DEBUG] Success to convert from bytes. type(%d), size(%zu)", type, length);
-
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
--- /dev/null
+#include "mmi-ipc-ecore.h"
+
+namespace mmi {
+
+namespace communication {
+
+std::shared_ptr<CommunicationChannelClient>
+CommunicationChannelClientFactory::create_channel() {
+ return std::make_shared<CommunicationChannelEcoreIPC>();
+}
+
+CommunicationChannelEcoreIPC::CommunicationChannelEcoreIPC() {
+ if (!ecore_ipc_init()) {
+ _E("Ecore IPC init failed");
+ }
+}
+
+CommunicationChannelEcoreIPC::~CommunicationChannelEcoreIPC() {
+ if (!ecore_ipc_shutdown()) {
+ _E("Ecore IPC shutdown failed");
+ }
+}
+
+int CommunicationChannelEcoreIPC::connect() {
+ if (m_server) {
+ return MMI_ERROR_OPERATION_FAILED;
+ }
+ m_server = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, "localhost", 9999, this);
+ ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, handler_server_add, this);
+ ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, handler_server_del, this);
+ ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, handler_server_data, this);
+ return 0;
+}
+
+int CommunicationChannelEcoreIPC::disconnect(void) {
+ if (m_server) {
+ ecore_ipc_server_del(m_server);
+ m_server = nullptr;
+ }
+ return 0;
+}
+
+int CommunicationChannelEcoreIPC::send(Message *message) {
+ auto clientMessage = static_cast<ClientMessage*>(message);
+ CLIENT_MESSAGE_TYPE type = clientMessage->message_type;
+
+ switch (type)
+ {
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_CREATE:
+ {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceCreate *>(message);
+ struct workflow_instance_create_payload {
+ int local_workflow_instance_id;
+ mmi_standard_workflow_type_e workflow_type;
+ } payload;
+ payload.local_workflow_instance_id = subclass->local_workflow_instance_id;
+ payload.workflow_type = subclass->workflow_type;
+ size_t byte_size = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(workflow_instance_create_payload);
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ if (bytes) {
+ memcpy(bytes, &type, sizeof(CLIENT_MESSAGE_TYPE));
+ memcpy(bytes + sizeof(CLIENT_MESSAGE_TYPE), &payload, sizeof(payload));
+ ecore_ipc_server_send(m_server, 0, 0, 0, 0, 0, bytes, byte_size);
+ free(bytes);
+ }
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_DESTROY:
+ {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceDestroy *>(message);
+ struct workflow_instance_destroy_payload {
+ int local_workflow_instance_id;
+ } payload;
+ payload.local_workflow_instance_id = subclass->local_workflow_instance_id;
+ size_t byte_size = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(workflow_instance_destroy_payload);
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ if (bytes) {
+ memcpy(bytes, &type, sizeof(CLIENT_MESSAGE_TYPE));
+ memcpy(bytes + sizeof(CLIENT_MESSAGE_TYPE), &payload, sizeof(workflow_instance_destroy_payload));
+ ecore_ipc_server_send(m_server, 0, 0, 0, 0, 0, bytes, byte_size);
+ free(bytes);
+ }
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_SET_ATTRIBUTE:
+ {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceSetAttribute *>(message);
+
+ char *attribute_name = nullptr;
+ mmi_attribute_get_name(subclass->attribute, &attribute_name);
+ mmi_primitive_value_h value = nullptr;
+ mmi_attribute_get_value(subclass->attribute, &value);
+ unsigned char *value_bytes = nullptr;
+ size_t value_size = 0;
+ mmi_primitive_value_to_bytes(value, &value_bytes, &value_size);
+
+ struct workflow_instance_set_attribute_payload {
+ int local_workflow_instance_id;
+ char attribute_name[MMI_NAME_MAX_LENGTH];
+ size_t value_size;
+ } payload;
+ payload.local_workflow_instance_id = subclass->local_workflow_instance_id;
+
+ strncpy(payload.attribute_name, attribute_name, MMI_NAME_MAX_LENGTH - 1);
+ payload.attribute_name[MMI_NAME_MAX_LENGTH - 1] = '\0';
+ payload.value_size = value_size;
+
+ size_t byte_size = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload);
+ byte_size += value_size;
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ size_t index = 0;
+ if (bytes) {
+ memcpy(bytes, &type, sizeof(CLIENT_MESSAGE_TYPE));
+ index += sizeof(CLIENT_MESSAGE_TYPE);
+ memcpy(bytes + index, &payload, sizeof(payload));
+ index += sizeof(payload);
+ memcpy(bytes + index, value_bytes, value_size);
+
+ ecore_ipc_server_send(m_server, 0, 0, 0, 0, 0, bytes, byte_size);
+ }
+ free(bytes);
+ free(value_bytes);
+ mmi_primitive_value_destroy(value);
+ free(attribute_name);
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_EMIT_SIGNAL:
+ {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceEmitSignal *>(message);
+ char *signal_name = nullptr;
+ mmi_signal_get_name(subclass->signal, &signal_name);
+
+ struct workflow_instance_emit_signal_payload {
+ int local_workflow_instance_id;
+ char signal_name[MMI_NAME_MAX_LENGTH];
+ int signal_parameter_count;
+ } payload;
+
+ payload.local_workflow_instance_id = subclass->local_workflow_instance_id;
+ strncpy(payload.signal_name, signal_name, MMI_NAME_MAX_LENGTH - 1);
+ payload.signal_name[MMI_NAME_MAX_LENGTH - 1] = '\0';
+ mmi_signal_get_parameter_count(subclass->signal, &(payload.signal_parameter_count));
+
+ int index = 0;
+ size_t byte_size = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(payload);
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ if (!bytes) return MMI_ERROR_OPERATION_FAILED;
+
+ memcpy(bytes, &type, sizeof(CLIENT_MESSAGE_TYPE));
+ index = sizeof(CLIENT_MESSAGE_TYPE);
+ memcpy(bytes + index, &payload, sizeof(payload));
+ index += sizeof(payload);
+
+ for (int loop = 0;loop < payload.signal_parameter_count;loop++) {
+ mmi_signal_parameter_h parameter = nullptr;
+ mmi_signal_get_parameter(subclass->signal, loop, ¶meter);
+
+ char *parameter_name = nullptr;
+ mmi_signal_parameter_get_name(parameter, ¶meter_name);
+
+ byte_size += MMI_NAME_MAX_LENGTH;
+ bytes = (unsigned char*)(realloc(bytes, byte_size));
+ memcpy(bytes + index, parameter_name, MMI_NAME_MAX_LENGTH);
+ index += MMI_NAME_MAX_LENGTH;
+
+ mmi_primitive_value_h value = nullptr;
+ mmi_signal_parameter_get_value(parameter, &value);
+
+ unsigned char *value_bytes = nullptr;
+ size_t value_size = 0;
+ mmi_primitive_value_to_bytes(value, &value_bytes, &value_size);
+
+ byte_size += (sizeof(int) + value_size);
+ bytes = (unsigned char*)(realloc(bytes, byte_size));
+ memcpy(bytes + index, &value_size, sizeof(int));
+ index += (sizeof(int));
+ memcpy(bytes + index, value_bytes, value_size);
+ index += (value_size);
+
+ free(value_bytes);
+ mmi_primitive_value_destroy(value);
+ mmi_signal_parameter_destroy(parameter);
+ }
+
+ if (bytes) {
+ ecore_ipc_server_send(m_server, 0, 0, 0, 0, 0, bytes, byte_size);
+ free(bytes);
+ }
+ free(signal_name);
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_ACTIVATE:
+ {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceActivate *>(message);
+ struct workflow_instance_activate_payload {
+ int local_workflow_instance_id;
+ } payload;
+ payload.local_workflow_instance_id = subclass->local_workflow_instance_id;
+ size_t byte_size = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(workflow_instance_activate_payload);
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ if (bytes) {
+ memcpy(bytes, &type, sizeof(CLIENT_MESSAGE_TYPE));
+ memcpy(bytes + sizeof(CLIENT_MESSAGE_TYPE), &payload, sizeof(workflow_instance_activate_payload));
+ ecore_ipc_server_send(m_server, 0, 0, 0, 0, 0, bytes, byte_size);
+ free(bytes);
+ }
+ }
+ break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_DEACTIVATE:
+ {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceDeactivate *>(message);
+ struct workflow_instance_deactivate_payload {
+ int local_workflow_instance_id;
+ } payload;
+ payload.local_workflow_instance_id = subclass->local_workflow_instance_id;
+ size_t byte_size = sizeof(CLIENT_MESSAGE_TYPE) + sizeof(workflow_instance_deactivate_payload);
+ unsigned char *bytes = (unsigned char*)(malloc(byte_size));
+ if (bytes) {
+ memcpy(bytes, &type, sizeof(CLIENT_MESSAGE_TYPE));
+ memcpy(bytes + sizeof(CLIENT_MESSAGE_TYPE), &payload, sizeof(workflow_instance_deactivate_payload));
+ ecore_ipc_server_send(m_server, 0, 0, 0, 0, 0, bytes, byte_size);
+ free(bytes);
+ }
+ }
+ break;
+ };
+ return 0;
+}
+
+Eina_Bool CommunicationChannelEcoreIPC::handler_server_add(void *data, int ev_type, void *ev)
+{
+ Ecore_Ipc_Event_Server_Add *e = (Ecore_Ipc_Event_Server_Add *)ev;
+ LOGI("Server Added : %p", e->server);
+ CommunicationChannelEcoreIPC *channel = static_cast<CommunicationChannelEcoreIPC*>(data);
+ if (channel) {
+ channel->m_connected = true;
+ channel->notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::CONNECTED);
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool CommunicationChannelEcoreIPC::handler_server_del(void *data, int ev_type, void *ev)
+{
+ Ecore_Ipc_Event_Server_Del *e = (Ecore_Ipc_Event_Server_Del *)ev;
+ LOGI("Server Deleted : %p", e->server);
+ CommunicationChannelEcoreIPC *channel = static_cast<CommunicationChannelEcoreIPC*>(data);
+ if (channel) {
+ channel->m_connected = false;
+ channel->notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::DISCONNECTED);
+ }
+ return EINA_TRUE;
+}
+
+Eina_Bool CommunicationChannelEcoreIPC::handler_server_data(void *data, int ev_type, void *ev)
+{
+ Ecore_Ipc_Event_Server_Data *e = (Ecore_Ipc_Event_Server_Data*)ev;
+ LOGI("Server Data Received : %p", e->server);
+ ClientMessageWorkflowInstanceOutput message;
+
+ size_t index = 0;
+ memcpy(&(message.local_workflow_instance_id), e->data + index, sizeof(int));
+ index += sizeof(int);
+
+ size_t source_name_length = 0;
+ memcpy(&(source_name_length), e->data + index, sizeof(size_t));
+ index += sizeof(size_t);
+
+ char *bytes = (char*)(malloc(source_name_length + 1));
+ memcpy(bytes, e->data + index, source_name_length);
+ bytes[source_name_length] = '\0';
+
+ message.source_name = (char*)bytes;
+ index += source_name_length;
+
+ free(bytes);
+
+ size_t data_size = 0;
+ memcpy(&(data_size), e->data + index, sizeof(size_t));
+ index += sizeof(size_t);
+
+ mmi_data_h output_data = nullptr;
+ if (MMI_ERROR_NONE !=
+ mmi_data_from_bytes((unsigned char*)(e->data + index), data_size, &(output_data))) {
+ LOGE("[ERROR] Failed to restore data from bytes");
+ return EINA_TRUE;
+ }
+ message.data = output_data;
+
+ CommunicationChannelEcoreIPC *channel = static_cast<CommunicationChannelEcoreIPC*>(data);
+ if (channel) {
+ channel->m_connected = false;
+ channel->notify_observers(
+ COMMUNICATION_CHANNEL_EVENT_TYPE::MESSAGE_RECEIVED,
+ static_cast<Message*>(&message));
+ }
+ mmi_data_destroy(output_data);
+ return EINA_TRUE;
+}
+
+}; // namespace communication
+
+}; // namespace mmi
+
--- /dev/null
+#pragma once
+
+#include <Ecore.h>
+#include <Ecore_Ipc.h>
+
+#include "mmi-communication-channel.h"
+
+namespace mmi {
+
+namespace communication {
+
+class CommunicationChannelEcoreIPC : public CommunicationChannelClient {
+public:
+ CommunicationChannelEcoreIPC();
+ ~CommunicationChannelEcoreIPC();
+
+ int connect() override;
+ int disconnect(void) override;
+ int send(Message *message) override;
+
+private:
+ static Eina_Bool handler_server_add(void *data, int ev_type, void *ev);
+ static Eina_Bool handler_server_del(void *data, int ev_type, void *ev);
+ static Eina_Bool handler_server_data(void *data, int ev_type, void *ev);
+
+private:
+ Ecore_Ipc_Server *m_server{nullptr};
+ bool m_connected{false};
+};
+
+}; // namespace communication
+
+}; // namespace mmi
+
namespace communication {
+std::shared_ptr<CommunicationChannelClient> CommunicationChannelClientFactory::create_channel() {
+ return std::make_shared<CommunicationChannelTIDL>();
+}
+
CommunicationChannelTIDL::CommunicationChannelTIDL() {
}
workflow_instance_set_attribute(subclass->local_workflow_instance_id, subclass->attribute);
}
break;
+ case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_EMIT_SIGNAL: {
+ auto subclass = static_cast<ClientMessageWorkflowInstanceEmitSignal*>(message);
+ workflow_instance_emit_signal(subclass->local_workflow_instance_id, subclass->signal);
+ }
+ break;
case CLIENT_MESSAGE_TYPE::WORKFLOW_INSTANCE_ACTIVATE: {
auto subclass = static_cast<ClientMessageWorkflowInstanceActivate*>(message);
workflow_instance_activate(subclass->local_workflow_instance_id);
return ret;
}
+int CommunicationChannelTIDL::workflow_instance_emit_signal(int local_workflow_instance_id, mmi_signal_h signal) {
+ LOGI("Emitting signal for workflow instance (%d)", local_workflow_instance_id);
+ int ret = MMI_ERROR_NONE;
+
+ if (NULL == signal) {
+ LOGE("Parameter is NULL or empty");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ rpc_port_proxy_mmi_h rpc_h = static_cast<rpc_port_proxy_mmi_h>(m_rpc_h);
+ if (NULL == rpc_h) {
+ LOGE("Fail to get tidl rpc info");
+ return MMI_ERROR_OPERATION_FAILED;
+ }
+
+ if (false == is_connected()) {
+ LOGE("Try to connect again");
+ int ret = retry_connection(rpc_h);
+ if (RPC_PORT_ERROR_NONE != ret) {
+ LOGE("Fail to retry connection(%d)", ret);
+ return MMI_ERROR_OPERATION_FAILED;
+ }
+ }
+
+ char *signal_name = nullptr;
+ mmi_signal_get_name(signal, &signal_name);
+
+ int parameter_count = 0;
+ mmi_signal_get_parameter_count(signal, ¶meter_count);
+
+ bundle *encoded = bundle_create();
+ bundle_add_str(encoded, "name", signal_name);
+ bundle_add_byte(encoded, "parameter_count", ¶meter_count, sizeof(int));
+
+ for (int loop = 0;loop < parameter_count;loop++) {
+ mmi_signal_parameter_h parameter = nullptr;
+ mmi_signal_get_parameter(signal, loop, ¶meter);
+
+ char *parameter_name = nullptr;
+ mmi_signal_parameter_get_name(parameter, ¶meter_name);
+
+ std::string name_string = std::string("parameter_name_") + std::to_string(loop);
+ bundle_add_str(encoded, name_string.c_str(), parameter_name);
+
+ mmi_primitive_value_h value = nullptr;
+ mmi_signal_parameter_get_value(parameter, &value);
+
+ unsigned char *value_bytes = nullptr;
+ size_t value_size = 0;
+
+ mmi_primitive_value_to_bytes(value, &value_bytes, &value_size);
+
+ std::string size_string = std::string("parameter_size_") + std::to_string(loop);
+ bundle_add_byte(encoded, size_string.c_str(), &value_size, sizeof(size_t));
+
+ std::string data_string = std::string("parameter_data_") + std::to_string(loop);
+ bundle_add_byte(encoded, data_string.c_str(), value_bytes, value_size);
+
+ mmi_primitive_value_destroy(value);
+ mmi_signal_parameter_destroy(parameter);
+ }
+
+ if (encoded) {
+ int ret = rpc_port_proxy_mmi_invoke_workflow_instance_emit_signal(rpc_h, local_workflow_instance_id, encoded);
+ bundle_free(encoded);
+
+ if (RPC_PORT_ERROR_NONE != ret) {
+ LOGE("Failed to set workflow signal(%d)\n", ret);
+ ret = MMI_ERROR_OPERATION_FAILED;
+ }
+ }
+
+ free(signal_name);
+ return ret;
+}
+
int CommunicationChannelTIDL::workflow_instance_activate(int local_workflow_instance_id) {
LOGI("Activating workflow instance of id (%d)", local_workflow_instance_id);
int workflow_instance_create(int local_workflow_instance_id, mmi_standard_workflow_type_e workflow_type, void *user_data);
int workflow_instance_destroy(int local_workflow_instance_id);
int workflow_instance_set_attribute(int local_workflow_instance_id, mmi_attribute_h attribute);
+ int workflow_instance_emit_signal(int local_workflow_instance_id, mmi_signal_h signal);
int workflow_instance_activate(int local_workflow_instance_id);
int workflow_instance_deactivate(int local_workflow_instance_id);
int workflow_instance_register_result_callback(int local_workflow_instance_id, void *user_data);
#ifndef __MMI_LOG_H__
#define __MMI_LOG_H__
-#include <dlog.h>
+#include "mmi-platform-config.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "MMI"
-#ifndef _E
-#define _E LOGE
-#endif
-
-#ifndef _D
-#define _D LOGD
-#endif
-
-#ifndef _I
-#define _I LOGI
-#endif
-
-#ifndef _W
-#define _W LOGW
-#endif
-
#endif // __MMI_LOG_H__
--- /dev/null
+/*
+ * Copyright (c) 2023 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 "mmi.h"
+#include "mmi-node-action.h"
+
+#include "mmi-log.h"
+
+int mmi_standard_node_create_action(mmi_standard_node_action_type_e type, mmi_node_h *node) {
+ if (nullptr == node) {
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+ *node = new mmi_node_s;
+ (*node)->type = MMI_STANDARD_NODE_TYPE_ACTION;
+ (*node)->sub_type = (int)type;
+ (*node)->ports = nullptr;
+ (*node)->port_count = 0;
+ memset(&(*node)->callbacks, 0, sizeof(mmi_node_callbacks));
+ return MMI_ERROR_NONE;
+}
+
+int mmi_standard_node_get_action_type(mmi_node_h node, mmi_standard_node_action_type_e *type) {
+ if (nullptr == node || nullptr == type) {
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+ *type = (mmi_standard_node_action_type_e)node->sub_type;
+ return MMI_ERROR_NONE;
+}
+
+int mmi_standard_node_register_action(mmi_standard_node_action_type_e type, mmi_node_callbacks *callbacks, mmi_node_h node) {
+ if (nullptr == callbacks || nullptr == node) {
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+ return MMI_ERROR_NONE;
+}
+
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_standard_node_register_logic(mmi_standard_node_logic_type_e type, mmi_node_callbacks *callbacks, mmi_node_h node) {
if (nullptr == callbacks || nullptr == node) {
return MMI_ERROR_INVALID_PARAMETER;
}
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_standard_node_register_processor(mmi_standard_node_processor_type_e type, mmi_node_callbacks *callbacks, mmi_node_h node) {
if (nullptr == callbacks || nullptr == node) {
return MMI_ERROR_INVALID_PARAMETER;
}
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_node_find_port(mmi_node_h node, mmi_port_type_e port_type, const char *port_name, mmi_port_h *port) {
if (nullptr == node || nullptr == port_name || nullptr == port) {
LOGE("[ERROR] parameter is null");
}
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
int mmi_node_get_type(mmi_node_h node, mmi_standard_node_type_e *type) {
if (nullptr == node || nullptr == type) {
}
break;
}
+// LCOV_EXCL_START
case MMI_STANDARD_NODE_TYPE_CONTROLLER: {
mmi_standard_node_controller_type_e node_controller_type;
mmi_standard_node_get_controller_type(node, &node_controller_type);
}
break;
}
+ case MMI_STANDARD_NODE_TYPE_ACTION: {
+ mmi_standard_node_action_type_e node_action_type;
+ mmi_standard_node_get_action_type(node, &node_action_type);
+ mmi_standard_node_action_type_e action_type;
+ mmi_standard_node_get_action_type(nodes[i], &action_type);
+ if (node_action_type == action_type) {
+ duplicated = true;
+ }
+ break;
+ }
+// LCOV_EXCL_STOP
}
}
if (duplicated) {
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
int mmi_node_instance_set_attribute(mmi_node_instance_h instance, mmi_attribute_h attribute) {
return MMI_ERROR_NONE;
}
int mmi_node_instance_update_pending_activation_result(mmi_error_e result) {
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
MMI_API int mmi_port_get_callbacks(mmi_port_h port, mmi_port_callbacks *callbacks) {
if (nullptr == port || nullptr == callbacks) {
LOGE("[ERROR] parameter is null");
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
MMI_API int mmi_port_set_name(mmi_port_h port, const char *name) {
if (nullptr == port || nullptr == name) {
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
MMI_API int mmi_port_instance_generate_output(mmi_port_instance_h instance, mmi_data_h data) {
mmi_plugin_module_event_handler_info_s event_handler_info = mmi_plugin_storage_get_plugin_module_event_handler();
void *user_data = mmi_plugin_storage_get_plugin_module_event_handler_user_data();
MMI_API int mmi_port_instance_announce_output_data_format(mmi_port_instance_h instance, const char *format) {
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
#include "mmi.h"
#include "mmi-signal.h"
+#include "mmi-log.h"
+
MMI_API int mmi_signal_parameter_create(mmi_primitive_value_h value, const char *name, mmi_signal_parameter_h *signal_parameter) {
if (signal_parameter == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ const size_t length = strlen(name);
+ if (0 == length || MMI_NAME_MAX_LENGTH <= length) {
+ _E("[ERROR] Length of name is invalid. length(%zu)", length);
+ return MMI_ERROR_INVALID_PARAMETER;
}
*signal_parameter = (mmi_signal_parameter_s*)calloc(1, sizeof(mmi_signal_parameter_s));
- if (*signal_parameter == NULL) return -1;
+ if (*signal_parameter == NULL) return MMI_ERROR_OUT_OF_MEMORY;
strncpy((*signal_parameter)->name, name, MMI_NAME_MAX_LENGTH - 1);
(*signal_parameter)->name[MMI_NAME_MAX_LENGTH - 1] = '\0';
mmi_primitive_value_clone(value, &((*signal_parameter)->value));
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_parameter_get_name(mmi_signal_parameter_h signal_parameter, char **name) {
if (signal_parameter == NULL || name == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
*name = strdup(signal_parameter->name);
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_parameter_get_value(mmi_signal_parameter_h signal_parameter, mmi_primitive_value_h *value) {
if (signal_parameter == NULL || value == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
mmi_primitive_value_clone(signal_parameter->value, value);
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_parameter_clone(mmi_signal_parameter_h signal_parameter, mmi_signal_parameter_h *cloned) {
if (cloned == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
*cloned = (mmi_signal_parameter_s*)calloc(1, sizeof(mmi_signal_parameter_s));
- if (*cloned == NULL) return -1;
+ if (*cloned == NULL) return MMI_ERROR_OUT_OF_MEMORY;
strncpy((*cloned)->name, signal_parameter->name, MMI_NAME_MAX_LENGTH - 1);
(*cloned)->name[MMI_NAME_MAX_LENGTH - 1] = '\0';
mmi_primitive_value_clone(signal_parameter->value, &((*cloned)->value));
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_parameter_destroy(mmi_signal_parameter_h signal_parameter) {
if (signal_parameter == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
mmi_primitive_value_destroy(signal_parameter->value);
free(signal_parameter);
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_create(const char *name, mmi_signal_h *handle) {
- if (handle == NULL) {
- return -1;
+ if (handle == NULL || name == NULL) {
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ const size_t length = strlen(name);
+ if (0 == length || MMI_NAME_MAX_LENGTH <= length) {
+ _E("[ERROR] Length of name is invalid. length(%zu)", length);
+ return MMI_ERROR_INVALID_PARAMETER;
}
*handle = (mmi_signal_s*)calloc(1, sizeof(mmi_signal_s));
- if (*handle == NULL) return -1;
+ if (*handle == NULL) return MMI_ERROR_OUT_OF_MEMORY;
strncpy((*handle)->name, name, MMI_NAME_MAX_LENGTH - 1);
(*handle)->name[MMI_NAME_MAX_LENGTH - 1] = '\0';
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_add_parameter(mmi_signal_h handle, mmi_signal_parameter_h parameter) {
if (handle == NULL || parameter == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
if (handle->parameter_count >= MMI_PARAMETER_MAX_COUNT) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ bool duplicated_name = false;
+ for (int loop = 0;loop < handle->parameter_count; loop++) {
+ if (strncmp(handle->parameters[loop]->name, parameter->name, MMI_NAME_MAX_LENGTH) == 0) {
+ duplicated_name = true;
+ }
+ }
+ if (duplicated_name) {
+ return MMI_ERROR_INVALID_PARAMETER;
}
mmi_signal_parameter_clone(parameter, &handle->parameters[handle->parameter_count]);
handle->parameter_count++;
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_get_name(mmi_signal_h handle, char **name) {
if (handle == NULL || name == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
- *name = handle->name;
- return 0;
+ *name = strdup(handle->name);
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_get_parameter_count(mmi_signal_h handle, int *count) {
if (handle == NULL || count == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
*count = handle->parameter_count;
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_get_parameter(mmi_signal_h handle, int index, mmi_signal_parameter_h *parameter) {
if (handle == NULL || parameter == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
if (index < 0 || index >= handle->parameter_count) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
mmi_signal_parameter_clone(handle->parameters[index], parameter);
- return 0;
+ return MMI_ERROR_NONE;
}
MMI_API int mmi_signal_destroy(mmi_signal_h handle) {
if (handle == NULL) {
- return -1;
+ return MMI_ERROR_INVALID_PARAMETER;
}
for (int i = 0; i < handle->parameter_count; i++) {
}
free(handle);
- return 0;
+ return MMI_ERROR_NONE;
}
return m_workflow_type;
}
+// LCOV_EXCL_START
bool add_output_callback(std::string key, mmi_workflow_output_cb callback, void *user_data) {
bool ret = false;
if (callback) {
}
return ret;
}
+// LCOV_EXCL_STOP
private:
int m_local_workflow_instance_id;
return newInstance;
}
+ WorkflowInstance* get(int local_workflow_instance_id) {
+ for (auto &instance : m_instances) {
+ if (instance->get_local_workflow_instance_id() == local_workflow_instance_id)
+ return instance;
+ }
+ return nullptr;
+ }
+
+// LCOV_EXCL_START
bool destroy(WorkflowInstance *instance) {
bool ret = false;
auto it = std::find(m_instances.begin(), m_instances.end(), instance);
}
return ret;
}
+// LCOV_EXCL_STOP
private:
int m_last_local_workflow_instance_id{0};
#include "mmi-client-manager.h"
#include "mmi-log.h"
#include "mmi-workflow-instance-manager.h"
-#include "mmi_proxy.h"
using namespace mmi;
using namespace mmi::communication;
if (workflow_instance) {
*instance = static_cast<void*>(workflow_instance);
- CommunicationChannel *channel = g_mmi_client_manager.get_communication_channel();
+ std::shared_ptr<CommunicationChannelClient> channel = g_mmi_client_manager.get_communication_channel();
if (channel) {
ClientMessageWorkflowInstanceCreate msg;
msg.local_workflow_instance_id =
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
MMI_API int mmi_workflow_instance_destroy(mmi_workflow_instance_h instance) {
if (nullptr == instance) {
LOGE("[ERROR] parameter is null");
return MMI_ERROR_OPERATION_FAILED;
}
- CommunicationChannel *channel = g_mmi_client_manager.get_communication_channel();
+ std::shared_ptr<CommunicationChannelClient> channel = g_mmi_client_manager.get_communication_channel();
if (channel) {
ClientMessageWorkflowInstanceDestroy msg;
WorkflowInstance *workflow_instance = static_cast<WorkflowInstance*>(instance);
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
MMI_API int mmi_workflow_instance_activate(mmi_workflow_instance_h instance) {
if (nullptr == instance) {
return MMI_ERROR_INVALID_PARAMETER;
}
- CommunicationChannel *channel = g_mmi_client_manager.get_communication_channel();
+ std::shared_ptr<CommunicationChannelClient> channel = g_mmi_client_manager.get_communication_channel();
if (nullptr == channel) {
LOGE("[ERROR] Failed to get channel");
return MMI_ERROR_OPERATION_FAILED;
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
MMI_API int mmi_workflow_instance_deactivate(mmi_workflow_instance_h instance) {
if (nullptr == instance) {
LOGE("[ERROR] parameter is null");
return MMI_ERROR_INVALID_PARAMETER;
}
- CommunicationChannel *channel = g_mmi_client_manager.get_communication_channel();
+ std::shared_ptr<CommunicationChannelClient> channel = g_mmi_client_manager.get_communication_channel();
if (nullptr == channel) {
LOGE("[ERROR] Failed to get channel");
return MMI_ERROR_OPERATION_FAILED;
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
MMI_API int mmi_workflow_instance_set_attribute(mmi_workflow_instance_h instance, mmi_attribute_h attribute) {
if (nullptr == instance) {
return MMI_ERROR_INVALID_PARAMETER;
}
- CommunicationChannel *channel = g_mmi_client_manager.get_communication_channel();
+ std::shared_ptr<CommunicationChannelClient> channel = g_mmi_client_manager.get_communication_channel();
if (nullptr == channel) {
LOGE("[ERROR] Failed to get channel");
return MMI_ERROR_OPERATION_FAILED;
return MMI_ERROR_NONE;
}
+MMI_API int mmi_workflow_instance_emit_signal(mmi_workflow_instance_h instance, mmi_signal_h signal) {
+ if (nullptr == instance) {
+ LOGE("[ERROR] parameter is null");
+ return MMI_ERROR_INVALID_PARAMETER;
+ }
+
+ std::shared_ptr<CommunicationChannelClient> channel = g_mmi_client_manager.get_communication_channel();
+ if (nullptr == channel) {
+ LOGE("[ERROR] Failed to get channel");
+ return MMI_ERROR_OPERATION_FAILED;
+ }
+
+ WorkflowInstance *workflow_instance = static_cast<WorkflowInstance*>(instance);
+
+ ClientMessageWorkflowInstanceEmitSignal msg;
+ msg.local_workflow_instance_id = workflow_instance->get_local_workflow_instance_id();
+ msg.signal = signal;
+
+ channel->send(&msg);
+
+ return MMI_ERROR_NONE;
+}
+// LCOV_EXCL_START
MMI_API int mmi_workflow_instance_set_output_callback(mmi_workflow_instance_h instance, const char *name, mmi_workflow_output_cb callback, void *user_data) {
if (nullptr == instance) {
LOGE("[ERROR] parameter is null");
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
#include "mmi-node-processor.h"
#include "mmi-node-logic.h"
#include "mmi-node-controller.h"
+#include "mmi-node-action.h"
enum class WorkflowScriptSection {
NONE,
m_standard_node_source_names.push_back({MMI_STANDARD_NODE_SOURCE_TYPE_CAMERA, "CAMERA"});
m_standard_node_processor_names.push_back({MMI_STANDARD_NODE_PROCESSOR_TYPE_ASR, "ASR"});
+ m_standard_node_processor_names.push_back({MMI_STANDARD_NODE_PROCESSOR_TYPE_VIDEO_CONVERTER, "VIDEO_CONVERTER"});
m_standard_node_processor_names.push_back({MMI_STANDARD_NODE_PROCESSOR_TYPE_FACE_RECOGNITION, "FACE_RECOGNITION"});
m_standard_node_processor_names.push_back({MMI_STANDARD_NODE_PROCESSOR_TYPE_SPEAKER_RECOGNITION, "SPEAKER_RECOGNITION"});
workflow_s->attribute_assignment_info_count = 0;
workflow_s->attribute_default_value_infos = nullptr;
workflow_s->attribute_default_value_info_count = 0;
+ workflow_s->signal_assignment_infos = nullptr;
+ workflow_s->signal_assignment_info_count = 0;
workflow_s->output_assignment_infos = nullptr;
workflow_s->output_assignment_info_count = 0;
workflow_s->attribute_assignment_info_count = 0;
workflow_s->attribute_default_value_infos = nullptr;
workflow_s->attribute_default_value_info_count = 0;
+ workflow_s->signal_assignment_infos = nullptr;
+ workflow_s->signal_assignment_info_count = 0;
workflow_s->output_assignment_infos = nullptr;
workflow_s->output_assignment_info_count = 0;
mmi_workflow_attribute_assignment_info_s *attribute_assignment_infos = workflow_s->attribute_assignment_infos;
size_t attribute_assignment_info_count = workflow_s->attribute_assignment_info_count;
workflow_s->attribute_assignment_infos = new(std::nothrow) mmi_workflow_attribute_assignment_info_s[attribute_assignment_info_count + 1];
+ if (nullptr == workflow_s->attribute_assignment_infos) {
+ LOGE("[ERROR] Failed to allocate memory");
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
if (attribute_assignment_info_count > 0) {
memcpy(workflow_s->attribute_assignment_infos, attribute_assignment_infos, sizeof(mmi_workflow_attribute_assignment_info_s) * attribute_assignment_info_count);
delete [] attribute_assignment_infos;
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_START
MMI_API int mmi_workflow_attribute_set_default_value(mmi_workflow_h workflow, mmi_attribute_h default_value) {
if (nullptr == workflow || nullptr == default_value) {
LOGE("[ERROR] parameter is null");
mmi_workflow_attribute_default_value_info_s *attribute_default_value_infos = workflow_s->attribute_default_value_infos;
size_t attribute_default_value_info_count = workflow_s->attribute_default_value_info_count;
workflow_s->attribute_default_value_infos = new(std::nothrow) mmi_workflow_attribute_default_value_info_s[attribute_default_value_info_count + 1];
+ if (nullptr == workflow_s->attribute_default_value_infos) {
+ LOGE("[ERROR] Failed to allocate memory");
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
+
if (attribute_default_value_info_count > 0) {
memcpy(workflow_s->attribute_default_value_infos, attribute_default_value_infos, sizeof(mmi_workflow_attribute_default_value_info_s) * attribute_default_value_info_count);
delete [] attribute_default_value_infos;
return MMI_ERROR_NONE;
}
-MMI_API int mmi_workflow_signal_assign(mmi_workflow_h workflow, const char *workflow_signal, mmi_node_h node, const char *node_signal) {
- if (nullptr == workflow || nullptr == workflow_signal || nullptr == node || nullptr == node_signal) {
+MMI_API int mmi_workflow_signal_assign(mmi_workflow_h workflow, const char *signal_name, const char *target_node_name, const char *target_signal_name) {
+ if (nullptr == workflow || nullptr == signal_name || nullptr == target_node_name || nullptr == target_signal_name) {
LOGE("[ERROR] parameter is null");
return MMI_ERROR_INVALID_PARAMETER;
}
+
+ mmi_workflow_s *workflow_s = static_cast<mmi_workflow_s *>(workflow);
+ mmi_workflow_signal_assignment_info_s *signal_assignment_infos = workflow_s->signal_assignment_infos;
+ size_t signal_assignment_info_count = workflow_s->signal_assignment_info_count;
+ workflow_s->signal_assignment_infos = new(std::nothrow) mmi_workflow_signal_assignment_info_s[signal_assignment_info_count + 1];
+ if (nullptr == workflow_s->signal_assignment_infos) {
+ LOGE("[ERROR] Failed to allocate memory");
+ return MMI_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (signal_assignment_info_count > 0) {
+ memcpy(workflow_s->signal_assignment_infos, signal_assignment_infos, sizeof(mmi_workflow_signal_assignment_info_s) * signal_assignment_info_count);
+ delete [] signal_assignment_infos;
+ }
+
+ snprintf(workflow_s->signal_assignment_infos[signal_assignment_info_count].signal_name, MMI_NAME_MAX_LENGTH, "%s", signal_name);
+ snprintf(workflow_s->signal_assignment_infos[signal_assignment_info_count].target_node_name, MMI_NAME_MAX_LENGTH, "%s", target_node_name);
+ snprintf(workflow_s->signal_assignment_infos[signal_assignment_info_count].target_signal_name, MMI_NAME_MAX_LENGTH, "%s", target_signal_name);
+
+ workflow_s->signal_assignment_info_count = signal_assignment_info_count + 1;
+
return MMI_ERROR_NONE;
}
+// LCOV_EXCL_STOP
MMI_API int mmi_workflow_output_assign(mmi_workflow_h workflow, const char *workflow_output, const char *out_node_name, const char *node_out_port_name) {
if (nullptr == workflow || nullptr == workflow_output || nullptr == out_node_name || nullptr == node_out_port_name) {
#include <Ecore.h>
#include "mmi-log.h"
-#include "mmi-ipc-tidl.h"
#include "mmi-client-manager.h"
static mmi_state_e g_mmi_state{MMI_STATE_NONE};
static std::vector<std::pair<mmi_state_changed_cb, void*>> g_state_changed_cb_list;
-struct CommunicationChannelFactoryTIDL : public ICommunicationChannelFactory {
- CommunicationChannel* create_channel() override {
- return new(std::nothrow) CommunicationChannelTIDL();
- }
- void destroy_channel(CommunicationChannel* channel) override {
- delete channel;
- }
-};
-static CommunicationChannelFactoryTIDL g_communication_channel_factory_tidl;
+CommunicationChannelClientFactory g_communication_channel_factory;
class CommunicationChannelObserver :
public SimpleEventObserver<COMMUNICATION_CHANNEL_EVENT_TYPE> {
public:
+// LCOV_EXCL_START
void on_observer_event(
const COMMUNICATION_CHANNEL_EVENT_TYPE &event, std::any data) override {
mmi_state_e previous_state = g_mmi_state;
}
}
}
+// LCOV_EXCL_STOP
};
static CommunicationChannelObserver g_communication_channel_observer;
ClientManager g_mmi_client_manager{
- &g_communication_channel_factory_tidl,
+ &g_communication_channel_factory,
&g_communication_channel_observer
};
_D("Adding prototype : %d", prototype->is_valid());
m_prototypes.push_back(prototype);
- _D("Node prototype added: type=%d, sub_type=%d, plugin_module_type=%d, plugin_module_identifier=%s",
- prototype->get_type(), to_int(prototype->get_sub_type()),
+ _D("Node prototype added: type=%s, sub_type=%s, plugin_module_type=%d, plugin_module_identifier=%s",
+ enum_to_string(prototype->get_type()).c_str(),
+ to_string(prototype->get_sub_type()).c_str(),
static_cast<int>(prototype->get_plugin_module_info().plugin_module_type),
prototype->get_plugin_module_info().plugin_module_identifier.c_str());
prototype->get_plugin_module_info().plugin_module_identifier.c_str());
_D(" node_infos:");
for (auto& elem : prototype->get_node_infos()) {
- _D(" name=%s, node_type=%d, node_sub_type=%d",
- elem.name.c_str(), elem.node_type, to_int(elem.node_sub_type));
+ _D(" name=%s, node_type=%s, node_sub_type=%s",
+ elem.name.c_str(),
+ enum_to_string(elem.node_type).c_str(),
+ to_string(elem.node_sub_type).c_str());
}
_D(" link_infos:");
for (auto& elem : prototype->get_link_infos()) {
class WorkflowPrototypeStoreDummy : public IWorkflowPrototypeStore {
public:
- bool add_workflow_prototype(std::shared_ptr<WorkflowPrototype> prototype) override {
- return true;
- }
- std::shared_ptr<WorkflowPrototype> get_workflow_prototype(mmi_standard_workflow_type_e type) override {
+ WorkflowPrototypeStoreDummy() {
+ mmi_primitive_value_h value = nullptr;
+ mmi_primitive_value_create_string("Default", &value);
+ mmi_attribute_h default_value = nullptr;
+ mmi_attribute_create(value, "COMMAND", &default_value);
+ attribute_default_value_info.default_value = default_value;
+ mmi_primitive_value_destroy(value);
+
auto prototype = std::make_shared<WorkflowPrototype>();
prototype->set_type(MMI_STANDARD_WORKFLOW_WAKEUPLESS_COMMAND);
prototype->add_node_info(mmi::NodeInfo{
"ASR", MMI_STANDARD_NODE_TYPE_PROCESSOR, MMI_STANDARD_NODE_PROCESSOR_TYPE_ASR});
AttributeAssignmentInfo attribute_assignment_info;
- attribute_assignment_info.attribute_name = "CANDIDATE";
+ attribute_assignment_info.attribute_name = "COMMAND";
attribute_assignment_info.target_node_name = "ASR";
attribute_assignment_info.target_attribute_name = "CANDIDATE";
prototype->add_attribute_assignment_info(attribute_assignment_info);
- return prototype;
+ prototype->add_attribute_default_value_info(attribute_default_value_info);
+
+ workflow_prototype = prototype;
+ }
+ virtual ~WorkflowPrototypeStoreDummy() {
+ if (attribute_default_value_info.default_value) {
+ mmi_attribute_destroy(attribute_default_value_info.default_value);
+ }
+ }
+
+ bool add_workflow_prototype(std::shared_ptr<WorkflowPrototype> prototype) override {
+ return true;
}
+ std::shared_ptr<WorkflowPrototype> get_workflow_prototype(mmi_standard_workflow_type_e type) override {
+ return workflow_prototype;
+ }
+ std::shared_ptr<WorkflowPrototype> workflow_prototype;
+ AttributeDefaultValueInfo attribute_default_value_info{nullptr};
};
class NodePrototypeStoreDummy : public INodePrototypeStore {
std::vector<std::shared_ptr<NodePrototype>> node_prototypes;
};
+class NodeAttributeSetHistoryItem {
+public:
+ NodeAttributeSetHistoryItem() {}
+ ~NodeAttributeSetHistoryItem() {
+ if (attribute) {
+ mmi_attribute_destroy(attribute);
+ }
+ }
+ void reset() {
+ type = MMI_STANDARD_NODE_TYPE_NONE;
+ sub_type = std::monostate();
+ if (attribute) {
+ mmi_attribute_destroy(attribute);
+ attribute = nullptr;
+ }
+ }
+ void set_item(
+ mmi_standard_node_type_e type,
+ mmi_standard_node_sub_type_e sub_type,
+ mmi_attribute_h attribute) {
+ this->type = type;
+ this->sub_type = sub_type;
+ if (this->attribute) {
+ mmi_attribute_destroy(this->attribute);
+ }
+ mmi_attribute_clone(attribute, &(this->attribute));
+ }
+ mmi_standard_node_type_e type{MMI_STANDARD_NODE_TYPE_NONE};
+ mmi_standard_node_sub_type_e sub_type{std::monostate()};
+ mmi_attribute_h attribute{nullptr};
+};
+
+static NodeAttributeSetHistoryItem g_last_node_attribute_set_history;
+
+class NodeInstanceTest : public NodeInstance
+{
+public:
+ NodeInstanceTest(mmi_standard_node_type_e node_type, mmi_standard_node_sub_type_e node_sub_type) :
+ NodeInstance(node_type, node_sub_type) {
+ }
+ virtual ~NodeInstanceTest() {
+ }
+ bool set_attribute(mmi_attribute_h attribute) override {
+ g_last_node_attribute_set_history.set_item(
+ get_node_type(), get_node_sub_type(), attribute);
+ return true;
+ }
+};
+
class NodeInstanceManagerDummy : public INodeInstanceManager {
public:
NodeInstanceManagerDummy() {
virtual std::shared_ptr<NodeInstance> create_node_instance(
mmi_standard_node_type_e node_type,
mmi_standard_node_sub_type_e node_sub_type) override {
- auto node_instance = std::make_shared<NodeInstance>(node_type, node_sub_type);
+ auto node_instance = std::make_shared<NodeInstanceTest>(node_type, node_sub_type);
if (node_instance) {
node_instance->set_node_prototype_store(node_prototype_store);
node_instance->set_plugin_module_proxy_provider(plugin_module_proxy_provider);
};
TEST_F(WorkflowInstanceTest, WorkflowAttributePassedToNodeAttribute_p) {
- ASSERT_NE(workflow_instance, nullptr);
+ EXPECT_NE(workflow_instance, nullptr);
workflow_instance->initialize();
mmi_primitive_value_h value = nullptr;
- mmi_primitive_value_create_int(5, &value);
+ mmi_primitive_value_create_string("Hello", &value);
mmi_attribute_h attribute = nullptr;
- mmi_attribute_create(value, "CANDIDATE", &attribute);
- ASSERT_TRUE(workflow_instance->set_attribute(attribute));
+ mmi_attribute_create(value, "COMMAND", &attribute);
+ EXPECT_TRUE(workflow_instance->set_attribute(attribute));
+ EXPECT_EQ(g_last_node_attribute_set_history.type, MMI_STANDARD_NODE_TYPE_PROCESSOR);
+ EXPECT_TRUE(std::holds_alternative<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type));
+ EXPECT_EQ(std::get<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type),
+ MMI_STANDARD_NODE_PROCESSOR_TYPE_ASR);
+ EXPECT_TRUE(g_last_node_attribute_set_history.attribute != nullptr);
+
+ mmi_primitive_value_h history_item_value;
+ mmi_attribute_get_value(g_last_node_attribute_set_history.attribute, &history_item_value);
+
+ mmi_primitive_value_type_e type;
+ mmi_primitive_value_get_type(history_item_value, &type);
+ EXPECT_EQ(type, MMI_PRIMITIVE_VALUE_TYPE_STRING);
+
+ const char* str;
+ mmi_primitive_value_get_string(history_item_value, &str);
+ EXPECT_STREQ(str, "Hello");
+
+ mmi_primitive_value_destroy(history_item_value);
+
workflow_instance->deinitialize();
mmi_attribute_destroy(attribute);
mmi_primitive_value_destroy(value);
}
+TEST_F(WorkflowInstanceTest, WorkflowAttributePassedProperlyAfter2ndInitialization_p) {
+ EXPECT_NE(workflow_instance, nullptr);
+ workflow_instance.reset();
+ workflow_instance = std::make_shared<WorkflowInstance>();
+ if (workflow_instance) {
+ workflow_instance->set_type(MMI_STANDARD_WORKFLOW_WAKEUPLESS_COMMAND);
+
+ workflow_instance->set_workflow_prototype_store(workflow_prototype_store);
+ workflow_instance->set_plugin_module_proxy_provider(plugin_module_proxy_provider);
+ workflow_instance->set_node_instance_manager(node_instance_manager);
+ }
+ EXPECT_NE(workflow_instance, nullptr);
+ workflow_instance->initialize();
+ mmi_primitive_value_h value = nullptr;
+ mmi_primitive_value_create_string("Hello", &value);
+ mmi_attribute_h attribute = nullptr;
+ mmi_attribute_create(value, "COMMAND", &attribute);
+ EXPECT_TRUE(workflow_instance->set_attribute(attribute));
+ EXPECT_EQ(g_last_node_attribute_set_history.type, MMI_STANDARD_NODE_TYPE_PROCESSOR);
+ EXPECT_TRUE(std::holds_alternative<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type));
+ EXPECT_EQ(std::get<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type),
+ MMI_STANDARD_NODE_PROCESSOR_TYPE_ASR);
+ EXPECT_TRUE(g_last_node_attribute_set_history.attribute != nullptr);
+
+ mmi_primitive_value_h history_item_value;
+ mmi_attribute_get_value(g_last_node_attribute_set_history.attribute, &history_item_value);
+
+ mmi_primitive_value_type_e type;
+ mmi_primitive_value_get_type(history_item_value, &type);
+ EXPECT_EQ(type, MMI_PRIMITIVE_VALUE_TYPE_STRING);
+
+ const char* str;
+ mmi_primitive_value_get_string(history_item_value, &str);
+ EXPECT_STREQ(str, "Hello");
+
+ mmi_primitive_value_destroy(history_item_value);
+
+ workflow_instance->deinitialize();
+ mmi_attribute_destroy(attribute);
+ mmi_primitive_value_destroy(value);
+}
+
+TEST_F(WorkflowInstanceTest, WorkflowDefaultAttributePassedToNodeAttribute_p) {
+ g_last_node_attribute_set_history.reset();
+
+ EXPECT_NE(workflow_instance, nullptr);
+ workflow_instance->initialize();
+ EXPECT_EQ(g_last_node_attribute_set_history.type, MMI_STANDARD_NODE_TYPE_PROCESSOR);
+ EXPECT_TRUE(std::holds_alternative<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type));
+ EXPECT_EQ(std::get<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type),
+ MMI_STANDARD_NODE_PROCESSOR_TYPE_ASR);
+ EXPECT_TRUE(g_last_node_attribute_set_history.attribute != nullptr);
+
+ mmi_primitive_value_h history_item_value;
+ mmi_attribute_get_value(g_last_node_attribute_set_history.attribute, &history_item_value);
+
+ mmi_primitive_value_type_e type;
+ mmi_primitive_value_get_type(history_item_value, &type);
+ EXPECT_EQ(type, MMI_PRIMITIVE_VALUE_TYPE_STRING);
+
+ const char* str;
+ mmi_primitive_value_get_string(history_item_value, &str);
+ EXPECT_STREQ(str, "Default");
+
+ mmi_primitive_value_destroy(history_item_value);
+
+ workflow_instance->deinitialize();
+}
+
+TEST_F(WorkflowInstanceTest, WorkflowDefaultAttributePassedProperlyAfter2ndInitialization_p) {
+ EXPECT_NE(workflow_instance, nullptr);
+ workflow_instance->initialize();
+ workflow_instance->deinitialize();
+
+ g_last_node_attribute_set_history.reset();
+
+ EXPECT_NE(workflow_instance, nullptr);
+ workflow_instance->initialize();
+
+ EXPECT_EQ(g_last_node_attribute_set_history.type, MMI_STANDARD_NODE_TYPE_PROCESSOR);
+ EXPECT_TRUE(std::holds_alternative<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type));
+ EXPECT_EQ(std::get<mmi_standard_node_processor_type_e>(g_last_node_attribute_set_history.sub_type),
+ MMI_STANDARD_NODE_PROCESSOR_TYPE_ASR);
+ EXPECT_TRUE(g_last_node_attribute_set_history.attribute != nullptr);
+
+ char *name = nullptr;
+ mmi_attribute_get_name(g_last_node_attribute_set_history.attribute, &name);
+ EXPECT_STREQ(name, "CANDIDATE");
+ free(name);
+
+ mmi_primitive_value_h history_item_value;
+ mmi_attribute_get_value(g_last_node_attribute_set_history.attribute, &history_item_value);
+
+ mmi_primitive_value_type_e type;
+ mmi_primitive_value_get_type(history_item_value, &type);
+ EXPECT_EQ(type, MMI_PRIMITIVE_VALUE_TYPE_STRING);
+
+ const char* str;
+ mmi_primitive_value_get_string(history_item_value, &str);
+ EXPECT_STREQ(str, "Default");
+
+ mmi_primitive_value_destroy(history_item_value);
+
+ workflow_instance->deinitialize();
+}
+
#ifdef TEST_MAIN_REQUIRED
int main(int argc, char** argv) {
std::cout << "Starting tests" << std::endl;
'mmi-ipc-test.cpp',
'mmi-data-test.cpp',
'attribute/mmi-attribute-test.cpp',
+ 'signal/mmi-signal-test.cpp',
'primitive-value/mmi-primitive-value-test.cpp',
'workflow/mmi-workflow-test.cpp',
]
EXPECT_EQ(mmi_data_create_audio(sourceValue, DATA_LENGTH, nullptr), MMI_ERROR_INVALID_PARAMETER);
}
+TEST_F(MMIDataTest, MMIDataCreateDataByCoordinate_p) {
+ constexpr int x = 123;
+ constexpr int y = 456;
+
+ ASSERT_EQ(mmi_data_create_coordinate(x, y, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+}
+
+TEST_F(MMIDataTest, MMIDataCreateDataByBoundingBox_p) {
+ constexpr int x = 12;
+ constexpr int y = 34;
+ constexpr int w = 56;
+ constexpr int h = 78;
+
+ ASSERT_EQ(mmi_data_create_bounding_box(x, y, w, h, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+}
+
TEST_F(MMIDataTest, MMIDataCreateDataByArray_p) {
EXPECT_EQ(mmi_data_create_array(&mmiData), MMI_ERROR_NONE);
ASSERT_NE(mmiData, nullptr);
EXPECT_EQ(mmi_data_destroy(tempValue), MMI_ERROR_NONE);
tempValue = nullptr;
+ EXPECT_EQ(mmi_data_create_coordinate(123, 456, &tempValue), MMI_ERROR_NONE);
+ EXPECT_EQ(mmi_data_get_type(tempValue, &type), MMI_ERROR_NONE);
+ EXPECT_EQ(type, MMI_DATA_TYPE_COORDINATE);
+ EXPECT_EQ(mmi_data_destroy(tempValue), MMI_ERROR_NONE);
+ tempValue = nullptr;
+
+ EXPECT_EQ(mmi_data_create_bounding_box(12, 34, 56, 78, &tempValue), MMI_ERROR_NONE);
+ EXPECT_EQ(mmi_data_get_type(tempValue, &type), MMI_ERROR_NONE);
+ EXPECT_EQ(type, MMI_DATA_TYPE_BOUNDING_BOX);
+ EXPECT_EQ(mmi_data_destroy(tempValue), MMI_ERROR_NONE);
+ tempValue = nullptr;
+
constexpr size_t length = 10;
constexpr char sourceValue[length] = {1, };
EXPECT_EQ(mmi_data_create_audio(sourceValue, length, &tempValue), MMI_ERROR_NONE);
EXPECT_EQ(mmi_data_get_text(mmiData, &textInData), MMI_ERROR_INVALID_PARAMETER);
}
+TEST_F(MMIDataTest, MMIDataGetCoordinateValue_p) {
+ constexpr int sourceX = 123;
+ constexpr int sourceY = 456;
+ ASSERT_EQ(mmi_data_create_coordinate(sourceX, sourceY, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+
+ int targetX = -1;
+ int targetY = -1;
+ EXPECT_EQ(mmi_data_get_coordinate(mmiData, &targetX, &targetY), MMI_ERROR_NONE);
+ EXPECT_EQ(targetX, sourceX);
+ EXPECT_EQ(targetY, sourceY);
+}
+
+TEST_F(MMIDataTest, MMIDataGetCoordinateValue_n1) {
+ constexpr int sourceX = 123;
+ constexpr int sourceY = 456;
+ ASSERT_EQ(mmi_data_create_coordinate(sourceX, sourceY, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+
+ int targetX = -1;
+ int targetY = -1;
+ EXPECT_EQ(mmi_data_get_coordinate(nullptr, &targetX, &targetY), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_data_get_coordinate(mmiData, nullptr, &targetY), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_data_get_coordinate(mmiData, &targetX, nullptr), MMI_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(MMIDataTest, MMIDataGetCoordinateValue_n2) {
+ constexpr const char *sourceText = "Hello";
+ ASSERT_EQ(mmi_data_create_text(sourceText, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+
+ int targetX = -1;
+ int targetY = -1;
+ EXPECT_EQ(mmi_data_get_coordinate(mmiData, &targetX, &targetY), MMI_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(MMIDataTest, MMIDataGetBoundingBoxValue_p) {
+ constexpr int sourceX = 12;
+ constexpr int sourceY = 34;
+ constexpr int sourceW = 56;
+ constexpr int sourceH = 78;
+ ASSERT_EQ(mmi_data_create_bounding_box(sourceX, sourceY, sourceW, sourceH, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+
+ int targetX = -1;
+ int targetY = -1;
+ int targetW = -1;
+ int targetH = -1;
+ EXPECT_EQ(mmi_data_get_bounding_box(mmiData, &targetX, &targetY, &targetW, &targetH), MMI_ERROR_NONE);
+ EXPECT_EQ(targetX, sourceX);
+ EXPECT_EQ(targetY, sourceY);
+ EXPECT_EQ(targetW, sourceW);
+ EXPECT_EQ(targetH, sourceH);
+}
+
+TEST_F(MMIDataTest, MMIDataGetBoundingBoxValue_n1) {
+ constexpr int sourceX = 12;
+ constexpr int sourceY = 34;
+ constexpr int sourceW = 56;
+ constexpr int sourceH = 78;
+ ASSERT_EQ(mmi_data_create_bounding_box(sourceX, sourceY, sourceW, sourceH, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+
+ int targetX = -1;
+ int targetY = -1;
+ int targetW = -1;
+ int targetH = -1;
+ EXPECT_EQ(mmi_data_get_bounding_box(nullptr, &targetX, &targetY, &targetW, &targetH), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_data_get_bounding_box(mmiData, nullptr, &targetY, &targetW, &targetH), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_data_get_bounding_box(mmiData, &targetX, nullptr, &targetW, &targetH), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_data_get_bounding_box(mmiData, &targetX, &targetY, nullptr, &targetH), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_data_get_bounding_box(mmiData, &targetX, &targetY, &targetW, nullptr), MMI_ERROR_INVALID_PARAMETER);
+}
+
+TEST_F(MMIDataTest, MMIDataGetBoundingBoxValue_n2) {
+ constexpr const char *sourceText = "Hello";
+ ASSERT_EQ(mmi_data_create_text(sourceText, &mmiData), MMI_ERROR_NONE);
+ ASSERT_NE(mmiData, nullptr);
+
+ int targetX = -1;
+ int targetY = -1;
+ int targetW = -1;
+ int targetH = -1;
+ EXPECT_EQ(mmi_data_get_bounding_box(mmiData, &targetX, &targetY, &targetW, &targetH), MMI_ERROR_INVALID_PARAMETER);
+}
+
TEST_F(MMIDataTest, MMIDataGetArrayCount_p) {
ASSERT_EQ(mmi_data_create_array(&mmiData), MMI_ERROR_NONE);
ASSERT_NE(mmiData, nullptr);
#include "mmi.h"
#include "mmi-tests.h"
-#include "mmi-ipc-tidl.h"
#include <Ecore.h>
-#include <rpc-port-internal.h>
static mmi_state_e g_state = MMI_STATE_NONE;
static int state_changed_cb(mmi_state_e state, void *user_data) {
#include "mmi.h"
#include "mmi-tests.h"
-#include "mmi-ipc-tidl.h"
#include <Ecore.h>
-#include <rpc-port-internal.h>
static int state_changed_cb(mmi_state_e state, void *user_data) {
return MMI_ERROR_NONE;
--- /dev/null
+/*
+ * Copyright (c) 2023 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 <gmock/gmock.h>
+
+#include <mmi-error.h>
+#include <mmi-signal.h>
+
+
+class MMISignalTest : public ::testing::Test {
+public:
+ void SetUp(void) override {
+ }
+
+ void TearDown(void) override {
+ }
+};
+
+TEST_F(MMISignalTest, MMISignalCreate_p) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalCreate_n1) {
+ mmi_signal_h signal = nullptr;
+
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(nullptr, &signal), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_signal_create(name, nullptr), MMI_ERROR_INVALID_PARAMETER);
+
+ if (signal) mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalCreate_n2) {
+ mmi_signal_h signal = nullptr;
+
+ EXPECT_EQ(mmi_signal_create("", &signal), MMI_ERROR_INVALID_PARAMETER);
+
+ constexpr size_t NAME_LENGTH = 300;
+ char name[NAME_LENGTH];
+ for (auto &c : name) {
+ c = 'a';
+ }
+ name[NAME_LENGTH - 1] = 0;
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_INVALID_PARAMETER);
+
+ if (signal) mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalGetName_p) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ char *temp_name = nullptr;
+ EXPECT_EQ(mmi_signal_get_name(signal, &temp_name), MMI_ERROR_NONE);
+ EXPECT_NE(temp_name, nullptr);
+ EXPECT_STREQ(temp_name, name);
+ free(temp_name);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalGetName_n) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ char *temp_name = nullptr;
+ EXPECT_EQ(mmi_signal_get_name(nullptr, &temp_name), MMI_ERROR_INVALID_PARAMETER);
+ EXPECT_EQ(mmi_signal_get_name(signal, nullptr), MMI_ERROR_INVALID_PARAMETER);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalAddParameter_p) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ mmi_primitive_value_h value = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_int(100, &value), MMI_ERROR_NONE);
+ EXPECT_NE(value, nullptr);
+
+ mmi_signal_parameter_h parameter = nullptr;
+ mmi_signal_parameter_create(value, "parameter", ¶meter);
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter), MMI_ERROR_NONE);
+
+ mmi_signal_parameter_destroy(parameter);
+ mmi_primitive_value_destroy(value);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalAddParameter_n) {
+ mmi_primitive_value_h value = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_int(100, &value), MMI_ERROR_NONE);
+ EXPECT_NE(value, nullptr);
+
+ mmi_signal_parameter_h parameter = nullptr;
+ mmi_signal_parameter_create(value, "parameter", ¶meter);
+ EXPECT_EQ(mmi_signal_add_parameter(nullptr, parameter), MMI_ERROR_INVALID_PARAMETER);
+
+ mmi_signal_parameter_destroy(parameter);
+ mmi_primitive_value_destroy(value);
+}
+
+TEST_F(MMISignalTest, MMISignalAddParameter_n2) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ mmi_signal_parameter_h parameter = nullptr;
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter), MMI_ERROR_INVALID_PARAMETER);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalAddParameters_p) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ mmi_primitive_value_h value_1 = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_int(100, &value_1), MMI_ERROR_NONE);
+ EXPECT_NE(value_1, nullptr);
+
+ mmi_primitive_value_h value_2 = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_string("Hello", &value_2), MMI_ERROR_NONE);
+ EXPECT_NE(value_2, nullptr);
+
+ mmi_signal_parameter_h parameter_1 = nullptr;
+ mmi_signal_parameter_create(value_1, "parameter_1", ¶meter_1);
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter_1), MMI_ERROR_NONE);
+
+ mmi_signal_parameter_h parameter_2 = nullptr;
+ mmi_signal_parameter_create(value_2, "parameter_2", ¶meter_2);
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter_2), MMI_ERROR_NONE);
+
+ mmi_signal_parameter_destroy(parameter_2);
+ mmi_signal_parameter_destroy(parameter_1);
+
+ mmi_primitive_value_destroy(value_2);
+ mmi_primitive_value_destroy(value_1);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalAddParameters_n) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ mmi_primitive_value_h value_1 = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_int(100, &value_1), MMI_ERROR_NONE);
+ EXPECT_NE(value_1, nullptr);
+
+ mmi_primitive_value_h value_2 = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_string("Hello", &value_2), MMI_ERROR_NONE);
+ EXPECT_NE(value_2, nullptr);
+
+ mmi_signal_parameter_h parameter_1 = nullptr;
+ mmi_signal_parameter_create(value_1, "parameter_1", ¶meter_1);
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter_1), MMI_ERROR_NONE);
+
+ /* Parameter with already-existing name */
+ mmi_signal_parameter_h parameter_2 = nullptr;
+ mmi_signal_parameter_create(value_2, "parameter_1", ¶meter_2);
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter_2), MMI_ERROR_INVALID_PARAMETER);
+
+ mmi_signal_parameter_destroy(parameter_2);
+ mmi_signal_parameter_destroy(parameter_1);
+
+ mmi_primitive_value_destroy(value_2);
+ mmi_primitive_value_destroy(value_1);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalGetParameterValue_p) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ mmi_primitive_value_h value = nullptr;
+ EXPECT_EQ(mmi_primitive_value_create_int(100, &value), MMI_ERROR_NONE);
+ EXPECT_NE(value, nullptr);
+
+ mmi_signal_parameter_h parameter = nullptr;
+ mmi_signal_parameter_create(value, "parameter", ¶meter);
+ EXPECT_EQ(mmi_signal_add_parameter(signal, parameter), MMI_ERROR_NONE);
+
+ mmi_signal_parameter_h temp_parameter = nullptr;
+ EXPECT_EQ(mmi_signal_get_parameter(signal, 0, &temp_parameter), MMI_ERROR_NONE);
+ EXPECT_NE(temp_parameter, nullptr);
+
+ char *temp_parameter_name = nullptr;
+ EXPECT_EQ(mmi_signal_parameter_get_name(temp_parameter, &temp_parameter_name), MMI_ERROR_NONE);
+ EXPECT_STREQ(temp_parameter_name, "parameter");
+ free(temp_parameter_name);
+
+ mmi_primitive_value_h temp_value = nullptr;
+ EXPECT_EQ(mmi_signal_parameter_get_value(temp_parameter, &temp_value), MMI_ERROR_NONE);
+ EXPECT_NE(temp_value, nullptr);
+
+ mmi_primitive_value_type_e type;
+ mmi_primitive_value_type_e temp_type;
+
+ mmi_primitive_value_get_type(value, &type);
+ mmi_primitive_value_get_type(temp_value, &temp_type);
+
+ EXPECT_EQ(type, temp_type);
+
+ int temp_int = 0;
+ EXPECT_EQ(mmi_primitive_value_get_int(temp_value, &temp_int), MMI_ERROR_NONE);
+ EXPECT_EQ(temp_int, 100);
+
+ mmi_signal_parameter_destroy(temp_parameter);
+ mmi_signal_parameter_destroy(parameter);
+
+ mmi_primitive_value_destroy(temp_value);
+ mmi_primitive_value_destroy(value);
+
+ mmi_signal_destroy(signal);
+}
+
+TEST_F(MMISignalTest, MMISignalDestroy_p1) {
+ mmi_signal_h signal = nullptr;
+ constexpr const char *name = "signal";
+ EXPECT_EQ(mmi_signal_create(name, &signal), MMI_ERROR_NONE);
+ EXPECT_NE(signal, nullptr);
+
+ EXPECT_EQ(mmi_signal_destroy(signal), MMI_ERROR_NONE);
+ signal = nullptr;
+}
+
+TEST_F(MMISignalTest, MMISignalDestroy_n) {
+ EXPECT_EQ(mmi_signal_destroy(nullptr), MMI_ERROR_INVALID_PARAMETER);
+}
int workflow_instance_create(in int local_workflow_instance_id, in int workflow_type);
int workflow_instance_destroy(in int local_workflow_instance_id);
int workflow_instance_set_attribute(in int local_workflow_instance_id, in bundle attribute);
+ int workflow_instance_emit_signal(in int local_workflow_instance_id, in bundle signal);
int workflow_instance_activate(in int local_workflow_instance_id);
int workflow_instance_deactivate(in int local_workflow_instance_id);
int workflow_instance_register_result_callback(in int local_workflow_instance_id, result_cb callback);