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;
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 = CCommonUI::TimeStrFromMilSeconds(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 CCommonUI::CreateMsgBox(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 CCommonUI::UpdatePlaybackView((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 elm_object_item_focus_set(m->focused_item, EINA_TRUE);
221 void CSongLayout::sm_CbItemSelect(void *data, Evas_Object *obj, void *event_info)
223 CSongLayout *root = (CSongLayout*)data;
226 root->m_OnItemSelect(obj, event_info);
229 void CSongLayout::m_OnItemSelect(Evas_Object *obj, void *event_info)
231 SSongItemInfo *itinfo = NULL;
232 char *mediaId = NULL;
234 itinfo = m_FindItemInfoFromItem(m->it_infolist, (Elm_Object_Item *)event_info);
236 _ERR(" no item info found ");
240 mediaId = itinfo->sinfo->Id();
243 m->mhandle->UpdatePlaylist(m->slist, ADD_TYPE_FRESH);
244 m->mhandle->SetCurrentSong(mediaId);
250 int CSongLayout::sm_CbSortArtistAZ(const void *d1, const void *d2)
252 CSongInfo *sinfo1 = (CSongInfo *)d1;
253 CSongInfo *sinfo2 = (CSongInfo *)d2;
257 txt1 = sinfo1->Artist();
261 txt2 = sinfo2->Artist();
265 return strcasecmp(txt1, txt2);
269 int CSongLayout::sm_CbSortArtistZA(const void *d1, const void *d2)
271 CSongInfo *sinfo1 = (CSongInfo *)d1;
272 CSongInfo *sinfo2 = (CSongInfo *)d2;
276 txt1 = sinfo1->Artist();
280 txt2 = sinfo2->Artist();
284 return strcasecmp(txt2, txt1);
288 int CSongLayout::sm_CbSortAlbumAZ(const void *d1, const void *d2)
290 CSongInfo *sinfo1 = (CSongInfo *)d1;
291 CSongInfo *sinfo2 = (CSongInfo *)d2;
295 txt1 = sinfo1->Album();
299 txt2 = sinfo2->Album();
303 return strcasecmp(txt1, txt2);
307 int CSongLayout::sm_CbSortAlbumZA(const void *d1, const void *d2)
309 CSongInfo *sinfo1 = (CSongInfo *)d1;
310 CSongInfo *sinfo2 = (CSongInfo *)d2;
314 txt1 = sinfo1->Album();
318 txt2 = sinfo2->Album();
322 return strcasecmp(txt2, txt1);
326 SSongItemInfo *CSongLayout::m_FindItemInfoFromItem(Eina_List *list, Elm_Object_Item *item)
329 SSongItemInfo *itinfo = NULL;
332 EINA_LIST_FOREACH(list, l, obj) {
333 itinfo = (SSongItemInfo *)obj;
334 if (itinfo->item == item)
342 void CSongLayout::m_UpdateSongList(bool sort_flag)
348 struct SSongItemInfo *itinfo;
349 Elm_Object_Item *item;
351 /* Remove existing songlist and prepare afresh */
352 m_EmptySongList(sort_flag);
355 r = m->mhandle->MediaGetList(LIST_TYPE_SONG, NULL, &(m->slist));
356 if (r == false || eina_list_count(m->slist) == 0) {
357 _ERR(" Fetching song list from media failed ");
359 SetEmptyStatus(true);
366 EINA_LIST_FOREACH(m->slist, l, obj) {
367 sinfo = (CSongInfo *)obj;
368 itinfo = (SSongItemInfo *)calloc(1, sizeof(*itinfo));
372 itinfo->sinfo = sinfo;
373 item = elm_genlist_item_append(m->songlist, m->item_class,
374 itinfo, NULL, ELM_GENLIST_ITEM_NONE,
375 sm_CbItemSelect, this);
377 m->it_infolist = eina_list_append(m->it_infolist, itinfo);
381 void CSongLayout::m_SortSongList(void)
385 const char *sortFuncId[] = {
394 sortType = CInfo::SortType();
396 m->slist = CSortMgr::Sort(m->slist, sortFuncId[sortType]);
399 void CSongLayout::m_EmptySongList(bool sort_flag)
402 elm_genlist_clear(m->songlist);
406 eina_list_free(m->slist);
410 eina_list_free(m->it_infolist);
411 m->it_infolist = NULL;
415 void CSongLayout::m_GotoPlayback(void)
418 memset(&parcel, 0, sizeof(SParcel));
419 parcel.updateType = E_PLAYLIST_UPDATE;
421 if (!m->vmgr->PushView(MUSIC_PLAYBACK_VIEW, &parcel))
422 _ERR(" viewmgr push view MUSIC_PLAYBACK_VIEW failed ");
426 void CSongLayout::m_GotoPlaybackUri(void)
428 Eina_List *list = NULL;
429 CSongInfo *sinfo = m->mhandle->MediaSongByUri(m->uri);
431 _ERR(" Fetching song list from uri failed ");
435 list = eina_list_append(list, sinfo);
439 m->mhandle->UpdatePlaylist(list, ADD_TYPE_FRESH);
441 eina_list_free(list);
447 void CSongLayout::m_CreateSongList(void)
449 Evas_Object *genlist = NULL;
450 Elm_Genlist_Item_Class *list_item = NULL;
452 genlist = elm_genlist_add(Layout());
456 elm_genlist_homogeneous_set(genlist, EINA_TRUE);
457 evas_object_size_hint_weight_set(genlist,
458 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
459 elm_object_part_content_set(Layout(), MUSIC_PART_SONGLIST, genlist);
460 Connect(genlist, SONG_LAYOUT_GENLIST, TYPE_MOUSE_MOVE | TYPE_KEY_DOWN | TYPE_ACTIVATED);
461 m->songlist = genlist;
463 list_item = elm_genlist_item_class_new();
465 evas_object_del(genlist);
466 _ERR(" elm_genlist_item_class_new failed ");
469 list_item->item_style = MUSIC_STYLE_SONGLIST;
470 list_item->func.text_get = sm_CbGetListItemText;
471 list_item->func.content_get = sm_CbGetListItemContent;
472 list_item->func.state_get = NULL;
473 list_item->func.del = sm_CbRemoveListItem;
474 m->item_class = list_item;
476 m_UpdateSongList(false);
480 bool CSongLayout::Create(CLayoutMgr *mgr, const char *uri)
486 Evas_Object *base = NULL;
487 Evas_Object *win = NULL;
488 Evas_Object *layout = NULL;
489 CMusicController *mhandle = NULL;
490 CViewMgr *vmgr = NULL;
492 _CHECK(m = new SSongLayout)
493 _CHECK(vmgr = CViewMgr::GetInstance())
494 _CHECK(base = mgr->Base())
495 _CHECK(win = vmgr->Window())
496 _CHECK(mhandle = CMusicController::GetInstance())
497 _CHECK(layout = CCommonUI::AddBase(base, MUSIC_SONG_LAYOUT))
498 _CHECK(CExtBaseLayout::Create(layout))
501 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ARTIST_AZ, sm_CbSortArtistAZ);
502 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ARTIST_ZA, sm_CbSortArtistZA);
503 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ALBUM_AZ, sm_CbSortAlbumAZ);
504 CSortMgr::GetInstance()->RegisterSortFunction(SORT_BY_ALBUM_ZA, sm_CbSortAlbumZA);
507 m->uri = new char[strlen(uri) + 1];
516 m->mhandle = mhandle;
521 Connect(layout, SONG_LAYOUT, TYPE_KEY_DOWN);
524 memset(&parcel, 0, sizeof(SParcel));
525 parcel.updateType = E_FOCUS_UPDATE;
526 parcel.layoutId = MUSIC_SONG_LAYOUT;
527 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
530 _CHECK_FAIL{ CExtBaseLayout::Destroy(); }
531 _CHECK_FAIL{ evas_object_del(layout); }
536 _CHECK_FAIL{ delete m; m = NULL; }
537 } _CREATE_END_AND_CATCH{ return false; }
542 void CSongLayout::Destroy(void)
546 Disconnect(Layout());
548 CExtBaseLayout::Destroy();
549 evas_object_del(Layout());
559 void CSongLayout::t_OnShow(void)
563 evas_object_show(Layout());
564 m_UpdateSongList(false);
575 void CSongLayout::Update(bool focusFlag)
580 m_UpdateSongList(true);
584 elm_object_focus_set(m->songlist, EINA_TRUE);
588 void CSongLayout::SetFocus(const char *btnStr)
592 Elm_Object_Item *item = elm_genlist_first_item_get(m->songlist);
595 elm_genlist_item_show(item, ELM_GENLIST_ITEM_SCROLLTO_IN);
596 elm_object_item_focus_set(item, EINA_TRUE);
600 void CSongLayout::OnKeyDown(int id, Evas *e, Evas_Object *obj, Evas_Event_Key_Down *ev)
605 if (!strcmp(ev->keyname, KEY_BACK) ||
606 !strcmp(ev->keyname, KEY_BACK_REMOTE)) {
608 memset(&parcel, 0, sizeof(SParcel));
609 parcel.updateType = E_FOCUS_UPDATE;
610 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
615 case SONG_LAYOUT_GENLIST:
617 Elm_Object_Item *it = NULL;
618 SContentInfo *ctxtinfo = NULL;
619 SSongItemInfo *itinfo = NULL;
621 if (strcmp(ev->keyname, KEY_MENU) &&
622 strcmp(ev->keyname, KEY_MENU_REMOTE))
625 it = elm_object_focused_item_get(obj);
627 _ERR(" unable to get focused item ");
630 m->focused_item = it;
637 ctxtinfo = (SContentInfo *)calloc(1, sizeof(*ctxtinfo));
641 itinfo = m_FindItemInfoFromItem(m->it_infolist, it);
647 ctxtinfo->type = CONTEXT_TYPE_SONG;
648 ctxtinfo->context = itinfo->sinfo;
649 ctxtinfo->cbdata = this;
650 ctxtinfo->update = sm_CbCtxtUpdate;
651 ctxtinfo->close = sm_CbCtxtClose;
653 m->ctxtinfo = ctxtinfo;
656 memset(&parcel, 0, sizeof(SParcel));
657 parcel.ctxtInfo = ctxtinfo;
658 if (!m->vmgr->PushView(MUSIC_CONTEXT_VIEW, &parcel))
659 _ERR("viewmgr push view MUSIC_CONTEXT_VIEW failed");
669 void CSongLayout::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev)
672 case SONG_LAYOUT_GENLIST:
674 Elm_Object_Item *item;
676 item = elm_genlist_at_xy_item_get(obj, ev->cur.canvas.x,
677 ev->cur.canvas.y, NULL);
679 if (!elm_object_item_focus_get(item))
680 elm_object_item_focus_set(item, EINA_TRUE);
690 void CSongLayout::OnActivated(int id, Evas_Object *obj, Elm_Object_Item *item)
693 case SONG_LAYOUT_GENLIST:
694 m_OnItemSelect(obj, item);