Refactor media key 69/225969/4
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 26 Feb 2020 03:08:35 +0000 (12:08 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 27 Feb 2020 01:11:22 +0000 (10:11 +0900)
Change-Id: If0f86f8347852cf93fa4bf854b20c35504d91fd6
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
CMakeLists.txt
packaging/capi-system-media-key.spec
src/log_private.hh [new file with mode: 0644]
src/media_key.c [deleted file]
src/media_key.cc [new file with mode: 0644]

index 9f16917..37a99b5 100644 (file)
@@ -1,96 +1,42 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(capi-system-media-key CXX)
 
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-SET(fw_name "capi-system-media-key")
-
-PROJECT(${fw_name})
-
-SET(CMAKE_INSTALL_PREFIX /usr)
-SET(PREFIX ${CMAKE_INSTALL_PREFIX})
-
-SET(INC_DIR include)
-INCLUDE_DIRECTORIES(${INC_DIR})
+INCLUDE(FindPkgConfig)
 
 SET(requires "dlog capi-base-common ecore ecore-input evas ecore-wl2")
 SET(pc_requires "capi-base-common")
 
-INCLUDE(FindPkgConfig)
-pkg_check_modules(${fw_name} REQUIRED ${requires})
-FOREACH(flag ${${fw_name}_CFLAGS})
-    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
-ENDFOREACH(flag)
-
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror")
-SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
-
-IF("${ARCH}" STREQUAL "arm")
-    ADD_DEFINITIONS("-DTARGET")
-ENDIF("${ARCH}" STREQUAL "arm")
+PKG_CHECK_MODULES(capi-system-media-key REQUIRED ${requires})
 
-ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
-ADD_DEFINITIONS("-DSLP_DEBUG")
+FOREACH(flag ${capi-system-media-key_CFLAGS})
+        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -Winline")
 
-SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++11")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
 
-aux_source_directory(src SOURCES)
-ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
 
-TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS})
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCES)
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SOURCES})
 
-SET_TARGET_PROPERTIES(${fw_name}
-     PROPERTIES
-     VERSION ${FULLVER}
-     SOVERSION ${MAJORVER}
-     CLEAN_DIRECT_OUTPUT 1
-)
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${FULLVER})
 
-INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR})
-INSTALL(
-        DIRECTORY ${INC_DIR}/ DESTINATION include/system
-        FILES_MATCHING
-        PATTERN "*_private.h" EXCLUDE
-        PATTERN "${INC_DIR}/*.h"
-        )
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${capi-system-media-key_LDFLAGS})
 
-SET(PC_NAME ${fw_name})
+SET(PC_NAME capi-system-media-key)
 SET(PC_REQUIRED ${pc_requires})
-SET(PC_LDFLAGS -l${fw_name})
+SET(PC_LDFLAGS -lcapi-system-media-key)
 SET(PC_CFLAGS -I\${includedir}/system)
 
-CONFIGURE_FILE(
-    ${fw_name}.pc.in
-    ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc
-    @ONLY
-)
-INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
-
-IF(UNIX)
-
-ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution)
-ADD_CUSTOM_COMMAND(
-        DEPENDS clean
-        COMMENT "distribution clean"
-        COMMAND find
-        ARGS    .
-        -not -name config.cmake -and \(
-        -name tester.c -or
-        -name Testing -or
-        -name CMakeFiles -or
-        -name cmake.depends -or
-        -name cmake.check_depends -or
-        -name CMakeCache.txt -or
-        -name cmake.check_cache -or
-        -name *.cmake -or
-        -name Makefile -or
-        -name core -or
-        -name core.* -or
-        -name gmon.out -or
-        -name install_manifest.txt -or
-        -name *.pc -or
-        -name *~ \)
-        | grep -v TC | xargs rm -rf
-        TARGET  distclean
-        VERBATIM
-)
-
-ENDIF(UNIX)
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc")
 
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
+        DESTINATION include/system
+        FILES_MATCHING PATTERN "*.h")
index 68f2d7e..5c156b0 100644 (file)
@@ -47,6 +47,7 @@ export LDFLAGS+=" -lgcov"
 %endif
 
 export CFLAGS+=" -DEFL_BETA_API_SUPPORT "
+export CXXFLAGS+=" -DEFL_BETA_API_SUPPORT "
 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 %cmake -DFULLVER=%{version} \
        -DMAJORVER=${MAJORVER} \
