Fixed player threading, other minor fixes

This commit is contained in:
Nite 2020-06-25 11:58:09 +02:00
parent c3be251e8b
commit 8c60e09914
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
4 changed files with 127 additions and 83 deletions

View File

@ -20,6 +20,7 @@ package org.moire.ultrasonic.service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler;
import android.util.Log; import android.util.Log;
import org.koin.java.standalone.KoinJavaComponent; import org.koin.java.standalone.KoinJavaComponent;
@ -106,7 +107,7 @@ public class DownloadServiceImpl implements DownloadService
} }
@Override @Override
public void restore(List<MusicDirectory.Entry> songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist) public synchronized void restore(List<MusicDirectory.Entry> songs, final int currentPlayingIndex, final int currentPlayingPosition, final boolean autoPlay, boolean newPlaylist)
{ {
download(songs, false, false, false, false, newPlaylist); download(songs, false, false, false, false, newPlaylist);
@ -318,7 +319,7 @@ public class DownloadServiceImpl implements DownloadService
} }
@Override @Override
public void setRepeatMode(RepeatMode repeatMode) public synchronized void setRepeatMode(RepeatMode repeatMode)
{ {
Util.setRepeatMode(context, repeatMode); Util.setRepeatMode(context, repeatMode);
MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance(); MediaPlayerService mediaPlayerService = MediaPlayerService.getRunningInstance();

View File

@ -347,7 +347,7 @@ public class Downloader
public synchronized void setFirstPlaying() public synchronized void setFirstPlaying()
{ {
if (player.currentPlaying == null) if (player.currentPlaying == null && downloadList.size() > 0)
{ {
player.currentPlaying = downloadList.get(0); player.currentPlaying = downloadList.get(0);
player.currentPlaying.setPlaying(true); player.currentPlaying.setPlaying(true);

View File

@ -8,7 +8,6 @@ import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.util.Log; import android.util.Log;
@ -62,9 +61,12 @@ public class MediaPlayerService extends Service
public Lazy<JukeboxService> jukeboxService = inject(JukeboxService.class); public Lazy<JukeboxService> jukeboxService = inject(JukeboxService.class);
private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class); private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class);
private Lazy<ShufflePlayBuffer> shufflePlayBuffer = inject(ShufflePlayBuffer.class); private Lazy<ShufflePlayBuffer> shufflePlayBufferLazy = inject(ShufflePlayBuffer.class);
private Lazy<Downloader> downloader = inject(Downloader.class); private Lazy<Downloader> downloaderLazy = inject(Downloader.class);
private Lazy<Player> player = inject(Player.class); private Lazy<Player> playerLazy = inject(Player.class);
private Player player;
private Downloader downloader;
private ShufflePlayBuffer shufflePlayBuffer;
private boolean isInForeground = false; private boolean isInForeground = false;
private NotificationCompat.Builder notificationBuilder; private NotificationCompat.Builder notificationBuilder;
@ -109,21 +111,25 @@ public class MediaPlayerService extends Service
{ {
super.onCreate(); super.onCreate();
downloader.getValue().onCreate(); downloader = downloaderLazy.getValue();
shufflePlayBuffer.getValue().onCreate(); player = playerLazy.getValue();
shufflePlayBuffer = shufflePlayBufferLazy.getValue();
player.getValue().onCreate(); downloader.onCreate();
shufflePlayBuffer.onCreate();
player.onCreate();
setupOnCurrentPlayingChangedHandler(); setupOnCurrentPlayingChangedHandler();
setupOnPlayerStateChangedHandler(); setupOnPlayerStateChangedHandler();
setupOnSongCompletedHandler(); setupOnSongCompletedHandler();
player.getValue().onPrepared = new Runnable() { player.onPrepared = new Runnable() {
@Override @Override
public void run() { public void run() {
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); downloader.getCurrentPlayingIndex(), getPlayerPosition());
} }
}; };
player.getValue().onNextSongRequested = new Runnable() { player.onNextSongRequested = new Runnable() {
@Override @Override
public void run() { public void run() {
setNextPlaying(); setNextPlaying();
@ -165,9 +171,9 @@ public class MediaPlayerService extends Service
try try
{ {
player.getValue().onDestroy(); player.onDestroy();
shufflePlayBuffer.getValue().onDestroy(); shufflePlayBuffer.onDestroy();
downloader.getValue().onDestroy(); downloader.onDestroy();
} }
catch (Throwable ignored) catch (Throwable ignored)
{ {
@ -180,35 +186,35 @@ public class MediaPlayerService extends Service
{ {
if (jukeboxService.getValue().isEnabled()) if (jukeboxService.getValue().isEnabled())
{ {
jukeboxService.getValue().skip(downloader.getValue().getCurrentPlayingIndex(), position / 1000); jukeboxService.getValue().skip(downloader.getCurrentPlayingIndex(), position / 1000);
} }
else else
{ {
player.getValue().seekTo(position); player.seekTo(position);
} }
} }
public synchronized int getPlayerPosition() 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 0;
} }
return jukeboxService.getValue().isEnabled() ? jukeboxService.getValue().getPositionSeconds() * 1000 : return jukeboxService.getValue().isEnabled() ? jukeboxService.getValue().getPositionSeconds() * 1000 :
player.getValue().getPlayerPosition(); player.getPlayerPosition();
} }
public synchronized int getPlayerDuration() public synchronized int getPlayerDuration()
{ {
return player.getValue().getPlayerDuration(); return player.getPlayerDuration();
} }
public synchronized void setCurrentPlaying(int currentPlayingIndex) public synchronized void setCurrentPlaying(int currentPlayingIndex)
{ {
try try
{ {
player.getValue().setCurrentPlaying(downloader.getValue().downloadList.get(currentPlayingIndex)); player.setCurrentPlaying(downloader.downloadList.get(currentPlayingIndex));
} }
catch (IndexOutOfBoundsException x) catch (IndexOutOfBoundsException x)
{ {
@ -218,24 +224,24 @@ public class MediaPlayerService extends Service
public void setupOnCurrentPlayingChangedHandler() public void setupOnCurrentPlayingChangedHandler()
{ {
player.getValue().onCurrentPlayingChanged = new Consumer<DownloadFile>() { player.onCurrentPlayingChanged = new Consumer<DownloadFile>() {
@Override @Override
public void accept(DownloadFile currentPlaying) { public void accept(DownloadFile currentPlaying) {
if (currentPlaying != null) if (currentPlaying != null)
{ {
Util.broadcastNewTrackInfo(MediaPlayerService.this, currentPlaying.getSong()); Util.broadcastNewTrackInfo(MediaPlayerService.this, currentPlaying.getSong());
Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), currentPlaying, Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), currentPlaying,
downloader.getValue().getDownloads().size(), downloader.getValue().getCurrentPlayingIndex() + 1); downloader.getDownloads().size(), downloader.getCurrentPlayingIndex() + 1);
} }
else else
{ {
Util.broadcastNewTrackInfo(MediaPlayerService.this, null); Util.broadcastNewTrackInfo(MediaPlayerService.this, null);
Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), null, Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), null,
downloader.getValue().getDownloads().size(), downloader.getValue().getCurrentPlayingIndex() + 1); downloader.getDownloads().size(), downloader.getCurrentPlayingIndex() + 1);
} }
// Update widget // Update widget
PlayerState playerState = player.getValue().playerState; PlayerState playerState = player.playerState;
MusicDirectory.Entry song = currentPlaying == null? null : currentPlaying.getSong(); MusicDirectory.Entry song = currentPlaying == null? null : currentPlaying.getSong();
UltraSonicAppWidgetProvider4x1.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false); UltraSonicAppWidgetProvider4x1.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
UltraSonicAppWidgetProvider4x2.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, true); UltraSonicAppWidgetProvider4x2.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, true);
@ -247,7 +253,7 @@ public class MediaPlayerService extends Service
if (currentPlaying != null) if (currentPlaying != null)
{ {
if (tabInstance != null) { if (tabInstance != null) {
updateNotification(player.getValue().playerState, currentPlaying); updateNotification(player.playerState, currentPlaying);
tabInstance.showNowPlaying(); tabInstance.showNowPlaying();
} }
} }
@ -257,7 +263,7 @@ public class MediaPlayerService extends Service
{ {
tabInstance.hideNowPlaying(); tabInstance.hideNowPlaying();
stopForeground(true); stopForeground(true);
player.getValue().clearRemoteControl(); player.clearRemoteControl();
isInForeground = false; isInForeground = false;
stopSelf(); stopSelf();
} }
@ -272,11 +278,11 @@ public class MediaPlayerService extends Service
if (!gaplessPlayback) if (!gaplessPlayback)
{ {
player.getValue().setNextPlaying(null); player.setNextPlaying(null);
return; return;
} }
int index = downloader.getValue().getCurrentPlayingIndex(); int index = downloader.getCurrentPlayingIndex();
if (index != -1) if (index != -1)
{ {
@ -286,7 +292,7 @@ public class MediaPlayerService extends Service
index += 1; index += 1;
break; break;
case ALL: case ALL:
index = (index + 1) % downloader.getValue().downloadList.size(); index = (index + 1) % downloader.downloadList.size();
break; break;
case SINGLE: case SINGLE:
break; 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 else
{ {
player.getValue().setNextPlaying(null); player.setNextPlaying(null);
} }
} }
public synchronized void togglePlayPause() 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(); start();
} }
else if (player.getValue().playerState == IDLE) else if (player.playerState == IDLE)
{ {
play(); play();
} }
else if (player.getValue().playerState == STARTED) else if (player.playerState == STARTED)
{ {
pause(); pause();
} }
@ -328,7 +334,7 @@ public class MediaPlayerService extends Service
*/ */
public synchronized void play() public synchronized void play()
{ {
int current = downloader.getValue().getCurrentPlayingIndex(); int current = downloader.getCurrentPlayingIndex();
if (current == -1) if (current == -1)
{ {
play(0); play(0);
@ -346,7 +352,8 @@ public class MediaPlayerService extends Service
public synchronized void play(int index, boolean start) 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(); resetPlayback();
} }
@ -357,30 +364,30 @@ public class MediaPlayerService extends Service
if (jukeboxService.getValue().isEnabled()) if (jukeboxService.getValue().isEnabled())
{ {
jukeboxService.getValue().skip(index, 0); jukeboxService.getValue().skip(index, 0);
player.getValue().setPlayerState(STARTED); player.setPlayerState(STARTED);
} }
else else
{ {
player.getValue().play(downloader.getValue().downloadList.get(index)); player.play(downloader.downloadList.get(index));
} }
} }
downloader.getValue().checkDownloads(); downloader.checkDownloads();
setNextPlaying(); setNextPlaying();
} }
} }
private synchronized void resetPlayback() private synchronized void resetPlayback()
{ {
player.getValue().reset(); player.reset();
player.getValue().setCurrentPlaying(null); player.setCurrentPlaying(null);
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); downloader.getCurrentPlayingIndex(), getPlayerPosition());
} }
public synchronized void pause() public synchronized void pause()
{ {
if (player.getValue().playerState == STARTED) if (player.playerState == STARTED)
{ {
if (jukeboxService.getValue().isEnabled()) if (jukeboxService.getValue().isEnabled())
{ {
@ -388,15 +395,15 @@ public class MediaPlayerService extends Service
} }
else else
{ {
player.getValue().pause(); player.pause();
} }
player.getValue().setPlayerState(PAUSED); player.setPlayerState(PAUSED);
} }
} }
public synchronized void stop() public synchronized void stop()
{ {
if (player.getValue().playerState == STARTED) if (player.playerState == STARTED)
{ {
if (jukeboxService.getValue().isEnabled()) if (jukeboxService.getValue().isEnabled())
{ {
@ -404,10 +411,10 @@ public class MediaPlayerService extends Service
} }
else else
{ {
player.getValue().pause(); player.pause();
} }
} }
player.getValue().setPlayerState(STOPPED); player.setPlayerState(STOPPED);
} }
public synchronized void start() public synchronized void start()
@ -418,19 +425,19 @@ public class MediaPlayerService extends Service
} }
else else
{ {
player.getValue().start(); player.start();
} }
player.getValue().setPlayerState(STARTED); player.setPlayerState(STARTED);
} }
public void setupOnPlayerStateChangedHandler() public void setupOnPlayerStateChangedHandler()
{ {
player.getValue().onPlayerStateChanged = new BiConsumer<PlayerState, DownloadFile>() { player.onPlayerStateChanged = new BiConsumer<PlayerState, DownloadFile>() {
@Override @Override
public void accept(PlayerState playerState, DownloadFile currentPlaying) { public void accept(PlayerState playerState, DownloadFile currentPlaying) {
if (playerState == PAUSED) 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)); boolean showWhenPaused = (playerState != PlayerState.STOPPED && Util.isNotificationAlwaysEnabled(MediaPlayerService.this));
@ -438,8 +445,8 @@ public class MediaPlayerService extends Service
Util.broadcastPlaybackStatusChange(MediaPlayerService.this, playerState); Util.broadcastPlaybackStatusChange(MediaPlayerService.this, playerState);
Util.broadcastA2dpPlayStatusChange(MediaPlayerService.this, playerState, currentPlaying.getSong(), Util.broadcastA2dpPlayStatusChange(MediaPlayerService.this, playerState, currentPlaying.getSong(),
downloader.getValue().downloadList.size() + downloader.getValue().backgroundDownloadList.size(), downloader.downloadList.size() + downloader.backgroundDownloadList.size(),
downloader.getValue().downloadList.indexOf(currentPlaying) + 1, getPlayerPosition()); downloader.downloadList.indexOf(currentPlaying) + 1, getPlayerPosition());
MusicDirectory.Entry song = currentPlaying.getSong(); MusicDirectory.Entry song = currentPlaying.getSong();
// Update widget // Update widget
@ -466,7 +473,7 @@ public class MediaPlayerService extends Service
if (tabInstance != null) if (tabInstance != null)
{ {
stopForeground(true); stopForeground(true);
player.getValue().clearRemoteControl(); player.clearRemoteControl();
isInForeground = false; isInForeground = false;
tabInstance.hideNowPlaying(); tabInstance.hideNowPlaying();
stopSelf(); stopSelf();
@ -487,10 +494,10 @@ public class MediaPlayerService extends Service
private void setupOnSongCompletedHandler() private void setupOnSongCompletedHandler()
{ {
player.getValue().onSongCompleted = new Consumer<DownloadFile>() { player.onSongCompleted = new Consumer<DownloadFile>() {
@Override @Override
public void accept(DownloadFile currentPlaying) { public void accept(DownloadFile currentPlaying) {
int index = downloader.getValue().getCurrentPlayingIndex(); int index = downloader.getCurrentPlayingIndex();
if (currentPlaying != null) if (currentPlaying != null)
{ {
@ -515,7 +522,7 @@ public class MediaPlayerService extends Service
switch (getRepeatMode()) switch (getRepeatMode())
{ {
case OFF: 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)) if (Util.getShouldClearPlaylist(MediaPlayerService.this))
{ {
@ -530,7 +537,7 @@ public class MediaPlayerService extends Service
play(index + 1); play(index + 1);
break; break;
case ALL: case ALL:
play((index + 1) % downloader.getValue().downloadList.size()); play((index + 1) % downloader.downloadList.size());
break; break;
case SINGLE: case SINGLE:
play(index); play(index);
@ -545,15 +552,15 @@ public class MediaPlayerService extends Service
public synchronized void clear(boolean serialize) public synchronized void clear(boolean serialize)
{ {
player.getValue().reset(); player.reset();
downloader.getValue().clear(); downloader.clear();
player.getValue().setCurrentPlaying(null); player.setCurrentPlaying(null);
setNextPlaying(); setNextPlaying();
if (serialize) { if (serialize) {
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.getValue().downloadList, downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
downloader.getValue().getCurrentPlayingIndex(), getPlayerPosition()); downloader.getCurrentPlayingIndex(), getPlayerPosition());
} }
} }
@ -632,7 +639,6 @@ public class MediaPlayerService extends Service
bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album); bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
} }
contentView.setTextViewText(R.id.trackname, title); contentView.setTextViewText(R.id.trackname, title);
bigView.setTextViewText(R.id.trackname, title); bigView.setTextViewText(R.id.trackname, title);
contentView.setTextViewText(R.id.artist, text); contentView.setTextViewText(R.id.artist, text);

View File

@ -117,7 +117,7 @@ public class Player
@Override @Override
public void run() public void run()
{ {
Thread.currentThread().setName("MediaPlayerService"); Thread.currentThread().setName("MediaPlayerThread");
Looper.prepare(); Looper.prepare();
@ -270,9 +270,9 @@ public class Player
return visualizerController; 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; this.playerState = playerState;
@ -286,7 +286,14 @@ public class Player
updateRemoteControl(); 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) 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; this.currentPlaying = currentPlaying;
updateRemoteControl(); 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) public synchronized void setNextPlaying(DownloadFile nextToPlay)
@ -362,7 +378,6 @@ public class Player
nextPlayingTask = null; nextPlayingTask = null;
} }
updateRemoteControl();
setCurrentPlaying(fileToPlay); setCurrentPlaying(fileToPlay);
bufferAndPlay(); bufferAndPlay();
} }
@ -375,7 +390,15 @@ public class Player
setCurrentPlaying(nextPlaying); setCurrentPlaying(nextPlaying);
setPlayerState(PlayerState.STARTED); setPlayerState(PlayerState.STARTED);
setupHandlers(currentPlaying, false); 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 // Proxy should not be being used here since the next player was already setup to play
if (proxy != null) if (proxy != null)
@ -409,7 +432,7 @@ public class Player
} }
} }
public void updateRemoteControl() private void updateRemoteControl()
{ {
if (!Util.isLockScreenEnabled(context)) if (!Util.isLockScreenEnabled(context))
{ {
@ -488,7 +511,7 @@ public class Player
} }
} }
public void setUpRemoteControlClient() private void setUpRemoteControlClient()
{ {
if (!Util.isLockScreenEnabled(context)) return; 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 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; return;