diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java index b4262ec7..8b7b2795 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java @@ -20,6 +20,7 @@ package org.moire.ultrasonic.service; import android.content.Context; import android.content.Intent; +import android.os.Handler; import android.util.Log; import org.koin.java.standalone.KoinJavaComponent; @@ -106,7 +107,7 @@ public class DownloadServiceImpl implements DownloadService } @Override - public void restore(List songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist) + public synchronized void restore(List songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist) { download(songs, false, false, false, false, newPlaylist); @@ -318,7 +319,7 @@ public class DownloadServiceImpl implements DownloadService } @Override - public void setRepeatMode(RepeatMode repeatMode) + public synchronized void setRepeatMode(RepeatMode repeatMode) { Util.setRepeatMode(context, repeatMode); MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance(); 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 3b694012..f5f18df4 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Downloader.java @@ -347,7 +347,7 @@ public class Downloader public synchronized void setFirstPlaying() { - if (player.currentPlaying == null) + if (player.currentPlaying == null && downloadList.size() > 0) { player.currentPlaying = downloadList.get(0); player.currentPlaying.setPlaying(true); 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 82b0d7a4..3e2b15f2 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java @@ -8,7 +8,6 @@ import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.media.MediaPlayer; import android.os.Build; import android.os.IBinder; import android.util.Log; @@ -62,9 +61,12 @@ public class MediaPlayerService extends Service public Lazy jukeboxService = inject(JukeboxService.class); private Lazy downloadQueueSerializer = inject(DownloadQueueSerializer.class); - private Lazy shufflePlayBuffer = inject(ShufflePlayBuffer.class); - private Lazy downloader = inject(Downloader.class); - private Lazy player = inject(Player.class); + private Lazy shufflePlayBufferLazy = inject(ShufflePlayBuffer.class); + private Lazy downloaderLazy = inject(Downloader.class); + private Lazy playerLazy = inject(Player.class); + private Player player; + private Downloader downloader; + private ShufflePlayBuffer shufflePlayBuffer; private boolean isInForeground = false; private NotificationCompat.Builder notificationBuilder; @@ -109,21 +111,25 @@ public class MediaPlayerService extends Service { super.onCreate(); - downloader.getValue().onCreate(); - shufflePlayBuffer.getValue().onCreate(); + downloader = downloaderLazy.getValue(); + player = playerLazy.getValue(); + shufflePlayBuffer = shufflePlayBufferLazy.getValue(); - player.getValue().onCreate(); + downloader.onCreate(); + shufflePlayBuffer.onCreate(); + + player.onCreate(); setupOnCurrentPlayingChangedHandler(); setupOnPlayerStateChangedHandler(); setupOnSongCompletedHandler(); - player.getValue().onPrepared = new Runnable() { + player.onPrepared = new Runnable() { @Override public void run() { - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, - downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + downloader.getCurrentPlayingIndex(), getPlayerPosition()); } }; - player.getValue().onNextSongRequested = new Runnable() { + player.onNextSongRequested = new Runnable() { @Override public void run() { setNextPlaying(); @@ -165,9 +171,9 @@ public class MediaPlayerService extends Service try { - player.getValue().onDestroy(); - shufflePlayBuffer.getValue().onDestroy(); - downloader.getValue().onDestroy(); + player.onDestroy(); + shufflePlayBuffer.onDestroy(); + downloader.onDestroy(); } catch (Throwable ignored) { @@ -180,35 +186,35 @@ public class MediaPlayerService extends Service { if (jukeboxService.getValue().isEnabled()) { - jukeboxService.getValue().skip(downloader.getValue().getCurrentPlayingIndex(), position / 1000); + jukeboxService.getValue().skip(downloader.getCurrentPlayingIndex(), position / 1000); } else { - player.getValue().seekTo(position); + player.seekTo(position); } } public synchronized int getPlayerPosition() { - if (player.getValue().playerState == IDLE || player.getValue().playerState == DOWNLOADING || player.getValue().playerState == PREPARING) + if (player.playerState == IDLE || player.playerState == DOWNLOADING || player.playerState == PREPARING) { return 0; } return jukeboxService.getValue().isEnabled() ? jukeboxService.getValue().getPositionSeconds() * 1000 : - player.getValue().getPlayerPosition(); + player.getPlayerPosition(); } public synchronized int getPlayerDuration() { - return player.getValue().getPlayerDuration(); + return player.getPlayerDuration(); } public synchronized void setCurrentPlaying(int currentPlayingIndex) { try { - player.getValue().setCurrentPlaying(downloader.getValue().downloadList.get(currentPlayingIndex)); + player.setCurrentPlaying(downloader.downloadList.get(currentPlayingIndex)); } catch (IndexOutOfBoundsException x) { @@ -218,24 +224,24 @@ public class MediaPlayerService extends Service public void setupOnCurrentPlayingChangedHandler() { - player.getValue().onCurrentPlayingChanged = new Consumer() { + player.onCurrentPlayingChanged = new Consumer() { @Override public void accept(DownloadFile currentPlaying) { if (currentPlaying != null) { Util.broadcastNewTrackInfo(MediaPlayerService.this, currentPlaying.getSong()); Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), currentPlaying, - downloader.getValue().getDownloads().size(), downloader.getValue().getCurrentPlayingIndex() + 1); + downloader.getDownloads().size(), downloader.getCurrentPlayingIndex() + 1); } else { Util.broadcastNewTrackInfo(MediaPlayerService.this, null); Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), null, - downloader.getValue().getDownloads().size(), downloader.getValue().getCurrentPlayingIndex() + 1); + downloader.getDownloads().size(), downloader.getCurrentPlayingIndex() + 1); } // Update widget - PlayerState playerState = player.getValue().playerState; + PlayerState playerState = player.playerState; MusicDirectory.Entry song = currentPlaying == null? null : currentPlaying.getSong(); UltraSonicAppWidgetProvider4x1.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false); UltraSonicAppWidgetProvider4x2.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, true); @@ -247,7 +253,7 @@ public class MediaPlayerService extends Service if (currentPlaying != null) { if (tabInstance != null) { - updateNotification(player.getValue().playerState, currentPlaying); + updateNotification(player.playerState, currentPlaying); tabInstance.showNowPlaying(); } } @@ -257,7 +263,7 @@ public class MediaPlayerService extends Service { tabInstance.hideNowPlaying(); stopForeground(true); - player.getValue().clearRemoteControl(); + player.clearRemoteControl(); isInForeground = false; stopSelf(); } @@ -272,11 +278,11 @@ public class MediaPlayerService extends Service if (!gaplessPlayback) { - player.getValue().setNextPlaying(null); + player.setNextPlaying(null); return; } - int index = downloader.getValue().getCurrentPlayingIndex(); + int index = downloader.getCurrentPlayingIndex(); if (index != -1) { @@ -286,7 +292,7 @@ public class MediaPlayerService extends Service index += 1; break; case ALL: - index = (index + 1) % downloader.getValue().downloadList.size(); + index = (index + 1) % downloader.downloadList.size(); break; case SINGLE: break; @@ -295,29 +301,29 @@ public class MediaPlayerService extends Service } } - player.getValue().clearNextPlaying(); + player.clearNextPlaying(); - if (index < downloader.getValue().downloadList.size() && index != -1) + if (index < downloader.downloadList.size() && index != -1) { - player.getValue().setNextPlaying(downloader.getValue().downloadList.get(index)); + player.setNextPlaying(downloader.downloadList.get(index)); } else { - player.getValue().setNextPlaying(null); + player.setNextPlaying(null); } } public synchronized void togglePlayPause() { - if (player.getValue().playerState == PAUSED || player.getValue().playerState == COMPLETED || player.getValue().playerState == STOPPED) + if (player.playerState == PAUSED || player.playerState == COMPLETED || player.playerState == STOPPED) { start(); } - else if (player.getValue().playerState == IDLE) + else if (player.playerState == IDLE) { play(); } - else if (player.getValue().playerState == STARTED) + else if (player.playerState == STARTED) { pause(); } @@ -328,7 +334,7 @@ public class MediaPlayerService extends Service */ public synchronized void play() { - int current = downloader.getValue().getCurrentPlayingIndex(); + int current = downloader.getCurrentPlayingIndex(); if (current == -1) { play(0); @@ -346,7 +352,8 @@ public class MediaPlayerService extends Service public synchronized void play(int index, boolean start) { - if (index < 0 || index >= downloader.getValue().downloadList.size()) + Log.v(TAG, String.format("play requested for %d", index)); + if (index < 0 || index >= downloader.downloadList.size()) { resetPlayback(); } @@ -357,30 +364,30 @@ public class MediaPlayerService extends Service if (jukeboxService.getValue().isEnabled()) { jukeboxService.getValue().skip(index, 0); - player.getValue().setPlayerState(STARTED); + player.setPlayerState(STARTED); } else { - player.getValue().play(downloader.getValue().downloadList.get(index)); + player.play(downloader.downloadList.get(index)); } } - downloader.getValue().checkDownloads(); + downloader.checkDownloads(); setNextPlaying(); } } private synchronized void resetPlayback() { - player.getValue().reset(); - player.getValue().setCurrentPlaying(null); - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, - downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); + player.reset(); + player.setCurrentPlaying(null); + downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + downloader.getCurrentPlayingIndex(), getPlayerPosition()); } public synchronized void pause() { - if (player.getValue().playerState == STARTED) + if (player.playerState == STARTED) { if (jukeboxService.getValue().isEnabled()) { @@ -388,15 +395,15 @@ public class MediaPlayerService extends Service } else { - player.getValue().pause(); + player.pause(); } - player.getValue().setPlayerState(PAUSED); + player.setPlayerState(PAUSED); } } public synchronized void stop() { - if (player.getValue().playerState == STARTED) + if (player.playerState == STARTED) { if (jukeboxService.getValue().isEnabled()) { @@ -404,10 +411,10 @@ public class MediaPlayerService extends Service } else { - player.getValue().pause(); + player.pause(); } } - player.getValue().setPlayerState(STOPPED); + player.setPlayerState(STOPPED); } public synchronized void start() @@ -418,19 +425,19 @@ public class MediaPlayerService extends Service } else { - player.getValue().start(); + player.start(); } - player.getValue().setPlayerState(STARTED); + player.setPlayerState(STARTED); } public void setupOnPlayerStateChangedHandler() { - player.getValue().onPlayerStateChanged = new BiConsumer() { + player.onPlayerStateChanged = new BiConsumer() { @Override public void accept(PlayerState playerState, DownloadFile currentPlaying) { if (playerState == PAUSED) { - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition()); } boolean showWhenPaused = (playerState != PlayerState.STOPPED && Util.isNotificationAlwaysEnabled(MediaPlayerService.this)); @@ -438,8 +445,8 @@ public class MediaPlayerService extends Service Util.broadcastPlaybackStatusChange(MediaPlayerService.this, playerState); Util.broadcastA2dpPlayStatusChange(MediaPlayerService.this, playerState, currentPlaying.getSong(), - downloader.getValue().downloadList.size() + downloader.getValue().backgroundDownloadList.size(), - downloader.getValue().downloadList.indexOf(currentPlaying) + 1, getPlayerPosition()); + downloader.downloadList.size() + downloader.backgroundDownloadList.size(), + downloader.downloadList.indexOf(currentPlaying) + 1, getPlayerPosition()); MusicDirectory.Entry song = currentPlaying.getSong(); // Update widget @@ -466,7 +473,7 @@ public class MediaPlayerService extends Service if (tabInstance != null) { stopForeground(true); - player.getValue().clearRemoteControl(); + player.clearRemoteControl(); isInForeground = false; tabInstance.hideNowPlaying(); stopSelf(); @@ -487,10 +494,10 @@ public class MediaPlayerService extends Service private void setupOnSongCompletedHandler() { - player.getValue().onSongCompleted = new Consumer() { + player.onSongCompleted = new Consumer() { @Override public void accept(DownloadFile currentPlaying) { - int index = downloader.getValue().getCurrentPlayingIndex(); + int index = downloader.getCurrentPlayingIndex(); if (currentPlaying != null) { @@ -515,7 +522,7 @@ public class MediaPlayerService extends Service switch (getRepeatMode()) { case OFF: - if (index + 1 < 0 || index + 1 >= downloader.getValue().downloadList.size()) + if (index + 1 < 0 || index + 1 >= downloader.downloadList.size()) { if (Util.getShouldClearPlaylist(MediaPlayerService.this)) { @@ -530,7 +537,7 @@ public class MediaPlayerService extends Service play(index + 1); break; case ALL: - play((index + 1) % downloader.getValue().downloadList.size()); + play((index + 1) % downloader.downloadList.size()); break; case SINGLE: play(index); @@ -545,15 +552,15 @@ public class MediaPlayerService extends Service public synchronized void clear(boolean serialize) { - player.getValue().reset(); - downloader.getValue().clear(); - player.getValue().setCurrentPlaying(null); + player.reset(); + downloader.clear(); + player.setCurrentPlaying(null); setNextPlaying(); if (serialize) { - downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, - downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); + downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, + downloader.getCurrentPlayingIndex(), getPlayerPosition()); } } @@ -632,7 +639,6 @@ public class MediaPlayerService extends Service bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album); } - contentView.setTextViewText(R.id.trackname, title); bigView.setTextViewText(R.id.trackname, title); contentView.setTextViewText(R.id.artist, text); diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Player.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Player.java index eb1001a6..def1bb07 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/Player.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/Player.java @@ -117,7 +117,7 @@ public class Player @Override public void run() { - Thread.currentThread().setName("MediaPlayerService"); + Thread.currentThread().setName("MediaPlayerThread"); Looper.prepare(); @@ -270,9 +270,9 @@ public class Player return visualizerController; } - public synchronized void setPlayerState(PlayerState playerState) + public synchronized void setPlayerState(final PlayerState playerState) { - Log.i(TAG, String.format("%s -> %s (%s)", playerState.name(), playerState.name(), currentPlaying)); + Log.i(TAG, String.format("%s -> %s (%s)", this.playerState.name(), playerState.name(), currentPlaying)); this.playerState = playerState; @@ -286,7 +286,14 @@ public class Player updateRemoteControl(); } - onPlayerStateChanged.accept(playerState, currentPlaying); + Handler mainHandler = new Handler(context.getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + onPlayerStateChanged.accept(playerState, currentPlaying); + } + }; + mainHandler.post(myRunnable); if (playerState == STARTED && positionCache == null) { @@ -301,11 +308,20 @@ public class Player } } - public synchronized void setCurrentPlaying(DownloadFile currentPlaying) + public synchronized void setCurrentPlaying(final DownloadFile currentPlaying) { + Log.v(TAG, String.format("setCurrentPlaying %s", currentPlaying)); this.currentPlaying = currentPlaying; updateRemoteControl(); - onCurrentPlayingChanged.accept(currentPlaying); + + Handler mainHandler = new Handler(context.getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + onCurrentPlayingChanged.accept(currentPlaying); + } + }; + mainHandler.post(myRunnable); } public synchronized void setNextPlaying(DownloadFile nextToPlay) @@ -362,7 +378,6 @@ public class Player nextPlayingTask = null; } - updateRemoteControl(); setCurrentPlaying(fileToPlay); bufferAndPlay(); } @@ -375,7 +390,15 @@ public class Player setCurrentPlaying(nextPlaying); setPlayerState(PlayerState.STARTED); setupHandlers(currentPlaying, false); - onNextSongRequested.run(); + + Handler mainHandler = new Handler(context.getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + onNextSongRequested.run(); + } + }; + mainHandler.post(myRunnable); // Proxy should not be being used here since the next player was already setup to play if (proxy != null) @@ -409,7 +432,7 @@ public class Player } } - public void updateRemoteControl() + private void updateRemoteControl() { if (!Util.isLockScreenEnabled(context)) { @@ -488,7 +511,7 @@ public class Player } } - public void setUpRemoteControlClient() + private void setUpRemoteControlClient() { if (!Util.isLockScreenEnabled(context)) return; @@ -705,7 +728,14 @@ public class Player } } - onPrepared.run(); + Handler mainHandler = new Handler(context.getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + onPrepared.run(); + } + }; + mainHandler.post(myRunnable); } }); @@ -838,7 +868,14 @@ public class Player } else { - onSongCompleted.accept(currentPlaying); + Handler mainHandler = new Handler(context.getMainLooper()); + Runnable myRunnable = new Runnable() { + @Override + public void run() { + onSongCompleted.accept(currentPlaying); + } + }; + mainHandler.post(myRunnable); } return;