viewer: adds playermgr and support playing video 78/42878/4
authorMinkyu Kang <mk7.kang@samsung.com>
Fri, 3 Jul 2015 10:25:22 +0000 (19:25 +0900)
committerMinkyu Kang <mk7.kang@samsung.com>
Fri, 3 Jul 2015 12:27:57 +0000 (21:27 +0900)
Werror was disabled due to deprecated compiler warning from sound manager module

Change-Id: Ia798d8b4a2900c8b8aa0c71efcf0641c2477b025
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
CMakeLists.txt
include/util/playermgr.h [new file with mode: 0644]
include/view/viewer.h
packaging/org.tizen.mediahub.spec
res/edc/view/viewer.edc
res/edc/widgets/button.edc
src/main.c
src/util/playermgr.c [new file with mode: 0644]
src/view/viewer.c

index 8077938..45014bc 100644 (file)
@@ -20,6 +20,7 @@ INCLUDE(FindPkgConfig)
 pkg_check_modules(PKGS REQUIRED
                elementary
                capi-appfw-application
+               capi-media-player
                app-utils)
 
 IF(NOT DEFINED PACKAGE_NAME)
@@ -56,6 +57,7 @@ src/layout/music.c
 src/util/controller.c
 src/util/timeout_handler.c
 src/util/util.c
+src/util/playermgr.c
 src/data/mediadata.c
 )
 
