summaryrefslogtreecommitdiff
path: root/src/camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/camera.c')
-rw-r--r--src/camera.c486
1 files changed, 381 insertions, 105 deletions
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 <mm_evas_renderer.h>
#endif /* TIZEN_FEATURE_EVAS_RENDERER */
+#include <gio/gio.h>
#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;
+}