2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <Elementary.h>
18 #include <media_content.h>
19 #include <app_debug.h>
20 #include <app_contents.h>
21 #include <app_media.h>
27 #include "data/datamgr.h"
28 #include "grid/grid.h"
29 #include "util/util.h"
31 #define STR_NO_PLAY_MOVIE "No recently watched movie"
32 #define STR_NO_PLAY_MUSIC "No music in playlist"
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,
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,
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);
49 static void _album_selected(void *data);
62 const char *grid_style;
65 char *(*get_grid_text)(void *data, Evas_Object *obj, const char *part);
66 Evas_Object *(*get_grid_content)(void *data, Evas_Object *obj,
68 void (*get_content_info)(struct _priv *priv, const char *title);
70 void (*selected)(void *data);
73 int app_contents_type;
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,
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,
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,
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,
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,
135 Evas_Object *thumbnail;
137 Elm_Object_Item *focused_it;
139 Eina_List *media_list;
140 Eina_List *view_list;
141 Eina_List *play_list;
143 struct datamgr *dmgr;
145 app_media *play_info;
152 struct _view_info *vinfo;
155 static void _destroy_play_list(struct _priv *priv)
157 eina_list_free(priv->play_list);
158 priv->play_list = NULL;
161 static void _update_view(struct _priv *priv)
163 struct _list_info *linfo;
164 struct view_update_data vdata;
166 linfo = eina_list_data_get(priv->view_list);
167 priv->view_list = eina_list_remove(priv->view_list, linfo);
169 vdata.list = linfo->list;
170 vdata.index = E_DETAIL_MUSIC_ARTIST;
171 vdata.id = linfo->title;
173 viewmgr_update_view(VIEW_DETAIL, UPDATE_CONTENT, &vdata);
174 viewmgr_push_view(VIEW_DETAIL);
181 static void _pop_view(void)
183 viewmgr_update_view(VIEW_BASE, UPDATE_BACK, NULL);
187 static void _key_down_cb(int id, void *data, Evas *e, Evas_Object *obj,
188 Evas_Event_Key_Down *ev)
193 _ERR("invalid argument");
201 if (!strcmp(ev->keyname, KEY_BACK) ||
202 !strcmp(ev->keyname, KEY_ESC)) {
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);
221 static void _focused_cb(int id, void *data, Evas_Object *obj,
232 priv->focused_it = it;
235 static void _clicked_cb(int id, void *data, Evas_Object *obj)
237 struct view_update_data vdata;
242 _ERR("invalid argument");
248 type = priv->vinfo->app_contents_type;
252 _destroy_play_list(priv);
254 priv->play_list = eina_list_append(priv->play_list,
257 vdata.list = priv->play_list;
259 vdata.id = VIEW_DETAIL;
261 viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata);
262 viewmgr_push_view(VIEW_VIEWER);
266 viewmgr_push_view(VIEW_MPLAYER);
273 static void _media_selected(void *data)
276 struct view_update_data vdata;
280 _ERR("invalid argument");
286 am = elm_object_item_data_get(priv->focused_it);
288 _ERR("failed to get app media");
292 vdata.list = priv->media_list;
293 vdata.index = util_get_media_index(vdata.list, am);
294 vdata.id = VIEW_DETAIL;
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);
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);
312 static void _album_selected(void *data)
315 struct view_update_data vdata;
316 struct _list_info *linfo;
317 struct datamgr *dmgr;
318 struct album_info *ai;
321 _ERR("invalid argument");
329 ai = elm_object_item_data_get(priv->focused_it);
331 _ERR("failed to get album info");
335 linfo = calloc(1, sizeof(*linfo));
337 _ERR("failed to allocate list info");
341 linfo->list = priv->media_list;
342 linfo->title = ai->artist;
344 priv->view_list = eina_list_append(priv->view_list, linfo);
346 vdata.list = dmgr->ops->get_list(dmgr->handle,
347 E_LIST_ALBUM_MEDIA, &ai->id);
348 vdata.index = E_DETAIL_MUSIC_ALBUM;
351 viewmgr_update_view(VIEW_DETAIL, UPDATE_CONTENT, &vdata);
352 viewmgr_push_view(VIEW_DETAIL);
357 static void _selected_cb(int id, void *data, Evas_Object *obj,
361 void (*_selected)(void *data);
368 if (priv->vinfo->detail_update)
369 _selected = priv->vinfo->selected;
371 _selected = _media_selected;
373 ecore_job_add(_selected, priv);
376 static input_handler _handler = {
377 .key_down = _key_down_cb,
378 .focused = _focused_cb,
379 .clicked = _clicked_cb,
380 .selected = _selected_cb
383 static char *_grid_text_get(void *data, Evas_Object *obj, const char *part)
395 mi = app_media_get_info(am);
397 _ERR("failed to get media info");
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;
415 util_time_string(buf, sizeof(buf), duration, false);
423 static Evas_Object *_grid_content_get(void *data, Evas_Object *obj,
429 struct color_data bg;
436 mi = app_media_get_info(am);
438 _ERR("failed to get media info");
443 if (!strcmp(part, PART_ELM_SWALLOW_THUMBNAIL)) {
444 eo = util_add_image(obj, mi->thumbnail_path);
446 _ERR("failed to create image object");
449 } else if (!strcmp(part, PART_ELM_SWALLOW_FAVORITE)) {
453 eo = util_add_image(obj, IMAGE_THUMBNAIL_FAVORITE);
455 _ERR("failed to create image object");
458 } else if (!strcmp(part, PART_ELM_SWALLOW_TEXTBG)) {
459 eo = evas_object_rectangle_add(obj);
461 _ERR("failed to create rectangle object");
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)
471 eo = util_add_image(obj, IMAGE_THUMBNAIL_PLAY);
473 _ERR("failed to create image object");
479 evas_object_show(eo);
484 static char *_album_text_get(void *data, Evas_Object *obj, const char *part)
486 struct album_info *ai;
493 return strdup(ai->name);
496 static Evas_Object *_album_content_get(void *data, Evas_Object *obj,
500 struct album_info *ai;
501 struct color_data bg;
509 if (!strcmp(part, PART_ELM_SWALLOW_THUMBNAIL)) {
510 eo = util_add_image(obj, ai->album_art);
512 _ERR("failed to create image object");
515 } else if (!strcmp(part, PART_ELM_SWALLOW_TEXTBG)) {
516 eo = evas_object_rectangle_add(obj);
518 _ERR("failed to create rectangle object");
522 app_contents_get_color(ai->name, NULL, &bg);
523 evas_object_color_set(eo, bg.r, bg.g, bg.b, bg.a);
527 evas_object_show(eo);
532 static Elm_Gengrid_Item_Class *_get_grid_item_class(struct _view_info *vinfo)
534 Elm_Gengrid_Item_Class *ic;
536 ic = elm_gengrid_item_class_new();
538 _ERR("failed to create gengrid item calss");
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;
549 static app_media *_get_app_media(const char *id)
555 r = media_content_connect();
556 if (r != MEDIA_CONTENT_ERROR_NONE) {
557 _ERR("failed to connect to media content");
561 r = media_info_get_media_from_db(id, &media);
562 if (r != MEDIA_CONTENT_ERROR_NONE) {
563 _ERR("failed to get media handle");
567 am = app_media_create(media);
569 _ERR("failed to create app media");
573 media_content_disconnect();
578 static app_media *_get_play_item(struct _priv *priv, const char *id)
582 struct recent_data *rdata;
587 am = _get_app_media(id);
591 type = view_info[priv->view_type].app_contents_type;
595 r = app_contents_get_recent_list(type, 1, &rlist);
596 if (r != APP_CONTENTS_ERROR_NONE) {
597 _ERR("failed to get recent list");
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);
608 am = _get_app_media(rdata->id);
610 app_contents_free_recent_list(rlist);
615 static void _get_place_title(const char *title, char *str, int size)
618 char *city, *country, *tmp;
622 city = strtok_r(buf, "/", &tmp);
623 country = strtok_r(tmp, "", &tmp);
625 snprintf(str, size, "%s", city);
628 snprintf(s, sizeof(s), ", %s", country);
633 static void _get_movie_info(struct _priv *priv, const char *title)
637 elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, title);
639 elm_object_signal_emit(priv->base,
640 SIG_HIDE_THUMBNAIL, SIG_SOURCE_SRC);
642 snprintf(buf, sizeof(buf), "%d movies",
643 eina_list_count(priv->media_list));
645 elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
648 static void _get_gallery_info(struct _priv *priv, const char *title)
653 int count[E_FILE_MAX] = {0};
656 _get_place_title(title, buf, sizeof(buf));
657 elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, buf);
659 elm_object_signal_emit(priv->base,
660 SIG_HIDE_THUMBNAIL, SIG_SOURCE_SRC);
662 EINA_LIST_FOREACH(priv->media_list, l, am) {
663 mi = app_media_get_info(am);
667 count[mi->media_type]++;
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]);
674 elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
677 static void _get_song_info(struct _priv *priv, const char *title)
683 elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, title);
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);
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);
694 elm_object_signal_emit(priv->base, SIG_SHOW_THUMBNAIL,
698 elm_object_signal_emit(priv->base, SIG_HIDE_THUMBNAIL,
702 snprintf(buf, sizeof(buf), "%d songs",
703 eina_list_count(priv->media_list));
705 elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
708 static void _get_album_info(struct _priv *priv, const char *title)
712 elm_object_part_text_set(priv->base, PART_DETAIL_TITLE, title);
714 elm_object_signal_emit(priv->base,
715 SIG_HIDE_THUMBNAIL, SIG_SOURCE_SRC);
717 snprintf(buf, sizeof(buf), "%d albums",
718 eina_list_count(priv->media_list));
720 elm_object_part_text_set(priv->base, PART_DETAIL_CONTENT_INFO, buf);
723 static void _set_no_play_info(struct _priv *priv)
728 type = priv->vinfo->app_contents_type;
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);
735 elm_object_text_set(priv->btn, buf);
737 elm_object_signal_emit(priv->btn, SIG_SET_STATUS_STOP, SIG_SOURCE_SRC);
739 elm_object_disabled_set(priv->btn, EINA_TRUE);
742 static void _set_movie_play_info(struct _priv *priv, app_media_info *mi)
745 char date[32], buf[256];
747 elm_object_signal_emit(priv->btn, SIG_SET_STATUS_STOP, SIG_SOURCE_SRC);
749 localtime_r(&mi->played_time, &tm);
750 strftime(date, sizeof(date), "%Y.%m.%d", &tm);
752 snprintf(buf, sizeof(buf), "%s - %s", mi->title, date);
754 elm_object_text_set(priv->btn, buf);
755 elm_object_disabled_set(priv->btn, EINA_FALSE);
758 static void _set_music_play_info(struct _priv *priv, app_media_info *mi)
762 switch (priv->status) {
764 elm_object_signal_emit(priv->btn, SIG_SET_STATUS_PLAY,
768 elm_object_signal_emit(priv->btn, SIG_SET_STATUS_PAUSE,
775 snprintf(buf, sizeof(buf), "%s - %s", mi->title, mi->audio->artist);
777 elm_object_text_set(priv->btn, buf);
778 elm_object_disabled_set(priv->btn, EINA_FALSE);
781 static void _update_title_area(struct _priv *priv, const char *title)
783 view_info[priv->view_type].get_content_info(priv, title);
786 static bool _update_thumbnail_area(struct _priv *priv)
789 Elm_Gengrid_Item_Class *ic;
793 elm_object_focus_set(priv->grid, EINA_FALSE);
794 elm_gengrid_clear(priv->grid);
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);
800 ic = _get_grid_item_class(priv->vinfo);
802 _ERR("failed to get grid item class");
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);
811 elm_gengrid_item_class_free(ic);
813 evas_object_show(priv->grid);
818 static bool _update_play_info(struct _priv *priv, const char *id)
824 type = view_info[priv->view_type].app_contents_type;
826 if (type == CONTENTS_GALLERY ||
827 (type == CONTENTS_MUSIC && priv->status == E_PLAYER_STOP)) {
828 _set_no_play_info(priv);
832 am = _get_play_item(priv, id);
834 _set_no_play_info(priv);
838 mi = app_media_get_info(am);
840 _ERR("failed to get app media info");
841 _set_no_play_info(priv);
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);
850 priv->play_info = am;
855 static bool _draw_title_area(struct _priv *priv)
859 img = util_add_image(priv->base, NULL);
861 _ERR("failed to add image");
865 elm_object_part_content_set(priv->base, PART_DETAIL_THUMBNAIL, img);
867 priv->thumbnail = img;
872 static bool _draw_thumbnail_area(struct _priv *priv)
876 grid = util_add_gengrid(priv->base, 0, 0, EINA_TRUE);
878 _ERR("failed to add gengrid");
882 elm_object_part_content_set(priv->base,
883 PART_DETAIL_THUMBNAIL_AREA, grid);
885 inputmgr_add_callback(grid, DETAIL_GRID, &_handler, priv);
892 static bool _draw_play_info(struct _priv *priv)
896 btn = util_add_button(priv->base, STYLE_BTN_PLAY_INFO, NULL);
898 _ERR("failed to add button");
902 elm_object_part_content_set(priv->base, PART_DETAIL_PLAY_INFO, btn);
904 inputmgr_add_callback(btn, DETAIL_PLAY_INFO, &_handler, priv);
911 static bool _draw_items(struct _priv *priv)
913 if (!_draw_title_area(priv)) {
914 _ERR("failed to draw title area");
918 if (!_draw_thumbnail_area(priv)) {
919 _ERR("failed to draw thumbnail area");
923 if (!_draw_play_info(priv)) {
924 _ERR("failed to draw play info");
931 static Evas_Object *_create(Evas_Object *win, void *data)
935 struct datamgr *dmgr;
938 _ERR("failed to get win object");
942 priv = calloc(1, sizeof(*priv));
944 _ERR("failed to allocate priv");
948 base = elm_layout_add(win);
950 _ERR("failed to create base object");
955 elm_layout_file_set(base, EDJEFILE, GRP_DETAIL_VIEW);
957 evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND,
959 elm_win_resize_object_add(win, base);
961 dmgr = datamgr_create(E_DATA_ALBUM, MUSIC_MEDIA_COND, E_SOURCE_ALL);
963 _ERR("failed to create datamgr");
972 if (!_draw_items(priv)) {
973 _ERR("failed to draw items");
974 datamgr_destroy(dmgr);
979 viewmgr_set_view_data(VIEW_DETAIL, priv);
984 static Eina_Bool _show_view(void *data)
989 return ECORE_CALLBACK_CANCEL;
993 elm_object_signal_emit(priv->base, SIG_SHOW_VIEW, "");
995 return ECORE_CALLBACK_CANCEL;
998 static void _show(void *view_data)
1003 _ERR("failed to get view data");
1009 evas_object_show(priv->base);
1011 elm_object_focus_set(priv->grid, EINA_TRUE);
1013 ecore_timer_add(SHOW_VIEW_INTERVAL, _show_view, priv);
1016 static void _hide(void *view_data)
1021 _ERR("failed to get view data");
1027 evas_object_hide(priv->base);
1028 elm_object_signal_emit(priv->base, SIG_HIDE_VIEW, "");
1031 static void _update(void *view_data, int update_type, void *data)
1034 struct view_update_data *vdata;
1037 _ERR("failed to get view data");
1042 _ERR("invalid argument");
1049 switch (update_type) {
1050 case UPDATE_CONTENT:
1051 priv->media_list = vdata->list;
1052 priv->view_type = vdata->index;
1054 priv->vinfo = &view_info[priv->view_type];
1056 _update_title_area(priv, vdata->id);
1057 _update_thumbnail_area(priv);
1058 _update_play_info(priv, NULL);
1061 case UPDATE_PLAY_INFO:
1062 _update_play_info(priv, vdata->id);
1065 priv->status = vdata->status;
1066 _update_play_info(priv, NULL);
1073 static void _destroy(void *view_data)
1078 _ERR("failed to get view data");
1084 _destroy_play_list(priv);
1085 app_media_destroy(priv->play_info);
1087 datamgr_destroy(priv->dmgr);
1089 evas_object_del(priv->base);
1094 static view_class _vclass = {
1095 .view_id = VIEW_DETAIL,
1100 .destroy = _destroy,
1103 view_class *view_detail_get_vclass(void)