@@ -77,7 +79,7 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
 FOREACH(flag ${PKGS_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall")
 
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${PKGS_LDFLAGS})
 CONFIGURE_FILE(${PACKAGE_NAME}.xml.in ${PACKAGE_NAME}.xml)
diff --git a/include/util/playermgr.h b/include/util/playermgr.h
new file mode 100644 (file)
index 0000000..7ba5831
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.
+*/
+
+#ifndef __AIR_MEDIAHUB_PLAYERMGR_H__
+#define __AIR_MEDIAHUB_PLAYERMGR_H__
+
+struct playermgr;
+
+struct playermgr *playermgr_create(Evas_Object *win);
+void playermgr_destroy(struct playermgr *m);
+
+bool playermgr_play(struct playermgr *m, const char *path);
+void playermgr_stop(struct playermgr *m);
+bool playermgr_resume(struct playermgr *m);
+bool playermgr_pause(struct playermgr *m);
+
+int playermgr_get_duration(struct playermgr *m);
+int playermgr_get_position(struct playermgr *m);
+bool playermgr_set_position(struct playermgr *m, int ms,
+               player_seek_completed_cb cb, void *data);
+void playermgr_get_state(struct playermgr *m, player_state_e *state);
+bool playermgr_set_completed_cb(struct playermgr *m,
+               player_completed_cb cb, void *data);
+
+#endif
index 1babe1c..b7622f2 100644 (file)
@@ -24,6 +24,7 @@
 #define GRP_VIEWER_VIEW "group.viewer_view"
 
 /* part */
+#define PART_VIEWER_BG "part.viewer_bg"
 #define PART_VIEWER_CONTENT "part.viewer_content"
 #define PART_VIEWER_TITLE "part.viewer_title"
 #define PART_VIEWER_DATE "part.viewer_date"
index 2a6c12a..969283d 100644 (file)
@@ -10,6 +10,7 @@ Source1:   %{name}.manifest
 BuildRequires: cmake
 BuildRequires: pkgconfig(elementary)
 BuildRequires: pkgconfig(capi-appfw-application)
+BuildRequires: pkgconfig(capi-media-player)
 BuildRequires: pkgconfig(app-utils)
 
 %define _appdir /usr/apps/%{name}
index a8007a1..e698125 100644 (file)
@@ -25,7 +25,22 @@ group {
                        scale: 1;
                        description {
                                state: "default" 0.0;
-                               color: 0 0 0 255;
+                               color: 0 0 0 0;
+                       }
+               }
+               part {
+                       name: PART_VIEWER_BG;
+                       type: SWALLOW;
+                       scale: 1;
+                       description {
+                               state: "default" 0.0;
+                               rel2 {
+                                       relative: 0.0 0.0;
+                               }
+                               rel2 {
+                                       relative: 1.0 1.0;
+                               }
+                               align: 0.0 0.0;
                        }
                }
                part {
index 2113a5b..98bff76 100644 (file)
@@ -502,7 +502,7 @@ group {
                        script {
                                set_int(cur_state, STATE_PAUSE);
                                set_state(PART:"bg", "default_pause", 0.0);
-                               set_state(PART:"color", "default", 0.0);
+                               set_state(PART:"color", "default_pause", 0.0);
                        }
                }
                program {
index 3b01bb5..d68cc2a 100644 (file)
@@ -34,12 +34,16 @@ struct _appdata {
 static Evas_Object *_add_win(const char *name)
 {
        Evas_Object *win;
+       int w, h;
 
-       win = elm_win_util_standard_add(NULL, name);
+       win = elm_win_add(NULL, name, ELM_WIN_BASIC);
        if (!win)
                return NULL;
 
        elm_win_title_set(win, MEDIAHUB_WIN_TITLE);
+       elm_win_alpha_set(win, EINA_TRUE);
+       elm_win_screen_size_get(win, NULL, NULL, &w, &h);
+       evas_object_resize(win, w, h);
 
        evas_object_show(win);
 
diff --git a/src/util/playermgr.c b/src/util/playermgr.c
new file mode 100644 (file)
index 0000000..07aa63c
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * 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 <stdbool.h>
+#include <Elementary.h>
+#include <app_debug.h>
+#include <player.h>
+
+#include "define.h"
+
+struct playermgr {
+       Evas_Object *win;
+       player_h player;
+};
+
+int playermgr_get_duration(struct playermgr *m)
+{
+       int r;
+       int ms;
+
+       if (!m) {
+               _ERR("invalid parameter");
+               return 0;
+       }
+
+       r = player_get_duration(m->player, &ms);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: get_position error (%d)", r);
+               return 0;
+       }
+
+       return ms;
+}
+
+int playermgr_get_position(struct playermgr *m)
+{
+       int r;
+       int ms;
+
+       if (!m) {
+               _ERR("invalid parameter");
+               return 0;
+       }
+
+       r = player_get_play_position(m->player, &ms);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: get_position error (%d)", r);
+               return 0;
+       }
+
+       return ms;
+}
+
+bool playermgr_set_position(struct playermgr *m, int ms,
+               player_seek_completed_cb cb, void *data)
+{
+       int r;
+
+       if (!m) {
+               _ERR("invalid parameter");
+               return false;
+       }
+
+       r = player_set_play_position(m->player, ms, false, cb, data);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: set_position error (%d)", r);
+               return false;
+       }
+
+       return true;
+}
+
+void playermgr_get_state(struct playermgr *m, player_state_e *state)
+{
+       int r;
+
+       if (!m) {
+               _ERR("invalid parameter");
+               return;
+       }
+
+       r = player_get_state(m->player, state);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: get_state error (%d)", r);
+               *state = PLAYER_STATE_NONE;
+       }
+}
+
+bool playermgr_pause(struct playermgr *m)
+{
+       player_state_e state;
+       int r;
+
+       if (!m) {
+               _ERR("invalid parameter");
+               return false;
+       }
+
+       playermgr_get_state(m, &state);
+       if (state == PLAYER_STATE_PAUSED)
+               return true;
+
+       r = player_pause(m->player);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: pause error (%d)", r);
+               return false;
+       }
+
+       return true;
+}
+
+bool playermgr_resume(struct playermgr *m)
+{
+       player_state_e state;
+       int r;
+
+       if (!m) {
+               _ERR("invalid parameter");
+               return false;
+       }
+
+       playermgr_get_state(m, &state);
+       if (state == PLAYER_STATE_PLAYING)
+               return true;
+
+       r = player_start(m->player);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: start error (%d)", r);
+               return false;
+       }
+
+       return true;
+}
+
+void playermgr_stop(struct playermgr *m)
+{
+       if (!m) {
+               _ERR("invalid parameter");
+               return;
+       }
+
+       player_pause(m->player);
+       player_stop(m->player);
+       player_unprepare(m->player);
+}
+
+bool playermgr_play(struct playermgr *m, const char *path)
+{
+       int r;
+
+       if (!m || !path) {
+               _ERR("invalid parameter");
+               return false;
+       }
+
+       playermgr_stop(m);
+
+       r = player_set_uri(m->player, path);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: set_uri error (%d)", r);
+               return false;
+       }
+
+       r = player_set_display(m->player, PLAYER_DISPLAY_TYPE_OVERLAY,
+                       GET_DISPLAY(m->win));
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: set_display error (%d)", r);
+               return false;
+       }
+
+       r = player_set_display_mode(m->player, PLAYER_DISPLAY_MODE_FULL_SCREEN);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: set_display_mode error (%d)", r);
+               return false;
+       }
+
+       r = player_prepare(m->player);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: prepare error (%d)", r);
+               return false;
+       }
+
+       r = player_start(m->player);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: start error (%d)", r);
+               return false;
+       }
+
+       return true;
+}
+
+bool playermgr_set_completed_cb(struct playermgr *m,
+               player_completed_cb cb, void *data)
+{
+       int r;
+
+       r = player_set_completed_cb(m->player, cb, data);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: set callback error (%d)", r);
+               return false;
+       }
+
+       return true;
+}
+
+struct playermgr *playermgr_create(Evas_Object *win)
+{
+       struct playermgr *m;
+       int r;
+
+       if (!win) {
+               _ERR("invalid parameter");
+               return NULL;
+       }
+
+       m = calloc(1, sizeof(*m));
+       if (!m) {
+               _ERR("failed to allocate");
+               return NULL;
+       }
+
+       r = player_create(&m->player);
+       if (r != PLAYER_ERROR_NONE) {
+               _ERR("player: creation error (%d)", r);
+               free(m);
+               return NULL;
+       }
+
+       m->win = win;
+
+       return m;
+}
+
+void playermgr_destroy(struct playermgr *m)
+{
+       if (!m) {
+               _ERR("invalid parameter");
+               return;
+       }
+
+       if (m->player) {
+               playermgr_stop(m);
+               player_destroy(m->player);
+       }
+
+       free(m);
+}
index 91c09be..898aa07 100644 (file)
 #include <layoutmgr.h>
 #include <media_content.h>
 #include <media_info.h>
