Remove media-util-internal.h
[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  * 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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <unistd.h>
21 #include <sys/syscall.h>
22
23 #include "media-util-dbg.h"
24 #include "media-util.h"
25
26 static GMutex scan_req_mutex;
27
28 typedef struct media_scan_data {
29         GIOChannel *channel;
30         scan_complete_cb user_callback;
31         int pid;
32         guint source_id;
33         char *req_path;
34         void *user_data;
35 } media_scan_data;
36
37 static GSList *req_list;
38
39 static int __check_dir_path(const char *dir_path, uid_t uid)
40 {
41         int ret = MS_MEDIA_ERR_NONE;
42         ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
43
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");
46
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");
51         }
52
53         return MS_MEDIA_ERR_NONE;
54 }
55
56 static gint __find_req_item(gconstpointer data, gconstpointer compare)
57 {
58         return g_strcmp0(((media_scan_data *)data)->req_path, (const char *)compare);
59 }
60
61 /* receive message from media-server[function : ms_receive_message_from_scanner] */
62 static gboolean __read_socket(GIOChannel *channel, GIOCondition condition, gpointer data)
63 {
64         ms_comm_msg_s recv_msg = {0, };
65         media_request_result_s req_result = {0, };
66         int sockfd = -1;
67         media_scan_data *req_data = NULL;
68         GSList *found = NULL;
69
70         sockfd = g_io_channel_unix_get_fd(channel);
71         if (sockfd < 0) {
72                 MSAPI_DBG("sock fd is invalid!");
73                 return G_SOURCE_REMOVE;
74         }
75
76         if (read(sockfd, &recv_msg, sizeof(ms_comm_msg_s)) < 0) {
77                 MSAPI_DBG_STRERROR("recv failed");
78                 return G_SOURCE_REMOVE;
79         }
80
81         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(recv_msg.msg), G_SOURCE_REMOVE, "Invalid msg");
82
83         switch (recv_msg.msg_type) {
84         case MS_MSG_SCANNER_RESULT:
85                 req_result.request_type = MEDIA_DIRECTORY_SCAN;
86                 break;
87         case MS_MSG_SCANNER_BULK_RESULT:
88                 req_result.request_type = MEDIA_FILES_REGISTER;
89                 break;
90         case MS_MSG_SCANNER_COMPLETE:
91                 req_result.request_type = MEDIA_REQUEST_SCAN_COMPLETE;
92                 break;
93         case MS_MSG_SCANNER_PARTIAL:
94                 req_result.request_type = MEDIA_REQUEST_SCAN_PARTIAL;
95                 break;
96         case MS_MSG_RECURSIVE_START:
97                 req_result.request_type = MEDIA_RECURSIVE_START;
98                 break;
99         case MS_MSG_EXTRACTOR_COMPLETE:
100                 req_result.request_type = MEDIA_REQUEST_EXTRACT_COMPLETE;
101                 break;
102         default:
103                 MSAPI_DBG("Invalid msg_type[%d]", recv_msg.msg_type);
104                 return G_SOURCE_REMOVE;
105         }
106
107
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);
110
111         /*NEED MUTEX*/
112         g_mutex_lock(&scan_req_mutex);
113
114         found = g_slist_find_custom(req_list, recv_msg.msg, __find_req_item);
115         if (!found) {
116                 g_mutex_unlock(&scan_req_mutex);
117                 MSAPI_DBG("Not in scan queue :%s", recv_msg.msg);
118                 return G_SOURCE_REMOVE;
119         }
120
121         req_data = (media_scan_data *)found->data;
122
123         req_result.complete_path = recv_msg.msg;
124         req_result.pid = recv_msg.pid;
125         req_result.result = recv_msg.result;
126
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) {
130
131                 (req_data->user_callback)(&req_result, req_data->user_data);
132                 g_free(req_data->req_path);
133                 g_free(req_data);
134                 req_list = g_slist_delete_link(req_list, found);
135
136                 g_mutex_unlock(&scan_req_mutex);
137
138                 MSAPI_DBG("REMOVE OK");
139
140                 return G_SOURCE_REMOVE;
141         }
142
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);
146
147         return G_SOURCE_CONTINUE;
148 }
149
150 static void __add_request(media_scan_data *scan_data)
151 {
152         /* NEED MUTEX */
153         g_mutex_lock(&scan_req_mutex);
154
155         req_list = g_slist_append(req_list, scan_data);
156
157         g_mutex_unlock(&scan_req_mutex);
158 }
159
160 static int __remove_request(const char *req_path)
161 {
162         media_scan_data *req_data = NULL;
163         media_request_result_s req_result;
164         GSList *found = NULL;
165
166          /*NEED MUTEX*/
167         g_mutex_lock(&scan_req_mutex);
168
169         found = g_slist_find_custom(req_list, req_path, __find_req_item);
170         if (!found) {
171                 MSAPI_DBG("Not in scan queue :%s", req_path);
172                 g_mutex_unlock(&scan_req_mutex);
173                 return MS_MEDIA_ERR_INVALID_PARAMETER;
174         }
175
176         req_data = (media_scan_data *)found->data;
177
178         req_result.pid = -1;
179         req_result.result = MS_MEDIA_ERR_NONE;
180         req_result.complete_path = (char *)req_path;
181         req_result.request_type = MEDIA_FILES_REGISTER;
182
183         /*call user define function*/
184         MSAPI_DBG("Call Cancel Callback");
185         (req_data->user_callback)(&req_result, req_data->user_data);
186
187         g_source_remove(req_data->source_id);
188
189         g_free(req_data->req_path);
190         g_free(req_data);
191         req_list = g_slist_delete_link(req_list, found);
192
193         MSAPI_DBG("CANCEL OK");
194
195         g_mutex_unlock(&scan_req_mutex);
196
197         return MS_MEDIA_ERR_NONE;
198 }
199
200 static void __attach_callback(const char *req_path, int *sockfd, scan_complete_cb user_callback, void *user_data)
201 {
202         GIOChannel *channel = NULL;
203         media_scan_data *data = NULL;
204         guint source_id = 0;
205
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);
212
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;
218
219         __add_request(data);
220 }
221
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,
226                                                                                         void *user_data,
227                                                                                         uid_t uid)
228 {
229         int ret = MS_MEDIA_ERR_NONE;
230         int request_msg_size = 0;
231         int sockfd = -1;
232         ms_comm_msg_s send_msg;
233         char *request_path = NULL;
234
235         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
236
237         MSAPI_DBG_SLOG("REQUEST UPDATE ASYNC [%d][%s]", msg_type, request_msg);
238
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;
243         } else {
244                 request_path = g_strdup(request_msg);
245         }
246
247         MSAPI_DBG_SLOG("querysize[%d] path[%s] query[%s]", request_msg_size, request_msg, request_path);
248
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);
252         send_msg.uid = uid;
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));
256
257         /*Create Socket*/
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);
262                 return ret;
263         }
264
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);
269                 close(sockfd);
270                 return ret;
271         }
272
273         __attach_callback(request_path, &sockfd, user_callback, user_data);
274         MS_SAFE_FREE(request_path);
275
276         return ret;
277 }
278
279 static int __media_db_request_update_cancel(ms_msg_type_e msg_type, const char *request_msg)
280 {
281         int ret = MS_MEDIA_ERR_NONE;
282         int request_msg_size = 0;
283         int sockfd = -1;
284         ms_comm_msg_s send_msg;
285         char *request_path = NULL;
286
287         MSAPI_RETVM_IF(!ms_ipc_is_valid_msg(request_msg), MS_MEDIA_ERR_INVALID_PARAMETER, "Invalid request_msg");
288
289         MSAPI_DBG("REQUEST CANCEL DIRECTORY SCANNING[%s]", request_msg);
290
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;
295         } else {
296                 request_path = g_strdup(request_msg);
297         }
298
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));
303
304         /*Create Socket*/
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);
309                 return ret;
310         }
311
312         ret = ms_ipc_send_msg_to_server_tcp(sockfd, MS_SCANNER_PORT, &send_msg, NULL);
313         close(sockfd);
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);
317                 return ret;
318         }
319
320         ret = __remove_request(request_path);
321         MS_SAFE_FREE(request_path);
322
323         return ret;
324 }
325
326 int media_directory_scanning_async(const char *directory_path,
327                                                                         const char *storage_id,
328                                                                         bool recursive_on,
329                                                                         scan_complete_cb user_callback,
330                                                                         void *user_data,
331                                                                         uid_t uid)
332 {
333         int ret = MS_MEDIA_ERR_NONE;
334
335         ret = __check_dir_path(directory_path, uid);
336         MSAPI_RETVM_IF(ret != MS_MEDIA_ERR_NONE, ret, "Invalid path");
337
338         if (recursive_on)
339                 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING, storage_id, directory_path, user_callback, user_data, uid);
340         else
341                 ret = __media_db_request_update_async(MS_MSG_DIRECTORY_SCANNING_NON_RECURSIVE, storage_id, directory_path, user_callback, user_data, uid);
342
343         return ret;
344 }
345
346 int media_directory_scanning_cancel(const char *directory_path, uid_t uid)
347 {
348         return __media_db_request_update_cancel(MS_MSG_DIRECTORY_SCANNING_CANCEL, directory_path);
349 }
350
351 int media_files_register(const char *list_path, insert_complete_cb user_callback, void *user_data, uid_t uid)
352 {
353         return __media_db_request_update_async(MS_MSG_BULK_INSERT, NULL, list_path, user_callback, user_data, uid);
354 }