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.
18 #include <Elementary.h>
19 #include <app_debug.h>
21 #include <layoutmgr.h>
23 #include <media_content.h>
24 #include <media_info.h>
26 #include <app_media.h>
27 #include <app_contents.h>
31 #include "util/controller.h"
32 #include "util/timeout_handler.h"
33 #include "util/playermgr.h"
34 #include "util/progressbar.h"
35 #include "util/util.h"
37 #define STYLE_VIEWER_BTN "viewer_btn"
38 #define PART_VIEWER_BTN "control_btn"
39 #define PLAY_BTN_LOC 1
41 #define VIEWER_TIMEOUT 3.0
42 #define VIEWER_SEPARATOR "/ "
43 #define VIDEO_COPYRIGHT "Unknown"
59 struct controller *ctl[VIEWER_MAX];
73 Evas_Object *photo_pre;
75 struct _viewer viewer;
76 struct _playlist playlist;
77 struct timeout_handler *timeout;
78 struct playermgr *player;
79 struct progressbar *progress;
89 static struct _btn_info btn_movie[] = {
104 static struct _btn_info btn_photo[] = {
106 .name = SRC_BTN_GALLERY_PREV,
110 .name = SRC_BTN_GALLERY_NEXT,
115 static struct _btn_info btn_video[] = {
117 .name = SRC_BTN_GALLERY_PREV,
121 .name = SRC_BTN_PLAY,
125 .name = SRC_BTN_GALLERY_NEXT,
130 struct _viewer_info {
131 struct _btn_info *btns;
134 void (*callback)(void *, const char *);
137 static void _player_play(struct _priv *priv);
138 static void _player_stop(struct _priv *priv);
140 static void _callback_movie(void *data, const char *ev);
141 static void _callback_photo(void *data, const char *ev);
142 static void _callback_video(void *data, const char *ev);
144 static struct _viewer_info viewer_info[] = {
149 .callback = _callback_movie,
155 .callback = _callback_photo,
161 .callback = _callback_video,
165 static void _add_to_recent(struct _priv *priv)
170 am = eina_list_nth(priv->playlist.list, priv->playlist.cur);
172 _ERR("failed to get app_media");
176 mi = app_media_get_info(am);
178 _ERR("failed to getting media info");
182 app_contents_recent_add(CONTENTS_MEDIA, mi->media_id);
184 app_media_update(am);
189 * we assumed that if video content have the copyright then it's a movie.
191 static inline bool _check_movie_type(app_media_info *mi)
193 return strcmp(mi->video->copyright, VIDEO_COPYRIGHT);
196 static void _set_bg_color(struct _priv *priv, int r, int g, int b, int a)
200 bg = evas_object_rectangle_add(evas_object_evas_get(priv->base));
202 _ERR("failed to add rect");
206 evas_object_color_set(bg, r, g, b, a);
208 elm_object_part_content_set(priv->base, PART_VIEWER_BG, bg);
211 static void _draw_thumbnail(struct _priv *priv, app_media_info *mi)
215 if (priv->photo_pre) {
216 evas_object_del(priv->photo_pre);
217 priv->photo_pre = NULL;
221 evas_object_del(priv->photo);
225 obj = elm_image_add(priv->base);
227 _ERR("failed to adding image");
231 elm_image_file_set(obj, mi->thumbnail_path, NULL);
232 elm_object_part_content_set(priv->base, PART_VIEWER_CONTENT, obj);
237 static void _remove_thumbnail(struct _priv *priv)
239 if (priv->photo_pre) {
240 evas_object_del(priv->photo_pre);
241 priv->photo_pre = NULL;
245 evas_object_del(priv->photo);
249 _set_bg_color(priv, 0, 0, 0, 0);
251 elm_object_part_content_unset(priv->base, PART_VIEWER_CONTENT);
254 static void _image_loaded(void *data, Evas_Object *obj, void *ev)
263 if (priv->photo != priv->photo_pre) {
265 evas_object_del(priv->photo);
270 elm_object_part_content_set(priv->base, PART_VIEWER_CONTENT, obj);
273 static void _image_loaded_detail(void *data, Evas_Object *obj, void *ev)
282 priv->photo_pre = NULL;
284 _add_to_recent(priv);
287 static void _draw_contents(struct _priv *priv, int id, app_media_info *mi)
291 if (id == VIEWER_MOVIE) {
294 } else if (id == VIEWER_VIDEO) {
295 _draw_thumbnail(priv, mi);
302 if (priv->photo_pre) {
303 obj = priv->photo_pre;
305 obj = elm_photocam_add(priv->base);
307 _ERR("failed to adding photocam");
311 evas_object_smart_callback_add(obj, "loaded",
312 _image_loaded, priv);
313 evas_object_smart_callback_add(obj, "loaded,detail",
314 _image_loaded_detail, priv);
316 elm_object_focus_allow_set(obj, EINA_FALSE);
317 elm_scroller_policy_set(obj,
318 ELM_SCROLLER_POLICY_AUTO,
319 ELM_SCROLLER_POLICY_AUTO);
322 * set this photocam object to photo_pre (preloaded photo)
323 * On "loaded" callback, photo_pre object will pass to photo
324 * On "loaded,detail" callback photo_pre object will set to NULL
326 priv->photo_pre = obj;
329 _set_bg_color(priv, 0, 0, 0, 255);
331 elm_photocam_file_set(obj, mi->file_path);
332 elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT);
335 static void _draw_title_bar(struct _priv *priv, int id, app_media_info *mi)
339 char date[32] = {0,};
341 if (id == VIEWER_MOVIE) {
342 elm_object_part_text_set(priv->base,
343 PART_VIEWER_TITLE, mi->title);
345 elm_object_part_text_set(priv->base, PART_VIEWER_DATE, "");
346 elm_object_part_text_set(priv->base, PART_VIEWER_PAGE, "");
348 strftime(date, sizeof(date), "%d %b, %Y", mi->content_time);
349 strftime(day, sizeof(day), "%a", mi->content_time);
352 snprintf(buf, sizeof(buf), "%s, %s", day, date);
354 elm_object_part_text_set(priv->base, PART_VIEWER_DATE, buf);
356 snprintf(buf, sizeof(buf), "%d / %d", priv->playlist.cur + 1,
357 eina_list_count(priv->playlist.list));
358 elm_object_part_text_set(priv->base, PART_VIEWER_PAGE, buf);
360 elm_object_part_text_set(priv->base, PART_VIEWER_TITLE, "");
364 static void _draw_progressbar(struct _priv *priv, int id, app_media_info *mi)
366 if (id == VIEWER_PHOTO) {
367 elm_object_part_text_set(priv->base, PART_VIEWER_PROGRESS, "");
368 elm_object_part_text_set(priv->base, PART_VIEWER_TOTAL, "");
369 progressbar_hide(priv->progress);
374 progressbar_reset(priv->progress,
375 mi->video->position, mi->video->duration);
376 progressbar_show(priv->progress);
379 static void _draw_favorite_icon(struct _priv *priv, int id, app_media_info *mi)
382 elm_object_signal_emit(priv->base, SIG_VIEWER_SHOW_FAV, "");
384 elm_object_signal_emit(priv->base, SIG_VIEWER_HIDE_FAV, "");
387 static app_media_info *_get_current_media_info(struct _priv *priv)
392 am = eina_list_nth(priv->playlist.list, priv->playlist.cur);
394 _ERR("failed to get app_media");
398 mi = app_media_get_info(am);
400 _ERR("failed to getting media info");
407 static void _set_played_position(struct _priv *priv, int position)
413 am = eina_list_nth(priv->playlist.list, priv->playlist.cur);
415 _ERR("failed to get app_media");
419 video = app_media_get_video_handle(am);
421 _ERR("failed to getting video handle");
425 r = video_meta_set_played_position(video, position);
426 if (r != MEDIA_CONTENT_ERROR_NONE) {
427 _ERR("failed to set played position");
431 r = video_meta_update_to_db(video);
432 if (r != MEDIA_CONTENT_ERROR_NONE) {
433 _ERR("failed to update db");
437 app_media_update(am);
440 static void _update_to_player(struct _priv *priv)
442 viewmgr_update_view(VIEW_MPLAYER, UPDATE_PLAYER, NULL);
445 static bool _viewer_show(struct _priv *priv)
447 struct _viewer_info *info;
448 struct controller *ctl;
453 mi = _get_current_media_info(priv);
455 _ERR("failed to getting media info");
459 switch (mi->media_type) {
460 case MEDIA_CONTENT_TYPE_IMAGE:
463 case MEDIA_CONTENT_TYPE_VIDEO:
464 if (_check_movie_type(mi))
473 info = &viewer_info[id];
474 ctl = priv->viewer.ctl[id];
475 priv->viewer.cur = id;
477 ctl->ops->show(ctl->handle);
479 switch (priv->playlist.dir) {
484 loc = info->btn_count - 1;
488 loc = info->focus_loc;
489 if (id == VIEWER_MOVIE) {
490 ctl->ops->signal(ctl->handle,
491 PLAY_BTN_LOC, SIG_SET_PAUSE);
495 ctl->ops->signal(ctl->handle, loc, SIG_SET_FOCUS);
496 ctl->ops->focus(ctl->handle, loc, true);
498 _draw_title_bar(priv, id, mi);
499 _draw_progressbar(priv, id, mi);
500 _draw_favorite_icon(priv, id, mi);
502 _draw_contents(priv, id, mi);
507 static void _viewer_hide(struct _priv *priv)
509 struct controller *ctl;
511 ctl = priv->viewer.ctl[priv->viewer.cur];
512 ctl->ops->hide(ctl->handle);
514 elm_object_signal_emit(priv->base, SIG_VIEWER_HIDE_FAV, "");
517 static bool _viewer_add(struct _priv *priv, int id)
519 struct _viewer_info *info;
520 struct controller *ctl;
523 info = &viewer_info[id];
525 ctl = controller_create(priv->base);
527 _ERR("failed to create controller");
531 for (i = 0; i < info->btn_count; i++) {
532 ctl->ops->add_control(ctl->handle,
533 info->btns[i].name, info->btns[i].loc,
534 STYLE_VIEWER_BTN, PART_VIEWER_BTN);
537 ctl->ops->add_callback(ctl->handle, info->callback, priv);
539 priv->viewer.ctl[id] = ctl;
544 static void _viewer_delete(struct _priv *priv)
548 for (i = 0; i < VIEWER_MAX; i++)
549 controller_destroy(priv->viewer.ctl[i]);
551 progressbar_destroy(priv->progress);
554 static bool _viewer_prev(struct _priv *priv)
558 struct controller *ctl;
560 ctl = priv->viewer.ctl[priv->viewer.cur];
561 ctl->ops->signal(ctl->handle, 0, SIG_SET_UNFOCUS);
565 total = eina_list_count(priv->playlist.list);
567 if (priv->playlist.cur == 0)
568 priv->playlist.cur = total - 1;
570 priv->playlist.cur--;
572 priv->playlist.dir = DIR_PREV;
574 r = _viewer_show(priv);
579 static bool _viewer_next(struct _priv *priv)
583 struct controller *ctl;
585 ctl = priv->viewer.ctl[priv->viewer.cur];
586 ctl->ops->signal(ctl->handle, ctl->ops->get_count(ctl->handle) - 1,
591 total = eina_list_count(priv->playlist.list);
593 if (priv->playlist.cur == total - 1)
594 priv->playlist.cur = 0;
596 priv->playlist.cur++;
598 priv->playlist.dir = DIR_NEXT;
600 r = _viewer_show(priv);
605 static void _show_bar(struct _priv *priv)
607 struct controller *ctl;
612 elm_object_signal_emit(priv->base, SIG_SHOW_BAR, "");
613 priv->bar_show = true;
615 ctl = priv->viewer.ctl[priv->viewer.cur];
616 ctl->ops->enable(ctl->handle);
619 static void _hide_bar(struct _priv *priv)
621 struct controller *ctl;
626 elm_object_signal_emit(priv->base, SIG_HIDE_BAR, "");
627 priv->bar_show = false;
629 ctl = priv->viewer.ctl[priv->viewer.cur];
630 ctl->ops->disable(ctl->handle);
633 static void _pop_view(struct _priv *priv)
635 struct view_update_data vdata;
637 if (priv->viewer.cur == VIEWER_MOVIE ||
638 priv->viewer.cur == VIEWER_VIDEO)
641 if (viewmgr_active_view_count() > 1) {
642 vdata.index = priv->playlist.cur;
643 viewmgr_update_view(VIEW_BASE, UPDATE_FOCUS, &vdata);
648 if (viewmgr_active_view_count() == 0)
652 static void _timeout_cb(void *data, int type, void *ei)
657 static void _event_cb(void *data, int type, void *ei)
666 if (type == ECORE_EVENT_KEY_UP) {
667 Evas_Event_Key_Up *ev;
674 if (!strcmp(ev->keyname, KEY_BACK) ||
675 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
676 if (priv->bar_show) {
686 static int _player_get_position(void *data)
695 return playermgr_get_position(priv->player);
698 static void _player_play(struct _priv *priv)
701 player_state_e state;
703 playermgr_get_state(priv->player, &state);
706 case PLAYER_STATE_PAUSED:
707 progressbar_resume(priv->progress);
708 playermgr_resume(priv->player);
710 case PLAYER_STATE_PLAYING:
711 progressbar_pause(priv->progress);
712 playermgr_pause(priv->player);
714 case PLAYER_STATE_IDLE:
715 case PLAYER_STATE_READY:
716 mi = _get_current_media_info(priv);
718 _ERR("failed to getting media info");
722 _remove_thumbnail(priv);
723 _update_to_player(priv);
725 progressbar_start(priv->progress);
726 playermgr_play(priv->player, mi->file_path,
727 mi->video->position);
729 _add_to_recent(priv);
733 _ERR("player was not created");
738 static void _player_stop(struct _priv *priv)
740 struct controller *ctl;
743 if (priv->viewer.cur == VIEWER_MOVIE) {
744 position = playermgr_get_position(priv->player);
745 _set_played_position(priv, position);
748 progressbar_stop(priv->progress);
749 playermgr_stop(priv->player);
751 ctl = priv->viewer.ctl[priv->viewer.cur];
752 ctl->ops->signal(ctl->handle, PLAY_BTN_LOC, SIG_SET_PLAY);
755 static void _player_complete_cb(void *data)
764 _set_played_position(priv, 0);
767 if (priv->viewer.cur == VIEWER_MOVIE)
769 else if (priv->viewer.cur == VIEWER_VIDEO) {
775 static struct progressbar_ops _progressbar_ops = {
776 .get_value = _player_get_position,
779 static void _callback_movie(void *data, const char *ev)
789 if (!strcmp(ev, SRC_BTN_PREV)) {
790 playermgr_set_position(priv->player, 0, NULL, NULL);
791 } else if (!strcmp(ev, SRC_BTN_NEXT)) {
792 ms = playermgr_get_duration(priv->player);
793 playermgr_set_position(priv->player, ms - 500, NULL, NULL);
794 } else if (!strcmp(ev, SRC_BTN_PLAY)) {
799 static void _callback_photo(void *data, const char *ev)
808 if (!strcmp(ev, SRC_BTN_GALLERY_PREV))
810 else if (!strcmp(ev, SRC_BTN_GALLERY_NEXT))
814 static void _callback_video(void *data, const char *ev)
823 if (!strcmp(ev, SRC_BTN_GALLERY_PREV)) {
826 } else if (!strcmp(ev, SRC_BTN_GALLERY_NEXT)) {
829 } else if (!strcmp(ev, SRC_BTN_PLAY)) {
834 static bool _ui_init(struct _priv *priv)
836 struct progressbar *prog;
840 for (i = 0; i < VIEWER_MAX; i++) {
841 r = _viewer_add(priv, i);
846 prog = progressbar_create(priv->base, STYLE_VIEWER_PROGRESS);
848 _ERR("failed to adding progressbar");
852 progressbar_set_parts(prog, PART_VIEWER_SLIDER, PART_VIEWER_TOTAL,
853 PART_VIEWER_PROGRESS, VIEWER_SEPARATOR);
854 progressbar_set_time_format(prog, PROG_TIME_FORMAT_FULL);
855 progressbar_set_ops(prog, &_progressbar_ops, priv);
857 priv->progress = prog;
859 priv->timeout = timeout_handler_init(VIEWER_TIMEOUT,
863 priv->bar_show = true;
868 _viewer_delete(priv);
872 static Evas_Object *_create(Evas_Object *win, void *data)
876 struct playermgr *player;
880 _ERR("failed to get win object");
884 priv = calloc(1, sizeof(*priv));
886 _ERR("failed to allocate priv");
890 base = elm_layout_add(win);
892 _ERR("failed to create base object");
897 elm_layout_file_set(base, EDJEFILE, GRP_VIEWER_VIEW);
899 evas_object_size_hint_weight_set(base,
900 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
901 elm_win_resize_object_add(win, base);
906 priv->playlist.list = NULL;
907 priv->playlist.cur = 0;
908 priv->playlist.dir = DIR_NONE;
910 player = playermgr_create(win);
912 _ERR("failed to create player");
916 r = playermgr_set_completed_cb(player, _player_complete_cb, priv);
918 _ERR("failed to set callback");
919 playermgr_destroy(player);
923 priv->player = player;
927 _ERR("failed to init UI");
928 playermgr_destroy(player);
932 viewmgr_set_view_data(VIEW_VIEWER, priv);
937 static void _show(void *view_data)
942 _ERR("failed to get view data");
948 media_content_connect();
952 timeout_handler_enable(priv->timeout, true);
954 evas_object_show(priv->base);
957 static void _hide(void *view_data)
962 _ERR("failed to get view data");
970 timeout_handler_enable(priv->timeout, false);
972 media_content_disconnect();
974 evas_object_hide(priv->base);
977 static void _update(void *view_data, int update_type, void *data)
980 struct view_update_data *vdata;
983 _ERR("failed to get view data");
990 switch (update_type) {
995 priv->playlist.list = vdata->list;
996 priv->playlist.cur = vdata->index;
997 priv->playlist.dir = DIR_NONE;
1004 static void _pause(void *view_data)
1009 _ERR("failed to get view data");
1018 static void _destroy(void *view_data)
1023 _ERR("failed to get view data");
1029 _viewer_delete(priv);
1031 timeout_handler_fini(priv->timeout);
1033 playermgr_destroy(priv->player);
1035 evas_object_del(priv->base);
1040 static view_class _vclass = {
1041 .view_id = VIEW_VIEWER,
1047 .destroy = _destroy,
1050 view_class *view_viewer_get_vclass(void)