Improve count query
[platform/core/api/media-content.git] / src / media_content.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include <media_info_private.h>
19 #include <media_util_private.h>
20
21 static sqlite3 *db_handle = NULL;
22 static int ref_count = 0;
23 static GMutex db_mutex;
24 static uid_t content_g_uid = 0;
25
26 sqlite3 * _content_get_db_handle(void)
27 {
28         return db_handle;
29 }
30
31 uid_t _content_get_uid(void)
32 {
33         if (content_g_uid == 0)
34                 return tzplatform_getuid(TZ_USER_NAME);
35         else
36                 return content_g_uid;
37 }
38
39 int _content_query_prepare(const char *select_query, const char *condition_query, const char *option_query, sqlite3_stmt **stmt)
40 {
41         int ret = MEDIA_CONTENT_ERROR_NONE;
42         char *query = NULL;
43
44         media_content_retvm_if(!STRING_VALID(select_query), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid select_query");
45
46         if (STRING_VALID(condition_query)) {
47                 if (STRING_VALID(option_query))
48                         query = sqlite3_mprintf("%s AND %s %s", select_query, condition_query, option_query);
49                 else
50                         query = sqlite3_mprintf("%s AND %s", select_query, condition_query);
51         } else {
52                 if (STRING_VALID(option_query))
53                         query = sqlite3_mprintf("%s %s", select_query, option_query);
54                 else
55                         query = sqlite3_mprintf("%s", select_query);
56         }
57
58         ret = _content_get_result(query, stmt);
59         SQLITE3_SAFE_FREE(query);
60
61         return ret;
62 }
63
64 int _content_get_result(char *query, sqlite3_stmt **stmt)
65 {
66         int err = MEDIA_CONTENT_ERROR_NONE;
67
68         media_content_retvm_if(_content_get_db_handle() == NULL, MEDIA_CONTENT_ERROR_DB_FAILED, "database is not connected");
69         media_content_retvm_if(!STRING_VALID(query), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid query");
70
71         media_content_sec_debug("Query[%s]", query);
72
73         err = sqlite3_prepare_v2(_content_get_db_handle(), query, strlen(query), stmt, NULL);
74         if (err != SQLITE_OK) {
75                 media_content_error("Failed to sqlite3_prepare_v2[%s]", sqlite3_errmsg(_content_get_db_handle()));
76                 if (err == SQLITE_BUSY)
77                         return MEDIA_CONTENT_ERROR_DB_BUSY;
78                 else if (err == SQLITE_PERM)
79                         return MEDIA_CONTENT_ERROR_PERMISSION_DENIED;
80                 else
81                         return MEDIA_CONTENT_ERROR_DB_FAILED;
82         }
83
84         return MEDIA_CONTENT_ERROR_NONE;
85 }
86
87 #ifdef _USE_SENIOR_MODE
88 int _content_query_prepare_by_union_select(sqlite3_stmt **stmt, char *select_query1, char *condition_query1, char *option_query1, char *select_query2, char *condition_query2, char *option_query2)
89 {
90         int len = 0;
91         int err = MEDIA_CONTENT_ERROR_NONE;
92         char query[MAX_QUERY_SIZE] = {0, };
93         memset(query, '\0', sizeof(query));
94
95         media_content_retvm_if(_content_get_db_handle() == NULL, MEDIA_CONTENT_ERROR_DB_FAILED, "database is not connected");
96         media_content_retvm_if(!STRING_VALID(select_query1), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid select_query1");
97         media_content_retvm_if(!STRING_VALID(select_query2), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid select_query2");
98
99         if (!STRING_VALID(condition_query1))
100                 condition_query1 = (char *)" ";
101
102         if (!STRING_VALID(option_query1))
103                 option_query1 = (char *)" ";
104
105         if (!STRING_VALID(condition_query2))
106                 condition_query2 = (char *)" ";
107
108         if (!STRING_VALID(option_query2))
109                 option_query2 = (char *)" ";
110
111         len = snprintf(query, sizeof(query), "SELECT * FROM (%s %s %s) as table1 UNION ALL SELECT * FROM (%s %s %s) as table2",
112                         select_query1, condition_query1, option_query1, select_query2, condition_query2, option_query2);
113         if (len > 0 && len < sizeof(query)) {
114                 query[len] = '\0';
115         } else if (len >= sizeof(query)) {
116                 query[MAX_QUERY_SIZE -1] = '\0';
117         } else {
118                 media_content_error("snprintf failed");
119                 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
120         }
121
122         media_content_sec_debug("Query : [%s]", query);
123
124         err = sqlite3_prepare_v2(_content_get_db_handle(), query, strlen(query), stmt, NULL);
125         if (err != SQLITE_OK) {
126                 media_content_error("DB_FAILED(0x%08x) fail to sqlite3_prepare(), %s", MEDIA_CONTENT_ERROR_DB_FAILED, sqlite3_errmsg(_content_get_db_handle()));
127
128                 if (err == SQLITE_BUSY) {
129                         media_content_error(" BUSY ERROR");
130                         return MEDIA_CONTENT_ERROR_DB_BUSY;
131                 } else if (err == SQLITE_PERM) {
132                         media_content_error("PERMISSION EROR");
133                         return MEDIA_CONTENT_ERROR_PERMISSION_DENIED;
134                 } else {
135                         media_content_error("OTHER ERROR");
136                         return MEDIA_CONTENT_ERROR_DB_FAILED;
137                 }
138         }
139
140         return MEDIA_CONTENT_ERROR_NONE;
141 }
142 #endif
143
144 int _content_error_capi(int internal_error)
145 {
146         if (internal_error == MS_MEDIA_ERR_NONE)
147                 return MEDIA_CONTENT_ERROR_NONE;
148
149         media_content_error("MS Error[%d]", internal_error);
150
151         switch (internal_error) {
152         case MS_MEDIA_ERR_INVALID_PARAMETER:
153                 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
154         case MS_MEDIA_ERR_OUT_OF_MEMORY:
155                 return MEDIA_CONTENT_ERROR_OUT_OF_MEMORY;
156         case MS_MEDIA_ERR_DB_BUSY_FAIL:
157                 return MEDIA_CONTENT_ERROR_DB_BUSY;
158         case MS_MEDIA_ERR_DB_CONSTRAINT_FAIL:
159         case MS_MEDIA_ERR_DB_NO_RECORD:
160         case MS_MEDIA_ERR_DB_CORRUPT:
161         case MS_MEDIA_ERR_DB_FULL_FAIL:
162         case MS_MEDIA_ERR_DB_RESET:
163         case MS_MEDIA_ERR_DB_INTERNAL:
164                 return MEDIA_CONTENT_ERROR_DB_FAILED;
165         case MS_MEDIA_ERR_IPC:
166                 return MEDIA_CONTENT_ERROR_NETWORK;
167         case MS_MEDIA_ERR_PERMISSION_DENIED:
168                 return MEDIA_CONTENT_ERROR_PERMISSION_DENIED;
169         case MS_MEDIA_ERR_THUMB_TOO_BIG:
170         case MS_MEDIA_ERR_THUMB_UNSUPPORTED:
171                 return MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT;
172         default:
173                 return MEDIA_CONTENT_ERROR_INVALID_OPERATION;
174         }
175 }
176
177 int _content_query_sql(char *query_str)
178 {
179         int ret = MEDIA_CONTENT_ERROR_NONE;
180
181         /*DB will be updated by Media Server.*/
182         ret = media_db_request_update_db(query_str, _content_get_uid());
183
184         return _content_error_capi(ret);
185 }
186
187 int media_content_connect(void)
188 {
189         int ret = MEDIA_CONTENT_ERROR_NONE;
190
191         g_mutex_lock(&db_mutex);
192         media_content_info("ref count : %d", ref_count);
193
194         if (ref_count == 0) {
195                 if (db_handle == NULL) {
196                         ret = media_db_connect(&db_handle, _content_get_uid(), false);
197                         ret = _content_error_capi(ret);
198                         if (ret == MEDIA_CONTENT_ERROR_NONE)
199                                 ref_count++;
200                 } else {
201                         media_content_error("Wrong DB Connection status");
202                         ret = MEDIA_CONTENT_ERROR_DB_FAILED;
203                 }
204         } else {
205                 if (db_handle != NULL) {
206                         ref_count++;
207                 } else {
208                         media_content_error("Wrong DB Handle status");
209                         ret = MEDIA_CONTENT_ERROR_DB_FAILED;
210                 }
211         }
212
213         media_content_info("ref count changed to: %d", ref_count);
214         g_mutex_unlock(&db_mutex);
215
216         return ret;
217 }
218
219 int media_content_connect_with_uid(uid_t uid)
220 {
221         media_content_sec_debug("media_content_connect_with_uid [%d]", uid);
222         content_g_uid = uid;
223
224         return media_content_connect();
225 }
226
227 int media_content_disconnect(void)
228 {
229         g_mutex_lock(&db_mutex);
230         media_content_debug("ref count : %d", ref_count);
231
232         if (db_handle && ref_count > 0) {
233                 if (--ref_count == 0) {
234                         media_db_disconnect(db_handle);
235                         db_handle = NULL;
236                 }
237         } else {
238                 media_content_error("Database is not connected");
239                 g_mutex_unlock(&db_mutex);
240                 return MEDIA_CONTENT_ERROR_DB_FAILED;
241         }
242
243         g_mutex_unlock(&db_mutex);
244
245         media_content_info("ref count changed to: %d", ref_count);
246
247         return MEDIA_CONTENT_ERROR_NONE;
248 }
249
250 int media_content_scan_file(const char *path)
251 {
252         int ret = MEDIA_CONTENT_ERROR_NONE;
253         bool ignore_file = FALSE;
254         bool ignore_dir = FALSE;
255         char *folder_path = NULL;
256         int check_file = MEDIA_CONTENT_ERROR_NONE;
257         char storage_id[MEDIA_CONTENT_UUID_SIZE+1] = {0,};
258         char repl_path[MAX_PATH_LEN] = {0,};
259
260         media_content_retvm_if(!STRING_VALID(path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid path");
261
262         media_content_sec_debug("Path : %s", path);
263
264         memset(repl_path, 0, sizeof(repl_path));
265         ret = _media_content_replace_path(path, repl_path);
266         media_content_retvm_if(!STRING_VALID(repl_path), MEDIA_CONTENT_ERROR_INVALID_OPERATION, "path replacement failed");
267
268         ret = _media_util_check_ignore_file(repl_path, &ignore_file);
269         media_content_retvm_if(ignore_file == TRUE, MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid path");
270
271         memset(storage_id, 0x00, sizeof(storage_id));
272         ret = media_svc_get_storage_id(_content_get_db_handle(), repl_path, storage_id, _content_get_uid());
273         if (ret != MS_MEDIA_ERR_NONE) {
274                 media_content_error("media_svc_get_storage_id failed : %d", ret);
275                 return _content_error_capi(ret);
276         }
277
278         check_file = _media_util_check_file_exist(repl_path);
279         if (check_file == MEDIA_CONTENT_ERROR_NONE) {
280                 /* This means this path has to be inserted or refreshed */
281                 folder_path = g_path_get_dirname(repl_path);
282                 ret = _media_util_check_ignore_dir(folder_path, &ignore_dir);
283                 g_free(folder_path);
284
285                 media_content_retvm_if(ignore_dir == TRUE, MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid folder path");
286                 /* check feature */
287                 media_content_retvm_if(!_media_util_check_support_media_type(repl_path), MEDIA_CONTENT_ERROR_NOT_SUPPORTED, "Unsupported media type");
288
289                 ms_user_storage_type_e storage_type;
290
291                 ret = ms_user_get_storage_type(_content_get_uid(), repl_path, &storage_type);
292                 if (ret != MS_MEDIA_ERR_NONE) {
293                         media_content_sec_error("ms_user_get_storage_type failed : %d (%s)", ret, repl_path);
294                         return _content_error_capi(ret);
295                 }
296                 ret = media_svc_check_item_exist_by_path(_content_get_db_handle(), storage_id, repl_path);
297                 if (ret == MS_MEDIA_ERR_NONE) {
298                         /* Refresh */
299                         ret = media_svc_refresh_item(_content_get_db_handle(), false, storage_id, storage_type, repl_path, _content_get_uid());
300                         if (ret != MS_MEDIA_ERR_NONE) {
301                                 media_content_error("media_svc_refresh_item failed : %d", ret);
302                                 return _content_error_capi(ret);
303                         }
304
305                 } else if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
306                         /* Insert */
307                         ret = media_svc_insert_item_immediately(_content_get_db_handle(), storage_id, storage_type, repl_path, _content_get_uid());
308                         if (ret != MS_MEDIA_ERR_NONE) {
309                                 if (ret == MS_MEDIA_ERR_DB_CONSTRAINT_FAIL) {
310                                         media_content_sec_error("This item is already inserted. This may be normal operation because other process already did this (%s)", repl_path);
311                                         ret = MEDIA_CONTENT_ERROR_NONE;
312                                 } else {
313                                         media_content_sec_error("media_svc_insert_item_immediately failed : %d (%s)", ret, repl_path);
314                                 }
315
316                                 return _content_error_capi(ret);
317                         }
318                 } else {
319                         media_content_error("media_svc_check_item_exist_by_path failed : %d", ret);
320                         return _content_error_capi(ret);
321                 }
322         } else if (check_file == MEDIA_CONTENT_ERROR_PERMISSION_DENIED) {
323                 media_content_error("You have no permission for this file %d", ret);
324                 return MEDIA_CONTENT_ERROR_PERMISSION_DENIED;
325         } else {
326                 /* This means this path has to be deleted */
327                 media_content_debug("This path doesn't exists in file system... So now start to delete it from DB");
328                 ret = media_svc_delete_item_by_path(_content_get_db_handle(), storage_id, repl_path, _content_get_uid());
329                 if (ret != MS_MEDIA_ERR_NONE) {
330                         if (ret == MS_MEDIA_ERR_DB_NO_RECORD) {
331                                 media_content_error("Does not exist in media DB also... So, this is an invalid parameter");
332                                 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
333                         }
334
335                         media_content_error("media_svc_delete_item_by_path failed : %d", ret);
336                         return _content_error_capi(ret);
337                 }
338         }
339
340         return _content_error_capi(ret);
341 }
342
343 void _media_content_scan_cb(media_request_result_s* result, void *user_data)
344 {
345         int err = -1;
346         media_content_scan_cb_data *cb_data = user_data;
347
348         err = _content_error_capi(result->result);
349 #ifdef _USE_TVPD_MODE
350         if (result->request_type != MEDIA_REQUEST_SCAN_COMPLETE &&
351                 result->request_type != MEDIA_REQUEST_SCAN_PARTIAL &&
352                 result->request_type != MEDIA_RECURSIVE_START) {
353                 if (cb_data && cb_data->callback) {
354                         media_content_debug("begin:User callback is being called now, result=%d", err);
355                         cb_data->callback(err, cb_data->user_data);
356                         media_content_debug("end:User callback is being called now, result=%d", err);
357                 }
358
359                 SAFE_FREE(cb_data);
360         }
361 #else
362         if (cb_data && cb_data->callback) {
363                 media_content_debug("User callback is being called now");
364                 cb_data->callback(err, cb_data->user_data);
365         }
366
367         SAFE_FREE(cb_data);
368 #endif
369
370         return;
371 }
372
373 #ifdef _USE_TVPD_MODE
374 void _media_content_scan_cb_v2(media_request_result_s* result, void *user_data)
375 {
376         int err = -1;
377         media_content_scan_cb_data_v2 *cb_data = user_data;
378         media_content_complete_phase_e complete_phase = -1;
379         if (!cb_data)
380                 media_content_debug("cb_data is NULL");
381         err = _content_error_capi(result->result);
382         media_content_debug("result is %d", err);
383
384         if (result->request_type == MEDIA_REQUEST_SCAN_PARTIAL)
385                 complete_phase = MEDIA_CONTENT_SCAN_PARTIAL_COMPLETE;
386         else if (result->request_type == MEDIA_REQUEST_SCAN_COMPLETE)
387                 complete_phase = MEDIA_CONTENT_SCAN_COMPLETE;
388         else if (result->request_type == MEDIA_REQUEST_EXTRACT_COMPLETE)
389                 complete_phase = MEDIA_CONTENT_EXTRACT_COMPLETE;
390         else if (result->request_type == MEDIA_RECURSIVE_START)
391                 complete_phase = MEDIA_CONTENT_RECURSIVE_START;
392
393         if (cb_data && cb_data->callback)
394                 cb_data->callback(err, complete_phase, cb_data->user_data);
395         else
396                 media_content_debug("run error");
397
398         if ((result->request_type != MEDIA_REQUEST_SCAN_COMPLETE) &&
399         (result->request_type != MEDIA_REQUEST_SCAN_PARTIAL) &&
400         (result->request_type != MEDIA_RECURSIVE_START))
401                 SAFE_FREE(cb_data);
402
403         return;
404 }
405 #endif
406
407 int media_content_scan_folder(const char *path, bool is_recursive, media_scan_completed_cb callback, void *user_data)
408 {
409         int ret = MEDIA_CONTENT_ERROR_NONE;
410         bool ignore_dir = FALSE;
411         char storage_id[MEDIA_CONTENT_UUID_SIZE+1] = {0, };
412         char repl_path[MAX_PATH_LEN] = {0, };
413         ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
414
415         media_content_retvm_if(!STRING_VALID(path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid path");
416         memset(repl_path, 0, sizeof(repl_path));
417         ret = _media_content_replace_path(path, repl_path);
418         media_content_retvm_if(!STRING_VALID(repl_path), MEDIA_CONTENT_ERROR_INVALID_OPERATION, "path replacement failed");
419
420         memset(storage_id, 0x00, sizeof(storage_id));
421
422         ret = _media_content_check_dir(repl_path);
423         media_content_retvm_if(ret == MEDIA_CONTENT_ERROR_PERMISSION_DENIED, ret, "Permission Denied");
424
425         if (ret == MEDIA_CONTENT_ERROR_NONE) {
426                 /* If directory exist check that's ignore directory or not*/
427                 ret = _media_util_check_ignore_dir(repl_path, &ignore_dir);
428                 media_content_retvm_if((ignore_dir == TRUE || ret != MEDIA_CONTENT_ERROR_NONE), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid folder path");
429         } else {
430                 /* This means this folder has to be deleted */
431                 /* Or, it is real invalid path.. check storage type */
432                 ret = ms_user_get_storage_type(_content_get_uid(), repl_path, &storage_type);
433                 if (ret != MS_MEDIA_ERR_NONE) {
434                         media_content_sec_error("ms_user_get_storage_type failed : %d (%s)", ret, repl_path);
435                         return _content_error_capi(ret);
436                 }
437
438                 media_content_debug("This path doesn't exists in file system... So will be deleted it from DB");
439         }
440
441         ret = media_svc_get_storage_id(_content_get_db_handle(), repl_path, storage_id, _content_get_uid());
442         if (ret != MS_MEDIA_ERR_NONE) {
443                 media_content_error("media_svc_get_storage_id failed : %d", ret);
444                 return _content_error_capi(ret);
445         }
446
447         media_content_scan_cb_data *cb_data = NULL;
448         cb_data = (media_content_scan_cb_data *)malloc(sizeof(media_content_scan_cb_data));
449         media_content_retvm_if(cb_data == NULL, MEDIA_CONTENT_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
450
451         cb_data->callback = callback;
452         cb_data->user_data = user_data;
453
454         ret = media_directory_scanning_async(repl_path, storage_id, is_recursive, _media_content_scan_cb, cb_data, _content_get_uid());
455         if (ret != MS_MEDIA_ERR_NONE) {
456                 media_content_error("media_directory_scanning_async failed : %d", ret);
457                 SAFE_FREE(cb_data);
458         }
459
460         return _content_error_capi(ret);
461 }
462
463 #ifdef _USE_TVPD_MODE
464 int media_content_scan_folder_v2(const char *path, bool is_recursive, media_scan_completed_cb_v2 callback, void *user_data)
465 {
466         int ret = MEDIA_CONTENT_ERROR_NONE;
467         bool ignore_dir = FALSE;
468         char storage_id[MEDIA_CONTENT_UUID_SIZE+1] = {0, };
469
470         media_content_retvm_if(!STRING_VALID(path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid path");
471         memset(storage_id, 0x00, sizeof(storage_id));
472
473         ret = _media_util_check_ignore_dir(path, &ignore_dir);
474         media_content_retvm_if(ignore_dir, MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid folder path");
475
476         ret = _media_content_check_dir(path);
477         media_content_retvm_if(ret == MEDIA_CONTENT_ERROR_PERMISSION_DENIED, ret, "Permission Denied");
478         media_content_retvm_if(ret == MEDIA_CONTENT_ERROR_INVALID_PARAMETER, ret, "invalid path[%s]", path);
479
480         media_content_scan_cb_data_v2* cb_data = NULL;
481         cb_data = (media_content_scan_cb_data_v2*)malloc(sizeof(media_content_scan_cb_data_v2));
482         media_content_retvm_if(cb_data == NULL, MEDIA_CONTENT_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
483
484         cb_data->callback = callback;
485         cb_data->user_data = user_data;
486
487         ret = media_svc_get_storage_id(_content_get_db_handle(), path, storage_id, _content_get_uid());
488         /*FIX ME. need to check ret value?*/
489
490         ret = media_directory_scanning_async(path, storage_id, is_recursive, _media_content_scan_cb_v2, cb_data, _content_get_uid());
491         if (ret != MS_MEDIA_ERR_NONE)
492                 media_content_error("media_directory_scanning_async failed : %d", ret);
493
494         return _content_error_capi(ret);
495 }
496 #endif
497
498 int media_content_cancel_scan_folder(const char *path)
499 {
500         int ret = MEDIA_CONTENT_ERROR_NONE;
501         char repl_path[MAX_PATH_LEN] = {0, };
502
503         media_content_retvm_if(!STRING_VALID(path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid path");
504
505         memset(repl_path, 0, sizeof(repl_path));
506         ret = _media_content_replace_path(path, repl_path);
507         media_content_retvm_if(!STRING_VALID(repl_path), MEDIA_CONTENT_ERROR_INVALID_OPERATION, "path replacement failed");
508
509         ret = media_directory_scanning_cancel(repl_path, _content_get_uid());
510         if (ret != MS_MEDIA_ERR_NONE)
511                 media_content_error("media_directory_scanning_async failed : %d", ret);
512
513         return _content_error_capi(ret);
514 }
515
516 void _media_content_db_update_noti_cb(
517                                                         int pid,
518                                                         media_item_type_e item,
519                                                         media_item_update_type_e update_type,
520                                                         char* path,
521                                                         char* uuid,
522                                                         media_type_e content_type,
523                                                         char *mime_type,
524                                                         void *user_data)
525 {
526         media_noti_cb_s *_noti_info = (media_noti_cb_s *)user_data;
527
528         if (_noti_info != NULL && _noti_info->update_noti_cb)
529                 _noti_info->update_noti_cb(
530                                         MEDIA_CONTENT_ERROR_NONE,
531                                         pid,
532                                         item,
533                                         update_type,
534                                         content_type,
535                                         uuid,
536                                         path,
537                                         mime_type,
538                                         _noti_info->user_data);
539 }
540
541 int media_content_add_db_updated_cb(media_content_db_update_cb callback, void *user_data, media_content_noti_h *noti_handle)
542 {
543         int ret = MEDIA_CONTENT_ERROR_NONE;
544         media_noti_cb_s *noti_info = NULL;
545
546         media_content_retvm_if(noti_handle == NULL, MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "handle is NULL");
547         media_content_retvm_if(callback == NULL, MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "callback is NULL");
548
549         noti_info = (media_noti_cb_s *)calloc(1, sizeof(media_noti_cb_s));
550         media_content_retvm_if(noti_info == NULL, MEDIA_CONTENT_ERROR_OUT_OF_MEMORY, "Failed to create noti info");
551
552         noti_info->update_noti_cb = callback;
553         noti_info->user_data = user_data;
554
555         ret = media_db_update_subscribe_internal((MediaNotiHandle*)noti_handle, _media_content_db_update_noti_cb, (void *)noti_info);
556         if (ret != MS_MEDIA_ERR_NONE)
557                 SAFE_FREE(noti_info);
558
559         return _content_error_capi(ret);
560 }
561
562 #ifdef TIZEN_FEATURE_COMPATIBILITY
563 int media_content_set_db_updated_cb(media_content_db_update_cb callback, void *user_data)
564 {
565         media_content_warn("DEPRECATION WARNING: media_content_set_db_updated_cb() is removed from 5.0.");
566
567         return MEDIA_CONTENT_ERROR_NONE;
568 }
569 #endif
570
571 void __media_content_clear_user_data(void *user_data)
572 {
573         media_noti_cb_s *noti_info = user_data;
574
575         SAFE_FREE(noti_info);
576
577         return;
578 }
579
580 int media_content_remove_db_updated_cb(media_content_noti_h noti_handle)
581 {
582         int ret = MEDIA_CONTENT_ERROR_NONE;
583
584         ret = media_db_update_unsubscribe_internal((MediaNotiHandle)noti_handle, __media_content_clear_user_data);
585
586         return _content_error_capi(ret);
587 }
588 #ifdef _USE_TVPD_MODE
589 GMutex* _content_get_db_mutex(void)
590 {
591         return &db_mutex;
592 }
593 #endif