Minor changes
[platform/core/multimedia/media-server.git] / lib / media-util-register.c
1 /*
2  * Media Utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <unistd.h>
23 #include <sys/syscall.h>
24
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>
30
31 static GMutex scan_req_mutex;
32
33 typedef struct media_scan_data {
34         GIOChannel *channel;
35         scan_complete_cb user_callback;
36         int pid;
37         guint source_id;
38         char *req_path;
39         void *user_data;
40 } media_scan_data;
41
42 static GSList *req_list;
43
44 static int __check_dir_path(const char *dir_path, uid_t uid)
45 {
46         int ret = MS_MEDIA_ERR_NONE;
47         ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
48
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");
51
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");
56         }
57
58         return MS_MEDIA_ERR_NONE;
59 }
60
61 static gint __find_req_item(gconstpointer data, gconstpointer compare)
62 {
63         return g_strcmp0(((media_scan_data *)data)->req_path, (const char *)compare);
64 }
65
66 /* receive message from media-server[function : ms_receive_message_from_scanner] */
67 static gboolean __read_socket(GIOChannel *channel, GIOCondition condition, gpointer data)
68 {
69         ms_comm_msg_s recv_msg = {0, };
70         media_request_result_s req_result = {0, };
71         int sockfd = -1;
72         media_scan_data *req_data = NULL;
73         GSList *found = NULL;
74
75         sockfd = g_io_channel_unix_get_fd(channel);
76         if (sockfd < 0) {
77                 MSAPI_DBG("sock fd is invalid!");
78                 return G_SOURCE_REMOVE;
79         }
80
81         if (read(sockfd, &recv_msg, sizeof(ms_comm_msg_s)) < 0) {
82                 MSAPI_DBG_STRERROR("recv failed");
83                 return G_SOURCE_REMOVE;
84         }
85
86         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(recv_msg.msg), G_SOURCE_REMOVE, "Invalid msg");
87
88         switch (recv_msg.msg_type) {
89         case MS_MSG_SCANNER_RESULT:
90                 req_result.request_type = MEDIA_DIRECTORY_SCAN;
91                 break;
92         case MS_MSG_SCANNER_BULK_RESULT:
93                 req_result.request_type = MEDIA_FILES_REGISTER;
94                 break;
95         case MS_MSG_SCANNER_COMPLETE:
96                 req_result.request_type = MEDIA_REQUEST_SCAN_COMPLETE;
97                 break;
98         case MS_MSG_SCANNER_PARTIAL:
99                 req_result.request_type = MEDIA_REQUEST_SCAN_PARTIAL;
100                 break;
101         case MS_MSG_RECURSIVE_START:
102                 req_result.request_type = MEDIA_RECURSIVE_START;
103                 break;
104         case MS_MSG_EXTRACTOR_COMPLETE:
105                 req_result.request_type = MEDIA_REQUEST_EXTRACT_COMPLETE;
106                 break;
107         default:
108                 MSAPI_DBG("Invalid msg_type[%d]", recv_msg.msg_type);
109                 return G_SOURCE_REMOVE;
110         }
111
112
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);
115
116         /*NEED MUTEX*/
117         g_mutex_lock(&scan_req_mutex);
118
119         found = g_slist_find_custom(req_list, recv_msg.msg, __find_req_item);
120         if (!found) {
121                 g_mutex_unlock(&scan_req_mutex);
122                 MSAPI_DBG("Not in scan queue :%s", recv_msg.msg);
123                 return G_SOURCE_REMOVE;
124         }
125
126         req_data = (media_scan_data *)found->data;
127
128         req_result.complete_path = recv_msg.msg;
129         req_result.pid = recv_msg.pid;
130         req_result.result = recv_msg.result;
131
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) {
135
136                 (req_data->user_callback)(&req_result, req_data->user_data);
137                 g_free(req_data->req_path);
138                 g_free(req_data);
139                 req_list = g_slist_delete_link(req_list, found);
140
141                 g_mutex_unlock(&scan_req_mutex);
142
143                 MSAPI_DBG("REMOVE OK");
144
145                 return G_SOURCE_REMOVE;
146         }
147
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);
151
152         return G_SOURCE_CONTINUE;
153 }
154
155 static void __add_request(media_scan_data *scan_data)
156 {
157         /* NEED MUTEX */
158         g_mutex_lock(&scan_req_mutex);
159
160         req_list = g_slist_append(req_list, scan_data);
161
162         g_mutex_unlock(&scan_req_mutex);
163 }
164
165 static int __remove_request(const char *req_path)
166 {
167         media_scan_data *req_data = NULL;
168         media_request_result_s req_result;
169         GSList *found = NULL;
170
171          /*NEED MUTEX*/
172         g_mutex_lock(&scan_req_mutex);
173
174         found = g_slist_find_custom(req_list, req_path, __find_req_item);
175         if (!found) {
176                 MSAPI_DBG("Not in scan queue :%s", req_path);
177                 g_mutex_unlock(&scan_req_mutex);
178                 return MS_MEDIA_ERR_INVALID_PARAMETER;
179         }
180
181         req_data = (media_scan_data *)found->data;
182
183         req_result.pid = -1;
184         req_result.result = MS_MEDIA_ERR_NONE;
185         req_result.complete_path = (char *)req_path;
186         req_result.request_type = MEDIA_FILES_REGISTER;
187
188         /*call user define function*/
189         MSAPI_DBG("Call Cancel Callback");
190         (req_data->user_callback)(&req_result, req_data->user_data);
191
192         g_source_remove(req_data->source_id);
193
194         g_free(req_data->req_path);
195         g_free(req_data);
196         req_list = g_slist_delete_link(req_list, found);
197
198         MSAPI_DBG("CANCEL OK");
199
200         g_mutex_unlock(&scan_req_mutex);
201
202         return MS_MEDIA_ERR_NONE;
203 }
204
205 static void __attach_callback(const char *req_path, int *sockfd, scan_complete_cb user_callback, void *user_data)
206 {
207         GIOChannel *channel = NULL;
208         media_scan_data *data = NULL;
209         guint source_id = 0;
210
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);
217
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;
223
224         __add_request(data);
225 }
226
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,
231                                                                                         void *user_data,
232                                                                                         uid_t uid)
233 {
234         int ret = MS_MEDIA_ERR_NONE;
235         int request_msg_size = 0;
236         int sockfd = -1;
237         ms_comm_msg_s send_msg;
238         char *request_path = NULL;
239
240         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
241
242         MSAPI_DBG_SLOG("REQUEST UPDATE ASYNC [%d][%s]", msg_type, request_msg);
243
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;
248         } else {
249                 request_path = g_strdup(request_msg);
250         }
251
252         MSAPI_DBG_SLOG("querysize[%d] path[%s] query[%s]", request_msg_size, request_msg, request_path);
253
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);
257         send_msg.uid = uid;
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));
261
262         /*Create Socket*/
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);
267                 return ret;
268         }
269
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);
274                 close(sockfd);
275                 return ret;
276         }
277
278         __attach_callback(request_path, &sockfd, user_callback, user_data);
279         MS_SAFE_FREE(request_path);
280
281         return ret;
282 }
283
284 static int __media_db_request_update_cancel(ms_msg_type_e msg_type, const char *request_msg)
285 {
286         int ret = MS_MEDIA_ERR_NONE;
287         int request_msg_size = 0;
288         int sockfd = -1;
289         ms_comm_msg_s send_msg;
290         char *request_path = NULL;
291
292         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
293
294         MSAPI_DBG("REQUEST CANCEL DIRECTORY SCANNING[%s]", request_msg);
295
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;
300         } else {
301                 request_path = g_strdup(request_msg);
302         }
303
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));
308
309         /*Create Socket*/
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);
314                 return ret;
315         }
316
317         ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
318         close(sockfd);
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);
322                 return ret;
323         }
324
325         ret = __remove_request(request_path);
326         MS_SAFE_FREE(request_path);
327
328         return ret;
329 }
330
331 int media_directory_scanning_async(const char *directory_path,
332                                                                         const char *storage_id,
333                                                                         bool recursive_on,
334                                                                         scan_complete_cb user_callback,
335                                                                         void *user_data,
336                                                                         uid_t uid)
337 {
338         int ret = MS_MEDIA_ERR_NONE;
339
340         ret = __check_dir_path(directory_path, uid);
341         MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
342
343         if (recursive_on)
344                 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING, storage_id, directory_path, user_callback, user_data, uid);
345         else
346                 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE, storage_id, directory_path, user_callback, user_data, uid);
347
348         return ret;
349 }
350
351 int media_directory_scanning_cancel(const char *directory_path, uid_t uid)
352 {
353         int ret = MS_MEDIA_ERR_NONE;
354
355         ret = __check_dir_path(directory_path, uid);
356         MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
357
358         ret = __media_db_request_update_cancel(MS_MSG_DIRECTORY_SCANNING_CANCEL, directory_path);
359
360         return ret;
361 }
362
363 int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data, uid_t uid)
364 {
365         return __media_db_request_update_async(MS_MSG_BULK_INSERT, NULL, list_path, user_callback, user_data, uid);
366 }