From 8b406b331e1ae985e45fcc59109e3c6ab602ce17 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 8 Sep 2016 21:48:29 +0900 Subject: [PATCH] New APIs are added New enum : camera_device_state_e New function : camera_get_device_state camera_add_device_state_changed_cb camera_remove_device_state_changed_cb [Version] 0.2.73 [Profile] Common [Issue Type] New function [Dependency module] N/A [Dependency commit] N/A [Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20160907.3] Change-Id: I9395c0b56c5dc3ebe738776f5ad91d5eca829733 Signed-off-by: Jeongmo Yang --- CMakeLists.txt | 4 +- include/camera.h | 75 +++++- include/camera_private.h | 34 ++- packaging/capi-media-camera.spec | 3 +- src/camera.c | 486 ++++++++++++++++++++++++++++++--------- test/camera_test.c | 113 +++++---- 6 files changed, 552 insertions(+), 163 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a8d9ab0..e334558 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,9 @@ SET(submodule "camera") # for package file IF(TIZEN_FEATURE_EVAS_RENDERER) -SET(dependents "libtbm dlog mm-common capi-base-common capi-media-tool ecore elementary mmsvc-camera tizen-extension-client mm-evas-renderer") +SET(dependents "glib-2.0 gio-2.0 libtbm dlog mm-common capi-base-common capi-media-tool ecore elementary mmsvc-camera tizen-extension-client mm-evas-renderer") ELSE(TIZEN_FEATURE_EVAS_RENDERER) -SET(dependents "libtbm dlog mm-common capi-base-common capi-media-tool ecore elementary mmsvc-camera tizen-extension-client") +SET(dependents "glib-2.0 gio-2.0 libtbm dlog mm-common capi-base-common capi-media-tool ecore elementary mmsvc-camera tizen-extension-client") ENDIF(TIZEN_FEATURE_EVAS_RENDERER) SET(pc_dependents "capi-base-common capi-media-tool libtbm evas ecore elementary") SET(fw_name "${project_prefix}-${service}-${submodule}") diff --git a/include/camera.h b/include/camera.h index e394ca1..9c17aa3 100644 --- a/include/camera.h +++ b/include/camera.h @@ -74,6 +74,16 @@ typedef enum { } camera_state_e; /** + * @brief Enumeration for the camera device state. + * @since_tizen 3.0 + */ +typedef enum { + CAMERA_DEVICE_STATE_NULL, /**< Not opened */ + CAMERA_DEVICE_STATE_OPENED, /**< Opened */ + CAMERA_DEVICE_STATE_WORKING /**< Now previewing or capturing or is being used for video recording */ +} camera_device_state_e; + +/** * @brief Enumeration for the camera device. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ @@ -516,7 +526,6 @@ typedef enum { /** * @brief Called when the camera state is changed. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif - * * @param[in] previous The previous state of the camera * @param[in] current The current state of the camera * @param[in] by_policy If @c true the state is changed by policy, otherwise @c false @@ -528,9 +537,18 @@ typedef enum { typedef void (*camera_state_changed_cb)(camera_state_e previous, camera_state_e current, bool by_policy, void *user_data); /** + * @brief Called when the camera device state is changed. + * @since_tizen 3.0 + * @param[in] device The hardware camera type + * @param[in] state The state of the camera device + * @param[in] user_data The user data passed from the callback registration function + * @see camera_add_device_state_changed_cb() + */ +typedef void (*camera_device_state_changed_cb)(camera_device_e device, camera_device_state_e state, void *user_data); + +/** * @brief Called when the camera is interrupted by policy. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif - * * @param[in] policy The policy that interrupted the camera * @param[in] previous The previous state of the camera * @param[in] current The current state of the camera @@ -595,7 +613,7 @@ typedef void (*camera_media_packet_preview_cb)(media_packet_h pkt, void *user_da * @brief Called to get information about image data taken by the camera once per frame while capturing. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * - * @remarks This function is issued in the context of gstreamer (video source thread) so the UI update code should not be directly invoked. + * @remarks This function is issued in the context of internal framework so the UI update code should not be directly invoked. * You must not call camera_start_preview() within this callback. * * @param[in] image The image data of the captured picture @@ -614,8 +632,8 @@ typedef void (*camera_capturing_cb)(camera_image_data_s *image, camera_image_dat * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * * @remarks The callback is called after camera_capturing_cb() is completed.\n - * If you want to show the user a preview after capturing is finished, an application can use camera_start_preview() after calling this callback. - * + * If you want to show the user a preview after capturing is finished, \n + * an application can use camera_start_preview() after calling this callback. * @param[in] user_data The user data passed from the callback registration function * @pre This callback function is invoked if it is registered using camera_start_capture() or camera_start_continuous_capture(). * @see camera_start_capture() @@ -633,8 +651,7 @@ typedef void (*camera_capture_completed_cb)(void *user_data); * In case of errors, one of these codes occur:\n * #CAMERA_ERROR_DEVICE,\n * #CAMERA_ERROR_INVALID_OPERATION,\n - * #CAMERA_ERROR_OUT_OF_MEMORY.\n - * + * #CAMERA_ERROR_OUT_OF_MEMORY. * @param[in] error The error code * @param[in] current_state The current state of the camera * @param[in] user_data The user data passed from the callback registration function @@ -1932,6 +1949,50 @@ int camera_set_error_cb(camera_h camera, camera_error_cb callback, void *user_da int camera_unset_error_cb(camera_h camera); /** + * @brief Gets the state of camera device. + * @since_tizen 3.0 + * @param[in] device The hardware camera type + * @param[out] state The current state of the device + * @return @c 0 on success, otherwise a negative error value + * @retval #CAMERA_ERROR_NONE Successful + * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CAMERA_ERROR_INVALID_OPERATION Invalid operation + * @retval #CAMERA_ERROR_NOT_SUPPORTED The feature is not supported + */ +int camera_get_device_state(camera_device_e device, camera_device_state_e *state); + +/** + * @brief Registers a callback function to be called when the camera device state changes. + * @since_tizen 3.0 + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @param[out] cb_id The id of registerd callback + * @return @c 0 on success, otherwise a negative error value + * @retval #CAMERA_ERROR_NONE Successful + * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CAMERA_ERROR_INVALID_OPERATION Invalid operation + * @retval #CAMERA_ERROR_OUT_OF_MEMORY Out of memory + * @retval #CAMERA_ERROR_NOT_SUPPORTED The feature is not supported + * @post This function will invoke camera_device_state_changed_cb() when the camera device's state changes. + * @see camera_remove_device_state_changed_cb() + * @see camera_device_state_changed_cb() + */ +int camera_add_device_state_changed_cb(camera_device_state_changed_cb callback, void *user_data, int *cb_id); + +/** + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @param[in] cb_id The id of registerd callback + * @return @c 0 on success, otherwise a negative error value + * @retval #CAMERA_ERROR_NONE Successful + * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CAMERA_ERROR_INVALID_OPERATION Invalid operation + * @retval #CAMERA_ERROR_NOT_SUPPORTED The feature is not supported + * @see camera_add_device_state_changed_cb() + */ +int camera_remove_device_state_changed_cb(int cb_id); + +/** * @} */ diff --git a/include/camera_private.h b/include/camera_private.h index 49a9571..8d84f75 100644 --- a/include/camera_private.h +++ b/include/camera_private.h @@ -19,7 +19,8 @@ #ifndef __TIZEN_MULTIMEDIA_CAMERA_PRIVATE_H__ -#define __TIZEN_MULTIMEDIA_CAMERA_PRIVATE_H__ +#define __TIZEN_MULTIMEDIA_CAMERA_PRIVATE_H__ +#include #include #include #include @@ -105,12 +106,18 @@ typedef struct _camera_msg_handler_info_s { } camera_msg_handler_info_s; typedef struct _camera_cb_info_s { + /* server connection */ gint fd; gboolean is_server_connected; /* message receive thread */ GThread *msg_recv_thread; gint msg_recv_running; + gchar recv_msg[MUSE_CAMERA_MSG_MAX_LENGTH]; + GCond api_cond[MUSE_CAMERA_API_MAX]; + GMutex api_mutex[MUSE_CAMERA_API_MAX]; + gint api_activating[MUSE_CAMERA_API_MAX]; + gint api_ret[MUSE_CAMERA_API_MAX]; /* general message handler info */ camera_msg_handler_info_s msg_handler_info; @@ -121,20 +128,26 @@ typedef struct _camera_cb_info_s { /* capture cb message handler info */ camera_msg_handler_info_s capture_cb_info; + /* idle event */ GList *idle_event_list; GCond idle_event_cond; GMutex idle_event_mutex; + + /* user callback */ gpointer user_cb[MUSE_CAMERA_EVENT_TYPE_NUM]; gpointer user_data[MUSE_CAMERA_EVENT_TYPE_NUM]; - gchar recv_msg[MUSE_CAMERA_MSG_MAX_LENGTH]; - GCond api_cond[MUSE_CAMERA_API_MAX]; - GMutex api_mutex[MUSE_CAMERA_API_MAX]; - gint api_activating[MUSE_CAMERA_API_MAX]; - gint api_ret[MUSE_CAMERA_API_MAX]; + + /* tbm */ tbm_bufmgr bufmgr; + + /* media packet */ media_format_h pkt_fmt; - int preview_cb_flag; GMutex mp_data_mutex; + + /* preview callback flag */ + int preview_cb_flag; + + /* evas surface */ #ifdef TIZEN_FEATURE_EVAS_RENDERER void *evas_info; GMutex evas_mutex; @@ -190,12 +203,19 @@ typedef struct _camera_msg_param { } value; } camera_msg_param; +typedef struct _camera_cb_info { + int id; + void *callback; + void *user_data; +} camera_cb_info; + int _camera_get_tbm_surface_format(int in_format, uint32_t *out_format); int _camera_get_media_packet_mimetype(int in_format, media_format_mimetype_e *mimetype); int _camera_media_packet_finalize(media_packet_h pkt, int error_code, void *user_data); int _camera_start_evas_rendering(camera_h camera); int _camera_stop_evas_rendering(camera_h camera, bool keep_screen); +int _camera_independent_request(int api, int device_type, const char *key, int *value); typedef bool (*camera_supported_cb_param1)(int param, void *user_data); typedef bool (*camera_supported_cb_param2)(int param1, int param2, void *user_data); diff --git a/packaging/capi-media-camera.spec b/packaging/capi-media-camera.spec index c69fa5d..5a8a3a9 100644 --- a/packaging/capi-media-camera.spec +++ b/packaging/capi-media-camera.spec @@ -1,6 +1,6 @@ Name: capi-media-camera Summary: A Camera API -Version: 0.2.72 +Version: 0.2.73 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -8,6 +8,7 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(mused) BuildRequires: pkgconfig(mm-common) BuildRequires: pkgconfig(capi-base-common) diff --git a/src/camera.c b/src/camera.c index b71ac92..78bf839 100644 --- a/src/camera.c +++ b/src/camera.c @@ -37,12 +37,19 @@ #ifdef TIZEN_FEATURE_EVAS_RENDERER #include #endif /* TIZEN_FEATURE_EVAS_RENDERER */ +#include #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "TIZEN_N_CAMERA" +/* for device changed callback */ +static GMutex g_cam_dev_state_changed_cb_lock; +static GList *g_cam_dev_state_changed_cb_list; +static int g_cam_dev_state_changed_cb_id; +static GDBusConnection *g_cam_dev_state_changed_cb_conn; +static guint g_cam_dev_state_changed_cb_subscribe_id; static void __global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -227,6 +234,56 @@ _DONE: } +static void __camera_device_state_changed_cb(GDBusConnection *connection, + const gchar *sender_name, const gchar *object_path, const gchar *interface_name, + const gchar *signal_name, GVariant *param, gpointer user_data) +{ + int value = 0; + camera_device_e device = CAMERA_DEVICE_CAMERA0; + camera_device_state_e state = CAMERA_DEVICE_STATE_NULL; + GList *tmp_list = NULL; + camera_cb_info *info = NULL; + + g_mutex_lock(&g_cam_dev_state_changed_cb_lock); + + if (!g_cam_dev_state_changed_cb_list || !param) { + LOGW("no callback or NULL param %p", param); + goto _DONE; + } + + /* get device and state */ + g_variant_get(param, "(i)", &value); + + device = value >> 16; + state = 0x0000ffff & value; + + LOGD("device %d, state %d", device, state); + + tmp_list = g_cam_dev_state_changed_cb_list; + + do { + info = (camera_cb_info *)tmp_list->data; + + if (info) { + if (info->callback) { + LOGD("start id[%d] callback", info->id); + ((camera_device_state_changed_cb)info->callback)(device, state, info->user_data); + LOGD("returned id[%d] callback", info->id); + } else { + LOGW("NULL callback for id %d", info->id); + } + } + + tmp_list = tmp_list->next; + } while (tmp_list); + +_DONE: + g_mutex_unlock(&g_cam_dev_state_changed_cb_lock); + + return; +} + + static int _camera_import_tbm_key(tbm_bufmgr bufmgr, unsigned int tbm_key, tbm_bo *bo, tbm_bo_handle *bo_handle) { tbm_bo tmp_bo = NULL; @@ -1476,7 +1533,7 @@ static void *_camera_msg_handler_func(gpointer data) camera_cb_info_s *cb_info = NULL; if (!handler_info || !handler_info->cb_info) { - LOGE("t:%d NULL handler %p", type, handler_info); + LOGE("NULL handler %p", handler_info); return NULL; } @@ -1545,7 +1602,7 @@ static void *_camera_msg_handler_func(gpointer data) g_mutex_init(&cam_idle_event->event_mutex); strncpy(cam_idle_event->recv_msg, cam_msg->recv_msg, sizeof(cam_idle_event->recv_msg) - 1); - /*LOGD("t:%d add camera event[%d, %p] to IDLE", type, event, cam_idle_event);*/ + /*LOGD("t:%d add camera event[%d, %p] to IDLE", type, cam_msg->event, cam_idle_event);*/ g_mutex_lock(&cb_info->idle_event_mutex); cb_info->idle_event_list = g_list_append(cb_info->idle_event_list, (gpointer)cam_idle_event); @@ -1837,9 +1894,10 @@ static void *_camera_msg_recv_func(gpointer data) g_atomic_int_set(&cb_info->msg_recv_running, 0); LOGD("camera destroy done. close client cb handler"); } - } else if (api == MUSE_CAMERA_API_GET_FLASH_STATE) { + } else if (api == MUSE_CAMERA_API_GET_FLASH_STATE || + api == MUSE_CAMERA_API_GET_DEVICE_STATE) { g_atomic_int_set(&cb_info->msg_recv_running, 0); - LOGD("get flash state done. close client cb handler"); + LOGD("get flash or device state done. close client cb handler"); } g_cond_signal(&cb_info->api_cond[api]); @@ -2200,6 +2258,91 @@ int _camera_stop_evas_rendering(camera_h camera, bool keep_screen) } +int _camera_independent_request(int api, int device_type, const char *key, int *value) +{ + int ret = CAMERA_ERROR_NONE; + int send_ret = 0; + int sock_fd = -1; + char *msg = NULL; + camera_cli_s *pc = NULL; + + /* create muse connection */ + if (!key || !value) { + LOGE("NULL pointer"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + sock_fd = muse_core_client_new(); + if (sock_fd < 0) { + LOGE("muse_core_client_new failed"); + return CAMERA_ERROR_INVALID_OPERATION; + } + + msg = muse_core_msg_json_factory_new(api, + MUSE_TYPE_INT, "module", MUSE_CAMERA, + MUSE_TYPE_INT, PARAM_DEVICE_TYPE, device_type, + 0); + if (!msg) { + LOGE("msg failed"); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + goto _REQUEST_EXIT; + } + + send_ret = muse_core_ipc_send_msg(sock_fd, msg); + + muse_core_msg_json_factory_free(msg); + msg = NULL; + + if (send_ret < 0) { + LOGE("send msg failed"); + ret = CAMERA_ERROR_INVALID_OPERATION; + goto _REQUEST_EXIT; + } + + pc = g_new0(camera_cli_s, 1); + if (!pc) { + LOGE("handle alloc failed"); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + goto _REQUEST_EXIT; + } + + pc->cb_info = _camera_client_callback_new(sock_fd, false); + if (!pc->cb_info) { + LOGE("cb_info alloc failed"); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + goto _REQUEST_EXIT; + } + + sock_fd = -1; + + ret = _camera_client_wait_for_cb_return(api, pc->cb_info, CAMERA_CB_TIMEOUT); + + if (ret == CAMERA_ERROR_NONE) + muse_core_msg_json_deserialize(key, pc->cb_info->recv_msg, NULL, value, NULL, MUSE_TYPE_ANY); + + LOGD("api %d - value %d", api, *value); + +_REQUEST_EXIT: + /* release resources */ + if (pc) { + if (pc->cb_info) { + _camera_client_callback_destroy(pc->cb_info); + pc->cb_info = NULL; + } + + g_free(pc); + pc = NULL; + } + + if (sock_fd > -1) { + muse_core_connection_close(sock_fd); + sock_fd = -1; + } + + return ret; +} + + int camera_create(camera_device_e device, camera_h *camera) { int sock_fd = -1; @@ -2492,8 +2635,10 @@ bool camera_is_supported_continuous_capture(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -2567,8 +2712,10 @@ bool camera_is_supported_face_detection(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -2591,8 +2738,10 @@ bool camera_is_supported_zero_shutter_lag(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -2615,8 +2764,10 @@ bool camera_is_supported_media_packet_preview_cb(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -3468,13 +3619,14 @@ int camera_set_preview_cb(camera_h camera, camera_preview_cb callback, void *use LOGD("Enter"); - pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW] = callback; - pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW] = user_data; - - SET_PREVIEW_CB_TYPE(pc->cb_info, PREVIEW_CB_TYPE_USER); - _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); + if (ret == CAMERA_ERROR_NONE) { + pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW] = callback; + pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW] = user_data; + SET_PREVIEW_CB_TYPE(pc->cb_info, PREVIEW_CB_TYPE_USER); + } + LOGD("ret : 0x%x", ret); return ret; @@ -3530,11 +3682,13 @@ int camera_set_media_packet_preview_cb(camera_h camera, camera_media_packet_prev LOGD("Enter"); - pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW] = callback; - pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW] = user_data; - _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); + if (ret == CAMERA_ERROR_NONE) { + pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW] = callback; + pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW] = user_data; + } + LOGD("ret : 0x%x", ret); return ret; @@ -3578,11 +3732,13 @@ int camera_set_state_changed_cb(camera_h camera, camera_state_changed_cb callbac LOGD("Enter"); - pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_STATE_CHANGE] = callback; - pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_STATE_CHANGE] = user_data; - _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); + if (ret == CAMERA_ERROR_NONE) { + pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_STATE_CHANGE] = callback; + pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_STATE_CHANGE] = user_data; + } + LOGD("ret : 0x%x", ret); return ret; @@ -3626,11 +3782,13 @@ int camera_set_interrupted_cb(camera_h camera, camera_interrupted_cb callback, v LOGD("Enter"); - pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_INTERRUPTED] = callback; - pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_INTERRUPTED] = user_data; - _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); + if (ret == CAMERA_ERROR_NONE) { + pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_INTERRUPTED] = callback; + pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_INTERRUPTED] = user_data; + } + LOGD("ret : 0x%x", ret); return ret; @@ -3674,11 +3832,13 @@ int camera_set_focus_changed_cb(camera_h camera, camera_focus_changed_cb callbac LOGD("Enter"); - pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_FOCUS_CHANGE] = callback; - pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_FOCUS_CHANGE] = user_data; - _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); + if (ret == CAMERA_ERROR_NONE) { + pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_FOCUS_CHANGE] = callback; + pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_FOCUS_CHANGE] = user_data; + } + LOGD("ret : 0x%x", ret); return ret; @@ -3722,11 +3882,13 @@ int camera_set_error_cb(camera_h camera, camera_error_cb callback, void *user_da LOGD("Enter"); - pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_ERROR] = callback; - pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_ERROR] = user_data; - _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); + if (ret == CAMERA_ERROR_NONE) { + pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_ERROR] = callback; + pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_ERROR] = user_data; + } + LOGD("ret : 0x%x", ret); return ret; @@ -5229,90 +5391,22 @@ int camera_attr_get_flash_mode(camera_h camera, camera_attr_flash_mode_e *mode) int camera_get_flash_state(camera_device_e device, camera_flash_state_e *state) { - int sock_fd = -1; - char *msg = NULL; int ret = CAMERA_ERROR_NONE; - int send_ret = 0; - camera_cli_s *pc = NULL; int get_flash_state = 0; - /* create muse connection */ - muse_camera_api_e api = MUSE_CAMERA_API_GET_FLASH_STATE; - muse_core_api_module_e muse_module = MUSE_CAMERA; - int device_type = (int)device; - if (!state) { LOGE("NULL pointer"); return CAMERA_ERROR_INVALID_PARAMETER; } - sock_fd = muse_core_client_new(); - if (sock_fd < 0) { - LOGE("muse_core_client_new failed"); - return CAMERA_ERROR_INVALID_OPERATION; - } - - msg = muse_core_msg_json_factory_new(api, - MUSE_TYPE_INT, "module", muse_module, - MUSE_TYPE_INT, PARAM_DEVICE_TYPE, device_type, - 0); - if (!msg) { - LOGE("msg failed"); - ret = CAMERA_ERROR_OUT_OF_MEMORY; - goto Exit; - } - - send_ret = muse_core_ipc_send_msg(sock_fd, msg); - - muse_core_msg_json_factory_free(msg); - msg = NULL; - - if (send_ret < 0) { - LOGE("send msg failed"); - ret = CAMERA_ERROR_INVALID_OPERATION; - goto Exit; - } - - pc = g_new0(camera_cli_s, 1); - if (!pc) { - LOGE("handle alloc failed"); - ret = CAMERA_ERROR_OUT_OF_MEMORY; - goto Exit; - } - - pc->cb_info = _camera_client_callback_new(sock_fd, false); - if (!pc->cb_info) { - LOGE("cb_info alloc failed"); - ret = CAMERA_ERROR_OUT_OF_MEMORY; - goto Exit; - } - - sock_fd = -1; - - ret = _camera_client_wait_for_cb_return(api, pc->cb_info, CAMERA_CB_TIMEOUT); + ret = _camera_independent_request(MUSE_CAMERA_API_GET_FLASH_STATE, + (int)device, "get_flash_state", &get_flash_state); if (ret == CAMERA_ERROR_NONE) { - muse_camera_msg_get(get_flash_state, pc->cb_info->recv_msg); *state = (camera_flash_state_e)get_flash_state; - } - - LOGD("Flash state : %d", *state); - -Exit: - /* release resources */ - if (pc) { - if (pc->cb_info) { - _camera_client_callback_destroy(pc->cb_info); - pc->cb_info = NULL; - } - - g_free(pc); - pc = NULL; - } - - if (sock_fd > -1) { - muse_core_connection_close(sock_fd); - sock_fd = -1; + LOGD("flash state %d", *state); + } else { + LOGE("failed 0x%x", ret); } return ret; @@ -5758,8 +5852,10 @@ bool camera_attr_is_supported_hdr_capture(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -5892,8 +5988,10 @@ bool camera_attr_is_supported_anti_shake(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -5968,8 +6066,10 @@ bool camera_attr_is_supported_video_stabilization(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -6044,8 +6144,10 @@ bool camera_attr_is_supported_auto_contrast(camera_h camera) _camera_msg_send(api, pc->cb_info, &ret, CAMERA_CB_TIMEOUT); - if (ret == CAMERA_ERROR_SERVICE_DISCONNECTED) + if (ret < 0) { + LOGE("error is occurred 0x%x", ret); ret = false; + } LOGD("ret : %d", ret); @@ -6384,3 +6486,177 @@ int camera_attr_get_display_roi_area(camera_h camera, int *x, int *y, int *width return ret; } + + +int camera_get_device_state(camera_device_e device, camera_device_state_e *state) +{ + int ret = CAMERA_ERROR_NONE; + int get_device_state = 0; + + if (!state) { + LOGE("NULL pointer"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + ret = _camera_independent_request(MUSE_CAMERA_API_GET_DEVICE_STATE, + (int)device, "get_device_state", &get_device_state); + + if (ret == CAMERA_ERROR_NONE) { + *state = (camera_device_state_e)get_device_state; + LOGD("device state %d", *state); + } else { + LOGE("failed 0x%x", ret); + } + + return ret; +} + + +int camera_add_device_state_changed_cb(camera_device_state_changed_cb callback, void *user_data, int *cb_id) +{ + int ret = CAMERA_ERROR_NONE; + camera_device_state_e state = CAMERA_DEVICE_STATE_NULL; + camera_cb_info *info = NULL; + + if (!callback || !cb_id) { + LOGE("invalid pointer %p %p", callback, cb_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + /* check camera support */ + ret = camera_get_device_state(CAMERA_DEVICE_CAMERA0, &state); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get device state failed"); + return ret; + } + + g_mutex_lock(&g_cam_dev_state_changed_cb_lock); + + info = g_new0(camera_cb_info, 1); + if (!info) { + LOGE("info failed"); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + goto _DONE; + } + + info->id = ++g_cam_dev_state_changed_cb_id; + info->callback = (void *)callback; + + *cb_id = info->id; + + /* subscribe dbus signal for camera state change */ + if (!g_cam_dev_state_changed_cb_conn) { + g_cam_dev_state_changed_cb_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); + if (!g_cam_dev_state_changed_cb_conn) { + LOGE("failed to get gdbus connection"); + ret = CAMERA_ERROR_INVALID_OPERATION; + goto _DONE; + } + + LOGD("subscribe signal %s - %s - %s", + MM_CAMCORDER_DBUS_OBJECT, + MM_CAMCORDER_DBUS_INTERFACE_CAMERA, + MM_CAMCORDER_DBUS_SIGNAL_STATE_CHANGED); + + g_cam_dev_state_changed_cb_subscribe_id = g_dbus_connection_signal_subscribe(g_cam_dev_state_changed_cb_conn, + NULL, MM_CAMCORDER_DBUS_INTERFACE_CAMERA, MM_CAMCORDER_DBUS_SIGNAL_STATE_CHANGED, MM_CAMCORDER_DBUS_OBJECT, NULL, + G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)__camera_device_state_changed_cb, NULL, NULL); + if (!g_cam_dev_state_changed_cb_subscribe_id) { + LOGE("failed to get gdbus connection"); + ret = CAMERA_ERROR_INVALID_OPERATION; + goto _DONE; + } + + LOGD("signal subscribe id %u", g_cam_dev_state_changed_cb_subscribe_id); + } + + g_cam_dev_state_changed_cb_list = g_list_prepend(g_cam_dev_state_changed_cb_list, (gpointer)info); + + LOGD("callback id %d", info->id); + +_DONE: + if (ret != CAMERA_ERROR_NONE) { + if (info) { + g_free(info); + info = NULL; + } + + if (g_cam_dev_state_changed_cb_conn) { + g_object_unref(g_cam_dev_state_changed_cb_conn); + g_cam_dev_state_changed_cb_conn = NULL; + } + } + + g_mutex_unlock(&g_cam_dev_state_changed_cb_lock); + + return ret; +} + + +int camera_remove_device_state_changed_cb(int cb_id) +{ + int ret = CAMERA_ERROR_NONE; + camera_device_state_e state = CAMERA_DEVICE_STATE_NULL; + GList *tmp_list = NULL; + camera_cb_info *info = NULL; + + /* check camera support */ + ret = camera_get_device_state(CAMERA_DEVICE_CAMERA0, &state); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get device state failed"); + return ret; + } + + g_mutex_lock(&g_cam_dev_state_changed_cb_lock); + + if (!g_cam_dev_state_changed_cb_list) { + LOGE("there is no callback info"); + ret = CAMERA_ERROR_INVALID_OPERATION; + goto _DONE; + } + + tmp_list = g_cam_dev_state_changed_cb_list; + + do { + info = tmp_list->data; + tmp_list = tmp_list->next; + + if (!info) { + LOGW("NULL info"); + continue; + } + + if (info->id == cb_id) { + g_cam_dev_state_changed_cb_list = g_list_remove(g_cam_dev_state_changed_cb_list, info); + + g_free(info); + info = NULL; + + if (!g_cam_dev_state_changed_cb_list) { + /* no remained callback */ + if (g_cam_dev_state_changed_cb_conn) { + /* unsubscribe signal */ + g_dbus_connection_signal_unsubscribe(g_cam_dev_state_changed_cb_conn, g_cam_dev_state_changed_cb_subscribe_id); + g_cam_dev_state_changed_cb_subscribe_id = 0; + + /* unref connection */ + g_object_unref(g_cam_dev_state_changed_cb_conn); + g_cam_dev_state_changed_cb_conn = NULL; + } + } + + LOGD("id %d callback removed", cb_id); + ret = CAMERA_ERROR_NONE; + + goto _DONE; + } + } while (tmp_list); + + LOGE("id %d callback not found", cb_id); + ret = CAMERA_ERROR_INVALID_PARAMETER; + +_DONE: + g_mutex_unlock(&g_cam_dev_state_changed_cb_lock); + + return ret; +} diff --git a/test/camera_test.c b/test/camera_test.c index 962db77..1d3b608 100644 --- a/test/camera_test.c +++ b/test/camera_test.c @@ -70,6 +70,7 @@ int camera_state; int camera_print_state; int multishot_num; static GTimer *timer = NULL; +static int g_camera_device_changed_cb_id; GTimeVal previous_time; GTimeVal current_time; @@ -130,7 +131,7 @@ GTimeVal res; int ret = 0; \ ret = expr; \ if (ret != 0) {\ - printf("[%s:%d] error code : %x \n", __func__, __LINE__, ret); \ + g_print("[%s:%d] error code : %x \n", __func__, __LINE__, ret); \ return; \ } \ } while (0) @@ -435,7 +436,7 @@ static inline void flush_stdin() static bool _release_idle_event_callback(void *data) { - printf("destroy camera handle\n\n"); + g_print("destroy camera handle\n\n"); camera_destroy(hcamcorder->camera); hcamcorder->camera = NULL; @@ -447,17 +448,17 @@ static bool _release_idle_event_callback(void *data) static void _camera_error_cb(int error, camera_state_e current_state, void *user_data) { - printf("\n\n\tERROR [0x%x], current state %d\n", error, current_state); + g_print("\n\n\tERROR [0x%x], current state %d\n", error, current_state); switch (error) { case CAMERA_ERROR_RESOURCE_CONFLICT: - printf("\t\t[CAMERA_ERROR_RESOURCE_CONFLICT]\n\n"); + g_print("\t\t[CAMERA_ERROR_RESOURCE_CONFLICT]\n\n"); break; case CAMERA_ERROR_SECURITY_RESTRICTED: - printf("\t\t[CAMERA_ERROR_SECURITY_RESTRICTED]\n\n"); + g_print("\t\t[CAMERA_ERROR_SECURITY_RESTRICTED]\n\n"); break; case CAMERA_ERROR_SERVICE_DISCONNECTED: - printf("\t\t[CAMERA_ERROR_SERVICE_DISCONNECTED]\n\n"); + g_print("\t\t[CAMERA_ERROR_SERVICE_DISCONNECTED]\n\n"); g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc)_release_idle_event_callback, NULL, NULL); @@ -471,12 +472,20 @@ static void _camera_error_cb(int error, camera_state_e current_state, void *user static void _camera_state_changed_cb(camera_state_e previous, camera_state_e current, bool by_policy, void *user_data) { - printf("camera state changed %d -> %d\n", previous, current); + g_print("\ncamera state changed %d -> %d\n", previous, current); + return; +} + +static void _camera_device_state_changed_cb(camera_device_e device, camera_device_state_e state, void *user_data) +{ + g_print("\ncamera device[%d] state changed to %d\n", device, state); + return; } static void _camera_interrupted_cb(camera_policy_e policy, camera_state_e previous, camera_state_e current, void *user_data) { - printf("camera interrupted callback called %d\n", policy); + g_print("\ncamera interrupted callback called %d\n", policy); + return; } static bool preview_resolution_cb(int width, int height, void *user_data) @@ -484,14 +493,14 @@ static bool preview_resolution_cb(int width, int height, void *user_data) resolution_stack *data = (resolution_stack *)user_data; if (data == NULL) { - printf("NULL data\n"); + g_print("NULL data\n"); return false; } data->width[data->count] = width; data->height[data->count] = height; - printf("%d. %dx%d\n", data->count, width, height); + g_print("%d. %dx%d\n", data->count, width, height); data->count++; @@ -503,14 +512,14 @@ static bool capture_resolution_test_cb(int width, int height, void *user_data) resolution_stack *data = (resolution_stack *)user_data; if (data == NULL) { - printf("NULL data\n"); + g_print("NULL data\n"); return false; } data->width[data->count] = width; data->height[data->count] = height; - printf("%d. %dx%d\n", data->count, width, height); + g_print("%d. %dx%d\n", data->count, width, height); data->count++; @@ -519,7 +528,7 @@ static bool capture_resolution_test_cb(int width, int height, void *user_data) static bool af_mode_foreach_cb(camera_attr_iso_e mode, void *user_data) { - printf("%d.%s\n", mode, af_scan[mode]); + g_print("%d.%s\n", mode, af_scan[mode]); return true; } @@ -528,20 +537,20 @@ static bool exposure_mode_cb(camera_attr_af_mode_e mode, void *user_data) exposure_stack *data = (exposure_stack *)user_data; if (data == NULL) { - printf("NULL data\n"); + g_print("NULL data\n"); return false; } data->mode = mode; data->count++; - printf("%d.%s\n", mode, exposure_mode[mode]); + g_print("%d.%s\n", mode, exposure_mode[mode]); return true; } static bool iso_mode_cb(camera_attr_iso_e mode, void *user_data) { - printf("%d.%s\n", mode, iso_mode[mode]); + g_print("%d.%s\n", mode, iso_mode[mode]); return true; } @@ -550,55 +559,55 @@ static bool camera_rotation_cb(camera_rotation_e mode, void *user_data) camera_rotation_stack *data = (camera_rotation_stack *)user_data; if (data == NULL) { - printf("NULL data\n"); + g_print("NULL data\n"); return false; } data->mode = mode; data->count++; - printf("%d.%s\n", mode, camera_rotation[mode]); + g_print("%d.%s\n", mode, camera_rotation[mode]); return true; } static bool preview_format_cb(camera_pixel_format_e mode, void *user_data) { - printf("%d.%s\n", mode, image_fmt[mode]); + g_print("%d.%s\n", mode, image_fmt[mode]); return true; } static bool white_balance_cb(camera_attr_whitebalance_e mode, void *user_data) { - printf("%d.%s\n", mode, wb[mode]); + g_print("%d.%s\n", mode, wb[mode]); return true; } static bool colortone_cb(camera_attr_effect_mode_e mode, void *user_data) { - printf("%d.%s\n", mode, ct[mode]); + g_print("%d.%s\n", mode, ct[mode]); return true; } static bool program_mode_cb(camera_attr_scene_mode_e mode, void *user_data) { - printf("%d.%s\n", mode, program_mode[mode]); + g_print("%d.%s\n", mode, program_mode[mode]); return true; } static bool strobe_mode_cb(camera_attr_flash_mode_e mode, void *user_data) { - printf("%d.%s\n", mode, strobe_mode[mode]); + g_print("%d.%s\n", mode, strobe_mode[mode]); return true; } static void _face_detected(camera_detected_face_s *faces, int count, void *user_data) { - printf("face detected!!\n"); + g_print("face detected!!\n"); int i; for (i = 0 ; i < count ; i++) - printf("%d) - %dx%d\n", faces[i].id, faces[i].x, faces[i].y); + g_print("%d) - %dx%d\n", faces[i].id, faces[i].x, faces[i].y); return; } @@ -608,20 +617,20 @@ static void _file_write(char *path, void *data, int size) FILE *fp = NULL; if (!path || !data || size <= 0) { - printf("ERROR %p %p %d\n", path, data, size); + g_print("ERROR %p %p %d\n", path, data, size); return; } fp = fopen(path, "w"); if (fp == NULL) { - printf("open error! [%s], errno %d\n", path, errno); + g_print("open error! [%s], errno %d\n", path, errno); return; } else { - printf("open success [%s]\n", path); + g_print("open success [%s]\n", path); if (fwrite(data, size, 1, fp) != 1) - printf("write error! errno %d\n", errno); + g_print("write error! errno %d\n", errno); else - printf("write success [%s]\n", path); + g_print("write success [%s]\n", path); fclose(fp); fp = NULL; @@ -662,6 +671,9 @@ static void print_menu() g_print("\t=======================================\n"); g_print("\t '1' Video Capture - Front Camera\n"); g_print("\t '2' Video Capture - Rear Camera\n"); + g_print("\t '3' Add camera device state changed callback\n"); + g_print("\t '4' Remove camera device state changed callback\n"); + g_print("\t '5' Get camera device state\n"); g_print("\t 'q' Exit\n"); g_print("\t=======================================\n"); @@ -756,10 +768,10 @@ static void main_menu(gchar buf) hcamcorder->isMultishot = TRUE; int interval = 0, count = 0; flush_stdin(); - printf("\ninput interval(ms)\n"); + g_print("\ninput interval(ms)\n"); err = scanf("%d", &interval); flush_stdin(); - printf("\ninput count(ms) \n"); + g_print("\ninput count(ms) \n"); err = scanf("%d", &count); camera_attr_set_image_quality(hcamcorder->camera, 100); camera_set_capture_format(hcamcorder->camera, CAMERA_PIXEL_FORMAT_JPEG); @@ -832,24 +844,24 @@ static void setting_menu(gchar buf) err = scanf("%d", &idx); int result = 0; if (resolution_list.count > idx && idx >= 0) { - printf("-----------------PREVIEW RESOLUTION (%dx%d)---------------------\n", + g_print("-----------------PREVIEW RESOLUTION (%dx%d)---------------------\n", resolution_list.width[idx], resolution_list.height[idx]); result = camera_set_preview_resolution(hcamcorder->camera, resolution_list.width[idx], resolution_list.height[idx]); } else { - printf("invalid input %d\n", idx); + g_print("invalid input %d\n", idx); result = -1; } resolution_list.count = 0; if (result != 0) - printf("FAIL\n"); + g_print("FAIL\n"); else - printf("PASS\n"); + g_print("PASS\n"); break; case '1': /* Setting > Capture Resolution setting */ g_print("*Select the preview resolution!\n"); - printf("-----------------CAPTURE RESOLUTION TEST: ---------------------\n"); + g_print("-----------------CAPTURE RESOLUTION TEST: ---------------------\n"); resolution_list.count = 0; camera_foreach_supported_capture_resolution(hcamcorder->camera, @@ -862,17 +874,17 @@ static void setting_menu(gchar buf) result = camera_set_capture_resolution(hcamcorder->camera, resolution_list.width[idx], resolution_list.height[idx]); - printf("camera_set_capture_resolution with width =%d, height=%d ret=0x%x\n", + g_print("camera_set_capture_resolution with width =%d, height=%d ret=0x%x\n", resolution_list.width[idx], resolution_list.height[idx], result); } else { - printf("invalid input %d\n", idx); + g_print("invalid input %d\n", idx); result = -1; } resolution_list.count = 0; if (result != 0) - printf("FAIL\n"); + g_print("FAIL\n"); else - printf("PASS\n"); + g_print("PASS\n"); break; case '2': /* Setting > Digital zoom level */ @@ -1352,6 +1364,7 @@ void _preview_cb(camera_preview_data_s *frame, void *user_data) static gboolean mode_change(gchar buf) { int err = 0; + camera_device_state_e device_state = CAMERA_DEVICE_STATE_NULL; char display_type = '\0'; bool check = FALSE; @@ -1366,6 +1379,24 @@ static gboolean mode_change(gchar buf) hcamcorder->type = cam_info = CAMERA_DEVICE_CAMERA0; check = TRUE; break; + case '3': + err = camera_add_device_state_changed_cb(_camera_device_state_changed_cb, + NULL, &g_camera_device_changed_cb_id); + g_print("add result 0x%x - cb id %d\n", err, g_camera_device_changed_cb_id); + return FALSE; + case '4': + if (g_camera_device_changed_cb_id > 0) { + err = camera_remove_device_state_changed_cb(g_camera_device_changed_cb_id); + g_camera_device_changed_cb_id = 0; + g_print("remove result 0x%x\n", err); + } else { + g_print("invalid callback id %d\n", g_camera_device_changed_cb_id); + } + return FALSE; + case '5': + err = camera_get_device_state(CAMERA_DEVICE_CAMERA0, &device_state); + g_print("get result 0x%x - state %d\n", err, device_state); + return FALSE; case 'q': g_print("\t Quit Camcorder Testsuite!!\n"); hcamcorder->mode = -1; -- 2.7.4