support pause/resume the application
[profile/tv/apps/native/air_mediahub.git] / src / layout / gallery.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 #include <gridmgr.h>
22 #include <layoutmgr.h>
23 #include <viewmgr.h>
24
25 #include "define.h"
26 #include "view.h"
27 #include "data/mediadata.h"
28 #include "util/listmgr.h"
29 #include "util/util.h"
30
31 /*
32    FIXME
33 #define LIST_MEDIA_COND "media_type=0 OR \
34                         (media_type=1 AND copyright LIKE \"Unknown\")"
35 */
36 #define LIST_MEDIA_COND "(media_type=0 OR media_type=1) AND copyright LIKE \"Unknown\""
37
38 #define TEXT_NOCONTENT "No Photo & Video"
39
40 #define GRID_PADDING 6
41 #define GRID_ITEM_X (200 + GRID_PADDING)
42 #define GRID_ITEM_Y (200 + GRID_PADDING)
43 #define GRID_NUM_ITEM 3
44
45 #define BOX_PADDING (62 - GRID_PADDING)
46
47 #define IMAGE_FAVORITE_ALPHA 150
48
49 struct _priv {
50         Evas_Object *base;
51         Evas_Object *layout;
52         Evas_Object *menu_btn;
53
54         layoutmgr *lmgr;
55
56         struct listmgr *listmgr;
57         struct listmgr_data *ldata;
58
59         struct mediadata *md;
60         int cur_index;
61
62         Eina_List *media_list;
63 };
64
65 static char *_grid_text_get(void *data, Evas_Object *obj, const char *part)
66 {
67         app_media *am;
68         app_media_info *info;
69         char buf[32];
70
71         if (!data)
72                 return NULL;
73
74         am = data;
75         info = app_media_get_info(am);
76         if (!info) {
77                 _ERR("failed to get media info");
78                 return NULL;
79         }
80
81         if (info->media_type != MEDIA_CONTENT_TYPE_VIDEO)
82                 return NULL;
83
84         if (!strcmp(part, PART_ELM_TEXT_PLAYTIME)) {
85                 util_time_string(buf, sizeof(buf),
86                                         info->video->duration, false);
87
88                 return strdup(buf);
89         }
90
91         return NULL;
92 }
93
94 static Evas_Object *_grid_content_get(void *data,
95                         Evas_Object *obj, const char *part)
96 {
97         Evas_Object *image;
98         app_media *am;
99         app_media_info *info;
100
101         if (!data)
102                 return NULL;
103
104         am = data;
105         info = app_media_get_info(am);
106         if (!info) {
107                 _ERR("failed to get media info");
108                 return NULL;
109         }
110
111         image = NULL;
112         if (!strcmp(part, PART_ELM_SWALLOW_THUMBNAIL)) {
113                 image = util_add_image(obj, info->thumbnail_path);
114                 if (!image) {
115                         _ERR("failed to create image object");
116                         return NULL;
117                 }
118
119                 evas_object_show(image);
120         } else if (!strcmp(part, PART_ELM_SWALLOW_VIDEO)) {
121                 if (info->media_type == MEDIA_CONTENT_TYPE_VIDEO) {
122                         image = util_add_image(obj, IMAGE_THUMBNAIL_PLAY);
123                         if (!image) {
124                                 _ERR("failed to create image object");
125                                 return NULL;
126                         }
127
128                         evas_object_show(image);
129                 }
130         } else if (!strcmp(part, PART_ELM_SWALLOW_FAVORITE)) {
131                 int r, g, b, a;
132
133                 if (!info->favorite)
134                         return NULL;
135
136                 image = util_add_image(obj, IMAGE_THUMBNAIL_FAVORITE);
137                 if (!image) {
138                         _ERR("failed to create image object");
139                         return NULL;
140                 }
141
142                 evas_object_color_get(image, &r, &g, &b, &a);
143                 evas_object_color_set(image, r, g, b, IMAGE_FAVORITE_ALPHA);
144
145                 evas_object_show(image);
146         }
147
148         return image;
149 }
150
151 static struct grid_class _gclass = {
152         .item_style = STYLE_GRID_GALLERY_ITEM,
153         .text_get = _grid_text_get,
154         .content_get = _grid_content_get
155 };
156
157 static void _grid_selected_cb(void *data, Elm_Object_Item *it)
158 {
159         app_media *am;
160         struct view_update_data vdata;
161         struct _priv *priv;
162
163         if (!data || !it) {
164                 _ERR("invalid argument");
165                 return;
166         }
167
168         priv = data;
169
170         am = elm_object_item_data_get(it);
171         if (!am) {
172                 _ERR("failed to get app media");
173                 return;
174         }
175
176         vdata.list = mediadata_get_medialist(priv->md);
177         vdata.index = util_get_media_index(vdata.list, am);
178         priv->cur_index = vdata.index;
179
180         viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata);
181         viewmgr_push_view(VIEW_VIEWER);
182 }
183
184 static struct listmgr_data *_create_listmgr_data(struct _priv *priv)
185 {
186         struct listmgr_data *data;
187         struct grid_ops *gops;
188
189         data = calloc(1, sizeof(*data));
190         if (!data)
191                 goto err;
192
193         data->menu_btn = priv->menu_btn;
194
195         data->grid_item_x = GRID_ITEM_X;
196         data->grid_item_y = GRID_ITEM_Y;
197         data->grid_num_item = GRID_NUM_ITEM;
198         data->box_padding = BOX_PADDING;
199
200         gops = calloc(1, sizeof(*gops));
201         if (!gops)
202                 goto err;
203
204         gops->gclass = &_gclass;
205         gops->selected_cb = _grid_selected_cb;
206         gops->ops_data = priv;
207
208         data->gops = gops;
209
210         return data;
211
212 err:
213         _ERR("failed to allocate memory");
214         return NULL;
215 }
216
217 static void _update_content_info(struct _priv *priv)
218 {
219         int photo, video;
220         char buf[128];
221
222         photo = mediadata_get_media_count(priv->md, E_MEDIA_PHOTO);
223         video = mediadata_get_media_count(priv->md, E_MEDIA_VIDEO);
224
225         if (photo < 0 || video < 0) {
226                 _ERR("failed to get media count");
227                 return;
228         }
229
230         snprintf(buf, sizeof(buf), "%d Photos, %d Videos", photo, video);
231
232         elm_object_part_text_set(priv->layout, PART_CONTENT_INFO, buf);
233 }
234
235 static void _update_content_list(struct _priv *priv)
236 {
237         Eina_List *list;
238
239         if (priv->media_list)
240                 return;
241
242         list = mediadata_get_list(priv->md, E_LIST_DATE);
243         if (!list) {
244                 elm_object_part_text_set(priv->layout,
245                                 PART_NOCONTENT, TEXT_NOCONTENT);
246                 return;
247         }
248
249         if (!listmgr_update_content_list(priv->listmgr, list))
250                 _ERR("failed to update list area");
251
252         priv->media_list = list;
253
254         _update_content_info(priv);
255 }
256
257 static bool _create(layoutmgr *lmgr, void *data)
258 {
259         struct listmgr *listmgr;
260         struct listmgr_data *ldata;
261         struct mediadata *md;
262         struct _priv *priv;
263         Evas_Object *base, *layout;
264
265         if (!lmgr) {
266                 _ERR("failed to get layoutmgr");
267                 return false;
268         }
269
270         if (!data) {
271                 _ERR("invalid argument");
272                 return false;
273         }
274
275         priv = calloc(1, sizeof(*priv));
276         if (!priv) {
277                 _ERR("failed to allocate priv");
278                 return false;
279         }
280
281         priv->menu_btn = (Evas_Object *)data;
282
283         base = layoutmgr_get_base(lmgr);
284         if (!base) {
285                 _ERR("failed to get base object");
286                 goto err;
287         }
288
289         layout = elm_layout_add(base);
290         if (!layout) {
291                 _ERR("failed to create layout");
292                 goto err;
293         }
294
295         if (!elm_layout_file_set(layout, EDJEFILE, GRP_GALLERY_LAYOUT)) {
296                 _ERR("failed to set layout file");
297                 goto err2;
298         }
299
300         ldata = _create_listmgr_data(priv);
301         if (!ldata) {
302                 _ERR("failed to create listmgr data");
303                 goto err2;
304         }
305
306         listmgr = listmgr_create(layout, (void *)ldata);
307         if (!listmgr) {
308                 _ERR("failed to create listmgr");
309                 goto err3;
310         }
311
312         md = mediadata_create(LIST_MEDIA_COND, E_SOURCE_ALL, E_SORT_DATE);
313         if (!md) {
314                 _ERR("failed to create mediadata");
315                 listmgr_destroy(listmgr);
316                 goto err3;
317         }
318
319         priv->base = base;
320         priv->layout = layout;
321         priv->lmgr = lmgr;
322         priv->listmgr = listmgr;
323         priv->ldata = ldata;
324         priv->md = md;
325
326         layoutmgr_set_layout_data(lmgr, LAYOUT_GALLERY, priv);
327
328         if (!listmgr_draw_list_area(listmgr)) {
329                 _ERR("failed to draw list area");
330                 mediadata_destroy(md);
331                 listmgr_destroy(listmgr);
332                 goto err3;
333         }
334
335         return true;
336
337 err3:
338         free(ldata);
339 err2:
340         evas_object_del(layout);
341 err:
342         free(priv);
343         return false;
344 }
345
346 static void _destroy(void *layout_data)
347 {
348         struct _priv *priv;
349
350         if (!layout_data) {
351                 _ERR("failed to get layout data");
352                 return;
353         }
354
355         priv = layout_data;
356
357         mediadata_free_list(priv->media_list);
358         mediadata_destroy(priv->md);
359
360         listmgr_destroy(priv->listmgr);
361         free(priv->ldata->gops);
362         free(priv->ldata);
363
364         evas_object_del(priv->layout);
365
366         free(priv);
367 }
368
369 static void _show(void *layout_data)
370 {
371         struct _priv *priv;
372
373         if (!layout_data) {
374                 _ERR("failed to layout data");
375                 return;
376         }
377
378         priv = layout_data;
379
380         evas_object_show(priv->layout);
381         elm_object_part_content_set(priv->base,
382                         PART_THUMBNAIL_AREA, priv->layout);
383 }
384
385 static void _hide(void *layout_data)
386 {
387         struct _priv *priv;
388
389         if (!layout_data) {
390                 _ERR("failed to get layout data");
391                 return;
392         }
393
394         priv = layout_data;
395
396         evas_object_hide(priv->layout);
397         elm_object_part_content_unset(priv->base, PART_THUMBNAIL_AREA);
398 }
399
400 static void _update(void *layout_data, int update_type, void *data)
401 {
402         struct view_update_data *vdata;
403         struct _priv *priv;
404         bool update;
405
406         if (!layout_data) {
407                 _ERR("failed to get layout data");
408                 return;
409         }
410
411         priv = layout_data;
412         vdata = data;
413
414         switch (update_type) {
415         case UPDATE_CONTENT:
416                 _update_content_list(priv);
417                 break;
418         case UPDATE_FOCUS:
419                 if (!vdata) {
420                         _ERR("invalid argument");
421                         return;
422                 }
423
424                 if (priv->cur_index != vdata->index)
425                         update = true;
426                 else
427                         update = false;
428
429                 listmgr_focus_content_list(priv->listmgr, vdata->index, update);
430
431                 break;
432         case UPDATE_RESUME:
433                 listmgr_focus_content_list(priv->listmgr,
434                                 priv->cur_index, false);
435                 break;
436         default:
437                 break;
438         }
439 }
440
441 static layout_class _lclass = {
442         .layout_id = LAYOUT_GALLERY,
443         .create = _create,
444         .show = _show,
445         .hide = _hide,
446         .destroy = _destroy,
447         .update = _update,
448 };
449
450 layout_class *layout_gallery_get_lclass(void)
451 {
452         return &_lclass;
453 }