summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/define.h2
-rw-r--r--include/util/util.h1
-rw-r--r--include/view/mplayer.h4
-rw-r--r--res/edc/images/ic_music_list_play.pngbin0 -> 1027 bytes
-rw-r--r--res/edc/images/ic_music_list_play_foc.pngbin0 -> 1709 bytes
-rw-r--r--res/edc/mediahub-theme.edc1
-rw-r--r--res/edc/view/mplayer.edc13
-rw-r--r--res/edc/widgets/genlist.edc376
-rw-r--r--src/util/util.c20
-rw-r--r--src/view/mplayer.c214
10 files changed, 629 insertions, 2 deletions
diff --git a/include/define.h b/include/define.h
index dc8be89..4edee07 100644
--- a/include/define.h
+++ b/include/define.h
@@ -51,6 +51,7 @@
#define COLOR_ITEM_SELECTED 64 136 211 255
#define COLOR_ITEM_BAR 190 190 190 255
#define COLOR_ITEM_BORDER 194 194 194 255
+#define COLOR_LIST_BG 244 244 244 255
/* part */
#define PART_ELM_TEXT_TITLE "elm.text.title"
@@ -65,6 +66,7 @@
#define SIG_BTN_SELECTED "btn,selected"
#define SIG_BTN_UNSELECTED "btn,unselected"
#define SIG_ITEM_SELECTED "item,selected"
+#define SIG_ITEM_UNSELECTED "item,unselected"
#define SIG_SOURCE_EDC "edc"
#define SIG_SOURCE_SRC "src"
diff --git a/include/util/util.h b/include/util/util.h
index c5b4afa..dd4bbb7 100644
--- a/include/util/util.h
+++ b/include/util/util.h
@@ -20,6 +20,7 @@
Evas_Object *util_add_box(Evas_Object *base);
Evas_Object *util_add_gengrid(Evas_Object *base,
int item_size_x, int item_size_y);
+Evas_Object *util_add_genlist(Evas_Object *base);
Evas_Object *util_add_image(Evas_Object *base, const char *file);
Evas_Object *util_add_scroller(Evas_Object *base);
diff --git a/include/view/mplayer.h b/include/view/mplayer.h
index 660e780..297ba41 100644
--- a/include/view/mplayer.h
+++ b/include/view/mplayer.h
@@ -25,6 +25,7 @@
/* style */
#define STYLE_MPLAYER_PROGRESS "music_progress"
+#define STYLE_MPLAYER_LIST "music_list"
/* part */
#define PART_MPLAYER_BG "part.mplayer_bg"
@@ -34,6 +35,7 @@
#define PART_MPLAYER_PROGRESS "part.mplayer_progress"
#define PART_MPLAYER_TOTAL "part.mplayer_total"
#define PART_MPLAYER_SLIDER "part.mplayer_slider"
+#define PART_MPLAYER_LIST "part.mplayer_list"
/* source */
#define SRC_BTN_MUSIC_SHUFFLE "shuffle"
@@ -57,5 +59,7 @@
#define IMAGE_MUSIC_SHUFFLE_DIS_NORMAL "btn_music_contr_shuffle_dis.png"
#define IMAGE_MUSIC_REPEAT_FOCUS "btn_music_contr_repeat_foc.png"
#define IMAGE_MUSIC_REPEAT_NORMAL "btn_music_contr_repeat_nor.png"
+#define IMAGE_MUSIC_LIST_PLAY "ic_music_list_play.png"
+#define IMAGE_MUSIC_LIST_PLAY_FOC "ic_music_list_play_foc.png"
#endif
diff --git a/res/edc/images/ic_music_list_play.png b/res/edc/images/ic_music_list_play.png
new file mode 100644
index 0000000..7a6ae5d
--- /dev/null
+++ b/res/edc/images/ic_music_list_play.png
Binary files differ
diff --git a/res/edc/images/ic_music_list_play_foc.png b/res/edc/images/ic_music_list_play_foc.png
new file mode 100644
index 0000000..9392c0f
--- /dev/null
+++ b/res/edc/images/ic_music_list_play_foc.png
Binary files differ
diff --git a/res/edc/mediahub-theme.edc b/res/edc/mediahub-theme.edc
index 4eb7b88..f1981b6 100644
--- a/res/edc/mediahub-theme.edc
+++ b/res/edc/mediahub-theme.edc
@@ -19,5 +19,6 @@
collections {
#include "widgets/button.edc"
#include "widgets/gengrid.edc"
+ #include "widgets/genlist.edc"
#include "widgets/slider.edc"
}
diff --git a/res/edc/view/mplayer.edc b/res/edc/view/mplayer.edc
index 1a4415f..21c9654 100644
--- a/res/edc/view/mplayer.edc
+++ b/res/edc/view/mplayer.edc
@@ -429,10 +429,21 @@ group {
clip_to: "rightarea";
description {
state: "default" 0.0;
- color: COLOR_BASE_BG;
+ color: COLOR_LIST_BG;
rel1.to: "rightarea";
rel2.to: "rightarea";
}
}
+ part {
+ name: PART_MPLAYER_LIST;
+ type: SWALLOW;
+ scale: 1;
+ clip_to: "rightarea";
+ description {
+ state: "default" 0.0;
+ rel1.to: "rightarea_bg";
+ rel2.to: "rightarea_bg";
+ }
+ }
}
}
diff --git a/res/edc/widgets/genlist.edc b/res/edc/widgets/genlist.edc
new file mode 100644
index 0000000..c93f86d
--- /dev/null
+++ b/res/edc/widgets/genlist.edc
@@ -0,0 +1,376 @@
+/*
+ * 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.
+ */
+
+#define LIST_TRANSITION_TIME 0.30
+
+group {
+ name: "elm/genlist/item/music_list/default";
+ data.item: "selectraise" "on";
+ data.item: "focusraise" "on";
+ data.item: "texts" "elm.text.title elm.text.artist elm.text.playtime";
+ data.item: "contents" "elm.swallow.icon";
+ data.item: "focus_highlight" "on";
+ images {
+ image: IMAGE_MUSIC_LIST_PLAY COMP;
+ image: IMAGE_MUSIC_LIST_PLAY_FOC COMP;
+ }
+ parts {
+ part {
+ name: "bg";
+ type: RECT;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 0 140;
+ color: COLOR_LIST_BG;
+ }
+ description {
+ state: "focused" 0.0;
+ inherit: "default" 0.0;
+ color: COLOR_ITEM_FOCUS;
+ }
+ }
+ part {
+ name: "left_padding";
+ type: SPACER;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 44 140;
+ rel1 {
+ to: "bg";
+ relative: 0.0 0.0;
+ }
+ rel2 {
+ to: "bg";
+ relative: 0.0 0.0;
+ }
+ fixed: 1 1;
+ align: 0.0 0.0;
+ }
+ }
+ part {
+ name: "image_bg";
+ type: RECT;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 0 140;
+ rel1 {
+ to: "left_padding";
+ relative: 1.0 0.0;
+ }
+ rel2 {
+ to: "left_padding";
+ relative: 1.0 0.0;
+ }
+ fixed: 1 1;
+ align: 0.0 0.0;
+ visible: 0;
+ }
+ description {
+ state: "default" 0.1;
+ inherit: "default" 0.0;
+ min: 40 140;
+ }
+ }
+ part {
+ name: "image_play";
+ type: IMAGE;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 40 40;
+ rel1 {
+ to: "image_bg";
+ relative: 0.5 0.5;
+ }
+ rel2 {
+ to: "image_bg";
+ relative: 0.5 0.5;
+ }
+ align: 0.5 0.5;
+ fixed: 1 1;
+ visible: 0;
+ }
+ description {
+ state: "default" 0.1;
+ inherit: "default" 0.0;
+ min: 40 40;
+ fixed: 1 1;
+ image.normal: IMAGE_MUSIC_LIST_PLAY;
+ visible: 1;
+ }
+ description {
+ state: "focused" 0.1;
+ inherit: "default" 0.0;
+ min: 40 40;
+ fixed: 1 1;
+ image.normal: IMAGE_MUSIC_LIST_PLAY_FOC;
+ visible: 1;
+ }
+ }
+ part {
+ name: "image_padding";
+ type: SPACER;
+ description {
+ state: "default" 0.0;
+ min: 0 140;
+ rel1 {
+ to: "image_bg";
+ relative: 1.0 0.0;
+ }
+ rel2 {
+ to: "image_bg";
+ relative: 1.0 0.0;
+ }
+ fixed: 1 1;
+ align: 0.0 0.0;
+ }
+ description {
+ state: "default" 0.1;
+ inherit: "default" 0.0;
+ min: 28 140;
+ }
+ }
+ part {
+ name: "right_padding";
+ type: SPACER;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 40 140;
+ rel1 {
+ to: "bg";
+ relative: 1.0 0.0;
+ }
+ rel2 {
+ to: "bg";
+ relative: 1.0 0.0;
+ }
+ fixed: 1 1;
+ align: 1.0 0.0;
+ }
+ }
+ part {
+ name: "time_padding";
+ type: SPACER;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 0 140;
+ rel1 {
+ to: "right_padding";
+ relative: 0.0 0.0;
+ }
+ rel2 {
+ to: "right_padding";
+ relative: 0.0 0.0;
+ }
+ fixed: 1 1;
+ align: 0.0 0.0;
+ }
+ description {
+ state: "default" 0.1;
+ inherit: "default" 0.0;
+ min: 130 140;
+ rel1 {
+ to: "right_padding";
+ relative: 1.0 0.0;
+ }
+ rel2 {
+ to: "right_padding";
+ relative: 1.0 0.0;
+ }
+ align: 0.0 0.0;
+ fixed: 1 1;
+ }
+ }
+ part {
+ name: PART_ELM_TEXT_PLAYTIME;
+ type: TEXT;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 130 0;
+ rel1 {
+ to: "time_padding";
+ relative: 1.0 0.0;
+ }
+ rel2 {
+ to: "time_padding";
+ relative: 1.0 1.0;
+ }
+ text {
+ font: FONT_LIGHT;
+ size: 28;
+ align: 1.0 0.5;
+ }
+ fixed: 1 0;
+ align: 1.0 0.0;
+ color: COLOR_TEXT_MENU;
+ }
+ description {
+ state: "focused" 0.0;
+ inherit: "default" 0.0;
+ color: COLOR_TEXT_FOCUS;
+ }
+ }
+ part {
+ name: PART_ELM_TEXT_TITLE;
+ type: TEXT;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 0 68;
+ rel1 {
+ to: "image_padding";
+ relative: 1.0 0.0;
+ }
+ rel2 {
+ to: PART_ELM_TEXT_PLAYTIME;
+ relative: 0.0 0.0;
+ }
+ text {
+ font: FONT_LIGHT;
+ size: 36;
+ align: 0.0 1.0;
+ }
+ fixed: 0 1;
+ align: 0.0 0.0;
+ color: COLOR_TEXT_INDEX;
+ }
+ description {
+ state: "focused" 0.0;
+ inherit: "default" 0.0;
+ color: COLOR_TEXT_FOCUS;
+ }
+ }
+ part {
+ name: PART_ELM_TEXT_ARTIST;
+ type: TEXT;
+ scale: 1;
+ description {
+ state: "default" 0.0;
+ min: 0 44;
+ rel1 {
+ to: PART_ELM_TEXT_TITLE;
+ relative: 0.0 1.0;
+ }
+ rel2 {
+ to: PART_ELM_TEXT_TITLE;
+ relative: 1.0 1.0;
+ }
+ text {
+ font: FONT_LIGHT;
+ size: 28;
+ align: 0.0 1.0;
+ }
+ fixed: 0 1;
+ align: 0.0 0.0;
+ color: COLOR_TEXT_MENU;
+ }
+ description {
+ state: "focused" 0.0;
+ inherit: "default" 0.0;
+ color: COLOR_TEXT_FOCUS;
+ }
+ }
+ }
+ script {
+ public focus_status = 0;
+ public select_status = 0;
+ }
+ programs {
+ program {
+ name: "go_active";
+ signal: "elm,state,focused";
+ source: "elm";
+ script {
+ set_int(focus_status, 1);
+ set_state(PART:"bg", "focused", 0.0);
+ set_state(PART:PART_ELM_TEXT_TITLE, "focused", 0.0);
+ set_state(PART:PART_ELM_TEXT_ARTIST, "focused", 0.0);
+ set_state(PART:PART_ELM_TEXT_PLAYTIME, "focused", 0.0);
+ if (get_int(select_status) == 1)
+ set_state(PART:"image_play", "focused", 0.1);
+ else
+ set_state(PART:"image_play", "default", 0.0);
+ }
+ }
+ program {
+ name: "go_passive";
+ signal: "elm,state,unfocused";
+ source: "elm";
+ script {
+ set_int(focus_status, 0);
+ set_state(PART:"bg", "default", 0.0);
+ set_state(PART:PART_ELM_TEXT_TITLE, "default", 0.0);
+ set_state(PART:PART_ELM_TEXT_ARTIST, "default", 0.0);
+ set_state(PART:PART_ELM_TEXT_PLAYTIME, "default", 0.0);
+ if (get_int(select_status) == 1)
+ set_state(PART:"image_play", "default", 0.1);
+ else
+ set_state(PART:"image_play", "default", 0.0);
+ }
+ }
+ program {
+ name: "go_select";
+ signal: SIG_ITEM_SELECTED;
+ source: SIG_SOURCE_SRC;
+ script {
+ set_int(select_status, 1);
+ run_program(PROGRAM:"anim,select");
+ }
+ }
+ program {
+ name: "anim,select";
+ action: STATE_SET "default" 0.1;
+ target: "image_padding";
+ target: "image_bg";
+ target: "time_padding";
+ transition: LINEAR LIST_TRANSITION_TIME;
+ after: "select,image";
+ }
+ program {
+ name: "select,image";
+ script {
+ if (get_int(focus_status) == 1)
+ set_state(PART:"image_play", "focused", 0.1);
+ else
+ set_state(PART:"image_play", "default", 0.1);
+ }
+ }
+ program {
+ name: "go_unselect";
+ signal: SIG_ITEM_UNSELECTED;
+ source: SIG_SOURCE_SRC;
+ script {
+ set_int(select_status, 0);
+ set_state(PART:"image_play", "default", 0.0);
+ run_program(PROGRAM:"anim,unselect");
+ }
+ }
+ program {
+ name: "anim,unselect";
+ action: STATE_SET "default" 0.0;
+ target: "image_padding";
+ target: "image_bg";
+ target: "time_padding";
+ transition: LINEAR LIST_TRANSITION_TIME;
+ }
+ }
+}
diff --git a/src/util/util.c b/src/util/util.c
index 73f2488..8446b7a 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -70,6 +70,26 @@ Evas_Object *util_add_gengrid(Evas_Object *base,
return grid;
}
+Evas_Object *util_add_genlist(Evas_Object *base)
+{
+ Evas_Object *list;
+
+ list = elm_genlist_add(base);
+ if (!list) {
+ _ERR("failed to adding genlist");
+ return NULL;
+ }
+
+ evas_object_size_hint_weight_set(list,
+ EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ elm_genlist_homogeneous_set(list, EINA_TRUE);
+ elm_genlist_select_mode_set(list, ELM_OBJECT_SELECT_MODE_ALWAYS);
+ elm_genlist_multi_select_set(list, EINA_FALSE);
+
+ return list;
+}
+
Evas_Object *util_add_image(Evas_Object *base, const char *file)
{
Evas_Object *image;
diff --git a/src/view/mplayer.c b/src/view/mplayer.c
index 90a89cb..c10468b 100644
--- a/src/view/mplayer.c
+++ b/src/view/mplayer.c
@@ -37,6 +37,11 @@
#define PART_MUSIC_BTN "control_btn"
#define PLAY_BTN_LOC 2
+struct _list_data {
+ app_media *am;
+ Elm_Object_Item *item;
+};
+
struct _playlist {
Eina_List *list;
int cur;
@@ -46,6 +51,9 @@ struct _priv {
Evas_Object *win;
Evas_Object *base;
Evas_Object *thumb;
+ Evas_Object *list;
+
+ Eina_List *item_list;
struct _playlist playlist;
struct playermgr *player;
@@ -129,6 +137,20 @@ static void _media_test(struct _priv *priv)
}
/* FIXME: test function end */
+static void _draw_playlist(struct _priv *priv)
+{
+ struct _list_data *ld;
+
+ ld = eina_list_nth(priv->item_list, priv->playlist.cur);
+ if (!ld) {
+ _ERR("failed to get list data");
+ return;
+ }
+
+ elm_genlist_item_bring_in(ld->item, ELM_GENLIST_ITEM_SCROLLTO_IN);
+ elm_genlist_realized_items_update(priv->list);
+}
+
static void _draw_thumbnail(struct _priv *priv, app_media_info *mi)
{
elm_image_file_set(priv->thumb, mi->thumbnail_path, NULL);
@@ -179,8 +201,10 @@ static void _mplayer_show(struct _priv *priv)
app_media_info *mi;
mi = _get_current_media_info(priv);
- if (!mi)
+ if (!mi) {
_ERR("failed to getting media info");
+ return;
+ }
ctl = priv->ctl;
ctl->ops->show(ctl->handle);
@@ -188,6 +212,7 @@ static void _mplayer_show(struct _priv *priv)
_draw_thumbnail(priv, mi);
_draw_music_info(priv, mi);
_draw_progressbar(priv, mi);
+ _draw_playlist(priv);
app_contents_recent_add(CONTENTS_MEDIA, mi->media_id);
}
@@ -228,6 +253,23 @@ static void _mplayer_next(struct _priv *priv)
_mplayer_show(priv);
}
+static void _mplayer_set_current(struct _priv *priv, int index)
+{
+ int total;
+
+ if (index < 0)
+ return;
+
+ total = eina_list_count(priv->playlist.list);
+
+ if (index >= total)
+ return;
+
+ priv->playlist.cur = index;
+
+ _mplayer_show(priv);
+}
+
static int _player_get_position(void *data)
{
struct _priv *priv;
@@ -351,6 +393,160 @@ static void _callback_music(void *data, const char *ev)
}
}
+static void _list_free(struct _priv *priv)
+{
+ elm_genlist_clear(priv->list);
+
+ eina_list_free(priv->item_list);
+ priv->item_list = NULL;
+}
+
+static void _list_item_del(void *data, Evas_Object *obj)
+{
+ free(data);
+}
+
+static char *_list_text_get(void *data, Evas_Object *obj, const char *part)
+{
+ struct _list_data *ld;
+ app_media *am;
+ app_media_info *mi;
+ Elm_Object_Item *item;
+ char buf[1024];
+
+ if (!data)
+ return NULL;
+
+ ld = data;
+ am = ld->am;
+ item = ld->item;
+
+ mi = app_media_get_info(am);
+ if (!mi) {
+ _ERR("failed to get media info");
+ return NULL;
+ }
+
+ if (!strcmp(part, PART_ELM_TEXT_TITLE)) {
+ snprintf(buf, sizeof(buf), "%02d. %s",
+ elm_genlist_item_index_get(item), mi->title);
+ } else if (!strcmp(part, PART_ELM_TEXT_ARTIST)) {
+ snprintf(buf, sizeof(buf), "%s / %s",
+ mi->audio->artist, mi->audio->album);
+ } else if (!strcmp(part, PART_ELM_TEXT_PLAYTIME)) {
+ util_time_string(buf, sizeof(buf), mi->audio->duration, false);
+ } else {
+ return NULL;
+ }
+
+ return strdup(buf);
+}
+
+static void _list_selected(int id, void *data,
+ Evas_Object *obj, Elm_Object_Item *it)
+{
+ struct _priv *priv;
+ int index;
+
+ if (!data || !it)
+ return;
+
+ priv = data;
+ index = elm_genlist_item_index_get(it) - 1;
+
+ if (priv->playlist.cur != index) {
+ _mplayer_set_current(priv, index);
+ _player_next(priv);
+ }
+}
+
+static void _list_realized(int id, void *data,
+ Evas_Object *obj, Elm_Object_Item *it)
+{
+ struct _priv *priv;
+ int index;
+
+ if (!data || !it)
+ return;
+
+ priv = data;
+ index = elm_genlist_item_index_get(it) - 1;
+
+ if (priv->playlist.cur == index) {
+ elm_object_item_signal_emit(it,
+ SIG_ITEM_SELECTED, SIG_SOURCE_SRC);
+ } else {
+ elm_object_item_signal_emit(it,
+ SIG_ITEM_UNSELECTED, SIG_SOURCE_SRC);
+ }
+}
+
+static void _list_mouse_move(int id, void *data, Evas *e, Evas_Object *obj,
+ Evas_Event_Mouse_Move *ev)
+{
+ Elm_Object_Item *it;
+
+ if (!data || !ev)
+ return;
+
+ it = elm_genlist_at_xy_item_get(obj, ev->cur.canvas.x,
+ ev->cur.canvas.y, NULL);
+
+ if (!it)
+ return;
+
+ if (!elm_object_item_focus_get(it))
+ elm_object_item_focus_set(it, EINA_TRUE);
+}
+
+static input_handler _list_handler = {
+ .realized = _list_realized,
+ .selected = _list_selected,
+ .mouse_move = _list_mouse_move,
+};
+
+static void _add_playlist_item(struct _priv *priv)
+{
+ Elm_Genlist_Item_Class *ic;
+ Elm_Object_Item *item;
+ app_media *am;
+ int i;
+ int total;
+
+ _list_free(priv);
+
+ ic = elm_genlist_item_class_new();
+ if (!ic) {
+ _ERR("failed to get genlist item class");
+ return;
+ }
+
+ ic->item_style = STYLE_MPLAYER_LIST;
+ ic->func.text_get = _list_text_get;
+ ic->func.content_get = NULL;
+ ic->func.state_get = NULL;
+ ic->func.del = _list_item_del;
+
+ total = eina_list_count(priv->playlist.list);
+
+ for (i = 0; i < total; i++) {
+ struct _list_data *ld;
+
+ ld = calloc(1, sizeof(*ld));
+ if (!ld)
+ continue;
+
+ am = eina_list_nth(priv->playlist.list, i);
+ ld->am = am;
+
+ item = elm_genlist_item_append(priv->list, ic, ld, NULL,
+ ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ ld->item = item;
+
+ priv->item_list = eina_list_append(priv->item_list, ld);
+ }
+}
+
static bool _ui_init(struct _priv *priv)
{
struct controller *ctl;
@@ -394,6 +590,15 @@ static bool _ui_init(struct _priv *priv)
priv->progress = prog;
+ obj = util_add_genlist(priv->base);
+ if (!obj)
+ goto err;
+
+ elm_object_part_content_set(priv->base, PART_MPLAYER_LIST, obj);
+ inputmgr_add_callback(obj, 0, &_list_handler, priv);
+
+ priv->list = obj;
+
return true;
err:
@@ -462,6 +667,7 @@ static Evas_Object *_create(Evas_Object *win, void *data)
/* FIXME */
_media_test(priv);
+ _add_playlist_item(priv);
viewmgr_set_view_data(VIEW_MPLAYER, priv);
@@ -524,6 +730,8 @@ static void _update(void *view_data, int update_type, void *data)
priv->playlist.list = vdata->list;
priv->playlist.cur = vdata->index;
+
+ _add_playlist_item(priv);
}
static void _destroy(void *view_data)
@@ -537,6 +745,10 @@ static void _destroy(void *view_data)
priv = view_data;
+ _list_free(priv);
+ inputmgr_remove_callback(priv->list, &_list_handler);
+
+ _player_stop(priv);
playermgr_destroy(priv->player);
controller_destroy(priv->ctl);