682d7a4fff11f101e5432817d403c590c1d63ff4
[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         } else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
419                 minfo = new CVideoInfo;
420                 if (!minfo) {
421                         _ERR("MediaInfo Create Failed");
422                         return false;
423                 }
424                 ((CVideoInfo *)minfo)->Create();
425
426                 if (!m_HandleEachVideoInfo(media_h, minfo))
427                         goto error;
428         }
429
430         minfo->SetType(type);
431
432         if (media_info_get_media_id(media_h, &buf) !=
433                 MEDIA_CONTENT_ERROR_NONE) {
434                 _ERR("Media ID Fetch error");
435                 goto error;
436         }
437         minfo->SetId(buf);
438
439         if (media_info_get_display_name(media_h, &buf) !=
440                 MEDIA_CONTENT_ERROR_NONE) {
441                 _ERR("Media display nam))e Fetch error");
442                 goto error;
443         }
444         minfo->SetName(buf);
445
446         if (media_info_get_size(media_h, &val) !=
447                 MEDIA_CONTENT_ERROR_NONE) {
448                 _ERR("Media size Fetch error");
449                 goto error;
450         }
451         minfo->SetSize(val);
452
453         if (media_info_get_file_path(media_h, &buf)
454                 != MEDIA_CONTENT_ERROR_NONE) {
455                 _ERR("Media file path Fetch error");
456                 goto error;
457         }
458         minfo->SetPath(buf);
459
460         if (media_info_get_thumbnail_path(media_h, &buf) !=
461                 MEDIA_CONTENT_ERROR_NONE) {
462                 _ERR("Media thumbnail path Fetch error");
463                 goto error;
464         }
465         minfo->SetThumbnailPath(buf);
466
467         if (media_info_get_modified_time(media_h, (time_t *)&val) !=
468                 MEDIA_CONTENT_ERROR_NONE) {
469                 _ERR("Media modified time Fetch error");
470                 goto error;
471         }
472         minfo->SetModifiedTime(val);
473
474         if (media_info_get_modified_time(media_h, (time_t *)&val) !=
475                 MEDIA_CONTENT_ERROR_NONE) {
476                 _ERR("Media created time Fetch error");
477                 goto error;
478         }
479         minfo->SetCreatedTime(val);
480
481         if (media_info_get_location_tag(media_h, &buf) !=
482                 MEDIA_CONTENT_ERROR_NONE) {
483                 _ERR("Media location tag Fetch error");
484                 goto error;
485         }
486         minfo->SetLocationTag(buf);
487
488         if (media_info_get_storage_type(media_h,
489                 (media_content_storage_e *)&val) !=
490                 MEDIA_CONTENT_ERROR_NONE) {
491                 _ERR("Media location tag Fetch error");
492                 goto error;
493         }
494         minfo->SetSource(val);
495
496         minfo->SetMediaInfo(media_h);
497
498         m->folder_medialist = eina_list_append(m->folder_medialist, minfo);
499
500         return true;
501
502 error:
503         _ERR("Erroring in reading mediadata");
504
505         if (type == MEDIA_CONTENT_TYPE_IMAGE)
506                 ((CImageInfo *)minfo)->Destroy();
507         else if (type == MEDIA_CONTENT_TYPE_VIDEO)
508                 ((CVideoInfo *)minfo)->Destroy();
509
510         delete minfo;
511
512         return false;
513 }
514
515 bool CMediadata::sm_CbEachFolderInfo(media_folder_h folder, void *dt)
516 {
517         CMediadata *root = (CMediadata *)dt;
518
519         if (!root)
520                 return false;
521
522         return root->m_HandleEachFolderInfo(folder);
523 }
524
525 bool CMediadata::m_HandleEachFolderInfo(media_folder_h folder)
526 {
527         CFolderInfo *finfo;
528         char *uuid;
529         char *buf;
530         int val;
531         int ret = -1;
532         filter_h filter;
533
534         finfo = new CFolderInfo;
535
536         finfo->Create();
537         if (!finfo) {
538                 _ERR("FolderInfo Create Failed");
539                 return false;
540         }
541
542         uuid = NULL;
543
544         m_CreateFilter(&filter, E_FILTER_TYPE_NONE);
545
546         if (media_folder_get_name(folder, &buf) !=
547                 MEDIA_CONTENT_ERROR_NONE) {
548                 _ERR("Media folder id Fetch error");
549                 goto error;
550         }
551         finfo->SetName(buf);
552
553         if (media_folder_get_modified_time(folder, (time_t *)&val)
554                 != MEDIA_CONTENT_ERROR_NONE) {
555                 _ERR("Media folder modified time Fetch error");
556                 goto error;
557         }
558         finfo->SetModifiedTime(val);
559
560         if (media_folder_get_folder_id(folder, &uuid)
561                 != MEDIA_CONTENT_ERROR_NONE) {
562                 _ERR("Media folder id Fetch error");
563                 goto error;
564         }
565
566         ret = media_folder_foreach_media_from_db(uuid, filter,
567                 sm_CbEachMediaInfo, (void *)this);
568         if (ret != MEDIA_CONTENT_ERROR_NONE) {
569                 if (ret == MEDIA_CONTENT_ERROR_DB_FAILED)
570                         _ERR("MEDIA CONTENT ERROR DB FAILED");
571                 else if (ret == MEDIA_CONTENT_ERROR_DB_BUSY)
572                         _ERR("MEDIA CONTENT ERROR DB BUSY");
573                 else
574                         _ERR("MEDIA CONTENT ERROR GENERAL");
575                 goto error;
576         }
577
578         finfo->SetMediaList(m->folder_medialist);
579         m_GetMediaList();
580
581         m_DeleteMediaList(E_TYPE_FOLDER_MEDIA);
582
583         m->folderlist = eina_list_append(m->folderlist, finfo);
584
585         m_DestroyFilter(filter);
586         free(uuid);
587
588         return true;
589
590 error:
591         _ERR("Error in creating Media list");
592         m_DestroyFilter(filter);
593         finfo->Destroy();
594         delete finfo;
595         free(uuid);
596         DestroyMediaList();
597
598         return false;
599 }
600
601 bool CMediadata::Initialize(void)
602 {
603         int ret;
604
605         if (g_ref_count > 0) {
606                 g_ref_count++;
607                 return false;
608         }
609
610         instance = new CMediadata;
611         if (!instance)
612                 return false;
613
614         instance->m = new SMediadata;
615         if (!instance->m) {
616                 _ERR("Mediadata init failed");
617                 delete instance;
618                 instance = NULL;
619                 return false;
620         }
621
622         ret = media_content_connect();
623         if (ret != MEDIA_CONTENT_ERROR_NONE) {
624                 _ERR("Media Content Connect Failed");
625                 return false;
626         }
627
628         g_ref_count++;
629
630         return true;
631 }
632
633 void CMediadata::Finalize(void)
634 {
635         if (!instance || !instance->m)
636                 return;
637
638         int ret;
639
640         if (g_ref_count <= 0)
641                 return;
642
643         g_ref_count--;
644
645         if (g_ref_count == 0) {
646                 instance->m_DeleteFolderList();
647                 instance->m_DeleteEventList();
648                 instance->m_DeleteMediaList(E_TYPE_MEDIA);
649                 instance->m_DeleteMediaList(E_TYPE_FOLDER_MEDIA);
650
651                 ret = media_content_disconnect();
652                 if (ret != MEDIA_CONTENT_ERROR_NONE)
653                         _ERR("Media Content Connect Failed");
654         }
655
656         delete instance->m;
657
658         delete instance;
659         instance = NULL;
660 }
661
662 CMediadata *CMediadata::GetInstance()
663 {
664         return instance;
665 }
666
667 bool CMediadata::CreateMediaList(int source_type, int media)
668 {
669         int ret;
670
671         m->source_type = source_type;
672         m->media = media;
673
674         m_CreateFilter(&m->filter, E_FILTER_TYPE_FOLDER);
675
676         ret = media_folder_foreach_folder_from_db(m->filter,
677                 sm_CbEachFolderInfo, (void *)this);
678         if (ret != MEDIA_CONTENT_ERROR_NONE) {
679                 _ERR("Failed to read from folders");
680                 m_DestroyFilter(m->filter);
681                 return false;
682         }
683
684         if (m->medialist)
685                 m_GetEventList();
686
687         m_DestroyFilter(m->filter);
688
689         return true;
690 }
691
692 CMediaInfo *CMediadata::FindMediaInfo(Eina_List *media_list, const char *path)
693 {
694         Eina_List *l;
695         CMediaInfo *minfo;
696         void *obj;
697
698         if (!media_list || !path)
699                 return NULL;
700
701         minfo = NULL;
702         EINA_LIST_FOREACH(media_list, l, obj) {
703                 minfo = (CMediaInfo *)obj;
704
705                 if (!strcmp(minfo->Path(), path))
706                         return minfo;
707         }
708
709         return NULL;
710 }
711
712 Eina_List *CMediadata::CreateListforType(Eina_List *media_list, int type)
713 {
714         Eina_List *l, *new_list;
715         CMediaInfo *minfo;
716         void *obj;
717
718         if (!media_list)
719                 return NULL;
720
721         new_list = NULL;
722         EINA_LIST_FOREACH(media_list, l, obj) {
723                 minfo = (CMediaInfo *)obj;
724
725                 if (type == minfo->Type())
726                         new_list = eina_list_append(new_list, minfo);
727         }
728
729         return new_list;
730 }
731
732 Eina_List *CMediadata::MediaList(void)
733 {
734         if (!m)
735                 return NULL;
736
737         return m->medialist;
738 }
739
740 Eina_List *CMediadata::EventList(void)
741 {
742         if (!m)
743                 return NULL;
744
745         return m->eventlist;
746 }
747
748 Eina_List *CMediadata::FolderList(void)
749 {
750         if (!m)
751                 return NULL;
752
753         return m->folderlist;
754 }