d55d2ca33373c7797538936bdae0c2615b0af61e
[profile/tv/apps/native/air_mediahub.git] / src / view / detail.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_contents.h>
21 #include <app_media.h>
22 #include <inputmgr.h>
23 #include <viewmgr.h>
24
25 #include "define.h"
26 #include "view.h"
27 #include "data/datamgr.h"
28 #include "grid/grid.h"
29 #include "util/util.h"
30
31 #define STR_NO_PLAY_MOVIE "No recently watched movie"
32 #define STR_NO_PLAY_MUSIC "No music in playlist"
33
34 struct _priv;
35
36 static char *_grid_text_get(void *data, Evas_Object *obj, const char *part);
37 static Evas_Object *_grid_content_get(void *data, Evas_Object *obj,
38                         const char *part);
39
40 static char *_album_text_get(void *data, Evas_Object *obj, const char *part);
41 static Evas_Object *_album_content_get(void *data, Evas_Object *obj,
42                         const char *part);
43
44 static void _get_movie_info(struct _priv *priv, const char *title);
45 static void _get_gallery_info(struct _priv *priv, const char *title);
46 static void _get_song_info(struct _priv *priv, const char *title);
47 static void _get_album_info(struct _priv *priv, const char *title);
48
49 static void _album_selected(void *data);
50
51 enum _object_type {
52         DETAIL_GRID = 0,
53         DETAIL_PLAY_INFO
54 };
55
56 struct _list_info {
57         Eina_List *list;
58         const char *title;
59 };
60
61 struct _view_info {
62         const char *grid_style;
63         int grid_item_x;
64         int grid_item_y;
65         char *(*get_grid_text)(void *data, Evas_Object *obj, const char *part);
66         Evas_Object *(*get_grid_content)(void *data, Evas_Object *obj,
67                                 const char *part);
68         void (*get_content_info)(struct _priv *priv, const char *title);
69
70         void (*selected)(void *data);
71         bool detail_update;
72
73         int app_contents_type;
74 };
75
76 static struct _view_info view_info[E_DETAIL_MAX] = {
77         [E_DETAIL_MOVIE_GENRE] = {
78                 .grid_style = STYLE_MOVIE_NAME,
79                 .grid_item_x = MOVIE_NAME_ITEM_X,
80                 .grid_item_y = MOVIE_NAME_ITEM_Y,
81                 .get_grid_text = _grid_text_get,
82                 .get_grid_content = _grid_content_get,
83                 .get_content_info = _get_movie_info,
84                 .detail_update = EINA_FALSE,
85                 .app_contents_type = CONTENTS_MOVIE,
86         },
87         [E_DETAIL_GALLERY_PLACE] = {
88                 .grid_style = STYLE_GALLERY_EVENT,
89                 .grid_item_x = GALLERY_EVENT_ITEM_X,
90                 .grid_item_y = GALLERY_EVENT_ITEM_Y,
91                 .get_grid_text = _grid_text_get,
92                 .get_grid_content = _grid_content_get,
93                 .get_content_info = _get_gallery_info,
94                 .detail_update = EINA_FALSE,
95                 .app_contents_type = CONTENTS_GALLERY,
96         },
97         [E_DETAIL_MUSIC_ALBUM] = {
98                 .grid_style = STYLE_MUSIC_SONG_DETAIL,
99                 .grid_item_x = MUSIC_SONG_ITEM_X,
100                 .grid_item_y = MUSIC_SONG_ITEM_Y,
101                 .get_grid_text = _grid_text_get,
102                 .get_grid_content = _grid_content_get,
103                 .get_content_info = _get_song_info,
104                 .detail_update = EINA_FALSE,
105                 .app_contents_type = CONTENTS_MUSIC,
106         },
107         [E_DETAIL_MUSIC_ARTIST] = {
108                 .grid_style = STYLE_MUSIC_ALBUM,
109                 .grid_item_x = MUSIC_ALBUM_ITEM_X,
110                 .grid_item_y = MUSIC_ALBUM_ITEM_Y,
111                 .get_grid_text = _album_text_get,
112                 .get_grid_content = _album_content_get,
113                 .get_content_info = _get_album_info,
114                 .selected = _album_selected,
115                 .detail_update = EINA_TRUE,
116                 .app_contents_type = CONTENTS_MUSIC,
117         },
118         [E_DETAIL_MUSIC_GENRE] = {
119                 .grid_style = STYLE_MUSIC_SONG_DETAIL,
120                 .grid_item_x = MUSIC_SONG_ITEM_X,
121                 .grid_item_y = MUSIC_SONG_ITEM_Y,
122                 .get_grid_text = _grid_text_get,
123                 .get_grid_content = _grid_content_get,
124                 .get_content_info = _get_song_info,
125                 .detail_update = EINA_FALSE,
126                 .app_contents_type = CONTENTS_MUSIC,
127         },
128 };
129
130 struct _priv {
131         Evas_Object *win;
132         Evas_Object *base;
133         Evas_Object *grid;
134         Evas_Object *btn;
135         Evas_Object *thumbnail;
136
137         Elm_Object_Item *focused_it;
138
139         Eina_List *media_list;
140         Eina_List *view_list;
141         Eina_List *play_list;
142
143         struct datamgr *dmgr;
144
145         app_media *play_info;
146
147         int view_type;
148         int depth;
149
150         int status;
151
152         struct _view_info *vinfo;
153 };
154
155 static void _destroy_play_list(struct _priv *priv)
156 {
157         eina_list_free(priv->play_list);
158         priv->play_list = NULL;
159 }
160
161 static void _update_view(struct _priv *priv)
162 {
163         struct _list_info *linfo;
164         struct view_update_data vdata;
165
166         linfo = eina_list_data_get(priv->view_list);
167         priv->view_list = eina_list_remove(priv->view_list, linfo);
168
169         vdata.list = linfo->list;
170         vdata.index = E_DETAIL_MUSIC_ARTIST;
171         vdata.id = linfo->title;
172
173         viewmgr_update_view(VIEW_DETAIL, UPDATE_CONTENT, &vdata);
174         viewmgr_push_view(VIEW_DETAIL);
175
176         priv->depth--;
177
178         free(linfo);
179 }
180
181 static void _pop_view(void)
182 {
183         viewmgr_update_view(VIEW_BASE, UPDATE_BACK, NULL);
184         viewmgr_pop_view();
185 }
186
187 static void _key_down_cb(int id, void *data, Evas *e, Evas_Object *obj,
188                         Evas_Event_Key_Down *ev)
189 {
190         struct _priv *priv;
191
192         if (!data || !ev) {
193                 _ERR("invalid argument");
194                 return;
195         }
196
197         priv = data;
198
199         switch (id) {
200         case DETAIL_GRID:
201                 if (!strcmp(ev->keyname, KEY_BACK) ||
202                         !strcmp(ev->keyname, KEY_ESC)) {
203                         if (priv->depth > 0)
204                                 _update_view(priv);
205                         else
206                                 _pop_view();
207                 }
208
209                 break;
210         case DETAIL_PLAY_INFO:
211                 if (!strcmp(ev->keyname, KEY_BACK) ||
212                         !strcmp(ev->keyname, KEY_ESC))
213                         elm_object_focus_set(priv->grid, EINA_TRUE);
214
215                 break;
216         default:
217                 break;
218         }
219 }
220
221 static void _focused_cb(int id, void *data, Evas_Object *obj,
222                         Elm_Object_Item *it)
223 {
224         struct _priv *priv;
225
226         if (!data)
227                 return;
228
229         priv = data;
230
231         if (it)
232                 priv->focused_it = it;
233 }
234
235 static void _clicked_cb(int id, void *data, Evas_Object *obj)
236 {
237         struct view_update_data vdata;
238         struct _priv *priv;
239         int type;
240
241         if (!data) {
242                 _ERR("invalid argument");
243                 return;
244         }
245
246         priv = data;
247
248         type = priv->vinfo->app_contents_type;
249
250         switch (type) {
251         case CONTENTS_MOVIE:
252                 _destroy_play_list(priv);
253
254                 priv->play_list = eina_list_append(priv->play_list,
255                                         priv->play_info);
256
257                 vdata.list = priv->play_list;
258                 vdata.index = 0;
259                 vdata.id = VIEW_DETAIL;
260
261                 viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata);
262                 viewmgr_push_view(VIEW_VIEWER);
263
264                 break;
265         case CONTENTS_MUSIC:
266                 viewmgr_push_view(VIEW_MPLAYER);
267                 break;
268         default:
269                 break;
270         }
271 }
272
273 static void _media_selected(void *data)
274 {
275         struct _priv *priv;
276         struct view_update_data vdata;
277         app_media *am;
278
279         if (!data) {
280                 _ERR("invalid argument");
281                 return;
282         }
283
284         priv = data;
285
286         am = elm_object_item_data_get(priv->focused_it);
287         if (!am) {
288                 _ERR("failed to get app media");
289                 return;
290         }
291
292         vdata.list = priv->media_list;
293         vdata.index = util_get_media_index(vdata.list, am);
294         vdata.id = VIEW_DETAIL;
295
296         switch (priv->view_type) {
297         case E_DETAIL_MOVIE_GENRE:
298         case E_DETAIL_GALLERY_PLACE:
299                 viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata);
300                 viewmgr_push_view(VIEW_VIEWER);
301                 break;
302         case E_DETAIL_MUSIC_ALBUM:
303         case E_DETAIL_MUSIC_GENRE:
304                 viewmgr_update_view(VIEW_MPLAYER, UPDATE_CONTENT, &vdata);
305                 viewmgr_push_view(VIEW_MPLAYER);
306                 break;
307         default:
308                 break;
309         }
310 }
311
312 static void _album_selected(void *data)
313 {
314         struct _priv *priv;
315         struct view_update_data vdata;
316         struct _list_info *linfo;
317         struct datamgr *dmgr;
318         struct album_info *ai;
319
320         if (!data) {
321                 _ERR("invalid argument");
322                 return;
323         }
324
325         priv = data;
326
327         dmgr = priv->dmgr;
328
329         ai = elm_object_item_data_get(priv->focused_it);
330         if (!ai) {
331                 _ERR("failed to get album info");
332                 return;
333         }
334
335         linfo = calloc(1, sizeof(*linfo));
336         if (!linfo) {
337                 _ERR("failed to allocate list info");
338                 return;
339         }
340
341         linfo->list = priv->media_list;
342         linfo->title = ai->artist;
343
344         priv->view_list = eina_list_append(priv->view_list, linfo);
345
346         vdata.list = dmgr->ops->get_list(dmgr->handle,
347                                 E_LIST_ALBUM_MEDIA, &ai->id);
348         vdata.index = E_DETAIL_MUSIC_ALBUM;
349         vdata.id = ai->name;
350
351         viewmgr_update_view(VIEW_DETAIL, UPDATE_CONTENT, &vdata);
352         viewmgr_push_view(VIEW_DETAIL);
353
354         priv->depth++;
355 }
356
357 static void _selected_cb(int id, void *data, Evas_Object *obj,
358                         Elm_Object_Item *it)
359 {
360         struct _priv *priv;
361         void (*_selected)(void *data);
362
363         if (!data || !it)
364                 return;
365
366         priv = data;
367
368         if (priv->vinfo->detail_update)
369                 _selected = priv->vinfo->selected;
370         else
371                 _selected = _media_selected;
372
373         ecore_job_add(_selected, priv);
374 }
375
376 static input_handler _handler = {
377         .key_down = _key_down_cb,
378         .focused = _focused_cb,
379         .clicked = _clicked_cb,
380         .selected = _selected_cb
381 };
382
383 static char *_grid_text_get(void *data, Evas_Object *obj, const char *part)
384 {
385         app_media *am;
386         app_media_info *mi;
387         int duration;
388         char buf[32];
389
390         if (!data)
391                 return NULL;
392
393         am = data;
394
395         mi = app_media_get_info(am);
396         if (!mi) {
397                 _ERR("failed to get media info");
398                 return NULL;
399         }
400
401         if (!strcmp(part, PART_ELM_TEXT_TITLE))
402                 return strdup(mi->title);
403         else if (!strcmp(part, PART_ELM_TEXT_ALBUM))
404                 return strdup(mi->audio->album);
405         else if (!strcmp(part, PART_ELM_TEXT_ARTIST))
406                 return strdup(mi->audio->artist);
407         else if (!strcmp(part, PART_ELM_TEXT_PLAYTIME)) {
408                 if (mi->media_type == MEDIA_CONTENT_TYPE_VIDEO)
409                         duration = mi->video->duration;
410                 else if (mi->media_type == MEDIA_CONTENT_TYPE_MUSIC)
411                         duration = mi->audio->duration;
412                 else
413                         return NULL;
414
415                 util_time_string(buf, sizeof(buf), duration, false);
416
417                 return strdup(buf);
418         }
419
420         return NULL;
421 }
422
423 static Evas_Object *_grid_content_get(void *data, Evas_Object *obj,
424                         const char *part)
425 {
426         Evas_Object *eo;
427         app_media *am;
428         app_media_info *mi;
429         struct color_data bg;
430
431         if (!data)
432                 return NULL;
433
434         am = data;
435
436         mi = app_media_get_info(am);
437         if (!mi) {
438                 _ERR("failed to get media info");
439                 return NULL;
440         }
441
442         eo = NULL;
443         if (!strcmp(part, PART_ELM_SWALLOW_THUMBNAIL)) {
444                 eo = util_add_image(obj, mi->thumbnail_path);
445                 if (!eo) {
446                         _ERR("failed to create image object");
447                         return NULL;
448                 }
449         } else if (!strcmp(part, PART_ELM_SWALLOW_FAVORITE)) {
450                 if (!mi->favorite)
451                         return NULL;
452
453                 eo = util_add_image(obj, IMAGE_THUMBNAIL_FAVORITE);
454                 if (!eo) {
455                         _ERR("failed to create image object");
456                         return NULL;
457                 }
458         } else if (!strcmp(part, PART_ELM_SWALLOW_TEXTBG)) {
459                 eo = evas_object_rectangle_add(obj);
460                 if (!eo) {
461                         _ERR("failed to create rectangle object");
462                         return NULL;
463                 }
464
465                 app_contents_get_color(mi->title, NULL, &bg);
466                 evas_object_color_set(eo, bg.r, bg.g, bg.b, bg.a);
467         } else if (!strcmp(part, PART_ELM_SWALLOW_VIDEO)) {
468                 if (mi->media_type != MEDIA_CONTENT_TYPE_VIDEO)
469                         return NULL;
470
471                 eo = util_add_image(obj, IMAGE_THUMBNAIL_PLAY);
472                 if (!eo) {
473                         _ERR("failed to create image object");
474                         return NULL;
475                 }
476         }
477
478         if (eo)
479                 evas_object_show(eo);
480
481         return eo;
482 }
483
484 static char *_album_text_get(void *data, Evas_Object *obj, const char *part)
485 {
486         struct album_info *ai;
487
488         if (!data)
489                 return NULL;
490
491         ai = data;
492
493         return strdup(ai->name);
494 }
495
496 static Evas_Object *_album_content_get(void *data, Evas_Object *obj,
497                         const char *part)
498 {
499         Evas_Object *eo;
500         struct album_info *ai;
501         struct color_data bg;
502
503         if (!data)
504                 return NULL;
505
506         ai = data;
507
508         eo = NULL;
509         if (!strcmp(part, PART_ELM_SWALLOW_THUMBNAIL)) {
510                 eo = util_add_image(obj, ai->album_art);
511                 if (!eo) {
512                         _ERR("failed to create image object");
513                         return NULL;
514                 }
515         } else if (!strcmp(part, PART_ELM_SWALLOW_TEXTBG)) {
516                 eo = evas_object_rectangle_add(obj);
517                 if (!eo) {
518                         _ERR("failed to create rectangle object");
519                         return NULL;
520                 }
521
522                 app_contents_get_color(ai->name, NULL, &bg);
523                 evas_object_color_set(eo, bg.r, bg.g, bg.b, bg.a);
524         }
525
526         if (eo)
527                 evas_object_show(eo);
528
529         return eo;
530 }
531
532 static Elm_Gengrid_Item_Class *_get_grid_item_class(struct _view_info *vinfo)
533 {
534         Elm_Gengrid_Item_Class *ic;
535
536         ic = elm_gengrid_item_class_new();
537         if (!ic) {
538                 _ERR("failed to create gengrid item calss");
539                 return NULL;
540         }
541
542         ic->item_style = vinfo->grid_style;
543         ic->func.text_get = vinfo->get_grid_text;
544         ic->func.content_get = vinfo->get_grid_content;
545
546         return ic;
547 }
548
549 static app_media *_get_app_media(const char *id)
550 {
551         media_info_h media;
552         app_media *am;
553         int r;
554
555         r = media_content_connect();
556         if (r != MEDIA_CONTENT_ERROR_NONE) {
557                 _ERR("failed to connect to media content");
558                 return NULL;
559         }
560
561         r = media_info_get_media_from_db(id, &media);
562         if (r != MEDIA_CONTENT_ERROR_NONE) {
563                 _ERR("failed to get media handle");
564                 return NULL;
565         }
566
567         am = app_media_create(media);
568         if (!am) {
569                 _ERR("failed to create app media");
570                 return NULL;
571         }
572
573         media_content_disconnect();
574
575         return am;
576 }
577
578 static app_media *_get_play_item(struct _priv *priv, const char *id)
579 {
580         GList *rlist;
581         app_media *am;
582         struct recent_data *rdata;
583         int type;
584         int r;
585
586         if (id) {
587                 am = _get_app_media(id);
588                 return am;
589         }
590
591         type = view_info[priv->view_type].app_contents_type;
592
593         rlist = NULL;
594         am = NULL;
595         r = app_contents_get_recent_list(type, 1, &rlist);
596         if (r != APP_CONTENTS_ERROR_NONE) {
597                 _ERR("failed to get recent list");
598                 return NULL;
599         }
600
601         rdata = g_list_nth_data(rlist, 0);
602         if (!rdata || !rdata->id) {
603                 _ERR("failed to get recent item");
604                 app_contents_free_recent_list(rlist);
605                 return NULL;
606         }
607
608         am = _get_app_media(rdata->id);
609
610         app_contents_free_recent_list(rlist);
611
612         return am;
613 }
614
615 static void _get_place_title(const char *title, char *str, int size)
616 {
617         char buf[64], s[64];
618         char *city, *country, *tmp;
619
620         strcpy(buf, title);
621
622         city = strtok_r(buf, "/", &tmp);
623         country = strtok_r(tmp, "", &tmp);
624
625         snprintf(str, size, "%s", city);
626
627         if (country) {
628                 snprintf(s, sizeof(s), ", %s", country);
629                 strcat(str, s);
630         }
631 }
632
633 static void _get_movie_info(struct _priv *priv, const char *title)
634 {
635         char buf[64];
636
637         elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, title);
638
639         elm_object_signal_emit(priv->base,
640                                 SIG_HIDE_THUMBNAIL, SIG_SOURCE_SRC);
641
642         snprintf(buf, sizeof(buf), "%d movies",
643                                 eina_list_count(priv->media_list));
644
645         elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
646 }
647
648 static void _get_gallery_info(struct _priv *priv, const char *title)
649 {
650         Eina_List *l;
651         app_media *am;
652         app_media_info *mi;
653         int count[E_FILE_MAX] = {0};
654         char buf[64];
655
656         _get_place_title(title, buf, sizeof(buf));
657         elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, buf);
658
659         elm_object_signal_emit(priv->base,
660                                 SIG_HIDE_THUMBNAIL, SIG_SOURCE_SRC);
661
662         EINA_LIST_FOREACH(priv->media_list, l, am) {
663                 mi = app_media_get_info(am);
664                 if (!mi)
665                         continue;
666
667                 count[mi->media_type]++;
668         }
669
670         snprintf(buf, sizeof(buf), "%d contents | %d photos, %d videos",
671                                 eina_list_count(priv->media_list),
672                                 count[E_FILE_PHOTO], count[E_FILE_VIDEO]);
673
674         elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
675 }
676
677 static void _get_song_info(struct _priv *priv, const char *title)
678 {
679         app_media *am;
680         app_media_info *mi;
681         char buf[64];
682
683         elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, title);
684
685         if (priv->view_type == E_DETAIL_MUSIC_ALBUM) {
686                 am = eina_list_nth(priv->media_list, 0);
687                 mi = app_media_get_info(am);
688
689                 if (mi && mi->thumbnail_path) {
690                         elm_image_file_set(priv->thumbnail,
691                                                 mi->thumbnail_path, NULL);
692                         elm_image_aspect_fixed_set(priv->thumbnail, EINA_FALSE);
693
694                         elm_object_signal_emit(priv->base, SIG_SHOW_THUMBNAIL,
695                                                 SIG_SOURCE_SRC);
696                 }
697         } else {
698                 elm_object_signal_emit(priv->base, SIG_HIDE_THUMBNAIL,
699                                         SIG_SOURCE_SRC);
700         }
701
702         snprintf(buf, sizeof(buf), "%d songs",
703                                 eina_list_count(priv->media_list));
704
705         elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
706 }
707
708 static void _get_album_info(struct _priv *priv, const char *title)
709 {
710         char buf[64];
711
712         elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, title);
713
714         elm_object_signal_emit(priv->base,
715                                 SIG_HIDE_THUMBNAIL, SIG_SOURCE_SRC);
716
717         snprintf(buf, sizeof(buf), "%d albums",
718                                 eina_list_count(priv->media_list));
719
720         elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
721 }
722
723 static void _set_no_play_info(struct _priv *priv)
724 {
725         int type;
726         char buf[64] = {0};
727
728         type = priv->vinfo->app_contents_type;
729
730         if (type == CONTENTS_MOVIE)
731                 snprintf(buf, sizeof(buf), STR_NO_PLAY_MOVIE);
732         else if (type == CONTENTS_MUSIC)
733                 snprintf(buf, sizeof(buf), STR_NO_PLAY_MUSIC);
734
735         elm_object_text_set(priv->btn, buf);
736
737         elm_object_signal_emit(priv->btn, SIG_SET_STATUS_STOP, SIG_SOURCE_SRC);
738
739         elm_object_disabled_set(priv->btn, EINA_TRUE);
740 }
741
742 static void _set_movie_play_info(struct _priv *priv, app_media_info *mi)
743 {
744         struct tm tm;
745         char date[32], buf[256];
746
747         elm_object_signal_emit(priv->btn, SIG_SET_STATUS_STOP, SIG_SOURCE_SRC);
748
749         localtime_r(&mi->played_time, &tm);
750         strftime(date, sizeof(date), "%Y.%m.%d", &tm);
751
752         snprintf(buf, sizeof(buf), "%s - %s", mi->title, date);
753
754         elm_object_text_set(priv->btn, buf);
755         elm_object_disabled_set(priv->btn, EINA_FALSE);
756 }
757
758 static void _set_music_play_info(struct _priv *priv, app_media_info *mi)
759 {
760         char buf[256];
761
762         switch (priv->status) {
763         case E_PLAYER_PLAY:
764                 elm_object_signal_emit(priv->btn, SIG_SET_STATUS_PLAY,
765                                         SIG_SOURCE_SRC);
766                 break;
767         case E_PLAYER_PAUSE:
768                 elm_object_signal_emit(priv->btn, SIG_SET_STATUS_PAUSE,
769                                         SIG_SOURCE_SRC);
770                 break;
771         default:
772                 break;
773         }
774
775         snprintf(buf, sizeof(buf), "%s - %s", mi->title, mi->audio->artist);
776
777         elm_object_text_set(priv->btn, buf);
778         elm_object_disabled_set(priv->btn, EINA_FALSE);
779 }
780
781 static void _update_title_area(struct _priv *priv, const char *title)
782 {
783         view_info[priv->view_type].get_content_info(priv, title);
784 }
785
786 static bool _update_thumbnail_area(struct _priv *priv)
787 {
788         Eina_List *l;
789         Elm_Gengrid_Item_Class *ic;
790         Elm_Object_Item *it;
791         void *data;
792
793         elm_object_focus_set(priv->grid, EINA_FALSE);
794         elm_gengrid_clear(priv->grid);
795
796         elm_gengrid_item_size_set(priv->grid,
797                         elm_config_scale_get() * priv->vinfo->grid_item_x,
798                         elm_config_scale_get() * priv->vinfo->grid_item_y);
799
800         ic = _get_grid_item_class(priv->vinfo);
801         if (!ic) {
802                 _ERR("failed to get grid item class");
803                 return false;
804         }
805
806         EINA_LIST_FOREACH(priv->media_list, l, data) {
807                 it = elm_gengrid_item_append(priv->grid, ic, data, NULL, NULL);
808                 elm_object_item_data_set(it, data);
809         }
810
811         elm_gengrid_item_class_free(ic);
812
813         evas_object_show(priv->grid);
814
815         return true;
816 }
817
818 static bool _update_play_info(struct _priv *priv, const char *id)
819 {
820         app_media *am;
821         app_media_info *mi;
822         int type;
823
824         type = view_info[priv->view_type].app_contents_type;
825
826         if (type == CONTENTS_GALLERY ||
827                 (type == CONTENTS_MUSIC && priv->status == E_PLAYER_STOP)) {
828                 _set_no_play_info(priv);
829                 return true;
830         }
831
832         am = _get_play_item(priv, id);
833         if (!am) {
834                 _set_no_play_info(priv);
835                 return false;
836         }
837
838         mi = app_media_get_info(am);
839         if (!mi) {
840                 _ERR("failed to get app media info");
841                 _set_no_play_info(priv);
842                 return false;
843         }
844
845         if (type == CONTENTS_MOVIE)
846                 _set_movie_play_info(priv, mi);
847         else if (type == CONTENTS_MUSIC)
848                 _set_music_play_info(priv, mi);
849
850         priv->play_info = am;
851
852         return true;
853 }
854
855 static bool _draw_title_area(struct _priv *priv)
856 {
857         Evas_Object *img;
858
859         img = util_add_image(priv->base, NULL);
860         if (!img) {
861                 _ERR("failed to add image");
862                 return false;
863         }
864
865         elm_object_part_content_set(priv->base, PART_DETAIL_THUMBNAIL, img);
866
867         priv->thumbnail = img;
868
869         return true;
870 }
871
872 static bool _draw_thumbnail_area(struct _priv *priv)
873 {
874         Evas_Object *grid;
875
876         grid = util_add_gengrid(priv->base, 0, 0, EINA_TRUE);
877         if (!grid) {
878                 _ERR("failed to add gengrid");
879                 return false;
880         }
881
882         elm_object_part_content_set(priv->base,
883                                 PART_DETAIL_THUMBNAIL_AREA, grid);
884
885         inputmgr_add_callback(grid, DETAIL_GRID, &_handler, priv);
886
887         priv->grid = grid;
888
889         return true;
890 }
891
892 static bool _draw_play_info(struct _priv *priv)
893 {
894         Evas_Object *btn;
895
896         btn = util_add_button(priv->base, STYLE_BTN_PLAY_INFO, NULL);
897         if (!btn) {
898                 _ERR("failed to add button");
899                 return false;
900         }
901
902         elm_object_part_content_set(priv->base, PART_DETAIL_PLAY_INFO, btn);
903
904         inputmgr_add_callback(btn, DETAIL_PLAY_INFO, &_handler, priv);
905
906         priv->btn = btn;
907
908         return true;
909 }
910
911 static bool _draw_items(struct _priv *priv)
912 {
913         if (!_draw_title_area(priv)) {
914                 _ERR("failed to draw title area");
915                 return false;
916         }
917
918         if (!_draw_thumbnail_area(priv)) {
919                 _ERR("failed to draw thumbnail area");
920                 return false;
921         }
922
923         if (!_draw_play_info(priv)) {
924                 _ERR("failed to draw play info");
925                 return false;
926         }
927
928         return true;
929 }
930
931 static Evas_Object *_create(Evas_Object *win, void *data)
932 {
933         struct _priv *priv;
934         Evas_Object *base;
935         struct datamgr *dmgr;
936
937         if (!win) {
938                 _ERR("failed to get win object");
939                 return NULL;
940         }
941
942         priv = calloc(1, sizeof(*priv));
943         if (!priv) {
944                 _ERR("failed to allocate priv");
945                 return NULL;
946         }
947
948         base = elm_layout_add(win);
949         if (!base) {
950                 _ERR("failed to create base object");
951                 free(priv);
952                 return NULL;
953         }
954
955         elm_layout_file_set(base, EDJEFILE, GRP_DETAIL_VIEW);
956
957         evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND,
958                                 EVAS_HINT_EXPAND);
959         elm_win_resize_object_add(win, base);
960
961         dmgr = datamgr_create(E_DATA_ALBUM, MUSIC_MEDIA_COND, E_SOURCE_ALL);
962         if (!dmgr) {
963                 _ERR("failed to create datamgr");
964                 free(priv);
965                 return NULL;
966         }
967
968         priv->win = win;
969         priv->base = base;
970         priv->dmgr = dmgr;
971
972         if (!_draw_items(priv)) {
973                 _ERR("failed to draw items");
974                 datamgr_destroy(dmgr);
975                 free(priv);
976                 return NULL;
977         }
978
979         viewmgr_set_view_data(VIEW_DETAIL, priv);
980
981         return base;
982 }
983
984 static Eina_Bool _show_view(void *data)
985 {
986         struct _priv *priv;
987
988         if (!data)
989                 return ECORE_CALLBACK_CANCEL;
990
991         priv = data;
992
993         elm_object_signal_emit(priv->base, SIG_SHOW_VIEW, "");
994
995         return ECORE_CALLBACK_CANCEL;
996 }
997
998 static void _show(void *view_data)
999 {
1000         struct _priv *priv;
1001
1002         if (!view_data) {
1003                 _ERR("failed to get view data");
1004                 return;
1005         }
1006
1007         priv = view_data;
1008
1009         evas_object_show(priv->base);
1010
1011         elm_object_focus_set(priv->grid, EINA_TRUE);
1012
1013         ecore_timer_add(SHOW_VIEW_INTERVAL, _show_view, priv);
1014 }
1015
1016 static void _hide(void *view_data)
1017 {
1018         struct _priv *priv;
1019
1020         if (!view_data) {
1021                 _ERR("failed to get view data");
1022                 return;
1023         }
1024
1025         priv = view_data;
1026
1027         evas_object_hide(priv->base);
1028         elm_object_signal_emit(priv->base, SIG_HIDE_VIEW, "");
1029 }
1030
1031 static void _update(void *view_data, int update_type, void *data)
1032 {
1033         struct _priv *priv;
1034         struct view_update_data *vdata;
1035
1036         if (!view_data) {
1037                 _ERR("failed to get view data");
1038                 return;
1039         }
1040
1041         if (!data) {
1042                 _ERR("invalid argument");
1043                 return;
1044         }
1045
1046         priv = view_data;
1047         vdata = data;
1048
1049         switch (update_type) {
1050         case UPDATE_CONTENT:
1051                 priv->media_list = vdata->list;
1052                 priv->view_type = vdata->index;
1053
1054                 priv->vinfo = &view_info[priv->view_type];
1055
1056                 _update_title_area(priv, vdata->id);
1057                 _update_thumbnail_area(priv);
1058                 _update_play_info(priv, NULL);
1059
1060                 break;
1061         case UPDATE_PLAY_INFO:
1062                 _update_play_info(priv, vdata->id);
1063                 break;
1064         case UPDATE_PLAYER:
1065                 priv->status = vdata->status;
1066                 _update_play_info(priv, NULL);
1067                 break;
1068         default:
1069                 break;
1070         }
1071 }
1072
1073 static void _destroy(void *view_data)
1074 {
1075         struct _priv *priv;
1076
1077         if (!view_data) {
1078                 _ERR("failed to get view data");
1079                 return;
1080         }
1081
1082         priv = view_data;
1083
1084         _destroy_play_list(priv);
1085         app_media_destroy(priv->play_info);
1086
1087         datamgr_destroy(priv->dmgr);
1088
1089         evas_object_del(priv->base);
1090
1091         free(priv);
1092 }
1093
1094 static view_class _vclass = {
1095         .view_id = VIEW_DETAIL,
1096         .create = _create,
1097         .show = _show,
1098         .hide = _hide,
1099         .update = _update,
1100         .destroy = _destroy,
1101 };
1102
1103 view_class *view_detail_get_vclass(void)
1104 {
1105         return &_vclass;
1106 }