From ccc471584c065597dbb7e1efb297faa35235a932 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Tue, 14 Jul 2015 22:15:53 +0900 Subject: [PATCH] music player: add music player view Change-Id: I4ab9399d12ae01d2abe72b966700753c941413e6 Signed-off-by: Minkyu Kang --- CMakeLists.txt | 1 + include/define.h | 2 + include/view.h | 3 + include/view/mplayer.h | 61 +++++++ src/main.c | 2 + src/view/mplayer.c | 474 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 543 insertions(+) create mode 100644 include/view/mplayer.h create mode 100644 src/view/mplayer.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 08e5efd..49b3cad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ SET(SRCS src/main.c src/view/base.c src/view/viewer.c +src/view/mplayer.c src/layout/movie.c src/layout/gallery.c src/layout/music.c diff --git a/include/define.h b/include/define.h index dd55262..73a2d81 100644 --- a/include/define.h +++ b/include/define.h @@ -20,6 +20,7 @@ /* views */ #include "view/base.h" #include "view/viewer.h" +#include "view/mplayer.h" /* layouts */ #include "layout/movie.h" @@ -45,6 +46,7 @@ #define COLOR_ITEM_FOCUS 0 119 246 255 #define COLOR_ITEM_FOCUS_0 0 119 246 0 #define COLOR_ITEM_SELECTED 64 136 211 255 +#define COLOR_ITEM_BAR 190 190 190 255 /* part */ #define PART_ELM_TEXT_TITLE "elm.text.title" diff --git a/include/view.h b/include/view.h index 18a07bf..3fec5db 100644 --- a/include/view.h +++ b/include/view.h @@ -23,6 +23,9 @@ view_class *view_base_get_vclass(void); /* viewer */ view_class *view_viewer_get_vclass(void); +/* music player */ +view_class *view_mplayer_get_vclass(void); + /* view data */ struct view_update_data { Eina_List *list; diff --git a/include/view/mplayer.h b/include/view/mplayer.h new file mode 100644 index 0000000..660e780 --- /dev/null +++ b/include/view/mplayer.h @@ -0,0 +1,61 @@ +/* + * 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_VIEW_MPLAYER_H__ +#define __AIR_MEDIAHUB_VIEW_MPLAYER_H__ + +/* view */ +#define VIEW_MPLAYER "VIEW_MPLAYER" + +/* group */ +#define GRP_MPLAYER_VIEW "group.mplayer_view" + +/* style */ +#define STYLE_MPLAYER_PROGRESS "music_progress" + +/* part */ +#define PART_MPLAYER_BG "part.mplayer_bg" +#define PART_MPLAYER_THUMB "part.mplayer_thumb" +#define PART_MPLAYER_TITLE "part.mplayer_title" +#define PART_MPLAYER_INFO "part.mplayer_info" +#define PART_MPLAYER_PROGRESS "part.mplayer_progress" +#define PART_MPLAYER_TOTAL "part.mplayer_total" +#define PART_MPLAYER_SLIDER "part.mplayer_slider" + +/* source */ +#define SRC_BTN_MUSIC_SHUFFLE "shuffle" +#define SRC_BTN_MUSIC_REPEAT "repeat" +#define SRC_BTN_MUSIC_PREV "prev" +#define SRC_BTN_MUSIC_PLAY "play" +#define SRC_BTN_MUSIC_NEXT "next" + +/* images */ +#define IMAGE_MUSIC_PREV_FOCUS "btn_music_contr_previous_foc.png" +#define IMAGE_MUSIC_PREV_NORMAL "btn_music_contr_previous_nor.png" +#define IMAGE_MUSIC_PLAY_FOCUS "btn_music_contr_play_foc.png" +#define IMAGE_MUSIC_PLAY_NORMAL "btn_music_contr_play_nor.png" +#define IMAGE_MUSIC_PAUSE_FOCUS "btn_music_contr_pause_foc.png" +#define IMAGE_MUSIC_PAUSE_NORMAL "btn_music_contr_pause_nor.png" +#define IMAGE_MUSIC_NEXT_FOCUS "btn_music_contr_next_foc.png" +#define IMAGE_MUSIC_NEXT_NORMAL "btn_music_contr_next_nor.png" +#define IMAGE_MUSIC_SHUFFLE_FOCUS "btn_music_contr_shuffle_nor_foc.png" +#define IMAGE_MUSIC_SHUFFLE_NORMAL "btn_music_contr_shuffle_nor.png" +#define IMAGE_MUSIC_SHUFFLE_DIS_FOCUS "btn_music_contr_shuffle_dis_foc.png" +#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" + +#endif diff --git a/src/main.c b/src/main.c index d68cc2a..7140ece 100644 --- a/src/main.c +++ b/src/main.c @@ -79,6 +79,7 @@ static bool _create(void *data) viewmgr_add_view(view_base_get_vclass(), NULL); viewmgr_add_view(view_viewer_get_vclass(), NULL); + viewmgr_add_view(view_mplayer_get_vclass(), NULL); elm_win_focus_highlight_enabled_set(win, EINA_TRUE); elm_win_focus_highlight_style_set(win, STYLE_INVISIBLE); @@ -101,6 +102,7 @@ static void _terminate(void *data) viewmgr_remove_view(VIEW_BASE); viewmgr_remove_view(VIEW_VIEWER); + viewmgr_remove_view(VIEW_MPLAYER); viewmgr_destroy(); diff --git a/src/view/mplayer.c b/src/view/mplayer.c new file mode 100644 index 0000000..6a16e4b --- /dev/null +++ b/src/view/mplayer.c @@ -0,0 +1,474 @@ +/* + * 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 "view.h" +#include "util/controller.h" +#include "util/playermgr.h" +#include "util/progressbar.h" +#include "util/util.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define STYLE_MUSIC_BTN "music_btn" +#define PART_MUSIC_BTN "control_btn" +#define PLAY_BTN_LOC 2 + +struct _playlist { + Eina_List *list; + int cur; +}; + +struct _priv { + Evas_Object *win; + Evas_Object *base; + Evas_Object *thumb; + + struct _playlist playlist; + struct playermgr *player; + struct progressbar *progress; + struct controller *ctl; +}; + +struct _btn_info { + const char *name; + int loc; +}; + +static struct _btn_info btn_player[] = { + { + .name = SRC_BTN_MUSIC_PREV, + .loc = 1, + }, + { + .name = SRC_BTN_MUSIC_PLAY, + .loc = 2, + }, + { + .name = SRC_BTN_MUSIC_NEXT, + .loc = 3, + }, +}; + +/* FIXME: test function */ +static bool _media(media_info_h media_h, void *dt) +{ + struct _priv *priv; + app_media *am; + + priv = dt; + + am = app_media_create(media_h); + + priv->playlist.list = eina_list_append(priv->playlist.list, am); + + return true; +} + +static void _media_test(struct _priv *priv) +{ + filter_h filter; + char buf[1024]; + int r; + + r = media_filter_create(&filter); + if (r != MEDIA_CONTENT_ERROR_NONE) { + _ERR("Media Filter Creation Failed"); + return; + } + + snprintf(buf, sizeof(buf), "MEDIA_TYPE=3"); + + r = media_filter_set_condition(filter, buf, + MEDIA_CONTENT_COLLATE_DEFAULT); + if (r != MEDIA_CONTENT_ERROR_NONE) { + _ERR("Fail to set filter condition"); + media_filter_destroy(filter); + return; + } + + media_content_connect(); + + r = media_info_foreach_media_from_db(filter, _media, priv); + if (r != MEDIA_CONTENT_ERROR_NONE) { + _ERR("MEDIA CONTENT ERROR: %d", r); + media_filter_destroy(filter); + media_content_disconnect(); + return; + } + + media_filter_destroy(filter); + media_content_disconnect(); +} +/* FIXME: test function end */ + +static void _draw_thumbnail(struct _priv *priv, app_media_info *mi) +{ + elm_image_file_set(priv->thumb, mi->thumbnail_path, NULL); + elm_object_part_content_set(priv->base, + PART_MPLAYER_THUMB, priv->thumb); +} + +static void _draw_music_info(struct _priv *priv, app_media_info *mi) +{ + char buf[128] = {0,}; + + snprintf(buf, sizeof(buf), "%s / %s", + mi->audio->artist, mi->audio->album); + + elm_object_part_text_set(priv->base, PART_MPLAYER_TITLE, mi->title); + elm_object_part_text_set(priv->base, PART_MPLAYER_INFO, buf); +} + +static void _draw_progressbar(struct _priv *priv, app_media_info *mi) +{ + progressbar_reset(priv->progress, 0, mi->audio->duration); + progressbar_show(priv->progress); +} + +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 void _mplayer_show(struct _priv *priv) +{ + struct controller *ctl; + app_media_info *mi; + + mi = _get_current_media_info(priv); + if (!mi) + _ERR("failed to getting media info"); + + ctl = priv->ctl; + ctl->ops->show(ctl->handle); + + _draw_thumbnail(priv, mi); + _draw_music_info(priv, mi); + _draw_progressbar(priv, mi); + + app_contents_recent_add(CONTENTS_MEDIA, mi->media_id); +} + +static void _mplayer_hide(struct _priv *priv) +{ + struct controller *ctl; + + ctl = priv->ctl; + ctl->ops->hide(ctl->handle); +} + +static void _mplayer_prev(struct _priv *priv) +{ + int total; + + total = eina_list_count(priv->playlist.list); + + if (priv->playlist.cur == 0) + priv->playlist.cur = total - 1; + else + priv->playlist.cur--; + + _mplayer_show(priv); +} + +static void _mplayer_next(struct _priv *priv) +{ + int total; + + total = eina_list_count(priv->playlist.list); + + if (priv->playlist.cur == total - 1) + priv->playlist.cur = 0; + else + priv->playlist.cur++; + + _mplayer_show(priv); +} + +static int _player_get_position(void *data) +{ + struct _priv *priv; + + if (!data) + return 0; + + priv = data; + + return playermgr_get_position(priv->player); +} + +static struct progressbar_ops _progressbar_ops = { + .get_value = _player_get_position, +}; + +static void _player_complete_cb(void *data) +{ + /* TODO */ +} + +static void _callback_music(void *data, const char *ev) +{ + struct _priv *priv; + + if (!data || !ev) + return; + + priv = data; + + if (!strcmp(ev, SRC_BTN_MUSIC_PREV)) { + _mplayer_prev(priv); + } else if (!strcmp(ev, SRC_BTN_MUSIC_NEXT)) { + _mplayer_next(priv); + } else if (!strcmp(ev, SRC_BTN_MUSIC_PLAY)) { + /* TODO */ + } +} + +static bool _ui_init(struct _priv *priv) +{ + struct controller *ctl; + struct progressbar *prog; + Evas_Object *obj; + int i; + + obj = elm_image_add(priv->base); + if (!obj) { + _ERR("failed to adding image"); + return false; + } + + priv->thumb = obj; + + ctl = controller_create(priv->base); + if (!ctl) { + _ERR("failed to create controller"); + return false; + } + + for (i = 0; i < ARRAY_SIZE(btn_player); i++) { + ctl->ops->add_control(ctl->handle, + btn_player[i].name, btn_player[i].loc, + STYLE_MUSIC_BTN, PART_MUSIC_BTN); + } + + ctl->ops->add_callback(ctl->handle, _callback_music, priv); + + priv->ctl = ctl; + + prog = progressbar_create(priv->base, STYLE_MPLAYER_PROGRESS); + if (!prog) { + _ERR("failed to adding progressbar"); + goto err; + } + + progressbar_set_parts(prog, PART_MPLAYER_SLIDER, PART_MPLAYER_TOTAL, + PART_MPLAYER_PROGRESS, ""); + progressbar_set_ops(prog, &_progressbar_ops, priv); + + priv->progress = prog; + + return true; + +err: + controller_destroy(ctl); + 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"); + free(priv); + return NULL; + } + + elm_layout_file_set(base, EDJEFILE, GRP_MPLAYER_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; + + player = playermgr_create(NULL); + 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; + } + + /* FIXME */ + _media_test(priv); + + viewmgr_set_view_data(VIEW_MPLAYER, priv); + + return base; +} + +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(); + + _mplayer_show(priv); + + evas_object_show(priv->base); +} + +static void _hide(void *view_data) +{ + struct _priv *priv; + + if (!view_data) { + _ERR("failed to get view data"); + return; + } + + priv = view_data; + + _mplayer_hide(priv); + + media_content_disconnect(); + + evas_object_hide(priv->base); +} + +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; + } + + if (!data) { + _ERR("invalid parameter"); + return; + } + + priv = view_data; + vdata = data; + + priv->playlist.list = vdata->list; + priv->playlist.cur = vdata->index; +} + +static void _destroy(void *view_data) +{ + struct _priv *priv; + + if (!view_data) { + _ERR("failed to get view data"); + return; + } + + priv = view_data; + + playermgr_destroy(priv->player); + + controller_destroy(priv->ctl); + progressbar_destroy(priv->progress); + + evas_object_del(priv->base); + + free(priv); +} + +static view_class _vclass = { + .view_id = VIEW_MPLAYER, + .create = _create, + .show = _show, + .hide = _hide, + .update = _update, + .destroy = _destroy, +}; + +view_class *view_mplayer_get_vclass(void) +{ + return &_vclass; +} -- 2.7.4