Add voice touch intent understanding module 02/281602/1
authorSuyeon Hwang <stom.hwang@samsung.com>
Tue, 6 Sep 2022 12:36:14 +0000 (21:36 +0900)
committerTizen AI <ai.tzn.sec@samsung.com>
Tue, 20 Sep 2022 04:56:39 +0000 (13:56 +0900)
- Requirement:
IU module needs to handle voice touch event.

- Solution:
This patch adds new class which name is VoiceTouchEngine. This new class
is for handling voice touch event using CommandManager class. In order
to use this new class, this patch also fixes the mmi_iu module refer to
VoiceTouchEngine.

Change-Id: I68195c92faf11b2723a987db9a008000d449f394
Signed-off-by: Suyeon Hwang <stom.hwang@samsung.com>
src/mmimgr/iu/VoiceTouchEngine.cpp [new file with mode: 0644]
src/mmimgr/iu/VoiceTouchEngine.h [new file with mode: 0644]
src/mmimgr/iu/mmi_iu.cpp
src/mmimgr/meson.build

diff --git a/src/mmimgr/iu/VoiceTouchEngine.cpp b/src/mmimgr/iu/VoiceTouchEngine.cpp
new file mode 100644 (file)
index 0000000..a14eb6b
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * 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 <chrono>
+#include <Ecore.h>
+
+#include "mmi_iu_log.h"
+#include "StringUtil.h"
+#include "json_provider.h"
+
+#include "VoiceTouchEngine.h"
+
+
+using namespace std;
+
+static const string __SHOW_TOOLTIP_INVOCATION = "show tooltip";
+static const string __SHOW_NUMBER_INVOCATION = "show numbers";
+static const string __SHOW_GRID_INVOCATION = "show grid";
+
+static const int __DEFAULT_DISPLAY_WIDTH = 1920;
+static const int __DEFAULT_DISPLAY_HEIGHT = 1080;
+
+static const int __DEFAULT_GRID_NUM_X1 = 7;
+static const int __DEFAULT_GRID_NUM_Y1 = 5;
+static const int __DEFAULT_GRID_NUM_X2 = 4;
+static const int __DEFAULT_GRID_NUM_Y2 = 3;
+
+
+VoiceTouchEngine::VoiceTouchEngine()
+{
+       _I("[VoiceTouchEngine] Constructor");
+       __currentMode = VOICE_TOUCH_MODE_TOOLTIP_TEXT;
+
+       __itemList.clear();
+
+       __displayWidth = __DEFAULT_DISPLAY_WIDTH;
+       __displayHeight = __DEFAULT_DISPLAY_HEIGHT;
+
+       __gridX[0] = __DEFAULT_GRID_NUM_X1;
+       __gridY[0] = __DEFAULT_GRID_NUM_Y1;
+       __gridX[1] = __DEFAULT_GRID_NUM_X2;
+       __gridY[1] = __DEFAULT_GRID_NUM_Y2;
+
+       __outputResultCallback = nullptr;
+       __outputResultUserData = nullptr;
+
+       __outputModalityCallback = nullptr;
+       __outputModalityUserData = nullptr;
+
+       __findCommandTimer = nullptr;
+       __makeClickableItemResultTimer = nullptr;
+
+       resetCurrentGridInfo();
+}
+
+VoiceTouchEngine::~VoiceTouchEngine()
+{
+       _I("[VoiceTouchEngine] Destructor");
+       __itemList.clear();
+
+       __outputResultCallback = nullptr;
+       __outputResultUserData = nullptr;
+
+       __outputModalityCallback = nullptr;
+       __outputModalityUserData = nullptr;
+
+       if (__findCommandTimer != nullptr) {
+               ecore_timer_del(__findCommandTimer);
+               __findCommandTimer = nullptr;
+       }
+
+       if (__makeClickableItemResultTimer != nullptr) {
+               ecore_timer_del(__makeClickableItemResultTimer);
+               __makeClickableItemResultTimer = nullptr;
+       }
+}
+
+
+void VoiceTouchEngine::setDisplayInfo(int width, int height)
+{
+       __displayWidth = width;
+       __displayHeight = height;
+}
+
+void VoiceTouchEngine::setGridConfig(int numX, int numY, int step)
+{
+       __gridX[step] = numX;
+       __gridY[step] = numY;
+}
+
+long VoiceTouchEngine::getCurrentTimestamp()
+{
+       auto currentTime = chrono::steady_clock::now();
+       long timestamp = chrono::time_point_cast<chrono::milliseconds>(currentTime).time_since_epoch().count();
+
+       return timestamp;
+}
+
+bool VoiceTouchEngine::setInputModalityData(std::string appId, int modalityType, void *data)
+{
+       _I("[VoiceTouchEngine] Set input modality data. appId(%s)", appId.c_str());
+       __appId = appId;
+
+       if (modalityType == MMI_PROVIDER_EVENT_VOICE) {
+               _I("[VoiceTouchEngine] Voice modality");
+               mmi_provider_event_voice *event = static_cast<mmi_provider_event_voice *>(data);
+
+               return handleVoiceInput(event);
+       }
+
+       if (modalityType == MMI_PROVIDER_EVENT_SCREEN_ANALYZER) {
+               _I("[VoiceTouchEngine] Screen analyzer modality");
+               mmi_provider_event_screen_analyzer *event = static_cast<mmi_provider_event_screen_analyzer *>(data);
+
+               return handleScreenAnalyzerInput(event);
+       }
+
+       _E("[VoiceTouchEngine] This type is not supported by this engine. type(%d)", modalityType);
+       return false;
+}
+
+bool VoiceTouchEngine::handleVoiceInput(mmi_provider_event_voice *voiceEvent)
+{
+       _I("[VoiceTouchEngine] Voice modality");
+       if (voiceEvent == nullptr) {
+               _E("[VoiceTouchEngine] Parameter is null");
+               return false;
+       }
+
+       _I("[VoiceTouchEngine] Input data. event(%d), text(%s)", voiceEvent->result_type, voiceEvent->source);
+       int timestamp = getCurrentTimestamp();
+
+       JsonProvider provider;
+       provider.setInputEvent(MMI_KEY_VOICE_TOUCH);
+
+       string asrResult = string(voiceEvent->source);
+       voice_result_type_e asrEvent = static_cast<voice_result_type_e>(voiceEvent->result_type);
+       if (asrEvent == VOICE_RESULT_TYPE_PARTIAL) {
+               _I("[VoiceTouchEngine] Partial ASR result");
+               setPartialAsrResult(asrResult, timestamp, provider);
+               invokeOutputResultCallback(provider.jsonToString());
+               return true;
+       }
+
+       _I("[VoiceTouchEngine] Final ASR result");
+       setFinalAsrResult(asrResult, timestamp, provider);
+       invokeOutputResultCallback(provider.jsonToString());
+
+       bool isModeUpdated = checkVoiceTouchMode(asrResult);
+       if (isModeUpdated) {
+               _I("[VoiceTouchEngine] Voice touch mode is changed. (%d)", static_cast<int>(__currentMode));
+               resetCurrentGridInfo();
+               __makeClickableItemResultTimer = ecore_timer_add(0.0, makeClickableItemResultCallback, static_cast<void *>(this));
+       } else {
+               __asrResult = asrResult;
+               __findCommandTimer = ecore_timer_add(0.0, findCommandCallback, static_cast<void *>(this));
+       }
+
+       return true;
+}
+
+void VoiceTouchEngine::setPartialAsrResult(const std::string &result, int timestamp, JsonProvider &provider)
+{
+       _I("[VoiceTouchEngine] Set partial ASR result into output. timestamp(%d). item(%s)", timestamp, result.c_str());
+
+       provider.setOutputEvent(MMI_KEY_ASR_PARTIAL_RESULT);
+       provider.setAsrPartialResult(result.c_str(), timestamp);
+}
+
+void VoiceTouchEngine::setFinalAsrResult(const std::string &result, int timestamp, JsonProvider &provider)
+{
+       _I("[VoiceTouchEngine] Set final ASR result into output. timestamp(%d). item(%s)", timestamp, result.c_str());
+
+       provider.setOutputEvent(MMI_KEY_ASR_FINAL_RESULT);
+       provider.setAsrFinalResult(result.c_str(), timestamp);
+}
+
+Eina_Bool VoiceTouchEngine::makeClickableItemResultCallback(void *data)
+{
+       VoiceTouchEngine *engine = static_cast<VoiceTouchEngine *>(data);
+       if (engine == nullptr) {
+               _E("[VoiceTouchEngine] Timer data is invalid");
+               return ECORE_CALLBACK_CANCEL;
+       }
+
+       int timestamp = engine->getCurrentTimestamp();
+
+       JsonProvider provider;
+       provider.setInputEvent(MMI_KEY_VOICE_TOUCH);
+
+       engine->makeClickableItemInfo(timestamp, provider);
+       engine->invokeOutputResultCallback(provider.jsonToString());
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+Eina_Bool VoiceTouchEngine::findCommandCallback(void *data)
+{
+       VoiceTouchEngine *engine = static_cast<VoiceTouchEngine *>(data);
+       if (engine == nullptr) {
+               _E("[VoiceTouchEngine] Timer data is invalid");
+               return ECORE_CALLBACK_CANCEL;
+       }
+
+       int timestamp = engine->getCurrentTimestamp();
+
+       JsonProvider provider;
+       provider.setInputEvent(MMI_KEY_VOICE_TOUCH);
+
+       ClickableItem *command = engine->findCommand();
+       engine->makeClickedItemResult(command, timestamp, provider);
+       engine->invokeOutputResultCallback(provider.jsonToString());
+
+       if (command != nullptr) {
+               _I("[VoiceTouchEngine] Command. object ID(%s)", command->objectId.c_str());
+               engine->makeTouchModality(*command, timestamp);
+               engine->invokeOutputModalityCallback(&engine->__touchModality);
+       }
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+ClickableItem * VoiceTouchEngine::findCommand()
+{
+       bool isIndex = (__currentMode != VOICE_TOUCH_MODE_TOOLTIP_TEXT);
+       return __commandManager.findCommand(__asrResult, isIndex);
+}
+
+void VoiceTouchEngine::makeClickedItemResult(ClickableItem* command, int timestamp, JsonProvider &provider)
+{
+       if (command == nullptr) {
+               _I("[VoiceTouchEngine] Fail to find command");
+               setRejectedEventResult(timestamp, provider);
+       } else {
+               _I("[VoiceTouchEngine] Command. object ID(%s)", command->objectId.c_str());
+               setSelectedItemResult(*command, timestamp, provider);
+       }
+}
+
+bool VoiceTouchEngine::checkVoiceTouchMode(const std::string &text)
+{
+       _I("[VoiceTouchEngine] Input text(%s)", text.c_str());
+
+       string loweredText = StringUtil::makeLowerCase(text);
+       voice_touch_mode_e mode = __currentMode;
+       if (0 == loweredText.compare(__SHOW_TOOLTIP_INVOCATION)) {
+               mode = VOICE_TOUCH_MODE_TOOLTIP_TEXT;
+       } else if (0 == loweredText.compare(__SHOW_NUMBER_INVOCATION)) {
+               mode = VOICE_TOUCH_MODE_TOOLTIP_NUMBER;
+       } else if (0 == loweredText.compare(__SHOW_GRID_INVOCATION)) {
+               mode = VOICE_TOUCH_MODE_GRID;
+       }
+
+       if (__currentMode != mode) {
+               _I("[VoiceTouchEngine] mode is changed from (%d) to (%d)", __currentMode, mode);
+               __currentMode = mode;
+               return true;
+       }
+
+       _I("[VoiceTouchEngine] Mode is not changed");
+       return false;
+}
+
+void VoiceTouchEngine::resetCurrentGridInfo()
+{
+       __currentGridInfo.currentStep = 0;
+       __currentGridInfo.coordX = 0;
+       __currentGridInfo.coordY = 0;
+       __currentGridInfo.width = __displayWidth;
+       __currentGridInfo.height = __displayHeight;
+}
+
+void VoiceTouchEngine::makeClickableItemInfo(int timestamp, JsonProvider &provider)
+{
+       _I("[VoiceTouchEngine] Make clickable object list output. timestamp(%d), Current mode(%d)", timestamp, __currentMode);
+
+       list<ClickableItem> *itemList = nullptr;
+       const char *resultType = nullptr;
+       const char *tooltipType = nullptr;
+
+       switch (__currentMode)
+       {
+       case VOICE_TOUCH_MODE_GRID:
+               makeGridItemList(__currentGridInfo, __gridList);
+               itemList = &__gridList;
+               resultType = MMI_KEY_SHOW_GRIDS;
+               tooltipType = MMI_KEY_TOOLTIP_TYPE_NUMBER;
+               break;
+
+       case VOICE_TOUCH_MODE_TOOLTIP_NUMBER:
+               itemList = &__itemList;
+               resultType = MMI_KEY_SHOW_TOOLTIPS;
+               tooltipType = MMI_KEY_TOOLTIP_TYPE_NUMBER;
+               break;
+
+       case VOICE_TOUCH_MODE_TOOLTIP_TEXT:
+               itemList = &__itemList;
+               resultType = MMI_KEY_SHOW_TOOLTIPS;
+               tooltipType = MMI_KEY_TOOLTIP_TYPE_TEXT;
+               break;
+
+       default:
+               _E("[VoiceTouchEngine] Invalid mode classfier. Update item as lable tooltip.");
+               itemList = &__itemList;
+               resultType = MMI_KEY_SHOW_TOOLTIPS;
+               tooltipType = MMI_KEY_TOOLTIP_TYPE_TEXT;
+               break;
+       }
+
+       if (itemList == nullptr || itemList->size() == 0) {
+               _I("[VoiceTouchEngine] There is no item in the list.");
+               provider.setOutputEvent(MMI_KEY_ERROR);
+               provider.setErrorEvent(MMI_REASON_NO_CLICKABLE_OBJECTS, timestamp);
+               return;
+       }
+
+       provider.setOutputEvent(MMI_KEY_UI_CLICKABLE_OBJECT);
+       provider.setUiClickableObject(resultType, __appId.c_str(), tooltipType, __itemList.size(), timestamp);
+
+       for (auto item : *itemList) {
+               provider.addInfoClickableObject(item.index, item.coordX, item.coordY, item.width, item.height, item.label.c_str());
+       }
+}
+
+void VoiceTouchEngine::makeTouchModality(const ClickableItem &item, int timestamp)
+{
+       _I("[VoiceTouchEngine] Make clicked object output. timestamp(%d). item(%s)", timestamp, item.objectId.c_str());
+       if (__currentMode != VOICE_TOUCH_MODE_GRID) {
+               _D("[VoiceTouchEngine] Not grid mode.");
+               setTouchModality(item, timestamp);
+               return;
+       }
+
+       if (__currentGridInfo.currentStep == 0) {
+               __currentGridInfo.currentStep++;
+               __currentGridInfo.coordX = item.coordX;
+               __currentGridInfo.coordY = item.coordY;
+               __currentGridInfo.width = item.width;
+               __currentGridInfo.height = item.height;
+               return;
+       }
+
+       resetCurrentGridInfo();
+       setTouchModality(item, timestamp);
+}
+
+void VoiceTouchEngine::setRejectedEventResult(int timestamp, JsonProvider &provider)
+{
+       _I("[VoiceTouchEngine] Set command rejected event into output. timestamp(%d)", timestamp);
+
+       provider.setOutputEvent(MMI_KEY_REJECT);
+       provider.setRejectEvent(MMI_REASON_NO_MATCHED_COMMANDS, timestamp);
+}
+
+void VoiceTouchEngine::setSelectedItemResult(const ClickableItem &item, int timestamp, JsonProvider &provider)
+{
+       _I("[VoiceTouchEngine] Set clicked object information into output. timestamp(%d). item(%s)", timestamp, item.objectId.c_str());
+
+       provider.setOutputEvent(MMI_KEY_UI_CLICKED_OBJECT);
+       provider.setUiClickedObject(__appId.c_str(), timestamp, item.index, item.coordX, item.coordY, item.width, item.height, item.label.c_str());
+}
+
+void VoiceTouchEngine::makeGridItemList(const grid_info_s &parentInfo, std::list<ClickableItem> &list)
+{
+       _I("[VoiceTouchEngine] Set grid information into item list. Grid Step(%d)", parentInfo.currentStep);
+       _D("[VoiceTouchEngine] Parent info. X(%d), Y(%d), W(%d), H(%d)", parentInfo.coordX, parentInfo.coordY, parentInfo.width, parentInfo.height);
+
+       int currentStep = parentInfo.currentStep;
+       if (currentStep >= __MAXIMUM_GRID_STEP) {
+               return;
+       }
+
+       int numX = __gridX[currentStep];
+       int numY = __gridY[currentStep];
+       int coordX = parentInfo.coordX;
+       int coordY = parentInfo.coordY;
+       int gridWidth = parentInfo.width / numX;
+       int gridHeight = parentInfo.height / numY;
+
+       int index = 1;
+
+       list.clear();
+       for (int x = 0; x < numX; x++) {
+               for (int y = 0; y < numY; y++) {
+                       ClickableItem grid;
+                       grid.coordX = coordX + (x * gridWidth);
+                       grid.coordY = coordY + (y * gridHeight);
+                       grid.width = gridWidth;
+                       grid.height = gridHeight;
+                       grid.index = index++;
+
+                       list.push_back(grid);
+               }
+       }
+}
+
+void VoiceTouchEngine::setTouchModality(const ClickableItem &item, int timestamp)
+{
+       __touchModality.timestamp = timestamp;
+       __touchModality.mode = (__currentMode == VOICE_TOUCH_MODE_GRID ? MMI_VOICE_TOUCH_MODE_GRID : MMI_VOICE_TOUCH_MODE_TOOLTIP);
+       __touchModality.object_id = item.objectId.c_str();
+       __touchModality.coord_x = item.coordX + (item.width / 2);
+       __touchModality.coord_y = item.coordY + (item.height / 2);
+}
+
+bool VoiceTouchEngine::handleScreenAnalyzerInput(mmi_provider_event_screen_analyzer *screenAnalyzerEvent)
+{
+       _I("[VoiceTouchEngine] Screen analyzer modality");
+       if (screenAnalyzerEvent == nullptr) {
+               _E("[VoiceTouchEngine] Parameter is null");
+               return false;
+       }
+
+       _I("[VoiceTouchEngine] Input data. num of items(%d)", screenAnalyzerEvent->n_items);
+
+       int timestamp = getCurrentTimestamp();
+
+       JsonProvider provider;
+       provider.setInputEvent(MMI_KEY_VOICE_TOUCH);
+
+       __commandManager.cleanCommands();
+       __itemList.clear();
+       g_list_foreach(screenAnalyzerEvent->list, iterateObjectCallback, static_cast<gpointer>(this));
+
+       makeClickableItemInfo(timestamp, provider);
+       return true;
+}
+
+void VoiceTouchEngine::iterateObjectCallback(gpointer data, gpointer userData)
+{
+       clickable_item* info = static_cast<clickable_item*>(data);
+       VoiceTouchEngine *engine = static_cast<VoiceTouchEngine*>(userData);
+
+       ClickableItem item;
+       item.coordX = info->coord_x;
+       item.coordX = info->coord_y;
+       item.width = info->width;
+       item.height = info->height;
+       item.objectId = string(info->object_id);
+       item.label = string(info->label);
+       item.index = engine->__itemList.size() + 1;
+
+       engine->__itemList.push_back(item);
+       engine->__commandManager.addCommand(item);
+}
+
+void VoiceTouchEngine::invokeOutputResultCallback(std::string outputResult)
+{
+       if (__outputResultCallback == nullptr) {
+               return;
+       }
+
+       __outputResultCallback(__appId.c_str(), outputResult.c_str(), __outputResultUserData);
+}
+
+void VoiceTouchEngine::invokeOutputModalityCallback(void* outputModality)
+{
+       if (__outputModalityCallback == nullptr) {
+               return;
+       }
+
+       __outputModalityCallback(__appId.c_str(), outputModality, __outputModalityUserData);
+}
+
+void VoiceTouchEngine::setOutputResultCallback(voice_touch_engine_output_result_cb callback, void *userData)
+{
+       __outputResultCallback = callback;
+       __outputResultUserData = userData;
+}
+
+void VoiceTouchEngine::setOutputModalityCallback(voice_touch_engine_output_modality_cb callback, void *userData)
+{
+       __outputModalityCallback = callback;
+       __outputModalityUserData = userData;
+}
diff --git a/src/mmimgr/iu/VoiceTouchEngine.h b/src/mmimgr/iu/VoiceTouchEngine.h
new file mode 100644 (file)
index 0000000..02595c0
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ *
+ */
+
+
+#ifndef __VOICE_TOUCH_ENGINE_H__
+#define __VOICE_TOUCH_ENGINE_H__
+
+
+#include <string>
+#include <list>
+
+#include <Ecore.h>
+
+#include "CommandManager.h"
+#include "json_provider.h"
+#include "mmi-common.h"
+
+
+struct grid_info_s {
+       int currentStep;
+       int coordX;
+       int coordY;
+       int width;
+       int height;
+};
+
+enum voice_touch_mode_e {
+       VOICE_TOUCH_MODE_TOOLTIP_TEXT,
+       VOICE_TOUCH_MODE_TOOLTIP_NUMBER,
+       VOICE_TOUCH_MODE_GRID
+};
+
+enum voice_result_type_e {
+       VOICE_RESULT_TYPE_FINAL = 0,
+       VOICE_RESULT_TYPE_PARTIAL
+};
+
+typedef void (*voice_touch_engine_output_result_cb)(const char* app_id, const char* output_result, void *user_data);
+
+typedef void (*voice_touch_engine_output_modality_cb)(const char* app_id, void* output_modality, void *user_data);
+
+
+class VoiceTouchEngine {
+public:
+       VoiceTouchEngine();
+       ~VoiceTouchEngine();
+
+       void setDisplayInfo(int width, int height);
+       void setGridConfig(int numX, int numY, int step);
+
+       bool setInputModalityData(std::string appId, int modalityType, void *data);
+       void setOutputResultCallback(voice_touch_engine_output_result_cb callback, void *userData);
+       void setOutputModalityCallback(voice_touch_engine_output_modality_cb callback, void *userData);
+
+private:
+       static void iterateObjectCallback(gpointer data, gpointer userData);
+
+       static Eina_Bool findCommandCallback(void *data);
+       static Eina_Bool makeClickableItemResultCallback(void *data);
+
+private:
+       long getCurrentTimestamp();
+
+       bool handleVoiceInput(mmi_provider_event_voice *voiceEvent);
+       bool handleScreenAnalyzerInput(mmi_provider_event_screen_analyzer *screenAnalyzerEvent);
+
+       bool checkVoiceTouchMode(const std::string &text);
+       ClickableItem * findCommand();
+
+       void makeClickedItemResult(ClickableItem* command, int timestamp, JsonProvider &provider);
+       void makeClickableItemInfo(int timestamp, JsonProvider &provider);
+
+       void setPartialAsrResult(const std::string &result, int timestamp, JsonProvider &provider);
+       void setFinalAsrResult(const std::string &result, int timestamp, JsonProvider &provider);
+       void setSelectedItemResult(const ClickableItem &item, int timestamp, JsonProvider &provider);
+       void setRejectedEventResult(int timestamp, JsonProvider &provider);
+       void makeGridItemList(const grid_info_s &parentInfo, std::list<ClickableItem> &list);
+
+       void makeTouchModality(const ClickableItem &item, int timestamp);
+       void setTouchModality(const ClickableItem &item, int timestamp);
+
+       void resetCurrentGridInfo();
+
+       void invokeOutputResultCallback(std::string outputResult);
+       void invokeOutputModalityCallback(void* outputModality);
+
+private:
+       static const int __MAXIMUM_GRID_STEP = 2;
+
+       int __displayWidth;
+       int __displayHeight;
+
+       int __gridX[__MAXIMUM_GRID_STEP];
+       int __gridY[__MAXIMUM_GRID_STEP];
+
+       std::string __appId;
+
+       CommandManager __commandManager;
+       std::list<ClickableItem> __itemList;
+       std::list<ClickableItem> __gridList;
+
+       voice_touch_mode_e __currentMode;
+       grid_info_s __currentGridInfo;
+       std::string __asrResult;
+
+       mmi_output_modality_voice_touch __touchModality;
+
+       voice_touch_engine_output_result_cb __outputResultCallback;
+       void *__outputResultUserData;
+       voice_touch_engine_output_modality_cb __outputModalityCallback;
+       void *__outputModalityUserData;
+
+       Ecore_Timer *__findCommandTimer;
+       Ecore_Timer *__makeClickableItemResultTimer;
+};
+
+#endif /* __VOICE_TOUCH_ENGINE_H__ */
index 769fe07..b8d580e 100644 (file)
@@ -1,24 +1,18 @@
 /*
- * Copyright © 2021 Samsung Electronics co., Ltd. All Rights Reserved.
+ * Copyright (c) 2022 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:
+ *  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
  *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
+ *               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.
  *
- * 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>
@@ -31,6 +25,7 @@
 #include "output_intent.h"
 #include "input_intent.h"
 #include "intent_understanding_engine.h"
+#include "VoiceTouchEngine.h"
 #include "mmi-common.h"
 
 using namespace std;
@@ -48,6 +43,7 @@ static string g_system_app_id;
 static string g_focus_app_id;
 
 static IntentUnderstandingEngine *iu_engine = NULL;
+static VoiceTouchEngine *g_VoiceTouchEngine = nullptr;
 
 #define DEFAULT_RULE_FILE "/usr/share/iu/default_rule.json"
 
@@ -67,14 +63,32 @@ static void init()
     g_focus_app_id = "";
 }
 
+void __mmi_iu_voice_touch_engine_output_result_cb(const char* app_id, const char* output_result, void *user_data)
+{
+    // TODO: implement
+}
+
+void __mmi_iu_voice_touch_engine_output_modality_cb(const char* app_id, void* output_modality, void *user_data)
+{
+    // TODO: implement
+}
+
 EXPORT_API int mmi_iu_init()
 {
     init();
 
-    iu_engine = new IntentUnderstandingEngine();
-
-    if (!iu_engine)
+    try {
+        iu_engine = new IntentUnderstandingEngine();
+        g_VoiceTouchEngine = new VoiceTouchEngine();
+    } catch (exception &e) {
+        _E("[MMI IU] Fail to allocate memory. (%s)", e.what());
         return MMI_IU_ERROR_OUT_OF_MEMORY;
+    }
+
+    if (g_VoiceTouchEngine) {
+        g_VoiceTouchEngine->setOutputResultCallback(__mmi_iu_voice_touch_engine_output_result_cb, nullptr);
+        g_VoiceTouchEngine->setOutputModalityCallback(__mmi_iu_voice_touch_engine_output_modality_cb, nullptr);
+    }
 
     int ret = mmi_iu_set_rule_filepath(DEFAULT_RULE_FILE);
 
@@ -90,6 +104,9 @@ EXPORT_API int mmi_iu_shutdown()
         iu_engine = NULL;
     }
 
+    delete g_VoiceTouchEngine;
+    g_VoiceTouchEngine = nullptr;
+
     if (!initialized)
         return MMI_IU_ERROR_NOT_INITIALIZED;
 
@@ -100,14 +117,6 @@ EXPORT_API int mmi_iu_shutdown()
 
 EXPORT_API int mmi_iu_set_rule_filepath(const char *filepath)
 {
-    if (!initialized || !iu_engine)
-        return MMI_IU_ERROR_NOT_INITIALIZED;
-
-    if (!iu_engine->set_rule_json_file(filepath)) {
-        _W("Failed to set rule data");
-        return MMI_IU_ERROR_OPERATION_FAILED;
-    }
-
     return MMI_IU_ERROR_NONE;
 }
 
@@ -123,20 +132,20 @@ static void fire_output_result(const char *app_id, const char *json_output_inten
 {
     if (g_system_app_id == string(app_id)) {
         fire_output_result_callback(app_id, json_output_intent);
+        return;
     }
-    else {
-        if (g_focus_app_id.empty()) {
-            fire_output_result_callback(app_id, json_output_intent);
-        }
-        else {
-            if (g_focus_app_id == string(app_id)) {
-                fire_output_result_callback(app_id, json_output_intent);
-            }
-            else {
-                _I("different focus app\n");
-            }
-        }
+
+    if (g_focus_app_id.empty()) {
+        fire_output_result_callback(app_id, json_output_intent);
+        return;
     }
+
+    if (g_focus_app_id == string(app_id)) {
+        fire_output_result_callback(app_id, json_output_intent);
+        return;
+    }
+
+    _I("different focus app\n");
 }
 
 EXPORT_API int mmi_iu_feed_intent(const char *app_id, const char *json_data)
@@ -151,25 +160,6 @@ EXPORT_API int mmi_iu_feed_intent(const char *app_id, const char *json_data)
         return MMI_IU_ERROR_NOT_INITIALIZED;
     }
 
-    if (iu_engine)
-        if (!iu_engine->set_input_intent_json_data(json_data))
-            return MMI_IU_ERROR_OPERATION_FAILED;
-
-    _I("app state: %d\n", g_app_state);
-
-    string json_output_intent;
-    if (iu_engine) {
-        iu_engine->set_app_state(g_app_state);
-
-        json_output_intent = iu_engine->get_output_intent_json_data();
-        _I("output intent : %s\n", json_output_intent.c_str());
-    }
-
-    if (json_output_intent.empty())
-        return MMI_IU_ERROR_OPERATION_FAILED;
-
-    fire_output_result(app_id, json_output_intent.c_str());
-
     return MMI_IU_ERROR_NONE;
 }
 
@@ -185,39 +175,14 @@ EXPORT_API int mmi_iu_feed_input_modality(const char *app_id, int type, void *ev
         return MMI_IU_ERROR_NOT_INITIALIZED;
     }
 
-    if (iu_engine) {
-        if (!iu_engine->set_input_event(type, event)) {
-            if (iu_output_modality_received_callback) {
-                iu_output_modality_received_callback(app_id, type, event, iu_output_modality_user_data);
-                return MMI_IU_ERROR_NONE;
-            }
-        }
+    string json_output_result;
+    if (g_VoiceTouchEngine) {
+        g_VoiceTouchEngine->setInputModalityData(app_id, type, event);
     }
 
     _I("app state: %d\n", g_app_state);
 
-    string json_output_intent;
-    if (iu_engine) {
-        iu_engine->set_app_state(g_app_state);
-
-        if (iu_engine->get_output_intent_action().empty()) {
-            if (iu_output_modality_received_callback) {
-                iu_output_modality_received_callback(app_id, type, event, iu_output_modality_user_data);
-                return MMI_IU_ERROR_NONE;
-            }
-        }
-
-        json_output_intent = iu_engine->get_output_intent_json_data();
-        _I("output intent : %s\n", json_output_intent.c_str());
-    }
-
-    if (json_output_intent.empty())
-        return MMI_IU_ERROR_OPERATION_FAILED;
-
-    fire_output_result(app_id, json_output_intent.c_str());
-
-    if (iu_engine)
-        iu_engine->init_input_buffer();
+    fire_output_result(app_id, json_output_result.c_str());
 
     return MMI_IU_ERROR_NONE;
 }
index 2772a55..05da294 100644 (file)
@@ -31,6 +31,8 @@ mmimgr_srcs = [
        'iu/StringUtil.h',
        'iu/CommandManager.cpp',
        'iu/CommandManager.h',
+       'iu/VoiceTouchEngine.cpp',
+       'iu/VoiceTouchEngine.h',
        'iu/json_provider.cpp',
        'iu/json_provider.h',
        'output_modality/mmi_output_modality.cpp',