c8997e1f42d7cb9f15ca7c5a420a6815c1a48b01
[profile/tv/apps/native/musicplayer.git] / src / views / playback-view.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <AppCommon.h>
18 #include "i18n.h"
19 #include "define.h"
20 #include "common.h"
21 #include "Timer.h"
22 #include "song_info.h"
23 #include "album_info.h"
24 #include "music-controller.h"
25 #include "volume-control.h"
26 #include "common-ui.h"
27 #include "playback-view.h"
28 #include "context-view.h"
29 #include "HandleVolume.h"
30 #include "PlaySettingCtxPopup.h"
31 #include "Info.h"
32 #include "SliderWidget.h"
33 #include "PlaybackController.h"
34 #include "AlbumCover.h"
35 #include "SongTitleLabel.h"
36
37
38 #define TOTAL_CONTROL_BTNS 6
39 #define TOTAL_EDIT_BTNS    3
40
41
42 enum EEvasObject {
43         EO_BASE,
44         EO_PLAYLIST,
45 };
46
47 struct SItemInfo {
48         Elm_Object_Item *item;
49         CSongInfo *sinfo;
50         bool edit_mode;
51         bool check_status;
52         bool select_status;
53 };
54
55 struct SPlaybackView {
56         Evas_Object *eoWin;
57
58         Evas_Object *eoBase;
59         Evas_Object *eoPlaylist;
60
61         Elm_Object_Item *focused_item;
62
63         CPlaybackController *pPlaybackController;
64         // These are reference values.
65         Evas_Object *eoBtnControl[TOTAL_CONTROL_BTNS];
66         Evas_Object *eoBtnEdit[TOTAL_EDIT_BTNS];
67
68         CAlbumCover *pAlbumCover;
69         CSliderWidget *pSliderWidget;
70         CSongTitleLabel *pSongTitleLabel;
71
72         Eina_List *elInfo;
73         CMusicController *pController; //! NOT NULL
74         CSongInfo *csinfo;
75         CViewMgr *mgr;
76         SItemInfo *cs_itinfo;
77         SContentInfo *ctxtinfo;
78
79         CHandleVolume *pHandleVolume;
80
81         int numCheckedItem;
82
83         SPlaybackView() {
84                 memset(this, 0, sizeof(SPlaybackView));
85         }
86 };
87
88
89 void CPlaybackView::sm_CbCtxtUpdate(void *dt, enum EActionType type, int lid)
90 {
91         CPlaybackView *root = (CPlaybackView *)dt;
92         if (root)
93                 root->m_OnCtxtUpdate(type, lid);
94 }
95
96
97 void CPlaybackView::m_OnCtxtUpdate(EActionType type, int lid)
98 {
99         SItemInfo *itinfo = NULL;
100         Elm_Object_Item *focusedItem = NULL;
101
102         if (!m->ctxtinfo || !m->ctxtinfo->context)
103                 return;
104
105         itinfo = m_FindItemInfoFromSong(m->elInfo,
106                 (CSongInfo *)m->ctxtinfo->context);
107         if (!itinfo) {
108                 _ERR(" Unable to find song in the list ");
109                 return;
110         }
111
112         if (type == ACTION_TYPE_DELETE) {
113                 itinfo->check_status = true;
114                 m_DeleteSelectedItems();
115
116                 if (!m->mgr->PopView()) {
117                         _ERR("CViewMgr::PopView failed");
118                         return;
119                 }
120
121                 SParcel parcel;
122                 memset(&parcel, 0, sizeof(SParcel));
123                 parcel.updateType = E_PLAYLIST_UPDATE;
124                 t_OnUpdate(&parcel);
125
126                 focusedItem = m->cs_itinfo->item;
127         }
128         else { // ACTION_TYPE_PLAY
129                 if (m->ctxtinfo->status == PLAY_STATUS_PLAY)
130                         m_KeyPausePress();
131                 else {
132                         if (itinfo == m->cs_itinfo)
133                                 m_KeyPlayPress();
134                         else
135                                 m_HandleGenlistItemActivated(m->eoPlaylist, itinfo->item);
136                 }
137
138                 if (!m->mgr->PopView()) {
139                         _ERR("CViewMgr::PopView failed");
140                         return;
141                 }
142
143                 focusedItem = m->focused_item;
144         }
145
146         if (!CViewMgr::GetInstance()->HideView(MUSIC_BASE_VIEW))
147                 _ERR("CViewMgr::HideView failed");
148
149         t_OnShow();
150
151         if (focusedItem) {
152                 elm_genlist_item_show(focusedItem, ELM_GENLIST_ITEM_SCROLLTO_IN);
153                 elm_object_item_focus_set(focusedItem, EINA_TRUE);
154         }
155 }
156
157
158 void CPlaybackView::sm_CbCtxtClose(void *dt)
159 {
160         CPlaybackView *root = (CPlaybackView *)dt;
161         if (root)
162                 root->m_OnCtxtClose();
163 }
164
165
166 void CPlaybackView::m_OnCtxtClose(void)
167 {
168         if (!m->mgr->PopView()) {
169                 _ERR("CViewMgr::PopView failed");
170                 return;
171         }
172
173         elm_object_item_focus_set(m->focused_item, EINA_TRUE);
174 }
175
176
177 int CPlaybackView::sm_CbCurrentSongCount(void *cookie)
178 {
179         CPlaybackView *root = (CPlaybackView *)cookie;
180         int ret = 0;
181         if (root)
182                 ret = root->m_CbCurrentSongCount();
183
184         return ret;
185 }
186
187
188 int CPlaybackView::m_CbCurrentSongCount(void)
189 {
190         return eina_list_count(m->elInfo);
191 }
192
193
194 void CPlaybackView::m_ChangeEditmodeAll(Eina_List *list, bool flag)
195 {
196         SItemInfo *itinfo = NULL;
197         void *obj = NULL;
198         Eina_List *l = NULL;
199
200         EINA_LIST_FOREACH(list, l, obj) {
201                 itinfo = (SItemInfo *)obj;
202                 itinfo->edit_mode = flag;
203         }
204 }
205
206
207 void CPlaybackView::m_DisableCheckAll(Eina_List *list)
208 {
209         SItemInfo *itinfo = NULL;
210         void *obj = NULL;
211         Eina_List *l = NULL;
212
213         EINA_LIST_FOREACH(list, l, obj) {
214                 itinfo = (SItemInfo *)obj;
215                 itinfo->check_status = false;
216         }
217
218         m->numCheckedItem = 0;
219 }
220
221
222 void CPlaybackView::m_SelectItem(SItemInfo *pItemInfo)
223 {
224         if (!pItemInfo || !pItemInfo->item)
225                 return;
226
227         elm_genlist_item_bring_in(pItemInfo->item, ELM_GENLIST_ITEM_SCROLLTO_IN);
228         elm_object_item_signal_emit(pItemInfo->item, MUSIC_SIGNAL_SELECT_ITEM, MUSIC_PLAYBACK_VIEW);
229
230         pItemInfo->select_status = true;
231 }
232
233
234 void CPlaybackView::m_UnselectItem(SItemInfo *pItemInfo)
235 {
236         if (!pItemInfo || !pItemInfo->item)
237                 return;
238
239         elm_object_item_signal_emit(pItemInfo->item, MUSIC_SIGNAL_UNSELECT_ITEM,
240                 MUSIC_PLAYBACK_VIEW);
241
242         pItemInfo->select_status = false;
243 }
244
245
246 void CPlaybackView::m_UpdateEmptySongInfo(void)
247 {
248         m->pController->SetPlayState(PLAY_STATUS_INITIAL);
249 }
250
251
252 void CPlaybackView::m_UpdateCtxtView(int playStatus)
253 {
254         if (!m->cs_itinfo || !m->ctxtinfo)
255                 return;
256
257         if (!m->mgr->CheckTop(MUSIC_CONTEXT_VIEW))
258                 return;
259
260         if (m->cs_itinfo->sinfo == m->ctxtinfo->context) {
261                 m->ctxtinfo->status = (EPlayStatus)playStatus;
262
263                 SParcel parcel;
264                 memset(&parcel, 0, sizeof(SParcel));
265                 parcel.updateType = E_SONG_UPDATE;
266                 m->mgr->UpdateView((const char *)MUSIC_CONTEXT_VIEW, &parcel);
267         }
268 }
269
270
271 void CPlaybackView::m_UpdateCurrentSongItem(int index)
272 {
273         SItemInfo *pItemInfo = NULL;
274
275         if (m->cs_itinfo) {
276                 m_UnselectItem(m->cs_itinfo);
277                 m_UpdateCtxtView(PLAY_STATUS_PAUSE);
278         }
279
280         pItemInfo = (SItemInfo *)eina_list_nth(m->elInfo, index);
281
282         if (pItemInfo) {
283                 m->cs_itinfo = pItemInfo;
284                 if (m->pController->PlayState() == PLAY_STATUS_STOP) {
285                         elm_genlist_item_bring_in(pItemInfo->item,
286                                 ELM_GENLIST_ITEM_SCROLLTO_IN);
287                 }
288                 else {
289                         m_SelectItem(pItemInfo);
290                         m_UpdateCtxtView(PLAY_STATUS_PLAY);
291                 }
292         }
293 }
294
295
296 void CPlaybackView::m_UpdateEditmodeFocusSequence(void)
297 {
298         elm_object_focus_next_object_set(m->eoPlaylist, m->eoBtnEdit[EDIT_BTN_CANCEL], ELM_FOCUS_LEFT);
299         elm_object_focus_next_object_set(m->eoBtnEdit[EDIT_BTN_CANCEL], m->eoPlaylist, ELM_FOCUS_RIGHT);
300         elm_object_focus_next_object_set(m->pSliderWidget->Base(), m->eoBtnEdit[EDIT_BTN_CANCEL], ELM_FOCUS_DOWN);
301 }
302
303
304 void CPlaybackView::m_UpdatePlaymodeFocusSequence(void)
305 {
306         switch (m->pController->PlayState()) {
307         case PLAY_STATUS_INITIAL:
308                 // Do nothing
309                 break;
310
311         case PLAY_STATUS_STOP:
312                 elm_object_focus_next_object_set(m->eoPlaylist, m->eoBtnControl[CTRL_BTN_PLAY], ELM_FOCUS_LEFT);
313                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_PLAY], m->eoPlaylist, ELM_FOCUS_RIGHT);
314                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_PLAY], m->eoBtnControl[CTRL_BTN_REPEAT], ELM_FOCUS_LEFT);
315                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_REPEAT], m->eoBtnControl[CTRL_BTN_PLAY], ELM_FOCUS_RIGHT);
316                 elm_object_signal_emit(m->eoBtnControl[CTRL_BTN_PLAY], MUSIC_SIGNAL_PAUSE, MUSIC_PLAYBACK_VIEW);
317                 break;
318
319         case PLAY_STATUS_PLAY:
320         case PLAY_STATUS_PAUSE:
321                 elm_object_focus_next_object_set(m->eoPlaylist,
322                         m->eoBtnControl[CTRL_BTN_FORWARD], ELM_FOCUS_LEFT);
323                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_FORWARD],
324                         m->eoPlaylist, ELM_FOCUS_RIGHT);
325                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_PLAY],
326                         m->eoBtnControl[CTRL_BTN_FORWARD], ELM_FOCUS_RIGHT);
327                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_PLAY],
328                         m->eoBtnControl[CTRL_BTN_REWIND], ELM_FOCUS_LEFT);
329                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_REPEAT],
330                         m->eoBtnControl[CTRL_BTN_REWIND], ELM_FOCUS_RIGHT);
331                 break;
332
333         default:
334                 ASSERT(!"Invalid State");
335                 break;
336         }
337 }
338
339
340 void CPlaybackView::m_UpdateCurrentSongInfo(void)
341 {
342         CSongInfo *sinfo = NULL;
343         int index;
344
345         if (eina_list_count(m->elInfo) == 0) {
346                 m->pController->EmptyPlaylist();
347                 return;
348         }
349
350         if (!m->pController->GetCurrentSongIndex(&index)) {
351                 _ERR(" music get current song index failed ");
352                 return;
353         }
354
355         if (!m->pController->GetSonginfoFromIndex(index, &sinfo)) {
356                 _ERR(" music get songinfo failed ");
357                 return;
358         }
359         m->csinfo = sinfo;
360
361         m_UpdateCurrentSongItem(index);
362         m->pController->UpdatePlayerUI();
363         m_UpdatePlaymodeFocusSequence();
364 }
365
366
367 void CPlaybackView::m_DisableEditButtons(bool flag)
368 {
369         /* flag - 1 means disable edit buttons and 0 means enable */
370         if (flag)
371                 elm_object_focus_set(m->eoBtnEdit[EDIT_BTN_CANCEL], EINA_TRUE);
372
373         elm_object_disabled_set(m->eoBtnEdit[EDIT_BTN_DELETE], (Eina_Bool)flag);
374         elm_object_disabled_set(m->eoBtnEdit[EDIT_BTN_DESELECT], (Eina_Bool)flag);
375         if (flag) {
376                 m_UpdateEditmodeFocusSequence();
377                 elm_object_focus_set(m->eoBtnEdit[EDIT_BTN_CANCEL], EINA_TRUE);
378         }
379         else {
380                 elm_object_focus_next_object_set(m->eoBtnEdit[EDIT_BTN_CANCEL], m->eoBtnEdit[EDIT_BTN_DESELECT], ELM_FOCUS_RIGHT);
381                 elm_object_focus_next_object_set(m->eoBtnEdit[EDIT_BTN_DELETE], m->eoPlaylist, ELM_FOCUS_RIGHT);
382                 elm_object_focus_next_object_set(m->eoPlaylist, m->eoBtnEdit[EDIT_BTN_DELETE], ELM_FOCUS_LEFT);
383         }
384 }
385
386
387 void CPlaybackView::m_FromEditToPlaybackMode(void)
388 {
389         if (m->pController->PlayState() == PLAY_STATUS_STOP) {
390                 elm_genlist_item_bring_in(m->cs_itinfo->item,
391                         ELM_GENLIST_ITEM_SCROLLTO_IN);
392         }
393         else
394                 m_SelectItem(m->cs_itinfo);
395
396         elm_object_signal_emit(m->eoBase, MUSIC_SIGNAL_PLAYBACK_MODE,
397                 MUSIC_PLAYBACK_VIEW);
398         elm_object_focus_set(m->eoBtnControl[CTRL_BTN_SETTINGS], EINA_TRUE);
399
400         m_ChangeEditmodeAll(m->elInfo, false);
401
402         elm_genlist_realized_items_update(m->eoPlaylist);
403
404         m_UpdatePlaymodeFocusSequence();
405 }
406
407
408 void CPlaybackView::m_FromPlaybackToEditMode(void)
409 {
410         elm_object_signal_emit(m->eoBase, MUSIC_SIGNAL_EDIT_MODE,
411                 MUSIC_PLAYBACK_VIEW);
412
413         m_DisableEditButtons(true);
414
415         elm_object_focus_set(m->eoBtnEdit[EDIT_BTN_CANCEL], EINA_TRUE);
416
417         m_ChangeEditmodeAll(m->elInfo, true);
418
419         elm_genlist_realized_items_update(m->eoPlaylist);
420
421         m_UpdateEditmodeFocusSequence();
422 }
423
424
425 void CPlaybackView::m_DeleteSelectedItems(void)
426 {
427         Eina_List *l = NULL, *l_next = NULL;
428         SItemInfo *pItemInfo = NULL;
429         void *obj = NULL;
430         bool updateFlag = false;
431         int index;
432
433         m_DisableEditButtons(true);
434         m->numCheckedItem = 0;
435         EINA_LIST_FOREACH_SAFE(m->elInfo, l, l_next, obj) {
436                 pItemInfo = (SItemInfo *)obj;
437                 if (pItemInfo->check_status) {
438                         if (m->cs_itinfo == pItemInfo) {
439                                 updateFlag = true;
440                                 m_UnselectItem(m->cs_itinfo);
441                                 m->cs_itinfo = NULL;
442                                 m->pController->SetPlayState(PLAY_STATUS_STOP);
443                                 m->pController->Stop();
444                         }
445                         index = elm_genlist_item_index_get(pItemInfo->item);
446                         m->pController->RemoveSong(pItemInfo->sinfo, index);
447
448                         m->elInfo = eina_list_remove(m->elInfo, pItemInfo);
449                         elm_object_item_del(pItemInfo->item);
450                 }
451         }
452
453         if (eina_list_count(m->elInfo) == 0) {
454                 m->pController->EmptyPlaylist();
455                 elm_genlist_realized_items_update(m->eoPlaylist);
456                 elm_object_focus_set(m->eoBtnEdit[EDIT_BTN_CANCEL], EINA_TRUE);
457                 return;
458         }
459
460         if (updateFlag)
461                 m_UpdateCurrentSongInfo();
462
463         elm_genlist_realized_items_update(m->eoPlaylist);
464         elm_object_focus_set(m->eoBtnEdit[EDIT_BTN_CANCEL], EINA_TRUE);
465 }
466
467
468 void CPlaybackView::m_KeyBackPress(void)
469 {
470         t_OnHide();
471
472         if (!CViewMgr::GetInstance()->ShowView(MUSIC_BASE_VIEW))
473                 _ERR("CViewMgr::ShowView failed");
474
475         if (CViewMgr::GetInstance()->CheckTop(MUSIC_CONTEXT_VIEW)) {
476                 if (!CViewMgr::GetInstance()->UpdateView(MUSIC_CONTEXT_VIEW, NULL))
477                         _ERR("CViewMgr::UpdateView failed");
478
479                 if (!CViewMgr::GetInstance()->ShowView(MUSIC_CONTEXT_VIEW))
480                         _ERR("CViewMgr::ShowView failed");
481         }
482 }
483
484
485 void CPlaybackView::m_KeyExitPress(void)
486 {
487         m->pController->Stop();
488         elm_exit();
489 }
490
491
492 void CPlaybackView::m_KeyPlayPress(void)
493 {
494         int state;
495
496         if (elm_object_disabled_get(m->eoBtnControl[CTRL_BTN_PLAY]))
497                 return;
498
499         state = m->pController->PlayState();
500         if (state == PLAY_STATUS_PAUSE) {
501                 m->pController->Resume();
502                 elm_object_signal_emit(m->eoBtnControl[CTRL_BTN_PLAY],
503                         MUSIC_SIGNAL_PLAY, MUSIC_PLAYBACK_VIEW);
504         }
505         else if (state != PLAY_STATUS_PLAY) {
506                 m->pController->Start();
507         }
508 }
509
510
511 void CPlaybackView::m_KeyPausePress(void)
512 {
513         int state;
514
515         if (elm_object_disabled_get(m->eoBtnControl[CTRL_BTN_PLAY]))
516                 return;
517
518         state = m->pController->PlayState();
519         if (state == PLAY_STATUS_PLAY) {
520                 elm_object_signal_emit(m->eoBtnControl[CTRL_BTN_PLAY],
521                         MUSIC_SIGNAL_PAUSE, MUSIC_PLAYBACK_VIEW);
522                 m->pController->Pause();
523         }
524 }
525
526
527 void CPlaybackView::m_KeyNextPress(void)
528 {
529         if (elm_object_disabled_get(m->eoBtnControl[CTRL_BTN_FORWARD]))
530                 return;
531
532         m->pController->HandleRemoteButtons(m->eoBtnControl[CTRL_BTN_FORWARD], EVENT_PRESSED);
533 }
534
535
536 void CPlaybackView::m_KeyPreviousPress(void)
537 {
538         if (elm_object_disabled_get(m->eoBtnControl[CTRL_BTN_REWIND]))
539                 return;
540
541         m->pController->HandleRemoteButtons(m->eoBtnControl[CTRL_BTN_REWIND], EVENT_PRESSED);
542 }
543
544
545 void CPlaybackView::m_KeyNextUnpress(void)
546 {
547         if (elm_object_disabled_get(m->eoBtnControl[CTRL_BTN_FORWARD]))
548                 return;
549
550         m->pController->HandleRemoteButtons(m->eoBtnControl[CTRL_BTN_FORWARD], EVENT_UNPRESSED);
551 }
552
553
554 void CPlaybackView::m_KeyPreviousUnpress(void)
555 {
556         if (elm_object_disabled_get(m->eoBtnControl[CTRL_BTN_REWIND]))
557                 return;
558
559         m->pController->HandleRemoteButtons(m->eoBtnControl[CTRL_BTN_REWIND], EVENT_UNPRESSED);
560 }
561
562
563 void CPlaybackView::m_HandleKeyPress(ESKey skey)
564 {
565         switch (skey) {
566         case SKEY_EXIT:
567                 m_KeyExitPress();
568                 break;
569
570         case SKEY_BACK:
571                 m_KeyBackPress();
572                 break;
573
574         case SKEY_PLAY:
575                 m_KeyPlayPress();
576                 break;
577
578         case SKEY_PAUSE:
579                 m_KeyPausePress();
580                 break;
581
582         case SKEY_NEXT:
583                 m_KeyNextPress();
584                 break;
585
586         case SKEY_PREVIOUS:
587                 m_KeyPreviousPress();
588                 break;
589
590         case SKEY_VOLUME_UP:
591                 m->pHandleVolume->Up();
592                 break;
593
594         case SKEY_VOLUME_DOWN:
595                 m->pHandleVolume->Down();
596                 break;
597
598         case SKEY_MUTE:
599                 m->pHandleVolume->Mute();
600                 break;
601
602         default:
603                 break;
604         }
605 }
606
607
608 void CPlaybackView::m_HandleKeyUnpress(ESKey skey)
609 {
610         switch (skey) {
611         case SKEY_PREVIOUS:
612                 m_KeyPreviousUnpress();
613                 break;
614
615         case SKEY_NEXT:
616                 m_KeyNextUnpress();
617                 break;
618
619         default:
620                 break;
621         }
622 }
623
624
625 void CPlaybackView::m_AddCurrentSonginfo(void)
626 {
627         m->pSongTitleLabel = new CSongTitleLabel;
628         m->pSongTitleLabel->Create(m->eoBase);
629
630         m->pAlbumCover = new CAlbumCover;
631         m->pAlbumCover->Create(m->eoBase);
632         
633         m->pSliderWidget = new CSliderWidget;
634         m->pSliderWidget->Create(m->eoBase);
635 }
636
637
638 SItemInfo *CPlaybackView::m_FindItemInfoFromSong(Eina_List *list, CSongInfo *sinfo)
639 {
640         Eina_List *l = NULL;
641         SItemInfo *itinfo = NULL;
642         void *obj = NULL;
643
644         EINA_LIST_FOREACH(list, l, obj) {
645                 itinfo = (SItemInfo *)obj;
646                 if (itinfo->sinfo == sinfo)
647                         return itinfo;
648         }
649
650         return NULL;
651 }
652
653
654 SItemInfo *CPlaybackView::m_FindItemInfoFromItem(Eina_List *list, Elm_Object_Item *item)
655 {
656         Eina_List *l = NULL;
657         SItemInfo *itinfo = NULL;
658         void *obj = NULL;
659
660         EINA_LIST_FOREACH(list, l, obj) {
661                 itinfo = (SItemInfo *)obj;
662                 if (itinfo->item == item)
663                         return itinfo;
664         }
665
666         return NULL;
667 }
668
669
670 void CPlaybackView::m_UpdateItemCheck(SItemInfo *itinfo)
671 {
672         if (!itinfo) {
673                 _ERR(" No item info to Update check ");
674                 return;
675         }
676
677         if (itinfo->check_status) {
678                 elm_object_item_signal_emit(itinfo->item,
679                         MUSIC_SIGNAL_CHECK_OFF, MUSIC_PLAYBACK_VIEW);
680                 itinfo->check_status = false;
681                 m->numCheckedItem--;
682         }
683         else {
684                 elm_object_item_signal_emit(itinfo->item,
685                         MUSIC_SIGNAL_CHECK_ON, MUSIC_PLAYBACK_VIEW);
686                 itinfo->check_status = true;
687                 m->numCheckedItem++;
688         }
689 }
690
691
692 class CElmGenlistItemClass {
693 public:
694         static char *sm_CbTextGet(void *data, Evas_Object *obj, const char *part)
695         {
696                 CSongInfo *sinfo = NULL;
697                 SItemInfo *pItemInfo = (SItemInfo *)data;
698                 char buf[MAX_LENGTH];
699                 char *timestr = NULL;
700                 int duration;
701                 int index;
702
703                 if (!pItemInfo || !obj)
704                         return NULL;
705
706                 sinfo = pItemInfo->sinfo;
707
708                 snprintf(buf, sizeof(buf), "%s", MUSIC_STR_EMPTY);
709
710                 if (!strcmp(part, "elm.text0")) {
711                         index = elm_genlist_item_index_get(pItemInfo->item);
712                         snprintf(buf, sizeof(buf), "%d", index);
713                 }
714                 else if (!strcmp(part, "elm.text1"))
715                         snprintf(buf, sizeof(buf), "%s", sinfo->Name());
716                 else if (!strcmp(part, "elm.text2"))
717                         snprintf(buf, sizeof(buf), "%s - %s",
718                         sinfo->Artist(),
719                         sinfo->Album());
720                 else if (!strcmp(part, "elm.text3")) {
721                         duration = sinfo->Duration();
722                         timestr = CCommonUI::TimeStrFromMilSeconds(duration);
723                         if (timestr) {
724                                 snprintf(buf, sizeof(buf), "%s", timestr);
725                                 free(timestr);
726                         }
727                 }
728
729                 if (strcmp(buf, MUSIC_STR_EMPTY))
730                         return strdup(buf);
731
732                 return NULL;
733         }
734         static Evas_Object *sm_CbContentGet(void *data, Evas_Object *obj, const char *part)
735         {
736                 CSongInfo *sinfo = NULL;
737                 SItemInfo *pItemInfo = (SItemInfo *)data;
738                 Evas_Object *img = NULL;
739                 char *path = NULL;
740                 char buf[MAX_LENGTH];
741
742                 if (!pItemInfo || !obj)
743                         return NULL;
744
745                 sinfo = pItemInfo->sinfo;
746
747                 img = elm_image_add(obj);
748                 if (!img)
749                         return NULL;
750
751                 elm_image_aspect_fixed_set(img, EINA_FALSE);
752
753                 if (!strcmp(part, "elm.swallow.icon")) {
754                         path = sinfo->ThumbnailPath();
755                         if (path)
756                                 elm_image_file_set(img, path, "NULL");
757                         else {
758                                 snprintf(buf, sizeof(buf), "%s/%s", IMAGEDIR,
759                                         MUSIC_IMAGE_DEFAULT_THUMB_126);
760                                 elm_image_file_set(img, buf, "NULL");
761                         }
762                 }
763
764                 return img;
765
766         }
767         static void         sm_CbDel(void *data, Evas_Object *obj)
768         {
769                 free(data);
770         }
771 };
772
773
774 Elm_Genlist_Item_Class *CPlaybackView::m_GetItemClass(void)
775 {
776         Elm_Genlist_Item_Class *list_item = NULL;
777
778         list_item = elm_genlist_item_class_new();
779         if (!list_item) {
780                 _ERR(" elm_genlist_item_class_new failed ");
781                 return NULL;
782         }
783
784         list_item->item_style       = MUSIC_STYLE_PLAYLIST;
785         list_item->func.text_get    = CElmGenlistItemClass::sm_CbTextGet;
786         list_item->func.content_get = CElmGenlistItemClass::sm_CbContentGet;
787         list_item->func.state_get   = NULL;
788         list_item->func.del         = CElmGenlistItemClass::sm_CbDel;
789
790         return list_item;
791 }
792
793
794 void CPlaybackView::m_AddGenlist(void)
795 {
796         Evas_Object *genlist = NULL;
797         Evas_Object *eoBase = NULL;
798
799         eoBase = m->eoBase;
800         genlist = elm_genlist_add(eoBase);
801         if (!genlist)
802                 return;
803
804         elm_genlist_homogeneous_set(genlist, EINA_TRUE);
805         evas_object_size_hint_weight_set(genlist,
806                 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
807         elm_object_part_content_set(eoBase, MUSIC_PART_PLAYLIST, genlist);
808         elm_genlist_select_mode_set(genlist, ELM_OBJECT_SELECT_MODE_ALWAYS);
809         elm_genlist_multi_select_set(genlist, EINA_FALSE);
810
811         Connect(genlist, EO_PLAYLIST, TYPE_REALIZED | TYPE_MOUSE_MOVE |
812                 TYPE_KEY_DOWN | TYPE_ACTIVATED);
813
814         evas_object_show(genlist);
815         m->eoPlaylist = genlist;
816 }
817
818
819 void CPlaybackView::m_AddPlaylist(void)
820 {
821         Elm_Genlist_Item_Class *list_item = NULL;
822         int ts = 0;
823         int i, index = -1;
824         CSongInfo *sinfo = NULL;
825         Elm_Object_Item *item = NULL;
826         SItemInfo *pItemInfo = NULL;
827
828         m_AddGenlist();
829         if (!m->eoPlaylist)
830                 return;
831
832         list_item = m_GetItemClass();
833         if (!list_item) {
834                 evas_object_del(m->eoPlaylist);
835                 return;
836         }
837
838         if (!m->pController->GetTotalSongs(&ts)) {
839                 _ERR(" music get total songs failed ");
840                 return;
841         }
842
843         if (!m->pController->GetCurrentSongIndex(&index))
844                 _ERR(" music get current song index failed ");
845
846         for (i = 0; i < ts; i++) {
847                 if (!m->pController->GetSonginfoFromIndex(i, &sinfo)) {
848                         _ERR(" music get songinfo failed ");
849                         continue;
850                 }
851                 pItemInfo = (SItemInfo *)calloc(1, sizeof(*pItemInfo));
852                 if (!pItemInfo)
853                         return;
854                 pItemInfo->sinfo = sinfo;
855                 pItemInfo->edit_mode = false;
856                 pItemInfo->check_status = false;
857                 pItemInfo->select_status = false;
858
859                 // event handling will be done in OnActivated function
860                 item = elm_genlist_item_append(m->eoPlaylist, list_item,
861                         pItemInfo, NULL, ELM_GENLIST_ITEM_NONE,
862                         NULL, m);
863                 pItemInfo->item = item;
864
865                 if (i == index) {
866                         pItemInfo->select_status = true;
867                         m->cs_itinfo = pItemInfo;
868                 }
869                 m->elInfo = eina_list_append(m->elInfo, pItemInfo);
870         }
871         m->numCheckedItem = 0;
872 }
873
874
875 void CPlaybackView::m_RemovePlaylist(void)
876 {
877         if (m->eoPlaylist) {
878                 elm_genlist_clear(m->eoPlaylist);
879                 m->eoPlaylist = NULL;
880         }
881
882         if (m->elInfo) {
883                 eina_list_free(m->elInfo);
884                 m->elInfo = NULL;
885         }
886 }
887
888
889 void CPlaybackView::m_HandleGenlistItemActivated(Evas_Object *obj, Elm_Object_Item *genListItem)
890 {
891         int index;
892         SItemInfo *itinfo = NULL;
893
894         if (!obj || !genListItem)
895                 return;
896
897         itinfo = m_FindItemInfoFromItem(m->elInfo, genListItem);
898         if (!itinfo) {
899                 _ERR(" no item info found ");
900                 return;
901         }
902
903         if (itinfo->edit_mode) {
904                 m_UpdateItemCheck(itinfo);
905                 if (m->numCheckedItem > 0)
906                         m_DisableEditButtons(false);
907                 else
908                         m_DisableEditButtons(true);
909                 return;
910         }
911
912         index = elm_genlist_item_index_get(genListItem);
913
914         m->pController->PlayIndexSong(--index);
915 }
916
917
918 bool CPlaybackView::Create(void *data)
919 {
920         ASSERT(!m);
921
922         CPlaybackController::SCallback cb;
923
924         _CREATE_BEGIN{
925                 _CHECK(m = new SPlaybackView)
926                 _CHECK(m->mgr = CViewMgr::GetInstance())
927                 _CHECK(m->eoWin = m->mgr->Window())
928                 _CHECK(m->pController = new CMusicController)
929                 _CHECK(m->pController->Create())
930                 _CHECK(m->eoBase = CCommonUI::AddBase(m->eoWin, MUSIC_PLAYBACK_VIEW))
931                 _CHECK(CBaseView::Create(NULL))
932                 _CHECK(CTimer::Create());
933                 _CHECK(m->pController->AddListener(this))
934                 _CHECK(m->pPlaybackController = new CPlaybackController)
935                 _COMMAND{ cb.cookie = this; cb.OnCurrentSongCount = sm_CbCurrentSongCount; }
936                 _CHECK(m->pPlaybackController->Create(m->eoBase, &cb))
937
938                 _WHEN_SUCCESS{
939                         evas_object_data_set(m->eoBase, PLAYBACK_VIEW_DATA, m);
940
941                         m_AddCurrentSonginfo();
942                         m_AddPlaylist();
943
944                         int i;
945                         for (i = 0; i < TOTAL_CONTROL_BTNS; i++)
946                                 m->eoBtnControl[i] = m->pPlaybackController->ControlBtnsObject((EPlayerControlBtns)i);
947
948                         for (i = 0; i < TOTAL_EDIT_BTNS; i++)
949                                 m->eoBtnEdit[i] = m->pPlaybackController->EditBtnsObject((EPlayerEditBtns)i);
950
951                         m->pHandleVolume = new CHandleVolume;
952                         m->pHandleVolume->Create(m->eoBase);
953
954                         m_UpdatePlaymodeFocusSequence();
955
956                         Connect(m->eoBase, EO_BASE, TYPE_KEY_DOWN | TYPE_KEY_UP);
957                 }
958
959                 _CHECK_FAIL{ m->pPlaybackController->Destroy(); }
960                 _CHECK_FAIL{ delete m->pPlaybackController; }
961                 _CHECK_FAIL{ m->pController->RemoveListener(this); }
962                 _CHECK_FAIL{ CTimer::Destroy(); }
963                 _CHECK_FAIL{ CBaseView::Destroy(); }
964                 _CHECK_FAIL{ evas_object_del(m->eoBase); }
965                 _CHECK_FAIL{ m->pController->Destroy(); }
966                 _CHECK_FAIL{ delete m->pController; }
967                 _CHECK_FAIL{ /* mgr->Window() */ }
968                 _CHECK_FAIL{ /* CViewerMgr::GetInstance() */}
969                 _CHECK_FAIL{ delete m; m = NULL; }
970         }_CREATE_END_AND_CATCH{ return false; }
971
972         return true;
973 }
974
975
976 void CPlaybackView::Destroy(void)
977 {
978         ASSERT(m);
979
980         Disconnect(m->eoBase);
981
982         m->pPlaybackController->Destroy();
983         delete m->pPlaybackController;
984
985         m->pController->RemoveListener(this);
986
987         m->pSliderWidget->Destroy();
988         delete m->pSliderWidget;
989
990         m->pAlbumCover->Destroy();
991         delete m->pAlbumCover;
992
993         m->pSongTitleLabel->Destroy();
994         delete m->pSongTitleLabel;
995
996         m->pHandleVolume->Destroy();
997         delete m->pHandleVolume;
998         CBaseView::Destroy();
999         evas_object_del(m->eoBase);
1000
1001         free(m->ctxtinfo);
1002         delete m;
1003         m = NULL;
1004 }
1005
1006
1007 Evas_Object* CPlaybackView::Base(void)
1008 {
1009         ASSERT(m);
1010
1011         return m->eoBase;
1012 }
1013
1014
1015 void CPlaybackView::t_OnShow(void)
1016 {
1017         ASSERT(m);
1018
1019         int state;
1020
1021         m_UpdateCurrentSongInfo();
1022
1023         state = m->pController->PlayState();
1024         if (state == PLAY_STATUS_INITIAL || state == PLAY_STATUS_STOP) {
1025                 m_RemovePlaylist();
1026                 m_AddPlaylist();
1027                 m->pController->Start();
1028         }
1029
1030         if (m->cs_itinfo) {
1031                 elm_genlist_item_show(m->cs_itinfo->item, ELM_GENLIST_ITEM_SCROLLTO_IN);
1032                 elm_object_item_focus_set(m->cs_itinfo->item, EINA_TRUE);
1033         }
1034
1035         evas_object_show(m->eoBase);
1036 }
1037
1038
1039 void CPlaybackView::t_OnUpdate(void *data)
1040 {
1041         ASSERT(m);
1042
1043         SParcel *parcel = (SParcel *)data;
1044         int updateType;
1045         ESKey keyEvent = SKEY_MAX;
1046
1047         if (!parcel)
1048                 updateType = E_PLAYLIST_UPDATE;
1049         else {
1050                 updateType = parcel->updateType;
1051                 keyEvent = parcel->keyEvent;
1052         }
1053
1054         switch (updateType) {
1055         case E_PLAYLIST_UPDATE:
1056                 m_RemovePlaylist();
1057                 m_AddPlaylist();
1058                 elm_object_disabled_set(m->eoBtnControl[CTRL_BTN_FORWARD], EINA_FALSE);
1059                 elm_object_disabled_set(m->eoBtnControl[CTRL_BTN_REWIND], EINA_FALSE);
1060                 elm_object_disabled_set(m->eoBtnControl[CTRL_BTN_PLAY], EINA_FALSE);
1061                 elm_object_focus_next_object_set(m->eoBtnControl[CTRL_BTN_REPEAT],
1062                         m->eoBtnControl[CTRL_BTN_REWIND], ELM_FOCUS_RIGHT);
1063                 m_FromEditToPlaybackMode();
1064                 break;
1065
1066         case E_KEY_PRESS:
1067                 m_HandleKeyPress(keyEvent);
1068                 break;
1069
1070         case E_KEY_RELEASE:
1071                 m_HandleKeyUnpress(keyEvent);
1072                 break;
1073
1074         default:
1075                 break;
1076         }
1077 }
1078
1079
1080 void CPlaybackView::t_OnTimer(int id)
1081 {
1082 }
1083
1084
1085 void CPlaybackView::t_OnHide(void)
1086 {
1087         ASSERT(m);
1088
1089         evas_object_hide(m->eoBase);
1090 }
1091
1092
1093 void CPlaybackView::OnSKeyDown(int id, Evas *e, Evas_Object *obj, Evas_Event_SKey_Down *ev)
1094 {
1095         switch (id) {
1096         case EO_BASE:
1097                 m_HandleKeyPress(ev->skey);
1098                 break;
1099
1100         case EO_PLAYLIST:
1101                 {
1102                         Elm_Object_Item *it = NULL;
1103                         it = elm_object_focused_item_get(obj);
1104                         if (!it) {
1105                                 _ERR(" unable to get focused item ");
1106                                 return;
1107                         }
1108                         m->focused_item = it;
1109
1110                         switch (ev->skey) {
1111                         case SKEY_MENU:
1112                                 {
1113                                         SContentInfo *ctxtinfo = NULL;
1114                                         SItemInfo *itinfo = NULL;
1115                                         SParcel parcel;
1116
1117                                         if (m->ctxtinfo) {
1118                                                 free(m->ctxtinfo);
1119                                                 m->ctxtinfo = NULL;
1120                                         }
1121
1122                                         ctxtinfo = (SContentInfo *)calloc(1, sizeof(*ctxtinfo));
1123                                         if (!ctxtinfo)
1124                                                 return;
1125
1126                                         itinfo = m_FindItemInfoFromItem(m->elInfo, it);
1127                                         if (!itinfo) {
1128                                                 free(ctxtinfo);
1129                                                 return;
1130                                         }
1131
1132                                         if (m->pController->PlayState() == PLAY_STATUS_PLAY &&
1133                                                 itinfo == m->cs_itinfo)
1134                                                 ctxtinfo->status = PLAY_STATUS_PLAY;
1135                                         else
1136                                                 ctxtinfo->status = PLAY_STATUS_PAUSE;
1137
1138                                         ctxtinfo->cbdata = this;
1139                                         ctxtinfo->update = sm_CbCtxtUpdate;
1140                                         ctxtinfo->close = sm_CbCtxtClose;
1141                                         ctxtinfo->type = CONTEXT_TYPE_PLAYSONG;
1142                                         ctxtinfo->context = itinfo->sinfo;
1143
1144                                         m->ctxtinfo = ctxtinfo;
1145
1146                                         memset(&parcel, 0, sizeof(SParcel));
1147                                         parcel.ctxtInfo = ctxtinfo;
1148                                         if (!m->mgr->PushView(MUSIC_CONTEXT_VIEW, &parcel))
1149                                                 _ERR("viewmgr push view MUSIC_CONTEXT_VIEW failed");
1150                                 }
1151                                 break;
1152
1153                         default:
1154                                 break;
1155                         }
1156                 }
1157                 break;
1158
1159         default:
1160                 break;
1161         }
1162 }
1163
1164
1165 void CPlaybackView::OnSKeyUp(int id, Evas *e, Evas_Object *obj, Evas_Event_SKey_Up *ev)
1166 {
1167         switch (id) {
1168         case EO_BASE:
1169                 m_HandleKeyUnpress(ev->skey);
1170                 break;
1171
1172         default:
1173                 break;
1174         }
1175 }
1176
1177
1178 void CPlaybackView::OnMouseMove(int id, Evas *e, Evas_Object *obj, Evas_Event_Mouse_Move *ev)
1179 {
1180         switch (id) {
1181         case EO_PLAYLIST:
1182                 {
1183                         Elm_Object_Item *item;
1184
1185                         item = elm_genlist_at_xy_item_get(obj, ev->cur.canvas.x,
1186                                 ev->cur.canvas.y, NULL);
1187                         if (!item)
1188                                 return;
1189
1190                         if (!elm_object_item_focus_get(item))
1191                                 elm_object_item_focus_set(item, EINA_TRUE);
1192                 }
1193                 break;
1194
1195         default:
1196                 break;
1197         }
1198 }
1199
1200
1201 void CPlaybackView::OnRealized(int id, Evas_Object *obj, Elm_Object_Item *item)
1202 {
1203         switch (id) {
1204         case EO_PLAYLIST:
1205                 {
1206                         int index = elm_genlist_item_index_get(item);
1207                         if ((index & 1) == 1)
1208                                 elm_object_item_signal_emit(item,
1209                                         MUSIC_SIGNAL_EVEN_ROW, MUSIC_PLAYBACK_VIEW);
1210                         else
1211                                 elm_object_item_signal_emit(item,
1212                                         MUSIC_SIGNAL_ODD_ROW, MUSIC_PLAYBACK_VIEW);
1213
1214                         SItemInfo *itInfo = m_FindItemInfoFromItem(m->elInfo, item);
1215                         if (itInfo->select_status)
1216                                 elm_object_item_signal_emit(item,
1217                                         MUSIC_SIGNAL_SELECT_ITEM, MUSIC_PLAYBACK_VIEW);
1218                         else
1219                                 elm_object_item_signal_emit(item,
1220                                         MUSIC_SIGNAL_UNSELECT_ITEM, MUSIC_PLAYBACK_VIEW);
1221
1222                         if (itInfo->edit_mode) {
1223                                 elm_object_item_signal_emit(item,
1224                                         MUSIC_SIGNAL_EDITMODE_ON, MUSIC_PLAYBACK_VIEW);
1225                                 if (itInfo->check_status) {
1226                                         elm_object_item_signal_emit(item,
1227                                                 MUSIC_SIGNAL_CHECK_ON, MUSIC_PLAYBACK_VIEW);
1228                                 }
1229                                 else
1230                                         elm_object_item_signal_emit(item,
1231                                                 MUSIC_SIGNAL_CHECK_OFF, MUSIC_PLAYBACK_VIEW);
1232                         }
1233                         else
1234                                 elm_object_item_signal_emit(item,
1235                                         MUSIC_SIGNAL_EDITMODE_OFF, MUSIC_PLAYBACK_VIEW);
1236                 }
1237                 break;
1238
1239         default:
1240                 break;
1241         }
1242 }
1243
1244
1245 void CPlaybackView::OnActivated(int id, Evas_Object *obj, Elm_Object_Item *item)
1246 {
1247         switch (id) {
1248         case EO_PLAYLIST:
1249                 m_HandleGenlistItemActivated(obj, item);
1250                 break;
1251
1252         default:
1253                 break;
1254         }
1255 }
1256
1257
1258 void CPlaybackView::OnComplete(void)
1259 {
1260         m_UpdateCurrentSongInfo();
1261 }
1262
1263
1264 void CPlaybackView::OnError(void)
1265 {
1266 }
1267
1268
1269 void CPlaybackView::OnUsbStatusChanged(SUsbStorageStatus status)
1270 {
1271 }
1272
1273
1274 void CPlaybackView::OnUpdateContent(void)
1275 {
1276 }
1277
1278
1279 void CPlaybackView::OnStartPlayback(void)
1280 {
1281         m_UpdateCurrentSongInfo();
1282 }
1283
1284
1285 void CPlaybackView::OnStopPlayback(void)
1286 {
1287 }
1288
1289
1290 void CPlaybackView::OnEmptyPlaylist(void)
1291 {
1292         eina_list_free(m->elInfo);
1293         m->elInfo = NULL;
1294         elm_genlist_clear(m->eoPlaylist);
1295         m_UpdateEmptySongInfo();
1296 }
1297
1298
1299 void CPlaybackView::OnPlayerModeChanged(EPlayerMode mode)
1300 {
1301         switch (mode) {
1302         case MODE_PLAYLIST_EDIT:
1303                 m_FromPlaybackToEditMode();
1304                 break;
1305
1306         case MODE_PLAYBACK:
1307                 m_FromEditToPlaybackMode();
1308                 break;
1309
1310         default:
1311                 ASSERT(!"Invalid Player Mode");
1312                 break;
1313         }
1314 }
1315
1316
1317 void CPlaybackView::OnEditButtonsPressed(EPlayerEditBtns editBtns)
1318 {
1319         switch (editBtns) {
1320         case EDIT_BTN_CANCEL:
1321                 m_DisableCheckAll(m->elInfo);
1322                 m_DisableEditButtons(true);
1323                 break;
1324
1325         case EDIT_BTN_DESELECT:
1326                 m_DisableCheckAll(m->elInfo);
1327                 m_DisableEditButtons(true);
1328                 elm_genlist_realized_items_update(m->eoPlaylist);
1329                 break;
1330
1331         case EDIT_BTN_DELETE:
1332                 m_DeleteSelectedItems();
1333                 break;
1334
1335         default:
1336                 ASSERT(!"Invalid Edit Button");
1337                 break;
1338         }
1339 }