From 1f9facaecf45bf9c1c16eab0bf6dc10cb58d44aa Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 26 Feb 2020 12:08:35 +0900 Subject: [PATCH] Refactor media key Change-Id: If0f86f8347852cf93fa4bf854b20c35504d91fd6 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 106 +++---------- packaging/capi-system-media-key.spec | 1 + src/log_private.hh | 47 ++++++ src/media_key.c | 226 --------------------------- src/media_key.cc | 226 +++++++++++++++++++++++++++ 5 files changed, 300 insertions(+), 306 deletions(-) create mode 100644 src/log_private.hh delete mode 100644 src/media_key.c create mode 100644 src/media_key.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f16917..37a99b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/packaging/capi-system-media-key.spec b/packaging/capi-system-media-key.spec index 68f2d7e..5c156b0 100644 --- a/packaging/capi-system-media-key.spec +++ b/packaging/capi-system-media-key.spec @@ -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 index 0000000..cfc24fc --- /dev/null +++ b/src/log_private.hh @@ -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 + +#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 index 6a901da..0000000 --- a/src/media_key.c +++ /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 -#include - -#include -#include -#include -#include - -#include - -#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 index 0000000..f2d11d5 --- /dev/null +++ b/src/media_key.cc @@ -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 +#include +#include +#include + +#include +#include +#include +#include + +#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 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 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 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(event); + if (ev == nullptr) { + _E("Invalid parameter"); + return ECORE_CALLBACK_RENEW; + } + + auto* handle = static_cast(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(event); + if (ev == nullptr) { + _E("Invalid parameter"); + return ECORE_CALLBACK_RENEW; + } + + auto* handle = static_cast(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 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; +} + -- 2.34.1