Clean source codes
[profile/tv/apps/native/musicplayer.git] / src / playback / MusicControllerImpl.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 <string.h>
18 #include <stdlib.h>
19 #include <AppCommon.h>
20 #include "i18n.h"
21 #include "song_info.h"
22 #include "album_info.h"
23 #include "folder_info.h"
24 #include "common.h"
25 #include "category_info.h"
26 #include "music-controller.h"
27 #include "MusicControllerImpl.h"
28 #include "playlist-mgr.h"
29 #include "playback-mgr.h"
30 #include "mediadata.h"
31 #include "bus.h"
32 #include "Info.h"
33
34
35 struct SMusicControllerImpl {
36         CPlayback *pPlayback;
37         CPlaylist* pPlaylist;
38         CMediadata* pMediadata;
39         CAlbumInfo *alinfo;
40         Eina_List *elListener;
41         int initial_index;
42
43         EPlayStatus    statePlay;
44         EShuffleStatus stateShuffle;
45
46         ERepeatStatus repeatstate;
47         SCbInfo *cbinfo;
48
49         SMusicControllerImpl() {
50                 pPlayback = NULL;
51                 pPlaylist = NULL;
52                 pMediadata = NULL;
53                 alinfo = NULL;
54                 elListener = NULL;
55                 initial_index = 0;
56                 statePlay = (EPlayStatus)0;
57                 stateShuffle= (EShuffleStatus)0;
58                 repeatstate= (ERepeatStatus)0;
59                 cbinfo = NULL;
60         }
61 };
62
63
64 void CMusicControllerImpl::sm_CbContentUpdated(void *dt)
65 {
66         CMusicControllerImpl *root = (CMusicControllerImpl *)dt;
67         if (root)
68                 root->m_OnContentUpdated();
69 }
70
71
72 void CMusicControllerImpl::m_OnContentUpdated(void)
73 {
74         Eina_List *l;
75         IMusicControllerListener *mcListener = NULL;
76         void *obj;
77
78         EINA_LIST_FOREACH(m->elListener, l, obj) {
79                 mcListener = (IMusicControllerListener *)obj;
80                 if (mcListener)
81                         mcListener->OnUpdateContent();
82         }
83 }
84
85
86 void CMusicControllerImpl::m_InvokeErrorCallback(SMusicControllerImpl *m, int type)
87 {
88         Eina_List *l;
89         IMusicControllerListener *mcListener = NULL;
90         void *obj;
91
92         if (!m)
93                 return;
94
95         EINA_LIST_FOREACH(m->elListener, l, obj) {
96                 mcListener = (IMusicControllerListener *)obj;
97                 if (mcListener)
98                         mcListener->OnError();
99         }
100 }
101
102
103 bool CMusicControllerImpl::t_PlayNext(int direction, int playnext_type)
104 {
105         bool r;
106         int index;
107
108         if (!m->pPlaylist->FlagCreate())
109                 return false;
110
111         Stop();
112
113         if (playnext_type == E_ON_COMPLETE &&
114                 m->repeatstate == REPEAT_STATUS_ONE)
115                 goto finish;
116
117         if (direction == DIR_NEXT) {
118                 r = m->pPlaylist->LoadNextSong(m->stateShuffle);
119         }
120         else {
121                 r = m->pPlaylist->LoadPreviousSong(m->stateShuffle);
122         }
123
124         if (r == false) {
125                 _ERR(" playlist load next/previous failed ");
126                 return false;
127         }
128
129         if (playnext_type == E_ON_COMPLETE &&
130                 m->repeatstate == REPEAT_STATUS_NONE) {
131                 r = m->pPlaylist->GetCurSongIndex(&index);
132                 if (r == false) {
133                         _ERR(" get cur song index failed ");
134                         return false;
135                 }
136
137                 if (index == m->initial_index)
138                         return true;
139         }
140
141 finish:
142         Start();
143
144         return true;
145 }
146
147
148 bool CMusicControllerImpl::Create(void)
149 {
150         ASSERT(!m);
151
152         _CREATE_BEGIN{
153                 _CHECK(m = new SMusicControllerImpl)
154                 _CHECK(m->alinfo = new CAlbumInfo)
155                 _CHECK(m->alinfo->Create() == true)
156                 _CHECK(m->pMediadata = new CMediadata)
157                 _CHECK(m->pMediadata->Create() == true)
158                 _CHECK(m->pPlayback = new CPlayback)
159                 _CHECK(m->pPlayback->Create() == true)
160                 _CHECK(m->pPlayback->SetCallback(this))
161                 _CHECK(m->pPlaylist = new CPlaylist)
162
163                 _WHEN_SUCCESS{
164                         m->statePlay = PLAY_STATUS_INITIAL;
165                         m->stateShuffle = SHUFFLE_STATUS_OFF;
166                         m->repeatstate = REPEAT_STATUS_ALL;
167                         m->initial_index = 0;
168                         CInfo::SetSortType(E_SORT_TITLE_A_Z);
169                         CInfo::SetSourceType(SOURCE_TYPE_ALL);
170                         m->cbinfo = m->pMediadata->AddCallback(E_CONTENT_UPDATE, sm_CbContentUpdated, this);
171
172                         // Even if CUsbConnectionListener creation failed,
173                         // application should run properly.
174                         if (!CUsbListener::Create())
175                                 _DBG("CUsbConnectionListener::Create failed");
176                 }
177
178                 _CHECK_FAIL{ delete m->pPlaylist; }
179                 _CHECK_FAIL{}
180                 _CHECK_FAIL{ m->pPlayback->Destroy(); }
181                 _CHECK_FAIL{ delete m->pPlayback; }
182                 _CHECK_FAIL{ m->pMediadata->Destroy(); }
183                 _CHECK_FAIL{ delete m->pMediadata; }
184                 _CHECK_FAIL{ m->alinfo->Destroy(); }
185                 _CHECK_FAIL{ delete m->alinfo; }
186
187                 _CHECK_FAIL{ delete m; m = NULL; }
188         } _CREATE_END_AND_CATCH{ return NULL; }
189
190         return true;
191 }
192
193
194 void CMusicControllerImpl::Destroy(void)
195 {
196         if (CUsbListener::FlagCreate())
197                 CUsbListener::Destroy();
198
199         if (!m->pPlayback->UnsetCallback())
200                 _ERR(" playback remove completion callback failed");
201
202         m->pPlayback->Destroy();
203         delete m->pPlayback;
204
205         if (m->pPlaylist->FlagCreate()) {
206                 m->pPlaylist->Destroy();
207         }
208         delete m->pPlaylist;
209
210         m->pMediadata->RemoveCallback(m->cbinfo);
211         m->pMediadata->Destroy();
212         delete m->pMediadata;
213
214         m->alinfo->Destroy();
215         delete m->alinfo;
216         delete m;
217         m = NULL;
218 }
219
220
221 bool CMusicControllerImpl::Start(void)
222 {
223         ASSERT(m);
224
225         const char *songpath;
226         int index;
227         CPlaylist *pPlaylist;
228         CPlayback *pPlayback;
229         CSongInfo *sinfo;
230         char *media_id;
231
232         pPlaylist = m->pPlaylist;
233         pPlayback = m->pPlayback;
234
235         _CREATE_BEGIN{
236                 _CHECK(pPlaylist->FlagCreate())
237                 _CHECK(pPlaylist->GetCurSongIndex(&index))
238                 _CHECK(songpath = pPlaylist->SongpathFromIndex(index))
239                 _CHECK(pPlayback->SetUri(songpath))
240                 _CHECK(pPlayback->Prepare())
241                 _CHECK(pPlayback->Start())
242                 _COMMAND{ m->statePlay = PLAY_STATUS_PLAY; }
243                 _CHECK(m->pPlaylist->GetSonginfoFromIndex(index, &sinfo))
244                 _CHECK(media_id = sinfo->Id())
245                 _CHECK(m->pMediadata->SetPlayedTime(media_id))
246
247                 _WHEN_SUCCESS{
248                         bus_send_signal();
249                 }
250
251                 _CHECK_FAIL{}
252                 _CHECK_FAIL{}
253                 _CHECK_FAIL{}
254
255                 _CHECK_FAIL{}
256                 _CHECK_FAIL{}
257                 _CHECK_FAIL{ _ERR("Playback Failed!!"); m_InvokeErrorCallback(m, E_PLAYBACK_ERROR); }
258                 _CHECK_FAIL{}
259                 _CHECK_FAIL{}
260                 _CHECK_FAIL{ _ERR("CMusicControllerImpl::Start Failed!!"); Stop(); }
261         } _CREATE_END_AND_CATCH{ return false; }
262
263         Eina_List *l;
264         IMusicControllerListener *mcListener = NULL;
265         void *obj;
266         EINA_LIST_FOREACH(m->elListener, l, obj) {
267                 mcListener = (IMusicControllerListener *)obj;
268                 if (mcListener)
269                         mcListener->OnStartPlayback();
270         }
271
272         return true;
273 }
274
275
276 bool CMusicControllerImpl::Stop(void)
277 {
278         ASSERT(m);
279
280         if (!m->pPlayback->Stop()) {
281                 _ERR("playback stop failed");
282                 return false;
283         }
284
285         m->statePlay = PLAY_STATUS_STOP;
286
287         if (!m->pPlayback->Unprepare()) {
288                 _ERR("playback unprepare failed");
289                 return false;
290         }
291
292         Eina_List *l;
293         IMusicControllerListener *mcListener = NULL;
294         void *obj;
295         EINA_LIST_FOREACH(m->elListener, l, obj) {
296                 mcListener = (IMusicControllerListener *)obj;
297                 if (mcListener)
298                         mcListener->OnStopPlayback();
299         }
300
301
302         return true;
303 }
304
305
306 bool CMusicControllerImpl::Resume(void)
307 {
308         ASSERT(m);
309
310         if (!m->pPlayback->Resume()) {
311                 _ERR("playback resume failed");
312                 return false;
313         }
314
315         m->statePlay = PLAY_STATUS_PLAY;
316
317         Eina_List *l;
318         IMusicControllerListener *mcListener = NULL;
319         void *obj;
320         EINA_LIST_FOREACH(m->elListener, l, obj) {
321                 mcListener = (IMusicControllerListener *)obj;
322                 if (mcListener)
323                         mcListener->OnResumePlayback();
324         }
325         return true;
326 }
327
328
329 bool CMusicControllerImpl::Pause(void)
330 {
331         ASSERT(m);
332
333         if (!m->pPlayback->Pause()) {
334                 _ERR("playback Pause failed");
335                 return false;
336         }
337
338         m->statePlay = PLAY_STATUS_PAUSE;
339
340         Eina_List *l;
341         IMusicControllerListener *mcListener = NULL;
342         void *obj;
343         EINA_LIST_FOREACH(m->elListener, l, obj) {
344                 mcListener = (IMusicControllerListener *)obj;
345                 if (mcListener)
346                         mcListener->OnPausePlayback();
347         }
348
349
350         return true;
351 }
352
353
354 bool CMusicControllerImpl::AddListener(IMusicControllerListener *listener)
355 {
356         ASSERT(m);
357         ASSERT(listener);
358
359         m->elListener = eina_list_append(m->elListener, listener);
360
361         return true;
362 }
363
364
365 bool CMusicControllerImpl::RemoveListener(IMusicControllerListener *listener)
366 {
367         ASSERT(m);
368         ASSERT(listener);
369
370         m->elListener = eina_list_remove(m->elListener, listener);
371
372         return true;
373 }
374
375
376 bool CMusicControllerImpl::GetCurrentSongIndex(int *ind)
377 {
378         ASSERT(m);
379
380         int index;
381
382         if (!m || !m->pPlaylist->FlagCreate()) {
383                 _ERR("NULL received");
384                 return false;
385         }
386
387         if (!m->pPlaylist->GetCurSongIndex(&index)) {
388                 _ERR(" playlist get current song index failed");
389                 return false;
390         }
391
392         *ind = index;
393
394         return true;
395 }
396
397
398 bool CMusicControllerImpl::GetTotalSongs(int *ts)
399 {
400         ASSERT(m);
401
402         int count;
403
404         if (!m->pPlaylist->FlagCreate()) {
405                 _ERR("NULL received");
406                 return false;
407         }
408
409         if (!m->pPlaylist->GetTotalSongs(&count)) {
410                 _ERR(" playlist get current song index failed");
411                 return false;
412         }
413
414         *ts = count;
415
416         return true;
417 }
418
419
420 bool CMusicControllerImpl::GetSonginfoFromIndex(int index, CSongInfo **const csinfo)
421 {
422         ASSERT(m);
423
424         if (!m->pPlaylist->FlagCreate() || !csinfo) {
425                 _ERR("NULL received");
426                 return false;
427         }
428
429         if (!m->pPlaylist->GetSonginfoFromIndex(index, csinfo)) {
430                 _ERR(" playlist get current song info failed");
431                 return false;
432         }
433
434         return true;
435 }
436
437
438 bool CMusicControllerImpl::SetPosition(int milseconds)
439 {
440         ASSERT(m);
441
442         if (!m->pPlayback->SetPosition(milseconds)) {
443                 _ERR("playback set position failed");
444                 return false;
445         }
446
447         Eina_List *l;
448         IMusicControllerListener *mcListener = NULL;
449         void *obj;
450         EINA_LIST_FOREACH(m->elListener, l, obj) {
451                 mcListener = (IMusicControllerListener *)obj;
452                 if (mcListener)
453                         mcListener->OnPosition(milseconds);
454         }
455         return true;
456 }
457
458
459 bool CMusicControllerImpl::GetPosition(int *const milseconds)
460 {
461         ASSERT(m);
462
463         if (!m->pPlayback->GetPosition(milseconds)) {
464                 _ERR("playback get position failed");
465                 return false;
466         }
467
468         return true;
469 }
470
471
472 bool CMusicControllerImpl::SetCurrentSong(char *mediaid)
473 {
474         ASSERT(m);
475         ASSERT(mediaid);
476
477         if (!m->pPlaylist->FlagCreate())
478                 return false;
479
480         m->pPlaylist->SetCurrentSong(mediaid);
481
482         return true;
483 }
484
485
486 bool CMusicControllerImpl::GetCurrentSong(CSongInfo **const sinfo)
487 {
488         ASSERT(m);
489
490         int index;
491
492         if (!m->pPlaylist->FlagCreate())
493                 return false;
494
495         if (!m->pPlaylist->GetCurSongIndex(&index)) {
496                 _ERR(" playlist get current song index failed");
497                 return false;
498         }
499
500         if (!m->pPlaylist->GetSonginfoFromIndex(index, sinfo)) {
501                 _ERR(" playlist get current song info failed");
502                 return false;
503         }
504
505         return true;
506 }
507
508
509 bool CMusicControllerImpl::UpdatePlaylist(Eina_List *slist, int addmode)
510 {
511         ASSERT(m);
512         ASSERT(slist);
513
514         if (m->pPlaylist->FlagCreate())
515                 m->pPlaylist->Update(slist, addmode);
516         else {
517                 if (!m->pPlaylist->Create(slist))
518                         _ERR(" playlist create failed ");
519         }
520         return true;
521 }
522
523
524 bool CMusicControllerImpl::EmptyPlaylist(void)
525 {
526         ASSERT(m);
527
528         if (!m->pPlaylist->FlagCreate())
529                 return false;
530
531         m->pPlaylist->Destroy();
532
533         Eina_List *l;
534         IMusicControllerListener *mcListener;
535         void * obj;
536
537         EINA_LIST_FOREACH(m->elListener, l, obj) {
538                 mcListener = (IMusicControllerListener *)obj;
539                 if (mcListener)
540                         mcListener->OnEmptyPlaylist();
541         }
542
543         return true;
544 }
545
546
547 bool CMusicControllerImpl::PlayPreviousSong(void)
548 {
549         ASSERT(m);
550
551         return t_PlayNext(DIR_PREVIOUS, E_BUTTON_CLICK);
552 }
553
554
555 bool CMusicControllerImpl::PlayNextSong(void)
556 {
557         ASSERT(m);
558
559         return t_PlayNext(DIR_NEXT, E_BUTTON_CLICK);
560 }
561
562
563 bool CMusicControllerImpl::PlayIndexSong(int index)
564 {
565         ASSERT(m);
566
567         if (!m->pPlaylist->FlagCreate())
568                 return false;
569
570         Stop();
571
572         if (!m->pPlaylist->SetCurSongIndex(index))
573                 return false;
574
575         Start();
576
577         m->initial_index = index;
578
579         return true;
580 }
581
582
583 bool CMusicControllerImpl::RemoveSong(CSongInfo *sinfo, int index)
584 {
585         ASSERT(m);
586         ASSERT(sinfo);
587
588         int ind;
589
590         if (!m->pPlaylist->FlagCreate())
591                 return false;
592
593         if (!GetCurrentSongIndex(&ind)) {
594                 _ERR("unable to find current song index");
595                 return false;
596         }
597
598         if (!m->pPlaylist->RemoveSong(sinfo, index, m->stateShuffle)) {
599                 _ERR("Song can not be deleted");
600                 return false;
601         }
602
603         if (ind != 0 && ind == index)
604                 Stop();
605
606         return true;
607 }
608
609
610 bool CMusicControllerImpl::MediaGetList(int EListType, void *info, Eina_List **list)
611 {
612         ASSERT(m);
613
614         Eina_List *mlist;
615
616         mlist = m->pMediadata->Medialist(CInfo::SourceType(), EListType, info);
617         if (!mlist)
618                 return false;
619
620         *list = eina_list_clone(mlist);
621
622         return true;
623 }
624
625
626 bool CMusicControllerImpl::MediaInsertPlaylist(const char *name, Eina_List *idlist)
627 {
628         ASSERT(m);
629         ASSERT(name);
630         ASSERT(idlist);
631
632         return m->pMediadata->Alloc(name, idlist);
633 }
634
635
636 bool CMusicControllerImpl::MediaExistPlaylist(const char *name)
637 {
638         ASSERT(m);
639         ASSERT(name);
640
641         return m->pMediadata->ExistPlaylist(name);
642 }
643
644
645 bool CMusicControllerImpl::MediaDeletePlaylist(int id)
646 {
647         ASSERT(m);
648
649         return m->pMediadata->Delete(id);
650 }
651
652
653 bool CMusicControllerImpl::MediaRenamePlaylist(int id, const char *name)
654 {
655         ASSERT(m);
656         ASSERT(name);
657
658         return m->pMediadata->Rename(id, name);
659 }
660
661
662 bool CMusicControllerImpl::MediaAddmediaPlaylist(int id, Eina_List *idlist)
663 {
664         ASSERT(m);
665         ASSERT(idlist);
666
667         return m->pMediadata->Insert(id, idlist);
668 }
669
670
671 bool CMusicControllerImpl::MediaRemovemediaPlaylist(int id, Eina_List *idlist)
672 {
673         ASSERT(m);
674         ASSERT(idlist);
675
676         return m->pMediadata->Remove(id, idlist);
677 }
678
679
680 bool CMusicControllerImpl::MediaAddsongsPlaylist(int lid, Eina_List *list)
681 {
682         ASSERT(m);
683         ASSERT(list);
684
685         Eina_List *idlist, *l;
686         CSongInfo *sinfo;
687         void *obj;
688         char *id;
689
690         idlist = NULL;
691         EINA_LIST_FOREACH(list, l, obj) {
692                 sinfo = (CSongInfo *)obj;
693                 id = sinfo->Id();
694                 if (id)
695                         idlist = eina_list_append(idlist, id);
696         }
697
698         if (!MediaAddmediaPlaylist(lid, idlist)) {
699                 _ERR(" Failed to add songs to playlist ");
700                 return false;
701         }
702
703         return true;
704 }
705
706
707 CSongInfo *CMusicControllerImpl::MediaSongByUri(char *uri)
708 {
709         ASSERT(m);
710         ASSERT(uri);
711
712         CSongInfo *sinfo;
713
714         sinfo = m->pMediadata->SongByUri(uri);
715         if (!sinfo)
716                 return NULL;
717
718         return sinfo;
719 }
720
721
722 bool CMusicControllerImpl::SetPlayState(EPlayStatus state)
723 {
724         ASSERT(m);
725
726         m->statePlay = state;
727
728         return true;
729 }
730
731
732 EPlayStatus CMusicControllerImpl::PlayState(void)
733 {
734         ASSERT(m);
735
736         return m->statePlay;
737 }
738
739
740 bool CMusicControllerImpl::SetShuffleState(EShuffleStatus state)
741 {
742         ASSERT(m);
743
744         m->stateShuffle = state;
745         if (state && m->pPlaylist->FlagCreate())
746                 m->pPlaylist->UpdateShuffle();
747
748         return true;
749 }
750
751
752 EShuffleStatus CMusicControllerImpl::ShuffleState(void)
753 {
754         ASSERT(m);
755
756         return m->stateShuffle;
757 }
758
759
760 bool CMusicControllerImpl::SetRepeatState(ERepeatStatus state)
761 {
762         ASSERT(m);
763
764         m->repeatstate = state;
765
766         return true;
767 }
768
769
770 ERepeatStatus CMusicControllerImpl::RepeatState(void)
771 {
772         ASSERT(m);
773
774         return m->repeatstate;
775 }
776
777
778 void CMusicControllerImpl::ChangePlayerMode(EPlayerMode mode)
779 {
780         ASSERT(m);
781
782         Eina_List *l;
783         IMusicControllerListener *mcListener;
784         void * obj;
785
786         EINA_LIST_FOREACH(m->elListener, l, obj) {
787                 mcListener = (IMusicControllerListener *)obj;
788                 if (mcListener)
789                         mcListener->OnPlayerModeChanged(mode);
790         }
791 }
792
793
794 void CMusicControllerImpl::HandlePlaylistEditButtons(EPlayerEditBtns btnId)
795 {
796         ASSERT(m);
797
798         Eina_List *l;
799         IMusicControllerListener *mcListener;
800         void * obj;
801
802         EINA_LIST_FOREACH(m->elListener, l, obj) {
803                 mcListener = (IMusicControllerListener *)obj;
804                 if (mcListener)
805                         mcListener->OnEditButtonsPressed(btnId);
806         }
807 }
808
809
810 void CMusicControllerImpl::HandleRemoteButtons(Evas_Object *eoBtn, EPlayerBtnsEvent ev)
811 {
812         ASSERT(m);
813
814         Eina_List *l;
815         IMusicControllerListener *mcListener;
816         void * obj;
817
818         EINA_LIST_FOREACH(m->elListener, l, obj) {
819                 mcListener = (IMusicControllerListener *)obj;
820                 if (mcListener)
821                         mcListener->OnRemoteButtonEvent(eoBtn, ev);
822         }
823 }
824
825
826 void CMusicControllerImpl::OnStatusChanged(SUsbHostDeviceInfo *changedDevice,
827         SUsbHostDeviceStatus status)
828 {
829         if (!m)
830                 return;
831
832         Eina_List *l;
833         IMusicControllerListener *mcListener = NULL;;
834         void *obj;
835
836         if (status == USB_HOST_DEV_CONNECTED) {
837                 if (CInfo::SourceType() == SOURCE_TYPE_USB) {
838                         if (!FlagConnected())
839                                 CInfo::SetSourceType(SOURCE_TYPE_ALL);
840                 }
841
842                 EINA_LIST_FOREACH(m->elListener, l, obj) {
843                         mcListener = (IMusicControllerListener *)obj;
844                         if (mcListener)
845                                 mcListener->OnUsbStatusChanged(IMusicControllerListener::USB_STORAGE_CONNECTED);
846                 }
847         }
848         else {
849                 if (CInfo::SourceType() == SOURCE_TYPE_USB) {
850                         CInfo::SetSourceType(SOURCE_TYPE_ALL);
851                 }
852
853                 EINA_LIST_FOREACH(m->elListener, l, obj) {
854                         mcListener = (IMusicControllerListener *)obj;
855                         if (mcListener)
856                                 mcListener->OnUsbStatusChanged(IMusicControllerListener::USB_STORAGE_DISCONNECTED);
857                 }
858         }
859 }
860
861
862 void CMusicControllerImpl::t_OnPlayComplete(void)
863 {
864         bool r;
865         Eina_List *l;
866         IMusicControllerListener *mcListener = NULL;
867         void *obj;
868
869         r = t_PlayNext(DIR_NEXT, E_ON_COMPLETE);
870         if (r == false)
871                 _ERR(" music play next song failed ");
872
873         EINA_LIST_FOREACH(m->elListener, l, obj) {
874                 mcListener = (IMusicControllerListener *)obj;
875                 if (mcListener)
876                         mcListener->OnComplete();
877         }
878 }