use exoplayer design for player callbacks

This commit is contained in:
dkanada 2021-03-06 15:51:16 +09:00
commit 0a9582c509
4 changed files with 53 additions and 39 deletions

View file

@ -137,7 +137,7 @@ public class MusicPlayerRemote {
} }
public static boolean isBuffering() { public static boolean isBuffering() {
return musicService != null && musicService.isBuffering(); return musicService != null && musicService.isLoading();
} }
public static void resumePlaying() { public static void resumePlaying() {

View file

@ -37,28 +37,30 @@ public class MultiPlayer implements Playback {
private PlaybackCallbacks callbacks; private PlaybackCallbacks callbacks;
private final ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() { private final ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
@Override @Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { public void onIsLoadingChanged(boolean isLoading) {
Log.i(TAG, String.format("onPlayerStateChanged: %b %d", playWhenReady, playbackState)); Log.i(TAG, String.format("onIsLoadingChanged: %b", isLoading));
if (callbacks != null) {
callbacks.onPlayerStateChanged(playWhenReady, playbackState);
}
} }
@Override @Override
public void onPositionDiscontinuity(int reason) { public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
Log.i(TAG, String.format("onPositionDiscontinuity: %d", reason)); Log.i(TAG, String.format("onPlayWhenReadyChanged: %b %d", playWhenReady, reason));
int windowIndex = exoPlayer.getCurrentWindowIndex(); if (callbacks != null) callbacks.onReadyChanged(playWhenReady, reason);
}
if (windowIndex == 1) { @Override
public void onPlaybackStateChanged(int state) {
Log.i(TAG, String.format("onPlaybackStateChanged: %d", state));
if (callbacks != null) callbacks.onStateChanged(state);
}
@Override
public void onMediaItemTransition(MediaItem mediaItem, int reason) {
Log.i(TAG, String.format("onMediaItemTransition: %s %d", mediaItem, reason));
if (exoPlayer.getMediaItemCount() > 1) {
exoPlayer.removeMediaItem(0); exoPlayer.removeMediaItem(0);
if (exoPlayer.isPlaying()) { callbacks.onTrackChanged(reason);
// there are still songs left in the queue
callbacks.onTrackWentToNext();
} else {
callbacks.onTrackEnded();
}
} }
} }
@ -88,6 +90,13 @@ public class MultiPlayer implements Playback {
@Override @Override
public void setDataSource(Song song) { public void setDataSource(Song song) {
String uri = MusicUtil.getSongFileUri(song);
MediaItem mediaItem = exoPlayer.getCurrentMediaItem();
if (mediaItem != null && mediaItem.playbackProperties.uri.toString().equals(uri)) {
return;
}
exoPlayer.clearMediaItems(); exoPlayer.clearMediaItems();
appendDataSource(MusicUtil.getSongFileUri(song)); appendDataSource(MusicUtil.getSongFileUri(song));
exoPlayer.seekTo(0, 0); exoPlayer.seekTo(0, 0);
@ -127,7 +136,7 @@ public class MultiPlayer implements Playback {
@Override @Override
public boolean isReady() { public boolean isReady() {
return true; return exoPlayer.getPlayWhenReady();
} }
@Override @Override
@ -136,7 +145,7 @@ public class MultiPlayer implements Playback {
} }
@Override @Override
public boolean isBuffering() { public boolean isLoading() {
return exoPlayer.getPlaybackState() == Player.STATE_BUFFERING; return exoPlayer.getPlaybackState() == Player.STATE_BUFFERING;
} }

View file

@ -51,7 +51,6 @@ import com.dkanada.gramophone.util.Util;
import com.dkanada.gramophone.widgets.AppWidgetAlbum; import com.dkanada.gramophone.widgets.AppWidgetAlbum;
import com.dkanada.gramophone.widgets.AppWidgetCard; import com.dkanada.gramophone.widgets.AppWidgetCard;
import com.dkanada.gramophone.widgets.AppWidgetClassic; import com.dkanada.gramophone.widgets.AppWidgetClassic;
import com.google.android.exoplayer2.Player;
import org.jellyfin.apiclient.interaction.EmptyResponse; import org.jellyfin.apiclient.interaction.EmptyResponse;
import org.jellyfin.apiclient.interaction.Response; import org.jellyfin.apiclient.interaction.Response;
@ -69,6 +68,9 @@ import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.google.android.exoplayer2.Player.MEDIA_ITEM_TRANSITION_REASON_AUTO;
import static com.google.android.exoplayer2.Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM;
public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks { public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
public static final String PACKAGE_NAME = "com.dkanada.gramophone"; public static final String PACKAGE_NAME = "com.dkanada.gramophone";
@ -483,8 +485,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return playback != null && playback.isPlaying(); return playback != null && playback.isPlaying();
} }
public boolean isBuffering() { public boolean isLoading() {
return playback != null && playback.isBuffering(); return playback != null && playback.isLoading();
} }
public int getPosition() { public int getPosition() {
@ -1036,26 +1038,29 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
} }
@Override @Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { public void onStateChanged(int state) {
notifyChange(STATE_CHANGED); notifyChange(STATE_CHANGED);
if (playWhenReady && playbackState == Player.STATE_READY) { }
@Override
public void onReadyChanged(boolean ready, int reason) {
notifyChange(STATE_CHANGED);
if (ready) {
progressHandler.sendEmptyMessage(TRACK_STARTED); progressHandler.sendEmptyMessage(TRACK_STARTED);
prepareNext(); prepareNext();
} else if (reason == PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM) {
progressHandler.sendEmptyMessage(TRACK_ENDED);
acquireWakeLock(30000);
} }
} }
@Override @Override
public void onTrackWentToNext() { public void onTrackChanged(int reason) {
playerHandler.sendEmptyMessage(TRACK_CHANGED); if (reason == MEDIA_ITEM_TRANSITION_REASON_AUTO) {
progressHandler.sendEmptyMessage(TRACK_CHANGED); playerHandler.sendEmptyMessage(TRACK_CHANGED);
} progressHandler.sendEmptyMessage(TRACK_CHANGED);
}
@Override
public void onTrackEnded() {
playerHandler.sendEmptyMessage(TRACK_ENDED);
progressHandler.sendEmptyMessage(TRACK_ENDED);
acquireWakeLock(30000);
} }
private static final class PlaybackHandler extends Handler { private static final class PlaybackHandler extends Handler {
@ -1292,7 +1297,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
info.setPositionTicks(progress * 10000); info.setPositionTicks(progress * 10000);
if (task != null) task.cancel(true); if (task != null) task.cancel(true);
executorService.shutdownNow(); if (executorService != null) executorService.shutdownNow();
} }
} }
} }

View file

@ -13,7 +13,7 @@ public interface Playback {
boolean isPlaying(); boolean isPlaying();
boolean isBuffering(); boolean isLoading();
void start(); void start();
@ -32,10 +32,10 @@ public interface Playback {
int getVolume(); int getVolume();
interface PlaybackCallbacks { interface PlaybackCallbacks {
void onPlayerStateChanged(boolean playWhenReady, int playbackState); void onStateChanged(int state);
void onTrackWentToNext(); void onReadyChanged(boolean ready, int reason);
void onTrackEnded(); void onTrackChanged(int reason);
} }
} }