fix to use evas_object_color_set
[profile/tv/apps/native/air_mediahub.git] / src / layout / movie.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/progressbar.h"
30 #include "util/util.h"
31
32 #define LIST_MEDIA_COND "media_type=1 AND copyright NOT LIKE \"Unknown\""
33
34 #define TEXT_NOCONTENT "No Movies"
35 #define TEXT_RECENTLY_WATCHED "Recently watched"
36
37 #define GRID_PADDING 26
38 #define GRID_ITEM_X (378 + GRID_PADDING)
39 #define GRID_ITEM_Y (294 + GRID_PADDING)
40 #define GRID_NUM_ITEM 2
41
42 #define BOX_PADDING (62 - GRID_PADDING)
43
44 #define IMAGE_FAVORITE_ALPHA 150
45
46 struct _priv {
47         Evas_Object *base;
48         Evas_Object *layout;
49         Evas_Object *box;
50         Evas_Object *menu_btn;
51
52         layoutmgr *lmgr;
53
54         struct listmgr *listmgr;
55         struct listmgr_data *ldata;
56
57         struct mediadata *md;
58
59         struct progressbar *prog;
60
61         Eina_List *media_list;
62         int cur_index;
63
64         app_media *recent_info;
65 };
66
67 static char *_grid_text_get(void *data, Evas_Object *obj, const char *part)
68 {
69         app_media *am;
70         app_media_info *info;
71
72         if (!data)
73                 return NULL;
74
75         am = data;
76
77         if (!strcmp(part, PART_ELM_TEXT_TITLE)) {
78                 info = app_media_get_info(am);
79                 if (!info) {
80                         _ERR("failed to get media info");
81                         return NULL;
82                 }
83
84                 return strdup(info->title);
85         }
86
87         return NULL;
88 }
89
90 static Evas_Object *_grid_content_get(void *data,
91                         Evas_Object *obj, const char *part)
92 {
93         Evas_Object *image;
94         app_media *am;
95         app_media_info *info;
96
97         if (!data)
98                 return NULL;
99
100         am = data;
101         info = app_media_get_info(am);
102         if (!info) {
103                 _ERR("failed to get media info");
104                 return NULL;
105         }
106
107         image = NULL;
108         if (!strcmp(part, PART_ELM_SWALLOW_THUMBNAIL)) {
109                 image = util_add_image(obj, info->thumbnail_path);
110                 if (!image) {
111                         _ERR("failed to create image object");
112                         return NULL;
113                 }
114
115                 evas_object_show(image);
116         } else if (!strcmp(part, PART_ELM_SWALLOW_FAVORITE)) {
117                 if (!info->favorite)
118                         return NULL;
119
120                 image = util_add_image(obj, IMAGE_THUMBNAIL_FAVORITE);
121                 if (!image) {
122                         _ERR("failed to create image object");
123                         return NULL;
124                 }
125
126                 util_set_alpha_color(image, IMAGE_FAVORITE_ALPHA);
127
128                 evas_object_show(image);
129         }
130
131         return image;
132 }
133
134 static struct grid_class _gclass = {
135         .item_style = STYLE_GRID_MOVIE_ITEM,
136         .text_get = _grid_text_get,
137         .content_get = _grid_content_get
138 };
139
140 static bool _update_recent(void *data, Evas_Object *base)
141 {
142         Evas_Object *recent, *image;
143         app_media_info *info;
144         struct tm tm;
145         struct _priv *priv;
146         char buf[32];
147
148         if (!data || !base) {
149                 _ERR("invalid argument");
150                 return false;
151         }
152
153         priv = data;
154
155         recent = elm_object_part_content_get(base, PART_ITEM_CONTENT);
156         if (!recent) {
157                 _ERR("failed to get recent content part");
158                 return false;
159         }
160
161         image = elm_object_part_content_get(recent,
162                                 PART_RECENT_CONTENT_THUMBNAIL);
163         if (!image) {
164                 _ERR("failed to get image object");
165                 return false;
166         }
167
168         info = app_media_get_info(priv->recent_info);
169         if (!info) {
170                 _ERR("failed to get app media info");
171                 return false;
172         }
173
174         elm_image_file_set(image, info->thumbnail_path, NULL);
175         elm_image_aspect_fixed_set(image, EINA_FALSE);
176
177         elm_object_part_text_set(recent, PART_RECENT_CONTENT_TITLE,
178                                 info->title);
179
180         localtime_r(&info->played_time, &tm);
181         strftime(buf, sizeof(buf), "%Y.%m.%d", &tm);
182         elm_object_part_text_set(recent, PART_RECENT_CONTENT_DATE, buf);
183
184         if (info->favorite)
185                 elm_object_signal_emit(recent, SIG_RECENT_SHOW_FAV,
186                                         SIG_SOURCE_SRC);
187         else
188                 elm_object_signal_emit(recent, SIG_RECENT_HIDE_FAV,
189                                         SIG_SOURCE_SRC);
190
191         progressbar_reset(priv->prog, info->video->position,
192                                 info->video->duration);
193
194         progressbar_show(priv->prog);
195
196         return true;
197 }
198
199 static bool _draw_recent_title(Evas_Object *base)
200 {
201         Evas_Object *btn;
202
203         btn = elm_button_add(base);
204         if (!btn) {
205                 _ERR("failed to create button object");
206                 return false;
207         }
208
209         elm_object_style_set(btn, STYLE_BTN_INDEX);
210         elm_object_text_set(btn, TEXT_RECENTLY_WATCHED);
211
212         elm_object_part_content_set(base, PART_ITEM_TITLE, btn);
213
214         return true;
215 }
216
217 static bool _draw_recent_content(struct _priv *priv, Evas_Object *base)
218 {
219         Evas_Object *btn, *image;
220         struct progressbar *prog;
221
222         btn = elm_button_add(base);
223         if (!btn) {
224                 _ERR("failed to create button object");
225                 return false;
226         }
227
228         elm_object_style_set(btn, STYLE_BTN_RECENT_CONTENT);
229
230         image = elm_image_add(btn);
231         if (!image) {
232                 _ERR("failed to create image object");
233                 return false;
234         }
235
236         elm_object_part_content_set(btn, PART_RECENT_CONTENT_THUMBNAIL, image);
237
238         elm_object_part_content_set(base, PART_ITEM_CONTENT, btn);
239
240         prog = progressbar_create(btn, STYLE_BASE_PROGRESS);
241         if (!prog) {
242                 _ERR("failed to create progressbar");
243                 return false;
244         }
245
246         progressbar_set_parts(prog, PART_RECENT_CONTENT_SLIDER,
247                                 PART_RECENT_CONTENT_TOTAL,
248                                 PART_RECENT_CONTENT_PROGRESS, "");
249
250         priv->prog = prog;
251
252         return true;
253 }
254
255 static bool _draw_recent(void *data, Evas_Object *base)
256 {
257         struct _priv *priv;
258
259         if (!data || !base) {
260                 _ERR("invalid argument");
261                 return false;
262         }
263
264         priv = data;
265
266         if (!_draw_recent_title(base)) {
267                 _ERR("failed to draw recent title");
268                 return false;
269         }
270
271         if (!_draw_recent_content(priv, base)) {
272                 _ERR("failed to draw recent content");
273                 return false;
274         }
275
276         return true;
277 }
278
279 static void _item_selected_cb(struct _priv *priv, app_media *am)
280 {
281         struct view_update_data vdata;
282
283         vdata.list = mediadata_get_medialist(priv->md);
284         vdata.index = util_get_media_index(vdata.list, am);
285         priv->cur_index = vdata.index;
286
287         viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata);
288         viewmgr_push_view(VIEW_VIEWER);
289 }
290
291 static void _recent_selected_cb(void *data, Evas_Object *obj)
292 {
293         struct _priv *priv;
294
295         if (!data || !obj)
296                 return;
297
298         priv = data;
299
300         _item_selected_cb(priv, priv->recent_info);
301 }
302
303 static void _grid_selected_cb(void *data, Elm_Object_Item *it)
304 {
305         app_media *am;
306         struct _priv *priv;
307
308         if (!data || !it) {
309                 _ERR("invalid argument");
310                 return;
311         }
312
313         priv = data;
314
315         am = elm_object_item_data_get(it);
316         if (!am) {
317                 _ERR("failed to get app media");
318                 return;
319         }
320
321         _item_selected_cb(priv, am);
322 }
323
324 static struct listmgr_data *_create_listmgr_data(struct _priv *priv)
325 {
326         struct listmgr_data *data;
327         struct play_info_ops *pops;
328         struct grid_ops *gops;
329
330         data = calloc(1, sizeof(*data));
331         if (!data)
332                 goto err;
333
334         data->menu_btn = priv->menu_btn;
335
336         data->grid_item_x = GRID_ITEM_X;
337         data->grid_item_y = GRID_ITEM_Y;
338         data->grid_num_item = GRID_NUM_ITEM;
339         data->box_padding = BOX_PADDING;
340
341         pops = calloc(1, sizeof(*pops));
342         if (!pops)
343                 goto err;
344
345         pops->draw = _draw_recent;
346         pops->update = _update_recent;
347         pops->selected_cb = _recent_selected_cb;
348         pops->ops_data = priv;
349
350         gops = calloc(1, sizeof(*gops));
351         if (!gops)
352                 goto err;
353
354         gops->gclass = &_gclass;
355         gops->selected_cb = _grid_selected_cb;
356         gops->ops_data = priv;
357
358         data->pops = pops;
359         data->gops = gops;
360
361         return data;
362
363 err:
364         _ERR("failed to allocate memory");
365         return NULL;
366 }
367
368 static void _update_content_info(struct _priv *priv)
369 {
370         int count;
371         char buf[128];
372
373         count = mediadata_get_media_count(priv->md, E_MEDIA_VIDEO);
374         if (count < 0) {
375                 _ERR("failed to get media count");
376                 return;
377         }
378
379         snprintf(buf, sizeof(buf), "%d Movies", count);
380
381         elm_object_part_text_set(priv->layout, PART_CONTENT_INFO, buf);
382 }
383
384 static void _update_content_list(struct _priv *priv)
385 {
386         Eina_List *list;
387
388         if (priv->media_list)
389                 return;
390
391         list = mediadata_get_list(priv->md, E_LIST_NAME);
392         if (!list) {
393                 elm_object_part_text_set(priv->layout,
394                                 PART_NOCONTENT, TEXT_NOCONTENT);
395                 return;
396         }
397
398         if (!listmgr_update_content_list(priv->listmgr, list)) {
399                 _ERR("failed to update list area");
400                 return;
401         }
402
403         priv->media_list = list;
404
405         _update_content_info(priv);
406 }
407
408 static void _update_recent_item(struct _priv *priv, int index)
409 {
410         Eina_List *list;
411         app_media *am;
412         app_media_info *info;
413
414         list = mediadata_get_medialist(priv->md);
415         am = eina_list_nth(list, index);
416         if (!am) {
417                 _ERR("failed to get app media");
418                 return;
419         }
420
421         info = app_media_get_info(am);
422         if (!info) {
423                 _ERR("failed to get app media info");
424                 return;
425         }
426
427         priv->recent_info = am;
428
429         if (!listmgr_update_play_info(priv->listmgr, info))
430                 _ERR("failed to update recently watched item");
431 }
432
433 static bool _create(layoutmgr *lmgr, void *data)
434 {
435         struct listmgr *listmgr;
436         struct listmgr_data *ldata;
437         struct mediadata *md;
438         struct _priv *priv;
439         Evas_Object *base, *layout;
440
441         if (!lmgr) {
442                 _ERR("failed to get layoutmgr");
443                 return false;
444         }
445
446         if (!data) {
447                 _ERR("invalid argument");
448                 return false;
449         }
450
451         priv = calloc(1, sizeof(*priv));
452         if (!priv) {
453                 _ERR("failed to allocate priv");
454                 return false;
455         }
456
457         priv->menu_btn = (Evas_Object *)data;
458
459         base = layoutmgr_get_base(lmgr);
460         if (!base) {
461                 _ERR("failed to get base object");
462                 goto err;
463         }
464
465         layout = elm_layout_add(base);
466         if (!layout) {
467                 _ERR("failed to create layout");
468                 goto err;
469         }
470
471         if (!elm_layout_file_set(layout, EDJEFILE, GRP_MOVIE_LAYOUT)) {
472                 _ERR("failed to set layout file");
473                 goto err2;
474         }
475
476         ldata = _create_listmgr_data(priv);
477         if (!ldata) {
478                 _ERR("failed to create listmgr data");
479                 goto err2;
480         }
481
482         listmgr = listmgr_create(layout, (void *)ldata);
483         if (!listmgr) {
484                 _ERR("failed to create listmgr");
485                 goto err3;
486         }
487
488         md = mediadata_create(LIST_MEDIA_COND, E_SOURCE_ALL, E_SORT_NAME);
489         if (!md) {
490                 _ERR("failed to create mediadata");
491                 listmgr_destroy(listmgr);
492                 goto err3;
493         }
494
495         priv->base = base;
496         priv->layout = layout;
497         priv->lmgr = lmgr;
498         priv->listmgr = listmgr;
499         priv->ldata = ldata;
500         priv->md = md;
501
502         layoutmgr_set_layout_data(lmgr, LAYOUT_MOVIE, priv);
503
504         if (!listmgr_draw_list_area(priv->listmgr)) {
505                 _ERR("failed to draw list area");
506                 mediadata_destroy(md);
507                 listmgr_destroy(listmgr);
508                 goto err3;
509         }
510
511         return true;
512
513 err3:
514         free(ldata);
515 err2:
516         evas_object_del(layout);
517 err:
518         free(priv);
519         return false;
520 }
521
522 static void _destroy(void *layout_data)
523 {
524         struct _priv *priv;
525
526         if (!layout_data) {
527                 _ERR("failed to get layout data");
528                 return;
529         }
530
531         priv = layout_data;
532
533         progressbar_destroy(priv->prog);
534
535         mediadata_free_list(priv->media_list);
536         mediadata_destroy(priv->md);
537
538         listmgr_destroy(priv->listmgr);
539         free(priv->ldata->pops);
540         free(priv->ldata->gops);
541         free(priv->ldata);
542
543         evas_object_del(priv->layout);
544
545         free(priv);
546 }
547
548 static void _show(void *layout_data)
549 {
550         struct _priv *priv;
551
552         if (!layout_data) {
553                 _ERR("failed to layout data");
554                 return;
555         }
556
557         priv = layout_data;
558
559         evas_object_show(priv->layout);
560         elm_object_part_content_set(priv->base,
561                         PART_THUMBNAIL_AREA, priv->layout);
562 }
563
564 static void _hide(void *layout_data)
565 {
566         struct _priv *priv;
567
568         if (!layout_data) {
569                 _ERR("failed to get layout data");
570                 return;
571         }
572
573         priv = layout_data;
574
575         evas_object_hide(priv->layout);
576         elm_object_part_content_unset(priv->base, PART_THUMBNAIL_AREA);
577 }
578
579 static void _update(void *layout_data, int update_type, void *data)
580 {
581         struct view_update_data *vdata;
582         struct _priv *priv;
583
584         if (!layout_data) {
585                 _ERR("failed to get layout data");
586                 return;
587         }
588
589         priv = layout_data;
590         vdata = data;
591
592         switch (update_type) {
593         case UPDATE_CONTENT:
594                 _update_content_list(priv);
595                 break;
596         case UPDATE_FOCUS:
597                 if (!vdata) {
598                         _ERR("invalid argument");
599                         return;
600                 }
601
602                 listmgr_focus_play_info(priv->listmgr);
603                 _update_recent_item(priv, vdata->index);
604                 break;
605         case UPDATE_RESUME:
606                 listmgr_focus_content_list(priv->listmgr,
607                                 priv->cur_index, false);
608                 break;
609         default:
610                 break;
611         }
612 }
613
614 static layout_class _lclass = {
615         .layout_id = LAYOUT_MOVIE,
616         .create = _create,
617         .show = _show,
618         .hide = _hide,
619         .destroy = _destroy,
620         .update = _update,
621 };
622
623 layout_class *layout_movie_get_lclass(void)
624 {
625         return &_lclass;
626 }