Sync with latest MMI framework code 99/302899/1 accepted/tizen/unified/20231219.041318
authorJi-hoon Lee <dalton.lee@samsung.com>
Fri, 15 Dec 2023 07:10:00 +0000 (16:10 +0900)
committerJi-hoon Lee <dalton.lee@samsung.com>
Fri, 15 Dec 2023 07:13:09 +0000 (16:13 +0900)
Sync Commit ID : bfc1bf1bdedb2992dd34065fa1ee31de1821b481

Change-Id: I9f9c651ce9c09c9ca090a6ada18293f17ee5dc89

130 files changed:
capi/meson.build
capi/mmi-attribute.h
capi/mmi-config-parser.h [new file with mode: 0644]
capi/mmi-data.h
capi/mmi-error.h
capi/mmi-node-action.h [new file with mode: 0644]
capi/mmi-node-processor.h
capi/mmi-node.h
capi/mmi-plugin-storage.h
capi/mmi-port.h
capi/mmi-primitive-value.h
capi/mmi-signal.h
capi/mmi-workflow.h
capi/mmi.h
external/magic_enum/magic_enum.hpp [new file with mode: 0644]
meson.build
meson_options.txt [new file with mode: 0644]
packaging/mmi.spec
platform/linux/meson.build [new file with mode: 0644]
platform/linux/mmi-platform-config.h [new file with mode: 0644]
platform/meson.build [new file with mode: 0644]
platform/tizen/meson.build [new file with mode: 0644]
platform/tizen/mmi-platform-config.h [new file with mode: 0644]
plugins/meson.build
plugins/nodes/camera/meson.build [deleted file]
plugins/nodes/camera/mmi-module-camera-preview.cpp [deleted file]
plugins/nodes/camera/mmi-module-camera-preview.h [deleted file]
plugins/nodes/camera/mmi-module-camera.cpp [deleted file]
plugins/nodes/face-recognition/data/recognizerInfo.json [deleted file]
plugins/nodes/face-recognition/meson.build [deleted file]
plugins/nodes/face-recognition/mmi-module-fr-data-manager.cpp [deleted file]
plugins/nodes/face-recognition/mmi-module-fr-data-manager.h [deleted file]
plugins/nodes/face-recognition/mmi-module-fr.cpp [deleted file]
plugins/nodes/face-recognition/mv_face_recognition_internal.h [deleted file]
plugins/nodes/match/meson.build [deleted file]
plugins/nodes/match/mmi-module-match-text-candidates.cpp [deleted file]
plugins/nodes/match/mmi-module-match-text-candidates.h [deleted file]
plugins/nodes/match/mmi-module-match.cpp [deleted file]
plugins/nodes/meson.build [deleted file]
plugins/nodes/mic/meson.build [deleted file]
plugins/nodes/mic/mmi-module-mic-recorder.cpp [deleted file]
plugins/nodes/mic/mmi-module-mic-recorder.h [deleted file]
plugins/nodes/mic/mmi-module-mic.cpp [deleted file]
plugins/nodes/regex-match/meson.build [deleted file]
plugins/nodes/regex-match/mmi-module-regex-match-regex-candidates.cpp [deleted file]
plugins/nodes/regex-match/mmi-module-regex-match-regex-candidates.h [deleted file]
plugins/nodes/regex-match/mmi-module-regex-match.cpp [deleted file]
plugins/nodes/voice-touch/meson.build [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-candidates.cpp [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-candidates.h [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-common.h [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-data-utility.cpp [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-data-utility.h [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-primitive-utility.cpp [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-primitive-utility.h [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-screen-info.cpp [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-screen-info.h [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-string-utility.cpp [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch-string-utility.h [deleted file]
plugins/nodes/voice-touch/mmi-module-voice-touch.cpp [deleted file]
plugins/workflows/script-parser/meson.build
plugins/workflows/script-parser/mmi-module-script-parser.cpp
plugins/workflows/user-recognition/user-recognition.mws
plugins/workflows/voice-touch/meson.build
plugins/workflows/voice-touch/mmi-module-voice-touch.cpp
plugins/workflows/voice-touch/voice-touch.mws [deleted file]
plugins/workflows/wakeupless-command/meson.build
plugins/workflows/wakeupless-command/mmi-module-wakeupless-command.cpp
setup_linux_build.sh [new file with mode: 0755]
src/common/mmi-communication-channel.h
src/common/mmi-communication-message.h
src/common/mmi-workflow-output-event.h
src/mmi-cli/meson.build
src/mmi-cli/mmi-cli-node-tester.cpp
src/mmi-cli/mmi-cli.cpp
src/mmi-manager/main.cpp
src/mmi-manager/meson.build
src/mmi-manager/mmi-client.cpp
src/mmi-manager/mmi-client.h
src/mmi-manager/mmi-common.h
src/mmi-manager/mmi-ipc-ecore.cpp [new file with mode: 0644]
src/mmi-manager/mmi-ipc-ecore.h [new file with mode: 0644]
src/mmi-manager/mmi-ipc-tidl.cpp
src/mmi-manager/mmi-ipc-tidl.h
src/mmi-manager/mmi-manager-log.h
src/mmi-manager/mmi-node-instance-manager.cpp
src/mmi-manager/mmi-node-instance.cpp
src/mmi-manager/mmi-node-instance.h
src/mmi-manager/mmi-node-prototype.cpp
src/mmi-manager/mmi-node-prototype.h
src/mmi-manager/mmi-plugin-module-proxy.cpp
src/mmi-manager/mmi-plugin-module-proxy.h
src/mmi-manager/mmi-plugin-module-registry.cpp
src/mmi-manager/mmi-port-instance.cpp
src/mmi-manager/mmi-self-container.cpp
src/mmi-manager/mmi-workflow-instance-manager.cpp
src/mmi-manager/mmi-workflow-instance-manager.h
src/mmi-manager/mmi-workflow-instance.cpp
src/mmi-manager/mmi-workflow-instance.h
src/mmi-manager/mmi-workflow-prototype-manager.cpp
src/mmi-manager/mmi-workflow-prototype.cpp
src/mmi-manager/mmi-workflow-prototype.h
src/mmi/meson.build
src/mmi/mmi-client-manager.h
src/mmi/mmi-config-parser.cpp [new file with mode: 0644]
src/mmi/mmi-data.cpp
src/mmi/mmi-ipc-ecore.cpp [new file with mode: 0644]
src/mmi/mmi-ipc-ecore.h [new file with mode: 0644]
src/mmi/mmi-ipc-tidl.cpp
src/mmi/mmi-ipc-tidl.h
src/mmi/mmi-log.h
src/mmi/mmi-node-action.cpp [new file with mode: 0644]
src/mmi/mmi-node-logic.cpp
src/mmi/mmi-node-processor.cpp
src/mmi/mmi-node.cpp
src/mmi/mmi-port.cpp
src/mmi/mmi-signal.cpp
src/mmi/mmi-workflow-instance-manager.h
src/mmi/mmi-workflow-instance.cpp
src/mmi/mmi-workflow-script-parser.h
src/mmi/mmi-workflow.cpp
src/mmi/mmi.cpp
tests/mmi-manager/plugin-module-registry/mmi-plugin-module-registry-tests.cpp
tests/mmi-manager/workflow-instance/mmi-workflow-instance-tests.cpp
tests/mmi/meson.build
tests/mmi/mmi-data-test.cpp
tests/mmi/mmi-ipc-test.cpp
tests/mmi/mmi-main-test.cpp
tests/mmi/signal/mmi-signal-test.cpp [new file with mode: 0644]
tidl/mmi.tidl

index a3a3de2..6423806 100644 (file)
@@ -8,10 +8,13 @@ install_headers(
        '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',
        )
index f09d947..c4a5205 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_ATTRIBUTE_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 #include <stdlib.h>
 #include <mmi-primitive-value.h>
 
diff --git a/capi/mmi-config-parser.h b/capi/mmi-config-parser.h
new file mode 100644 (file)
index 0000000..6c3fd31
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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_ */
index e1a8b5a..01ee761 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_DATA_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 #include <stdlib.h>
 
 
@@ -49,6 +49,7 @@ typedef enum {
     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,
@@ -64,12 +65,12 @@ typedef enum {
 
 - 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
@@ -112,16 +113,17 @@ typedef enum {
     }
     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
@@ -160,6 +162,10 @@ int mmi_data_create_video(const void *ptr, size_t len, mmi_data_h *data);
 
 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);
@@ -184,6 +190,10 @@ int mmi_data_get_video(mmi_data_h data, const void **ptr, size_t *len);
 
 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);
index edbf780..3e8bd45 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_ERROR_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 
 
 /**
@@ -39,19 +39,16 @@ extern "C" {
 #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;
 
 
diff --git a/capi/mmi-node-action.h b/capi/mmi-node-action.h
new file mode 100644 (file)
index 0000000..69e3020
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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__ */
index 3cd7551..8ff0f15 100644 (file)
@@ -59,6 +59,17 @@ enum mmi_standard_node_processor_type_e {
     /*
         - 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
index 124ecca..a6ddc09 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_NODE_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 
 #include <mmi-attribute.h>
 #include <mmi-data.h>
@@ -49,6 +49,7 @@ enum mmi_standard_node_type_e {
     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;
index b68e22c..336233f 100644 (file)
@@ -27,6 +27,7 @@
 #include <mmi-node-processor.h>
 #include <mmi-node-logic.h>
 #include <mmi-node-controller.h>
+#include <mmi-node-action.h>
 #include <mmi-workflow.h>
 
 /**
index 2efc3de..23963fb 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_PORT_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 
 #include <mmi-data.h>
 #include <mmi-defines.h>
index b8b25e8..8679ca8 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_PRIMITIVE_VALUE_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 #include <stdlib.h>
 
 
index 3d989ec..7db8613 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_SIGNAL_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 
 #include <stdlib.h>
 #include <string.h>
index 148dd3e..862ebb4 100644 (file)
@@ -20,7 +20,7 @@
 #define __TIZEN_UIX_MMI_WORKFLOW_H__
 
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
 
 #include <mmi-attribute.h>
 #include <mmi-data.h>
@@ -76,6 +76,12 @@ typedef struct {
 } 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];
@@ -91,6 +97,8 @@ typedef struct {
     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;
@@ -125,7 +133,7 @@ int mmi_workflow_attribute_assign(mmi_workflow_h workflow, const char *attribute
 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. */
@@ -172,7 +180,7 @@ int mmi_workflow_instance_deactivate(mmi_workflow_instance_h instance);
 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);
index e3df8d8..06a1cd4 100644 (file)
@@ -18,7 +18,8 @@
 #ifndef __MMI_H__
 #define __MMI_H__
 
-#include <tizen.h>
+#include "mmi-platform-config.h"
+
 #define MMI_API __attribute__ ((visibility("default")))
 
 #include <mmi-defines.h>
diff --git a/external/magic_enum/magic_enum.hpp b/external/magic_enum/magic_enum.hpp
new file mode 100644 (file)
index 0000000..a4ea49a
--- /dev/null
@@ -0,0 +1,1472 @@
+//  __  __             _        ______                          _____
+// |  \/  |           (_)      |  ____|                        / ____|_     _
+// | \  / | __ _  __ _ _  ___  | |__   _ __  _   _ _ __ ___   | |   _| |_ _| |_
+// | |\/| |/ _` |/ _` | |/ __| |  __| | '_ \| | | | '_ ` _ \  | |  |_   _|_   _|
+// | |  | | (_| | (_| | | (__  | |____| | | | |_| | | | | | | | |____|_|   |_|
+// |_|  |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_|  \_____|
+//                __/ | 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
index 7818836..9920cdb 100644 (file)
@@ -6,6 +6,9 @@ project(
        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'))
@@ -13,9 +16,17 @@ mmi_prefix_libdir = join_paths(mmi_prefix, get_option('libdir'))
 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
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644 (file)
index 0000000..6d1f29a
--- /dev/null
@@ -0,0 +1 @@
+option('platform_option', type : 'string', value : 'linux', description : 'An option for specifying target platform')
index 84f31e4..2495414 100644 (file)
@@ -1,5 +1,3 @@
-%define USE_GCOV 0
-
 Name:          mmi
 Version:       2.0.1
 Release:       0
@@ -18,18 +16,17 @@ BuildRequires:      pkgconfig(glib-2.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
 
@@ -53,6 +50,13 @@ Requires:    pkgconfig(rpc-port)
 %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
@@ -70,7 +74,7 @@ tidlc -s -l C -i tidl/mmi.tidl -o mmi_stub
 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"
@@ -81,17 +85,47 @@ meson setup --prefix=/usr \
        --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
@@ -108,7 +142,6 @@ ninja -C builddir test
 %license COPYING
 %{_datadir}/mmi/plugins/*.so*
 %{_datadir}/mmi/scripts/*.mws
-%{_datadir}/face_recognition/*
 
 %files cli
 %manifest %{name}.manifest
@@ -116,6 +149,7 @@ ninja -C builddir test
 %license COPYING
 %{_bindir}/mmi-cli
 %{_bindir}/mmi-cli-node-tester
+#%{TZ_SYS_RO_SHARE}/mmi/configs/mmi-config.xml
 
 %files devel
 %manifest %{name}.manifest
@@ -124,9 +158,13 @@ ninja -C builddir test
 %{_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
-
diff --git a/platform/linux/meson.build b/platform/linux/meson.build
new file mode 100644 (file)
index 0000000..15842f3
--- /dev/null
@@ -0,0 +1,11 @@
+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'
+       )
diff --git a/platform/linux/mmi-platform-config.h b/platform/linux/mmi-platform-config.h
new file mode 100644 (file)
index 0000000..5c06d5c
--- /dev/null
@@ -0,0 +1,63 @@
+#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)
diff --git a/platform/meson.build b/platform/meson.build
new file mode 100644 (file)
index 0000000..409bafc
--- /dev/null
@@ -0,0 +1,2 @@
+mmi_platform_option = get_option('platform_option')
+subdir(mmi_platform_option)
diff --git a/platform/tizen/meson.build b/platform/tizen/meson.build
new file mode 100644 (file)
index 0000000..9f08faf
--- /dev/null
@@ -0,0 +1,11 @@
+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'
+       )
diff --git a/platform/tizen/mmi-platform-config.h b/platform/tizen/mmi-platform-config.h
new file mode 100644 (file)
index 0000000..8c0bc9a
--- /dev/null
@@ -0,0 +1,38 @@
+#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
+
index c7ea24c..bef0dc0 100644 (file)
@@ -1,2 +1 @@
-subdir('nodes')
 subdir('workflows')
diff --git a/plugins/nodes/camera/meson.build b/plugins/nodes/camera/meson.build
deleted file mode 100644 (file)
index add475c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-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
-       )
diff --git a/plugins/nodes/camera/mmi-module-camera-preview.cpp b/plugins/nodes/camera/mmi-module-camera-preview.cpp
deleted file mode 100644 (file)
index bdc4a30..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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, &timestamp);
-
-    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);
-    }
-}
-
diff --git a/plugins/nodes/camera/mmi-module-camera-preview.h b/plugins/nodes/camera/mmi-module-camera-preview.h
deleted file mode 100644 (file)
index 17ba9d1..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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);
-};
diff --git a/plugins/nodes/camera/mmi-module-camera.cpp b/plugins/nodes/camera/mmi-module-camera.cpp
deleted file mode 100644 (file)
index 9ecea3a..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-#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"
diff --git a/plugins/nodes/face-recognition/data/recognizerInfo.json b/plugins/nodes/face-recognition/data/recognizerInfo.json
deleted file mode 100644 (file)
index dc7ba76..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-    "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
diff --git a/plugins/nodes/face-recognition/meson.build b/plugins/nodes/face-recognition/meson.build
deleted file mode 100644 (file)
index 6e48678..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-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/')
diff --git a/plugins/nodes/face-recognition/mmi-module-fr-data-manager.cpp b/plugins/nodes/face-recognition/mmi-module-fr-data-manager.cpp
deleted file mode 100644 (file)
index 10b5f8c..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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;
-}
diff --git a/plugins/nodes/face-recognition/mmi-module-fr-data-manager.h b/plugins/nodes/face-recognition/mmi-module-fr-data-manager.h
deleted file mode 100644 (file)
index 000de19..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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};
-};
diff --git a/plugins/nodes/face-recognition/mmi-module-fr.cpp b/plugins/nodes/face-recognition/mmi-module-fr.cpp
deleted file mode 100644 (file)
index 0266f6a..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-#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"
diff --git a/plugins/nodes/face-recognition/mv_face_recognition_internal.h b/plugins/nodes/face-recognition/mv_face_recognition_internal.h
deleted file mode 100644 (file)
index bf0f362..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/match/meson.build b/plugins/nodes/match/meson.build
deleted file mode 100644 (file)
index 8331078..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-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
-       )
diff --git a/plugins/nodes/match/mmi-module-match-text-candidates.cpp b/plugins/nodes/match/mmi-module-match-text-candidates.cpp
deleted file mode 100644 (file)
index db19c9c..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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();
-}
-
diff --git a/plugins/nodes/match/mmi-module-match-text-candidates.h b/plugins/nodes/match/mmi-module-match-text-candidates.h
deleted file mode 100644 (file)
index a9b015f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/match/mmi-module-match.cpp b/plugins/nodes/match/mmi-module-match.cpp
deleted file mode 100644 (file)
index bd76346..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-#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"
diff --git a/plugins/nodes/meson.build b/plugins/nodes/meson.build
deleted file mode 100755 (executable)
index 9e13383..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-subdir('mic')
-subdir('camera')
-subdir('match')
-subdir('regex-match')
-subdir('face-recognition')
-subdir('voice-touch')
diff --git a/plugins/nodes/mic/meson.build b/plugins/nodes/mic/meson.build
deleted file mode 100644 (file)
index b01fe78..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-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
-       )
diff --git a/plugins/nodes/mic/mmi-module-mic-recorder.cpp b/plugins/nodes/mic/mmi-module-mic-recorder.cpp
deleted file mode 100644 (file)
index 800bf7a..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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;
-}
diff --git a/plugins/nodes/mic/mmi-module-mic-recorder.h b/plugins/nodes/mic/mmi-module-mic-recorder.h
deleted file mode 100644 (file)
index 44fd953..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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};
-};
diff --git a/plugins/nodes/mic/mmi-module-mic.cpp b/plugins/nodes/mic/mmi-module-mic.cpp
deleted file mode 100644 (file)
index a81ae8a..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-#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"
diff --git a/plugins/nodes/regex-match/meson.build b/plugins/nodes/regex-match/meson.build
deleted file mode 100644 (file)
index f214608..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-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
-       )
diff --git a/plugins/nodes/regex-match/mmi-module-regex-match-regex-candidates.cpp b/plugins/nodes/regex-match/mmi-module-regex-match-regex-candidates.cpp
deleted file mode 100644 (file)
index ada0376..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 &regex = 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();
-}
-
diff --git a/plugins/nodes/regex-match/mmi-module-regex-match-regex-candidates.h b/plugins/nodes/regex-match/mmi-module-regex-match-regex-candidates.h
deleted file mode 100644 (file)
index 9eed260..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/regex-match/mmi-module-regex-match.cpp b/plugins/nodes/regex-match/mmi-module-regex-match.cpp
deleted file mode 100644 (file)
index e110148..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-#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, &regex_name);
-
-        mmi_primitive_value_h regex_pattern = nullptr;
-        mmi_primitive_value_get_array_element(value, i + 1, &regex_pattern);
-
-        const char *regex_name_value = nullptr;
-        mmi_primitive_value_get_string(regex_name, &regex_name_value);
-
-        const char *regex_pattern_value = nullptr;
-        mmi_primitive_value_get_string(regex_pattern, &regex_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"
diff --git a/plugins/nodes/voice-touch/meson.build b/plugins/nodes/voice-touch/meson.build
deleted file mode 100644 (file)
index 1564037..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-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
-       )
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-candidates.cpp b/plugins/nodes/voice-touch/mmi-module-voice-touch-candidates.cpp
deleted file mode 100644 (file)
index 07e08bc..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * 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();
-}
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-candidates.h b/plugins/nodes/voice-touch/mmi-module-voice-touch-candidates.h
deleted file mode 100644 (file)
index 29b6f6a..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-common.h b/plugins/nodes/voice-touch/mmi-module-voice-touch-common.h
deleted file mode 100644 (file)
index 18e0a7e..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-
-/*
- * 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__ */
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-data-utility.cpp b/plugins/nodes/voice-touch/mmi-module-voice-touch-data-utility.cpp
deleted file mode 100644 (file)
index 24c43a7..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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);
-    }
-}
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-data-utility.h b/plugins/nodes/voice-touch/mmi-module-voice-touch-data-utility.h
deleted file mode 100644 (file)
index db0cc42..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-primitive-utility.cpp b/plugins/nodes/voice-touch/mmi-module-voice-touch-primitive-utility.cpp
deleted file mode 100644 (file)
index 6c39a1f..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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);
-}
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-primitive-utility.h b/plugins/nodes/voice-touch/mmi-module-voice-touch-primitive-utility.h
deleted file mode 100644 (file)
index 32c70a4..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-screen-info.cpp b/plugins/nodes/voice-touch/mmi-module-voice-touch-screen-info.cpp
deleted file mode 100644 (file)
index 7aa456e..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * 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;
-}
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-screen-info.h b/plugins/nodes/voice-touch/mmi-module-voice-touch-screen-info.h
deleted file mode 100644 (file)
index 057c901..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-string-utility.cpp b/plugins/nodes/voice-touch/mmi-module-voice-touch-string-utility.cpp
deleted file mode 100644 (file)
index 7a1134c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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;
-}
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch-string-utility.h b/plugins/nodes/voice-touch/mmi-module-voice-touch-string-utility.h
deleted file mode 100644 (file)
index 12c71b2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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__ */
diff --git a/plugins/nodes/voice-touch/mmi-module-voice-touch.cpp b/plugins/nodes/voice-touch/mmi-module-voice-touch.cpp
deleted file mode 100644 (file)
index 76d72fc..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-#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"
index dd3564c..6da0280 100644 (file)
@@ -2,12 +2,10 @@ mmi_module_script_parser_library_srcs = [
        '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,
        ]
 
index b708256..ae02cdd 100644 (file)
@@ -8,14 +8,13 @@
 #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) {
index 49148b8..9e7b5ec 100644 (file)
@@ -4,12 +4,14 @@ name : USER_RECOGNITION
 @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
index 628d533..6bc11da 100644 (file)
@@ -2,12 +2,10 @@ mmi_module_voice_touch_library_srcs = [
        '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,
        ]
 
index f8baebd..a636f7f 100644 (file)
@@ -1,4 +1,5 @@
 #include <mmi.h>
+#include <mmi-log.h>
 #include <mmi-plugin-storage.h>
 #include <mmi-workflow.h>
 
@@ -7,7 +8,6 @@
 #include <string>
 #include <map>
 
-#include <dlog.h>
 #include <Ecore.h>
 
 #ifdef  LOG_TAG
@@ -66,7 +66,12 @@ extern "C" {
 
         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");
@@ -77,13 +82,14 @@ extern "C" {
 
 #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 */
@@ -94,40 +100,34 @@ extern "C" {
         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);
diff --git a/plugins/workflows/voice-touch/voice-touch.mws b/plugins/workflows/voice-touch/voice-touch.mws
deleted file mode 100644 (file)
index c4daa81..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-@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
index 55c517b..2fc5a2a 100644 (file)
@@ -2,12 +2,10 @@ mmi_module_wakeupless_command_library_srcs = [
        '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,
        ]
 
index 62d0070..c0379d3 100644 (file)
@@ -1,11 +1,11 @@
 #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()
@@ -57,6 +47,8 @@ extern "C" {
         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);
diff --git a/setup_linux_build.sh b/setup_linux_build.sh
new file mode 100755 (executable)
index 0000000..bf10d42
--- /dev/null
@@ -0,0 +1,5 @@
+meson setup --prefix=/usr/local/mmi \
+       --bindir /usr/local/mmi/bin \
+       --libdir /usr/local/mmi/lib \
+       --datadir /usr/local/mmi/share \
+       ./linux_build
index c09948d..f915565 100644 (file)
@@ -43,6 +43,7 @@ public:
     virtual int send(Message *message) = 0;
 };
 
+// LCOV_EXCL_START
 class CommunicationChannelManager : public CommunicationChannel,
     public SimpleEventObserver<WORKFLOW_OUTPUT_EVENT_TYPE> {
 public:
@@ -55,20 +56,23 @@ 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
 
index 4fc7ca0..9eb6924 100644 (file)
@@ -22,8 +22,6 @@
 #include <vector>
 #include <functional>
 
-#include <bundle.h>
-
 #include "mmi.h"
 
 namespace mmi {
@@ -42,9 +40,11 @@ enum class CLIENT_MESSAGE_TYPE {
     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 {
@@ -78,6 +78,12 @@ struct ClientMessageWorkflowInstanceSetAttribute : public ClientMessage {
     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};
@@ -88,6 +94,13 @@ struct ClientMessageWorkflowInstanceDeactivate : public ClientMessage {
     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
index 818b3e5..af09d14 100644 (file)
 
 #pragma once
 
+#include "mmi-platform-config.h"
 #include "mmi-event-observer.h"
 
 #include <memory>
-#include <bundle.h>
 
 namespace mmi {
 
@@ -39,10 +39,12 @@ struct WorkflowOutputEventOutputGenerated : public WorkflowOutputEvent {
     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
index 0512065..e90d46e 100644 (file)
@@ -1,19 +1,25 @@
-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(
@@ -31,7 +37,7 @@ mmi_cli_program_deps = [
 
 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,
index 3a4a9c4..2282f85 100644 (file)
@@ -106,7 +106,7 @@ private:
     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;
@@ -687,7 +687,7 @@ void Program::set_attribute(AttributeTestType type) {
         }
     }
     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);
index d3e6963..adcaf4d 100644 (file)
@@ -102,6 +102,36 @@ public:
         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);
@@ -146,6 +176,11 @@ int main(void)
         },
         "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();
         },
index 97c95c5..d5f79fb 100644 (file)
 #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
@@ -59,7 +51,7 @@ int main(int argc, char *argv[]) {
         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);
 
index ecec178..30310c2 100644 (file)
@@ -1,6 +1,5 @@
 mmi_manager_library_srcs = [
        'mmi-manager.cpp',
-       'mmi-ipc-tidl.cpp',
        'mmi-client.cpp',
        'mmi-common.cpp',
        'mmi-data-gateway.cpp',
@@ -17,39 +16,45 @@ mmi_manager_library_srcs = [
        '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(
@@ -66,13 +71,15 @@ mmi_manager_program_deps = [
        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/')
index 3135075..6c7ab41 100644 (file)
@@ -24,7 +24,6 @@
 #include "mmi-client.h"
 #include "mmi-common.h"
 #include "mmi-manager-log.h"
-#include "mmi_stub.h"
 
 namespace mmi {
 
@@ -34,6 +33,7 @@ ClientManager::ClientManager() {
 ClientManager::~ClientManager() {
 }
 
+// LCOV_EXCL_START
 void ClientManager::on_observer_event(
     const COMMUNICATION_CHANNEL_EVENT_TYPE &event, std::any data) {
     try {
@@ -48,6 +48,7 @@ void ClientManager::on_observer_event(
         LOGE("Failed to cast message data: %s", e.what());
     }
 }
+// LCOV_EXCL_STOP
 
 int ClientManager::initialize() {
     return MMI_ERROR_NONE;
index 50e1c1e..c3af26a 100644 (file)
@@ -33,7 +33,6 @@
 
 #include "mmi-common.h"
 #include "mmi-communication-channel.h"
-#include "mmi_stub.h"
 
 namespace mmi {
 
index 3fc6ad1..08cb1d7 100644 (file)
@@ -25,7 +25,7 @@
 #define __MMI_COMMON_H__
 
 #include <stdbool.h>
-#include <tizen.h>
+#include "mmi-platform-config.h"
 
 #ifndef MMI_API
 #define MMI_API __attribute__ ((visibility("default")))
diff --git a/src/mmi-manager/mmi-ipc-ecore.cpp b/src/mmi-manager/mmi-ipc-ecore.cpp
new file mode 100644 (file)
index 0000000..b2e6780
--- /dev/null
@@ -0,0 +1,350 @@
+#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, &parameter);
+
+                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
+
diff --git a/src/mmi-manager/mmi-ipc-ecore.h b/src/mmi-manager/mmi-ipc-ecore.h
new file mode 100644 (file)
index 0000000..87e6396
--- /dev/null
@@ -0,0 +1,43 @@
+#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
+
index a3f2325..70f571a 100644 (file)
@@ -37,12 +37,17 @@ 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");
@@ -64,6 +69,7 @@ int CommunicationChannelTIDL::connect() {
         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,
@@ -242,6 +248,67 @@ int CommunicationChannelTIDL::workflow_instance_set_attribute(rpc_port_stub_mmi_
     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**)&parameter_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(), &parameter_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, &parameter);
+
+        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);
@@ -297,16 +364,24 @@ void CommunicationChannelTIDL::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;
+        }
+
         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());
     }
@@ -334,6 +409,7 @@ void CommunicationChannelTIDL::clear_invoke_callbacks() {
     }
     m_invoke_callbacks.clear();
 }
+// LCOV_EXCL_STOP
 
 } // namespace communication
 //
index 9117ece..22c32cc 100644 (file)
@@ -50,17 +50,19 @@ private:
     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);
index 51afe9c..accce89 100644 (file)
@@ -24,7 +24,9 @@
 #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
@@ -47,4 +49,9 @@
 #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__ 
index ab07751..00178d0 100644 (file)
@@ -57,6 +57,7 @@ std::shared_ptr<NodeInstance> NodeInstanceManager::create_node_instance(
     return ret;
 }
 
+// LCOV_EXCL_START
 bool NodeInstanceManager::destroy_node_instance(
     std::shared_ptr<NodeInstance> node_instance) {
     if (node_instance) {
@@ -114,6 +115,7 @@ bool NodeInstanceManager::link_node_instances(
 
     return true;
 }
+// LCOV_EXCL_STOP
 
 void NodeInstanceManager::initialize() {
 }
@@ -131,6 +133,7 @@ void NodeInstanceManager::set_plugin_module_proxy_provider(
     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;
@@ -144,7 +147,6 @@ void NodeInstanceManager::on_observer_event(
             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);
                 }
             }
@@ -168,6 +170,7 @@ void NodeInstanceManager::on_observer_event(
         LOGE("Failed to cast message data: %s", e.what());
     }
 }
+// LCOV_EXCL_STOP
 
 } // namespace mmi
 
index 8c4c6db..f754f2a 100644 (file)
@@ -32,11 +32,13 @@ NodeInstance::NodeInstance(
     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(
@@ -67,6 +69,10 @@ 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());
@@ -122,14 +128,15 @@ bool NodeInstance::initialize() {
         }
     }
 
-    _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;
@@ -174,6 +181,7 @@ bool NodeInstance::initialize() {
     if (m_callbacks.initialized_cb != nullptr) {
         m_callbacks.initialized_cb(static_cast<mmi_node_instance_h>(this));
     }
+// LCOV_EXCL_STOP
 
     return true;
 }
@@ -183,7 +191,9 @@ bool NodeInstance::deinitialize() {
         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;
 }
 
@@ -280,6 +290,7 @@ std::shared_ptr<IPluginModuleProxy> NodeInstance::get_plugin_module_proxy() {
     return m_plugin_module_proxy;
 }
 
+// LCOV_EXCL_START
 bool NodeInstance::set_attribute(mmi_attribute_h attribute)
 {
     char *name = nullptr;
@@ -294,7 +305,22 @@ bool NodeInstance::set_attribute(mmi_attribute_h attribute)
     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
 
 
index 5e7e9bf..99c66f5 100644 (file)
@@ -65,7 +65,8 @@ public:
     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;
index 2a6aa31..8926170 100644 (file)
@@ -66,6 +66,13 @@ bool NodePrototype::is_valid() {
                 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());
index 9273134..2870d2f 100644 (file)
@@ -30,7 +30,9 @@
 #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>
@@ -44,20 +46,21 @@ typedef std::variant<
     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");
     }
 }
 
index b9682dc..6cadc29 100644 (file)
@@ -28,6 +28,7 @@
 
 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) {
@@ -208,6 +209,7 @@ void PluginModuleProxySharedLibrary::add_node_instance_info(mmi_plugin_module_no
 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
 
index f02002e..1a56c43 100644 (file)
@@ -100,7 +100,7 @@ struct IPluginModuleProxyFactory : public SimpleEventObservable<PROXY_FACTORY_EV
 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()};
index 0f19279..29e0b8f 100644 (file)
@@ -98,6 +98,12 @@ static std::shared_ptr<NodePrototype> create_node_prototype(mmi_node_h node) {
             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;
@@ -146,7 +152,10 @@ bool PluginModuleRegistry::load_node_prototypes() {
                 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 {
@@ -202,6 +211,12 @@ static std::shared_ptr<WorkflowPrototype> create_workflow_prototype(mmi_workflow
                 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;
@@ -243,6 +258,17 @@ static std::shared_ptr<WorkflowPrototype> create_workflow_prototype(mmi_workflow
             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++) {
index d74e0b4..44c771c 100644 (file)
@@ -50,8 +50,6 @@ void PortInstance::add_linked_port_instance(std::shared_ptr<PortInstance> port_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);
     }
@@ -62,8 +60,6 @@ void PortInstance::on_output_data_generated(mmi_data_h 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);
     }
index daffaf9..558a1f4 100644 (file)
@@ -28,6 +28,7 @@
 
 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() {
@@ -365,6 +366,7 @@ void PluginModuleProxySelfContainerTest::remove_node_instance_info(mmi_node_inst
         }
     }
 }
+// LCOV_EXCL_STOP
 
 } // namespace mmi
 
index bfbd1fe..c32996e 100644 (file)
@@ -71,6 +71,7 @@ std::shared_ptr<WorkflowInstance> WorkflowInstanceManager::get_workflow_instance
     return nullptr;
 }
 
+// LCOV_EXCL_START
 void WorkflowInstanceManager::on_observer_event(
     const COMMUNICATION_CHANNEL_EVENT_TYPE &event, std::any data) {
     try {
@@ -113,6 +114,11 @@ void WorkflowInstanceManager::handle_client_message(ClientMessage *message) {
         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);
@@ -229,6 +235,20 @@ void WorkflowInstanceManager::handle_set_attribute(
     }
 }
 
+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) {
@@ -256,6 +276,7 @@ void WorkflowInstanceManager::handle_deactivate(
         instance->deactivate();
     }
 }
+// LCOV_EXCL_STOP
 
 } // namespace mmi
 
index 5e32912..e4b50c8 100644 (file)
@@ -72,6 +72,7 @@ private:
     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:
index e26b78f..24c7143 100644 (file)
@@ -25,7 +25,6 @@
 #include "mmi-manager-log.h"
 #include "mmi-workflow-output-event.h"
 
-#include <bundle.h>
 namespace mmi {
 
 WorkflowInstance::WorkflowInstance() {
@@ -166,18 +165,18 @@ void WorkflowInstance::initialize() {
             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);
 
@@ -220,8 +219,10 @@ void WorkflowInstance::deinitialize() {
         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");
@@ -253,6 +254,7 @@ void WorkflowInstance::deactivate() {
 
     m_state = WORKFLOW_INSTANCE_STATE::INITIALIZED;
 }
+// LCOV_EXCL_STOP
 
 bool WorkflowInstance::set_attribute(mmi_attribute_h attribute) {
     _D("Setting attribute : %p", attribute);
@@ -282,8 +284,11 @@ bool WorkflowInstance::set_attribute(mmi_attribute_h 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());
                 }
@@ -300,6 +305,51 @@ bool WorkflowInstance::set_attribute(mmi_attribute_h attribute) {
     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 {
@@ -334,6 +384,7 @@ void WorkflowInstance::on_observer_event(
         LOGE("Failed to cast message data: %s", e.what());
     }
 }
+// LCOV_EXCL_STOP
 
 bool WorkflowInstance::set_attribute_default_values() {
     _D("Setting attribute default value");
index 42ef79c..dd80d8f 100644 (file)
@@ -74,6 +74,8 @@ public:
     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:
index 5aa3977..c5d89f3 100644 (file)
@@ -52,6 +52,7 @@ bool WorkflowPrototypeManager::add_workflow_prototype(std::shared_ptr<WorkflowPr
     return true;
 }
 
+// LCOV_EXCL_START
 std::shared_ptr<WorkflowPrototype> WorkflowPrototypeManager::get_workflow_prototype(
     mmi_standard_workflow_type_e type) {
     std::shared_ptr<WorkflowPrototype> ret;
@@ -71,6 +72,7 @@ void WorkflowPrototypeManager::initialize() {
 
 void WorkflowPrototypeManager::deinitialize() {
 }
+// LCOV_EXCL_STOP
 
 } // namespace mmi
 
index ca66168..9866de1 100644 (file)
@@ -70,7 +70,15 @@ bool WorkflowPrototype::add_attribute_assignment_info(AttributeAssignmentInfo at
 }
 
 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;
 }
 
@@ -91,6 +99,7 @@ std::vector<LinkInfo> WorkflowPrototype::get_link_infos() {
     return m_link_infos;
 }
 
+// LCOV_EXCL_START
 std::vector<AttributeAssignmentInfo> WorkflowPrototype::get_attribute_assignment_infos() {
     return m_attribute_assignment_infos;
 }
@@ -98,6 +107,11 @@ std::vector<AttributeAssignmentInfo> WorkflowPrototype::get_attribute_assignment
 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;
index 85058b1..14a397c 100644 (file)
@@ -55,6 +55,12 @@ typedef struct {
 } 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;
@@ -80,6 +86,7 @@ public:
     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();
@@ -88,6 +95,7 @@ public:
     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;
@@ -98,6 +106,7 @@ private:
     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;
 };
 
index 4260c90..11613ef 100644 (file)
@@ -3,11 +3,7 @@ mmi_srcs = [
        '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',
@@ -16,32 +12,42 @@ mmi_srcs = [
        '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(
index c8b921b..9851726 100644 (file)
@@ -34,7 +34,7 @@ struct ICommunicationChannelFactory {
 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) {
@@ -67,7 +67,7 @@ public:
         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;
 
@@ -76,7 +76,8 @@ public:
         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() {
@@ -85,13 +86,41 @@ public:
 
     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};
diff --git a/src/mmi/mmi-config-parser.cpp b/src/mmi/mmi-config-parser.cpp
new file mode 100644 (file)
index 0000000..38c5ef6
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * 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;
+}
index 7119506..f12867b 100644 (file)
@@ -61,7 +61,7 @@ static inline mmi_data_h *get_element_value_pointer_in_struct(mmi_data_h struct_
     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");
@@ -87,9 +87,9 @@ int mmi_data_create_bool(bool value, mmi_data_h *data) {
 
     *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) {
@@ -116,10 +116,10 @@ int mmi_data_create_int(int value, mmi_data_h *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");
@@ -145,9 +145,9 @@ int mmi_data_create_float(float value, mmi_data_h *data) {
 
     *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) {
@@ -173,7 +173,6 @@ int mmi_data_create_text(const char *value, mmi_data_h *data) {
 
     *data = new_data;
 
-    _D("[DEBUG] Success to create for string(%s)", value);
     return MMI_ERROR_NONE;
 }
 
@@ -202,10 +201,10 @@ int mmi_data_create_audio(const void *ptr, size_t len, mmi_data_h *data) {
 
     *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");
@@ -231,7 +230,6 @@ int mmi_data_create_video(const void *ptr, size_t len, mmi_data_h *data) {
 
     *data = new_data;
 
-    _D("[DEBUG] Success to create for video data. len(%zu)", len);
     return MMI_ERROR_NONE;
 }
 
@@ -260,7 +258,67 @@ int mmi_data_create_user_identification(const void *ptr, size_t len, mmi_data_h
 
     *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;
 }
 
@@ -282,7 +340,6 @@ int mmi_data_create_array(mmi_data_h *data) {
 
     *data = new_data;
 
-    _D("[DEBUG] Success to create empty array");
     return MMI_ERROR_NONE;
 }
 
@@ -318,7 +375,6 @@ int mmi_data_add_array_element(mmi_data_h array, mmi_data_h element) {
         return MMI_ERROR_OUT_OF_MEMORY;
     }
 
-    _D("[DEBUG] Success to add element(%zu)", get_count_of_elements(array));
     return MMI_ERROR_NONE;
 }
 
@@ -340,7 +396,6 @@ int mmi_data_create_struct(mmi_data_h *struct_handle) {
 
     *struct_handle = new_data;
 
-    _D("[DEBUG] Success to create empty array");
     return MMI_ERROR_NONE;
 }
 
@@ -377,7 +432,6 @@ int mmi_data_set_struct_element(mmi_data_h struct_handle, const char *name, mmi_
         return MMI_ERROR_OUT_OF_MEMORY;
     }
 
-    _D("[DEBUG] Success to add element with name(%s)", name);
     return MMI_ERROR_NONE;
 }
 
@@ -389,10 +443,10 @@ int mmi_data_get_type(mmi_data_h data, mmi_data_type_e *type) {
 
     *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");
@@ -406,9 +460,9 @@ int mmi_data_get_bool(mmi_data_h data, bool *value) {
 
     *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) {
@@ -423,10 +477,10 @@ int mmi_data_get_int(mmi_data_h data, int *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");
@@ -440,9 +494,9 @@ int mmi_data_get_float(mmi_data_h data, float *value) {
 
     *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) {
@@ -457,10 +511,10 @@ int mmi_data_get_text(mmi_data_h data, const char **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");
@@ -475,7 +529,6 @@ int mmi_data_get_audio(mmi_data_h data, const void **ptr, size_t *len) {
     *len = data->datalen;
     *ptr = data->data;
 
-    _D("[DEBUG] Success to get value: audio(%zu)", *len);
     return MMI_ERROR_NONE;
 }
 
@@ -493,7 +546,6 @@ int mmi_data_get_video(mmi_data_h data, const void **ptr, size_t *len) {
     *len = data->datalen;
     *ptr = data->data;
 
-    _D("[DEBUG] Success to get value: video(%zu)", *len);
     return MMI_ERROR_NONE;
 }
 
@@ -511,7 +563,55 @@ int mmi_data_get_user_identification(mmi_data_h data, const void **ptr, size_t *
     *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;
 }
 
@@ -528,7 +628,6 @@ int mmi_data_get_array_count(mmi_data_h array, size_t *count) {
 
     *count = get_count_of_elements(array);
 
-    _D("[DEBUG] Success to get array count(%zu)", *count);
     return MMI_ERROR_NONE;
 }
 
@@ -551,7 +650,6 @@ int mmi_data_get_array_element(mmi_data_h array, size_t index, mmi_data_h *eleme
 
     *element = *(get_element_pointer_in_array(array, index));
 
-    _D("[DEBUG] Success to get array element on index(%zu)", index);
     return MMI_ERROR_NONE;
 }
 
@@ -590,7 +688,6 @@ int mmi_data_get_struct_element(mmi_data_h struct_handle, const char *name, mmi_
 
     *element = target_element;
 
-    _D("[DEBUG] Success to get element on name(%s)", name);
     return MMI_ERROR_NONE;
 }
 
@@ -607,7 +704,6 @@ int mmi_data_get_struct_count(mmi_data_h struct_handle, size_t *count) {
 
     *count = get_count_of_struct_elements(struct_handle);
 
-    _D("[DEBUG] Success to get struct count(%zu)", *count);
     return MMI_ERROR_NONE;
 }
 
@@ -631,7 +727,6 @@ int mmi_data_get_struct_element_name(mmi_data_h struct_handle, size_t index, con
     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;
 }
 
@@ -655,7 +750,6 @@ int mmi_data_get_struct_element_value(mmi_data_h struct_handle, size_t index, mm
 
     *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;
 }
 
@@ -679,10 +773,10 @@ int mmi_data_destroy(mmi_data_h data) {
     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;
@@ -772,8 +866,6 @@ int mmi_data_to_bytes(mmi_data_h data, unsigned char **bytes, size_t *length) {
         *length = total_size;
     }
 
-    _D("[DEBUG] Success to convert data to bytes");
-
     return MMI_ERROR_NONE;
 }
 
@@ -857,7 +949,6 @@ int mmi_data_from_bytes(unsigned char *bytes, size_t length, mmi_data_h *data) {
         *data = value;
     }
 
-    _D("[DEBUG] Success to convert from bytes. type(%d), size(%zu)", type, length);
-
     return MMI_ERROR_NONE;
 }
+// LCOV_EXCL_STOP
diff --git a/src/mmi/mmi-ipc-ecore.cpp b/src/mmi/mmi-ipc-ecore.cpp
new file mode 100644 (file)
index 0000000..cb1fca3
--- /dev/null
@@ -0,0 +1,305 @@
+#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, &parameter);
+
+                char *parameter_name = nullptr;
+                mmi_signal_parameter_get_name(parameter, &parameter_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
+
diff --git a/src/mmi/mmi-ipc-ecore.h b/src/mmi/mmi-ipc-ecore.h
new file mode 100644 (file)
index 0000000..98c1ebe
--- /dev/null
@@ -0,0 +1,34 @@
+#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
+
index a58fc8f..bffcb93 100644 (file)
@@ -28,6 +28,10 @@ namespace mmi {
 
 namespace communication {
 
+std::shared_ptr<CommunicationChannelClient> CommunicationChannelClientFactory::create_channel() {
+    return std::make_shared<CommunicationChannelTIDL>();
+}
+
 CommunicationChannelTIDL::CommunicationChannelTIDL() {
 }
 
@@ -166,6 +170,11 @@ int CommunicationChannelTIDL::send(Message *message) {
         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);
@@ -304,6 +313,82 @@ int CommunicationChannelTIDL::workflow_instance_set_attribute(int local_workflow
     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, &parameter_count);
+
+    bundle *encoded = bundle_create();
+    bundle_add_str(encoded, "name", signal_name);
+    bundle_add_byte(encoded, "parameter_count", &parameter_count, sizeof(int));
+
+    for (int loop = 0;loop < parameter_count;loop++) {
+        mmi_signal_parameter_h parameter = nullptr;
+        mmi_signal_get_parameter(signal, loop, &parameter);
+
+        char *parameter_name = nullptr;
+        mmi_signal_parameter_get_name(parameter, &parameter_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);
 
index 8f794c7..c603998 100644 (file)
@@ -41,6 +41,7 @@ private:
     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);
index 7718fcd..17ef75f 100644 (file)
 #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__
diff --git a/src/mmi/mmi-node-action.cpp b/src/mmi/mmi-node-action.cpp
new file mode 100644 (file)
index 0000000..91e62e3
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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;
+}
+
index 36e003d..f859186 100644 (file)
@@ -42,10 +42,12 @@ int mmi_standard_node_get_logic_type(mmi_node_h node, mmi_standard_node_logic_ty
     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
 
index 8634a81..d94a7fe 100644 (file)
@@ -42,10 +42,12 @@ int mmi_standard_node_get_processor_type(mmi_node_h node, mmi_standard_node_proc
     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
 
index 1faffa9..47f7aff 100644 (file)
@@ -52,6 +52,7 @@ int mmi_node_add_port(mmi_node_h node, mmi_port_h port) {
     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");
@@ -75,6 +76,7 @@ int mmi_node_link_by_name(mmi_node_h from_node, const char *from_port_name, mmi_
     }
     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) {
@@ -182,6 +184,7 @@ int mmi_node_register(mmi_node_h node) {
                 }
                 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);
@@ -192,6 +195,17 @@ int mmi_node_register(mmi_node_h node) {
                 }
                 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) {
@@ -274,6 +288,7 @@ int mmi_node_destroy(mmi_node_h node) {
     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;
 }
@@ -305,3 +320,4 @@ int mmi_node_instance_emit_signal(mmi_node_instance_h instance, mmi_signal_h sig
 int mmi_node_instance_update_pending_activation_result(mmi_error_e result) {
     return MMI_ERROR_NONE;
 }
+// LCOV_EXCL_STOP
index 2358a9e..9e3fc47 100644 (file)
@@ -82,6 +82,7 @@ MMI_API int mmi_port_get_data_type(mmi_port_h port, mmi_data_type_e *data_type)
     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");
@@ -94,6 +95,7 @@ MMI_API int mmi_port_get_callbacks(mmi_port_h port, mmi_port_callbacks *callback
 
     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) {
@@ -180,6 +182,7 @@ MMI_API int mmi_port_destroy(mmi_port_h port) {
     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();
@@ -203,3 +206,4 @@ MMI_API int mmi_port_instance_request_input_data_format(mmi_port_instance_h inst
 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
index 1d2c97c..bee325b 100644 (file)
 #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++) {
@@ -143,5 +167,5 @@ MMI_API int mmi_signal_destroy(mmi_signal_h handle) {
     }
 
     free(handle);
-    return 0;
+    return MMI_ERROR_NONE;
 }
index ae6ff6e..f286cbb 100644 (file)
@@ -48,6 +48,7 @@ public:
         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) {
@@ -66,6 +67,7 @@ public:
         }
         return ret;
     }
+// LCOV_EXCL_STOP
 
 private:
     int m_local_workflow_instance_id;
@@ -97,6 +99,15 @@ public:
         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);
@@ -108,6 +119,7 @@ public:
         }
         return ret;
     }
+// LCOV_EXCL_STOP
 
 private:
     int m_last_local_workflow_instance_id{0};
index 74d5844..fb2cea4 100644 (file)
@@ -29,7 +29,6 @@
 #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;
@@ -52,7 +51,7 @@ MMI_API int mmi_standard_workflow_instance_create(mmi_standard_workflow_type_e t
     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 =
@@ -69,6 +68,7 @@ MMI_API int mmi_standard_workflow_instance_create(mmi_standard_workflow_type_e t
     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");
@@ -81,7 +81,7 @@ MMI_API int mmi_workflow_instance_destroy(mmi_workflow_instance_h instance) {
         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);
@@ -94,6 +94,7 @@ MMI_API int mmi_workflow_instance_destroy(mmi_workflow_instance_h instance) {
 
     return MMI_ERROR_NONE;
 }
+// LCOV_EXCL_STOP
 
 MMI_API int mmi_workflow_instance_activate(mmi_workflow_instance_h instance) {
     if (nullptr == instance) {
@@ -101,7 +102,7 @@ MMI_API int mmi_workflow_instance_activate(mmi_workflow_instance_h 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;
@@ -117,13 +118,14 @@ MMI_API int mmi_workflow_instance_activate(mmi_workflow_instance_h instance) {
     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;
@@ -138,6 +140,7 @@ MMI_API int mmi_workflow_instance_deactivate(mmi_workflow_instance_h instance) {
 
     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) {
@@ -145,7 +148,7 @@ MMI_API int mmi_workflow_instance_set_attribute(mmi_workflow_instance_h 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;
@@ -162,7 +165,30 @@ MMI_API int mmi_workflow_instance_set_attribute(mmi_workflow_instance_h instance
     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");
@@ -184,3 +210,4 @@ MMI_API int mmi_workflow_instance_set_output_callback(mmi_workflow_instance_h in
 
     return MMI_ERROR_NONE;
 }
+// LCOV_EXCL_STOP
index d2e035d..0f20bfe 100644 (file)
@@ -28,6 +28,7 @@
 #include "mmi-node-processor.h"
 #include "mmi-node-logic.h"
 #include "mmi-node-controller.h"
+#include "mmi-node-action.h"
 
 enum class WorkflowScriptSection {
     NONE,
@@ -116,6 +117,7 @@ public:
         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"});
 
@@ -448,6 +450,8 @@ private:
         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;
 
index dcc7260..db6843a 100644 (file)
@@ -49,6 +49,8 @@ MMI_API int mmi_workflow_create(mmi_workflow_h *workflow) {
     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;
 
@@ -139,6 +141,10 @@ MMI_API int mmi_workflow_attribute_assign(mmi_workflow_h workflow, const char *a
     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;
@@ -153,6 +159,7 @@ MMI_API int mmi_workflow_attribute_assign(mmi_workflow_h workflow, const char *a
     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");
@@ -163,6 +170,11 @@ MMI_API int mmi_workflow_attribute_set_default_value(mmi_workflow_h workflow, mm
     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;
@@ -177,13 +189,35 @@ MMI_API int mmi_workflow_attribute_set_default_value(mmi_workflow_h workflow, mm
     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) {
index e49ec6e..88d10ec 100644 (file)
@@ -24,7 +24,6 @@
 #include <Ecore.h>
 
 #include "mmi-log.h"
-#include "mmi-ipc-tidl.h"
 
 #include "mmi-client-manager.h"
 
@@ -36,19 +35,12 @@ using namespace mmi::communication;
 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;
@@ -65,11 +57,12 @@ public:
             }
         }
     }
+// 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
 };
 
index d60dcde..66bc567 100644 (file)
@@ -30,8 +30,9 @@ public:
         _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());
 
@@ -74,8 +75,10 @@ public:
            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()) {
index 96d13b8..50cc718 100644 (file)
@@ -26,10 +26,14 @@ int __wrap_vconf_get_int(const char *in_key, int *intval)
 
 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);
 
@@ -39,12 +43,28 @@ public:
         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 {
@@ -66,6 +86,55 @@ public:
     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() {
@@ -89,7 +158,7 @@ public:
     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);
@@ -162,18 +231,143 @@ public:
 };
 
 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;
index 4834a64..ad61818 100644 (file)
@@ -4,6 +4,7 @@ mmi_tests_srcs = [
        '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',
        ]
index 393acb0..626449c 100644 (file)
@@ -88,6 +88,24 @@ TEST_F(MMIDataTest, MMIDataCreateDataByAudio_n) {
     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);
@@ -231,6 +249,18 @@ TEST_F(MMIDataTest, MMIDataGetType_p) {
     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);
@@ -319,6 +349,92 @@ TEST_F(MMIDataTest, MMIDataGetTextValue_n2) {
     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);
index 2574314..7604dcb 100644 (file)
 
 #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) {
index 1abb86a..aec1353 100644 (file)
 
 #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;
diff --git a/tests/mmi/signal/mmi-signal-test.cpp b/tests/mmi/signal/mmi-signal-test.cpp
new file mode 100644 (file)
index 0000000..1bbfc31
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * 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", &parameter);
+    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", &parameter);
+    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", &parameter_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", &parameter_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", &parameter_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", &parameter_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", &parameter);
+    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);
+}
index 3d5f6f0..aec62ab 100644 (file)
@@ -4,6 +4,7 @@ interface mmi {
        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);