+#include <player.h>
 #include <app_media.h>
 
 #include "define.h"
 #include "util/controller.h"
 #include "util/timeout_handler.h"
+#include "util/playermgr.h"
+#include "util/util.h"
 
 #define STYLE_VIEWER_BTN "viewer_btn"
 #define PART_VIEWER_BTN "control_btn"
+#define PLAY_BTN_LOC 2
 
 #define VIEWER_TIMEOUT 3.0
+#define VIEWER_INTERVAL 0.1
 
 #define VIDEO_COPYRIGHT "Unknown"
 
@@ -62,10 +67,12 @@ struct _priv {
        Evas_Object *photo;
        Evas_Object *photo_pre;
        Evas_Object *favorite;
+       Evas_Object *timer;
 
        struct _viewer viewer;
        struct _playlist playlist;
        struct timeout_handler *timeout;
+       struct playermgr *player;
 
        bool bar_show;
 };
@@ -139,6 +146,8 @@ struct _viewer_info {
        void (*callback)(void *, const char *);
 };
 
+static void _player_play(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);
@@ -247,7 +256,22 @@ static void _up_string(char *str)
        }
 }
 
-static void _draw_thumbnail(struct _priv *priv, int id, app_media_info *mi)
+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 _draw_thumbnail(struct _priv *priv, app_media_info *mi)
 {
        Evas_Object *obj;
 
@@ -273,6 +297,23 @@ static void _draw_thumbnail(struct _priv *priv, int id, app_media_info *mi)
        priv->photo = obj;
 }
 
+static void _remove_thumbnail(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;
@@ -304,15 +345,15 @@ static void _image_loaded_detail(void *data, Evas_Object *obj, void *ev)
        priv->photo_pre = NULL;
 }
 
-static void _load_image_file(struct _priv *priv, int id, app_media_info *mi)
+static void _draw_contents(struct _priv *priv, int id, app_media_info *mi)
 {
        Evas_Object *obj;
 
        if (id == VIEWER_MOVIE) {
-               elm_object_part_content_unset(priv->base, PART_VIEWER_CONTENT);
+               _player_play(priv);
                return;
        } else if (id == VIEWER_VIDEO) {
-               _draw_thumbnail(priv, id, mi);
+               _draw_thumbnail(priv, mi);
                return;
        }
 
@@ -346,6 +387,8 @@ static void _load_image_file(struct _priv *priv, int id, app_media_info *mi)
                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);
 }
@@ -393,6 +436,14 @@ static void _draw_time_info(struct _priv *priv, int id, app_media_info *mi)
        elm_object_part_text_set(priv->base, PART_VIEWER_TOTAL, total);
 }
 
