diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/player/MiniPlayerFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/player/MiniPlayerFragment.java index 994f86de..ecb8caf5 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/player/MiniPlayerFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/player/MiniPlayerFragment.java @@ -57,6 +57,7 @@ public class MiniPlayerFragment extends AbsMusicServiceFragment implements Music setUpPlayPauseButton(); binding.progressBar.setProgressTintList(ColorStateList.valueOf(ThemeStore.accentColor(requireActivity()))); + binding.progressBar.setIndeterminateTintList(ColorStateList.valueOf(ThemeStore.accentColor(requireActivity()))); } private void setUpPlayPauseButton() { @@ -89,6 +90,7 @@ public class MiniPlayerFragment extends AbsMusicServiceFragment implements Music @Override public void onUpdateProgressViews(int progress, int total) { + binding.progressBar.setIndeterminate(MusicPlayerRemote.isBuffering()); binding.progressBar.setMax(total); binding.progressBar.setProgress(progress); } diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerFragment.java index bf4e453a..02dde037 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerFragment.java @@ -274,6 +274,7 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum public void onColorChanged(int color) { animateColorChange(color); playbackControlsFragment.setDark(ColorUtil.isColorLight(color)); + playbackControlsFragment.updateBufferingIndicatorColor(color); getCallbacks().onPaletteColorChanged(); } diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerPlaybackControlsFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerPlaybackControlsFragment.java index 8e68037f..5bd29117 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerPlaybackControlsFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/player/card/CardPlayerPlaybackControlsFragment.java @@ -1,5 +1,6 @@ package com.dkanada.gramophone.fragments.player.card; +import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.PorterDuff; import android.os.Bundle; @@ -133,6 +134,11 @@ public class CardPlayerPlaybackControlsFragment extends AbsMusicServiceFragment } } + public void updateBufferingIndicatorColor(int color) { + binding.playerBufferingIndicator.setProgressBackgroundTintList(ColorStateList.valueOf(getResources().getColor(android.R.color.transparent))); + binding.playerBufferingIndicator.setIndeterminateTintList(ColorStateList.valueOf(color)); + } + private void setUpMusicControllers() { setUpPlayPauseFab(); setUpPrevNext(); @@ -227,6 +233,8 @@ public class CardPlayerPlaybackControlsFragment extends AbsMusicServiceFragment @Override public void onUpdateProgressViews(int progress, int total) { + binding.playerBufferingIndicator.setVisibility(MusicPlayerRemote.isBuffering() ? View.VISIBLE : View.GONE); + binding.playerProgressSlider.setMax(total); binding.playerProgressSlider.setProgress(progress); diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerFragment.java index 1262d955..a5432c94 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerFragment.java @@ -277,6 +277,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum public void onColorChanged(int color) { animateColorChange(color); playbackControlsFragment.setDark(ColorUtil.isColorLight(color)); + playbackControlsFragment.updateBufferingIndicatorColor(color); getCallbacks().onPaletteColorChanged(); } diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java index c9865984..de8f32c3 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java @@ -4,6 +4,7 @@ import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; +import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.PorterDuff; import android.os.Bundle; @@ -138,6 +139,11 @@ public class FlatPlayerPlaybackControlsFragment extends AbsMusicServiceFragment } } + public void updateBufferingIndicatorColor(int color) { + binding.playerBufferingIndicator.setProgressBackgroundTintList(ColorStateList.valueOf(getResources().getColor(android.R.color.transparent))); + binding.playerBufferingIndicator.setIndeterminateTintList(ColorStateList.valueOf(color)); + } + private void setUpMusicControllers() { setUpPlayPauseButton(); setUpPrevNext(); @@ -282,6 +288,8 @@ public class FlatPlayerPlaybackControlsFragment extends AbsMusicServiceFragment @Override public void onUpdateProgressViews(int progress, int total) { + binding.playerBufferingIndicator.setVisibility(MusicPlayerRemote.isBuffering() ? View.VISIBLE : View.GONE); + binding.playerProgressSlider.setMax(total); binding.playerProgressSlider.setProgress(progress); diff --git a/app/src/main/java/com/dkanada/gramophone/helper/MusicPlayerRemote.java b/app/src/main/java/com/dkanada/gramophone/helper/MusicPlayerRemote.java index f13938e0..cfb31b50 100644 --- a/app/src/main/java/com/dkanada/gramophone/helper/MusicPlayerRemote.java +++ b/app/src/main/java/com/dkanada/gramophone/helper/MusicPlayerRemote.java @@ -136,6 +136,10 @@ public class MusicPlayerRemote { return musicService != null && musicService.isPlaying(); } + public static boolean isBuffering() { + return musicService != null && musicService.isLoading(); + } + public static void resumePlaying() { if (musicService != null) { musicService.play(); diff --git a/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java b/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java index 70d84c20..d0f5d181 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java +++ b/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java @@ -12,6 +12,7 @@ import com.dkanada.gramophone.util.MusicUtil; import com.dkanada.gramophone.util.PreferenceUtil; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.database.ExoDatabaseProvider; @@ -44,35 +45,28 @@ public class MultiPlayer implements Playback { @Override public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) { Log.i(TAG, String.format("onPlayWhenReadyChanged: %b %d", playWhenReady, reason)); + if (callbacks != null) callbacks.onReadyChanged(playWhenReady, reason); } @Override - public void onPlaybackStateChanged(int playbackState) { - Log.i(TAG, String.format("onPlaybackStateChanged: %d", playbackState)); - if (callbacks != null && exoPlayer.isPlaying()) { - callbacks.onTrackStarted(); - } + 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); + callbacks.onTrackChanged(reason); + } } @Override public void onPositionDiscontinuity(int reason) { Log.i(TAG, String.format("onPositionDiscontinuity: %d", reason)); - int windowIndex = exoPlayer.getCurrentWindowIndex(); - - if (windowIndex == 1) { - exoPlayer.removeMediaItem(0); - if (exoPlayer.isPlaying()) { - // there are still songs left in the queue - callbacks.onTrackWentToNext(); - } else { - callbacks.onTrackEnded(); - } - } } @Override @@ -101,6 +95,13 @@ public class MultiPlayer implements Playback { @Override 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(); appendDataSource(MusicUtil.getSongFileUri(song)); exoPlayer.seekTo(0, 0); @@ -140,7 +141,7 @@ public class MultiPlayer implements Playback { @Override public boolean isReady() { - return true; + return exoPlayer.getPlayWhenReady(); } @Override @@ -148,6 +149,11 @@ public class MultiPlayer implements Playback { return exoPlayer.isPlaying() || exoPlayer.getPlayWhenReady(); } + @Override + public boolean isLoading() { + return exoPlayer.getPlaybackState() == Player.STATE_BUFFERING; + } + @Override public void start() { exoPlayer.setPlayWhenReady(true); diff --git a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java index b470a15e..c8677a5d 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java +++ b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java @@ -60,7 +60,6 @@ import org.jellyfin.apiclient.model.session.PlaybackStopInfo; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Random; @@ -69,6 +68,9 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; 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 static final String PACKAGE_NAME = "com.dkanada.gramophone"; @@ -483,6 +485,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP return playback != null && playback.isPlaying(); } + public boolean isLoading() { + return playback != null && playback.isLoading(); + } + public int getPosition() { return position; } @@ -1032,25 +1038,30 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP } @Override - public void onTrackStarted() { - progressHandler.sendEmptyMessage(TRACK_STARTED); - + public void onStateChanged(int state) { notifyChange(STATE_CHANGED); - prepareNext(); } @Override - public void onTrackWentToNext() { - playerHandler.sendEmptyMessage(TRACK_CHANGED); - progressHandler.sendEmptyMessage(TRACK_CHANGED); + public void onReadyChanged(boolean ready, int reason) { + notifyChange(STATE_CHANGED); + + if (ready) { + progressHandler.sendEmptyMessage(TRACK_STARTED); + prepareNext(); + } else if (reason == PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM) { + progressHandler.sendEmptyMessage(TRACK_ENDED); + } } @Override - public void onTrackEnded() { - playerHandler.sendEmptyMessage(TRACK_ENDED); - progressHandler.sendEmptyMessage(TRACK_ENDED); - + public void onTrackChanged(int reason) { acquireWakeLock(30000); + + if (reason == MEDIA_ITEM_TRANSITION_REASON_AUTO) { + playerHandler.sendEmptyMessage(TRACK_CHANGED); + progressHandler.sendEmptyMessage(TRACK_CHANGED); + } } private static final class PlaybackHandler extends Handler { diff --git a/app/src/main/java/com/dkanada/gramophone/service/playback/Playback.java b/app/src/main/java/com/dkanada/gramophone/service/playback/Playback.java index d99ce93f..dddc1089 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/playback/Playback.java +++ b/app/src/main/java/com/dkanada/gramophone/service/playback/Playback.java @@ -13,6 +13,8 @@ public interface Playback { boolean isPlaying(); + boolean isLoading(); + void start(); void pause(); @@ -30,10 +32,10 @@ public interface Playback { int getVolume(); interface PlaybackCallbacks { - void onTrackStarted(); + void onStateChanged(int state); - void onTrackWentToNext(); + void onReadyChanged(boolean ready, int reason); - void onTrackEnded(); + void onTrackChanged(int reason); } } diff --git a/app/src/main/res/layout/fragment_card_player_playback_controls.xml b/app/src/main/res/layout/fragment_card_player_playback_controls.xml index 6e1444e3..1312d7a1 100644 --- a/app/src/main/res/layout/fragment_card_player_playback_controls.xml +++ b/app/src/main/res/layout/fragment_card_player_playback_controls.xml @@ -12,6 +12,19 @@ android:layout_height="@dimen/progress_container_height" android:background="@color/twenty_percent_black_overlay"> + + + +