@Override public int getFirstWindowIndex(boolean shuffleModeEnabled) { return timeline.getFirstWindowIndex(shuffleModeEnabled); }
/** * Returns the index of the window before the window at index {@code windowIndex} depending on the * {@code repeatMode} and whether shuffling is enabled. * * @param windowIndex Index of a window in the timeline. * @param repeatMode A repeat mode. * @param shuffleModeEnabled Whether shuffling is enabled. * @return The index of the previous window, or {@link C#INDEX_UNSET} if this is the first window. */ public int getPreviousWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { switch (repeatMode) { case Player.REPEAT_MODE_OFF: return windowIndex == getFirstWindowIndex(shuffleModeEnabled) ? C.INDEX_UNSET : windowIndex - 1; case Player.REPEAT_MODE_ONE: return windowIndex; case Player.REPEAT_MODE_ALL: return windowIndex == getFirstWindowIndex(shuffleModeEnabled) ? getLastWindowIndex(shuffleModeEnabled) : windowIndex - 1; default: throw new IllegalStateException(); } }
/** * Returns the index of the window after the window at index {@code windowIndex} depending on the * {@code repeatMode} and whether shuffling is enabled. * * @param windowIndex Index of a window in the timeline. * @param repeatMode A repeat mode. * @param shuffleModeEnabled Whether shuffling is enabled. * @return The index of the next window, or {@link C#INDEX_UNSET} if this is the last window. */ public int getNextWindowIndex(int windowIndex, @Player.RepeatMode int repeatMode, boolean shuffleModeEnabled) { switch (repeatMode) { case Player.REPEAT_MODE_OFF: return windowIndex == getLastWindowIndex(shuffleModeEnabled) ? C.INDEX_UNSET : windowIndex + 1; case Player.REPEAT_MODE_ONE: return windowIndex; case Player.REPEAT_MODE_ALL: return windowIndex == getLastWindowIndex(shuffleModeEnabled) ? getFirstWindowIndex(shuffleModeEnabled) : windowIndex + 1; default: throw new IllegalStateException(); } }
/** Assert that timeline is empty (i.e. has no windows or periods). */ public static void assertEmpty(Timeline timeline) { assertWindowTags(timeline); assertPeriodCounts(timeline); for (boolean shuffled : new boolean[] {false, true}) { assertThat(timeline.getFirstWindowIndex(shuffled)).isEqualTo(C.INDEX_UNSET); assertThat(timeline.getLastWindowIndex(shuffled)).isEqualTo(C.INDEX_UNSET); } }
/** * Returns dummy media period id for the first-to-be-played period of the current timeline. * * @param shuffleModeEnabled Whether shuffle mode is enabled. * @param window A writable {@link Timeline.Window}. * @return A dummy media period id for the first-to-be-played period of the current timeline. */ public MediaPeriodId getDummyFirstMediaPeriodId( boolean shuffleModeEnabled, Timeline.Window window) { if (timeline.isEmpty()) { return DUMMY_MEDIA_PERIOD_ID; } int firstPeriodIndex = timeline.getWindow(timeline.getFirstWindowIndex(shuffleModeEnabled), window) .firstPeriodIndex; return new MediaPeriodId(timeline.getUidOfPeriod(firstPeriodIndex)); }
/** Assert that timeline is empty (i.e. has no windows or periods). */ public static void assertEmpty(Timeline timeline) { assertWindowTags(timeline); assertPeriodCounts(timeline); for (boolean shuffled : new boolean[] {false, true}) { assertThat(timeline.getFirstWindowIndex(shuffled)).isEqualTo(C.INDEX_UNSET); assertThat(timeline.getLastWindowIndex(shuffled)).isEqualTo(C.INDEX_UNSET); } }
@Override public int getFirstWindowIndex(boolean shuffleModeEnabled) { if (childCount == 0) { return C.INDEX_UNSET; } if (isAtomic) { shuffleModeEnabled = false; } // Find first non-empty child. int firstChildIndex = shuffleModeEnabled ? shuffleOrder.getFirstIndex() : 0; while (getTimelineByChildIndex(firstChildIndex).isEmpty()) { firstChildIndex = getNextChildIndex(firstChildIndex, shuffleModeEnabled); if (firstChildIndex == C.INDEX_UNSET) { // All children are empty. return C.INDEX_UNSET; } } return getFirstWindowIndexByChildIndex(firstChildIndex) + getTimelineByChildIndex(firstChildIndex).getFirstWindowIndex(shuffleModeEnabled); }
@Test public void testSetShuffleOrderBeforePreparation() throws Exception { mediaSource.setShuffleOrder(new ShuffleOrder.UnshuffledShuffleOrder(/* length= */ 0)); mediaSource.addMediaSources( Arrays.asList(createFakeMediaSource(), createFakeMediaSource(), createFakeMediaSource())); Timeline timeline = testRunner.prepareSource(); assertThat(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true)).isEqualTo(0); }
@Test public void testSetShuffleOrderAfterPreparation() throws Exception { mediaSource.addMediaSources( Arrays.asList(createFakeMediaSource(), createFakeMediaSource(), createFakeMediaSource())); testRunner.prepareSource(); mediaSource.setShuffleOrder(new ShuffleOrder.UnshuffledShuffleOrder(/* length= */ 3)); Timeline timeline = testRunner.assertTimelineChangeBlocking(); assertThat(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true)).isEqualTo(0); }
+ getTimelineByChildIndex(nextChildIndex).getFirstWindowIndex(shuffleModeEnabled);
@Test public void testCustomCallbackAfterPreparationSetShuffleOrder() throws Exception { DummyMainThread dummyMainThread = new DummyMainThread(); try { mediaSource.addMediaSources( Arrays.asList(createFakeMediaSource(), createFakeMediaSource(), createFakeMediaSource())); testRunner.prepareSource(); TimelineGrabber timelineGrabber = new TimelineGrabber(testRunner); dummyMainThread.runOnMainThread( () -> mediaSource.setShuffleOrder( new ShuffleOrder.UnshuffledShuffleOrder(/* length= */ 3), timelineGrabber)); Timeline timeline = timelineGrabber.assertTimelineChangeBlocking(); assertThat(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true)).isEqualTo(0); } finally { dummyMainThread.release(); } }
TimelineAsserts.assertNextWindowIndices( timeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ true, 1, 2, 0); assertThat(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ false)).isEqualTo(0); assertThat(timeline.getFirstWindowIndex(/* shuffleModeEnabled= */ true)).isEqualTo(0); assertThat(timeline.getLastWindowIndex(/* shuffleModeEnabled= */ false)).isEqualTo(2); assertThat(timeline.getLastWindowIndex(/* shuffleModeEnabled= */ true)).isEqualTo(2);
TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ONE, true, 0, 1, 2); TimelineAsserts.assertNextWindowIndices(timeline, Player.REPEAT_MODE_ALL, true, 2, 0, 1); assertThat(timeline.getFirstWindowIndex(false)).isEqualTo(0); assertThat(timeline.getLastWindowIndex(false)).isEqualTo(2); assertThat(timeline.getFirstWindowIndex(true)).isEqualTo(2); assertThat(timeline.getLastWindowIndex(true)).isEqualTo(0); testRunner.assertPrepareAndReleaseAllPeriods();
Pair<Object, Long> defaultPosition = getPeriodPosition( timeline, timeline.getFirstWindowIndex(shuffleModeEnabled), C.TIME_UNSET); Object periodUid = defaultPosition.first; long startPositionUs = defaultPosition.second; Pair<Object, Long> defaultPosition = getPeriodPosition( timeline, timeline.getFirstWindowIndex(shuffleModeEnabled), C.TIME_UNSET); Object periodUid = defaultPosition.first; long startPositionUs = defaultPosition.second;
TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_ONE, false, 0, 1, 2); TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_ALL, false, 2, 0, 1); assertThat(timeline.getFirstWindowIndex(false)).isEqualTo(0); assertThat(timeline.getLastWindowIndex(false)).isEqualTo(timeline.getWindowCount() - 1); TimelineAsserts.assertNextWindowIndices( TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_ONE, true, 0, 1, 2); TimelineAsserts.assertPreviousWindowIndices(timeline, Player.REPEAT_MODE_ALL, true, 1, 2, 0); assertThat(timeline.getFirstWindowIndex(true)).isEqualTo(timeline.getWindowCount() - 1); assertThat(timeline.getLastWindowIndex(true)).isEqualTo(0);