+static void _draw_progress_info(struct _priv *priv, int ms)
+{
+       char progress[32] = {0,};
+
+       _time_string(progress, sizeof(progress), ms);
+       elm_object_part_text_set(priv->base, PART_VIEWER_PROGRESS, progress);
+}
+
 static void _draw_favorite_icon(struct _priv *priv, int id, app_media_info *mi)
 {
        if (!mi->favorite)
@@ -402,26 +453,37 @@ static void _draw_favorite_icon(struct _priv *priv, int id, app_media_info *mi)
                        PART_VIEWER_FAVORITE, priv->favorite);
 }
 
-static bool _viewer_show(struct _priv *priv, int cur, int foc)
+static app_media_info *_get_current_media_info(struct _priv *priv)
 {
-       struct _viewer_info *info;
-       struct controller *ctl;
-       int id;
-       int loc;
        app_media *am;
        app_media_info *mi;
 
-       am = eina_list_nth(priv->playlist.list, cur);
+       am = eina_list_nth(priv->playlist.list, priv->playlist.cur);
        if (!am) {
                _ERR("failed to get app_media");
-               return false;
+               return NULL;
        }
 
-       priv->playlist.cur = cur;
-
        mi = app_media_get_info(am);
        if (!mi) {
                _ERR("failed to getting media info");
+               return NULL;
+       }
+
+       return mi;
+}
+
+static bool _viewer_show(struct _priv *priv, int foc)
+{
+       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;
        }
 
@@ -455,11 +517,15 @@ static bool _viewer_show(struct _priv *priv, int cur, int foc)
        case DIR_NONE:
        default:
                loc = info->focus_loc;
+               if (id == VIEWER_MOVIE) {
+                       ctl->ops->signal(ctl->handle,
+                                       PLAY_BTN_LOC, SIG_SET_PAUSE);
+               }
                break;
        }
        ctl->ops->focus(ctl->handle, loc, true);
 
-       _load_image_file(priv, id, mi);
+       _draw_contents(priv, id, mi);
 
        _draw_title_bar(priv, id, mi);
        _draw_time_info(priv, id, mi);
@@ -527,7 +593,7 @@ static bool _viewer_prev(struct _priv *priv)
        else
                priv->playlist.cur--;
 
-       r = _viewer_show(priv, priv->playlist.cur, DIR_PREV);
+       r = _viewer_show(priv, DIR_PREV);
 
        return r;
 }
@@ -546,7 +612,7 @@ static bool _viewer_next(struct _priv *priv)
        else
                priv->playlist.cur++;
 
-       r = _viewer_show(priv, priv->playlist.cur, DIR_NEXT);
+       r = _viewer_show(priv, DIR_NEXT);
 
        return r;
 }
@@ -623,8 +689,141 @@ err:
        return false;
 }
 
