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>
22 #include "AppCommon.h"
23 #include "InputHandler.h"
28 #include "song_info.h"
29 #include "album_info.h"
30 #include "music-controller.h"
31 #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;
64 Ecore_Idler *focusIdler;
67 memset(this, 0, sizeof(SSongLayout));
75 Eina_Bool CSongLayout::sm_CbFocusIdler(void *dt)
77 CSongLayout *root = (CSongLayout *)dt;
80 root->m_OnFocusIdler();
82 return ECORE_CALLBACK_CANCEL;
86 void CSongLayout::m_OnFocusIdler(void)
90 Elm_Object_Item *item = elm_genlist_first_item_get(m->songlist);
93 elm_genlist_item_show(item, ELM_GENLIST_ITEM_SCROLLTO_IN);
94 elm_object_item_focus_set(item, EINA_TRUE);
98 char *CSongLayout::sm_CbGetListItemText(void *data, Evas_Object *obj, const char *part)
100 SSongItemInfo *itinfo = (SSongItemInfo *)data;
101 CSongInfo *sinfo = NULL;
102 char buf[MAX_LENGTH];
103 char *timestr = NULL;
110 sinfo = itinfo->sinfo;
112 snprintf(buf, sizeof(buf), "%s", MUSIC_STR_EMPTY);
114 if (!strcmp(part, "elm.text")) {
115 index = elm_genlist_item_index_get(itinfo->item);
116 if ((index & 1) == 1) {
117 elm_object_item_signal_emit(itinfo->item,
118 MUSIC_SIGNAL_EVEN_ROW, MUSIC_BASE_VIEW);
121 elm_object_item_signal_emit(itinfo->item,
122 MUSIC_SIGNAL_ODD_ROW, MUSIC_BASE_VIEW);
124 snprintf(buf, sizeof(buf), " %s", sinfo->Name());
126 else if (!strcmp(part, "elm.text1"))
127 snprintf(buf, sizeof(buf), "%s", sinfo->Artist());
128 else if (!strcmp(part, "elm.text2"))
129 snprintf(buf, sizeof(buf), "%s", sinfo->Album());
130 else if (!strcmp(part, "elm.text3")) {
131 duration = sinfo->Duration();
132 timestr = CCommonUI::TimeStrFromMilSeconds(duration);
134 snprintf(buf, sizeof(buf), "%s", timestr);
139 if (strcmp(buf, MUSIC_STR_EMPTY))
146 Evas_Object *CSongLayout::sm_CbGetListItemContent(void *data, Evas_Object *obj, const char *part)
148 SSongItemInfo *itinfo = (SSongItemInfo *)data;
149 CSongInfo *sinfo = NULL;
150 Evas_Object *img = NULL;
152 char buf[MAX_LENGTH];
157 sinfo = itinfo->sinfo;
159 img = elm_image_add(obj);
162 elm_image_aspect_fixed_set(img, EINA_FALSE);
164 if (!strcmp(part, "elm.swallow.icon")) {
165 path = sinfo->ThumbnailPath();
167 elm_image_file_set(img, path, "NULL");
169 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR,
170 MUSIC_IMAGE_DEFAULT_THUMB);
171 elm_image_file_set(img, buf, "NULL");
179 void CSongLayout::sm_CbRemoveListItem(void *data, Evas_Object *obj)
185 void CSongLayout::sm_CbCtxtUpdate(void *dt, enum EActionType type, int lid)
187 CSongLayout *root = (CSongLayout *)dt;
190 root->m_OnCtxtUpdate(type, lid);
194 void CSongLayout::m_OnCtxtUpdate(EActionType type, int lid)
196 Eina_List *list = NULL;
199 if (!m->ctxtinfo || !m->ctxtinfo->context)
202 if (type == ACTION_TYPE_ADDNEXT)
203 mode = ADD_TYPE_NEXT;
207 list = eina_list_append(list, m->ctxtinfo->context);
208 if (type == ACTION_TYPE_ADDTO) {
209 if (!m->mhandle->MediaAddsongsPlaylist(lid, list))
210 _ERR(" Adding songs to playlist failed ");
212 CCommonUI::CreateMsgBox(m->base, MUSIC_TEXT_ADDTO_MSG);
217 m->mhandle->UpdatePlaylist(list, mode);
218 eina_list_free(list);
220 if (type == ACTION_TYPE_PLAY) {
222 m->mhandle->SetCurrentSong(((CSongInfo *)m->ctxtinfo->context)->Id());
225 CCommonUI::UpdatePlaybackView((EAddType)type, Layout(), m->focused_item);
229 void CSongLayout::sm_CbCtxtClose(void *dt)
231 CSongLayout *root = (CSongLayout *)dt;
234 root->m_OnCtxtClose();
238 void CSongLayout::m_OnCtxtClose(void)
241 m->vmgr->PushView(MUSIC_BASE_VIEW, NULL);
242 elm_object_item_focus_set(m->focused_item, EINA_TRUE);
246 void CSongLayout::sm_CbItemSelect(void *data, Evas_Object *obj, void *event_info)
248 CSongLayout *root = (CSongLayout*)data;
251 root->m_OnItemSelect(obj, event_info);
254 void CSongLayout::m_OnItemSelect(Evas_Object *obj, void *event_info)
256 SSongItemInfo *itinfo = NULL;
257 char *mediaId = NULL;
259 itinfo = m_FindItemInfoFromItem(m->it_infolist, (Elm_Object_Item *)event_info);
261 _ERR(" no item info found ");
265 mediaId = itinfo->sinfo->Id();
268 m->mhandle->UpdatePlaylist(m->slist, ADD_TYPE_FRESH);
269 m->mhandle->SetCurrentSong(mediaId);
275 int CSongLayout::sm_CbSortArtistAZ(const void *d1, const void *d2)
277 CSongInfo *sinfo1 = (CSongInfo *)d1;
278 CSongInfo *sinfo2 = (CSongInfo *)d2;
282 txt1 = sinfo1->Artist();
286 txt2 = sinfo2->Artist();
290 return strcasecmp(txt1, txt2);
294 int CSongLayout::sm_CbSortArtistZA(const void *d1, const void *d2)
296 CSongInfo *sinfo1 = (CSongInfo *)d1;
297 CSongInfo *sinfo2 = (CSongInfo *)d2;
301 txt1 = sinfo1->Artist();
305 txt2 = sinfo2->Artist();
309 return strcasecmp(txt2, txt1);
313 int CSongLayout::sm_CbSortAlbumAZ(const void *d1, const void *d2)
315 CSongInfo *sinfo1 = (CSongInfo *)d1;
316 CSongInfo *sinfo2 = (CSongInfo *)d2;
320 txt1 = sinfo1->Album();
324 txt2 = sinfo2->Album();
328 return strcasecmp(txt1, txt2);
332 int CSongLayout::sm_CbSortAlbumZA(const void *d1, const void *d2)
334 CSongInfo *sinfo1 = (CSongInfo *)d1;
335 CSongInfo *sinfo2 = (CSongInfo *)d2;
339 txt1 = sinfo1->Album();
343 txt2 = sinfo2->Album();
347 return strcasecmp(txt2, txt1);
351 SSongItemInfo *CSongLayout::m_FindItemInfoFromItem(Eina_List *list, Elm_Object_Item *item)
354 SSongItemInfo *itinfo = NULL;
357 EINA_LIST_FOREACH(list, l, obj) {
358 itinfo = (SSongItemInfo *)obj;
359 if (itinfo->item == item)
367 void CSongLayout::m_UpdateSongList(bool sort_flag)
373 struct SSongItemInfo *itinfo;
374 Elm_Object_Item *item;
376 /* Remove existing songlist and prepare afresh */
377 m_EmptySongList(sort_flag);
380 r = m->mhandle->MediaGetList(LIST_TYPE_SONG, NULL, &(m->slist));
381 if (r == false || eina_list_count(m->slist) == 0) {
382 _ERR(" Fetching song list from media failed ");
384 SetEmptyStatus(true);
391 EINA_LIST_FOREACH(m->slist, l, obj) {
392 sinfo = (CSongInfo *)obj;
393 itinfo = (SSongItemInfo *)calloc(1, sizeof(*itinfo));
397 itinfo->sinfo = sinfo;
398 item = elm_genlist_item_append(m->songlist, m->item_class,
399 itinfo, NULL, ELM_GENLIST_ITEM_NONE,
400 sm_CbItemSelect, this);
402 m->it_infolist = eina_list_append(m->it_infolist, itinfo);
406 void CSongLayout::m_SortSongList(void)
410 const char *sortFuncId[] = {
419 sortType = CInfo::SortType();
421 m->slist = CSortMgr::Sort(m->slist, sortFuncId[sortType]);
424 void CSongLayout::m_EmptySongList(bool sort_flag)
427 elm_genlist_clear(m->songlist);
431 eina_list_free(m->slist);
435 eina_list_free(m->it_infolist);
436 m->it_infolist = NULL;
440 void CSongLayout::m_GotoPlayback(void)
443 memset(&parcel, 0, sizeof(SParcel));
444 parcel.updateType = E_PLAYLIST_UPDATE;
446 if (!m->vmgr->PushView(MUSIC_PLAYBACK_VIEW, &parcel))
447 _ERR(" viewmgr push view MUSIC_PLAYBACK_VIEW failed ");
451 void CSongLayout::m_GotoPlaybackUri(void)
453 Eina_List *list = NULL;
454 CSongInfo *sinfo = m->mhandle->MediaSongByUri(m->uri);
456 _ERR(" Fetching song list from uri failed ");
460 list = eina_list_append(list, sinfo);
464 m->mhandle->UpdatePlaylist(list, ADD_TYPE_FRESH);
466 eina_list_free(list);
472 void CSongLayout::m_CreateSongList(void)
474 Evas_Object *genlist = NULL;
475 Elm_Genlist_Item_Class *list_item = NULL;
477 genlist = elm_genlist_add(Layout());
481 elm_genlist_homogeneous_set(genlist, EINA_TRUE);
482 evas_object_size_hint_weight_set(genlist,
483 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
484 elm_object_part_content_set(Layout(), MUSIC_PART_SONGLIST, genlist);
485 Connect(genlist, SONG_LAYOUT_GENLIST, TYPE_MOUSE_MOVE | TYPE_KEY_DOWN | TYPE_ACTIVATED);
486 m->songlist = genlist;
488 list_item = elm_genlist_item_class_new();
490 evas_object_del(genlist);
491 _ERR(" elm_genlist_item_class_new failed ");
494 list_item->item_style = MUSIC_STYLE_SONGLIST;
495 list_item->func.text_get = sm_CbGetListItemText;
496 list_item->func.content_get = sm_CbGetListItemContent;
497 list_item->func.state_get = NULL;
498 list_item->func.del = sm_CbRemoveListItem;
499 m->item_class = list_item;
501 m_UpdateSongList(false);
505 bool CSongLayout::Create(CLayoutMgr *mgr, const char *uri)
511 Evas_Object *base = NULL;
512 Evas_Object *win = NULL;
513 Evas_Object *layout = NULL;
514 CMusicController *mhandle = NULL;
515 CViewMgr *vmgr = NULL;
517 _CHECK(m = new SSongLayout)
518 _CHECK(vmgr = CViewMgr::GetInstance())
519 _CHECK(base = mgr->Base())
520 _CHECK(win = vmgr->Window())
521 _CHECK(mhandle = CMusicController::GetInstance())
522 _CHECK(layout = CCommonUI::AddBase(base, MUSIC_SONG_LAYOUT))
523 _CHECK(CExtBaseLayout::Create(layout))
526 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ARTIST_AZ, sm_CbSortArtistAZ);
527 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ARTIST_ZA, sm_CbSortArtistZA);
528 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ALBUM_AZ, sm_CbSortAlbumAZ);
529 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ALBUM_ZA, sm_CbSortAlbumZA);
532 m->uri = new char[strlen(uri) + 1];
541 m->mhandle = mhandle;
546 Connect(layout, SONG_LAYOUT, TYPE_KEY_DOWN);
549 memset(&parcel, 0, sizeof(SParcel));
550 parcel.updateType = E_FOCUS_UPDATE;
551 parcel.layoutId = MUSIC_SONG_LAYOUT;
552 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
555 _CHECK_FAIL{ CExtBaseLayout::Destroy(); }
556 _CHECK_FAIL{ evas_object_del(layout); }
561 _CHECK_FAIL{ delete m; m = NULL; }
562 } _CREATE_END_AND_CATCH{ return false; }
567 void CSongLayout::Destroy(void)
571 Disconnect(Layout());
573 CExtBaseLayout::Destroy();
574 evas_object_del(Layout());
584 void CSongLayout::t_OnShow(void)
588 evas_object_show(Layout());
589 m_UpdateSongList(false);
600 void CSongLayout::Update(bool focusFlag)
605 m_UpdateSongList(true);
609 elm_object_focus_set(m->songlist, EINA_TRUE);
613 void CSongLayout::SetFocus(const char *btnStr)
616 m->focusIdler = ecore_idler_add(sm_CbFocusIdler, this);
620 void CSongLayout::OnKeyDown(int id, Evas *e, Evas_Object *obj, Evas_Event_Key_Down *ev)
625 if (!strcmp(ev->keyname, KEY_BACK) ||
626 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
628 memset(&parcel, 0, sizeof(SParcel));
629 parcel.updateType = E_FOCUS_UPDATE;
630 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
635 case SONG_LAYOUT_GENLIST:
637 Elm_Object_Item *it = NULL;
638 SContentInfo *ctxtinfo = NULL;
639 SSongItemInfo *itinfo = NULL;
641 if (strcmp(ev->keyname, KEY_MENU) &&
642 strcmp(ev->keyname, KEY_MENU_REMOTE))
645 it = elm_object_focused_item_get(obj);
647 _ERR(" unable to get focused item ");
650 m->focused_item = it;
657 ctxtinfo = (SContentInfo *)calloc(1, sizeof(*ctxtinfo));
661 itinfo = m_FindItemInfoFromItem(m->it_infolist, it);
667 ctxtinfo->type = CONTEXT_TYPE_SONG;
668 ctxtinfo->context = itinfo->sinfo;
669 ctxtinfo->cbdata = this;
670 ctxtinfo->update = sm_CbCtxtUpdate;
671 ctxtinfo->close = sm_CbCtxtClose;
673 m->ctxtinfo = ctxtinfo;
676 memset(&parcel, 0, sizeof(SParcel));
677 parcel.ctxtInfo = ctxtinfo;
678 if (!m->vmgr->PushView(MUSIC_CONTEXT_VIEW, &parcel))
679 _ERR("viewmgr push view MUSIC_CONTEXT_VIEW failed");
689 void CSongLayout::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev)
692 case SONG_LAYOUT_GENLIST:
694 Elm_Object_Item *item;
696 item = elm_genlist_at_xy_item_get(obj, ev->cur.canvas.x,
697 ev->cur.canvas.y, NULL);
699 if (!elm_object_item_focus_get(item))
700 elm_object_item_focus_set(item, EINA_TRUE);
710 void CSongLayout::OnActivated(int id, Evas_Object *obj, Elm_Object_Item *item)
713 case SONG_LAYOUT_GENLIST:
714 m_OnItemSelect(obj, item);