Skip to content

Commit 0e591ab

Browse files
committed
Add chapter markers support to seekbar and update UI elements
1 parent 44bf345 commit 0e591ab

3 files changed

Lines changed: 73 additions & 2 deletions

File tree

app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@
6666
import org.schabi.newpipe.extractor.MediaFormat;
6767
import org.schabi.newpipe.extractor.stream.AudioStream;
6868
import org.schabi.newpipe.extractor.stream.StreamInfo;
69+
import org.schabi.newpipe.extractor.stream.StreamSegment;
6970
import org.schabi.newpipe.extractor.stream.VideoStream;
71+
import org.schabi.newpipe.views.ChaptersSeekBar;
7072
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
7173
import org.schabi.newpipe.ktx.AnimationType;
7274
import org.schabi.newpipe.player.Player;
@@ -86,6 +88,7 @@
8688
import org.schabi.newpipe.util.external_communication.ShareUtils;
8789
import org.schabi.newpipe.views.player.PlayerFastSeekOverlay;
8890

91+
import java.util.Collections;
8992
import java.util.List;
9093
import java.util.Objects;
9194
import java.util.Optional;
@@ -148,6 +151,9 @@ private enum PlayButtonAction {
148151
private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder =
149152
new SeekbarPreviewThumbnailHolder();
150153

154+
@NonNull
155+
private List<StreamSegment> currentChapters = Collections.emptyList();
156+
151157

152158
/*//////////////////////////////////////////////////////////////////////////
153159
// Constructor, setup, destroy
@@ -586,6 +592,14 @@ public void onProgressChanged(final SeekBar seekBar, final int progress,
586592
binding.currentSeekbarPreviewThumbnail,
587593
binding.subtitleView::getWidth);
588594

595+
// Chapter title tooltip
596+
if (!currentChapters.isEmpty()) {
597+
final StreamSegment chapter = getChapterAtMs(progress);
598+
if (chapter != null && chapter.getTitle() != null) {
599+
binding.currentChapterTitle.setText(chapter.getTitle());
600+
}
601+
}
602+
589603
adjustSeekbarPreviewContainer();
590604
}
591605

@@ -639,6 +653,10 @@ public void onStartTrackingTouch(final SeekBar seekBar) {
639653
AnimationType.SCALE_AND_ALPHA);
640654
animate(binding.currentSeekbarPreviewThumbnail, true, DEFAULT_CONTROLS_DURATION,
641655
AnimationType.SCALE_AND_ALPHA);
656+
if (!currentChapters.isEmpty()) {
657+
animate(binding.currentChapterTitle, true, DEFAULT_CONTROLS_DURATION,
658+
AnimationType.SCALE_AND_ALPHA);
659+
}
642660
}
643661

644662
@Override // seekbar listener
@@ -655,6 +673,7 @@ public void onStopTrackingTouch(final SeekBar seekBar) {
655673
binding.playbackCurrentTime.setText(getTimeString(seekBar.getProgress()));
656674
animate(binding.currentDisplaySeek, false, 200, AnimationType.SCALE_AND_ALPHA);
657675
animate(binding.currentSeekbarPreviewThumbnail, false, 200, AnimationType.SCALE_AND_ALPHA);
676+
animate(binding.currentChapterTitle, false, 200, AnimationType.SCALE_AND_ALPHA);
658677

659678
if (player.getCurrentState() == STATE_PAUSED_SEEK) {
660679
player.changeState(STATE_BUFFERING);
@@ -665,6 +684,25 @@ public void onStopTrackingTouch(final SeekBar seekBar) {
665684

666685
showControlsThenHide();
667686
}
687+
688+
/**
689+
* Returns the chapter active at the given playback position, or {@code null} if
690+
* {@code currentChapters} is empty.
691+
*
692+
* @param positionMs playback position in milliseconds
693+
* @return the {@link StreamSegment} whose window contains {@code positionMs}
694+
*/
695+
@Nullable
696+
private StreamSegment getChapterAtMs(final long positionMs) {
697+
StreamSegment result = null;
698+
for (final StreamSegment seg : currentChapters) {
699+
if (seg.getStartTimeSeconds() * 1000L > positionMs) {
700+
break;
701+
}
702+
result = seg;
703+
}
704+
return result;
705+
}
668706
//endregion
669707

670708

@@ -1023,6 +1061,22 @@ public void onMetadataChanged(@NonNull final StreamInfo info) {
10231061
binding.channelTextView.setText(info.getUploaderName());
10241062

10251063
this.seekbarPreviewThumbnailHolder.resetFrom(player.getContext(), info.getPreviewFrames());
1064+
1065+
// Chapter markers on seekbar
1066+
currentChapters = info.getStreamSegments() != null
1067+
? info.getStreamSegments() : Collections.emptyList();
1068+
Log.d(TAG, "onMetadataChanged: seekBarClass="
1069+
+ binding.playbackSeekBar.getClass().getSimpleName()
1070+
+ " segments=" + currentChapters.size()
1071+
+ " duration=" + info.getDuration());
1072+
if (binding.playbackSeekBar instanceof ChaptersSeekBar) {
1073+
((ChaptersSeekBar) binding.playbackSeekBar)
1074+
.setChapters(currentChapters, info.getDuration());
1075+
} else {
1076+
Log.e(TAG, "onMetadataChanged: playbackSeekBar is NOT a ChaptersSeekBar! "
1077+
+ "Check that player.xml was rebuilt.");
1078+
}
1079+
binding.currentChapterTitle.setVisibility(View.GONE);
10261080
}
10271081

10281082
private void updateStreamRelatedViews() {

app/src/main/java/org/schabi/newpipe/views/FocusAwareSeekBar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* (onStartTrackingTouch/onStopTrackingTouch), so existing code does not need to be changed to
3434
* work with it.
3535
*/
36-
public final class FocusAwareSeekBar extends AppCompatSeekBar {
36+
public class FocusAwareSeekBar extends AppCompatSeekBar {
3737
private NestedListener listener;
3838

3939
private ViewTreeObserver treeObserver;

app/src/main/res/layout/player.xml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,23 @@
415415
android:orientation="vertical"
416416
android:paddingBottom="12dp">
417417

418+
<org.schabi.newpipe.views.NewPipeTextView
419+
android:id="@+id/currentChapterTitle"
420+
android:layout_width="wrap_content"
421+
android:layout_height="wrap_content"
422+
android:background="#60000000"
423+
android:ellipsize="end"
424+
android:maxLines="1"
425+
android:paddingLeft="5dp"
426+
android:paddingRight="5dp"
427+
android:paddingBottom="2dp"
428+
android:textColor="@android:color/white"
429+
android:textSize="12sp"
430+
android:visibility="gone"
431+
tools:ignore="RtlHardcoded"
432+
tools:text="Introduction"
433+
tools:visibility="visible" />
434+
418435
<org.schabi.newpipe.views.NewPipeTextView
419436
android:id="@+id/currentDisplaySeek"
420437
android:layout_width="wrap_content"
@@ -467,7 +484,7 @@
467484
tools:text="1:06:29" />
468485

469486

470-
<org.schabi.newpipe.views.FocusAwareSeekBar
487+
<org.schabi.newpipe.views.ChaptersSeekBar
471488
android:id="@+id/playbackSeekBar"
472489
style="@style/Widget.AppCompat.SeekBar"
473490
android:layout_width="0dp"

0 commit comments

Comments
 (0)