diff --git a/src/log_private.hh b/src/log_private.hh
new file mode 100644 (file)
index 0000000..cfc24fc
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020 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 LOG_PRIVATE_H_
+#define LOG_PRIVATE_H_
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "CAPI_SYSTEM_MEDIA_KEY"
+
+#ifdef _E
+#undef _E
+#endif
+#define _E LOGE
+
+#ifdef _W
+#undef _W
+#endif
+#define _W LOGW
+
+#ifdef _I
+#undef _I
+#endif
+#define _I LOGI
+
+#ifdef _D
+#undef _D
+#endif
+#define _D LOGD
+
+#endif  // LOG_PRIVATE_H_
diff --git a/src/media_key.c b/src/media_key.c
deleted file mode 100644 (file)
index 6a901da..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2011 - 2017 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 <unistd.h>
-#include <string.h>
-
-#include <Evas.h>
-#include <Ecore.h>
-#include <Ecore_Input.h>
-#include <Ecore_Wl2.h>
-
-#include <dlog.h>
-
-#include "media_key.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_SYSTEM_MEDIA_KEY"
-
-struct key_map {
-       char *key_str;
-       media_key_e key;
-};
-
-struct key_map media_keys[] = {
-       { "XF86AudioPlay", MEDIA_KEY_PLAY },
-       { "XF86AudioStop", MEDIA_KEY_STOP },
-       { "XF86AudioPause", MEDIA_KEY_PAUSE },
-       { "XF86AudioNext", MEDIA_KEY_NEXT },
-       { "XF86AudioPrev", MEDIA_KEY_PREVIOUS },
-       { "XF86AudioRewind", MEDIA_KEY_REWIND },
-       { "XF86AudioForward", MEDIA_KEY_FASTFORWARD },
-       { "XF86AudioPlayPause", MEDIA_KEY_PLAYPAUSE },
-       { "XF86AudioMedia", MEDIA_KEY_MEDIA },
-       { NULL, MEDIA_KEY_UNKNOWN },
-};
-
-static media_key_event_cb _media_key_event_cb;
-static void *_media_key_data;
-static int _media_key_initialized;
-
-static Ecore_Event_Handler *_media_key_up;
-static Ecore_Event_Handler *_media_key_down;
-
-static int _media_key_init(void)
-{
-       if (_media_key_initialized)
-               return 0;
-
-       ecore_wl2_init();
-       if (!ecore_wl2_display_connect(NULL)) {
-               LOGE("Failed to connect to wl2 display");
-               ecore_wl2_shutdown();
-               return -1;
-       }
-
-       _media_key_initialized = 1;
-
-       return 0;
-}
-
-static void _media_key_handler(const char *key_str, media_key_e event)
-{
-       int i;
-       media_key_e key = MEDIA_KEY_UNKNOWN;
-
-       for (i = 0; media_keys[i].key_str; i++) {
-               if (!strcmp(key_str, media_keys[i].key_str)) {
-                       key = media_keys[i].key;
-                       break;
-               }
-       }
-
-       if (_media_key_event_cb && key != MEDIA_KEY_UNKNOWN)
-               _media_key_event_cb(key, event, _media_key_data);
-}
-
-static Eina_Bool _media_key_press_cb(void *data, int type, void *event)
-{
-       Evas_Event_Key_Down *ev;
-
-       ev = event;
-       if (!ev) {
-               LOGE("Invalid event object");
-               return ECORE_CALLBACK_RENEW;
-       }
-
-       _media_key_handler(ev->keyname, MEDIA_KEY_STATUS_PRESSED);
-
-       return ECORE_CALLBACK_RENEW;
-}
-
-static Eina_Bool _media_key_release_cb(void *data, int type, void *event)
-{
-       Evas_Event_Key_Up *ev;
-
-       ev = event;
-       if (!ev) {
-               LOGE("Invalid event object");
-               return ECORE_CALLBACK_RENEW;
-       }
-
-       _media_key_handler(ev->keyname, MEDIA_KEY_STATUS_RELEASED);
-
-       return ECORE_CALLBACK_RENEW;
-}
-
-static int _grab_media_key(void)
-{
-       int i;
-       Eina_Bool ret;
-
-       for (i = 0; media_keys[i].key_str; i++) {
-               ret = ecore_wl2_window_keygrab_set(NULL, media_keys[i].key_str,
-                               0, 0, 0, ECORE_WL2_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE);
-               if (ret != EINA_TRUE) {
-                       LOGE("failed to grab key: %s", media_keys[i].key_str);
-                       for (i = i - 1; i >= 0; i--)
-                               ecore_wl2_window_keygrab_unset(NULL, media_keys[i].key_str, 0, 0);
-
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-static int _ungrab_media_key(void)
-{
-       int i;
-       Eina_Bool ret;
-
-       for (i = 0; media_keys[i].key_str; i++) {
-               ret = ecore_wl2_window_keygrab_unset(NULL, media_keys[i].key_str, 0, 0);
-               if (ret != EINA_TRUE)
-                       LOGE("failed to ungrab key: %s", media_keys[i].key_str);
-       }
-
-       return 0;
-}
-
-int media_key_reserve(media_key_event_cb callback, void *user_data)
-{
-       int ret;
-
-       LOGW("Reserve");
-       if (callback == NULL) {
-               LOGE("[%s] media_key_event_cb callback is NULL", __FUNCTION__);
-               return MEDIA_KEY_ERROR_INVALID_PARAMETER;
-       }
-
-       if (!_media_key_initialized) {
-               if (_media_key_init())
-                       return MEDIA_KEY_ERROR_OPERATION_FAILED;
-       }
-
-       _media_key_event_cb = callback;
-       _media_key_data = user_data;
-       if (_media_key_down) {
-               LOGI("ecore event andler already added, just update callback");
-               return MEDIA_KEY_ERROR_NONE;
-       }
-
-       ret = _grab_media_key();
-       if (ret) {
-               LOGE("reserve media key error [%d]", ret);
-               return MEDIA_KEY_ERROR_OPERATION_FAILED;
-       }
-
-       _media_key_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _media_key_press_cb, NULL);
-       if (!_media_key_down)
-               LOGE("failed to register key down event handler");
-
-       _media_key_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _media_key_release_cb, NULL);
-       if (!_media_key_up)
-               LOGE("failed to register key up event handler");
-
-       return MEDIA_KEY_ERROR_NONE;
-}
-
-int media_key_release(void)
-{
-       int ret;
-
-       LOGW("Release");
-       if (!_media_key_initialized) {
-               LOGI("media key is not reserved");
-               return MEDIA_KEY_ERROR_NONE;
-       }
-
-       if (_media_key_down) {
-               ecore_event_handler_del(_media_key_down);
-               _media_key_down = NULL;
-       }
-
-       if (_media_key_up) {
-               ecore_event_handler_del(_media_key_up);
-               _media_key_up = NULL;
-       }
-
-       ret = _ungrab_media_key();
-       if (ret) {
-               LOGE("release media key error [%d]", ret);
-               return MEDIA_KEY_ERROR_OPERATION_FAILED;
-       }
-
-       _media_key_event_cb = NULL;
-       _media_key_data = NULL;
-
-       return MEDIA_KEY_ERROR_NONE;
-}
diff --git a/src/media_key.cc b/src/media_key.cc
new file mode 100644 (file)
index 0000000..f2d11d5
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2020 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 <Ecore.h>
+#include <Ecore_Input.h>
+#include <Ecore_Wl2.h>
+#include <Evas.h>
+
+#include <map>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include "media_key.h"
+#include "log_private.hh"
+
+#ifdef EXPORT_API
+#undef EXPORT_API
+#endif
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace {
+
+class MediaKey {
+ private:
+  MediaKey() = default;
+  ~MediaKey() {
+    if (!disposed_)
+      Dispose();
+  }
+
+ public:
+  static MediaKey& GetInst() {
+    static MediaKey inst;
+
+    std::lock_guard<std::recursive_mutex> lock(inst.GetMutex());
+    if (inst.disposed_)
+      inst.Init();
+    return inst;
+  }
+
+  void Dispose() {
+    Fini();
+  }
+
+  int Reserve(media_key_event_cb cb, void* data) {
+    _W("Reserve");
+    std::lock_guard<std::recursive_mutex> lock(GetMutex());
+    cb_ = cb;
+    data_ = data;
+
+    int ret = MEDIA_KEY_ERROR_NONE;
+    if (!grabbed_)
+      ret = Grab();
+
+    return ret;
+  }
+
+  void Release() {
+    _W("Release");
+    std::lock_guard<std::recursive_mutex> lock(GetMutex());
+    if (grabbed_)
+      Ungrab();
+
+    cb_ = nullptr;
+    data_ = nullptr;
+  }
+
+ private:
+  void Init() {
+    key_map_ = {
+      { "XF86AudioPlay", MEDIA_KEY_PLAY },
+      { "XF86AudioStop", MEDIA_KEY_STOP },
+      { "XF86AudioPause", MEDIA_KEY_PAUSE },
+      { "XF86AudioNext", MEDIA_KEY_NEXT },
+      { "XF86AudioPrev", MEDIA_KEY_PREVIOUS },
+      { "XF86AudioRewind", MEDIA_KEY_REWIND },
+      { "XF86AudioForward", MEDIA_KEY_FASTFORWARD },
+      { "XF86AudioPlayPause", MEDIA_KEY_PLAYPAUSE },
+      { "XF86AudioMedia", MEDIA_KEY_MEDIA }
+    };
+
+    ecore_wl2_init();
+
+    if (!ecore_wl2_display_connect(NULL)) {
+      _E("Failed to connect to wl2 display");
+      ecore_wl2_shutdown();
+      return;
+    }
+
+    disposed_ = false;
+  }
+
+  void Fini() {
+    Ecore_Wl2_Display* dpy = ecore_wl2_connected_display_get(NULL);
+    if (dpy)
+      ecore_wl2_display_disconnect(dpy);
+
+    ecore_wl2_shutdown();
+    disposed_ = true;
+  }
+
+  int Grab() {
+    for (auto i = key_map_.begin(); i != key_map_.end(); i++) {
+      _D("key(%s)", i->first.c_str());
+      auto ret = ecore_wl2_window_keygrab_set(NULL, i->first.c_str(),
+          0, 0, 0, ECORE_WL2_WINDOW_KEYGRAB_OVERRIDE_EXCLUSIVE);
+      if (ret != EINA_TRUE) {
+        _E("Failed to grab key(%s)", i->first.c_str());
+        Ungrab();
+        return MEDIA_KEY_ERROR_OPERATION_FAILED;
+      }
+    }
+
+    key_down_handler_ = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
+        MediaKeyPressCb, this);
+    if (!key_down_handler_)
+      _E("Failed to register key down event handler");
+
+    key_up_handler_ = ecore_event_handler_add(ECORE_EVENT_KEY_UP,
+        MediaKeyReleaseCb, this);
+    if (!key_up_handler_)
+      _E("Failed to register key up event handler");
+
+    grabbed_ = true;
+    return 0;
+  }
+
+  void Ungrab() {
+    if (key_up_handler_) {
+      ecore_event_handler_del(key_up_handler_);
+      key_up_handler_ = nullptr;
+    }
+
+    if (key_down_handler_) {
+      ecore_event_handler_del(key_down_handler_);
+      key_down_handler_ = nullptr;
+    }
+
+    for (auto i = key_map_.rbegin(); i != key_map_.rend(); i++) {
+      _D("key(%s)", i->first.c_str());
+      auto ret = ecore_wl2_window_keygrab_unset(NULL, i->first.c_str(), 0, 0);
+      if (ret != EINA_TRUE)
+        _W("Failed to ungrab key(%s)", i->first.c_str());
+    }
+
+    grabbed_ = false;
+  }
+
+  std::recursive_mutex& GetMutex() const {
+    return mutex_;
+  }
+
+  static Eina_Bool MediaKeyPressCb(void* data, int type, void* event) {
+    Evas_Event_Key_Down* ev = static_cast<Evas_Event_Key_Down*>(event);
+    if (ev == nullptr) {
+      _E("Invalid parameter");
+      return ECORE_CALLBACK_RENEW;
+    }
+
+    auto* handle = static_cast<MediaKey*>(data);
+    if (handle->cb_ == nullptr)
+      return ECORE_CALLBACK_RENEW;
+
+    media_key_e media_key = handle->key_map_[ev->keyname];
+    handle->cb_(media_key, MEDIA_KEY_STATUS_PRESSED, handle->data_);
+    return ECORE_CALLBACK_RENEW;
+  }
+
+  static Eina_Bool MediaKeyReleaseCb(void* data, int type, void* event) {
+    Evas_Event_Key_Up* ev = static_cast<Evas_Event_Key_Up*>(event);
+    if (ev == nullptr) {
+      _E("Invalid parameter");
+      return ECORE_CALLBACK_RENEW;
+    }
+
+    auto* handle = static_cast<MediaKey*>(data);
+    if (handle->cb_ == nullptr)
+      return ECORE_CALLBACK_RENEW;
+
+    media_key_e media_key = handle->key_map_[ev->keyname];
+    handle->cb_(media_key, MEDIA_KEY_STATUS_RELEASED, handle->data_);
+    return ECORE_CALLBACK_RENEW;
+  }
+
+ private:
+  bool disposed_ = true;
+  bool grabbed_ = false;
+  media_key_event_cb cb_ = nullptr;
+  void* data_ = nullptr;
+  Ecore_Event_Handler* key_up_handler_ = nullptr;
+  Ecore_Event_Handler* key_down_handler_ = nullptr;
+  std::map<std::string, media_key_e> key_map_;
+  mutable std::recursive_mutex mutex_;
+};
+
+}  // namespace
+
+extern "C" EXPORT_API int media_key_reserve(media_key_event_cb callback,
+    void* user_data) {
+  if (callback == nullptr) {
+    _E("Invalid parameter");
+    return MEDIA_KEY_ERROR_INVALID_PARAMETER;
+  }
+
+  return ::MediaKey::GetInst().Reserve(callback, user_data);
+}
+
+extern "C" EXPORT_API int media_key_release(void) {
+  ::MediaKey::GetInst().Release();
+  return MEDIA_KEY_ERROR_NONE;
+}
+