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"
26 #include "folder_info.h"
27 #include "song_info.h"
28 #include "album_info.h"
30 #include <InputHandler.h>
31 #include "music-controller.h"
32 #include "LayoutMgr.h"
34 #include "common-ui.h"
36 #include "ExtBaseLayout.h"
38 #include "folder-layout.h"
39 #include "base-view.h"
41 #define TOTAL_ADD_BTNS 3
42 #define GENGRID_ITEM_SIZE_W (263+20)
43 #define GENGRID_ITEM_SIZE_H (359+20)
48 FOLDER_LAYOUT_GENGRID,
49 FOLDER_LAYOUT_PLAY_BUTTON,
50 FOLDER_LAYOUT_NEXT_BUTTON,
51 FOLDER_LAYOUT_LAST_BUTTON,
60 struct SFolderItemInfo {
63 Elm_Object_Item *item;
67 const char *g_sourceTexts[] = {
68 N_("All Source"), // SOURCE_TYPE_ALL
69 N_("TV"), // SOURCE_TYPE_TV
70 N_("USB") // SOURCE_TYPE_USB
87 struct SFolderLayout {
91 Elm_Object_Item *focused_item;
94 Eina_List *it_infolist;
95 Elm_Gengrid_Item_Class *item_class;
96 Elm_Gengrid_Item_Class *songitem_class;
97 Ecore_Idler *focus_idler;
98 CMusicController *mhandle;
101 CFolderInfo *c_finfo;
103 SContentInfo *ctxtinfo;
104 CFolderLayout *parent;
108 memset(this, 0, sizeof(SFolderLayout));
116 char *CFolderLayout::sm_CbGetGridItemText(void *data, Evas_Object *obj, const char *part)
118 SFolderItemInfo *itinfo = (SFolderItemInfo *)data;
119 CFolderInfo *finfo = NULL;
121 char buf[MAX_LENGTH];
127 finfo = itinfo->finfo;
129 if (!strcmp(part, "elm.text")) {
134 else if (!strcmp(part, "elm.text1")) {
135 count = finfo->Count();
136 snprintf(buf, sizeof(buf), "%d Songs", count);
144 char *CFolderLayout::sm_CbGetGridSongItemText(void *data, Evas_Object *obj, const char *part)
146 SFolderItemInfo *itinfo = (SFolderItemInfo *)data;
147 CSongInfo *sinfo = NULL;
153 sinfo = itinfo->sinfo;
155 if (!strcmp(part, "elm.text"))
157 else if (!strcmp(part, "elm.text1"))
158 txt = sinfo->Artist();
167 Evas_Object *CFolderLayout::sm_CbGetGridItemContent(void *data, Evas_Object *obj, const char *part)
169 Evas_Object *img = NULL;
170 char buf[MAX_LENGTH];
175 if (!strcmp(part, "elm.swallow.icon")) {
176 img = elm_image_add(obj);
180 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR,
182 elm_image_file_set(img, buf, "NULL");
183 elm_image_no_scale_set(img, EINA_TRUE);
191 Evas_Object *CFolderLayout::sm_CbGetGridSongItemContent(void *data, Evas_Object *obj, const char *part)
193 CSongInfo *sinfo = NULL;
194 SFolderItemInfo *itinfo = NULL;
196 Evas_Object *img = NULL;
197 char buf[MAX_LENGTH];
202 itinfo = (SFolderItemInfo *)data;
203 sinfo = itinfo->sinfo;
205 if (!strcmp(part, "elm.swallow.icon")) {
206 img = elm_image_add(obj);
210 path = sinfo->ThumbnailPath();
212 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR,
213 MUSIC_IMAGE_DEFAULT_THUMB_126);
214 elm_image_file_set(img, buf, NULL);
215 elm_image_no_scale_set(img, EINA_TRUE);
218 elm_image_file_set(img, path, NULL);
219 elm_image_aspect_fixed_set(img, EINA_FALSE);
227 void CFolderLayout::sm_CbRemoveGridItem(void *data, Evas_Object *obj)
233 Eina_Bool CFolderLayout::sm_CbFocusIdler(void *dt)
235 CFolderLayout *root = (CFolderLayout *)dt;
238 root->m_OnFocusIdler();
240 return ECORE_CALLBACK_CANCEL;
244 void CFolderLayout::m_OnFocusIdler(void)
246 Elm_Object_Item *it = NULL;
248 m->focus_idler = NULL;
250 if (m->depth == E_DEPTH_SONG) {
251 it = elm_gengrid_first_item_get(m->grid);
252 elm_object_item_focus_set(it, EINA_TRUE);
255 it = m_FindItemByInfo(m->it_infolist, m->c_finfo);
257 elm_gengrid_item_show(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
258 elm_object_item_focus_set(it, EINA_TRUE);
264 void CFolderLayout::sm_CbCtxtUpdate(void *dt, enum EActionType type, int lid)
266 CFolderLayout *root = (CFolderLayout *)dt;
268 root->m_OnCtxtUpdate(type, lid);
272 void CFolderLayout::m_OnCtxtUpdate(EActionType type, int lid)
274 Eina_List *list = NULL;
275 CSongInfo *sinfo = NULL;
278 if (!m->ctxtinfo || !m->ctxtinfo->context)
281 if (type == ACTION_TYPE_ADDNEXT)
282 mode = ADD_TYPE_NEXT;
286 if (m->depth == E_DEPTH_SONG) {
287 sinfo = (CSongInfo *)m->ctxtinfo->context;
288 list = eina_list_append(list, sinfo);
291 m->mhandle->MediaGetList(LIST_TYPE_FOLDER_SONG,
292 m->ctxtinfo->context, &list);
293 sinfo = (CSongInfo *)eina_list_data_get(list);
296 if (type == ACTION_TYPE_ADDTO) {
297 if (!m->mhandle->MediaAddsongsPlaylist(lid, list))
298 _ERR(" Adding songs to playlist failed ");
300 _create_message_box(m->base, MUSIC_TEXT_ADDTO_MSG);
305 m->mhandle->UpdatePlaylist(list, mode);
306 eina_list_free(list);
308 if (type == ACTION_TYPE_PLAY) {
310 m->mhandle->SetCurrentSong(sinfo->Id());
313 _update_playback_view((EAddType)type, m->parent->Layout(), m->focused_item);
316 void CFolderLayout::sm_CbCtxtClose(void *dt)
318 CFolderLayout *root = (CFolderLayout *)dt;
320 root->m_OnCtxtClose();
324 void CFolderLayout::m_OnCtxtClose(void)
327 m->vmgr->PushView(MUSIC_BASE_VIEW, NULL);
328 elm_object_item_focus_set(m->focused_item, EINA_TRUE);
332 void CFolderLayout::sm_CbItemSelect(void *data, Elm_Object_Item *it, const char *emission, const char *source)
334 CFolderLayout *root = (CFolderLayout *)data;
336 root->m_OnItemSelect(it, emission, source);
340 void CFolderLayout::m_OnItemSelect(Elm_Object_Item *it, const char *emission, const char *source)
342 SFolderItemInfo *itinfo = NULL;
348 itinfo = m_FindItemInfo(m->it_infolist, it);
350 _ERR(" no item info found ");
354 if (m->depth == E_DEPTH_SONG) {
356 m->c_sinfo = new CSongInfo;
359 if (!m->c_sinfo->FlagCreate()) {
360 m->c_sinfo->Create();
363 m->c_sinfo->Duplicate(itinfo->sinfo);
367 m->c_finfo = new CFolderInfo;
370 if (!m->c_finfo->FlagCreate()) {
371 m->c_finfo->Create();
374 m->c_finfo->Duplicate(itinfo->finfo);
377 if (m->depth == E_DEPTH_SONG) {
378 id = m->c_sinfo->Id();
379 elm_gengrid_item_selected_set(it, EINA_FALSE);
380 m_GotoPlayback(ADD_TYPE_FRESH, id);
383 m->depth = E_DEPTH_SONG;
384 m_UpdateFolderGrid(false);
385 m->focus_idler = ecore_idler_add(sm_CbFocusIdler, this);
390 SFolderItemInfo *CFolderLayout::m_FindItemInfo(Eina_List *list, Elm_Object_Item *item)
393 SFolderItemInfo *itinfo = NULL;
399 EINA_LIST_FOREACH(list, l, obj) {
400 itinfo = (SFolderItemInfo *)obj;
401 if (itinfo->item == item)
409 int CFolderLayout::m_ConvertToMin(int milsec)
412 min = milsec / 60000; /*milli seconds per minute*/
418 void CFolderLayout::m_RemoveFocusIdler(void)
423 ecore_idler_del(m->focus_idler);
424 m->focus_idler = NULL;
428 void CFolderLayout::m_GotoPlayback(int mode, char *id)
430 Eina_List *list = NULL;
432 SFolderItemInfo *itinfo = NULL;
436 if (!m->it_infolist || eina_list_count(m->it_infolist) == 0)
439 if (m->depth == E_DEPTH_SONG) {
440 EINA_LIST_FOREACH(m->it_infolist, l, obj) {
441 itinfo = (SFolderItemInfo *)obj;
442 list = eina_list_append(list, itinfo->sinfo);
446 r = m->mhandle->MediaGetList(LIST_TYPE_SONG, NULL, &list);
447 if (r == false || eina_list_count(list) == 0)
451 m->mhandle->UpdatePlaylist(list, mode);
452 eina_list_free(list);
454 if (mode == ADD_TYPE_FRESH) {
456 if (id) /* If want to play selected song */
457 m->mhandle->SetCurrentSong(id);
460 _update_playback_view((EAddType)mode, CExtBaseLayout::Layout(), NULL);
464 Elm_Object_Item *CFolderLayout::m_FindItemByInfo(Eina_List *list, CFolderInfo *finfo)
467 SFolderItemInfo *itinfo = NULL;
474 EINA_LIST_FOREACH(list, l, obj) {
475 itinfo = (SFolderItemInfo *)obj;
476 id = itinfo->finfo->Id();
477 if (!strcmp(id, finfo->Id()))
485 void CFolderLayout::m_SortFolderGrid(void)
489 const char *sortFuncId[] = {
497 sortType = m->mhandle->SortType();
498 m->flist = CSort::Sort(m->flist, sortFuncId[sortType]);
502 void CFolderLayout::m_CreateFolderGrid(void)
504 Evas_Object *grid = NULL;
505 Elm_Gengrid_Item_Class *grid_item = NULL;
507 grid = elm_gengrid_add(Layout());
510 evas_object_size_hint_weight_set(grid,
511 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
512 elm_gengrid_align_set(grid, 0, 0);
513 elm_object_part_content_set(Layout(), MUSIC_PART_FOLDER_GRID, grid);
514 Connect(grid, FOLDER_LAYOUT_GENGRID,
515 TYPE_MOUSE_MOVE | TYPE_KEY_DOWN |
516 TYPE_REALIZED | TYPE_UNREALIZED | TYPE_ACTIVATED);
517 elm_gengrid_item_size_set(grid,
518 elm_config_scale_get() * GENGRID_ITEM_SIZE_W,
519 elm_config_scale_get() * GENGRID_ITEM_SIZE_H);
522 grid_item = elm_gengrid_item_class_new();
524 evas_object_del(grid);
525 _ERR(" elm_genlist_item_class_new failed ");
528 grid_item->item_style = MUSIC_STYLE_FOLDER_GRID;
529 grid_item->func.text_get = sm_CbGetGridItemText;
530 grid_item->func.content_get = sm_CbGetGridItemContent;
531 grid_item->func.state_get = NULL;
532 grid_item->func.del = sm_CbRemoveGridItem;
533 m->item_class = grid_item;
535 grid_item = elm_gengrid_item_class_new();
537 elm_gengrid_item_class_free(m->item_class);
538 m->item_class = NULL;
539 evas_object_del(grid);
540 _ERR(" elm_genlist_item_class_new failed ");
543 grid_item->item_style = MUSIC_STYLE_FOLDER_GRID;
544 grid_item->func.text_get = sm_CbGetGridSongItemText;
545 grid_item->func.content_get = sm_CbGetGridSongItemContent;
546 grid_item->func.state_get = NULL;
547 grid_item->func.del = sm_CbRemoveGridItem;
548 m->songitem_class = grid_item;
550 m_UpdateFolderGrid(false);
554 void CFolderLayout::m_EmptyFolderGrid(bool sort_flag)
557 elm_gengrid_clear(m->grid);
560 eina_list_free(m->flist);
564 eina_list_free(m->it_infolist);
565 m->it_infolist = NULL;
569 void CFolderLayout::m_UpdateFolderGrid(bool sort_flag)
573 CFolderInfo *finfo = NULL;
574 CSongInfo *sinfo = NULL;
577 struct SFolderItemInfo *itinfo = NULL;
578 Elm_Object_Item *item = NULL;
579 char buf[MAX_LENGTH];
582 if (!m->grid || !m->item_class)
585 /* Remove existing foldergrid and prepare afresh */
586 m_EmptyFolderGrid(sort_flag);
589 if (m->depth == E_DEPTH_SONG) {
590 r = m->mhandle->MediaGetList(LIST_TYPE_FOLDER_SONG, m->c_finfo, &(m->flist));
592 eina_list_count(m->flist) == 0) {
593 _ERR(" Fetching folder list failed ");
598 r = m->mhandle->MediaGetList(LIST_TYPE_FOLDER,
601 eina_list_count(m->flist) == 0) {
602 _ERR(" Fetching folder list failed ");
603 SetEmptyStatus(true);
613 if (m->depth == E_DEPTH_SONG) {
614 EINA_LIST_FOREACH(m->flist, l, obj) {
615 sinfo = (CSongInfo *)obj;
616 itinfo = (SFolderItemInfo *)calloc(1, sizeof(*itinfo));
619 itinfo->sinfo = sinfo;
620 item = elm_gengrid_item_append(m->grid,
621 m->songitem_class, itinfo,
624 m->it_infolist = eina_list_append(m->it_infolist,
626 elm_object_part_text_set(Layout(),
627 MUSIC_PART_FOLDER_NAME,
630 dur = sinfo->Duration();
635 EINA_LIST_FOREACH(m->flist, l, obj) {
636 finfo = (CFolderInfo *)obj;
637 itinfo = (SFolderItemInfo *)calloc(1, sizeof(*itinfo));
640 itinfo->finfo = finfo;
641 item = elm_gengrid_item_append(m->grid, m->item_class,
644 m->it_infolist = eina_list_append(m->it_infolist,
646 source_type = m->mhandle->SourceType();
647 elm_object_part_text_set(Layout(),
648 MUSIC_PART_FOLDER_NAME,
649 _(g_sourceTexts[source_type]));
650 ts = ts + finfo->Count();
651 td = td + finfo->Duration();
654 snprintf(buf, sizeof(buf), "%d", ts);
655 elm_object_part_text_set(Layout(), MUSIC_PART_FOLDER_SONGCOUNT, buf);
657 snprintf(buf, sizeof(buf), "%d %s", m_ConvertToMin(td),
659 elm_object_part_text_set(Layout(), MUSIC_PART_FOLDER_TIME, buf);
663 void CFolderLayout::m_CreateTopsection(void)
667 char buf[MAX_LENGTH];
669 SBtnInfo btninfo[TOTAL_ADD_BTNS];
671 btninfo[BTN_PLAY].name = MUSIC_STR_PLAY;
672 btninfo[BTN_PLAY].part = MUSIC_PART_FOLDER_PLAYBTN;
673 btninfo[BTN_PLAY].style = MUSIC_STYLE_ADD_PLAY_BTN;
674 btninfo[BTN_PLAY].icon = MUSIC_IMAGE_ADD_PLAY;
675 btninfo[BTN_PLAY].type = FOLDER_LAYOUT_PLAY_BUTTON;
677 btninfo[BTN_NEXT].name = MUSIC_STR_ADDNEXT;
678 btninfo[BTN_NEXT].part = MUSIC_PART_FOLDER_NEXTBTN;
679 btninfo[BTN_NEXT].style = MUSIC_STYLE_ADD_NEXT_BTN;
680 btninfo[BTN_NEXT].icon = MUSIC_IMAGE_ADD_NEXT;
681 btninfo[BTN_NEXT].type = FOLDER_LAYOUT_NEXT_BUTTON;
683 btninfo[BTN_LAST].name = MUSIC_STR_ADDLAST;
684 btninfo[BTN_LAST].part = MUSIC_PART_FOLDER_LASTBTN;
685 btninfo[BTN_LAST].style = MUSIC_STYLE_ADD_LAST_BTN;
686 btninfo[BTN_LAST].icon = MUSIC_IMAGE_ADD_LAST;
687 btninfo[BTN_LAST].type = FOLDER_LAYOUT_LAST_BUTTON;
689 for (i = 0; i < TOTAL_ADD_BTNS; i++) {
690 btn = elm_button_add(Layout());
694 evas_object_size_hint_weight_set(btn,
695 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
696 elm_object_text_set(btn, _(btninfo[i].name));
697 elm_object_style_set(btn, btninfo[i].style);
699 Connect(btn, btninfo[i].type, TYPE_MOUSE_MOVE | TYPE_CLICKED);
701 img = elm_image_add(btn);
703 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR,
705 elm_image_file_set(img, buf, NULL);
706 elm_object_part_content_set(btn,
707 MUSIC_PART_ELM_SWALLOWICON, img);
710 elm_object_part_content_set(Layout(), btninfo[i].part,
716 bool CFolderLayout::Create(CLayoutMgr *mgr)
720 Evas_Object *base = NULL;
721 Evas_Object *win = NULL;
722 Evas_Object *layout = NULL;
723 CMusicController *mhandle = NULL;
724 CViewMgr *vmgr = NULL;
729 m = new SFolderLayout;
731 _ERR(" calloc failed ");
735 vmgr = CViewMgr::GetInstance();
737 _ERR(" get view mgr failed ");
745 _ERR(" get base failed ");
751 win = vmgr->Window();
753 _ERR(" vimewmgr get win failed ");
758 mhandle = CMusicController::GetInstance();
760 _ERR(" music controller get music instance failed ");
766 layout = _add_base(base, MUSIC_FOLDER_LAYOUT);
768 _ERR(" get layout failed ");
773 bool r = CExtBaseLayout::Create(layout);
775 _ERR(" CBaseLayout creation failed ");
776 evas_object_del(layout);
785 m->mhandle = mhandle;
787 m->depth = E_DEPTH_FOLDER;
790 m_CreateTopsection();
791 m_CreateFolderGrid();
793 Connect(layout, FOLDER_LAYOUT, TYPE_KEY_DOWN);
796 parcel.ctxtInfo = NULL;
797 parcel.updateType = E_LAYOUT_UPDATE;
798 parcel.layoutId = NULL;
799 parcel.keyEvent = NULL;
800 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
806 void CFolderLayout::Destroy(void)
810 m_RemoveFocusIdler();
811 m_EmptyFolderGrid(false);
812 CExtBaseLayout::Destroy();
813 evas_object_del(Layout());
816 if (m->c_sinfo && m->c_sinfo->FlagCreate())
817 m->c_sinfo->Destroy();
825 void CFolderLayout::t_OnShow(void)
828 m->depth = E_DEPTH_FOLDER;
829 m_UpdateFolderGrid(false);
830 evas_object_show(Layout());
834 void CFolderLayout::Update(bool focusFlag)
839 m_UpdateFolderGrid(true);
843 elm_object_focus_set(m->grid, EINA_TRUE);
847 void CFolderLayout::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev)
850 case FOLDER_LAYOUT_GENGRID:
852 Elm_Object_Item *item;
854 item = elm_gengrid_at_xy_item_get(obj, ev->cur.canvas.x,
855 ev->cur.canvas.y, NULL, NULL);
859 if (!elm_object_item_focus_get(item))
860 elm_object_item_focus_set(item, EINA_TRUE);
864 case FOLDER_LAYOUT_PLAY_BUTTON:
865 case FOLDER_LAYOUT_NEXT_BUTTON:
866 case FOLDER_LAYOUT_LAST_BUTTON:
868 if (!elm_object_focus_get(obj))
869 elm_object_focus_set(obj, EINA_TRUE);
879 void CFolderLayout::OnMouseClicked(int id, Evas_Object *obj)
882 case FOLDER_LAYOUT_PLAY_BUTTON:
883 m_GotoPlayback(ADD_TYPE_FRESH, NULL);
886 case FOLDER_LAYOUT_NEXT_BUTTON:
887 m_GotoPlayback(ADD_TYPE_NEXT, NULL);
890 case FOLDER_LAYOUT_LAST_BUTTON:
891 m_GotoPlayback(ADD_TYPE_END, NULL);
900 void CFolderLayout::OnRealized(int id, Evas_Object *obj, Elm_Object_Item *item)
903 case FOLDER_LAYOUT_GENGRID:
904 elm_object_item_signal_callback_add(item,
905 MUSIC_SIGNAL_BTN_CLICKED, MUSIC_BASE_VIEW,
906 sm_CbItemSelect, this);
915 void CFolderLayout::OnUnrealized(int id, Evas_Object *obj, Elm_Object_Item *item)
918 case FOLDER_LAYOUT_GENGRID:
919 elm_object_item_signal_callback_del((Elm_Object_Item *)item,
920 MUSIC_SIGNAL_BTN_CLICKED, MUSIC_BASE_VIEW,
930 void CFolderLayout::OnKeyDown(int id, Evas *e, Evas_Object *obj, Evas_Event_Key_Down *ev)
935 if (!strcmp(ev->keyname, KEY_BACK)) {
936 if (m->depth == E_DEPTH_SONG) {
937 m->depth = E_DEPTH_FOLDER;
938 m_UpdateFolderGrid(false);
939 m_RemoveFocusIdler();
940 m->focus_idler = ecore_idler_add(sm_CbFocusIdler, this);
944 parcel.ctxtInfo = NULL;
945 parcel.updateType = E_FOCUS_UPDATE;
946 parcel.layoutId = NULL;
947 parcel.keyEvent = NULL;
948 m->vmgr->UpdateView((const char *)MUSIC_BASE_VIEW, &parcel);
954 case FOLDER_LAYOUT_GENGRID:
956 Elm_Object_Item *it = NULL;
957 SContentInfo *ctxtinfo = NULL;
958 SFolderItemInfo *itinfo = NULL;
963 if (strcmp(ev->keyname, KEY_MENU))
966 it = elm_object_focused_item_get(obj);
968 _ERR(" unable to get focused item ");
971 m->focused_item = it;
978 ctxtinfo = (SContentInfo *)calloc(1, sizeof(*ctxtinfo));
982 itinfo = m_FindItemInfo(m->it_infolist, it);
988 ctxtinfo->cbdata = this;
989 ctxtinfo->update = sm_CbCtxtUpdate;
990 ctxtinfo->close = sm_CbCtxtClose;
991 if (m->depth == E_DEPTH_SONG) {
992 ctxtinfo->type = CONTEXT_TYPE_SONG;
993 ctxtinfo->context = itinfo->sinfo;
996 ctxtinfo->type = CONTEXT_TYPE_FOLDER;
997 ctxtinfo->context = itinfo->finfo;
1000 m->ctxtinfo = ctxtinfo;
1003 parcel.ctxtInfo = ctxtinfo;
1004 if (!m->vmgr->PushView(MUSIC_CONTEXT_VIEW, &parcel))
1005 _ERR("viewmgr push view MUSIC_CONTEXT_VIEW failed");
1015 void CFolderLayout::OnActivated(int id, Evas_Object *obj, Elm_Object_Item *item)
1018 case FOLDER_LAYOUT_GENGRID:
1019 m_OnItemSelect(item, NULL, NULL);