Commit 76ce0cc6 by tonihei Committed by Marc Baechinger

Ensure onMediaItemTransition is sent for repeats of the same item

Currently, repeating the same item (via seekNext/Previous) implicitly
results in a seek to the default position of the current item, which
looks exactly the same as a direct seek. As a result, we don't send
onMediaItemTransition as we would for every other seekNext/Previous
call.

This can be fixed by explicitly marking the repeat case in the internal
BasePlayer/ExoPlayerImpl methods, so that the callback can be triggered.

Issue: google/ExoPlayer#10667
PiperOrigin-RevId: 481951788
parent a404fde4
...@@ -21,6 +21,7 @@ import static java.lang.Math.min; ...@@ -21,6 +21,7 @@ import static java.lang.Math.min;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.ForOverride;
import java.util.List; import java.util.List;
/** Abstract base {@link Player} which implements common implementation independent methods. */ /** Abstract base {@link Player} which implements common implementation independent methods. */
...@@ -185,7 +186,12 @@ public abstract class BasePlayer implements Player { ...@@ -185,7 +186,12 @@ public abstract class BasePlayer implements Player {
@Override @Override
public final void seekToPreviousMediaItem() { public final void seekToPreviousMediaItem() {
int previousMediaItemIndex = getPreviousMediaItemIndex(); int previousMediaItemIndex = getPreviousMediaItemIndex();
if (previousMediaItemIndex != C.INDEX_UNSET) { if (previousMediaItemIndex == C.INDEX_UNSET) {
return;
}
if (previousMediaItemIndex == getCurrentMediaItemIndex()) {
repeatCurrentMediaItem();
} else {
seekToDefaultPosition(previousMediaItemIndex); seekToDefaultPosition(previousMediaItemIndex);
} }
} }
...@@ -252,7 +258,12 @@ public abstract class BasePlayer implements Player { ...@@ -252,7 +258,12 @@ public abstract class BasePlayer implements Player {
@Override @Override
public final void seekToNextMediaItem() { public final void seekToNextMediaItem() {
int nextMediaItemIndex = getNextMediaItemIndex(); int nextMediaItemIndex = getNextMediaItemIndex();
if (nextMediaItemIndex != C.INDEX_UNSET) { if (nextMediaItemIndex == C.INDEX_UNSET) {
return;
}
if (nextMediaItemIndex == getCurrentMediaItemIndex()) {
repeatCurrentMediaItem();
} else {
seekToDefaultPosition(nextMediaItemIndex); seekToDefaultPosition(nextMediaItemIndex);
} }
} }
...@@ -424,6 +435,17 @@ public abstract class BasePlayer implements Player { ...@@ -424,6 +435,17 @@ public abstract class BasePlayer implements Player {
: timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs(); : timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs();
} }
/**
* Repeat the current media item.
*
* <p>The default implementation seeks to the default position in the current item, which can be
* overridden for additional handling.
*/
@ForOverride
protected void repeatCurrentMediaItem() {
seekToDefaultPosition();
}
private @RepeatMode int getRepeatModeForNavigation() { private @RepeatMode int getRepeatModeForNavigation() {
@RepeatMode int repeatMode = getRepeatMode(); @RepeatMode int repeatMode = getRepeatMode();
return repeatMode == REPEAT_MODE_ONE ? REPEAT_MODE_OFF : repeatMode; return repeatMode == REPEAT_MODE_ONE ? REPEAT_MODE_OFF : repeatMode;
......
...@@ -8812,6 +8812,39 @@ public final class ExoPlayerTest { ...@@ -8812,6 +8812,39 @@ public final class ExoPlayerTest {
} }
@Test @Test
public void seekToNextPrevious_singleItemRepeat_notifiesMediaItemTransition() throws Exception {
List<MediaItem> reportedMediaItems = new ArrayList<>();
List<Integer> reportedTransitionReasons = new ArrayList<>();
MediaSource mediaSource = FakeMediaSource.createWithWindowId(/* windowId= */ new Object());
ExoPlayer player = new TestExoPlayerBuilder(context).build();
player.addListener(
new Listener() {
@Override
public void onMediaItemTransition(@Nullable MediaItem mediaItem, int reason) {
reportedMediaItems.add(mediaItem);
reportedTransitionReasons.add(reason);
}
});
player.setMediaSource(mediaSource);
player.prepare();
runUntilPlaybackState(player, Player.STATE_READY);
player.setRepeatMode(Player.REPEAT_MODE_ALL);
player.seekToNextMediaItem();
player.seekToPreviousMediaItem();
player.release();
MediaItem expectedMediaItem = mediaSource.getMediaItem();
assertThat(reportedMediaItems)
.containsExactly(expectedMediaItem, expectedMediaItem, expectedMediaItem);
assertThat(reportedTransitionReasons)
.containsExactly(
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED,
Player.MEDIA_ITEM_TRANSITION_REASON_SEEK,
Player.MEDIA_ITEM_TRANSITION_REASON_SEEK);
}
@Test
public void repeat_notifiesMediaItemTransition() throws Exception { public void repeat_notifiesMediaItemTransition() throws Exception {
List<MediaItem> reportedMediaItems = new ArrayList<>(); List<MediaItem> reportedMediaItems = new ArrayList<>();
List<Integer> reportedTransitionReasons = new ArrayList<>(); List<Integer> reportedTransitionReasons = new ArrayList<>();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment