store playback requests when exoplayer is loading

This commit is contained in:
dkanada 2020-10-18 01:37:36 +09:00
commit 6d24095c5c
4 changed files with 56 additions and 49 deletions

View file

@ -29,12 +29,6 @@ public class MusicProgressViewUpdateHelper extends Handler {
this.intervalPaused = UPDATE_INTERVAL_PAUSED; this.intervalPaused = UPDATE_INTERVAL_PAUSED;
} }
public MusicProgressViewUpdateHelper(Callback callback, int intervalPlaying, int intervalPaused) {
this.callback = callback;
this.intervalPlaying = intervalPlaying;
this.intervalPaused = intervalPaused;
}
@Override @Override
public void handleMessage(@NonNull Message msg) { public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg); super.handleMessage(msg);

View file

@ -34,6 +34,7 @@ import java.io.File;
import okhttp3.Call; import okhttp3.Call;
import okhttp3.Callback; import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -42,9 +43,9 @@ import okhttp3.internal.annotations.EverythingIsNonNull;
public class MultiPlayer implements Playback { public class MultiPlayer implements Playback {
public static final String TAG = MultiPlayer.class.getSimpleName(); public static final String TAG = MultiPlayer.class.getSimpleName();
private Context context; private final Context context;
private final OkHttpClient httpClient;
private OkHttpClient httpClient;
private SimpleExoPlayer exoPlayer; private SimpleExoPlayer exoPlayer;
private ConcatenatingMediaSource mediaSource; private ConcatenatingMediaSource mediaSource;
@ -55,7 +56,9 @@ public class MultiPlayer implements Playback {
private boolean isReady = false; private boolean isReady = false;
private boolean isPlaying = false; private boolean isPlaying = false;
private boolean isNew = false;
private boolean requestPlay = false;
private int requestProgress = 0;
private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() { private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
@Override @Override
@ -72,6 +75,20 @@ public class MultiPlayer implements Playback {
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.i(TAG, "onPlayerStateChanged playWhenReady: " + playWhenReady); Log.i(TAG, "onPlayerStateChanged playWhenReady: " + playWhenReady);
Log.i(TAG, "onPlayerStateChanged playbackState: " + playbackState); Log.i(TAG, "onPlayerStateChanged playbackState: " + playbackState);
if (callbacks == null) return;
if (requestProgress != 0 && playbackState == Player.STATE_READY) {
exoPlayer.seekTo(requestProgress);
requestProgress = 0;
}
if (exoPlayer.isPlaying() || requestPlay && playbackState == ExoPlayer.STATE_READY) {
requestPlay = false;
exoPlayer.setPlayWhenReady(true);
callbacks.onTrackStarted();
}
} }
@Override @Override
@ -81,7 +98,7 @@ public class MultiPlayer implements Playback {
if (windowIndex == 1) { if (windowIndex == 1) {
mediaSource.removeMediaSource(0); mediaSource.removeMediaSource(0);
if (mediaSource.getSize() != 0) { if (exoPlayer.isPlaying()) {
// there are still songs left in the queue // there are still songs left in the queue
callbacks.onTrackWentToNext(); callbacks.onTrackWentToNext();
} else { } else {
@ -105,15 +122,22 @@ public class MultiPlayer implements Playback {
} }
}; };
public MultiPlayer(final Context context) { public MultiPlayer(Context context) {
this.context = context; this.context = context;
httpClient = new OkHttpClient(); Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
httpClient = new OkHttpClient.Builder().dispatcher(dispatcher).build();
if (exoPlayer != null) exoPlayer.release(); if (exoPlayer != null) exoPlayer.release();
exoPlayer = new SimpleExoPlayer.Builder(context).build(); exoPlayer = new SimpleExoPlayer.Builder(context).build();
mediaSource = new ConcatenatingMediaSource(); mediaSource = new ConcatenatingMediaSource();
exoPlayer.addListener(eventListener);
exoPlayer.prepare(mediaSource);
exoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF);
if (simpleCache != null) simpleCache.release(); if (simpleCache != null) simpleCache.release();
LeastRecentlyUsedCacheEvictor recentlyUsedCache = new LeastRecentlyUsedCacheEvictor(Long.MAX_VALUE); LeastRecentlyUsedCacheEvictor recentlyUsedCache = new LeastRecentlyUsedCacheEvictor(Long.MAX_VALUE);
ExoDatabaseProvider databaseProvider = new ExoDatabaseProvider(context); ExoDatabaseProvider databaseProvider = new ExoDatabaseProvider(context);
@ -126,11 +150,6 @@ public class MultiPlayer implements Playback {
@Override @Override
public void setDataSource(Song song) { public void setDataSource(Song song) {
isReady = false; isReady = false;
if (context == null) {
return;
}
isNew = true;
mediaSource = new ConcatenatingMediaSource(); mediaSource = new ConcatenatingMediaSource();
exoPlayer.addListener(eventListener); exoPlayer.addListener(eventListener);
@ -139,27 +158,22 @@ public class MultiPlayer implements Playback {
// queue and other information is currently handled outside exoplayer // queue and other information is currently handled outside exoplayer
exoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF); exoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF);
appendDataSource(MusicUtil.getSongFileUri(song), 0); appendDataSource(MusicUtil.getSongFileUri(song));
isReady = true;
} }
@Override @Override
public void queueDataSource(Song song) { public void queueDataSource(Song song) {
if (context == null) {
return;
}
String path = MusicUtil.getSongFileUri(song); String path = MusicUtil.getSongFileUri(song);
if (mediaSource.getSize() == 2 && mediaSource.getMediaSource(1).getTag() != path) { if (mediaSource.getSize() == 2 && mediaSource.getMediaSource(1).getTag() != path) {
mediaSource.removeMediaSource(1); mediaSource.removeMediaSource(1);
} }
if (mediaSource.getSize() != 2) { if (mediaSource.getSize() != 2) {
appendDataSource(path, 1); appendDataSource(path);
} }
} }
private void appendDataSource(String path, int position) { private void appendDataSource(String path) {
Uri uri = Uri.parse(path); Uri uri = Uri.parse(path);
httpClient.newCall(new Request.Builder().url(path).head().build()).enqueue(new Callback() { httpClient.newCall(new Request.Builder().url(path).head().build()).enqueue(new Callback() {
@ -185,8 +199,8 @@ public class MultiPlayer implements Playback {
.createMediaSource(uri); .createMediaSource(uri);
} }
mediaSource.addMediaSource(Math.min(mediaSource.getSize(), position), source); mediaSource.addMediaSource(source);
if (position == 0) start(); isReady = true;
} }
}); });
} }
@ -208,19 +222,19 @@ public class MultiPlayer implements Playback {
} }
@Override @Override
public boolean isInitialized() { public boolean isReady() {
return isReady; return isReady;
} }
@Override @Override
public void start() { public void start() {
if (!isReady) {
requestPlay = true;
return;
}
isPlaying = true; isPlaying = true;
exoPlayer.setPlayWhenReady(true); exoPlayer.setPlayWhenReady(true);
if (isNew) {
callbacks.onTrackStarted();
isNew = false;
}
} }
@Override @Override
@ -256,6 +270,11 @@ public class MultiPlayer implements Playback {
@Override @Override
public void setProgress(int position) { public void setProgress(int position) {
if (!isReady) {
requestProgress = position;
return;
}
exoPlayer.seekTo(position); exoPlayer.seekTo(position);
} }

View file

@ -409,7 +409,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
this.playingQueue = restoredQueue; this.playingQueue = restoredQueue;
position = restoredPosition; position = restoredPosition;
openCurrent(true); openCurrent();
if (restoredPositionInTrack > 0) seek(restoredPositionInTrack); if (restoredPositionInTrack > 0) seek(restoredPositionInTrack);
@ -458,25 +458,20 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
synchronized (this) { synchronized (this) {
this.position = position; this.position = position;
openCurrent(false); openCurrent();
playback.start();
notifyChange(META_CHANGED); notifyChange(META_CHANGED);
notHandledMetaChangedForCurrentTrack = false; notHandledMetaChangedForCurrentTrack = false;
} }
} }
private void openCurrent(boolean queue) { private void openCurrent() {
synchronized (this) { synchronized (this) {
// current song will be null when queue is cleared // current song will be null when queue is cleared
if (getCurrentSong() == null) return; if (getCurrentSong() == null) return;
if (queue) { playback.setDataSource(getCurrentSong());
// restore queue from database
playback.queueDataSource(getCurrentSong());
} else {
// set current song and start playback
playback.setDataSource(getCurrentSong());
}
} }
} }
@ -784,7 +779,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
synchronized (this) { synchronized (this) {
if (requestFocus()) { if (requestFocus()) {
if (!playback.isPlaying()) { if (!playback.isPlaying()) {
if (!playback.isInitialized()) { if (!playback.isReady()) {
playSongAt(getPosition()); playSongAt(getPosition());
} else { } else {
playback.start(); playback.start();
@ -945,10 +940,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
case PLAY_STATE_CHANGED: case PLAY_STATE_CHANGED:
updateNotification(); updateNotification();
updateMediaSessionPlaybackState(); updateMediaSessionPlaybackState();
final boolean isPlaying = isPlaying(); if (!isPlaying()) saveProgress();
if (!isPlaying && getSongProgressMillis() > 0) {
saveProgress();
}
break; break;
case META_CHANGED: case META_CHANGED:
updateNotification(); updateNotification();
@ -1003,6 +995,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override @Override
public void onTrackStarted() { public void onTrackStarted() {
progressHandler.sendEmptyMessage(PLAY_SONG);
notifyChange(PLAY_STATE_CHANGED); notifyChange(PLAY_STATE_CHANGED);
prepareNext(); prepareNext();
} }
@ -1244,6 +1237,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
startInfo.setCanSeek(true); startInfo.setCanSeek(true);
startInfo.setIsPaused(false); startInfo.setIsPaused(false);
App.getApiClient().ensureWebSocket();
App.getApiClient().ReportPlaybackStartAsync(startInfo, new EmptyResponse()); App.getApiClient().ReportPlaybackStartAsync(startInfo, new EmptyResponse());
} }

View file

@ -15,7 +15,7 @@ public interface Playback {
void stop(); void stop();
boolean isInitialized(); boolean isReady();
boolean isPlaying(); boolean isPlaying();