4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Yong Yeon Kim <yy9875.kim@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.
23 #include <sys/syscall.h>
25 #include "media-server-ipc.h"
26 #include "media-util-internal.h"
27 #include "media-util-dbg.h"
28 #include "media-util.h"
29 #include <system_info.h>
31 static GMutex scan_req_mutex;
33 typedef struct media_scan_data {
35 scan_complete_cb user_callback;
42 static GSList *req_list;
44 static int __check_dir_path(const char *dir_path, uid_t uid)
46 int ret = MS_MEDIA_ERR_NONE;
47 ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
49 ret = ms_user_get_storage_type(uid, dir_path, &storage_type);
50 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
52 /* dir_path can be a deleted path. */
53 if (g_file_test(dir_path, G_FILE_TEST_EXISTS)) {
54 /* Check only exist */
55 MSAPI_RETVM_IF(!g_file_test(dir_path, G_FILE_TEST_IS_DIR), MS_MEDIA_ERR_INVALID_PARAMETER, "Not a directory");
58 return MS_MEDIA_ERR_NONE;
61 static gint __find_req_item(gconstpointer data, gconstpointer compare)
63 return g_strcmp0(((media_scan_data *)data)->req_path, (const char *)compare);
66 /* receive message from media-server[function : ms_receive_message_from_scanner] */
67 static gboolean __read_socket(GIOChannel *channel, GIOCondition condition, gpointer data)
69 ms_comm_msg_s recv_msg = {0, };
70 media_request_result_s req_result = {0, };
72 media_scan_data *req_data = NULL;
75 sockfd = g_io_channel_unix_get_fd(channel);
77 MSAPI_DBG("sock fd is invalid!");
78 return G_SOURCE_REMOVE;
81 if (read(sockfd, &recv_msg, sizeof(ms_comm_msg_s)) < 0) {
82 MSAPI_DBG_STRERROR("recv failed");
83 return G_SOURCE_REMOVE;
86 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(recv_msg.msg), G_SOURCE_REMOVE, "Invalid msg");
88 switch (recv_msg.msg_type) {
89 case MS_MSG_SCANNER_RESULT:
90 req_result.request_type = MEDIA_DIRECTORY_SCAN;
92 case MS_MSG_SCANNER_BULK_RESULT:
93 req_result.request_type = MEDIA_FILES_REGISTER;
95 case MS_MSG_SCANNER_COMPLETE:
96 req_result.request_type = MEDIA_REQUEST_SCAN_COMPLETE;
98 case MS_MSG_SCANNER_PARTIAL:
99 req_result.request_type = MEDIA_REQUEST_SCAN_PARTIAL;
101 case MS_MSG_RECURSIVE_START:
102 req_result.request_type = MEDIA_RECURSIVE_START;
104 case MS_MSG_EXTRACTOR_COMPLETE:
105 req_result.request_type = MEDIA_REQUEST_EXTRACT_COMPLETE;
108 MSAPI_DBG("Invalid msg_type[%d]", recv_msg.msg_type);
109 return G_SOURCE_REMOVE;
113 MSAPI_DBG_SLOG("complete_path :%s", recv_msg.msg);
114 MSAPI_DBG("pid[%d] result[%d] request_type[%d]", recv_msg.pid, recv_msg.result, req_result.request_type);
117 g_mutex_lock(&scan_req_mutex);
119 found = g_slist_find_custom(req_list, recv_msg.msg, __find_req_item);
121 g_mutex_unlock(&scan_req_mutex);
122 MSAPI_DBG("Not in scan queue :%s", recv_msg.msg);
123 return G_SOURCE_REMOVE;
126 req_data = (media_scan_data *)found->data;
128 req_result.complete_path = recv_msg.msg;
129 req_result.pid = recv_msg.pid;
130 req_result.result = recv_msg.result;
132 if (recv_msg.msg_type != MS_MSG_SCANNER_COMPLETE &&
133 recv_msg.msg_type != MS_MSG_SCANNER_PARTIAL &&
134 recv_msg.msg_type != MS_MSG_RECURSIVE_START) {
136 (req_data->user_callback)(&req_result, req_data->user_data);
137 g_free(req_data->req_path);
139 req_list = g_slist_delete_link(req_list, found);
141 g_mutex_unlock(&scan_req_mutex);
143 MSAPI_DBG("REMOVE OK");
145 return G_SOURCE_REMOVE;
148 /*call user define function. Scanner V2 case only*/
149 (req_data->user_callback)(&req_result, req_data->user_data);
150 g_mutex_unlock(&scan_req_mutex);
152 return G_SOURCE_CONTINUE;
155 static void __add_request(media_scan_data *scan_data)
158 g_mutex_lock(&scan_req_mutex);
160 req_list = g_slist_append(req_list, scan_data);
162 g_mutex_unlock(&scan_req_mutex);
165 static int __remove_request(const char *req_path)
167 media_scan_data *req_data = NULL;
168 media_request_result_s req_result;
169 GSList *found = NULL;
172 g_mutex_lock(&scan_req_mutex);
174 found = g_slist_find_custom(req_list, req_path, __find_req_item);
176 MSAPI_DBG("Not in scan queue :%s", req_path);
177 g_mutex_unlock(&scan_req_mutex);
178 return MS_MEDIA_ERR_INVALID_PARAMETER;
181 req_data = (media_scan_data *)found->data;
184 req_result.result = MS_MEDIA_ERR_NONE;
185 req_result.complete_path = (char *)req_path;
186 req_result.request_type = MEDIA_FILES_REGISTER;
188 /*call user define function*/
189 MSAPI_DBG("Call Cancel Callback");
190 (req_data->user_callback)(&req_result, req_data->user_data);
192 g_source_remove(req_data->source_id);
194 g_free(req_data->req_path);
196 req_list = g_slist_delete_link(req_list, found);
198 MSAPI_DBG("CANCEL OK");
200 g_mutex_unlock(&scan_req_mutex);
202 return MS_MEDIA_ERR_NONE;
205 static void __attach_callback(const char *req_path, int *sockfd, scan_complete_cb user_callback, void *user_data)
207 GIOChannel *channel = NULL;
208 media_scan_data *data = NULL;
211 data = g_new0(media_scan_data, 1);
212 /* Create new channel to watch socket */
213 channel = g_io_channel_unix_new(*sockfd);
214 g_io_channel_set_close_on_unref(channel, TRUE);
215 source_id = g_io_add_watch(channel, G_IO_IN, __read_socket, NULL);
216 g_io_channel_unref(channel);
218 data->user_callback = user_callback;
219 data->user_data = user_data;
220 data->req_path = g_strdup(req_path);
221 data->channel = channel;
222 data->source_id = source_id;
227 static int __media_db_request_update_async(ms_msg_type_e msg_type,
228 const char *storage_id,
229 const char *request_msg,
230 scan_complete_cb user_callback,
234 int ret = MS_MEDIA_ERR_NONE;
235 int request_msg_size = 0;
237 ms_comm_msg_s send_msg;
238 char *request_path = NULL;
240 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
242 MSAPI_DBG("REQUEST UPDATE ASYNC [%d][%s]", msg_type, request_msg);
244 request_msg_size = strlen(request_msg);
245 if (request_msg[request_msg_size - 1] == '/') {
246 request_path = g_strndup(request_msg, request_msg_size - 1);
247 request_msg_size = request_msg_size - 1;
249 request_path = g_strdup(request_msg);
252 MSAPI_DBG("querysize[%d] path[%s] query[%s]", request_msg_size, request_msg, request_path);
254 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
255 send_msg.msg_type = msg_type;
256 send_msg.pid = syscall(__NR_getpid);
258 SAFE_STRLCPY(send_msg.msg, request_path, sizeof(send_msg.msg));
259 if (MS_STRING_VALID(storage_id))
260 SAFE_STRLCPY(send_msg.storage_id, storage_id, sizeof(send_msg.storage_id));
263 ret = ms_ipc_create_client_socket(0, &sockfd);
264 if (ret != MS_MEDIA_ERR_NONE) {
265 MSAPI_DBG_ERR("ms_ipc_create_client_socket failed : %d", ret);
266 MS_SAFE_FREE(request_path);
270 ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
271 if (ret != MS_MEDIA_ERR_NONE) {
272 MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
273 MS_SAFE_FREE(request_path);
278 __attach_callback(request_path, &sockfd, user_callback, user_data);
279 MS_SAFE_FREE(request_path);
284 static int __media_db_request_update_cancel(ms_msg_type_e msg_type, const char *request_msg)
286 int ret = MS_MEDIA_ERR_NONE;
287 int request_msg_size = 0;
289 ms_comm_msg_s send_msg;
290 char *request_path = NULL;
292 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
294 MSAPI_DBG("REQUEST CANCEL DIRECTORY SCANNING[%s]", request_msg);
296 request_msg_size = strlen(request_msg);
297 if (request_msg[request_msg_size - 1] == '/') {
298 request_path = g_strndup(request_msg, request_msg_size - 1);
299 request_msg_size = request_msg_size - 1;
301 request_path = g_strdup(request_msg);
304 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
305 send_msg.msg_type = msg_type;
306 send_msg.pid = syscall(__NR_getpid);
307 SAFE_STRLCPY(send_msg.msg, request_path, sizeof(send_msg.msg));
310 ret = ms_ipc_create_client_socket(0, &sockfd);
311 if (ret != MS_MEDIA_ERR_NONE) {
312 MSAPI_DBG_ERR("ms_ipc_create_client_socket failed : %d", ret);
313 MS_SAFE_FREE(request_path);
317 ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
319 if (ret != MS_MEDIA_ERR_NONE) {
320 MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
321 MS_SAFE_FREE(request_path);
325 ret = __remove_request(request_path);
326 MS_SAFE_FREE(request_path);
331 int media_directory_scanning_async(const char *directory_path,
332 const char *storage_id,
334 scan_complete_cb user_callback,
338 int ret = MS_MEDIA_ERR_NONE;
340 ret = __check_dir_path(directory_path, uid);
341 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
344 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING, storage_id, directory_path, user_callback, user_data, uid);
346 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE, storage_id, directory_path, user_callback, user_data, uid);
351 int media_directory_scanning_cancel(const char *directory_path, uid_t uid)
353 int ret = MS_MEDIA_ERR_NONE;
355 ret = __check_dir_path(directory_path, uid);
356 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
358 ret = __media_db_request_update_cancel(MS_MSG_DIRECTORY_SCANNING_CANCEL, directory_path);
363 int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data, uid_t uid)
365 return __media_db_request_update_async(MS_MSG_BULK_INSERT, NULL, list_path, user_callback, user_data, uid);