-Added variable speed and pitch to background player.

-Moved playback speed LUT to BasePlayer.
This commit is contained in:
John Zhen M 2017-10-09 19:52:23 -07:00 committed by John Zhen Mo
parent 77979eddde
commit 94f7baf299
4 changed files with 122 additions and 10 deletions

View File

@ -74,6 +74,11 @@ public class BackgroundPlayerActivity extends AppCompatActivity
private ImageButton forwardButton; private ImageButton forwardButton;
private ImageButton shuffleButton; private ImageButton shuffleButton;
private TextView playbackSpeedButton;
private PopupMenu playbackSpeedPopupMenu;
private TextView playbackPitchButton;
private PopupMenu playbackPitchPopupMenu;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Activity Lifecycle // Activity Lifecycle
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -198,12 +203,57 @@ public class BackgroundPlayerActivity extends AppCompatActivity
playPauseButton = rootView.findViewById(R.id.control_play_pause); playPauseButton = rootView.findViewById(R.id.control_play_pause);
forwardButton = rootView.findViewById(R.id.control_forward); forwardButton = rootView.findViewById(R.id.control_forward);
shuffleButton = rootView.findViewById(R.id.control_shuffle); shuffleButton = rootView.findViewById(R.id.control_shuffle);
playbackSpeedButton = rootView.findViewById(R.id.control_playback_speed);
playbackPitchButton = rootView.findViewById(R.id.control_playback_pitch);
repeatButton.setOnClickListener(this); repeatButton.setOnClickListener(this);
backwardButton.setOnClickListener(this); backwardButton.setOnClickListener(this);
playPauseButton.setOnClickListener(this); playPauseButton.setOnClickListener(this);
forwardButton.setOnClickListener(this); forwardButton.setOnClickListener(this);
shuffleButton.setOnClickListener(this); shuffleButton.setOnClickListener(this);
playbackSpeedButton.setOnClickListener(this);
playbackPitchButton.setOnClickListener(this);
playbackSpeedPopupMenu = new PopupMenu(this, playbackSpeedButton);
playbackPitchPopupMenu = new PopupMenu(this, playbackPitchButton);
buildPlaybackSpeedMenu();
buildPlaybackPitchMenu();
}
private void buildPlaybackSpeedMenu() {
if (playbackSpeedPopupMenu == null) return;
playbackSpeedPopupMenu.getMenu().removeGroup(PLAYBACK_SPEED_POPUP_MENU_GROUP_ID);
for (int i = 0; i < BasePlayer.PLAYBACK_SPEEDS.length; i++) {
final float playbackSpeed = BasePlayer.PLAYBACK_SPEEDS[i];
final String formattedSpeed = player.formatSpeed(playbackSpeed);
final MenuItem item = playbackSpeedPopupMenu.getMenu().add(PLAYBACK_SPEED_POPUP_MENU_GROUP_ID, i, Menu.NONE, formattedSpeed);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
player.setPlaybackSpeed(playbackSpeed);
return true;
}
});
}
}
private void buildPlaybackPitchMenu() {
if (playbackPitchPopupMenu == null) return;
playbackPitchPopupMenu.getMenu().removeGroup(PLAYBACK_SPEED_POPUP_MENU_GROUP_ID);
for (int i = 0; i < BasePlayer.PLAYBACK_PITCHES.length; i++) {
final float playbackPitch = BasePlayer.PLAYBACK_PITCHES[i];
final String formattedPitch = player.formatPitch(playbackPitch);
final MenuItem item = playbackPitchPopupMenu.getMenu().add(PLAYBACK_SPEED_POPUP_MENU_GROUP_ID, i, Menu.NONE, formattedPitch);
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
player.setPlaybackPitch(playbackPitch);
return true;
}
});
}
} }
private void buildItemPopupMenu(final PlayQueueItem item, final View view) { private void buildItemPopupMenu(final PlayQueueItem item, final View view) {
@ -313,16 +363,26 @@ public class BackgroundPlayerActivity extends AppCompatActivity
public void onClick(View view) { public void onClick(View view) {
if (view.getId() == repeatButton.getId()) { if (view.getId() == repeatButton.getId()) {
player.onRepeatClicked(); player.onRepeatClicked();
} else if (view.getId() == backwardButton.getId()) { } else if (view.getId() == backwardButton.getId()) {
player.onPlayPrevious(); player.onPlayPrevious();
scrollToSelected(); scrollToSelected();
} else if (view.getId() == playPauseButton.getId()) { } else if (view.getId() == playPauseButton.getId()) {
player.onVideoPlayPause(); player.onVideoPlayPause();
scrollToSelected(); scrollToSelected();
} else if (view.getId() == forwardButton.getId()) { } else if (view.getId() == forwardButton.getId()) {
player.onPlayNext(); player.onPlayNext();
} else if (view.getId() == shuffleButton.getId()) { } else if (view.getId() == shuffleButton.getId()) {
player.onShuffleClicked(); player.onShuffleClicked();
} else if (view.getId() == playbackSpeedButton.getId()) {
playbackSpeedPopupMenu.show();
} else if (view.getId() == playbackPitchButton.getId()) {
playbackPitchPopupMenu.show();
} }
} }
@ -379,25 +439,23 @@ public class BackgroundPlayerActivity extends AppCompatActivity
repeatAlpha = 255; repeatAlpha = 255;
break; break;
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
repeatButton.setImageAlpha(repeatAlpha);
} else {
repeatButton.setAlpha(repeatAlpha);
}
int shuffleAlpha = 255; int shuffleAlpha = 255;
if (!shuffled) { if (!shuffled) {
shuffleAlpha = 77; shuffleAlpha = 77;
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
repeatButton.setImageAlpha(repeatAlpha);
shuffleButton.setImageAlpha(shuffleAlpha); shuffleButton.setImageAlpha(shuffleAlpha);
} else { } else {
repeatButton.setAlpha(repeatAlpha);
shuffleButton.setAlpha(shuffleAlpha); shuffleButton.setAlpha(shuffleAlpha);
} }
if (parameters != null) { if (parameters != null) {
final float speed = parameters.speed; playbackSpeedButton.setText(player.formatSpeed(parameters.speed));
final float pitch = parameters.pitch; playbackPitchButton.setText(player.formatPitch(parameters.pitch));
} }
scrollToSelected(); scrollToSelected();

View File

@ -142,6 +142,9 @@ public abstract class BasePlayer implements Player.EventListener,
// Playback // Playback
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
protected static final float[] PLAYBACK_SPEEDS = {0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f};
protected static final float[] PLAYBACK_PITCHES = {0.8f, 0.9f, 0.95f, 1f, 1.05f, 1.1f, 1.2f};
protected MediaSourceManager playbackManager; protected MediaSourceManager playbackManager;
protected PlayQueue playQueue; protected PlayQueue playQueue;
@ -862,6 +865,7 @@ public abstract class BasePlayer implements Player.EventListener,
private final StringBuilder stringBuilder = new StringBuilder(); private final StringBuilder stringBuilder = new StringBuilder();
private final Formatter formatter = new Formatter(stringBuilder, Locale.getDefault()); private final Formatter formatter = new Formatter(stringBuilder, Locale.getDefault());
private final NumberFormat speedFormatter = new DecimalFormat("0.##x"); private final NumberFormat speedFormatter = new DecimalFormat("0.##x");
private final NumberFormat pitchFormatter = new DecimalFormat("##.##%");
// todo: merge this into Localization // todo: merge this into Localization
public String getTimeString(int milliSeconds) { public String getTimeString(int milliSeconds) {
@ -880,6 +884,10 @@ public abstract class BasePlayer implements Player.EventListener,
return speedFormatter.format(speed); return speedFormatter.format(speed);
} }
protected String formatPitch(float pitch) {
return pitchFormatter.format(pitch);
}
protected void startProgressLoop() { protected void startProgressLoop() {
if (progressUpdateReactor != null) progressUpdateReactor.dispose(); if (progressUpdateReactor != null) progressUpdateReactor.dispose();
progressUpdateReactor = getProgressReactor(); progressUpdateReactor = getProgressReactor();
@ -990,11 +998,28 @@ public abstract class BasePlayer implements Player.EventListener,
} }
public float getPlaybackSpeed() { public float getPlaybackSpeed() {
return simpleExoPlayer.getPlaybackParameters().speed; return getPlaybackParameters().speed;
}
public float getPlaybackPitch() {
return getPlaybackParameters().pitch;
} }
public void setPlaybackSpeed(float speed) { public void setPlaybackSpeed(float speed) {
simpleExoPlayer.setPlaybackParameters(new PlaybackParameters(speed, 1f)); setPlaybackParameters(speed, getPlaybackPitch());
}
public void setPlaybackPitch(float pitch) {
setPlaybackParameters(getPlaybackSpeed(), pitch);
}
public PlaybackParameters getPlaybackParameters() {
final PlaybackParameters parameters = simpleExoPlayer.getPlaybackParameters();
return parameters == null ? new PlaybackParameters(1f, 1f) : parameters;
}
public void setPlaybackParameters(float speed, float pitch) {
simpleExoPlayer.setPlaybackParameters(new PlaybackParameters(speed, pitch));
} }
public int getCurrentQueueIndex() { public int getCurrentQueueIndex() {

View File

@ -103,7 +103,6 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds
private static final float[] PLAYBACK_SPEEDS = {0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f};
private static final TrackSelection.Factory FIXED_FACTORY = new FixedTrackSelection.Factory(); private static final TrackSelection.Factory FIXED_FACTORY = new FixedTrackSelection.Factory();
private List<TrackGroupInfo> trackGroupInfos; private List<TrackGroupInfo> trackGroupInfos;

View File

@ -122,6 +122,21 @@
android:background="@drawable/player_controls_bg" android:background="@drawable/player_controls_bg"
tools:ignore="RtlHardcoded"> tools:ignore="RtlHardcoded">
<TextView
android:id="@+id/control_playback_speed"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/control_repeat"
android:gravity="center"
android:minWidth="50dp"
android:text="1x"
android:textColor="@android:color/white"
android:textStyle="bold"
tools:ignore="HardcodedText,RtlHardcoded"/>
<ImageButton <ImageButton
android:id="@+id/control_repeat" android:id="@+id/control_repeat"
android:layout_width="25dp" android:layout_width="25dp"
@ -196,6 +211,21 @@
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_palette_white_24dp" android:src="@drawable/ic_palette_white_24dp"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
<TextView
android:id="@+id/control_playback_pitch"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/control_shuffle"
android:gravity="center"
android:minWidth="50dp"
android:text="100%"
android:textColor="@android:color/white"
android:textStyle="bold"
tools:ignore="HardcodedText,RtlHardcoded"/>
</RelativeLayout> </RelativeLayout>
</RelativeLayout> </RelativeLayout>