diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java index 985c43fa551..c5f7c5e1c93 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ConcatenatingMediaSource.java @@ -50,10 +50,11 @@ public class ConcatenatingMediaSource extends CompositeMediaSource mediaSourcesPublic; @@ -265,6 +266,9 @@ public final synchronized void addMediaSources( *

Note: If you want to move the instance, it's preferable to use {@link #moveMediaSource(int, * int)} instead. * + *

Note: If you want to remove a set of contiguous sources, it's preferable to use + * {@link #removeMediaSourceRange(int, int)} instead. + * * @param index The index at which the media source will be removed. This index must be in the * range of 0 <= index < {@link #getSize()}. */ @@ -276,7 +280,10 @@ public final synchronized void removeMediaSource(int index) { * Removes a {@link MediaSource} from the playlist and executes a custom action on completion. * *

Note: If you want to move the instance, it's preferable to use {@link #moveMediaSource(int, - * int)} instead. + * int, Runnable)} instead. + * + *

Note: If you want to remove a set of contiguous sources, it's preferable to use + * {@link #removeMediaSourceRange(int, int, Runnable)} instead. * * @param index The index at which the media source will be removed. This index must be in the * range of 0 <= index < {@link #getSize()}. @@ -297,6 +304,60 @@ public final synchronized void removeMediaSource( } } + /** + * Removes a range of {@link MediaSource}s from the playlist, by specifying an initial index + * (included) and a final index (excluded). + * + *

Note: when specified range is empty, no actual media source is removed and no exception + * is thrown. + * + * @param fromIndex The initial range index, pointing to the first media source that will be + * removed. This index must be in the range of 0 <= index <= {@link #getSize()}. + * @param toIndex The final range index, pointing to the first media source that will be left + * untouched. This index must be in the range of 0 <= index <= {@link #getSize()}. + * @throws IndexOutOfBoundsException When the range is malformed, i.e. {@code fromIndex} < + * 0, {@code toIndex} > {@link #getSize()}, {@code fromIndex} > {@code toIndex} + */ + public final synchronized void removeMediaSourceRange(int fromIndex, int toIndex) { + removeMediaSourceRange(fromIndex, toIndex, null); + } + + /** + * Removes a range of {@link MediaSource}s from the playlist, by specifying an initial index + * (included) and a final index (excluded), and executes a custom action on completion. + * + *

Note: when specified range is empty, no actual media source is removed and no exception + * is thrown. + * + * @param fromIndex The initial range index, pointing to the first media source that will be + * removed. This index must be in the range of 0 <= index <= {@link #getSize()}. + * @param toIndex The final range index, pointing to the first media source that will be left + * untouched. This index must be in the range of 0 <= index <= {@link #getSize()}. + * @param actionOnCompletion A {@link Runnable} which is executed immediately after the media + * source range has been removed from the playlist. + * @throws IndexOutOfBoundsException When the range is malformed, i.e. {@code fromIndex} < + * 0, {@code toIndex} > {@link #getSize()}, {@code fromIndex} > {@code toIndex} + */ + public final synchronized void removeMediaSourceRange( + int fromIndex, int toIndex, @Nullable Runnable actionOnCompletion) { + Util.removeRange(mediaSourcesPublic, fromIndex, toIndex); + if (fromIndex == toIndex) { + if (actionOnCompletion != null) { + actionOnCompletion.run(); + } + return; + } + if (player != null) { + player + .createMessage(this) + .setType(MSG_REMOVE_RANGE) + .setPayload(new MessageData<>(fromIndex, toIndex, actionOnCompletion)) + .send(); + } else if (actionOnCompletion != null) { + actionOnCompletion.run(); + } + } + /** * Moves an existing {@link MediaSource} within the playlist. * @@ -489,6 +550,18 @@ public final void handleMessage(int messageType, Object message) throws ExoPlayb removeMediaSourceInternal(removeMessage.index); scheduleListenerNotification(removeMessage.actionOnCompletion); break; + case MSG_REMOVE_RANGE: + MessageData removeRangeMessage = (MessageData) message; + int fromIndex = removeRangeMessage.index; + int toIndex = removeRangeMessage.customData; + for (int index = toIndex - 1; index >= fromIndex; index--) { + shuffleOrder = shuffleOrder.cloneAndRemove(index); + } + for (int index = toIndex - 1; index >= fromIndex; index--) { + removeMediaSourceInternal(index); + } + scheduleListenerNotification(removeRangeMessage.actionOnCompletion); + break; case MSG_MOVE: MessageData moveMessage = (MessageData) message; shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index);