Skip to content

Commit 9421566

Browse files
folkematQuantumBadger
authored andcommitted
Added playback speed control
1 parent f7c9b90 commit 9421566

File tree

2 files changed

+147
-2
lines changed

2 files changed

+147
-2
lines changed

src/main/java/org/quantumbadger/redreader/views/video/ExoPlayerWrapperView.java

Lines changed: 142 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
import android.widget.LinearLayout;
2828
import android.widget.RelativeLayout;
2929
import android.widget.TextView;
30-
30+
import android.widget.Button;
31+
import android.widget.SeekBar;
3132
import androidx.annotation.DrawableRes;
3233
import androidx.annotation.NonNull;
3334
import androidx.annotation.Nullable;
@@ -44,6 +45,7 @@
4445
import androidx.media3.ui.PlayerView;
4546
import androidx.media3.ui.TimeBar;
4647

48+
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
4749
import org.quantumbadger.redreader.R;
4850
import org.quantumbadger.redreader.common.AndroidCommon;
4951
import org.quantumbadger.redreader.common.General;
@@ -70,6 +72,9 @@ public interface Listener {
7072
@Nullable private final DefaultTimeBar mTimeBarView;
7173
@Nullable private final TextView mTimeTextView;
7274

75+
@Nullable private final TextView mSpeedTextView;
76+
private float mCurrentPlaybackSpeed = 1.0f;
77+
7378
private boolean mReleased;
7479

7580
public ExoPlayerWrapperView(
@@ -233,6 +238,15 @@ public ExoPlayerWrapperView(
233238
addButton(zoomButton.get(), buttons);
234239
}
235240

241+
addButton(createButton(
242+
context,
243+
mControlView,
244+
R.drawable.ic_time_dark,
245+
R.string.video_speed_setting,
246+
view -> {
247+
openSpeedSettingDialog(context);
248+
}), buttons);
249+
236250
mTimeBarView = new DefaultTimeBar(context, null);
237251
controlBar.addView(mTimeBarView);
238252

@@ -279,11 +293,20 @@ public void run() {
279293
updateProgressRunnable.run();
280294

281295
{
296+
final LinearLayout timeAndSpeedLayout = new LinearLayout(context);
297+
timeAndSpeedLayout.setOrientation(LinearLayout.HORIZONTAL);
298+
controlBar.addView(timeAndSpeedLayout);
299+
282300
mTimeTextView = new TextView(context);
283-
controlBar.addView(mTimeTextView);
301+
timeAndSpeedLayout.addView(mTimeTextView);
284302
mTimeTextView.setTextColor(Color.WHITE);
285303
mTimeTextView.setTextSize(18);
286304

305+
mSpeedTextView = new TextView(context);
306+
timeAndSpeedLayout.addView(mSpeedTextView);
307+
mSpeedTextView.setTextColor(Color.WHITE);
308+
mSpeedTextView.setText(String.format(Locale.US, "(%.2fx)", mCurrentPlaybackSpeed));
309+
287310
final int marginSidesPx = General.dpToPixels(context, 16);
288311
final int marginBottomPx = General.dpToPixels(context, 8);
289312

@@ -300,6 +323,7 @@ public void run() {
300323
mControlView = null;
301324
mTimeBarView = null;
302325
mTimeTextView = null;
326+
mSpeedTextView = null;
303327
}
304328

305329
videoPlayerView.setLayoutParams(new FrameLayout.LayoutParams(
@@ -436,4 +460,120 @@ public static String msToMinutesAndSecondsString(final long ms) {
436460

437461
return String.format(Locale.US, "%d:%02d", mins, secs);
438462
}
463+
private void openSpeedSettingDialog(final Context context) {
464+
// Pause video playback before opening the dialog
465+
mVideoPlayer.setPlayWhenReady(false);
466+
467+
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
468+
builder.setTitle(R.string.video_speed_instruction);
469+
470+
final LinearLayout speedSettingsLayout = new LinearLayout(context);
471+
speedSettingsLayout.setOrientation(LinearLayout.VERTICAL);
472+
speedSettingsLayout.setPadding(20, 20, 20, 20);
473+
474+
final TextView speedValue = new TextView(context);
475+
speedValue.setText(String.format(
476+
Locale.US,
477+
getResources().getString(R.string.video_speed_term) + ": %.2fx",
478+
mCurrentPlaybackSpeed)
479+
);
480+
speedValue.setTextSize(18);
481+
speedValue.setPadding(10, 10, 10, 10);
482+
483+
final SeekBar speedSeekBar = new SeekBar(context);
484+
speedSeekBar.setMax(300 - 1); // 3.00 is max for now
485+
486+
final LinearLayout.LayoutParams seekBarParams = new LinearLayout.LayoutParams(
487+
LinearLayout.LayoutParams.MATCH_PARENT,
488+
LinearLayout.LayoutParams.WRAP_CONTENT
489+
);
490+
seekBarParams.height = 150;
491+
speedSeekBar.setLayoutParams(seekBarParams);
492+
493+
speedSeekBar.setProgress((int) ((mCurrentPlaybackSpeed - 0.01) * 100));
494+
495+
// Listener for changes in the SeekBar's position
496+
speedSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
497+
@Override
498+
public void onProgressChanged(final SeekBar seekBar,
499+
final int progress,final boolean fromUser) {
500+
final float selectedSpeed = 0.01f * (progress + 1);
501+
speedValue.setText(String.format(
502+
Locale.US,
503+
getResources().getString(R.string.video_speed_term) + ": %.2fx",
504+
selectedSpeed)
505+
);
506+
}
507+
508+
@Override
509+
public void onStartTrackingTouch(final SeekBar seekBar) { }
510+
511+
@Override
512+
public void onStopTrackingTouch(final SeekBar seekBar) { }
513+
});
514+
515+
speedSettingsLayout.addView(speedValue);
516+
speedSettingsLayout.addView(speedSeekBar);
517+
518+
// Creating rows for the speed preset buttons
519+
final LinearLayout[] rows = new LinearLayout[4];
520+
for (int i = 0; i < rows.length; i++) {
521+
rows[i] = new LinearLayout(context);
522+
rows[i].setOrientation(LinearLayout.HORIZONTAL);
523+
speedSettingsLayout.addView(rows[i]);
524+
}
525+
526+
// Labels and values for the preset speed buttons
527+
final String[] speedLabels = {"0.5", "1.0", "1.5", "2.0"};
528+
final int[] speedProgressValues = {49, 99, 149, 199};
529+
530+
// Adding preset speed buttons to the layout
531+
for (int i = 0; i < speedLabels.length; i++) {
532+
addPresetSpeedButton(rows[i / 4], speedLabels[i],
533+
speedProgressValues[i], speedSeekBar, speedValue, context);
534+
}
535+
536+
builder.setView(speedSettingsLayout);
537+
538+
builder.setPositiveButton(R.string.dialog_go, (dialog, which) -> {
539+
mCurrentPlaybackSpeed = 0.01f * (speedSeekBar.getProgress() + 1);
540+
mVideoPlayer.setPlaybackSpeed(mCurrentPlaybackSpeed);
541+
mSpeedTextView.setText(String.format(Locale.US, "(%.2fx)", mCurrentPlaybackSpeed));
542+
// Resume video playback when dialog is dismissed
543+
mVideoPlayer.setPlayWhenReady(true);
544+
});
545+
builder.setNegativeButton(R.string.dialog_cancel, (dialog, which) -> {
546+
// Resume video playback when dialog is dismissed
547+
mVideoPlayer.setPlayWhenReady(true);
548+
});
549+
550+
builder.setOnCancelListener(dialog -> {
551+
// Resume video playback when dialog is canceled
552+
mVideoPlayer.setPlayWhenReady(true);
553+
});
554+
555+
builder.show();
556+
}
557+
558+
// Method to add a preset speed button to the layout
559+
private void addPresetSpeedButton(final LinearLayout rowLayout, final String label,
560+
final int progress, final SeekBar seekBar,
561+
final TextView speedValue, final Context context) {
562+
final Button speedButton = new Button(context);
563+
speedButton.setText(label);
564+
// Setting button click behavior to update the SeekBar and speedValue TextView
565+
speedButton.setOnClickListener(v -> {
566+
seekBar.setProgress(progress);
567+
final float selectedSpeed = 0.01f * (progress + 1);
568+
speedValue.setText(String.format(
569+
Locale.US,
570+
getResources().getString(R.string.video_speed_term) + ": %.2fx",
571+
selectedSpeed)
572+
);
573+
});
574+
575+
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
576+
0, LayoutParams.WRAP_CONTENT, 1.0f);
577+
rowLayout.addView(speedButton, params);
578+
}
439579
}

src/main/res/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,4 +1902,9 @@
19021902
<string name="album_grid_pref_horizontal_padding">Horizontal padding</string>
19031903

19041904
<string name="album_pref_compact_title">Compact title</string>
1905+
1906+
<!-- 2025-03-12 -->
1907+
<string name="video_speed_setting">Change video speed</string>
1908+
<string name="video_speed_instruction">Choose playback speed</string>
1909+
<string name="video_speed_term">Speed</string>
19051910
</resources>

0 commit comments

Comments
 (0)