04556b06cedfb83a248903d18d21f1308c8daaab
[profile/tv/apps/native/air_mediahub.git] / src / data / mediadata.c
1 /*
2  * Copyright (c) 2015 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 #include <Elementary.h>
18 #include <media_content.h>
19 #include <app_debug.h>
20 #include <app_media.h>
21
22 #include "data/mediadata.h"
23
24 typedef int (*media_compare)(struct group_info *gi, app_media_info *info);
25 typedef char *(*group_name_get)(app_media_info *info);
26
27 static int _compare_cb_date(const void *, const void *);
28 static int _compare_cb_name(const void *, const void *);
29
30 static int _compare_title(struct group_info *, app_media_info *);
31 static char *_get_title(app_media_info *);
32
33 enum _filter_type {
34         E_FILTER_FOLDER = 0,
35         E_FILTER_MEDIA
36 };
37
38 struct mediadata {
39         Eina_List *folder_list;
40         Eina_List *media_list;
41 };
42
43 struct _data {
44         const char *media_type;
45         int source_type;
46         int sort_type;
47         Eina_List *item_list;
48         Eina_List *folder_list;
49         Eina_List *media_list;
50 };
51
52 struct _sort_info {
53         int order_type;
54         const char *order_keyword;
55         Eina_Compare_Cb func;
56 };
57
58 struct _list_info {
59         media_compare media_cmp;
60         group_name_get name_get;
61 };
62
63 static struct _sort_info g_sort_info[E_SORT_MAX] = {
64         [E_SORT_DATE] = {
65                 .order_type = MEDIA_CONTENT_ORDER_DESC,
66                 .order_keyword = MEDIA_MODIFIED_TIME,
67                 .func = _compare_cb_date,
68         },
69         [E_SORT_NAME] = {
70                 .order_type = MEDIA_CONTENT_ORDER_ASC,
71                 .order_keyword = MEDIA_TITLE,
72                 .func = _compare_cb_name,
73         }
74 };
75
76 static struct _list_info g_list_info[E_LIST_MAX] = {
77         [E_LIST_NAME] = {
78                 .media_cmp = _compare_title,
79                 .name_get = _get_title,
80         }
81 };
82
83 static bool _create_filter(struct _data *data, filter_h *filter, int type)
84 {
85         filter_h tmp_filter;
86         int ret;
87         char buf[1024];
88
89         ret = media_filter_create(&tmp_filter);
90         if (ret != MEDIA_CONTENT_ERROR_NONE) {
91                 _ERR("failed to create media filter");
92                 return false;
93         }
94
95         snprintf(buf, sizeof(buf), "%s", data->media_type);
96
97         if (type == E_FILTER_FOLDER && data->source_type != E_SOURCE_ALL) {
98                 char s[64];
99
100                 snprintf(s, sizeof(s), " AND MEDIA_STORAGE_TYPE=%d",
101                                         data->source_type);
102                 strcat(buf, s);
103         }
104
105         media_filter_set_condition(tmp_filter, buf,
106                         MEDIA_CONTENT_COLLATE_DEFAULT);
107
108         media_filter_set_order(tmp_filter,
109                         g_sort_info[data->sort_type].order_type,
110                         g_sort_info[data->sort_type].order_keyword,
111                         MEDIA_CONTENT_COLLATE_NOCASE);
112
113         *filter = tmp_filter;
114
115         return true;
116 }
117
118 static int _compare_title(struct group_info *gi, app_media_info *info)
119 {
120         if (!gi || !gi->name || !info->title)
121                 return -1;
122
123         return strncasecmp(gi->name, info->title, 1);
124 }
125
126 static char *_get_title(app_media_info *info)
127 {
128         if (!info->title)
129                 return NULL;
130
131         return strndup(info->title, 1);
132 }
133
134 static int _compare_cb_date(const void *data1, const void *data2)
135 {
136         app_media *am1, *am2;
137         app_media_info *info1, *info2;
138
139         am1 = (app_media *)data1;
140         am2 = (app_media *)data2;
141
142         info1 = app_media_get_info(am1);
143         info2 = app_media_get_info(am2);
144
145         if (!info1 || !info2)
146                 return -1;
147
148         if (info1->modified_time > info2->modified_time)
149                 return 1;
150
151         return -1;
152 }
153
154 static int _compare_cb_name(const void *data1, const void *data2)
155 {
156         app_media *am1, *am2;
157         app_media_info *info1, *info2;
158
159         am1 = (app_media *)data1;
160         am2 = (app_media *)data2;
161
162         info1 = app_media_get_info(am1);
163         info2 = app_media_get_info(am2);
164
165         if (!info1 || !info2 || !info1->display_name || !info2->display_name)
166                 return -1;
167
168         return strcasecmp(info1->display_name, info2->display_name);
169 }
170
171 static Eina_List *_sort_list(Eina_List *list, int sort)
172 {
173         Eina_List *sorted_list;
174
175         sorted_list = eina_list_sort(list, 0, g_sort_info[sort].func);
176
177         return sorted_list;
178 }
179
180 static void _destroy_folderlist(Eina_List *list)
181 {
182         struct group_info *gi;
183         app_media *am;
184
185         EINA_LIST_FREE(list, gi) {
186                 free(gi->name);
187                 EINA_LIST_FREE(gi->list, am)
188                         app_media_destroy(am);
189                 free(gi);
190         }
191 }
192
193 static bool _get_each_media_info(media_info_h media_h, void *dt)
194 {
195         app_media *am;
196         struct _data *data;
197
198         if (!dt)
199                 return false;
200
201         data = dt;
202
203         am = app_media_create(media_h);
204         if (!am) {
205                 _ERR("failed to create app media");
206                 return false;
207         }
208
209         data->item_list = eina_list_append(data->item_list, am);
210
211         return true;
212 }
213
214 static bool _get_each_folder_info(media_folder_h folder, void *dt)
215 {
216         filter_h filter;
217         struct _data *data;
218         struct group_info *gi;
219         int ret;
220         char *uuid;
221
222         if (!dt)
223                 return false;
224
225         data = dt;
226
227         gi = calloc(1, sizeof(*gi));
228         if (!gi) {
229                 _ERR("failed to create folderdata");
230                 return false;
231         }
232
233         if (media_folder_get_name(folder, &(gi->name))
234                         != MEDIA_CONTENT_ERROR_NONE) {
235                 _ERR("Media folder id Fetch error");
236                 goto err;
237         }
238
239         if (media_folder_get_folder_id(folder, &uuid)
240                 != MEDIA_CONTENT_ERROR_NONE) {
241                 _ERR("failed to fetch media folder id");
242                 goto err;
243         }
244
245         if (!_create_filter(data, &filter, E_FILTER_MEDIA)) {
246                 _ERR("failed to create filter");
247                 goto err;
248         }
249
250         ret = media_folder_foreach_media_from_db(uuid, filter,
251                                 _get_each_media_info, data);
252         if (ret != MEDIA_CONTENT_ERROR_NONE) {
253                 _ERR("failed to get media info");
254                 goto err;
255         }
256
257         gi->list = eina_list_clone(data->item_list);
258         data->media_list = eina_list_merge(data->media_list, data->item_list);
259         data->item_list = NULL;
260
261         data->folder_list = eina_list_append(data->folder_list, gi);
262
263         media_filter_destroy(filter);
264         free(uuid);
265
266         return true;
267
268 err:
269         media_filter_destroy(filter);
270         free(uuid);
271         _destroy_folderlist(data->folder_list);
272         return false;
273 }
274
275 static bool _get_folderlist(struct _data *data)
276 {
277         filter_h filter;
278         int ret;
279
280         if (!_create_filter(data, &filter, E_FILTER_FOLDER)) {
281                 _ERR("failed to create filter");
282                 return false;
283         }
284
285         ret = media_folder_foreach_folder_from_db(filter,
286                         _get_each_folder_info, data);
287         if (ret != MEDIA_CONTENT_ERROR_NONE) {
288                 _ERR("failed to get folder info");
289                 media_filter_destroy(filter);
290                 return false;
291         }
292
293         media_filter_destroy(filter);
294
295         return true;
296 }
297
298 struct mediadata *mediadata_create(const char *media_type,
299                         int source_type, int sort_type)
300 {
301         struct mediadata *md;
302         struct _data data;
303         int ret;
304
305         if (!media_type || source_type < 0 || source_type >= E_SOURCE_MAX
306                 || sort_type < 0 || sort_type >= E_SORT_MAX) {
307                 _ERR("invalid argument");
308                 return NULL;
309         }
310
311         md = calloc(1, sizeof(*md));
312         if (!md) {
313                 _ERR("failed to create mediadata");
314                 return NULL;
315         }
316
317         ret = media_content_connect();
318         if (ret != MEDIA_CONTENT_ERROR_NONE) {
319                 _ERR("failed to connect to media content");
320                 free(md);
321                 return NULL;
322         }
323
324         data.media_type = media_type;
325         data.source_type = source_type;
326         data.sort_type = sort_type;
327         data.item_list = NULL;
328         data.folder_list = NULL;
329         data.media_list = NULL;
330
331         if (!_get_folderlist(&data)) {
332                 _ERR("failed to get folderlist");
333                 free(md);
334                 media_content_disconnect();
335                 return NULL;
336         }
337
338         media_content_disconnect();
339
340         md->folder_list = data.folder_list;
341         md->media_list = _sort_list(data.media_list, data.sort_type);
342
343         return md;
344 }
345
346 void mediadata_destroy(struct mediadata *md)
347 {
348         if (!md) {
349                 _ERR("failed to get mediadata");
350                 return;
351         }
352
353         _destroy_folderlist(md->folder_list);
354         eina_list_free(md->media_list);
355 }
356
357 Eina_List *mediadata_get_list(struct mediadata *md, int list_type)
358 {
359         Eina_List *list, *l;
360         struct group_info *gi;
361         app_media *am;
362         app_media_info *info;
363
364         if (!md) {
365                 _ERR("failed to get mediadata");
366                 return NULL;
367         }
368
369         if (list_type < 0 || list_type >= E_LIST_MAX) {
370                 _ERR("invalid argument");
371                 return NULL;
372         }
373
374         gi = NULL;
375         list = NULL;
376         EINA_LIST_FOREACH(md->media_list, l, am) {
377                 info = app_media_get_info(am);
378                 if (!info) {
379                         _ERR("failed to get media info");
380                         mediadata_free_list(list);
381                         return NULL;
382                 }
383
384                 if (g_list_info[list_type].media_cmp(gi, info)) {
385                         gi = calloc(1, sizeof(*gi));
386                         if (!gi) {
387                                 _ERR("failed to create group info");
388                                 mediadata_free_list(list);
389                                 return NULL;
390                         }
391
392                         gi->name = g_list_info[list_type].name_get(info);
393
394                         list = eina_list_append(list, gi);
395                 }
396
397                 gi->list = eina_list_append(gi->list, am);
398         }
399
400         return list;
401 }
402
403 void mediadata_free_list(Eina_List *list)
404 {
405         Eina_List *l;
406         struct group_info *gi;
407
408         EINA_LIST_FOREACH(list, l, gi) {
409                 free(gi->name);
410                 eina_list_free(gi->list);
411
412                 free(gi);
413         }
414 }