9d90d7e46c0bbf306fa21bda1be17ea7688ea5d9
[profile/tv/apps/native/gallery.git] / src / data / mediadata.cpp
1  /*
2  * Copyright (c) 2014 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 <AppCommon.h>
18 #include "define.h"
19 #include "mediainfo.h"
20 #include "eventinfo.h"
21 #include "folderinfo.h"
22 #include "imageinfo.h"
23 #include "videoinfo.h"
24 #include "mediadata.h"
25 #include "menudef.h"
26 #include "util.h"
27
28 #define MEDIA_CONDITION_IMAGE_VIDEO "(MEDIA_TYPE=0 OR MEDIA_TYPE=1)"
29 #define MEDIA_CONDITION_IMAGE "(MEDIA_TYPE=0)"
30 #define MEDIA_CONDITION_VIDEO "(MEDIA_TYPE=1)"
31
32 struct SMediadata {
33         filter_h filter;
34         Eina_List *folderlist;
35         Eina_List *folder_medialist;
36         Eina_List *eventlist;
37         Eina_List *medialist;
38         int media;
39         int source_type;
40
41         SMediadata() {
42                 memset(this, 0, sizeof(SMediadata));
43         }
44 };
45
46 enum {
47         E_FILTER_TYPE_FOLDER = 0,
48         E_FILTER_TYPE_NONE
49 };
50
51 enum {
52         E_TYPE_MEDIA = 0,
53         E_TYPE_FOLDER_MEDIA
54 };
55
56 CMediadata *CMediadata::instance = NULL;
57 int CMediadata::g_ref_count = 0;
58
59 void CMediadata::m_DeleteFolderList(void)
60 {
61         CFolderInfo *finfo;
62         void *obj;
63
64         finfo = NULL;
65         EINA_LIST_FREE(m->folderlist, obj) {
66                 finfo = (CFolderInfo *)obj;
67                 finfo->Destroy();
68                 delete finfo;
69         }
70
71         m->folderlist = NULL;
72 }
73
74 void CMediadata::m_DeleteEventList(void)
75 {
76         CEventInfo *einfo;
77         void *obj;
78
79         einfo = NULL;
80         EINA_LIST_FREE(m->eventlist, obj) {
81                 einfo = (CEventInfo *)obj;
82                 einfo->Destroy();
83                 delete einfo;
84         }
85
86         m->eventlist = NULL;
87 }
88
89 void CMediadata::m_DeleteMediaList(int type)
90 {
91         CMediaInfo *minfo;
92         Eina_List *medialist;
93         void *obj;
94
95         if (type == E_TYPE_MEDIA)
96                 medialist = m->medialist;
97         else if (type == E_TYPE_FOLDER_MEDIA)
98                 medialist = m->folder_medialist;
99         else {
100                 _ERR("Wrong MediaInfo Type");
101                 return;
102         }
103
104         minfo = NULL;
105         EINA_LIST_FREE(medialist, obj) {
106                 minfo = (CMediaInfo *)obj;
107
108                 if (minfo->Type() == E_MEDIA_IMAGE)
109                         ((CImageInfo *)minfo)->Destroy();
110                 else if (minfo->Type() == E_MEDIA_VIDEO)
111                         ((CVideoInfo *)minfo)->Destroy();
112
113                 delete minfo;
114         }
115
116         if (type == E_TYPE_MEDIA)
117                 m->medialist = NULL;
118         else if (type == E_TYPE_FOLDER_MEDIA)
119                 m->folder_medialist = NULL;
120 }
121
122 void CMediadata::DestroyMediaList(void)
123 {
124         if (m->folderlist)
125                 m_DeleteFolderList();
126
127         if (m->eventlist)
128                 m_DeleteEventList();
129
130         if (m->medialist)
131                 m_DeleteMediaList(E_TYPE_MEDIA);
132
133         if (m->folder_medialist)
134                 m_DeleteMediaList(E_TYPE_FOLDER_MEDIA);
135 }
136
137 bool CMediadata::m_CreateFilter(filter_h *filter, int type)
138 {
139         filter_h tmp_filter;
140         media_content_order_e order;
141         const char *keyword;
142         char buf[1024];
143         const char *mediatype;
144
145         int ret = media_filter_create(&tmp_filter);
146         if (ret != MEDIA_CONTENT_ERROR_NONE) {
147                 _ERR("Media Filter Creation Failed");
148                 return false;
149         }
150
151         if (m->media == E_MEDIA_IMAGE)
152                 mediatype = MEDIA_CONDITION_IMAGE;
153         else if (m->media == E_MEDIA_VIDEO)
154                 mediatype = MEDIA_CONDITION_VIDEO;
155         else
156                 mediatype = MEDIA_CONDITION_IMAGE_VIDEO;
157
158         switch (m->source_type) {
159         case E_SOURCE_TV:
160                 snprintf(buf, sizeof(buf), "%s AND (MEDIA_STORAGE_TYPE=0)",
161                         mediatype);
162                 break;
163
164         case E_SOURCE_USB:
165                 snprintf(buf, sizeof(buf), "%s AND (MEDIA_STORAGE_TYPE=1)",
166                         mediatype);
167                 break;
168
169         case E_SOURCE_ALL:
170         default:
171                 snprintf(buf, sizeof(buf), "%s", mediatype);
172                 break;
173
174         }
175
176         if (type == E_FILTER_TYPE_FOLDER) {
177                 media_filter_set_condition(tmp_filter, buf,
178                         MEDIA_CONTENT_COLLATE_DEFAULT);
179         }
180         else {
181                 media_filter_set_condition(tmp_filter,
182                         mediatype,
183                         MEDIA_CONTENT_COLLATE_DEFAULT);
184         }
185
186         order = MEDIA_CONTENT_ORDER_DESC;
187         keyword = MEDIA_MODIFIED_TIME;
188
189         media_filter_set_order(tmp_filter, order,
190                 keyword, MEDIA_CONTENT_COLLATE_NOCASE);
191
192         *filter = tmp_filter;
193
194         return true;
195 }
196
197 bool CMediadata::m_DestroyFilter(filter_h filter)
198 {
199         if (media_filter_destroy(filter) != MEDIA_CONTENT_ERROR_NONE) {
200                 _ERR("Filter destroy failed");
201                 return false;
202         }
203
204         return true;
205 }
206
207 void CMediadata::m_GetMediaList(void)
208 {
209         CMediaInfo *minfo, *nminfo;
210         Eina_List *l;
211         void *obj;
212
213         nminfo = NULL;
214         EINA_LIST_FOREACH(m->folder_medialist, l, obj) {
215                 minfo = (CMediaInfo *)obj;
216
217                 if (minfo->Type() == E_MEDIA_IMAGE) {
218                         nminfo = new CImageInfo;
219                         ((CImageInfo *)nminfo)->Create();
220                         ((CImageInfo *)nminfo)->Duplicate(minfo);
221                 } else if (minfo->Type() == E_MEDIA_VIDEO) {
222                         nminfo = new CVideoInfo;
223                         ((CVideoInfo *)nminfo)->Create();
224                         ((CVideoInfo *)nminfo)->Duplicate(minfo);
225                 }
226
227                 m->medialist = eina_list_append(m->medialist, nminfo);
228         }
229 }
230
231 void CMediadata::m_GetEventList(void)
232 {
233         CEventInfo *einfo;
234         CMediaInfo *minfo;
235         Eina_List *l1, *l2;
236         Eina_List *eventlist;
237         char *date_taken;
238         bool bevent_found;
239         time_t timeval;
240         struct tm tm;
241         char buf[32];
242         void *obj, *obj2;
243
244         eventlist = NULL;
245         date_taken = NULL;
246         EINA_LIST_FOREACH(m->medialist, l1, obj) {
247                 minfo = (CMediaInfo *)obj;
248
249                 date_taken = NULL;
250                 timeval = minfo->Time();
251                 if (timeval > 0) {
252                         localtime_r(&timeval, &tm);
253                         strftime(buf, sizeof(buf), "%Y.%m.%d", &tm);
254                         date_taken = strdup(buf);
255                 }
256
257                 if (!date_taken) {
258                         einfo = new CEventInfo;
259                         einfo->Create();
260                         if (!einfo)
261                                 goto error;
262
263                         einfo->SetType(E_TYPE_EVENT_NO_INFO);
264                         einfo->SetName(NULL);
265                         einfo->SetModifiedTime(0);
266                         einfo->SetMediaInfo(minfo);
267
268                         eventlist = eina_list_append(eventlist, einfo);
269                 }
270                 else {
271                         bevent_found = false;
272                         EINA_LIST_FOREACH(eventlist, l2, obj2) {
273                                 einfo = (CEventInfo *)obj2;
274
275                                 if (!strcmp(einfo->Name(), date_taken)) {
276                                         einfo->SetMediaInfo(minfo);
277                                         bevent_found = true;
278                                         break;
279                                 }
280                         }
281
282                         if (!bevent_found) {
283                                 einfo = new CEventInfo;
284                                 einfo->Create();
285                                 if (!einfo)
286                                         goto error;
287
288                                 einfo->SetType(E_TYPE_EVENT_INFO);
289                                 einfo->SetName(date_taken);
290                                 einfo->SetModifiedTime(timeval);
291                                 einfo->SetMediaInfo(minfo);
292
293                                 eventlist = eina_list_append(eventlist, einfo);
294                         }
295                         free(date_taken);
296                 }
297         }
298
299         m->eventlist = eventlist;
300
301         return;
302
303 error:
304         free(date_taken);
305         m_DeleteEventList();
306 }
307
308 bool CMediadata::m_HandleEachImageInfo(media_info_h media_h, CMediaInfo *minfo)
309 {
310         int val;
311         image_meta_h image_h;
312
313         if (media_info_get_image(media_h, &image_h) !=
314                 MEDIA_CONTENT_ERROR_NONE) {
315                 _ERR("Media Image Handle Fetch Error");
316                 return false;
317         }
318
319         if (image_meta_get_width(image_h, &val) !=
320                 MEDIA_CONTENT_ERROR_NONE) {
321                 _ERR("Image meta get width error");
322                 return false;
323         }
324         ((CImageInfo *)minfo)->SetWidth(val);
325
326         if (image_meta_get_height(image_h, &val) !=
327                 MEDIA_CONTENT_ERROR_NONE) {
328                 _ERR("Image meta get height error");
329                 return false;
330         }
331         ((CImageInfo *)minfo)->SetHeight(val);
332
333         if (image_meta_get_orientation(image_h,
334                 (media_content_orientation_e *)&val) !=
335                 MEDIA_CONTENT_ERROR_NONE) {
336                 _ERR("Image meta get orientation error");
337                 return false;
338         }
339         ((CImageInfo *)minfo)->SetOrientation(val);
340
341         if (image_meta_destroy(image_h) != MEDIA_CONTENT_ERROR_NONE) {
342                 _ERR("Image meta destroy error");
343                 return false;
344         }
345
346         return true;
347 }
348
349 bool CMediadata::m_HandleEachVideoInfo(media_info_h media_h, CMediaInfo *minfo)
350 {
351         int val;
352         video_meta_h video_h;
353
354         if (media_info_get_video(media_h, &video_h) !=
355                 MEDIA_CONTENT_ERROR_NONE || !video_h) {
356                 _ERR("Media video handle fetch error");
357                 return false;
358         }
359
360         if (video_meta_get_duration(video_h, &val) !=
361                 MEDIA_CONTENT_ERROR_NONE) {
362                 _ERR("video meta get duration error");
363                 return false;
364         }
365         ((CVideoInfo *)minfo)->SetDuration(val);
366
367         if (video_meta_get_played_position(video_h, &val) !=
368                 MEDIA_CONTENT_ERROR_NONE) {
369                 _ERR("video meta get played position error");
370                 return false;
371         }
372         ((CVideoInfo *)minfo)->SetPlayedPosition(val);
373
374         if (video_meta_destroy(video_h) != MEDIA_CONTENT_ERROR_NONE) {
375                 _ERR("video meta destroy error");
376                 return false;
377         }
378
379         return true;
380 }
381
382 bool CMediadata::sm_CbEachMediaInfo(media_info_h media_h, void *dt)
383 {
384         CMediadata *root = (CMediadata *)dt;
385
386         if (!root)
387                 return false;
388
389         return root->m_HandleEachMediaInfo(media_h);
390 }
391
392 bool CMediadata::m_HandleEachMediaInfo(media_info_h media_h)
393 {
394         CMediaInfo *minfo;
395         char *buf;
396         int type;
397         unsigned long long val;
398
399         minfo = NULL;
400
401         if (media_info_get_media_type(media_h,
402                 (media_content_type_e *)&type) !=
403                 MEDIA_CONTENT_ERROR_NONE) {
404                 _ERR("Media type Fetch error");
405                 return false;
406         }
407
408         if (type == MEDIA_CONTENT_TYPE_IMAGE) {
409                 minfo = new CImageInfo;
410                 if (!minfo) {
411                         _ERR("MediaInfo Create Failed");
412                         return false;
413                 }
414                 ((CImageInfo *)minfo)->Create();
415
416                 if (!m_HandleEachImageInfo(media_h, minfo))
417                         goto error;
418         }
419         else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
420                 minfo = new CVideoInfo;
421                 if (!minfo) {
422                         _ERR("MediaInfo Create Failed");
423                         return false;
424                 }
425                 ((CVideoInfo *)minfo)->Create();
426
427                 if (!m_HandleEachVideoInfo(media_h, minfo))
428                         goto error;
429         }
430
431         minfo->SetType(type);
432
433         if (media_info_get_media_id(media_h, &buf) !=
434                 MEDIA_CONTENT_ERROR_NONE) {
435                 _ERR("Media ID Fetch error");
436                 goto error;
437         }
438         minfo->SetId(buf);
439
440         if (media_info_get_display_name(media_h, &buf) !=
441                 MEDIA_CONTENT_ERROR_NONE) {
442                 _ERR("Media display nam))e Fetch error");
443                 goto error;
444         }
445         minfo->SetName(buf);
446
447         if (media_info_get_size(media_h, &val) !=
448                 MEDIA_CONTENT_ERROR_NONE) {
449                 _ERR("Media size Fetch error");
450                 goto error;
451         }
452         minfo->SetSize(val);
453
454         if (media_info_get_file_path(media_h, &buf)
455                 != MEDIA_CONTENT_ERROR_NONE) {
456                 _ERR("Media file path Fetch error");
457                 goto error;
458         }
459         minfo->SetPath(buf);
460
461         if (media_info_get_thumbnail_path(media_h, &buf) !=
462                 MEDIA_CONTENT_ERROR_NONE) {
463                 _ERR("Media thumbnail path Fetch error");
464                 goto error;
465         }
466         minfo->SetThumbnailPath(buf);
467
468         if (media_info_get_modified_time(media_h, (time_t *)&val) !=
469                 MEDIA_CONTENT_ERROR_NONE) {
470                 _ERR("Media modified time Fetch error");
471                 goto error;
472         }
473         minfo->SetModifiedTime(val);
474
475         if (media_info_get_modified_time(media_h, (time_t *)&val) !=
476                 MEDIA_CONTENT_ERROR_NONE) {
477                 _ERR("Media created time Fetch error");
478                 goto error;
479         }
480         minfo->SetCreatedTime(val);
481
482         if (media_info_get_location_tag(media_h, &buf) !=
483                 MEDIA_CONTENT_ERROR_NONE) {
484                 _ERR("Media location tag Fetch error");
485                 goto error;
486         }
487         minfo->SetLocationTag(buf);
488
489         if (media_info_get_storage_type(media_h,
490                 (media_content_storage_e *)&val) !=
491                 MEDIA_CONTENT_ERROR_NONE) {
492                 _ERR("Media location tag Fetch error");
493                 goto error;
494         }
495         minfo->SetSource(val);
496
497         m->folder_medialist = eina_list_append(m->folder_medialist, minfo);
498
499         return true;
500
501 error:
502         _ERR("Erroring in reading mediadata");
503
504         if (type == MEDIA_CONTENT_TYPE_IMAGE)
505                 ((CImageInfo *)minfo)->Destroy();
506         else if (type == MEDIA_CONTENT_TYPE_VIDEO)
507                 ((CVideoInfo *)minfo)->Destroy();
508
509         delete minfo;
510
511         return false;
512 }
513
514 bool CMediadata::sm_CbEachFolderInfo(media_folder_h folder, void *dt)
515 {
516         CMediadata *root = (CMediadata *)dt;
517
518         if (!root)
519                 return false;
520
521         return root->m_HandleEachFolderInfo(folder);
522 }
523
524 bool CMediadata::m_HandleEachFolderInfo(media_folder_h folder)
525 {
526         CFolderInfo *finfo;
527         char *uuid;
528         char *buf;
529         int val;
530         int ret = -1;
531         filter_h filter;
532
533         finfo = new CFolderInfo;
534
535         finfo->Create();
536         if (!finfo) {
537                 _ERR("FolderInfo Create Failed");
538                 return false;
539         }
540
541         uuid = NULL;
542
543         m_CreateFilter(&filter, E_FILTER_TYPE_NONE);
544
545         if (media_folder_get_name(folder, &buf) !=
546                 MEDIA_CONTENT_ERROR_NONE) {
547                 _ERR("Media folder id Fetch error");
548                 goto error;
549         }
550         finfo->SetName(buf);
551
552         if (media_folder_get_modified_time(folder, (time_t *)&val)
553                 != MEDIA_CONTENT_ERROR_NONE) {
554                 _ERR("Media folder modified time Fetch error");
555                 goto error;
556         }
557         finfo->SetModifiedTime(val);
558
559         if (media_folder_get_folder_id(folder, &uuid)
560                 != MEDIA_CONTENT_ERROR_NONE) {
561                 _ERR("Media folder id Fetch error");
562                 goto error;
563         }
564
565         ret = media_folder_foreach_media_from_db(uuid, filter,
566                 sm_CbEachMediaInfo, (void *)this);
567         if (ret != MEDIA_CONTENT_ERROR_NONE) {
568                 if (ret == MEDIA_CONTENT_ERROR_DB_FAILED)
569                         _ERR("MEDIA CONTENT ERROR DB FAILED");
570                 else if (ret == MEDIA_CONTENT_ERROR_DB_BUSY)
571                         _ERR("MEDIA CONTENT ERROR DB BUSY");
572                 else
573                         _ERR("MEDIA CONTENT ERROR GENERAL");
574                 goto error;
575         }
576
577         finfo->SetMediaList(m->folder_medialist);
578         m_GetMediaList();
579
580         m_DeleteMediaList(E_TYPE_FOLDER_MEDIA);
581
582         m->folderlist = eina_list_append(m->folderlist, finfo);
583
584         m_DestroyFilter(filter);
585         free(uuid);
586
587         return true;
588
589 error:
590         _ERR("Error in creating Media list");
591         m_DestroyFilter(filter);
592         finfo->Destroy();
593         delete finfo;
594         free(uuid);
595         DestroyMediaList();
596
597         return false;
598 }
599
600 bool CMediadata::Initialize(void)
601 {
602         int ret;
603
604         if (g_ref_count > 0) {
605                 g_ref_count++;
606                 return false;
607         }
608
609         instance = new CMediadata;
610         if (!instance)
611                 return false;
612
613         instance->m = new SMediadata;
614         if (!instance->m) {
615                 _ERR("Mediadata init failed");
616                 delete instance;
617                 instance = NULL;
618                 return false;
619         }
620
621         ret = media_content_connect();
622         if (ret != MEDIA_CONTENT_ERROR_NONE) {
623                 _ERR("Media Content Connect Failed");
624                 return false;
625         }
626
627         g_ref_count++;
628
629         return true;
630 }
631
632 void CMediadata::Finalize(void)
633 {
634         if (!instance || !instance->m)
635                 return;
636
637         int ret;
638
639         if (g_ref_count <= 0)
640                 return;
641
642         g_ref_count--;
643
644         if (g_ref_count == 0) {
645                 instance->m_DeleteFolderList();
646                 instance->m_DeleteEventList();
647                 instance->m_DeleteMediaList(E_TYPE_MEDIA);
648                 instance->m_DeleteMediaList(E_TYPE_FOLDER_MEDIA);
649
650                 ret = media_content_disconnect();
651                 if (ret != MEDIA_CONTENT_ERROR_NONE)
652                         _ERR("Media Content Connect Failed");
653         }
654
655         delete instance->m;
656
657         delete instance;
658         instance = NULL;
659 }
660
661 CMediadata *CMediadata::GetInstance()
662 {
663         return instance;
664 }
665
666 bool CMediadata::CreateMediaList(int source_type, int media)
667 {
668         int ret;
669
670         m->source_type = source_type;
671         m->media = media;
672
673         m_CreateFilter(&m->filter, E_FILTER_TYPE_FOLDER);
674
675         ret = media_folder_foreach_folder_from_db(m->filter,
676                 sm_CbEachFolderInfo, (void *)this);
677         if (ret != MEDIA_CONTENT_ERROR_NONE) {
678                 _ERR("Failed to read from folders");
679                 m_DestroyFilter(m->filter);
680                 return false;
681         }
682
683         if (m->medialist)
684                 m_GetEventList();
685
686         m_DestroyFilter(m->filter);
687
688         return true;
689 }
690
691 CMediaInfo *CMediadata::FindMediaInfo(Eina_List *media_list, const char *path)
692 {
693         Eina_List *l;
694         CMediaInfo *minfo;
695         void *obj;
696
697         if (!media_list || !path)
698                 return NULL;
699
700         minfo = NULL;
701         EINA_LIST_FOREACH(media_list, l, obj) {
702                 minfo = (CMediaInfo *)obj;
703
704                 if (!strcmp(minfo->Path(), path))
705                         return minfo;
706         }
707
708         return NULL;
709 }
710
711 Eina_List *CMediadata::CreateListforType(Eina_List *media_list, int type)
712 {
713         Eina_List *l, *new_list;
714         CMediaInfo *minfo;
715         void *obj;
716
717         if (!media_list)
718                 return NULL;
719
720         new_list = NULL;
721         EINA_LIST_FOREACH(media_list, l, obj) {
722                 minfo = (CMediaInfo *)obj;
723
724                 if (type == minfo->Type())
725                         new_list = eina_list_append(new_list, minfo);
726         }
727
728         return new_list;
729 }
730
731 Eina_List *CMediadata::MediaList(void)
732 {
733         if (!m)
734                 return NULL;
735
736         return m->medialist;
737 }
738
739 Eina_List *CMediadata::EventList(void)
740 {
741         if (!m)
742                 return NULL;
743
744         return m->eventlist;
745 }
746
747 Eina_List *CMediadata::FolderList(void)
748 {
749         if (!m)
750                 return NULL;
751
752         return m->folderlist;
753 }