+static Eina_Bool _timer_cb(void *data)
+{
+       struct _priv *priv;
+       int ms;
+
+       if (!data)
+               return ECORE_CALLBACK_CANCEL;
+
+       priv = data;
+
+       ms = playermgr_get_position(priv->player);
+
+       _draw_progress_info(priv, ms);
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+static void _timer_reset(struct _priv *priv)
+{
+       if (priv->timer)
+               ecore_timer_reset(priv->timer);
+       else
+               priv->timer = ecore_timer_add(VIEWER_INTERVAL, _timer_cb, priv);
+}
+
+static void _player_play(struct _priv *priv)
+{
+       app_media_info *mi;
+       player_state_e state;
+
+       playermgr_get_state(priv->player, &state);
+
+       switch (state) {
+       case PLAYER_STATE_PAUSED:
+               if (priv->timer)
+                       ecore_timer_thaw(priv->timer);
+
+               playermgr_resume(priv->player);
+               break;
+       case PLAYER_STATE_PLAYING:
+               if (priv->timer)
+                       ecore_timer_freeze(priv->timer);
+
+               playermgr_pause(priv->player);
+               break;
+       case PLAYER_STATE_IDLE:
+       case PLAYER_STATE_READY:
+               mi = _get_current_media_info(priv);
+               if (!mi) {
+                       _ERR("failed to getting media info");
+                       return;
+               }
+
+               _remove_thumbnail(priv);
+               _timer_reset(priv);
+
+               playermgr_play(priv->player, mi->file_path);
+
+               break;
+       default:
+               _ERR("player was not created");
+               break;
+       }
+}
+
+static void _player_stop(struct _priv *priv)
+{
+       struct controller *ctl;
+
+       ecore_timer_del(priv->timer);
+       priv->timer = NULL;
+
+       playermgr_stop(priv->player);
+
+       ctl = priv->viewer.ctl[priv->viewer.cur];
+       ctl->ops->signal(ctl->handle, PLAY_BTN_LOC, SIG_SET_PLAY);
+}
+
+static void _player_complete_cb(void *data)
+{
+       struct _priv *priv;
+
+       if (!data)
+               return;
+
+       priv = data;
+
+       ecore_timer_del(priv->timer);
+       priv->timer = NULL;
+}
+
+static void _player_set_position_cb(void *data)
+{
+       struct _priv *priv;
+       struct controller *ctl;
+       int ms;
+
+       if (!data)
+               return;
+
+       priv = data;
+
+       ms = playermgr_get_position(priv->player);
+       _draw_progress_info(priv, ms);
+
+       /* FIXME: what will you do here? */
+       playermgr_pause(priv->player);
+
+       if (priv->timer)
+               ecore_timer_freeze(priv->timer);
+
+       ctl = priv->viewer.ctl[priv->viewer.cur];
+       ctl->ops->signal(ctl->handle, PLAY_BTN_LOC, SIG_SET_PLAY);
+}
+
 static void _callback_movie(void *data, const char *ev)
 {
+       struct _priv *priv;
+       int ms;
+
+       if (!data || !ev)
+               return;
+
+       priv = data;
+
+       if (!strcmp(ev, SRC_BTN_PREV)) {
+               playermgr_set_position(priv->player, 0,
+                               _player_set_position_cb, priv);
+       } else if (!strcmp(ev, SRC_BTN_NEXT)) {
+               ms = playermgr_get_duration(priv->player);
+               playermgr_set_position(priv->player, ms - 1000,
+                               _player_set_position_cb, priv);
+       } else if (!strcmp(ev, SRC_BTN_PLAY)) {
+               _player_play(priv);
+       }
 }
 
 static void _callback_photo(void *data, const char *ev)
@@ -636,11 +835,10 @@ static void _callback_photo(void *data, const char *ev)
 
        priv = data;
 
-       if (!strcmp(ev, SRC_BTN_PHOTO_PREV)) {
+       if (!strcmp(ev, SRC_BTN_PHOTO_PREV))
                _viewer_prev(priv);
-       } else if (!strcmp(ev, SRC_BTN_PHOTO_NEXT)) {
+       else if (!strcmp(ev, SRC_BTN_PHOTO_NEXT))
                _viewer_next(priv);
-       }
 }
 
 static void _callback_video(void *data, const char *ev)
@@ -653,9 +851,13 @@ static void _callback_video(void *data, const char *ev)
        priv = data;
 
        if (!strcmp(ev, SRC_BTN_PREV)) {
+               _player_stop(priv);
                _viewer_prev(priv);
        } else if (!strcmp(ev, SRC_BTN_NEXT)) {
+               _player_stop(priv);
                _viewer_next(priv);
+       } else if (!strcmp(ev, SRC_BTN_PLAY)) {
+               _player_play(priv);
        }
 }
 
@@ -663,6 +865,7 @@ static Evas_Object *_create(Evas_Object *win, void *data)
 {
        struct _priv *priv;
        Evas_Object *base;
+       struct playermgr *player;
        bool r;
 
        if (!win) {
@@ -695,9 +898,25 @@ static Evas_Object *_create(Evas_Object *win, void *data)
        priv->playlist.list = NULL;
        priv->playlist.cur = 0;
 
+       player = playermgr_create(win);
+       if (!player) {
+               _ERR("failed to create player");
+               return NULL;
+       }
+
+       r = playermgr_set_completed_cb(player, _player_complete_cb, priv);
+       if (!r) {
+               _ERR("failed to set callback");
+               playermgr_destroy(player);
+               return NULL;
+       }
+
+       priv->player = player;
+
        r = _ui_init(priv);
        if (!r) {
                _ERR("failed to init UI");
+               playermgr_destroy(player);
                return NULL;
        }
 
@@ -721,7 +940,7 @@ static void _show(void *view_data)
        priv = view_data;
 
        /* FIXME: test code */
-       _viewer_show(priv, priv->playlist.cur, DIR_NONE);
+       _viewer_show(priv, DIR_NONE);
 
        timeout_handler_reset(priv->timeout);
 
@@ -763,6 +982,11 @@ static void _destroy(void *view_data)
 
        timeout_handler_fini(priv->timeout);
 
+       ecore_timer_del(priv->timer);
+       priv->timer = NULL;
+
+       playermgr_destroy(priv->player);
+
        evas_object_del(priv->base);
 
        free(priv);