/* * 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 #include #include "define.h" #include "view.h" #include "util/controller.h" #include "util/timeout_handler.h" #include "util/playermgr.h" #include "util/progressbar.h" #include "util/util.h" #define STYLE_VIEWER_BTN "viewer_btn" #define PART_VIEWER_BTN "control_btn" #define POSITION_MARGIN 500 #define VIEWER_TIMEOUT 5.0 #define VIEWER_SEPARATOR "/ " #define SLIDE_SHOW_INTERVAL 3.0 #define ERROR_MESSAGE "Something went wrong." #define BTN_LOC_NONE -1 #define BTN_LOC_PREV 0 #define BTN_LOC_REW 1 #define BTN_LOC_PLAY 2 #define BTN_LOC_FF 3 #define BTN_LOC_NEXT 4 #define BTN_LOC_ROTATE 5 #define BTN_LOC_ZOOM 5 /*#define BTN_LOC_ZOOM 6*/ #define BTN_LOC_SLIDE 8 enum { WIND_NONE, WIND_FF, WIND_REW, }; enum { VIEWER_MOVIE, VIEWER_PHOTO, VIEWER_VIDEO, VIEWER_MAX }; struct _viewer { struct controller *ctl[VIEWER_MAX]; int cur; int foc; }; struct _playlist { Eina_List *list; int cur; }; struct _slideshow { Ecore_Timer *timer; bool enable; }; struct _priv { Evas_Object *win; Evas_Object *base; Evas_Object *photo; Evas_Object *photo_pre; struct _viewer viewer; struct _playlist playlist; struct timeout_handler *timeout; struct playermgr *player; struct progressbar *progress; struct _slideshow slideshow; bool bar_show; const char *prev_view; }; struct _btn_info { const char *name; int loc; }; static struct _btn_info btn_movie[] = { { .name = SRC_BTN_PREV, .loc = BTN_LOC_PREV, }, { .name = SRC_BTN_REW, .loc = BTN_LOC_REW, }, { .name = SRC_BTN_PLAY, .loc = BTN_LOC_PLAY, }, { .name = SRC_BTN_FF, .loc = BTN_LOC_FF, }, { .name = SRC_BTN_NEXT, .loc = BTN_LOC_NEXT, }, }; static struct _btn_info btn_photo[] = { { .name = SRC_BTN_GALLERY_PREV, .loc = BTN_LOC_PREV, }, { .name = SRC_BTN_GALLERY_NEXT, .loc = BTN_LOC_NEXT, }, /* { .name = SRC_BTN_ROTATE, .loc = BTN_LOC_ROTATE, }, */ { .name = SRC_BTN_ZOOM, .loc = BTN_LOC_ZOOM, }, { .name = SRC_BTN_SLIDE, .loc = BTN_LOC_SLIDE, }, }; static struct _btn_info btn_video[] = { { .name = SRC_BTN_GALLERY_PREV, .loc = BTN_LOC_PREV, }, { .name = SRC_BTN_REW, .loc = BTN_LOC_REW, }, { .name = SRC_BTN_PLAY, .loc = BTN_LOC_PLAY, }, { .name = SRC_BTN_GALLERY_NEXT, .loc = BTN_LOC_NEXT, }, { .name = SRC_BTN_FF, .loc = BTN_LOC_FF, }, { .name = SRC_BTN_SLIDE, .loc = BTN_LOC_SLIDE, }, }; struct _viewer_info { struct _btn_info *btns; int btn_count; int focus_loc; void (*callback)(void *, const char *); }; static void _player_play(struct _priv *priv); static void _player_stop(struct _priv *priv); static void _player_pause(struct _priv *priv); static void _callback_movie(void *data, const char *ev); static void _callback_photo(void *data, const char *ev); static void _callback_video(void *data, const char *ev); static void _slideshow_set(struct _priv *priv); static void _slideshow_enable(struct _priv *priv); static void _slideshow_disable(struct _priv *priv); static struct _viewer_info viewer_info[] = { { .btns = btn_movie, .btn_count = 5, .focus_loc = BTN_LOC_PLAY, .callback = _callback_movie, }, { .btns = btn_photo, .btn_count = 4, .focus_loc = BTN_LOC_NEXT, .callback = _callback_photo, }, { .btns = btn_video, .btn_count = 6, .focus_loc = BTN_LOC_NEXT, .callback = _callback_video, }, }; static void _set_bg_color(struct _priv *priv, int r, int g, int b, int a) { Evas_Object *bg; bg = evas_object_rectangle_add(evas_object_evas_get(priv->base)); if (!bg) { _ERR("failed to add rect"); return; } evas_object_color_set(bg, r, g, b, a); elm_object_part_content_set(priv->base, PART_VIEWER_BG, bg); } static void _image_unload(struct _priv *priv) { if (priv->photo_pre) { evas_object_del(priv->photo_pre); priv->photo_pre = NULL; } if (priv->photo) { evas_object_del(priv->photo); priv->photo = NULL; } _set_bg_color(priv, 0, 0, 0, 0); elm_object_part_content_unset(priv->base, PART_VIEWER_CONTENT); } static void _image_loaded(void *data, Evas_Object *obj, void *ev) { struct _priv *priv; if (!data || !obj) return; priv = data; if (priv->photo != priv->photo_pre) { if (priv->photo) evas_object_del(priv->photo); priv->photo = obj; } elm_object_part_content_set(priv->base, PART_VIEWER_CONTENT, obj); } static void _image_loaded_detail(void *data, Evas_Object *obj, void *ev) { struct _priv *priv; if (!data) return; priv = data; priv->photo_pre = NULL; util_add_to_recent(priv->playlist.list, priv->playlist.cur); } static void _draw_contents(struct _priv *priv, int id, app_media_info *mi) { Evas_Object *obj; if (id == VIEWER_MOVIE) { _image_unload(priv); _player_play(priv); return; } else if (id == VIEWER_VIDEO) { _image_unload(priv); _player_play(priv); if (!priv->slideshow.enable) _player_pause(priv); return; } else if (id == VIEWER_PHOTO) { if (priv->slideshow.enable) _slideshow_set(priv); } if (!mi->file_path) return; if (priv->photo_pre) { obj = priv->photo_pre; } else { obj = elm_photocam_add(priv->base); if (!obj) { _ERR("failed to adding photocam"); return; } evas_object_smart_callback_add(obj, "loaded", _image_loaded, priv); evas_object_smart_callback_add(obj, "loaded,detail", _image_loaded_detail, priv); elm_object_focus_allow_set(obj, EINA_FALSE); elm_scroller_policy_set(obj, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); /* * set this photocam object to photo_pre (preloaded photo) * On "loaded" callback, photo_pre object will pass to photo * On "loaded,detail" callback photo_pre object will set to NULL */ priv->photo_pre = obj; } _set_bg_color(priv, 0, 0, 0, 255); elm_photocam_file_set(obj, mi->file_path); elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT); elm_photocam_image_orient_set(obj, util_get_orient(mi->image->orientation)); } static void _draw_title_bar(struct _priv *priv, int id, app_media_info *mi) { char buf[32] = {0,}; char day[32] = {0,}; char date[32] = {0,}; if (id == VIEWER_MOVIE) { elm_object_part_text_set(priv->base, PART_VIEWER_TITLE, mi->title); elm_object_part_text_set(priv->base, PART_VIEWER_DATE, ""); elm_object_part_text_set(priv->base, PART_VIEWER_PAGE, ""); } else { strftime(date, sizeof(date), "%d %b, %Y", mi->content_time); strftime(day, sizeof(day), "%a", mi->content_time); util_up_string(day); snprintf(buf, sizeof(buf), "%s, %s", day, date); elm_object_part_text_set(priv->base, PART_VIEWER_DATE, buf); snprintf(buf, sizeof(buf), "%d / %d", priv->playlist.cur + 1, eina_list_count(priv->playlist.list)); elm_object_part_text_set(priv->base, PART_VIEWER_PAGE, buf); elm_object_part_text_set(priv->base, PART_VIEWER_TITLE, ""); } } static void _draw_progressbar(struct _priv *priv, int id, app_media_info *mi) { if (id == VIEWER_PHOTO) { elm_object_part_text_set(priv->base, PART_VIEWER_PROGRESS, ""); elm_object_part_text_set(priv->base, PART_VIEWER_TOTAL, ""); progressbar_hide(priv->progress); return; } progressbar_reset(priv->progress, mi->video->position, mi->video->duration); progressbar_show(priv->progress); } static void _draw_favorite_icon(struct _priv *priv, int id, app_media_info *mi) { if (mi->favorite) elm_object_signal_emit(priv->base, SIG_VIEWER_SHOW_FAV, ""); else elm_object_signal_emit(priv->base, SIG_VIEWER_HIDE_FAV, ""); } static void _draw_wind(struct _priv *priv, int speed) { char buf[32] = {0,}; if (speed) { snprintf(buf, sizeof(buf), "x%d", speed); elm_object_part_text_set(priv->base, PART_VIEWER_WIND, buf); } else { elm_object_part_text_set(priv->base, PART_VIEWER_WIND, ""); } } static app_media_info *_get_current_media_info(struct _priv *priv) { app_media *am; app_media_info *mi; am = eina_list_nth(priv->playlist.list, priv->playlist.cur); if (!am) { _ERR("failed to get app_media"); return NULL; } mi = app_media_get_info(am); if (!mi) { _ERR("failed to getting media info"); return NULL; } return mi; } static const char *_get_current_media_id(struct _priv *priv) { app_media_info *mi; mi = _get_current_media_info(priv); if (!mi) return NULL; return mi->media_id; } static void _set_played_position(struct _priv *priv) { video_meta_h video; app_media *am; int position; int duration; int r; if (priv->viewer.cur != VIEWER_MOVIE) return; position = playermgr_get_position(priv->player); duration = playermgr_get_duration(priv->player); if (position > duration - POSITION_MARGIN) position = 0; am = eina_list_nth(priv->playlist.list, priv->playlist.cur); if (!am) { _ERR("failed to get app_media"); return; } video = app_media_get_video_handle(am); if (!video) { _ERR("failed to getting video handle"); return; } r = video_meta_set_played_position(video, position); if (r != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to set played position"); return; } r = video_meta_update_to_db(video); if (r != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to update db"); return; } app_media_update(am); } static void _set_image_orientation(struct _priv *priv) { app_media *am; app_media_info *mi; image_meta_h image; media_content_orientation_e orient; int r; if (priv->viewer.cur != VIEWER_PHOTO) return; am = eina_list_nth(priv->playlist.list, priv->playlist.cur); if (!am) { _ERR("failed to get app_media"); return; } mi = _get_current_media_info(priv); if (!mi) { _ERR("failed to getting media info"); return; } image = app_media_get_image_handle(am); if (!image) { _ERR("failed to getting image handle"); return; } switch (mi->image->orientation) { case MEDIA_CONTENT_ORIENTATION_NORMAL: orient = MEDIA_CONTENT_ORIENTATION_ROT_270; break; case MEDIA_CONTENT_ORIENTATION_ROT_90: orient = MEDIA_CONTENT_ORIENTATION_NORMAL; break; case MEDIA_CONTENT_ORIENTATION_ROT_180: orient = MEDIA_CONTENT_ORIENTATION_ROT_90; break; case MEDIA_CONTENT_ORIENTATION_ROT_270: orient = MEDIA_CONTENT_ORIENTATION_ROT_180; break; default: return; } r = image_meta_set_orientation(image, orient); if (r != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to set played position"); return; } r = image_meta_update_to_db(image); if (r != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to update db"); return; } app_media_update(am); } static void _set_image_zoom(struct _priv *priv) { struct view_update_data vdata; vdata.list = priv->playlist.list; vdata.index = priv->playlist.cur; viewmgr_update_view(VIEW_ZOOM, UPDATE_CONTENT, &vdata); viewmgr_push_view(VIEW_ZOOM); } static void _update_info(struct _priv *priv, app_media_info *mi) { struct view_update_data vdata; /* update history */ util_add_to_recent(priv->playlist.list, priv->playlist.cur); /* update play info for movie */ if (util_check_movie_type(mi->video->copyright)) { vdata.index = priv->playlist.cur; vdata.id = mi->media_id; viewmgr_update_view(VIEW_BASE, UPDATE_PLAY_INFO, &vdata); viewmgr_update_view(VIEW_DETAIL, UPDATE_PLAY_INFO, &vdata); } } static void _update_to_player(struct _priv *priv) { struct view_update_data vdata; vdata.status = E_PLAYER_STOP; viewmgr_update_view(VIEW_MPLAYER, UPDATE_PLAYER, &vdata); } static bool _viewer_show(struct _priv *priv) { struct _viewer_info *info; struct controller *ctl; int id; int loc; app_media_info *mi; mi = _get_current_media_info(priv); if (!mi) { _ERR("failed to getting media info"); return false; } switch (mi->media_type) { case MEDIA_CONTENT_TYPE_IMAGE: id = VIEWER_PHOTO; break; case MEDIA_CONTENT_TYPE_VIDEO: if (util_check_movie_type(mi->video->copyright)) id = VIEWER_MOVIE; else id = VIEWER_VIDEO; break; default: return false; } info = &viewer_info[id]; ctl = priv->viewer.ctl[id]; priv->viewer.cur = id; if (!priv->slideshow.enable) ctl->ops->show(ctl->handle); loc = priv->viewer.foc; if (loc == BTN_LOC_NONE) { loc = info->focus_loc; if (id == VIEWER_MOVIE) { ctl->ops->signal(ctl->handle, BTN_LOC_PLAY, SIG_SET_PAUSE); } } _draw_title_bar(priv, id, mi); _draw_progressbar(priv, id, mi); _draw_favorite_icon(priv, id, mi); _draw_contents(priv, id, mi); ctl->ops->signal(ctl->handle, loc, SIG_SET_FOCUS); ctl->ops->focus(ctl->handle, loc, true); return true; } static void _viewer_hide(struct _priv *priv) { struct controller *ctl; ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->hide(ctl->handle); elm_object_signal_emit(priv->base, SIG_VIEWER_HIDE_FAV, ""); } static bool _viewer_add(struct _priv *priv, int id) { struct _viewer_info *info; struct controller *ctl; int i; info = &viewer_info[id]; ctl = controller_create(priv->base); if (!ctl) { _ERR("failed to create controller"); return false; } for (i = 0; i < info->btn_count; i++) { ctl->ops->add_control(ctl->handle, info->btns[i].name, info->btns[i].loc, STYLE_VIEWER_BTN, PART_VIEWER_BTN); } ctl->ops->add_callback(ctl->handle, info->callback, priv); priv->viewer.ctl[id] = ctl; return true; } static void _viewer_delete(struct _priv *priv) { int i; for (i = 0; i < VIEWER_MAX; i++) controller_destroy(priv->viewer.ctl[i]); progressbar_destroy(priv->progress); } static bool _viewer_prev(struct _priv *priv) { int total; bool r; struct controller *ctl; ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_PREV, SIG_SET_UNFOCUS); _viewer_hide(priv); total = eina_list_count(priv->playlist.list); if (priv->playlist.cur == 0) priv->playlist.cur = total - 1; else priv->playlist.cur--; priv->viewer.foc = BTN_LOC_PREV; r = _viewer_show(priv); return r; } static bool _viewer_next(struct _priv *priv) { int total; bool r; struct controller *ctl; ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_NEXT, SIG_SET_UNFOCUS); _viewer_hide(priv); total = eina_list_count(priv->playlist.list); if (priv->playlist.cur == total - 1) priv->playlist.cur = 0; else priv->playlist.cur++; priv->viewer.foc = BTN_LOC_NEXT; r = _viewer_show(priv); return r; } static void _show_bar(struct _priv *priv) { struct controller *ctl; if (priv->bar_show) return; elm_object_signal_emit(priv->base, SIG_SHOW_BAR, ""); priv->bar_show = true; ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->enable(ctl->handle); } static void _hide_bar(struct _priv *priv) { struct controller *ctl; if (!priv->bar_show) return; elm_object_signal_emit(priv->base, SIG_HIDE_BAR, ""); priv->bar_show = false; ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->disable(ctl->handle); } static Eina_Bool _slideshow_next(void *data) { struct _priv *priv; if (!data) return ECORE_CALLBACK_CANCEL; priv = data; priv->slideshow.timer = NULL; if (!priv->slideshow.enable) return ECORE_CALLBACK_CANCEL; _viewer_next(priv); return ECORE_CALLBACK_CANCEL; } static void _slideshow_set(struct _priv *priv) { if (priv->slideshow.timer) return; priv->slideshow.timer = ecore_timer_add(SLIDE_SHOW_INTERVAL, _slideshow_next, priv); } static void _slideshow_enable(struct _priv *priv) { priv->slideshow.enable = true; } static void _slideshow_disable(struct _priv *priv) { priv->slideshow.enable = false; if (priv->slideshow.timer) { ecore_timer_del(priv->slideshow.timer); priv->slideshow.timer = NULL; } } static void _pop_view(struct _priv *priv) { struct view_update_data vdata; if (priv->viewer.cur == VIEWER_MOVIE || priv->viewer.cur == VIEWER_VIDEO) _player_stop(priv); if (!priv->prev_view) { viewmgr_pop_view(); ui_app_exit(); return; } if (!strcmp(priv->prev_view, VIEW_BASE)) { vdata.index = priv->playlist.cur; vdata.id = _get_current_media_id(priv); viewmgr_update_view(VIEW_BASE, UPDATE_FOCUS, &vdata); } viewmgr_pop_view(); } static void _error_exit(struct _priv *priv) { _pop_view(priv); util_add_notify(priv->win, STYLE_TOAST, STYLE_TOAST, ERROR_MESSAGE, VIEWER_TIMEOUT); } static int _player_get_position(void *data) { struct _priv *priv; if (!data) return 0; priv = data; return playermgr_get_position(priv->player); } static void _player_set_position(struct _priv *priv, int position) { int ms; bool r; ms = position; /* set to last position */ if (position == -1) ms = playermgr_get_duration(priv->player) - 100; r = playermgr_set_position(priv->player, ms, NULL, NULL); if (!r) _error_exit(priv); } static void _player_play_pause(struct _priv *priv) { app_media_info *mi; player_state_e state; bool r; playermgr_get_state(priv->player, &state); switch (state) { case PLAYER_STATE_PAUSED: progressbar_resume(priv->progress); r = playermgr_resume(priv->player); if (!r) { _error_exit(priv); return; } break; case PLAYER_STATE_PLAYING: progressbar_pause(priv->progress); playermgr_stop_wind(priv->player); r = playermgr_pause(priv->player); if (!r) { _error_exit(priv); return; } break; case PLAYER_STATE_IDLE: case PLAYER_STATE_READY: mi = _get_current_media_info(priv); if (!mi) { _ERR("failed to getting media info"); return; } _update_to_player(priv); playermgr_stop_wind(priv->player); r = playermgr_play(priv->player, mi->file_path, mi->video->position); if (!r) { _error_exit(priv); return; } progressbar_start(priv->progress); _update_info(priv, mi); break; default: _ERR("player was not created"); _error_exit(priv); return; } } static void _player_play(struct _priv *priv) { app_media_info *mi; player_state_e state; struct controller *ctl; bool r; playermgr_get_state(priv->player, &state); switch (state) { case PLAYER_STATE_PAUSED: progressbar_resume(priv->progress); r = playermgr_resume(priv->player); if (!r) { _error_exit(priv); return; } break; case PLAYER_STATE_PLAYING: break; case PLAYER_STATE_IDLE: case PLAYER_STATE_READY: mi = _get_current_media_info(priv); if (!mi) { _ERR("failed to getting media info"); return; } _update_to_player(priv); playermgr_stop_wind(priv->player); r = playermgr_play(priv->player, mi->file_path, mi->video->position); if (!r) { _error_exit(priv); return; } progressbar_start(priv->progress); _update_info(priv, mi); break; default: _ERR("player was not created"); _error_exit(priv); return; } ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_PLAY, SIG_SET_PAUSE); ctl->ops->focus(ctl->handle, BTN_LOC_PLAY, true); } static void _player_pause(struct _priv *priv) { player_state_e state; struct controller *ctl; bool r; playermgr_get_state(priv->player, &state); switch (state) { case PLAYER_STATE_PLAYING: progressbar_pause(priv->progress); r = playermgr_pause(priv->player); if (!r) { _error_exit(priv); return; } break; case PLAYER_STATE_PAUSED: case PLAYER_STATE_IDLE: case PLAYER_STATE_READY: break; default: _ERR("player was not created"); _error_exit(priv); return; } ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_PLAY, SIG_SET_PLAY); ctl->ops->focus(ctl->handle, BTN_LOC_PLAY, true); } static void _player_stop(struct _priv *priv) { struct controller *ctl; _set_played_position(priv); progressbar_stop(priv->progress); playermgr_stop(priv->player); ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_PLAY, SIG_SET_PLAY); } static void _player_complete_cb(void *data) { struct _priv *priv; if (!data) return; priv = data; if (priv->viewer.cur == VIEWER_MOVIE) { _pop_view(priv); } else if (priv->viewer.cur == VIEWER_VIDEO) { _player_stop(priv); if (priv->slideshow.enable) _viewer_next(priv); else _viewer_show(priv); } } static void _player_set_wind(struct _priv *priv, int wind) { struct controller *ctl; switch (wind) { case WIND_FF: elm_object_signal_emit(priv->base, SIG_VIEWER_SHOW_FF, ""); playermgr_set_ff(priv->player); timeout_handler_enable(priv->timeout, false); progressbar_resume(priv->progress); ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_PLAY, SIG_SET_PLAY); break; case WIND_REW: elm_object_signal_emit(priv->base, SIG_VIEWER_SHOW_REW, ""); playermgr_set_rew(priv->player); timeout_handler_enable(priv->timeout, false); progressbar_resume(priv->progress); ctl = priv->viewer.ctl[priv->viewer.cur]; ctl->ops->signal(ctl->handle, BTN_LOC_PLAY, SIG_SET_PLAY); break; case WIND_NONE: default: elm_object_signal_emit(priv->base, SIG_VIEWER_HIDE_WIND, ""); playermgr_stop_wind(priv->player); timeout_handler_enable(priv->timeout, true); break; } _draw_wind(priv, playermgr_get_wind(priv->player)); } static void _player_seek_cb(void *data) { struct _priv *priv; if (!data) return; priv = data; _player_set_wind(priv, WIND_NONE); } static struct progressbar_ops _progressbar_ops = { .get_value = _player_get_position, }; static void _callback_movie(void *data, const char *ev) { struct _priv *priv; if (!data || !ev) return; priv = data; if (!strcmp(ev, SRC_BTN_PREV)) { _player_set_wind(priv, WIND_NONE); _player_set_position(priv, 0); } else if (!strcmp(ev, SRC_BTN_NEXT)) { _player_set_wind(priv, WIND_NONE); _player_set_position(priv, -1); } else if (!strcmp(ev, SRC_BTN_PLAY)) { _player_set_wind(priv, WIND_NONE); _player_play_pause(priv); } else if (!strcmp(ev, SRC_BTN_REW)) { _player_set_wind(priv, WIND_REW); } else if (!strcmp(ev, SRC_BTN_FF)) { _player_set_wind(priv, WIND_FF); } } static void _callback_photo(void *data, const char *ev) { struct _priv *priv; if (!data || !ev) return; priv = data; if (!strcmp(ev, SRC_BTN_GALLERY_PREV)) { _viewer_prev(priv); } else if (!strcmp(ev, SRC_BTN_GALLERY_NEXT)) { _viewer_next(priv); } else if (!strcmp(ev, SRC_BTN_ROTATE)) { _set_image_orientation(priv); priv->viewer.foc = BTN_LOC_ROTATE; _viewer_show(priv); } else if (!strcmp(ev, SRC_BTN_ZOOM)) { _set_image_zoom(priv); } else if (!strcmp(ev, SRC_BTN_SLIDE)) { _slideshow_enable(priv); _hide_bar(priv); _viewer_show(priv); } } static void _callback_video(void *data, const char *ev) { struct _priv *priv; if (!data || !ev) return; priv = data; if (!strcmp(ev, SRC_BTN_GALLERY_PREV)) { _player_set_wind(priv, WIND_NONE); _player_stop(priv); _viewer_prev(priv); } else if (!strcmp(ev, SRC_BTN_GALLERY_NEXT)) { _player_set_wind(priv, WIND_NONE); _player_stop(priv); _viewer_next(priv); } else if (!strcmp(ev, SRC_BTN_PLAY)) { _player_set_wind(priv, WIND_NONE); _player_play_pause(priv); } else if (!strcmp(ev, SRC_BTN_SLIDE)) { _player_set_wind(priv, WIND_NONE); _slideshow_enable(priv); _hide_bar(priv); _viewer_show(priv); } else if (!strcmp(ev, SRC_BTN_REW)) { _player_set_wind(priv, WIND_REW); } else if (!strcmp(ev, SRC_BTN_FF)) { _player_set_wind(priv, WIND_FF); } } static Eina_Bool _timeout_cb(void *data, int type, void *ei) { _hide_bar(data); return ECORE_CALLBACK_CANCEL; } static Eina_Bool _event_cb(void *data, int type, void *ei) { struct _priv *priv; if (!data) return ECORE_CALLBACK_PASS_ON; priv = data; if (type == ECORE_EVENT_KEY_DOWN) { Evas_Event_Key_Down *ev; if (!ei) return ECORE_CALLBACK_PASS_ON; ev = ei; if (priv->slideshow.enable) { if (!strcmp(ev->keyname, KEY_BACK) || !strcmp(ev->keyname, KEY_ESC)) { if (priv->viewer.cur == VIEWER_VIDEO) _player_stop(priv); _slideshow_disable(priv); _viewer_show(priv); _show_bar(priv); } return ECORE_CALLBACK_DONE; } if (!strcmp(ev->keyname, KEY_BACK) || !strcmp(ev->keyname, KEY_ESC)) { if (priv->bar_show) { _pop_view(priv); return ECORE_CALLBACK_DONE; } } else if (!strcmp(ev->keyname, KEY_PLAY)) { if (priv->viewer.cur != VIEWER_PHOTO) _player_play(priv); } else if (!strcmp(ev->keyname, KEY_PAUSE)) { if (priv->viewer.cur != VIEWER_PHOTO) _player_pause(priv); } else if (!strcmp(ev->keyname, KEY_STOP)) { if (priv->viewer.cur == VIEWER_MOVIE) { _pop_view(priv); return ECORE_CALLBACK_DONE; } else if (priv->viewer.cur == VIEWER_VIDEO) { _player_stop(priv); _viewer_show(priv); } } else if (!strcmp(ev->keyname, KEY_NEXT)) { if (priv->viewer.cur == VIEWER_MOVIE) { _player_set_position(priv, -1); } else if (priv->viewer.cur == VIEWER_PHOTO) { _viewer_next(priv); } else if (priv->viewer.cur == VIEWER_VIDEO) { _player_stop(priv); _viewer_next(priv); } } else if (!strcmp(ev->keyname, KEY_PREVIOUS)) { if (priv->viewer.cur == VIEWER_MOVIE) { _player_set_position(priv, 0); } else if (priv->viewer.cur == VIEWER_PHOTO) { _viewer_prev(priv); } else if (priv->viewer.cur == VIEWER_VIDEO) { _player_stop(priv); _viewer_prev(priv); } } } else { if (priv->slideshow.enable) return ECORE_CALLBACK_DONE; } _show_bar(data); return ECORE_CALLBACK_PASS_ON; } static bool _ui_init(struct _priv *priv) { struct progressbar *prog; bool r; int i; for (i = 0; i < VIEWER_MAX; i++) { r = _viewer_add(priv, i); if (!r) goto err; } prog = progressbar_create(priv->base, STYLE_VIEWER_PROGRESS); if (!prog) { _ERR("failed to adding progressbar"); goto err; } progressbar_set_parts(prog, PART_VIEWER_SLIDER, PART_VIEWER_TOTAL, PART_VIEWER_PROGRESS, VIEWER_SEPARATOR); progressbar_set_time_format(prog, PROG_TIME_FORMAT_FULL); progressbar_set_ops(prog, &_progressbar_ops, priv); priv->progress = prog; priv->timeout = timeout_handler_init(VIEWER_TIMEOUT, _timeout_cb, priv, _event_cb, priv); priv->bar_show = true; return true; err: _viewer_delete(priv); return false; } static Evas_Object *_create(Evas_Object *win, void *data) { struct _priv *priv; Evas_Object *base; struct playermgr *player; bool r; if (!win) { _ERR("failed to get win object"); return NULL; } priv = calloc(1, sizeof(*priv)); if (!priv) { _ERR("failed to allocate priv"); return NULL; } base = elm_layout_add(win); if (!base) { _ERR("failed to create base object"); goto err; } elm_layout_file_set(base, EDJEFILE, GRP_VIEWER_VIEW); evas_object_size_hint_weight_set(base, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(win, base); priv->win = win; priv->base = base; priv->playlist.list = NULL; priv->playlist.cur = 0; priv->viewer.foc = BTN_LOC_NONE; _slideshow_disable(priv); player = playermgr_create(win); if (!player) { _ERR("failed to create player"); evas_object_del(base); goto err; } r = playermgr_set_completed_cb(player, _player_complete_cb, priv); if (!r) { _ERR("failed to set callback"); evas_object_del(base); playermgr_destroy(player); goto err; } r = playermgr_set_seek_cb(player, _player_seek_cb, priv); if (!r) { _ERR("failed to set callback"); evas_object_del(base); playermgr_destroy(player); goto err; } priv->player = player; r = _ui_init(priv); if (!r) { _ERR("failed to init UI"); evas_object_del(base); playermgr_destroy(player); goto err; } viewmgr_set_view_data(VIEW_VIEWER, priv); return base; err: free(priv); return NULL; } static Eina_Bool _show_view(void *data) { struct _priv *priv; if (!data) return ECORE_CALLBACK_CANCEL; priv = data; elm_object_signal_emit(priv->base, SIG_SHOW_VIEW, ""); return ECORE_CALLBACK_CANCEL; } static void _show(void *view_data) { struct _priv *priv; if (!view_data) { _ERR("failed to get view data"); return; } priv = view_data; media_content_connect(); _viewer_show(priv); timeout_handler_enable(priv->timeout, true); evas_object_show(priv->base); ecore_timer_add(SHOW_VIEW_INTERVAL, _show_view, priv); } static void _hide(void *view_data) { struct _priv *priv; if (!view_data) { _ERR("failed to get view data"); return; } priv = view_data; _slideshow_disable(priv); _viewer_hide(priv); timeout_handler_enable(priv->timeout, false); media_content_disconnect(); evas_object_hide(priv->base); elm_object_signal_emit(priv->base, SIG_HIDE_VIEW, ""); } static void _update(void *view_data, int update_type, void *data) { struct _priv *priv; struct view_update_data *vdata; if (!view_data) { _ERR("failed to get view data"); return; } priv = view_data; vdata = data; switch (update_type) { case UPDATE_CONTENT: if (!vdata) break; priv->playlist.list = vdata->list; priv->playlist.cur = vdata->index; priv->prev_view = vdata->id; priv->viewer.foc = BTN_LOC_NONE; priv->slideshow.enable = false; break; default: break; } } static void _pause(void *view_data) { struct _priv *priv; if (!view_data) { _ERR("failed to get view data"); return; } priv = view_data; _pop_view(priv); } static void _destroy(void *view_data) { struct _priv *priv; if (!view_data) { _ERR("failed to get view data"); return; } priv = view_data; _viewer_delete(priv); timeout_handler_fini(priv->timeout); playermgr_destroy(priv->player); evas_object_del(priv->base); free(priv); } static view_class _vclass = { .view_id = VIEW_VIEWER, .create = _create, .show = _show, .hide = _hide, .update = _update, .pause = _pause, .destroy = _destroy, }; view_class *view_viewer_get_vclass(void) { return &_vclass; }