2 * Media Utility for DCM
4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Ji Yong Min <jiyong.min@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <sys/types.h>
27 #include <media-server-ipc.h>
28 #include <media-util.h>
29 #include <media-util-internal.h>
30 #include <media-util-dbg.h>
31 #include <media-util-dcm.h>
32 #include <media-util-err.h>
33 #include <media-util-ipc.h>
34 #include <tzplatform_config.h>
36 #define DCM_MSG_MAX_SIZE 4096
38 static GQueue *g_request_queue = NULL;
39 static GQueue *g_manage_queue = NULL;
54 faceUserData *userData;
59 DCM_PHONE, /**< Stored only in phone */
60 DCM_MMC /**< Stored only in MMC */
61 } media_dcm_store_type;
63 extern char MEDIA_IPC_PATH[][70];
65 int __media_dcm_check_req_queue(const char *path);
66 int __media_dcm_pop_manage_queue(const unsigned int request_id, const char *path);
67 int _media_dcm_send_request();
69 gboolean __media_dcm_check_cancel(void)
72 req = (dcmReq *)g_queue_peek_head(g_request_queue);
84 void __media_dcm_shutdown_channel(gboolean only_shutdown)
87 dcmReq *req = (dcmReq *)g_queue_peek_head(g_request_queue);
89 len = g_queue_get_length(g_manage_queue);
93 if (len == 0 && req->isCanceled == TRUE) {
94 MSAPI_DBG("The manage queue will be released");
96 MSAPI_DBG("There is remain item in the manage queue");
100 GSource *source_id = g_main_context_find_source_by_id(g_main_context_get_thread_default(), req->source_id);
101 if (source_id != NULL) {
102 g_source_destroy(source_id);
104 MSAPI_DBG_ERR("G_SOURCE_ID is NULL");
107 g_io_channel_shutdown(req->channel, TRUE, NULL);
108 g_io_channel_unref(req->channel);
109 g_queue_pop_head(g_request_queue);
111 MS_SAFE_FREE(req->path);
112 MS_SAFE_FREE(req->userData);
115 if(g_manage_queue && len == 0) {
116 g_queue_free(g_manage_queue);
117 g_manage_queue = NULL;
122 int __media_dcm_pop_req_queue(const char *path)
126 req_len = g_queue_get_length(g_request_queue);
129 MSAPI_DBG("There is no request in the queue");
131 __media_dcm_shutdown_channel(TRUE);
134 /* Check manage queue */
136 req_len = g_queue_get_length(g_manage_queue);
139 _media_dcm_send_request();
142 return MS_MEDIA_ERR_NONE;
145 int __media_dcm_check_req_queue_for_cancel(unsigned int request_id, const char *path)
149 req_len = g_queue_get_length(g_request_queue);
152 MSAPI_DBG("There is no request in the queue");
155 req = (dcmReq *)g_queue_peek_head(g_request_queue);
157 if (req != NULL && strncmp(path, req->path, strlen(path)) == 0 && request_id == req->request_id) {
158 req->isCanceled = true;
159 __media_dcm_shutdown_channel(false);
161 return MS_MEDIA_ERR_NONE;
165 return MS_MEDIA_ERR_INTERNAL;
168 gboolean __media_dcm_write_socket(GIOChannel *src, GIOCondition condition, gpointer data)
172 int err = MS_MEDIA_ERR_NONE;
174 memset((void *)&recv_msg, 0, sizeof(dcmMsg));
175 sock = g_io_channel_unix_get_fd(src);
177 MSAPI_DBG("__media_dcm_write_socket socket : %d", sock);
179 if ((err = recv(sock, &recv_msg, sizeof(dcmMsg), 0)) < 0) {
180 MSAPI_DBG_STRERROR("recv failed ");
181 if (recv_msg.msg_size > 0) {
182 __media_dcm_pop_req_queue(recv_msg.msg);
184 MSAPI_DBG_ERR("origin path size is wrong.");
190 MSAPI_DBG("Completed.. %d, %s, %d", recv_msg.msg_type, recv_msg.msg, recv_msg.result);
192 if (__media_dcm_check_cancel()) {
193 MSAPI_DBG_ERR("__media_dcm_check_cancel is true");
195 faceUserData* cb = (faceUserData*)data;
196 if (cb->func != NULL) {
197 cb->func(recv_msg.msg_type, (int)(recv_msg.result), cb->user_data);
202 __media_dcm_pop_req_queue(recv_msg.msg);
209 int __media_dcm_check_req_queue(const char *path)
213 req_len = g_queue_get_length(g_request_queue);
215 MSAPI_DBG("Queue length : %d", req_len);
216 MSAPI_DBG("Queue path : %s", path);
219 MSAPI_DBG("There is no request in the queue");
222 for (i = 0; i < req_len; i++) {
224 req = (dcmReq *)g_queue_peek_nth(g_request_queue, i);
225 if (req == NULL) continue;
227 if (strncmp(path, req->path, strlen(path)) == 0) {
228 MSAPI_DBG("Same Request - %s", path);
229 return MS_MEDIA_ERR_INVALID_PARAMETER;
234 return MS_MEDIA_ERR_NONE;
237 int __media_dcm_pop_manage_queue(const unsigned int request_id, const char *path)
240 gboolean flag = FALSE;
242 req_len = g_queue_get_length(g_manage_queue);
245 MSAPI_DBG("There is no request in the queue");
247 for (i = 0; i < req_len; i++) {
249 req = (dcmReq *)g_queue_peek_nth(g_manage_queue, i);
250 if (req == NULL) continue;
252 if (strncmp(path, req->path, strlen(path)) == 0) {
253 g_queue_pop_nth(g_manage_queue, i);
255 MS_SAFE_FREE(req->path);
256 MS_SAFE_FREE(req->userData);
263 return __media_dcm_check_req_queue_for_cancel(request_id, path);
265 __media_dcm_shutdown_channel(FALSE);
267 return MS_MEDIA_ERR_NONE;
271 return MS_MEDIA_ERR_NONE;
274 int __media_dcm_get_store_type_by_path(const char *full_path)
276 if (full_path != NULL && MEDIA_ROOT_PATH_INTERNAL != NULL && MEDIA_ROOT_PATH_SDCARD != NULL) {
277 if (strncmp(full_path, MEDIA_ROOT_PATH_INTERNAL, strlen(MEDIA_ROOT_PATH_INTERNAL)) == 0) {
279 } else if (strncmp(full_path, MEDIA_ROOT_PATH_SDCARD, strlen(MEDIA_ROOT_PATH_SDCARD)) == 0) {
287 int _media_dcm_send_request()
289 int err = MS_MEDIA_ERR_NONE;
291 struct sockaddr_un serv_addr;
292 ms_sock_info_s sock_info;
293 dcmReq *req_manager = NULL;
294 sock_info.port = MS_DCM_CREATOR_PORT;
296 MSAPI_DBG("_media_dcm_send_request start");
298 err = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_60, &sock_info);
299 if (err != MS_MEDIA_ERR_NONE) {
300 MSAPI_DBG_ERR("ms_ipc_create_client_socket failed");
304 memset(&serv_addr, 0, sizeof(serv_addr));
305 sock = sock_info.sock_fd;
306 serv_addr.sun_family = AF_UNIX;
307 strncpy(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[sock_info.port]), strlen(tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[sock_info.port])));
309 GIOChannel *channel = NULL;
310 channel = g_io_channel_unix_new(sock);
313 /* Connecting to the dcm service */
314 if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
315 MSAPI_DBG_STRERROR("connect");
316 g_io_channel_shutdown(channel, TRUE, NULL);
317 g_io_channel_unref(channel);
318 ms_ipc_delete_client_socket(&sock_info);
319 return MS_MEDIA_ERR_SOCKET_CONN;
322 req_manager = (dcmReq *)g_queue_pop_head(g_manage_queue);
324 if (req_manager == NULL) {
325 MSAPI_DBG_ERR("queue pop fail");
326 g_io_channel_shutdown(channel, TRUE, NULL);
327 g_io_channel_unref(channel);
328 ms_ipc_delete_client_socket(&sock_info);
329 return MS_MEDIA_ERR_INVALID_PARAMETER;
332 GSource *source = NULL;
333 source = g_io_create_watch(channel, G_IO_IN);
334 g_source_set_callback(source, (GSourceFunc)__media_dcm_write_socket, req_manager->userData, NULL);
335 source_id = g_source_attach(source, g_main_context_get_thread_default());
339 memset((void *)&req_msg, 0, sizeof(dcmMsg));
341 req_msg.pid = getpid();
342 req_msg.msg_type = req_manager->msg_type;
343 req_msg.uid = req_manager->uid;
344 strncpy(req_msg.msg, req_manager->path, sizeof(req_msg.msg));
345 req_msg.msg[strlen(req_msg.msg)] = '\0';
346 req_msg.msg_size = strlen(req_msg.msg) + 1;
348 if (send(sock, &req_msg, sizeof(req_msg), 0) != sizeof(req_msg)) {
349 MSAPI_DBG_STRERROR("send failed");
351 g_source_destroy(g_main_context_find_source_by_id(g_main_context_get_thread_default(), source_id));
352 g_io_channel_shutdown(channel, TRUE, NULL);
353 g_io_channel_unref(channel);
354 ms_ipc_delete_client_socket(&sock_info);
355 return MS_MEDIA_ERR_SOCKET_SEND;
358 MSAPI_DBG("Sending msg to dcm service is successful");
361 if (req_manager->msg_type == DCM_REQUEST_MEDIA/*DCM_REQUEST_INSERT_FACE*/) {
362 if (g_request_queue == NULL) {
363 g_request_queue = g_queue_new();
366 dcmReq *dcm_req = calloc(1, sizeof(dcmReq));
367 if (dcm_req == NULL) {
368 MSAPI_DBG_ERR("Failed to create request element");
369 return MS_MEDIA_ERR_INVALID_PARAMETER;
372 dcm_req->channel = channel;
373 dcm_req->path = strdup(req_manager->path);
374 dcm_req->source_id = source_id;
375 dcm_req->userData = req_manager->userData;
377 g_queue_push_tail(g_request_queue, (gpointer)dcm_req);
383 int _media_dcm_request(int msg_type, const char *path, uid_t uid)
386 struct sockaddr_un serv_addr;
387 ms_sock_info_s sock_info;
388 int err = MS_MEDIA_ERR_NONE;
390 sock_info.port = MS_DCM_CREATOR_PORT;
392 err = ms_ipc_create_client_socket(MS_PROTOCOL_TCP, MS_TIMEOUT_SEC_60, &sock_info);
393 if (err != MS_MEDIA_ERR_NONE) {
394 MSAPI_DBG_ERR("ms_ipc_create_client_socket failed");
398 memset(&serv_addr, 0, sizeof(serv_addr));
399 sock = sock_info.sock_fd;
400 serv_addr.sun_family = AF_UNIX;
401 strncpy(serv_addr.sun_path, tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[sock_info.port]), strlen(tzplatform_mkpath(TZ_SYS_RUN, MEDIA_IPC_PATH[sock_info.port])));
403 /* Connecting to the dcm service */
404 if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
405 MSAPI_DBG_STRERROR("connect");
406 ms_ipc_delete_client_socket(&sock_info);
407 return MS_MEDIA_ERR_SOCKET_CONN;
413 memset((void *)&req_msg, 0, sizeof(dcmMsg));
414 memset((void *)&recv_msg, 0, sizeof(dcmMsg));
416 /* Get PID of client*/
420 /* Set requset message */
421 req_msg.msg_type = msg_type;
424 req_msg.msg_size = strlen(path);
425 memcpy(req_msg.msg, path, strlen(path));
426 req_msg.msg[strlen(path)+1] = '\0';
429 if (req_msg.msg_size > DCM_MSG_MAX_SIZE) {
430 MSAPI_DBG_ERR("path's length exceeds %d", DCM_MSG_MAX_SIZE);
431 ms_ipc_delete_client_socket(&sock_info);
432 return MS_MEDIA_ERR_INVALID_PARAMETER;
435 if (send(sock, &req_msg, sizeof(dcmMsg), 0) != sizeof(dcmMsg)) {
436 MSAPI_DBG_STRERROR("sendto failed");
437 ms_ipc_delete_client_socket(&sock_info);
438 return MS_MEDIA_ERR_SOCKET_SEND;
441 MSAPI_DBG("Sending msg to dcm service is successful");
443 if ((err = recv(sock, &recv_msg, sizeof(dcmMsg), 0)) < 0) {
444 MSAPI_DBG_ERR("recv failed ");
445 ms_ipc_delete_client_socket(&sock_info);
446 return MS_MEDIA_ERR_SOCKET_RECEIVE;
449 MSAPI_DBG("recv %d from dcm service is successful", recv_msg.msg_type);
451 ms_ipc_delete_client_socket(&sock_info);
453 return MS_MEDIA_ERR_NONE;
456 int _media_dcm_request_async(int msg_type, const unsigned int request_id, const char *path, faceUserData *userData, uid_t uid)
458 int err = MS_MEDIA_ERR_NONE;
460 MSAPI_DBG("Path : %s", path);
462 if (g_manage_queue == NULL) {
463 MSAPI_DBG("g_manage_queue is NULL");
464 if (msg_type == DCM_REQUEST_CANCEL_FACE)
465 return MS_MEDIA_ERR_INTERNAL;
467 g_manage_queue = g_queue_new();
469 dcmReq *dcm_req = NULL;
470 dcm_req = calloc(1, sizeof(dcmReq));
471 if (dcm_req == NULL) {
472 MSAPI_DBG_ERR("Failed to create request element");
473 return MS_MEDIA_ERR_INVALID_PARAMETER;
476 dcm_req->msg_type = msg_type;
477 dcm_req->path = strdup(path);
478 dcm_req->userData = userData;
479 dcm_req->isCanceled = FALSE;
480 dcm_req->request_id = request_id;
483 MSAPI_DBG("Enqueue");
484 g_queue_push_tail(g_manage_queue, (gpointer)dcm_req);
486 /* directly request at first time */
487 err = _media_dcm_send_request();
490 MSAPI_DBG("g_manage_queue is not NULL");
491 if (msg_type != DCM_REQUEST_CANCEL_FACE) {
493 dcmReq *dcm_req = NULL;
494 dcm_req = calloc(1, sizeof(dcmReq));
495 if (dcm_req == NULL) {
496 MSAPI_DBG_ERR("Failed to create request element");
497 return MS_MEDIA_ERR_INVALID_PARAMETER;
500 dcm_req->msg_type = msg_type;
501 dcm_req->path = strdup(path);
502 dcm_req->userData = userData;
503 dcm_req->isCanceled = FALSE;
504 dcm_req->request_id = request_id;
507 MSAPI_DBG("Enqueue");
508 g_queue_push_tail(g_manage_queue, (gpointer)dcm_req);
511 MSAPI_DBG("Dequeue");
512 err = __media_dcm_pop_manage_queue(request_id, path);
519 int dcm_request_extract_all(uid_t uid)
521 int err = MS_MEDIA_ERR_NONE;
523 /* Request for image file to the daemon "Dcm generator" */
524 err = _media_dcm_request(DCM_REQUEST_ALL_MEDIA, NULL, uid);
525 if (err != MS_MEDIA_ERR_NONE) {
526 MSAPI_DBG_ERR("_media_dcm_request failed : %d", err);
530 return MS_MEDIA_ERR_NONE;
533 int dcm_request_extract_media(const char *path, uid_t uid)
535 int err = MS_MEDIA_ERR_NONE;
537 /* Request for image file to the daemon "Dcm generator" */
538 err = _media_dcm_request(DCM_REQUEST_MEDIA, path, uid);
539 if (err != MS_MEDIA_ERR_NONE) {
540 MSAPI_DBG_ERR("_media_dcm_request failed : %d", err);
544 return MS_MEDIA_ERR_NONE;
547 int dcm_request_extract_face_async(const unsigned int request_id, const char *path, FaceFunc func, void *user_data, uid_t uid)
549 int err = MS_MEDIA_ERR_NONE;
553 MSAPI_DBG_ERR("Invalid parameter");
554 return MS_MEDIA_ERR_INVALID_PARAMETER;
557 exist = open(path, O_RDONLY);
559 MSAPI_DBG_ERR("The path(%s) doesn't exist.", path);
560 if (errno == EACCES || errno == EPERM)
561 return MS_MEDIA_ERR_PERMISSION_DENIED;
563 return MS_MEDIA_ERR_INVALID_PARAMETER;
567 MSAPI_DBG("Path : %s", path);
570 store_type = __media_dcm_get_store_type_by_path(path);
572 if ((store_type != DCM_PHONE) && (store_type != DCM_MMC)) {
573 MSAPI_DBG_ERR("The path(%s) is invalid", path);
574 return MS_MEDIA_ERR_INVALID_PARAMETER;
577 MSAPI_DBG("Path : %s", path);
579 faceUserData *userData = (faceUserData*)malloc(sizeof(faceUserData));
580 if (userData == NULL) {
581 MSAPI_DBG_ERR("memory allocation failed");
582 return MS_MEDIA_ERR_OUT_OF_MEMORY;
584 userData->func = (FaceFunc)func;
585 userData->user_data = user_data;
587 /* Request for image file to the daemon "Dcm generator" */
588 err = _media_dcm_request_async(DCM_REQUEST_MEDIA/*DCM_REQUEST_INSERT_FACE*/, request_id, path, userData, uid);
589 if (err != MS_MEDIA_ERR_NONE) {
590 MSAPI_DBG_ERR("_media_dcm_request failed : %d", err);
594 return MS_MEDIA_ERR_NONE;
597 int dcm_request_cancel_face(const unsigned int request_id, const char *path)
599 int err = MS_MEDIA_ERR_NONE;
601 /* Request for image file to the daemon "Dcm generator" */
602 err = _media_dcm_request_async(DCM_REQUEST_CANCEL_FACE, request_id, path, NULL, request_id);
603 if (err != MS_MEDIA_ERR_NONE) {
604 MSAPI_DBG_ERR("_media_dcm_request failed : %d", err);
608 return MS_MEDIA_ERR_NONE;