2018-03-21 07:11:54 +00:00
|
|
|
package org.schabi.newpipe.player.helper;
|
|
|
|
|
2021-11-04 18:47:08 +00:00
|
|
|
import static org.schabi.newpipe.player.Player.DEBUG;
|
|
|
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|
|
|
|
2018-03-21 07:11:54 +00:00
|
|
|
import android.app.Dialog;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.view.View;
|
|
|
|
import android.widget.CheckBox;
|
|
|
|
import android.widget.SeekBar;
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
import androidx.annotation.IdRes;
|
2020-03-31 17:20:15 +00:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.appcompat.app.AlertDialog;
|
|
|
|
import androidx.fragment.app.DialogFragment;
|
2021-01-15 16:11:04 +00:00
|
|
|
import androidx.preference.PreferenceManager;
|
2020-03-31 17:20:15 +00:00
|
|
|
|
2018-03-21 07:11:54 +00:00
|
|
|
import org.schabi.newpipe.R;
|
2018-03-22 03:08:33 +00:00
|
|
|
import org.schabi.newpipe.util.SliderStrategy;
|
2018-03-21 07:11:54 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
import java.util.Objects;
|
|
|
|
import java.util.function.DoubleConsumer;
|
|
|
|
import java.util.function.DoubleFunction;
|
|
|
|
|
|
|
|
import icepick.Icepick;
|
|
|
|
import icepick.State;
|
|
|
|
|
2018-03-21 07:11:54 +00:00
|
|
|
public class PlaybackParameterDialog extends DialogFragment {
|
2022-01-01 18:02:03 +00:00
|
|
|
private static final String TAG = "PlaybackParameterDialog";
|
|
|
|
|
2018-05-12 03:09:02 +00:00
|
|
|
// Minimum allowable range in ExoPlayer
|
2020-04-02 11:51:10 +00:00
|
|
|
private static final double MINIMUM_PLAYBACK_VALUE = 0.10f;
|
|
|
|
private static final double MAXIMUM_PLAYBACK_VALUE = 3.00f;
|
2018-03-21 07:11:54 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private static final double STEP_1_PERCENT_VALUE = 0.01f;
|
|
|
|
private static final double STEP_5_PERCENT_VALUE = 0.05f;
|
|
|
|
private static final double STEP_10_PERCENT_VALUE = 0.10f;
|
|
|
|
private static final double STEP_25_PERCENT_VALUE = 0.25f;
|
|
|
|
private static final double STEP_100_PERCENT_VALUE = 1.00f;
|
2018-03-21 07:11:54 +00:00
|
|
|
|
2020-04-02 11:51:10 +00:00
|
|
|
private static final double DEFAULT_TEMPO = 1.00f;
|
|
|
|
private static final double DEFAULT_PITCH = 1.00f;
|
2022-01-01 18:02:03 +00:00
|
|
|
private static final double DEFAULT_STEP = STEP_25_PERCENT_VALUE;
|
2020-04-02 11:51:10 +00:00
|
|
|
private static final boolean DEFAULT_SKIP_SILENCE = false;
|
2018-06-26 17:18:01 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private static final SliderStrategy QUADRATIC_STRATEGY = new SliderStrategy.Quadratic(
|
|
|
|
MINIMUM_PLAYBACK_VALUE,
|
|
|
|
MAXIMUM_PLAYBACK_VALUE,
|
|
|
|
1.00f,
|
|
|
|
10_000);
|
2018-03-21 07:11:54 +00:00
|
|
|
|
2020-03-31 17:20:15 +00:00
|
|
|
@Nullable
|
|
|
|
private Callback callback;
|
2020-04-02 11:51:10 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
@State
|
|
|
|
double initialTempo = DEFAULT_TEMPO;
|
|
|
|
@State
|
|
|
|
double initialPitch = DEFAULT_PITCH;
|
|
|
|
@State
|
|
|
|
boolean initialSkipSilence = DEFAULT_SKIP_SILENCE;
|
|
|
|
|
|
|
|
@State
|
|
|
|
double tempo = DEFAULT_TEMPO;
|
|
|
|
@State
|
|
|
|
double pitch = DEFAULT_PITCH;
|
|
|
|
@State
|
|
|
|
double stepSize = DEFAULT_STEP;
|
|
|
|
@State
|
|
|
|
boolean skipSilence = DEFAULT_SKIP_SILENCE;
|
2018-06-26 17:18:01 +00:00
|
|
|
|
2020-03-31 17:20:15 +00:00
|
|
|
private SeekBar tempoSlider;
|
|
|
|
private TextView tempoCurrentText;
|
|
|
|
private TextView tempoStepDownText;
|
|
|
|
private TextView tempoStepUpText;
|
2022-01-01 18:02:03 +00:00
|
|
|
|
2020-03-31 17:20:15 +00:00
|
|
|
private SeekBar pitchSlider;
|
|
|
|
private TextView pitchCurrentText;
|
|
|
|
private TextView pitchStepDownText;
|
|
|
|
private TextView pitchStepUpText;
|
2022-01-01 18:02:03 +00:00
|
|
|
|
2020-03-31 17:20:15 +00:00
|
|
|
private CheckBox unhookingCheckbox;
|
|
|
|
private CheckBox skipSilenceCheckbox;
|
2018-03-22 03:08:33 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
public static PlaybackParameterDialog newInstance(
|
|
|
|
final double playbackTempo,
|
|
|
|
final double playbackPitch,
|
|
|
|
final boolean playbackSkipSilence,
|
|
|
|
final Callback callback
|
|
|
|
) {
|
2020-08-16 08:24:58 +00:00
|
|
|
final PlaybackParameterDialog dialog = new PlaybackParameterDialog();
|
2019-12-29 21:15:01 +00:00
|
|
|
dialog.callback = callback;
|
2022-01-01 18:02:03 +00:00
|
|
|
|
2018-03-21 07:11:54 +00:00
|
|
|
dialog.initialTempo = playbackTempo;
|
|
|
|
dialog.initialPitch = playbackPitch;
|
2022-01-01 18:02:03 +00:00
|
|
|
dialog.initialSkipSilence = playbackSkipSilence;
|
2018-06-26 17:18:01 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
dialog.tempo = dialog.initialTempo;
|
|
|
|
dialog.pitch = dialog.initialPitch;
|
|
|
|
dialog.skipSilence = dialog.initialSkipSilence;
|
2018-06-26 17:18:01 +00:00
|
|
|
|
2018-03-21 07:11:54 +00:00
|
|
|
return dialog;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Lifecycle
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@Override
|
2022-01-01 18:02:03 +00:00
|
|
|
public void onAttach(final Context context) {
|
2018-03-21 07:11:54 +00:00
|
|
|
super.onAttach(context);
|
2019-12-29 21:15:01 +00:00
|
|
|
if (context instanceof Callback) {
|
2018-03-21 07:11:54 +00:00
|
|
|
callback = (Callback) context;
|
2019-12-29 21:15:01 +00:00
|
|
|
} else if (callback == null) {
|
2018-03-21 07:11:54 +00:00
|
|
|
dismiss();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-01-01 18:02:03 +00:00
|
|
|
public void onSaveInstanceState(final Bundle outState) {
|
2018-03-21 07:11:54 +00:00
|
|
|
super.onSaveInstanceState(outState);
|
2022-01-01 18:02:03 +00:00
|
|
|
Icepick.saveInstanceState(this, outState);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Dialog
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
|
|
|
@NonNull
|
|
|
|
@Override
|
2020-03-31 17:20:15 +00:00
|
|
|
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
2020-01-28 19:48:42 +00:00
|
|
|
assureCorrectAppLanguage(getContext());
|
2022-01-01 18:02:03 +00:00
|
|
|
Icepick.restoreInstanceState(this, savedInstanceState);
|
|
|
|
|
2018-03-21 07:11:54 +00:00
|
|
|
final View view = View.inflate(getContext(), R.layout.dialog_playback_parameter, null);
|
2022-01-01 18:02:03 +00:00
|
|
|
initUI(view);
|
|
|
|
initUIData();
|
2018-03-21 07:11:54 +00:00
|
|
|
|
|
|
|
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireActivity())
|
|
|
|
.setView(view)
|
|
|
|
.setCancelable(true)
|
2022-01-01 18:02:03 +00:00
|
|
|
.setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
|
|
|
|
setAndUpdateTempo(initialTempo);
|
|
|
|
setAndUpdatePitch(initialPitch);
|
|
|
|
setAndUpdateSkipSilence(initialSkipSilence);
|
|
|
|
updateCallback();
|
|
|
|
})
|
|
|
|
.setNeutralButton(R.string.playback_reset, (dialogInterface, i) -> {
|
|
|
|
setAndUpdateTempo(DEFAULT_TEMPO);
|
|
|
|
setAndUpdatePitch(DEFAULT_PITCH);
|
|
|
|
setAndUpdateSkipSilence(DEFAULT_SKIP_SILENCE);
|
|
|
|
updateCallback();
|
|
|
|
})
|
|
|
|
.setPositiveButton(R.string.ok, (dialogInterface, i) -> updateCallback());
|
2018-03-21 07:11:54 +00:00
|
|
|
|
|
|
|
return dialogBuilder.create();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
2018-03-22 03:08:33 +00:00
|
|
|
// Control Views
|
2018-03-21 07:11:54 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void initUI(@NonNull final View rootView) {
|
|
|
|
// Tempo
|
|
|
|
tempoSlider = Objects.requireNonNull(rootView.findViewById(R.id.tempoSeekbar));
|
|
|
|
tempoCurrentText = Objects.requireNonNull(rootView.findViewById(R.id.tempoCurrentText));
|
|
|
|
tempoStepUpText = Objects.requireNonNull(rootView.findViewById(R.id.tempoStepUp));
|
|
|
|
tempoStepDownText = Objects.requireNonNull(rootView.findViewById(R.id.tempoStepDown));
|
|
|
|
|
|
|
|
setText(rootView, R.id.tempoMinimumText, PlayerHelper::formatSpeed, MINIMUM_PLAYBACK_VALUE);
|
|
|
|
setText(rootView, R.id.tempoMaximumText, PlayerHelper::formatSpeed, MAXIMUM_PLAYBACK_VALUE);
|
|
|
|
|
|
|
|
// Pitch
|
|
|
|
pitchSlider = Objects.requireNonNull(rootView.findViewById(R.id.pitchSeekbar));
|
|
|
|
pitchCurrentText = Objects.requireNonNull(rootView.findViewById(R.id.pitchCurrentText));
|
|
|
|
pitchStepUpText = Objects.requireNonNull(rootView.findViewById(R.id.pitchStepUp));
|
|
|
|
pitchStepDownText = Objects.requireNonNull(rootView.findViewById(R.id.pitchStepDown));
|
|
|
|
|
|
|
|
setText(rootView, R.id.pitchMinimumText, PlayerHelper::formatPitch, MINIMUM_PLAYBACK_VALUE);
|
|
|
|
setText(rootView, R.id.pitchMaximumText, PlayerHelper::formatPitch, MAXIMUM_PLAYBACK_VALUE);
|
|
|
|
|
|
|
|
// Steps
|
|
|
|
setupStepTextView(rootView, R.id.stepSizeOnePercent, STEP_1_PERCENT_VALUE);
|
|
|
|
setupStepTextView(rootView, R.id.stepSizeFivePercent, STEP_5_PERCENT_VALUE);
|
|
|
|
setupStepTextView(rootView, R.id.stepSizeTenPercent, STEP_10_PERCENT_VALUE);
|
|
|
|
setupStepTextView(rootView, R.id.stepSizeTwentyFivePercent, STEP_25_PERCENT_VALUE);
|
|
|
|
setupStepTextView(rootView, R.id.stepSizeOneHundredPercent, STEP_100_PERCENT_VALUE);
|
|
|
|
|
|
|
|
// Bottom controls
|
|
|
|
unhookingCheckbox =
|
|
|
|
Objects.requireNonNull(rootView.findViewById(R.id.unhookCheckbox));
|
|
|
|
skipSilenceCheckbox =
|
|
|
|
Objects.requireNonNull(rootView.findViewById(R.id.skipSilenceCheckbox));
|
|
|
|
}
|
|
|
|
|
|
|
|
private TextView setText(
|
|
|
|
final TextView textView,
|
|
|
|
final DoubleFunction<String> formatter,
|
|
|
|
final double value
|
|
|
|
) {
|
|
|
|
Objects.requireNonNull(textView).setText(formatter.apply(value));
|
|
|
|
return textView;
|
|
|
|
}
|
|
|
|
|
|
|
|
private TextView setText(
|
|
|
|
final View rootView,
|
|
|
|
@IdRes final int idRes,
|
|
|
|
final DoubleFunction<String> formatter,
|
|
|
|
final double value
|
|
|
|
) {
|
|
|
|
final TextView textView = rootView.findViewById(idRes);
|
|
|
|
setText(textView, formatter, value);
|
|
|
|
return textView;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setupStepTextView(
|
|
|
|
final View rootView,
|
|
|
|
@IdRes final int idRes,
|
|
|
|
final double stepSizeValue
|
|
|
|
) {
|
|
|
|
setText(rootView, idRes, PlaybackParameterDialog::getPercentString, stepSizeValue)
|
|
|
|
.setOnClickListener(view -> setAndUpdateStepSize(stepSizeValue));
|
|
|
|
}
|
|
|
|
|
|
|
|
private void initUIData() {
|
|
|
|
// Tempo
|
|
|
|
tempoSlider.setMax(QUADRATIC_STRATEGY.progressOf(MAXIMUM_PLAYBACK_VALUE));
|
|
|
|
setAndUpdateTempo(tempo);
|
|
|
|
tempoSlider.setOnSeekBarChangeListener(
|
|
|
|
getTempoOrPitchSeekbarChangeListener(this::onTempoSliderUpdated));
|
|
|
|
|
|
|
|
registerOnStepClickListener(
|
|
|
|
tempoStepDownText, tempo, -1, this::onTempoSliderUpdated);
|
|
|
|
registerOnStepClickListener(
|
|
|
|
tempoStepUpText, tempo, 1, this::onTempoSliderUpdated);
|
|
|
|
|
|
|
|
// Pitch
|
|
|
|
pitchSlider.setMax(QUADRATIC_STRATEGY.progressOf(MAXIMUM_PLAYBACK_VALUE));
|
|
|
|
setAndUpdatePitch(pitch);
|
|
|
|
pitchSlider.setOnSeekBarChangeListener(
|
|
|
|
getTempoOrPitchSeekbarChangeListener(this::onPitchSliderUpdated));
|
|
|
|
|
|
|
|
registerOnStepClickListener(
|
|
|
|
pitchStepDownText, pitch, -1, this::onPitchSliderUpdated);
|
|
|
|
registerOnStepClickListener(
|
|
|
|
pitchStepUpText, pitch, 1, this::onPitchSliderUpdated);
|
|
|
|
|
|
|
|
// Steps
|
|
|
|
setAndUpdateStepSize(stepSize);
|
|
|
|
|
|
|
|
// Bottom controls
|
|
|
|
// restore whether pitch and tempo are unhooked or not
|
|
|
|
unhookingCheckbox.setChecked(PreferenceManager
|
2021-12-21 17:17:48 +00:00
|
|
|
.getDefaultSharedPreferences(requireContext())
|
2022-01-01 18:02:03 +00:00
|
|
|
.getBoolean(getString(R.string.playback_unhook_key), true));
|
2021-12-21 17:17:48 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
unhookingCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
|
|
|
// save whether pitch and tempo are unhooked or not
|
|
|
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
2021-12-21 17:17:48 +00:00
|
|
|
.edit()
|
2022-01-01 18:02:03 +00:00
|
|
|
.putBoolean(getString(R.string.playback_unhook_key), isChecked)
|
2021-12-21 17:17:48 +00:00
|
|
|
.apply();
|
2018-05-08 18:24:42 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
if (!isChecked) {
|
|
|
|
// when unchecked, slide back to the minimum of current tempo or pitch
|
|
|
|
setSliders(Math.min(pitch, tempo));
|
|
|
|
}
|
|
|
|
});
|
2018-05-08 18:24:42 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
setAndUpdateSkipSilence(skipSilence);
|
|
|
|
skipSilenceCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
|
|
|
skipSilence = isChecked;
|
|
|
|
updateCallback();
|
|
|
|
});
|
2018-05-08 18:24:42 +00:00
|
|
|
}
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void registerOnStepClickListener(
|
|
|
|
final TextView stepTextView,
|
|
|
|
final double currentValue,
|
|
|
|
final double direction, // -1 for step down, +1 for step up
|
|
|
|
final DoubleConsumer newValueConsumer
|
|
|
|
) {
|
|
|
|
stepTextView.setOnClickListener(view ->
|
|
|
|
newValueConsumer.accept(currentValue * direction)
|
|
|
|
);
|
2021-12-21 17:17:48 +00:00
|
|
|
}
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void setAndUpdateStepSize(final double newStepSize) {
|
|
|
|
this.stepSize = newStepSize;
|
2021-12-21 17:17:48 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
tempoStepUpText.setText(getStepUpPercentString(newStepSize));
|
|
|
|
tempoStepDownText.setText(getStepDownPercentString(newStepSize));
|
2018-05-08 18:24:42 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
pitchStepUpText.setText(getStepUpPercentString(newStepSize));
|
|
|
|
pitchStepDownText.setText(getStepDownPercentString(newStepSize));
|
|
|
|
}
|
2021-12-21 17:17:48 +00:00
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void setAndUpdateSkipSilence(final boolean newSkipSilence) {
|
|
|
|
this.skipSilence = newSkipSilence;
|
|
|
|
skipSilenceCheckbox.setChecked(newSkipSilence);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
2018-03-22 03:08:33 +00:00
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Sliders
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private SeekBar.OnSeekBarChangeListener getTempoOrPitchSeekbarChangeListener(
|
|
|
|
final DoubleConsumer newValueConsumer
|
|
|
|
) {
|
|
|
|
return new SeekBar.OnSeekBarChangeListener() {
|
2018-03-21 07:11:54 +00:00
|
|
|
@Override
|
2022-01-01 18:02:03 +00:00
|
|
|
public void onProgressChanged(final SeekBar seekBar, final int progress,
|
2020-03-31 17:20:15 +00:00
|
|
|
final boolean fromUser) {
|
2022-01-01 18:02:03 +00:00
|
|
|
if (fromUser) { // this change is first in chain
|
|
|
|
newValueConsumer.accept(QUADRATIC_STRATEGY.valueOf(progress));
|
|
|
|
updateCallback();
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-01-01 18:02:03 +00:00
|
|
|
public void onStartTrackingTouch(final SeekBar seekBar) {
|
|
|
|
// Do nothing
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 17:17:48 +00:00
|
|
|
@Override
|
2022-01-01 18:02:03 +00:00
|
|
|
public void onStopTrackingTouch(final SeekBar seekBar) {
|
|
|
|
// Do nothing
|
2021-12-21 17:17:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-03-22 03:08:33 +00:00
|
|
|
private void onTempoSliderUpdated(final double newTempo) {
|
2018-03-21 07:11:54 +00:00
|
|
|
if (!unhookingCheckbox.isChecked()) {
|
|
|
|
setSliders(newTempo);
|
|
|
|
} else {
|
2022-01-01 18:02:03 +00:00
|
|
|
setAndUpdateTempo(newTempo);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 03:08:33 +00:00
|
|
|
private void onPitchSliderUpdated(final double newPitch) {
|
2018-03-21 07:11:54 +00:00
|
|
|
if (!unhookingCheckbox.isChecked()) {
|
|
|
|
setSliders(newPitch);
|
|
|
|
} else {
|
2022-01-01 18:02:03 +00:00
|
|
|
setAndUpdatePitch(newPitch);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-22 03:08:33 +00:00
|
|
|
private void setSliders(final double newValue) {
|
2022-01-01 18:02:03 +00:00
|
|
|
setAndUpdateTempo(newValue);
|
|
|
|
setAndUpdatePitch(newValue);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void setAndUpdateTempo(final double newTempo) {
|
|
|
|
this.tempo = newTempo;
|
|
|
|
tempoSlider.setProgress(QUADRATIC_STRATEGY.progressOf(tempo));
|
|
|
|
setText(tempoCurrentText, PlayerHelper::formatSpeed, tempo);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void setAndUpdatePitch(final double newPitch) {
|
|
|
|
this.pitch = newPitch;
|
|
|
|
pitchSlider.setProgress(QUADRATIC_STRATEGY.progressOf(pitch));
|
|
|
|
setText(pitchCurrentText, PlayerHelper::formatPitch, pitch);
|
2021-12-21 17:17:48 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 03:08:33 +00:00
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Helper
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2022-01-01 18:02:03 +00:00
|
|
|
private void updateCallback() {
|
|
|
|
if (callback == null) {
|
|
|
|
return;
|
2021-12-21 17:17:48 +00:00
|
|
|
}
|
2022-01-01 18:02:03 +00:00
|
|
|
if (DEBUG) {
|
|
|
|
Log.d(TAG, "Updating callback: "
|
|
|
|
+ "tempo = [" + tempo + "], "
|
|
|
|
+ "pitch = [" + pitch + "], "
|
|
|
|
+ "skipSilence = [" + skipSilence + "]"
|
|
|
|
);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
2022-01-01 18:02:03 +00:00
|
|
|
callback.onPlaybackParameterChanged((float) tempo, (float) pitch, skipSilence);
|
2021-12-21 17:17:48 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 03:08:33 +00:00
|
|
|
@NonNull
|
|
|
|
private static String getStepUpPercentString(final double percent) {
|
2022-01-01 18:02:03 +00:00
|
|
|
return '+' + getPercentString(percent);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
|
2018-03-22 03:08:33 +00:00
|
|
|
@NonNull
|
|
|
|
private static String getStepDownPercentString(final double percent) {
|
2022-01-01 18:02:03 +00:00
|
|
|
return '-' + getPercentString(percent);
|
2018-05-08 18:24:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@NonNull
|
|
|
|
private static String getPercentString(final double percent) {
|
|
|
|
return PlayerHelper.formatPitch(percent);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
2020-04-02 11:51:10 +00:00
|
|
|
|
2020-03-31 17:20:15 +00:00
|
|
|
public interface Callback {
|
|
|
|
void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
|
|
|
|
boolean playbackSkipSilence);
|
2018-03-21 07:11:54 +00:00
|
|
|
}
|
|
|
|
}
|