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.
19 #include <AppCommon.h>
21 #include "song_info.h"
22 #include "album_info.h"
23 #include "folder_info.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"
35 struct SMusicControllerImpl {
38 CMediadata* pMediadata;
40 Eina_List *elListener;
43 EPlayStatus statePlay;
44 EShuffleStatus stateShuffle;
46 ERepeatStatus repeatstate;
49 SMusicControllerImpl() {
56 statePlay = (EPlayStatus)0;
57 stateShuffle= (EShuffleStatus)0;
58 repeatstate= (ERepeatStatus)0;
64 void CMusicControllerImpl::sm_CbContentUpdated(void *dt)
66 CMusicControllerImpl *root = (CMusicControllerImpl *)dt;
68 root->m_OnContentUpdated();
72 void CMusicControllerImpl::m_OnContentUpdated(void)
75 IMusicControllerListener *mcListener = NULL;
78 EINA_LIST_FOREACH(m->elListener, l, obj) {
79 mcListener = (IMusicControllerListener *)obj;
81 mcListener->OnUpdateContent();
86 void CMusicControllerImpl::m_InvokeErrorCallback(SMusicControllerImpl *m, int type)
89 IMusicControllerListener *mcListener = NULL;
95 EINA_LIST_FOREACH(m->elListener, l, obj) {
96 mcListener = (IMusicControllerListener *)obj;
98 mcListener->OnError();
103 bool CMusicControllerImpl::t_PlayNext(int direction, int playnext_type)
108 if (!m->pPlaylist->FlagCreate())
113 if (playnext_type == E_ON_COMPLETE &&
114 m->repeatstate == REPEAT_STATUS_ONE)
117 if (direction == DIR_NEXT) {
118 r = m->pPlaylist->LoadNextSong(m->stateShuffle);
121 r = m->pPlaylist->LoadPreviousSong(m->stateShuffle);
125 _ERR(" playlist load next/previous failed ");
129 if (playnext_type == E_ON_COMPLETE &&
130 m->repeatstate == REPEAT_STATUS_NONE) {
131 r = m->pPlaylist->GetCurSongIndex(&index);
133 _ERR(" get cur song index failed ");
137 if (index == m->initial_index)
148 bool CMusicControllerImpl::Create(void)
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)
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);
172 // Even if CUsbConnectionListener creation failed,
173 // application should run properly.
174 if (!CUsbListener::Create())
175 _DBG("CUsbConnectionListener::Create failed");
178 _CHECK_FAIL{ delete m->pPlaylist; }
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; }
187 _CHECK_FAIL{ delete m; m = NULL; }
188 } _CREATE_END_AND_CATCH{ return NULL; }
194 void CMusicControllerImpl::Destroy(void)
196 if (CUsbListener::FlagCreate())
197 CUsbListener::Destroy();
199 if (!m->pPlayback->UnsetCallback())
200 _ERR(" playback remove completion callback failed");
202 m->pPlayback->Destroy();
205 if (m->pPlaylist->FlagCreate()) {
206 m->pPlaylist->Destroy();
210 m->pMediadata->RemoveCallback(m->cbinfo);
211 m->pMediadata->Destroy();
212 delete m->pMediadata;
214 m->alinfo->Destroy();
221 bool CMusicControllerImpl::Start(void)
225 const char *songpath;
227 CPlaylist *pPlaylist;
228 CPlayback *pPlayback;
232 pPlaylist = m->pPlaylist;
233 pPlayback = m->pPlayback;
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))
257 _CHECK_FAIL{ _ERR("Playback Failed!!"); m_InvokeErrorCallback(m, E_PLAYBACK_ERROR); }
260 _CHECK_FAIL{ _ERR("CMusicControllerImpl::Start Failed!!"); Stop(); }
261 } _CREATE_END_AND_CATCH{ return false; }
264 IMusicControllerListener *mcListener = NULL;
266 EINA_LIST_FOREACH(m->elListener, l, obj) {
267 mcListener = (IMusicControllerListener *)obj;
269 mcListener->OnStartPlayback();
276 bool CMusicControllerImpl::Stop(void)
280 if (!m->pPlayback->Stop()) {
281 _ERR("playback stop failed");
285 m->statePlay = PLAY_STATUS_STOP;
287 if (!m->pPlayback->Unprepare()) {
288 _ERR("playback unprepare failed");
293 IMusicControllerListener *mcListener = NULL;
295 EINA_LIST_FOREACH(m->elListener, l, obj) {
296 mcListener = (IMusicControllerListener *)obj;
298 mcListener->OnStopPlayback();
306 bool CMusicControllerImpl::Resume(void)
310 if (!m->pPlayback->Resume()) {
311 _ERR("playback resume failed");
315 m->statePlay = PLAY_STATUS_PLAY;
318 IMusicControllerListener *mcListener = NULL;
320 EINA_LIST_FOREACH(m->elListener, l, obj) {
321 mcListener = (IMusicControllerListener *)obj;
323 mcListener->OnResumePlayback();
329 bool CMusicControllerImpl::Pause(void)
333 if (!m->pPlayback->Pause()) {
334 _ERR("playback Pause failed");
338 m->statePlay = PLAY_STATUS_PAUSE;
341 IMusicControllerListener *mcListener = NULL;
343 EINA_LIST_FOREACH(m->elListener, l, obj) {
344 mcListener = (IMusicControllerListener *)obj;
346 mcListener->OnPausePlayback();
354 bool CMusicControllerImpl::AddListener(IMusicControllerListener *listener)
359 m->elListener = eina_list_append(m->elListener, listener);
365 bool CMusicControllerImpl::RemoveListener(IMusicControllerListener *listener)
370 m->elListener = eina_list_remove(m->elListener, listener);
376 bool CMusicControllerImpl::GetCurrentSongIndex(int *ind)
382 if (!m || !m->pPlaylist->FlagCreate()) {
383 _ERR("NULL received");
387 if (!m->pPlaylist->GetCurSongIndex(&index)) {
388 _ERR(" playlist get current song index failed");
398 bool CMusicControllerImpl::GetTotalSongs(int *ts)
404 if (!m->pPlaylist->FlagCreate()) {
405 _ERR("NULL received");
409 if (!m->pPlaylist->GetTotalSongs(&count)) {
410 _ERR(" playlist get current song index failed");
420 bool CMusicControllerImpl::GetSonginfoFromIndex(int index, CSongInfo **const csinfo)
424 if (!m->pPlaylist->FlagCreate() || !csinfo) {
425 _ERR("NULL received");
429 if (!m->pPlaylist->GetSonginfoFromIndex(index, csinfo)) {
430 _ERR(" playlist get current song info failed");
438 bool CMusicControllerImpl::SetPosition(int milseconds)
442 if (!m->pPlayback->SetPosition(milseconds)) {
443 _ERR("playback set position failed");
448 IMusicControllerListener *mcListener = NULL;
450 EINA_LIST_FOREACH(m->elListener, l, obj) {
451 mcListener = (IMusicControllerListener *)obj;
453 mcListener->OnPosition(milseconds);
459 bool CMusicControllerImpl::GetPosition(int *const milseconds)
463 if (!m->pPlayback->GetPosition(milseconds)) {
464 _ERR("playback get position failed");
472 bool CMusicControllerImpl::SetCurrentSong(char *mediaid)
477 if (!m->pPlaylist->FlagCreate())
480 m->pPlaylist->SetCurrentSong(mediaid);
486 bool CMusicControllerImpl::GetCurrentSong(CSongInfo **const sinfo)
492 if (!m->pPlaylist->FlagCreate())
495 if (!m->pPlaylist->GetCurSongIndex(&index)) {
496 _ERR(" playlist get current song index failed");
500 if (!m->pPlaylist->GetSonginfoFromIndex(index, sinfo)) {
501 _ERR(" playlist get current song info failed");
509 bool CMusicControllerImpl::UpdatePlaylist(Eina_List *slist, int addmode)
514 if (m->pPlaylist->FlagCreate())
515 m->pPlaylist->Update(slist, addmode);
517 if (!m->pPlaylist->Create(slist))
518 _ERR(" playlist create failed ");
524 bool CMusicControllerImpl::EmptyPlaylist(void)
528 if (!m->pPlaylist->FlagCreate())
531 m->pPlaylist->Destroy();
534 IMusicControllerListener *mcListener;
537 EINA_LIST_FOREACH(m->elListener, l, obj) {
538 mcListener = (IMusicControllerListener *)obj;
540 mcListener->OnEmptyPlaylist();
547 bool CMusicControllerImpl::PlayPreviousSong(void)
551 return t_PlayNext(DIR_PREVIOUS, E_BUTTON_CLICK);
555 bool CMusicControllerImpl::PlayNextSong(void)
559 return t_PlayNext(DIR_NEXT, E_BUTTON_CLICK);
563 bool CMusicControllerImpl::PlayIndexSong(int index)
567 if (!m->pPlaylist->FlagCreate())
572 if (!m->pPlaylist->SetCurSongIndex(index))
577 m->initial_index = index;
583 bool CMusicControllerImpl::RemoveSong(CSongInfo *sinfo, int index)
590 if (!m->pPlaylist->FlagCreate())
593 if (!GetCurrentSongIndex(&ind)) {
594 _ERR("unable to find current song index");
598 if (!m->pPlaylist->RemoveSong(sinfo, index, m->stateShuffle)) {
599 _ERR("Song can not be deleted");
603 if (ind != 0 && ind == index)
610 bool CMusicControllerImpl::MediaGetList(int EListType, void *info, Eina_List **list)
616 mlist = m->pMediadata->Medialist(CInfo::SourceType(), EListType, info);
620 *list = eina_list_clone(mlist);
626 bool CMusicControllerImpl::MediaInsertPlaylist(const char *name, Eina_List *idlist)
632 return m->pMediadata->Alloc(name, idlist);
636 bool CMusicControllerImpl::MediaExistPlaylist(const char *name)
641 return m->pMediadata->ExistPlaylist(name);
645 bool CMusicControllerImpl::MediaDeletePlaylist(int id)
649 return m->pMediadata->Delete(id);
653 bool CMusicControllerImpl::MediaRenamePlaylist(int id, const char *name)
658 return m->pMediadata->Rename(id, name);
662 bool CMusicControllerImpl::MediaAddmediaPlaylist(int id, Eina_List *idlist)
667 return m->pMediadata->Insert(id, idlist);
671 bool CMusicControllerImpl::MediaRemovemediaPlaylist(int id, Eina_List *idlist)
676 return m->pMediadata->Remove(id, idlist);
680 bool CMusicControllerImpl::MediaAddsongsPlaylist(int lid, Eina_List *list)
685 Eina_List *idlist, *l;
691 EINA_LIST_FOREACH(list, l, obj) {
692 sinfo = (CSongInfo *)obj;
695 idlist = eina_list_append(idlist, id);
698 if (!MediaAddmediaPlaylist(lid, idlist)) {
699 _ERR(" Failed to add songs to playlist ");
707 CSongInfo *CMusicControllerImpl::MediaSongByUri(char *uri)
714 sinfo = m->pMediadata->SongByUri(uri);
722 bool CMusicControllerImpl::SetPlayState(EPlayStatus state)
726 m->statePlay = state;
732 EPlayStatus CMusicControllerImpl::PlayState(void)
740 bool CMusicControllerImpl::SetShuffleState(EShuffleStatus state)
744 m->stateShuffle = state;
745 if (state && m->pPlaylist->FlagCreate())
746 m->pPlaylist->UpdateShuffle();
752 EShuffleStatus CMusicControllerImpl::ShuffleState(void)
756 return m->stateShuffle;
760 bool CMusicControllerImpl::SetRepeatState(ERepeatStatus state)
764 m->repeatstate = state;
770 ERepeatStatus CMusicControllerImpl::RepeatState(void)
774 return m->repeatstate;
778 void CMusicControllerImpl::ChangePlayerMode(EPlayerMode mode)
783 IMusicControllerListener *mcListener;
786 EINA_LIST_FOREACH(m->elListener, l, obj) {
787 mcListener = (IMusicControllerListener *)obj;
789 mcListener->OnPlayerModeChanged(mode);
794 void CMusicControllerImpl::HandlePlaylistEditButtons(EPlayerEditBtns btnId)
799 IMusicControllerListener *mcListener;
802 EINA_LIST_FOREACH(m->elListener, l, obj) {
803 mcListener = (IMusicControllerListener *)obj;
805 mcListener->OnEditButtonsPressed(btnId);
810 void CMusicControllerImpl::HandleRemoteButtons(Evas_Object *eoBtn, EPlayerBtnsEvent ev)
815 IMusicControllerListener *mcListener;
818 EINA_LIST_FOREACH(m->elListener, l, obj) {
819 mcListener = (IMusicControllerListener *)obj;
821 mcListener->OnRemoteButtonEvent(eoBtn, ev);
826 void CMusicControllerImpl::OnStatusChanged(SUsbHostDeviceInfo *changedDevice,
827 SUsbHostDeviceStatus status)
833 IMusicControllerListener *mcListener = NULL;;
836 if (status == USB_HOST_DEV_CONNECTED) {
837 if (CInfo::SourceType() == SOURCE_TYPE_USB) {
838 if (!FlagConnected())
839 CInfo::SetSourceType(SOURCE_TYPE_ALL);
842 EINA_LIST_FOREACH(m->elListener, l, obj) {
843 mcListener = (IMusicControllerListener *)obj;
845 mcListener->OnUsbStatusChanged(IMusicControllerListener::USB_STORAGE_CONNECTED);
849 if (CInfo::SourceType() == SOURCE_TYPE_USB) {
850 CInfo::SetSourceType(SOURCE_TYPE_ALL);
853 EINA_LIST_FOREACH(m->elListener, l, obj) {
854 mcListener = (IMusicControllerListener *)obj;
856 mcListener->OnUsbStatusChanged(IMusicControllerListener::USB_STORAGE_DISCONNECTED);
862 void CMusicControllerImpl::t_OnPlayComplete(void)
866 IMusicControllerListener *mcListener = NULL;
869 r = t_PlayNext(DIR_NEXT, E_ON_COMPLETE);
871 _ERR(" music play next song failed ");
873 EINA_LIST_FOREACH(m->elListener, l, obj) {
874 mcListener = (IMusicControllerListener *)obj;
876 mcListener->OnComplete();