2 * Copyright (c) 2014 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.
17 #include <Elementary.h>
20 #include "AppCommon.h"
21 #include "InputHandler.h"
27 #include "song_info.h"
28 #include "album_info.h"
29 #include "music-controller.h"
30 #include "LayoutMgr.h"
32 #include "common-ui.h"
34 #include "ExtBaseLayout.h"
36 #include "song-layout.h"
37 #include "base-view.h"
46 struct SSongItemInfo {
48 Elm_Object_Item *item;
54 Evas_Object *songlist;
55 Elm_Object_Item *focused_item;
57 Eina_List *it_infolist;
58 Elm_Genlist_Item_Class *item_class;
59 CMusicController *mhandle;
62 SContentInfo *ctxtinfo;
66 memset(this, 0, sizeof(SSongLayout));
74 char *CSongLayout::sm_CbGetListItemText(void *data, Evas_Object *obj, const char *part)
76 SSongItemInfo *itinfo = (SSongItemInfo *)data;
77 CSongInfo *sinfo = NULL;
86 sinfo = itinfo->sinfo;
88 snprintf(buf, sizeof(buf), "%s", MUSIC_STR_EMPTY);
90 if (!strcmp(part, "elm.text")) {
91 index = elm_genlist_item_index_get(itinfo->item);
92 if ((index & 1) == 1) {
93 elm_object_item_signal_emit(itinfo->item,
94 MUSIC_SIGNAL_EVEN_ROW, MUSIC_BASE_VIEW);
97 elm_object_item_signal_emit(itinfo->item,
98 MUSIC_SIGNAL_ODD_ROW, MUSIC_BASE_VIEW);
100 snprintf(buf, sizeof(buf), " %s", sinfo->Name());
102 else if (!strcmp(part, "elm.text1"))
103 snprintf(buf, sizeof(buf), "%s", sinfo->Artist());
104 else if (!strcmp(part, "elm.text2"))
105 snprintf(buf, sizeof(buf), "%s", sinfo->Album());
106 else if (!strcmp(part, "elm.text3")) {
107 duration = sinfo->Duration();
108 timestr = _get_timestr_from_milseconds(duration);
110 snprintf(buf, sizeof(buf), "%s", timestr);
115 if (strcmp(buf, MUSIC_STR_EMPTY))
122 Evas_Object *CSongLayout::sm_CbGetListItemContent(void *data, Evas_Object *obj, const char *part)
124 SSongItemInfo *itinfo = (SSongItemInfo *)data;
125 CSongInfo *sinfo = NULL;
126 Evas_Object *img = NULL;
128 char buf[MAX_LENGTH];
133 sinfo = itinfo->sinfo;
135 img = elm_image_add(obj);
138 elm_image_aspect_fixed_set(img, EINA_FALSE);
140 if (!strcmp(part, "elm.swallow.icon")) {
141 path = sinfo->ThumbnailPath();
143 elm_image_file_set(img, path, "NULL");
145 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR,
146 MUSIC_IMAGE_DEFAULT_THUMB);
147 elm_image_file_set(img, buf, "NULL");
155 void CSongLayout::sm_CbRemoveListItem(void *data, Evas_Object *obj)
161 void CSongLayout::sm_CbCtxtUpdate(void *dt, enum EActionType type, int lid)
163 CSongLayout *root = (CSongLayout *)dt;
166 root->m_OnCtxtUpdate(type, lid);
170 void CSongLayout::m_OnCtxtUpdate(EActionType type, int lid)
172 Eina_List *list = NULL;
175 if (!m->ctxtinfo || !m->ctxtinfo->context)
178 if (type == ACTION_TYPE_ADDNEXT)
179 mode = ADD_TYPE_NEXT;
183 list = eina_list_append(list, m->ctxtinfo->context);
184 if (type == ACTION_TYPE_ADDTO) {
185 if (!m->mhandle->MediaAddsongsPlaylist(lid, list))
186 _ERR(" Adding songs to playlist failed ");
188 _create_message_box(m->base, MUSIC_TEXT_ADDTO_MSG);
193 m->mhandle->UpdatePlaylist(list, mode);
194 eina_list_free(list);
196 if (type == ACTION_TYPE_PLAY) {
198 m->mhandle->SetCurrentSong(((CSongInfo *)m->ctxtinfo->context)->Id());
201 _update_playback_view((EAddType)type, Layout(), m->focused_item);
205 void CSongLayout::sm_CbCtxtClose(void *dt)
207 CSongLayout *root = (CSongLayout *)dt;
210 root->m_OnCtxtClose();
214 void CSongLayout::m_OnCtxtClose(void)
217 m->vmgr->PushView(MUSIC_BASE_VIEW, NULL);
218 elm_object_item_focus_set(m->focused_item, EINA_TRUE);
222 void CSongLayout::sm_CbItemSelect(void *data, Evas_Object *obj, void *event_info)
224 CSongLayout *root = (CSongLayout*)data;
227 root->m_OnItemSelect(obj, event_info);
230 void CSongLayout::m_OnItemSelect(Evas_Object *obj, void *event_info)
232 SSongItemInfo *itinfo = NULL;
233 char *mediaId = NULL;
235 itinfo = m_FindItemInfoFromItem(m->it_infolist, (Elm_Object_Item *)event_info);
237 _ERR(" no item info found ");
241 mediaId = itinfo->sinfo->Id();
244 m->mhandle->UpdatePlaylist(m->slist, ADD_TYPE_FRESH);
245 m->mhandle->SetCurrentSong(mediaId);
251 int CSongLayout::sm_CbSortArtistAZ(const void *d1, const void *d2)
253 CSongInfo *sinfo1 = (CSongInfo *)d1;
254 CSongInfo *sinfo2 = (CSongInfo *)d2;
258 txt1 = sinfo1->Artist();
262 txt2 = sinfo2->Artist();
266 return strcasecmp(txt1, txt2);
270 int CSongLayout::sm_CbSortArtistZA(const void *d1, const void *d2)
272 CSongInfo *sinfo1 = (CSongInfo *)d1;
273 CSongInfo *sinfo2 = (CSongInfo *)d2;
277 txt1 = sinfo1->Artist();
281 txt2 = sinfo2->Artist();
285 return strcasecmp(txt2, txt1);
289 int CSongLayout::sm_CbSortAlbumAZ(const void *d1, const void *d2)
291 CSongInfo *sinfo1 = (CSongInfo *)d1;
292 CSongInfo *sinfo2 = (CSongInfo *)d2;
296 txt1 = sinfo1->Album();
300 txt2 = sinfo2->Album();
304 return strcasecmp(txt1, txt2);
308 int CSongLayout::sm_CbSortAlbumZA(const void *d1, const void *d2)
310 CSongInfo *sinfo1 = (CSongInfo *)d1;
311 CSongInfo *sinfo2 = (CSongInfo *)d2;
315 txt1 = sinfo1->Album();
319 txt2 = sinfo2->Album();
323 return strcasecmp(txt2, txt1);
327 SSongItemInfo *CSongLayout::m_FindItemInfoFromItem(Eina_List *list, Elm_Object_Item *item)
330 SSongItemInfo *itinfo = NULL;
333 EINA_LIST_FOREACH(list, l, obj) {
334 itinfo = (SSongItemInfo *)obj;
335 if (itinfo->item == item)
343 void CSongLayout::m_UpdateSongList(bool sort_flag)
349 struct SSongItemInfo *itinfo;
350 Elm_Object_Item *item;
352 /* Remove existing songlist and prepare afresh */
353 m_EmptySongList(sort_flag);
356 r = m->mhandle->MediaGetList(LIST_TYPE_SONG, NULL, &(m->slist));
357 if (r == false || eina_list_count(m->slist) == 0) {
358 _ERR(" Fetching song list from media failed ");
360 SetEmptyStatus(true);
367 EINA_LIST_FOREACH(m->slist, l, obj) {
368 sinfo = (CSongInfo *)obj;
369 itinfo = (SSongItemInfo *)calloc(1, sizeof(*itinfo));
373 itinfo->sinfo = sinfo;
374 item = elm_genlist_item_append(m->songlist, m->item_class,
375 itinfo, NULL, ELM_GENLIST_ITEM_NONE,
376 sm_CbItemSelect, this);
378 m->it_infolist = eina_list_append(m->it_infolist, itinfo);
382 void CSongLayout::m_SortSongList(void)
386 const char *sortFuncId[] = {
395 sortType = CInfo::SortType();
397 m->slist = CSort::Sort(m->slist, sortFuncId[sortType]);
400 void CSongLayout::m_EmptySongList(bool sort_flag)
403 elm_genlist_clear(m->songlist);
407 eina_list_free(m->slist);
411 eina_list_free(m->it_infolist);
412 m->it_infolist = NULL;
416 void CSongLayout::m_GotoPlayback(void)
419 parcel.ctxtInfo = NULL;
420 parcel.updateType = E_PLAYLIST_UPDATE;
421 parcel.layoutId = NULL;
422 parcel.keyEvent = NULL;
424 if (!m->vmgr->PushView(MUSIC_PLAYBACK_VIEW, &parcel))
425 _ERR(" viewmgr push view MUSIC_PLAYBACK_VIEW failed ");
429 void CSongLayout::m_GotoPlaybackUri(void)
431 Eina_List *list = NULL;
432 CSongInfo *sinfo = m->mhandle->MediaSongByUri(m->uri);
434 _ERR(" Fetching song list from uri failed ");
438 list = eina_list_append(list, sinfo);
442 m->mhandle->UpdatePlaylist(list, ADD_TYPE_FRESH);
444 eina_list_free(list);
450 void CSongLayout::m_CreateSongList(void)
452 Evas_Object *genlist = NULL;
453 Elm_Genlist_Item_Class *list_item = NULL;
455 genlist = elm_genlist_add(Layout());
459 elm_genlist_homogeneous_set(genlist, EINA_TRUE);
460 evas_object_size_hint_weight_set(genlist,
461 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
462 elm_object_part_content_set(Layout(), MUSIC_PART_SONGLIST, genlist);
463 Connect(genlist, SONG_LAYOUT_GENLIST, TYPE_MOUSE_MOVE | TYPE_KEY_DOWN | TYPE_ACTIVATED);
464 m->songlist = genlist;
466 list_item = elm_genlist_item_class_new();
468 evas_object_del(genlist);
469 _ERR(" elm_genlist_item_class_new failed ");
472 list_item->item_style = MUSIC_STYLE_SONGLIST;
473 list_item->func.text_get = sm_CbGetListItemText;
474 list_item->func.content_get = sm_CbGetListItemContent;
475 list_item->func.state_get = NULL;
476 list_item->func.del = sm_CbRemoveListItem;
477 m->item_class = list_item;
479 m_UpdateSongList(false);
483 bool CSongLayout::Create(CLayoutMgr *mgr, const char *uri)
487 Evas_Object *base = NULL;
488 Evas_Object *win = NULL;
489 Evas_Object *layout = NULL;
490 CMusicController *mhandle = NULL;
491 CViewMgr *vmgr = NULL;
498 _ERR(" calloc failed ");
502 vmgr = CViewMgr::GetInstance();
504 _ERR(" get view mgr failed ");
512 _ERR(" get base failed ");
518 win = vmgr->Window();
520 _ERR(" vimewmgr get win failed ");
526 mhandle = CMusicController::GetInstance();
528 _ERR(" music controller get music instance failed ");
534 layout = _add_base(base, MUSIC_SONG_LAYOUT);
536 _ERR(" get layout failed ");
542 bool r = CExtBaseLayout::Create(layout);
544 _ERR(" CBaseLayout creation failed ");
545 evas_object_del(layout);
551 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ARTIST_AZ, sm_CbSortArtistAZ);
552 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ARTIST_ZA, sm_CbSortArtistZA);
553 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ALBUM_AZ, sm_CbSortAlbumAZ);
554 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ALBUM_ZA, sm_CbSortAlbumZA);
557 m->uri = new char[strlen(uri) + 1];
567 m->mhandle = mhandle;
572 Connect(layout, SONG_LAYOUT, TYPE_KEY_DOWN);
575 parcel.ctxtInfo = NULL;
576 parcel.updateType = E_FOCUS_UPDATE;
577 parcel.layoutId = MUSIC_SONG_LAYOUT;
578 parcel.keyEvent = NULL;
579 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
584 void CSongLayout::Destroy(void)
588 CExtBaseLayout::Destroy();
589 evas_object_del(Layout());
598 void CSongLayout::t_OnShow(void)
602 evas_object_show(Layout());
613 void CSongLayout::Update(bool focusFlag)
618 m_UpdateSongList(true);
622 elm_object_focus_set(m->songlist, EINA_TRUE);
626 void CSongLayout::OnKeyDown(int id, Evas *e, Evas_Object *obj, Evas_Event_Key_Down *ev)
631 if (!strcmp(ev->keyname, KEY_BACK) ||
632 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
634 parcel.ctxtInfo = NULL;
635 parcel.updateType = E_FOCUS_UPDATE;
636 parcel.layoutId = NULL;
637 parcel.keyEvent = NULL;
638 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
643 case SONG_LAYOUT_GENLIST:
645 Elm_Object_Item *it = NULL;
646 SContentInfo *ctxtinfo = NULL;
647 SSongItemInfo *itinfo = NULL;
649 if (strcmp(ev->keyname, KEY_MENU) &&
650 strcmp(ev->keyname, KEY_MENU_REMOTE))
653 it = elm_object_focused_item_get(obj);
655 _ERR(" unable to get focused item ");
658 m->focused_item = it;
665 ctxtinfo = (SContentInfo *)calloc(1, sizeof(*ctxtinfo));
669 itinfo = m_FindItemInfoFromItem(m->it_infolist, it);
675 ctxtinfo->type = CONTEXT_TYPE_SONG;
676 ctxtinfo->context = itinfo->sinfo;
677 ctxtinfo->cbdata = this;
678 ctxtinfo->update = sm_CbCtxtUpdate;
679 ctxtinfo->close = sm_CbCtxtClose;
681 m->ctxtinfo = ctxtinfo;
684 parcel.ctxtInfo = ctxtinfo;
685 if (!m->vmgr->PushView(MUSIC_CONTEXT_VIEW, &parcel))
686 _ERR("viewmgr push view MUSIC_CONTEXT_VIEW failed");
696 void CSongLayout::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev)
699 case SONG_LAYOUT_GENLIST:
701 Elm_Object_Item *item;
703 item = elm_genlist_at_xy_item_get(obj, ev->cur.canvas.x,
704 ev->cur.canvas.y, NULL);
706 if (!elm_object_item_focus_get(item))
707 elm_object_item_focus_set(item, EINA_TRUE);
717 void CSongLayout::OnActivated(int id, Evas_Object *obj, Elm_Object_Item *item)
720 case SONG_LAYOUT_GENLIST:
721 m_OnItemSelect(obj, item);