Merge pull request #114 from Maxr1998/buffering-indicator
Add buffering indicator
This commit is contained in:
commit
3ff578ef91
12 changed files with 102 additions and 32 deletions
|
|
@ -57,6 +57,7 @@ public class MiniPlayerFragment extends AbsMusicServiceFragment implements Music
|
||||||
setUpPlayPauseButton();
|
setUpPlayPauseButton();
|
||||||
|
|
||||||
binding.progressBar.setProgressTintList(ColorStateList.valueOf(ThemeStore.accentColor(requireActivity())));
|
binding.progressBar.setProgressTintList(ColorStateList.valueOf(ThemeStore.accentColor(requireActivity())));
|
||||||
|
binding.progressBar.setIndeterminateTintList(ColorStateList.valueOf(ThemeStore.accentColor(requireActivity())));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpPlayPauseButton() {
|
private void setUpPlayPauseButton() {
|
||||||
|
|
@ -89,6 +90,7 @@ public class MiniPlayerFragment extends AbsMusicServiceFragment implements Music
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateProgressViews(int progress, int total) {
|
public void onUpdateProgressViews(int progress, int total) {
|
||||||
|
binding.progressBar.setIndeterminate(MusicPlayerRemote.isBuffering());
|
||||||
binding.progressBar.setMax(total);
|
binding.progressBar.setMax(total);
|
||||||
binding.progressBar.setProgress(progress);
|
binding.progressBar.setProgress(progress);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,7 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
|
||||||
public void onColorChanged(int color) {
|
public void onColorChanged(int color) {
|
||||||
animateColorChange(color);
|
animateColorChange(color);
|
||||||
playbackControlsFragment.setDark(ColorUtil.isColorLight(color));
|
playbackControlsFragment.setDark(ColorUtil.isColorLight(color));
|
||||||
|
playbackControlsFragment.updateBufferingIndicatorColor(color);
|
||||||
getCallbacks().onPaletteColorChanged();
|
getCallbacks().onPaletteColorChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.dkanada.gramophone.fragments.player.card;
|
package com.dkanada.gramophone.fragments.player.card;
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.os.Bundle;
|
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() {
|
private void setUpMusicControllers() {
|
||||||
setUpPlayPauseFab();
|
setUpPlayPauseFab();
|
||||||
setUpPrevNext();
|
setUpPrevNext();
|
||||||
|
|
@ -227,6 +233,8 @@ public class CardPlayerPlaybackControlsFragment extends AbsMusicServiceFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateProgressViews(int progress, int total) {
|
public void onUpdateProgressViews(int progress, int total) {
|
||||||
|
binding.playerBufferingIndicator.setVisibility(MusicPlayerRemote.isBuffering() ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
binding.playerProgressSlider.setMax(total);
|
binding.playerProgressSlider.setMax(total);
|
||||||
binding.playerProgressSlider.setProgress(progress);
|
binding.playerProgressSlider.setProgress(progress);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
|
||||||
public void onColorChanged(int color) {
|
public void onColorChanged(int color) {
|
||||||
animateColorChange(color);
|
animateColorChange(color);
|
||||||
playbackControlsFragment.setDark(ColorUtil.isColorLight(color));
|
playbackControlsFragment.setDark(ColorUtil.isColorLight(color));
|
||||||
|
playbackControlsFragment.updateBufferingIndicatorColor(color);
|
||||||
getCallbacks().onPaletteColorChanged();
|
getCallbacks().onPaletteColorChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.animation.Animator;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.TimeInterpolator;
|
import android.animation.TimeInterpolator;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.os.Bundle;
|
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() {
|
private void setUpMusicControllers() {
|
||||||
setUpPlayPauseButton();
|
setUpPlayPauseButton();
|
||||||
setUpPrevNext();
|
setUpPrevNext();
|
||||||
|
|
@ -282,6 +288,8 @@ public class FlatPlayerPlaybackControlsFragment extends AbsMusicServiceFragment
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateProgressViews(int progress, int total) {
|
public void onUpdateProgressViews(int progress, int total) {
|
||||||
|
binding.playerBufferingIndicator.setVisibility(MusicPlayerRemote.isBuffering() ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
binding.playerProgressSlider.setMax(total);
|
binding.playerProgressSlider.setMax(total);
|
||||||
binding.playerProgressSlider.setProgress(progress);
|
binding.playerProgressSlider.setProgress(progress);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,10 @@ public class MusicPlayerRemote {
|
||||||
return musicService != null && musicService.isPlaying();
|
return musicService != null && musicService.isPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isBuffering() {
|
||||||
|
return musicService != null && musicService.isLoading();
|
||||||
|
}
|
||||||
|
|
||||||
public static void resumePlaying() {
|
public static void resumePlaying() {
|
||||||
if (musicService != null) {
|
if (musicService != null) {
|
||||||
musicService.play();
|
musicService.play();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import com.dkanada.gramophone.util.MusicUtil;
|
||||||
import com.dkanada.gramophone.util.PreferenceUtil;
|
import com.dkanada.gramophone.util.PreferenceUtil;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.ExoPlayer;
|
import com.google.android.exoplayer2.ExoPlayer;
|
||||||
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.MediaItem;
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
|
||||||
|
|
@ -44,35 +45,28 @@ public class MultiPlayer implements Playback {
|
||||||
@Override
|
@Override
|
||||||
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
|
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
|
||||||
Log.i(TAG, String.format("onPlayWhenReadyChanged: %b %d", playWhenReady, reason));
|
Log.i(TAG, String.format("onPlayWhenReadyChanged: %b %d", playWhenReady, reason));
|
||||||
|
if (callbacks != null) callbacks.onReadyChanged(playWhenReady, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlaybackStateChanged(int playbackState) {
|
public void onPlaybackStateChanged(int state) {
|
||||||
Log.i(TAG, String.format("onPlaybackStateChanged: %d", playbackState));
|
Log.i(TAG, String.format("onPlaybackStateChanged: %d", state));
|
||||||
if (callbacks != null && exoPlayer.isPlaying()) {
|
if (callbacks != null) callbacks.onStateChanged(state);
|
||||||
callbacks.onTrackStarted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaItemTransition(MediaItem mediaItem, int reason) {
|
public void onMediaItemTransition(MediaItem mediaItem, int reason) {
|
||||||
Log.i(TAG, String.format("onMediaItemTransition: %s %d", mediaItem, reason));
|
Log.i(TAG, String.format("onMediaItemTransition: %s %d", mediaItem, reason));
|
||||||
|
|
||||||
|
if (exoPlayer.getMediaItemCount() > 1) {
|
||||||
|
exoPlayer.removeMediaItem(0);
|
||||||
|
callbacks.onTrackChanged(reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int reason) {
|
public void onPositionDiscontinuity(int reason) {
|
||||||
Log.i(TAG, String.format("onPositionDiscontinuity: %d", 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
|
@Override
|
||||||
|
|
@ -101,6 +95,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);
|
||||||
|
|
@ -140,7 +141,7 @@ public class MultiPlayer implements Playback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
return true;
|
return exoPlayer.getPlayWhenReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -148,6 +149,11 @@ public class MultiPlayer implements Playback {
|
||||||
return exoPlayer.isPlaying() || exoPlayer.getPlayWhenReady();
|
return exoPlayer.isPlaying() || exoPlayer.getPlayWhenReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoading() {
|
||||||
|
return exoPlayer.getPlaybackState() == Player.STATE_BUFFERING;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
exoPlayer.setPlayWhenReady(true);
|
exoPlayer.setPlayWhenReady(true);
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ import org.jellyfin.apiclient.model.session.PlaybackStopInfo;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
@ -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,6 +485,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
||||||
return playback != null && playback.isPlaying();
|
return playback != null && playback.isPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLoading() {
|
||||||
|
return playback != null && playback.isLoading();
|
||||||
|
}
|
||||||
|
|
||||||
public int getPosition() {
|
public int getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
@ -1032,25 +1038,30 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTrackStarted() {
|
public void onStateChanged(int state) {
|
||||||
progressHandler.sendEmptyMessage(TRACK_STARTED);
|
|
||||||
|
|
||||||
notifyChange(STATE_CHANGED);
|
notifyChange(STATE_CHANGED);
|
||||||
prepareNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTrackWentToNext() {
|
public void onReadyChanged(boolean ready, int reason) {
|
||||||
playerHandler.sendEmptyMessage(TRACK_CHANGED);
|
notifyChange(STATE_CHANGED);
|
||||||
progressHandler.sendEmptyMessage(TRACK_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
|
@Override
|
||||||
public void onTrackEnded() {
|
public void onTrackChanged(int reason) {
|
||||||
playerHandler.sendEmptyMessage(TRACK_ENDED);
|
|
||||||
progressHandler.sendEmptyMessage(TRACK_ENDED);
|
|
||||||
|
|
||||||
acquireWakeLock(30000);
|
acquireWakeLock(30000);
|
||||||
|
|
||||||
|
if (reason == MEDIA_ITEM_TRANSITION_REASON_AUTO) {
|
||||||
|
playerHandler.sendEmptyMessage(TRACK_CHANGED);
|
||||||
|
progressHandler.sendEmptyMessage(TRACK_CHANGED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PlaybackHandler extends Handler {
|
private static final class PlaybackHandler extends Handler {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ public interface Playback {
|
||||||
|
|
||||||
boolean isPlaying();
|
boolean isPlaying();
|
||||||
|
|
||||||
|
boolean isLoading();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
|
|
@ -30,10 +32,10 @@ public interface Playback {
|
||||||
int getVolume();
|
int getVolume();
|
||||||
|
|
||||||
interface PlaybackCallbacks {
|
interface PlaybackCallbacks {
|
||||||
void onTrackStarted();
|
void onStateChanged(int state);
|
||||||
|
|
||||||
void onTrackWentToNext();
|
void onReadyChanged(boolean ready, int reason);
|
||||||
|
|
||||||
void onTrackEnded();
|
void onTrackChanged(int reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,19 @@
|
||||||
android:layout_height="@dimen/progress_container_height"
|
android:layout_height="@dimen/progress_container_height"
|
||||||
android:background="@color/twenty_percent_black_overlay">
|
android:background="@color/twenty_percent_black_overlay">
|
||||||
|
|
||||||
|
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||||
|
android:id="@+id/player_buffering_indicator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:indeterminate="true"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:mpb_progressStyle="horizontal"
|
||||||
|
app:mpb_useIntrinsicPadding="false"
|
||||||
|
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/player_song_current_progress"
|
android:id="@+id/player_song_current_progress"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,19 @@
|
||||||
android:layout_height="@dimen/progress_container_height"
|
android:layout_height="@dimen/progress_container_height"
|
||||||
android:background="@color/twenty_percent_black_overlay">
|
android:background="@color/twenty_percent_black_overlay">
|
||||||
|
|
||||||
|
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||||
|
android:id="@+id/player_buffering_indicator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:indeterminate="true"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:mpb_progressStyle="horizontal"
|
||||||
|
app:mpb_useIntrinsicPadding="false"
|
||||||
|
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/player_song_current_progress"
|
android:id="@+id/player_song_current_progress"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
app:mpb_progressStyle="horizontal"
|
app:mpb_progressStyle="horizontal"
|
||||||
app:mpb_useIntrinsicPadding="false"
|
app:mpb_useIntrinsicPadding="false"
|
||||||
|
app:mpb_setBothDrawables="true"
|
||||||
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal" />
|
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue