2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "humanactivitymonitor/gesture_manager.h"
19 #include <gesture_recognition.h>
21 #include "common/extension.h"
22 #include "common/logger.h"
23 #include "common/optional.h"
24 #include "common/picojson.h"
25 #include "common/scope_exit.h"
26 #include "common/tools.h"
29 namespace humanactivitymonitor {
31 using common::PlatformResult;
32 using common::ErrorCode;
33 using common::tools::ReportError;
34 using common::tools::ReportSuccess;
38 const std::string kListenerId = "listenerId";
39 const std::string kListener = "GestureRecognitionListener";
40 const std::string kType = "type";
41 const std::string kTimestamp = "timestamp";
42 const std::string kAlwayOn = "alwaysOn";
43 const std::string kAction = "action";
44 const std::string kEvent = "event";
45 const std::string kError = "error";
46 const std::string kOnError = "onerror";
47 const std::string kOnDetect = "ondetect";
49 ErrorCode getErrorCode(int error) {
51 case GESTURE_ERROR_NONE:
52 return ErrorCode::NO_ERROR;
53 case GESTURE_ERROR_INVALID_PARAMETER:
54 return ErrorCode::INVALID_VALUES_ERR;
55 case GESTURE_ERROR_OPERATION_FAILED:
56 return ErrorCode::IO_ERR;
57 case GESTURE_ERROR_NOT_SUPPORTED:
58 return ErrorCode::NOT_SUPPORTED_ERR;
59 case GESTURE_ERROR_INVALID_OPERATION:
60 case GESTURE_ERROR_OUT_OF_MEMORY:
61 case GESTURE_ERROR_PERMISSION_DENIED:
62 case GESTURE_ERROR_ALREADY_STARTED:
63 case GESTURE_ERROR_NOT_STARTED:
65 return ErrorCode::ABORT_ERR;
69 PlatformResult StrToGestureType(const std::string& type, gesture_type_e* type_e) {
70 if ("GESTURE_DOUBLE_TAP" == type) {
71 *type_e = GESTURE_DOUBLE_TAP;
72 } else if ("GESTURE_MOVE_TO_EAR" == type) {
73 *type_e = GESTURE_MOVE_TO_EAR;
74 } else if ("GESTURE_NO_MOVE" == type) {
75 *type_e = GESTURE_NO_MOVE;
76 } else if ("GESTURE_PICK_UP" == type) {
77 *type_e = GESTURE_PICK_UP;
78 } else if ("GESTURE_SHAKE" == type) {
79 *type_e = GESTURE_SHAKE;
80 } else if ("GESTURE_SNAP" == type) {
81 *type_e = GESTURE_SNAP;
82 } else if ("GESTURE_TILT" == type) {
83 *type_e = GESTURE_TILT;
84 } else if ("GESTURE_TURN_FACE_DOWN" == type) {
85 *type_e = GESTURE_TURN_FACE_DOWN;
86 } else if ("GESTURE_WRIST_UP" == type) {
87 *type_e = GESTURE_WRIST_UP;
89 return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unknown gesture type");
92 return PlatformResult(ErrorCode::NO_ERROR);
95 std::string GestureTypeToStr(gesture_type_e type) {
97 case GESTURE_DOUBLE_TAP:
98 return "GESTURE_DOUBLE_TAP";
99 case GESTURE_MOVE_TO_EAR:
100 return "GESTURE_MOVE_TO_EAR";
101 case GESTURE_NO_MOVE:
102 return "GESTURE_NO_MOVE";
103 case GESTURE_PICK_UP:
104 return "GESTURE_PICK_UP";
106 return "GESTURE_SHAKE";
108 return "GESTURE_SNAP";
110 return "GESTURE_TILT";
111 case GESTURE_TURN_FACE_DOWN:
112 return "GESTURE_TURN_FACE_DOWN";
113 case GESTURE_WRIST_UP:
114 return "GESTURE_WRIST_UP";
116 return "GESTURE_UNKNOWN_TYPE";
119 std::string GestureEventToStr(gesture_event_e event, gesture_type_e gesture) {
121 // GESTURE_EVENT_DETECTED == GESTURE_SHAKE_DETECTED == GESTURE_SNAP_X_NEGATIVE == 1
122 case GESTURE_EVENT_DETECTED:
123 if (GESTURE_SHAKE == gesture) {
124 return "GESTURE_SHAKE_DETECTED";
125 } else if (GESTURE_SNAP == gesture) {
126 return "GESTURE_SNAP_X_NEGATIVE";
128 return "GESTURE_EVENT_DETECTED";
130 // GESTURE_SHAKE_FINISHED == GESTURE_SNAP_X_POSITIVE == 2
131 case GESTURE_SHAKE_FINISHED:
132 if (GESTURE_SHAKE == gesture) {
133 return "GESTURE_SHAKE_FINISHED";
135 return "GESTURE_SNAP_X_POSITIVE";
137 case GESTURE_SNAP_Y_NEGATIVE:
138 return "GESTURE_SNAP_Y_NEGATIVE";
139 case GESTURE_SNAP_Y_POSITIVE:
140 return "GESTURE_SNAP_Y_POSITIVE";
141 case GESTURE_SNAP_Z_NEGATIVE:
142 return "GESTURE_SNAP_Z_NEGATIVE";
143 case GESTURE_SNAP_Z_POSITIVE:
144 return "GESTURE_SNAP_Z_POSITIVE";
146 return "GESTURE_EVENT_NONE";
150 void GestureRecognitionDefaultCb(gesture_type_e gesture, const gesture_data_h data,
151 double timestamp, gesture_error_e error, void* user_data) {
154 GestureManager* manager = static_cast<GestureManager*>(user_data);
156 LoggerW("User data is null");
160 manager->CompleteGestureListenerCb(gesture, data, timestamp, error, false);
163 void GestureRecognitionAlwaysOnCb(gesture_type_e gesture, const gesture_data_h data,
164 double timestamp, gesture_error_e error, void* user_data) {
166 GestureManager* manager = static_cast<GestureManager*>(user_data);
169 LoggerW("User data is null");
173 manager->CompleteGestureListenerCb(gesture, data, timestamp, error, true);
178 GestureManager::GestureManager()
179 : m_callback(nullptr), m_recognition_default_map(), m_recognition_always_on_map() {
183 GestureManager::~GestureManager() {
186 int ret = GESTURE_ERROR_NONE;
188 for (auto& it : m_recognition_default_map) {
189 ret = gesture_stop_recognition(it.second);
190 if (GESTURE_ERROR_NONE != ret) {
191 LoggerE("gesture_stop_recognition() failed");
194 ret = gesture_release(it.second);
195 if (GESTURE_ERROR_NONE != ret) {
196 LoggerE("gesture_release() failed");
200 for (auto& it : m_recognition_always_on_map) {
201 ret = gesture_stop_recognition(it.second);
202 if (GESTURE_ERROR_NONE != ret) {
203 LoggerE("gesture_stop_recognition() failed");
206 ret = gesture_release(it.second);
207 if (GESTURE_ERROR_NONE != ret) {
208 LoggerE("gesture_release() failed");
212 m_recognition_default_map.clear();
213 m_recognition_always_on_map.clear();
216 PlatformResult GestureManager::IsSupported(const std::string& type, bool* is_supported) {
219 gesture_type_e type_e = GESTURE_DOUBLE_TAP;
220 PlatformResult result = StrToGestureType(type, &type_e);
225 int ret = gesture_is_supported(type_e, is_supported);
226 if (GESTURE_ERROR_NONE != ret) {
227 return LogAndCreateResult(
228 getErrorCode(ret), "Checking gesture failed",
229 ("Checking gesture failed, error: %d (%s)", ret, get_error_message(ret)));
232 return PlatformResult(ErrorCode::NO_ERROR);
235 gesture_event_e GestureManager::GetGestureEvent(const gesture_data_h data) {
238 gesture_event_e event = GESTURE_EVENT_NONE;
239 int ret = gesture_get_event(data, &event);
240 if (GESTURE_ERROR_NONE != ret) {
241 LoggerE("gesture_get_event() failed, error %d (%s)", ret, get_error_message(ret));
247 void GestureManager::FillTiltData(const gesture_data_h data, picojson::object* obj) {
253 int ret = gesture_get_tilt(data, &x, &y);
254 if (GESTURE_ERROR_NONE != ret) {
255 LoggerE("gesture_get_tilt() failed, error %d (%s)", ret, get_error_message(ret));
258 obj->insert(std::make_pair("x", picojson::value(static_cast<double>(x))));
259 obj->insert(std::make_pair("y", picojson::value(static_cast<double>(y))));
262 void GestureManager::CompleteGestureListenerCb(gesture_type_e gesture, const gesture_data_h data,
263 double timestamp, gesture_error_e error,
267 picojson::value response = picojson::value(picojson::object());
268 auto& obj = response.get<picojson::object>();
270 obj.insert(std::make_pair(kAlwayOn, picojson::value(always_on)));
271 obj.insert(std::make_pair(kListenerId, picojson::value(kListener)));
273 if (GESTURE_ERROR_NONE != error) {
274 obj.insert(std::make_pair(kAction, picojson::value(kOnError)));
276 PlatformResult result =
277 LogAndCreateResult(getErrorCode(error), "Error occurred during recognition");
278 ReportError(result, &obj);
280 gesture_event_e event = GetGestureEvent(data);
281 if (GESTURE_EVENT_NONE == event) {
282 LoggerD("Gesture event none detected.");
286 std::string gesture_str = GestureTypeToStr(gesture);
287 if ("GESTURE_UNKNOWN_TYPE" == gesture_str) {
288 LoggerE("Unknown gesture type");
292 obj.insert(std::make_pair(kAction, picojson::value(kOnDetect)));
294 picojson::value result = picojson::value(picojson::object());
295 auto& result_obj = result.get<picojson::object>();
297 result_obj.insert(std::make_pair(kEvent, picojson::value(GestureEventToStr(event, gesture))));
298 result_obj.insert(std::make_pair(kTimestamp, picojson::value(timestamp)));
299 result_obj.insert(std::make_pair(kType, picojson::value(gesture_str)));
301 if (GESTURE_TILT == gesture) {
302 FillTiltData(data, &result_obj);
305 ReportSuccess(result, obj);
309 LoggerE("Callback is not defined");
311 m_callback(&response);
315 PlatformResult GestureManager::AddListener(gesture_type_e type, gesture_option_e option,
316 RecognitionMap& gesture_map,
317 gesture_recognition_cb callback) {
320 gesture_h handle = nullptr;
322 int ret = gesture_create(&handle);
323 if (GESTURE_ERROR_NONE != ret) {
324 return LogAndCreateResult(
325 getErrorCode(ret), "Creating handle failed",
326 ("Creating handle failed, error: %d (%s)", ret, get_error_message(ret)));
329 ret = gesture_start_recognition(handle, type, option, callback, this);
330 if (GESTURE_ERROR_NONE != ret) {
331 gesture_release(handle);
332 return LogAndCreateResult(
333 getErrorCode(ret), "Starting recognition failed",
334 ("Starting recognition failed, error: %d (%s)", ret, get_error_message(ret)));
337 gesture_map[type] = handle;
339 return PlatformResult(ErrorCode::NO_ERROR);
342 PlatformResult GestureManager::AddGestureRecognitionListener(const std::string& type,
343 bool always_on, JsonCallback cb) {
346 gesture_type_e type_e = GESTURE_DOUBLE_TAP;
347 PlatformResult result = StrToGestureType(type, &type_e);
352 gesture_option_e option = GESTURE_OPTION_DEFAULT;
353 gesture_recognition_cb callback = GestureRecognitionDefaultCb;
354 RecognitionMap* gesture_map = &m_recognition_default_map;
361 option = GESTURE_OPTION_ALWAYS_ON;
362 callback = GestureRecognitionAlwaysOnCb;
363 gesture_map = &m_recognition_always_on_map;
366 return AddListener(type_e, option, *gesture_map, callback);
369 PlatformResult GestureManager::RemoveGestureRecognitionListener(const std::string& type,
373 auto& recognition_map = always_on ? m_recognition_always_on_map : m_recognition_default_map;
374 gesture_type_e type_e = GESTURE_DOUBLE_TAP;
375 PlatformResult result = StrToGestureType(type, &type_e);
377 LoggerD("Unknown gesture type.");
378 return PlatformResult(ErrorCode::NO_ERROR);
381 gesture_h handle = nullptr;
382 RecognitionMap::iterator it = recognition_map.find(type_e);
384 if (recognition_map.end() != it) {
389 int ret = gesture_stop_recognition(handle);
390 if (GESTURE_ERROR_NONE != ret) {
391 return LogAndCreateResult(
392 getErrorCode(ret), "Stoping recognition failed",
393 ("Stoping recognition failed, error: %d (%s)", ret, get_error_message(ret)));
396 ret = gesture_release(handle);
397 if (GESTURE_ERROR_NONE != ret) {
398 LoggerE("gesture_release() failed");
401 recognition_map.erase(it);
404 return PlatformResult(ErrorCode::NO_ERROR);
407 } // namespace humanactivitymonitor
408 } // namespace extension