store playback requests when exoplayer is loading
This commit is contained in:
parent
2c8229b0dc
commit
6d24095c5c
4 changed files with 56 additions and 49 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ public interface Playback {
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
boolean isInitialized();
|
boolean isReady();
|
||||||
|
|
||||||
boolean isPlaying();
|
boolean isPlaying();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue