/* * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include "define.h" #include "layout.h" #include "view.h" #include "data/datamgr.h" #include "grid/grid.h" #include "util/listmgr.h" #include "util/progressbar.h" #include "util/util.h" #define TEXT_NOCONTENT "No Movies" #define TEXT_RECENTLY_WATCHED "Recently watched" #define GRID_PADDING 26 #define GRID_ITEM_X (378 + GRID_PADDING) #define GRID_ITEM_Y (294 + GRID_PADDING) #define GRID_NUM_ITEM 2 #define BOX_PADDING (62 - GRID_PADDING) struct _priv { Evas_Object *base; Evas_Object *layout; Evas_Object *box; Evas_Object *menu_btn; Evas_Object *view_btn; layoutmgr *lmgr; struct listmgr *listmgr; struct listmgr_data *ldata; struct datamgr *dmgr[E_DATA_MAX]; struct progressbar *prog; Eina_List *media_list; app_media *recent_info; int view_mode; int source_type; struct grid_data *gdata; }; static bool _update_recent_info(Evas_Object *base, app_media_info *info) { Evas_Object *img, *img_bg, *text_bg; struct color_data bg; struct tm tm; char buf[32]; img = elm_object_part_content_get(base, PART_RECENT_CONTENT_THUMBNAIL); img_bg = elm_object_part_content_get(base, PART_RECENT_CONTENT_IMGBG); if (!img || !img_bg) { _ERR("failed to get object"); return false; } if (info->thumbnail_path) { elm_image_file_set(img, info->thumbnail_path, NULL); elm_image_aspect_fixed_set(img, EINA_FALSE); evas_object_color_set(img_bg, 0, 0, 0, 0); } else evas_object_color_set(img_bg, 0, 0, 0, 255); text_bg = elm_object_part_content_get(base, PART_RECENT_CONTENT_TEXTBG); if (!text_bg) { _ERR("failed to get textbg part"); return false; } app_contents_get_color(info->title, NULL, &bg); evas_object_color_set(text_bg, bg.r, bg.g, bg.b, bg.a); elm_object_part_text_set(base, PART_RECENT_CONTENT_TITLE, info->title); localtime_r(&info->played_time, &tm); strftime(buf, sizeof(buf), "%Y.%m.%d", &tm); elm_object_part_text_set(base, PART_RECENT_CONTENT_DATE, buf); if (info->favorite) elm_object_signal_emit(base, SIG_RECENT_SHOW_FAV, SIG_SOURCE_SRC); else elm_object_signal_emit(base, SIG_RECENT_HIDE_FAV, SIG_SOURCE_SRC); return true; } static bool _update_recent(void *data, Evas_Object *base) { Evas_Object *recent; app_media_info *info; struct _priv *priv; if (!data || !base) { _ERR("invalid argument"); return false; } priv = data; recent = elm_object_part_content_get(base, PART_ITEM_CONTENT); if (!recent) { _ERR("failed to get recent content part"); return false; } info = app_media_get_info(priv->recent_info); if (!info) { _ERR("failed to get app media info"); return false; } if (!_update_recent_info(recent, info)) { _ERR("failed to update recent info"); return false; } progressbar_reset(priv->prog, info->video->position, info->video->duration); progressbar_show(priv->prog); return true; } static bool _draw_recent_title(Evas_Object *base) { Evas_Object *btn; btn = elm_button_add(base); if (!btn) { _ERR("failed to create button object"); return false; } elm_object_style_set(btn, STYLE_BTN_INDEX); elm_object_text_set(btn, TEXT_RECENTLY_WATCHED); elm_object_part_content_set(base, PART_ITEM_TITLE, btn); return true; } static bool _draw_recent_content(struct _priv *priv, Evas_Object *base) { Evas_Object *btn, *image, *img_bg, *text_bg; struct progressbar *prog; btn = elm_button_add(base); if (!btn) { _ERR("failed to create button object"); return false; } elm_object_style_set(btn, STYLE_BTN_RECENT_CONTENT); image = elm_image_add(btn); if (!image) { _ERR("failed to create image object"); return false; } img_bg = evas_object_rectangle_add(btn); if (!img_bg) { _ERR("failed to create rectangle object"); return false; } text_bg = evas_object_rectangle_add(btn); if (!text_bg) { _ERR("failed to create rectangle object"); return false; } elm_object_part_content_set(btn, PART_RECENT_CONTENT_THUMBNAIL, image); elm_object_part_content_set(btn, PART_RECENT_CONTENT_IMGBG, img_bg); elm_object_part_content_set(btn, PART_RECENT_CONTENT_TEXTBG, text_bg); elm_object_part_content_set(base, PART_ITEM_CONTENT, btn); prog = progressbar_create(btn, STYLE_BASE_PROGRESS); if (!prog) { _ERR("failed to create progressbar"); return false; } progressbar_set_parts(prog, PART_RECENT_CONTENT_SLIDER, PART_RECENT_CONTENT_TOTAL, PART_RECENT_CONTENT_PROGRESS, ""); priv->prog = prog; return true; } static bool _draw_recent(void *data, Evas_Object *base) { struct _priv *priv; if (!data || !base) { _ERR("invalid argument"); return false; } priv = data; if (!_draw_recent_title(base)) { _ERR("failed to draw recent title"); return false; } if (!_draw_recent_content(priv, base)) { _ERR("failed to draw recent content"); return false; } return true; } static void _recent_item_selected(struct _priv *priv, app_media *am) { app_media_info *info; struct view_update_data vdata; struct datamgr *dmgr; info = app_media_get_info(am); if (!info) { _ERR("failed to get app media info"); return; } dmgr = priv->dmgr[E_DATA_MEDIA]; if (!dmgr) return; vdata.list = dmgr->ops->get_list(dmgr->handle, E_LIST_MEDIA, NULL); vdata.index = util_get_media_index_from_id(vdata.list, info->media_id); vdata.id = VIEW_BASE; viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata); viewmgr_push_view(VIEW_VIEWER); } static void _recent_key_down_cb(void *data, Evas_Object *obj, Evas_Event_Key_Down *ev) { struct view_update_data vdata; struct datamgr *dmgr; struct _priv *priv; if (!data || !ev) return; priv = data; dmgr = priv->dmgr[E_DATA_MEDIA]; if (!dmgr) return; if (!strcmp(ev->keyname, KEY_MENU) || !strcmp(ev->keyname, KEY_CONTEXT_MENU)) { vdata.list = dmgr->ops->get_list(dmgr->handle, E_LIST_MEDIA, NULL); vdata.index = util_get_media_index(vdata.list, priv->recent_info); vdata.id = VIEW_BASE; viewmgr_update_view(VIEW_ACTION_MENU, UPDATE_CONTENT, &vdata); viewmgr_show_view(VIEW_ACTION_MENU); } } static void _recent_selected_cb(void *data, Evas_Object *obj) { struct _priv *priv; struct view_update_data vdata; struct datamgr *dmgr; if (!data || !obj) return; priv = data; dmgr = priv->dmgr[E_DATA_MEDIA]; if (!dmgr) return; vdata.list = dmgr->ops->get_list(dmgr->handle, E_LIST_MEDIA, NULL); vdata.index = util_get_media_index(vdata.list, priv->recent_info); vdata.id = VIEW_BASE; viewmgr_update_view(VIEW_VIEWER, UPDATE_CONTENT, &vdata); viewmgr_push_view(VIEW_VIEWER); } static struct listmgr_data *_create_listmgr_data(struct _priv *priv) { struct listmgr_data *data; struct play_info_data *pdata; data = calloc(1, sizeof(*data)); if (!data) goto err; data->menu_btn = priv->menu_btn; data->view_btn = priv->view_btn; pdata = calloc(1, sizeof(*pdata)); if (!pdata) goto err2; pdata->draw = _draw_recent; pdata->update = _update_recent; pdata->key_down_cb = _recent_key_down_cb; pdata->selected_cb = _recent_selected_cb; pdata->cb_data = priv; data->pdata = pdata; return data; err2: free(data); err: _ERR("failed to allocate memory"); return NULL; } static void _update_bottom_area(struct _priv *priv) { struct datamgr *dmgr; char buf[128]; /* update view mode button state */ if (priv->media_list) elm_object_disabled_set(priv->view_btn, EINA_FALSE); else elm_object_disabled_set(priv->view_btn, EINA_TRUE); /* update content info */ dmgr = priv->dmgr[E_DATA_MEDIA]; if (!dmgr) return; priv->gdata->get_item_info(dmgr, priv->media_list, buf, sizeof(buf)); elm_object_part_text_set(priv->base, PART_BASE_CONTENT_INFO, buf); } static void _clear_content_list(struct _priv *priv) { if (priv->media_list) { priv->gdata->free_item_list(priv->dmgr[E_DATA_MEDIA], priv->media_list); priv->media_list = NULL; } elm_object_part_text_set(priv->layout, PART_NOCONTENT, ""); listmgr_clear_content_list(priv->listmgr); } static void _update_content_list(struct _priv *priv) { if (priv->media_list) return; priv->gdata = get_movie_grid_data(priv->view_mode); if (!priv->gdata) { elm_object_part_text_set(priv->layout, PART_NOCONTENT, TEXT_NOCONTENT); return; } priv->media_list = priv->gdata->get_item_list(priv->dmgr[E_DATA_MEDIA]); if (!priv->media_list) elm_object_part_text_set(priv->layout, PART_NOCONTENT, TEXT_NOCONTENT); priv->gdata->data = priv->dmgr[E_DATA_MEDIA]; if (!listmgr_update_content_list(priv->listmgr, priv->media_list, priv->gdata)) { _ERR("failed to update list area"); return; } } static app_media *_get_recent_item(Eina_List *list) { GList *rlist; app_media *am; struct recent_data *rdata; int r; rlist = NULL; am = NULL; r = app_contents_get_recent_list(CONTENTS_MOVIE, 1, &rlist); if (r != APP_CONTENTS_ERROR_NONE) { _ERR("failed to get movie recent list"); return NULL; } rdata = g_list_nth_data(rlist, 0); if (rdata && rdata->id) am = util_find_media_info(list, rdata->id); app_contents_free_recent_list(rlist); return am; } static void _update_recent_item(struct _priv *priv, const char *id) { Eina_List *list; app_media *am; app_media_info *info; struct datamgr *dmgr; dmgr = priv->dmgr[E_DATA_MEDIA]; if (!dmgr) return; info = NULL; list = dmgr->ops->get_list(dmgr->handle, E_LIST_MEDIA, NULL); if (id) am = util_find_media_info(list, id); else am = _get_recent_item(list); if (am) { info = app_media_get_info(am); if (!info) _ERR("failed to get app media info"); } priv->recent_info = am; if (!listmgr_update_play_info(priv->listmgr, info)) _ERR("failed to update recently watched item"); } static void _destroy_datamgr(struct _priv *priv) { int i; for (i = 0; i < E_DATA_MAX; i++) datamgr_destroy(priv->dmgr[i]); } static void _destroy_utils(struct _priv *priv) { _destroy_datamgr(priv); listmgr_destroy(priv->listmgr); free(priv->ldata->pdata); free(priv->ldata); } static bool _create_utils(struct _priv *priv) { struct listmgr *listmgr; struct listmgr_data *ldata; struct datamgr *dmgr; int i; for (i = 0; i < E_DATA_MAX; i++) { dmgr = datamgr_create(i, MOVIE_MEDIA_COND, E_SOURCE_ALL); if (!dmgr) { _ERR("failed to create datamgr"); _destroy_datamgr(priv); return false; } priv->dmgr[i] = dmgr; } ldata = _create_listmgr_data(priv); if (!ldata) { _ERR("failed to create listmgr data"); _destroy_datamgr(priv); return false; } listmgr = listmgr_create(priv->layout, (void *)ldata); if (!listmgr) { _ERR("failed to create listmgr"); _destroy_datamgr(priv); free(ldata); return false; } priv->ldata = ldata; priv->listmgr = listmgr; return true; } static bool _create(layoutmgr *lmgr, void *data) { struct layout_data *ld; struct _priv *priv; Evas_Object *base, *layout; if (!lmgr) { _ERR("failed to get layoutmgr"); return false; } if (!data) { _ERR("invalid argument"); return false; } ld = data; priv = calloc(1, sizeof(*priv)); if (!priv) { _ERR("failed to allocate priv"); return false; } base = layoutmgr_get_base(lmgr); if (!base) { _ERR("failed to get base object"); goto err; } layout = elm_layout_add(base); if (!layout) { _ERR("failed to create layout"); goto err; } if (!elm_layout_file_set(layout, EDJEFILE, GRP_MOVIE_LAYOUT)) { _ERR("failed to set layout file"); goto err2; } priv->base = base; priv->layout = layout; priv->menu_btn = ld->top; priv->view_btn = ld->bottom; priv->lmgr = lmgr; priv->gdata = get_movie_grid_data(E_MOVIE_NAME); if (!_create_utils(priv)) { _ERR("failed to create utils"); goto err2; } layoutmgr_set_layout_data(lmgr, LAYOUT_MOVIE, priv); if (!listmgr_draw_list_area(priv->listmgr)) { _ERR("failed to draw list area"); goto err3; } return true; err3: _destroy_utils(priv); err2: evas_object_del(layout); err: free(priv); return false; } static void _destroy(void *layout_data) { struct _priv *priv; if (!layout_data) { _ERR("failed to get layout data"); return; } priv = layout_data; progressbar_destroy(priv->prog); priv->gdata->free_item_list(priv->dmgr[E_DATA_MEDIA], priv->media_list); _destroy_utils(priv); evas_object_del(priv->layout); free(priv); } static void _show(void *layout_data) { struct _priv *priv; if (!layout_data) { _ERR("failed to layout data"); return; } priv = layout_data; evas_object_show(priv->layout); elm_object_part_content_set(priv->base, PART_BASE_THUMBNAIL_AREA, priv->layout); } static void _hide(void *layout_data) { struct _priv *priv; if (!layout_data) { _ERR("failed to get layout data"); return; } priv = layout_data; evas_object_hide(priv->layout); elm_object_part_content_unset(priv->base, PART_BASE_THUMBNAIL_AREA); } static void _update(void *layout_data, int update_type, void *data) { struct view_update_data *vdata; struct _priv *priv; struct datamgr *dmgr; int mode; if (!layout_data) { _ERR("failed to get layout data"); return; } priv = layout_data; switch (update_type) { case UPDATE_CONTENT: _update_content_list(priv); _update_bottom_area(priv); _update_recent_item(priv, NULL); break; case UPDATE_CONTENT_ITEM: listmgr_update_content_item(priv->listmgr); _update_recent_item(priv, NULL); break; case UPDATE_FOCUS: if (!data) { _ERR("invalid argument"); return; } vdata = data; _update_recent_item(priv, vdata->id); listmgr_focus_play_info(priv->listmgr); break; case UPDATE_BACK: listmgr_focus_content_list(priv->listmgr, NULL); break; case UPDATE_RECENT: if (!data) { _ERR("invalid argument"); return; } _update_content_list(priv); _update_bottom_area(priv); _recent_item_selected(priv, data); break; case UPDATE_FOCUS_STATE: listmgr_set_focus_state(priv->listmgr, EINA_FALSE); break; case UPDATE_VIEW_MODE: if (!data) { _ERR("invalid argument"); return; } vdata = data; mode = vdata->index; /* Folder view mode will be implemented later */ if (mode == E_MOVIE_FOLDER) return; if (mode == priv->view_mode) return; _clear_content_list(priv); priv->view_mode = mode; _update_content_list(priv); _update_bottom_area(priv); break; case UPDATE_SOURCE_TYPE: if (!data) { _ERR("invalid argument"); return; } vdata = data; mode = vdata->index; if (mode == priv->source_type) return; priv->source_type = mode; dmgr = priv->dmgr[E_DATA_MEDIA]; dmgr->ops->set_source(dmgr->handle, mode); _clear_content_list(priv); _update_content_list(priv); _update_bottom_area(priv); break; case UPDATE_SOURCE_CONTENT: if (!data) { _ERR("invalid argument"); return; } vdata = data; _clear_content_list(priv); _update_content_list(priv); if (vdata->index == E_LAYOUT_MOVIE) { _update_bottom_area(priv); _update_recent_item(priv, NULL); listmgr_focus_menu_btn(priv->listmgr); } break; default: break; } } static layout_class _lclass = { .layout_id = LAYOUT_MOVIE, .create = _create, .show = _show, .hide = _hide, .destroy = _destroy, .update = _update, }; layout_class *layout_movie_get_lclass(void) { return &_lclass; }