4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include <sys/syscall.h>
23 #include "media-util-dbg.h"
24 #include "media-util.h"
26 static GMutex scan_req_mutex;
28 typedef struct media_scan_data {
30 scan_complete_cb user_callback;
37 static GSList *req_list;
39 static int __check_dir_path(const char *dir_path, uid_t uid)
41 int ret = MS_MEDIA_ERR_NONE;
42 ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
44 ret = ms_user_get_storage_type(uid, dir_path, &storage_type);
45 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid path");
47 /* dir_path can be a deleted path. */
48 if (g_file_test(dir_path, G_FILE_TEST_EXISTS)) {
49 /* Check only exist */
50 MSAPI_RETVM_IF(!g_file_test(dir_path, G_FILE_TEST_IS_DIR), MS_MEDIA_ERR_INVALID_PARAMETER, "Not a directory");
53 return MS_MEDIA_ERR_NONE;
56 static gint __find_req_item(gconstpointer data, gconstpointer compare)
58 return g_strcmp0(((media_scan_data *)data)->req_path, (const char *)compare);
61 /* receive message from media-server[function : ms_receive_message_from_scanner] */
62 static gboolean __read_socket(GIOChannel *channel, GIOCondition condition, gpointer data)
64 ms_comm_msg_s recv_msg = {0, };
65 media_request_result_s req_result = {0, };
67 media_scan_data *req_data = NULL;
70 sockfd = g_io_channel_unix_get_fd(channel);
72 MSAPI_DBG("sock fd is invalid!");
73 return G_SOURCE_REMOVE;
76 if (read(sockfd, &recv_msg, sizeof(ms_comm_msg_s)) < 0) {
77 MSAPI_DBG_STRERROR("recv failed");
78 return G_SOURCE_REMOVE;
81 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(recv_msg.msg), G_SOURCE_REMOVE, "Invalid msg");
83 switch (recv_msg.msg_type) {
84 case MS_MSG_SCANNER_RESULT:
85 req_result.request_type = MEDIA_DIRECTORY_SCAN;
87 case MS_MSG_SCANNER_BULK_RESULT:
88 req_result.request_type = MEDIA_FILES_REGISTER;
90 case MS_MSG_SCANNER_COMPLETE:
91 req_result.request_type = MEDIA_REQUEST_SCAN_COMPLETE;
93 case MS_MSG_SCANNER_PARTIAL:
94 req_result.request_type = MEDIA_REQUEST_SCAN_PARTIAL;
96 case MS_MSG_RECURSIVE_START:
97 req_result.request_type = MEDIA_RECURSIVE_START;
99 case MS_MSG_EXTRACTOR_COMPLETE:
100 req_result.request_type = MEDIA_REQUEST_EXTRACT_COMPLETE;
103 MSAPI_DBG("Invalid msg_type[%d]", recv_msg.msg_type);
104 return G_SOURCE_REMOVE;
108 MSAPI_DBG_SLOG("complete_path :%s", recv_msg.msg);
109 MSAPI_DBG("pid[%d] result[%d] request_type[%d]", recv_msg.pid, recv_msg.result, req_result.request_type);
112 g_mutex_lock(&scan_req_mutex);
114 found = g_slist_find_custom(req_list, recv_msg.msg, __find_req_item);
116 g_mutex_unlock(&scan_req_mutex);
117 MSAPI_DBG("Not in scan queue :%s", recv_msg.msg);
118 return G_SOURCE_REMOVE;
121 req_data = (media_scan_data *)found->data;
123 req_result.complete_path = recv_msg.msg;
124 req_result.pid = recv_msg.pid;
125 req_result.result = recv_msg.result;
127 if (recv_msg.msg_type != MS_MSG_SCANNER_COMPLETE &&
128 recv_msg.msg_type != MS_MSG_SCANNER_PARTIAL &&
129 recv_msg.msg_type != MS_MSG_RECURSIVE_START) {
131 (req_data->user_callback)(&req_result, req_data->user_data);
132 g_free(req_data->req_path);
134 req_list = g_slist_delete_link(req_list, found);
136 g_mutex_unlock(&scan_req_mutex);
138 MSAPI_DBG("REMOVE OK");
140 return G_SOURCE_REMOVE;
143 /*call user define function. Scanner V2 case only*/
144 (req_data->user_callback)(&req_result, req_data->user_data);
145 g_mutex_unlock(&scan_req_mutex);
147 return G_SOURCE_CONTINUE;
150 static void __add_request(media_scan_data *scan_data)
153 g_mutex_lock(&scan_req_mutex);
155 req_list = g_slist_append(req_list, scan_data);
157 g_mutex_unlock(&scan_req_mutex);
160 static int __remove_request(const char *req_path)
162 media_scan_data *req_data = NULL;
163 media_request_result_s req_result;
164 GSList *found = NULL;
167 g_mutex_lock(&scan_req_mutex);
169 found = g_slist_find_custom(req_list, req_path, __find_req_item);
171 MSAPI_DBG("Not in scan queue :%s", req_path);
172 g_mutex_unlock(&scan_req_mutex);
173 return MS_MEDIA_ERR_INVALID_PARAMETER;
176 req_data = (media_scan_data *)found->data;
179 req_result.result = MS_MEDIA_ERR_NONE;
180 req_result.complete_path = (char *)req_path;
181 req_result.request_type = MEDIA_FILES_REGISTER;
183 /*call user define function*/
184 MSAPI_DBG("Call Cancel Callback");
185 (req_data->user_callback)(&req_result, req_data->user_data);
187 g_source_remove(req_data->source_id);
189 g_free(req_data->req_path);
191 req_list = g_slist_delete_link(req_list, found);
193 MSAPI_DBG("CANCEL OK");
195 g_mutex_unlock(&scan_req_mutex);
197 return MS_MEDIA_ERR_NONE;
200 static void __attach_callback(const char *req_path, int *sockfd, scan_complete_cb user_callback, void *user_data)
202 GIOChannel *channel = NULL;
203 media_scan_data *data = NULL;
206 data = g_new0(media_scan_data, 1);
207 /* Create new channel to watch socket */
208 channel = g_io_channel_unix_new(*sockfd);
209 g_io_channel_set_close_on_unref(channel, TRUE);
210 source_id = g_io_add_watch(channel, G_IO_IN, __read_socket, NULL);
211 g_io_channel_unref(channel);
213 data->user_callback = user_callback;
214 data->user_data = user_data;
215 data->req_path = g_strdup(req_path);
216 data->channel = channel;
217 data->source_id = source_id;
222 static int __media_db_request_update_async(ms_msg_type_e msg_type,
223 const char *storage_id,
224 const char *request_msg,
225 scan_complete_cb user_callback,
229 int ret = MS_MEDIA_ERR_NONE;
230 int request_msg_size = 0;
232 ms_comm_msg_s send_msg;
233 char *request_path = NULL;
235 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
237 MSAPI_DBG_SLOG("REQUEST UPDATE ASYNC [%d][%s]", msg_type, request_msg);
239 request_msg_size = strlen(request_msg);
240 if (request_msg[request_msg_size - 1] == '/') {
241 request_path = g_strndup(request_msg, request_msg_size - 1);
242 request_msg_size = request_msg_size - 1;
244 request_path = g_strdup(request_msg);
247 MSAPI_DBG_SLOG("querysize[%d] path[%s] query[%s]", request_msg_size, request_msg, request_path);
249 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
250 send_msg.msg_type = msg_type;
251 send_msg.pid = syscall(__NR_getpid);
253 SAFE_STRLCPY(send_msg.msg, request_path, sizeof(send_msg.msg));
254 if (MS_STRING_VALID(storage_id))
255 SAFE_STRLCPY(send_msg.storage_id, storage_id, sizeof(send_msg.storage_id));
258 ret = ms_ipc_create_client_socket(0, &sockfd);
259 if (ret != MS_MEDIA_ERR_NONE) {
260 MSAPI_DBG_ERR("ms_ipc_create_client_socket failed : %d", ret);
261 MS_SAFE_FREE(request_path);
265 ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
266 if (ret != MS_MEDIA_ERR_NONE) {
267 MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
268 MS_SAFE_FREE(request_path);
273 __attach_callback(request_path, &sockfd, user_callback, user_data);
274 MS_SAFE_FREE(request_path);
279 static int __media_db_request_update_cancel(ms_msg_type_e msg_type, const char *request_msg)
281 int ret = MS_MEDIA_ERR_NONE;
282 int request_msg_size = 0;
284 ms_comm_msg_s send_msg;
285 char *request_path = NULL;
287 MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
289 MSAPI_DBG("REQUEST CANCEL DIRECTORY SCANNING[%s]", request_msg);
291 request_msg_size = strlen(request_msg);
292 if (request_msg[request_msg_size - 1] == '/') {
293 request_path = g_strndup(request_msg, request_msg_size - 1);
294 request_msg_size = request_msg_size - 1;
296 request_path = g_strdup(request_msg);
299 memset((void *)&send_msg, 0, sizeof(ms_comm_msg_s));
300 send_msg.msg_type = msg_type;
301 send_msg.pid = syscall(__NR_getpid);
302 SAFE_STRLCPY(send_msg.msg, request_path, sizeof(send_msg.msg));
305 ret = ms_ipc_create_client_socket(0, &sockfd);
306 if (ret != MS_MEDIA_ERR_NONE) {
307 MSAPI_DBG_ERR("ms_ipc_create_client_socket failed : %d", ret);
308 MS_SAFE_FREE(request_path);
312 ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
314 if (ret != MS_MEDIA_ERR_NONE) {
315 MSAPI_DBG_ERR("ms_ipc_send_msg_to_server failed : %d", ret);
316 MS_SAFE_FREE(request_path);
320 ret = __remove_request(request_path);
321 MS_SAFE_FREE(request_path);
326 int media_directory_scanning_async(const char *directory_path,
327 const char *storage_id,
329 scan_complete_cb user_callback,
333 int ret = MS_MEDIA_ERR_NONE;
335 ret = __check_dir_path(directory_path, uid);
336 MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
339 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING, storage_id, directory_path, user_callback, user_data, uid);
341 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE, storage_id, directory_path, user_callback, user_data, uid);
346 int media_directory_scanning_cancel(const char *directory_path, uid_t uid)
348 return __media_db_request_update_cancel(MS_MSG_DIRECTORY_SCANNING_CANCEL, directory_path);
351 int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data, uid_t uid)
353 return __media_db_request_update_async(MS_MSG_BULK_INSERT, NULL, list_path, user_callback, user_data, uid);