diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java index 038fa16f..cae4632d 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/BookmarkActivity.java @@ -34,6 +34,7 @@ import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.service.DownloadFile; +import org.moire.ultrasonic.service.MediaPlayerController; import org.moire.ultrasonic.service.MusicService; import org.moire.ultrasonic.service.MusicServiceFactory; import org.moire.ultrasonic.util.Constants; @@ -296,7 +297,8 @@ public class BookmarkActivity extends SubsonicTabActivity private void enableButtons() { - if (getMediaPlayerController() == null) + MediaPlayerController mediaPlayerController = getMediaPlayerController(); + if (mediaPlayerController == null) { return; } @@ -310,7 +312,7 @@ public class BookmarkActivity extends SubsonicTabActivity for (MusicDirectory.Entry song : selection) { - DownloadFile downloadFile = downloader.getValue().getDownloadFileForSong(song); + DownloadFile downloadFile = mediaPlayerController.getDownloadFileForSong(song); if (downloadFile.isWorkDone()) { deleteEnabled = true; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java index f03c005d..80e8e291 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java @@ -293,7 +293,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi @Override protected Boolean doInBackground() throws Throwable { - if (downloader.getValue().getCurrentPlayingIndex() < downloader.getValue().downloadList.size() - 1) + if (getMediaPlayerController().getCurrentPlayingNumberOnPlaylist() < getMediaPlayerController().getPlaylistSize() - 1) { getMediaPlayerController().next(); return true; @@ -567,7 +567,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi final MediaPlayerController mediaPlayerController = getMediaPlayerController(); - if (mediaPlayerController == null || localMediaPlayer.getValue().currentPlaying == null) + if (mediaPlayerController == null || mediaPlayerController.getCurrentPlaying() == null) { playlistFlipper.setDisplayedChild(1); } @@ -632,7 +632,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi } } - final DownloadFile currentDownloading = downloader.getValue().currentDownloading; + final DownloadFile currentDownloading = getMediaPlayerController().getCurrentDownloading(); for (int i = 0; i < count; i++) { if (currentDownloading == playlistView.getItemAtPosition(i)) @@ -782,7 +782,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi if (mediaPlayerController != null) { - DownloadFile downloadFile = localMediaPlayer.getValue().currentPlaying; + DownloadFile downloadFile = mediaPlayerController.getCurrentPlaying(); if (downloadFile != null) { @@ -1019,7 +1019,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi onDownloadListChanged(); return true; case R.id.menu_item_save_playlist: - if (!downloader.getValue().downloadList.isEmpty()) + if (getMediaPlayerController().getPlaylistSize() > 0) { showDialog(DIALOG_SAVE_PLAYLIST); } @@ -1142,7 +1142,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi if (mediaPlayerController != null) { - List downloadServiceSongs = downloader.getValue().downloadList; + List downloadServiceSongs = mediaPlayerController.getPlayList(); if (downloadServiceSongs != null) { @@ -1170,17 +1170,18 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi private void update() { - if (getMediaPlayerController() == null) + MediaPlayerController mediaPlayerController = getMediaPlayerController(); + if (mediaPlayerController == null) { return; } - if (currentRevision != downloader.getValue().getDownloadListUpdateRevision()) + if (currentRevision != mediaPlayerController.getPlayListUpdateRevision()) { onDownloadListChanged(); } - if (currentPlaying != localMediaPlayer.getValue().currentPlaying) + if (currentPlaying != mediaPlayerController.getCurrentPlaying()) { onCurrentChanged(); } @@ -1199,7 +1200,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi protected Void doInBackground() throws Throwable { final List entries = new LinkedList(); - for (final DownloadFile downloadFile : downloader.getValue().downloadList) + for (final DownloadFile downloadFile : getMediaPlayerController().getPlayList()) { entries.add(downloadFile.getSong()); } @@ -1254,7 +1255,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi { warnIfNetworkOrStorageUnavailable(); - final int current = downloader.getValue().getCurrentPlayingIndex(); + final int current = getMediaPlayerController().getCurrentPlayingNumberOnPlaylist(); if (current == -1) { @@ -1275,7 +1276,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi return; } - final List list = downloader.getValue().downloadList; + final List list = mediaPlayerController.getPlayList(); emptyTextView.setText(R.string.download_empty); final SongListAdapter adapter = new SongListAdapter(this, list); @@ -1313,7 +1314,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi return; } - DownloadFile currentPlaying = localMediaPlayer.getValue().currentPlaying; + DownloadFile currentPlaying = mediaPlayerController.getCurrentPlaying(); if (currentPlaying == item) { @@ -1333,7 +1334,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi }); emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE); - currentRevision = downloader.getValue().getDownloadListUpdateRevision(); + currentRevision = mediaPlayerController.getPlayListUpdateRevision(); switch (mediaPlayerController.getRepeatMode()) { @@ -1360,13 +1361,13 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi return; } - currentPlaying = localMediaPlayer.getValue().currentPlaying; + currentPlaying = mediaPlayerController.getCurrentPlaying(); scrollToCurrent(); - long totalDuration = downloader.getValue().getDownloadListDuration(); - long totalSongs = downloader.getValue().downloadList.size(); - int currentSongIndex = downloader.getValue().getCurrentPlayingIndex() + 1; + long totalDuration = mediaPlayerController.getPlayListDuration(); + long totalSongs = mediaPlayerController.getPlaylistSize(); + int currentSongIndex = mediaPlayerController.getCurrentPlayingNumberOnPlaylist() + 1; String duration = Util.formatTotalDuration(totalDuration); @@ -1580,7 +1581,7 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi if (e1X - e2X > swipeDistance && absX > swipeVelocity) { warnIfNetworkOrStorageUnavailable(); - if (downloader.getValue().getCurrentPlayingIndex() < downloader.getValue().downloadList.size() - 1) + if (mediaPlayerController.getCurrentPlayingNumberOnPlaylist() < mediaPlayerController.getPlaylistSize() - 1) { mediaPlayerController.next(); onCurrentChanged(); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SearchActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SearchActivity.java index 113449eb..88b7a70a 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SearchActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SearchActivity.java @@ -520,7 +520,7 @@ public class SearchActivity extends SubsonicTabActivity if (autoplay) { - mediaPlayerController.play(downloader.getValue().downloadList.size() - 1); + mediaPlayerController.play(mediaPlayerController.getPlaylistSize() - 1); } Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1)); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java index 9b13b225..a96159a2 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SelectAlbumActivity.java @@ -40,6 +40,7 @@ import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.Share; import org.moire.ultrasonic.service.DownloadFile; +import org.moire.ultrasonic.service.MediaPlayerController; import org.moire.ultrasonic.service.MusicService; import org.moire.ultrasonic.service.MusicServiceFactory; import org.moire.ultrasonic.util.AlbumHeader; @@ -1010,7 +1011,8 @@ public class SelectAlbumActivity extends SubsonicTabActivity private void enableButtons() { - if (getMediaPlayerController() == null) + MediaPlayerController mediaPlayerController = getMediaPlayerController(); + if (mediaPlayerController == null) { return; } @@ -1024,7 +1026,7 @@ public class SelectAlbumActivity extends SubsonicTabActivity for (MusicDirectory.Entry song : selection) { - DownloadFile downloadFile = downloader.getValue().getDownloadFileForSong(song); + DownloadFile downloadFile = mediaPlayerController.getDownloadFileForSong(song); if (downloadFile.isWorkDone()) { deleteEnabled = true; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java index 3a6b5279..06d10d70 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/SubsonicTabActivity.java @@ -78,9 +78,6 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen private Lazy mediaPlayerControllerLazy = inject(MediaPlayerController.class); private Lazy lifecycleSupport = inject(MediaPlayerLifecycleSupport.class); - protected Lazy downloader = inject(Downloader.class); - protected Lazy localMediaPlayer = inject(LocalMediaPlayer.class); - public MenuDrawer menuDrawer; private int activePosition = 1; @@ -269,7 +266,7 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen if (playerState.equals(PlayerState.PAUSED) || playerState.equals(PlayerState.STARTED)) { - DownloadFile file = localMediaPlayer.getValue().currentPlaying; + DownloadFile file = mediaPlayerControllerLazy.getValue().getCurrentPlaying(); if (file != null) { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java index 0fe2a691..9bc2ad66 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/receiver/A2dpIntentReceiver.java @@ -6,8 +6,6 @@ import android.content.Intent; import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.service.MediaPlayerController; -import org.moire.ultrasonic.service.Downloader; -import org.moire.ultrasonic.service.LocalMediaPlayer; import kotlin.Lazy; @@ -17,18 +15,16 @@ public class A2dpIntentReceiver extends BroadcastReceiver { private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse"; private Lazy mediaPlayerControllerLazy = inject(MediaPlayerController.class); - private Lazy downloader = inject(Downloader.class); - protected Lazy localMediaPlayer = inject(LocalMediaPlayer.class); @Override public void onReceive(Context context, Intent intent) { - if (localMediaPlayer.getValue().currentPlaying == null) + if (mediaPlayerControllerLazy.getValue().getCurrentPlaying() == null) { return; } - Entry song = localMediaPlayer.getValue().currentPlaying.getSong(); + Entry song = mediaPlayerControllerLazy.getValue().getCurrentPlaying().getSong(); if (song == null) { @@ -39,7 +35,7 @@ public class A2dpIntentReceiver extends BroadcastReceiver Integer duration = song.getDuration(); int playerPosition = mediaPlayerControllerLazy.getValue().getPlayerPosition(); - int listSize = downloader.getValue().getDownloads().size(); + int listSize = mediaPlayerControllerLazy.getValue().getPlaylistSize(); if (duration != null) { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/BiConsumer.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/BiConsumer.java index 537ef5f4..8909762e 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/BiConsumer.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/BiConsumer.java @@ -1,5 +1,10 @@ package org.moire.ultrasonic.service; +/** + * Abstract class for consumers with two parameters + * @param The type of the first object to consume + * @param The type of the second object to consume + */ public abstract class BiConsumer { public abstract void accept(T t, U u); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Consumer.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Consumer.java index 4fd5c473..d2b09de7 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Consumer.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Consumer.java @@ -1,5 +1,9 @@ package org.moire.ultrasonic.service; +/** + * Abstract class for consumers with one parameter + * @param The type of the object to consume + */ public abstract class Consumer { public abstract void accept(T t); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadFile.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadFile.java index 2d0c7b90..4bfa4277 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadFile.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadFile.java @@ -24,6 +24,7 @@ import android.os.PowerManager; import android.text.TextUtils; import android.util.Log; +import org.jetbrains.annotations.NotNull; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.util.CacheCleaner; import org.moire.ultrasonic.util.CancellableTask; @@ -51,7 +52,6 @@ import static org.koin.java.standalone.KoinJavaComponent.inject; */ public class DownloadFile { - private static final String TAG = DownloadFile.class.getSimpleName(); private final Context context; private final MusicDirectory.Entry song; @@ -70,7 +70,6 @@ public class DownloadFile private Lazy downloader = inject(Downloader.class); - public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) { super(); @@ -287,6 +286,7 @@ public class DownloadFile this.isPlaying = isPlaying; } + @NotNull @Override public String toString() { @@ -309,7 +309,7 @@ public class DownloadFile { PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE); wakeLock = pm.newWakeLock(SCREEN_DIM_WAKE_LOCK | ON_AFTER_RELEASE, toString()); - wakeLock.acquire(); + wakeLock.acquire(10*60*1000L /*10 minutes*/); Log.i(TAG, String.format("Acquired wake lock %s", wakeLock)); } @@ -450,6 +450,7 @@ public class DownloadFile } } + @NotNull @Override public String toString() { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadQueueSerializer.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadQueueSerializer.java index 570ab067..3fe70765 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadQueueSerializer.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadQueueSerializer.java @@ -11,6 +11,11 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +/** + * This class is responsible for the serialization / deserialization + * of the DownloadQueue (playlist) to the filesystem. + * It also serializes the player state e.g. current playing number and play position. + */ public class DownloadQueueSerializer { private static final String TAG = DownloadQueueSerializer.class.getSimpleName(); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java index dd22283e..bc7449fa 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java @@ -22,6 +22,10 @@ import static org.koin.java.standalone.KoinJavaComponent.inject; import static org.moire.ultrasonic.domain.PlayerState.DOWNLOADING; import static org.moire.ultrasonic.domain.PlayerState.STARTED; +/** + * This class is responsible for maintaining the playlist and downloading + * its items from the network to the filesystem. + */ public class Downloader { private static final String TAG = Downloader.class.getSimpleName(); @@ -85,7 +89,7 @@ public class Downloader Log.i(TAG, "Downloader destroyed"); } - protected synchronized void checkDownloads() + public synchronized void checkDownloads() { if (!Util.isExternalStoragePresent() || !externalStorageMonitor.isExternalStorageAvailable()) { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/ExternalStorageMonitor.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/ExternalStorageMonitor.java index 489eb39b..390eb56b 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/ExternalStorageMonitor.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/ExternalStorageMonitor.java @@ -6,6 +6,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.util.Log; +/** + * Monitors the state of the mobile's external storage + */ public class ExternalStorageMonitor { private static final String TAG = ExternalStorageMonitor.class.getSimpleName(); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java index 02659e46..c00b3d2e 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/LocalMediaPlayer.java @@ -43,6 +43,9 @@ import static org.moire.ultrasonic.domain.PlayerState.PREPARED; import static org.moire.ultrasonic.domain.PlayerState.PREPARING; import static org.moire.ultrasonic.domain.PlayerState.STARTED; +/** + * Represents a Media Player which uses the mobile's resources for playback + */ public class LocalMediaPlayer { private static final String TAG = LocalMediaPlayer.class.getSimpleName(); @@ -59,6 +62,7 @@ public class LocalMediaPlayer public PlayerState playerState = IDLE; public DownloadFile currentPlaying; public DownloadFile nextPlaying; + private PlayerState nextPlayerState = IDLE; private boolean nextSetup; private CancellableTask nextPlayingTask; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerController.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerController.java index 19f15d80..ad6eb2e0 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerController.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerController.java @@ -27,12 +27,14 @@ import org.moire.ultrasonic.domain.RepeatMode; import java.util.List; /** + * This interface contains all functions which are necessary for the Application UI + * to control the Media Player implementation. + * * @author Sindre Mehus * @version $Id$ */ public interface MediaPlayerController { - void download(List songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle, boolean newPlaylist); void downloadBackground(List songs, boolean save); @@ -114,4 +116,20 @@ public interface MediaPlayerController void updateNotification(); void setSongRating(final int rating); + + DownloadFile getCurrentPlaying(); + + int getPlaylistSize(); + + int getCurrentPlayingNumberOnPlaylist(); + + DownloadFile getCurrentDownloading(); + + List getPlayList(); + + long getPlayListUpdateRevision(); + + long getPlayListDuration(); + + DownloadFile getDownloadFileForSong(Entry song); } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java index 15813a2e..4b71ac4b 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerControllerImpl.java @@ -43,6 +43,10 @@ import kotlin.Lazy; import static org.koin.java.standalone.KoinJavaComponent.inject; /** + * The implementation of the Media Player Controller. + * This class contains everything that is necessary for the Application UI + * to control the Media Player implementation. + * * @author Sindre Mehus, Joshua Bahnsen * @version $Id$ */ @@ -58,21 +62,24 @@ public class MediaPlayerControllerImpl implements MediaPlayerController private Context context; private Lazy jukeboxMediaPlayer = inject(JukeboxMediaPlayer.class); - private Lazy downloadQueueSerializer = inject(DownloadQueueSerializer.class); - private Lazy externalStorageMonitor = inject(ExternalStorageMonitor.class); + private final DownloadQueueSerializer downloadQueueSerializer; + private final ExternalStorageMonitor externalStorageMonitor; private final Downloader downloader; private final ShufflePlayBuffer shufflePlayBuffer; private final LocalMediaPlayer localMediaPlayer; - public MediaPlayerControllerImpl(Context context, Downloader downloader, ShufflePlayBuffer shufflePlayBuffer, - LocalMediaPlayer localMediaPlayer) + public MediaPlayerControllerImpl(Context context, DownloadQueueSerializer downloadQueueSerializer, + ExternalStorageMonitor externalStorageMonitor, Downloader downloader, + ShufflePlayBuffer shufflePlayBuffer, LocalMediaPlayer localMediaPlayer) { this.context = context; + this.downloadQueueSerializer = downloadQueueSerializer; + this.externalStorageMonitor = externalStorageMonitor; this.downloader = downloader; this.shufflePlayBuffer = shufflePlayBuffer; this.localMediaPlayer = localMediaPlayer; - externalStorageMonitor.getValue().onCreate(new Runnable() { + this.externalStorageMonitor.onCreate(new Runnable() { @Override public void run() { reset(); @@ -87,7 +94,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController public void onDestroy() { - externalStorageMonitor.getValue().onDestroy(); + externalStorageMonitor.onDestroy(); context.stopService(new Intent(context, MediaPlayerService.class)); Log.i(TAG, "MediaPlayerControllerImpl destroyed"); } @@ -235,14 +242,14 @@ public class MediaPlayerControllerImpl implements MediaPlayerController downloader.checkDownloads(); } - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } @Override public synchronized void downloadBackground(List songs, boolean save) { downloader.downloadBackground(songs, save); - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } public synchronized void setCurrentPlaying(DownloadFile currentPlaying) @@ -291,7 +298,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController { downloader.shuffle(); - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); jukeboxMediaPlayer.getValue().updatePlaylist(); MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance(); @@ -365,7 +372,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController } } - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); jukeboxMediaPlayer.getValue().updatePlaylist(); } @@ -380,7 +387,7 @@ public class MediaPlayerControllerImpl implements MediaPlayerController downloader.removeDownloadFile(downloadFile); - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); jukeboxMediaPlayer.getValue().updatePlaylist(); if (downloadFile == localMediaPlayer.nextPlaying) @@ -597,4 +604,44 @@ public class MediaPlayerControllerImpl implements MediaPlayerController updateNotification(); } + + @Override + public DownloadFile getCurrentPlaying() { + return localMediaPlayer.currentPlaying; + } + + @Override + public int getPlaylistSize() { + return downloader.downloadList.size(); + } + + @Override + public int getCurrentPlayingNumberOnPlaylist() { + return downloader.getCurrentPlayingIndex(); + } + + @Override + public DownloadFile getCurrentDownloading() { + return downloader.currentDownloading; + } + + @Override + public List getPlayList() { + return downloader.downloadList; + } + + @Override + public long getPlayListUpdateRevision() { + return downloader.getDownloadListUpdateRevision(); + } + + @Override + public long getPlayListDuration() { + return downloader.getDownloadListDuration(); + } + + @Override + public DownloadFile getDownloadFileForSong(Entry song) { + return downloader.getDownloadFileForSong(song); + } } \ No newline at end of file diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java index 15663aa6..f34c06b3 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerLifecycleSupport.java @@ -35,26 +35,26 @@ import org.moire.ultrasonic.util.CacheCleaner; import org.moire.ultrasonic.util.Constants; import org.moire.ultrasonic.util.Util; -import kotlin.Lazy; - -import static org.koin.java.standalone.KoinJavaComponent.inject; - /** + * This class is responsible for handling received events for the Media Player implementation + * * @author Sindre Mehus */ public class MediaPlayerLifecycleSupport { private static final String TAG = MediaPlayerLifecycleSupport.class.getSimpleName(); - private Lazy downloadQueueSerializer = inject(DownloadQueueSerializer.class); + private DownloadQueueSerializer downloadQueueSerializer; // From DI private final MediaPlayerControllerImpl mediaPlayerController; // From DI private final Downloader downloader; // From DI private Context context; private BroadcastReceiver headsetEventReceiver; - public MediaPlayerLifecycleSupport(Context context, final MediaPlayerControllerImpl mediaPlayerController, final Downloader downloader) + public MediaPlayerLifecycleSupport(Context context, DownloadQueueSerializer downloadQueueSerializer, + final MediaPlayerControllerImpl mediaPlayerController, final Downloader downloader) { + this.downloadQueueSerializer = downloadQueueSerializer; this.mediaPlayerController = mediaPlayerController; this.context = context; this.downloader = downloader; @@ -75,14 +75,14 @@ public class MediaPlayerLifecycleSupport commandFilter.addAction(Constants.CMD_PROCESS_KEYCODE); context.registerReceiver(intentReceiver, commandFilter); - downloadQueueSerializer.getValue().deserializeDownloadQueue(new Consumer() { + this.downloadQueueSerializer.deserializeDownloadQueue(new Consumer() { @Override public void accept(State state) { // TODO: here the autoPlay = false creates problems when Ultrasonic is started by a Play MediaButton as the player won't start this way. mediaPlayerController.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition, false, false); // Work-around: Serialize again, as the restore() method creates a serialization without current playing info. - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + MediaPlayerLifecycleSupport.this.downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), mediaPlayerController.getPlayerPosition()); } }); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java index a1622a31..c5c26d67 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java @@ -47,6 +47,10 @@ import static org.moire.ultrasonic.domain.PlayerState.PREPARING; import static org.moire.ultrasonic.domain.PlayerState.STARTED; import static org.moire.ultrasonic.domain.PlayerState.STOPPED; +/** + * Android Foreground Service for playing music + * while the rest of the Ultrasonic App is in the background. + */ public class MediaPlayerService extends Service { private static final String TAG = MediaPlayerService.class.getSimpleName(); @@ -61,13 +65,14 @@ public class MediaPlayerService extends Service private final Scrobbler scrobbler = new Scrobbler(); public Lazy jukeboxMediaPlayer = inject(JukeboxMediaPlayer.class); - private Lazy downloadQueueSerializer = inject(DownloadQueueSerializer.class); + private Lazy downloadQueueSerializerLazy = inject(DownloadQueueSerializer.class); private Lazy shufflePlayBufferLazy = inject(ShufflePlayBuffer.class); private Lazy downloaderLazy = inject(Downloader.class); private Lazy localMediaPlayerLazy = inject(LocalMediaPlayer.class); private LocalMediaPlayer localMediaPlayer; private Downloader downloader; private ShufflePlayBuffer shufflePlayBuffer; + private DownloadQueueSerializer downloadQueueSerializer; private boolean isInForeground = false; private NotificationCompat.Builder notificationBuilder; @@ -129,6 +134,7 @@ public class MediaPlayerService extends Service downloader = downloaderLazy.getValue(); localMediaPlayer = localMediaPlayerLazy.getValue(); shufflePlayBuffer = shufflePlayBufferLazy.getValue(); + downloadQueueSerializer = downloadQueueSerializerLazy.getValue(); downloader.onCreate(); shufflePlayBuffer.onCreate(); @@ -140,7 +146,7 @@ public class MediaPlayerService extends Service localMediaPlayer.onPrepared = new Runnable() { @Override public void run() { - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } }; @@ -401,7 +407,7 @@ public class MediaPlayerService extends Service { localMediaPlayer.reset(); localMediaPlayer.setCurrentPlaying(null); - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } @@ -457,7 +463,7 @@ public class MediaPlayerService extends Service public void accept(PlayerState playerState, DownloadFile currentPlaying) { if (playerState == PAUSED) { - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } boolean showWhenPaused = (playerState != PlayerState.STOPPED && Util.isNotificationAlwaysEnabled(MediaPlayerService.this)); @@ -579,7 +585,7 @@ public class MediaPlayerService extends Service setNextPlaying(); if (serialize) { - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + downloadQueueSerializer.serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/State.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/State.java index b0c19e90..60c282c9 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/State.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/State.java @@ -6,6 +6,9 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +/** + * Represents the state of the Media Player implementation + */ public class State implements Serializable { public static final long serialVersionUID = -6346438781062572270L; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Supplier.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Supplier.java index 9a4a072c..67ebea09 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Supplier.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Supplier.java @@ -1,5 +1,9 @@ package org.moire.ultrasonic.service; +/** + * Abstract class for supplying items to a consumer + * @param The type of the item supplied + */ public abstract class Supplier { public abstract T get(); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java index cc6a83a1..830eb882 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/CacheCleaner.java @@ -27,6 +27,10 @@ import static org.koin.java.standalone.KoinJavaComponent.inject; * @author Sindre Mehus * @version $Id$ */ + +/** + * Responsible for cleaning up files from the offline download cache on the filesystem + */ public class CacheCleaner { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java b/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java index 973bf91e..b12b438a 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java @@ -37,10 +37,9 @@ import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.featureflags.Feature; import org.moire.ultrasonic.featureflags.FeatureStorage; import org.moire.ultrasonic.service.DownloadFile; -import org.moire.ultrasonic.service.Downloader; +import org.moire.ultrasonic.service.MediaPlayerController; import org.moire.ultrasonic.service.MusicService; import org.moire.ultrasonic.service.MusicServiceFactory; -import org.moire.ultrasonic.service.LocalMediaPlayer; import org.moire.ultrasonic.util.Util; import org.moire.ultrasonic.util.VideoPlayerType; @@ -82,8 +81,7 @@ public class SongView extends UpdateView implements Checkable private boolean maximized = false; private boolean useFiveStarRating; - private Lazy downloader = inject(Downloader.class); - protected Lazy localMediaPlayer = inject(LocalMediaPlayer.class); + private Lazy mediaPlayerControllerLazy = inject(MediaPlayerController.class); public SongView(Context context) { @@ -170,7 +168,7 @@ public class SongView extends UpdateView implements Checkable this.song = song; - this.downloadFile = downloader.getValue().getDownloadFileForSong(song); + this.downloadFile = mediaPlayerControllerLazy.getValue().getDownloadFileForSong(song); StringBuilder artist = new StringBuilder(60); @@ -321,7 +319,7 @@ public class SongView extends UpdateView implements Checkable { updateBackground(); - downloadFile = downloader.getValue().getDownloadFileForSong(this.song); + downloadFile = mediaPlayerControllerLazy.getValue().getDownloadFileForSong(this.song); File partialFile = downloadFile.getPartialFile(); if (downloadFile.isWorkDone()) @@ -411,7 +409,7 @@ public class SongView extends UpdateView implements Checkable viewHolder.fiveStar4.setImageDrawable(rating > 3 ? starDrawable : starHollowDrawable); viewHolder.fiveStar5.setImageDrawable(rating > 4 ? starDrawable : starHollowDrawable); - boolean playing = localMediaPlayer.getValue().currentPlaying == downloadFile; + boolean playing = mediaPlayerControllerLazy.getValue().getCurrentPlaying() == downloadFile; if (playing) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt index 64ae896e..c13d5ad3 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/di/MusicServiceModule.kt @@ -113,13 +113,15 @@ val musicServiceModule = module(MUSIC_SERVICE_CONTEXT) { single { SubsonicImageLoader(getProperty(DiProperties.APP_CONTEXT), get()) } - single { MediaPlayerControllerImpl(androidContext(), get(), get(), get()) } - single { MediaPlayerControllerImpl(androidContext(), get(), get(), get()) } + single { MediaPlayerControllerImpl(androidContext(), get(), get(), get(), get(), get()) } single { JukeboxMediaPlayer(androidContext(), get()) } - single { MediaPlayerLifecycleSupport(androidContext(), get(), get()) } + single { MediaPlayerLifecycleSupport(androidContext(), get(), get(), get()) } single { DownloadQueueSerializer(androidContext()) } single { ExternalStorageMonitor(androidContext()) } single { ShufflePlayBuffer(androidContext()) } single { Downloader(androidContext(), get(), get(), get()) } single { LocalMediaPlayer(androidContext()) } + + // TODO: Ideally this can be cleaned up when all circular references are removed. + single { MediaPlayerControllerImpl(androidContext(), get(), get(), get(), get(), get()) } }