Merge branch 'master' into dev

This commit is contained in:
Stypox 2023-02-08 22:48:14 +01:00
commit a17c32fada
142 changed files with 1736 additions and 521 deletions

View file

@ -348,7 +348,7 @@ public final class Player implements PlaybackListener, Listener {
final boolean playbackSkipSilence = getPrefs().getBoolean(getContext().getString(
R.string.playback_skip_silence_key), getPlaybackSkipSilence());
final boolean samePlayQueue = playQueue != null && playQueue.equals(newQueue);
final boolean samePlayQueue = playQueue != null && playQueue.equalStreamsAndIndex(newQueue);
final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode());
final boolean playWhenReady = intent.getBooleanExtra(PLAY_WHEN_READY, true);
final boolean isMuted = intent.getBooleanExtra(IS_MUTED, isMuted());

View file

@ -1,21 +1,27 @@
package org.schabi.newpipe.player.mediasource;
import androidx.annotation.NonNull;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.CompositeMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.WrappingMediaSource;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import org.schabi.newpipe.player.mediaitem.MediaItemTag;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
public class LoadedMediaSource extends WrappingMediaSource implements ManagedMediaSource {
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class LoadedMediaSource extends CompositeMediaSource<Integer> implements ManagedMediaSource {
private final MediaSource source;
private final PlayQueueItem stream;
private final MediaItem mediaItem;
private final long expireTimestamp;
/**
* Uses a {@link WrappingMediaSource} to wrap one child {@link MediaSource}
* Uses a {@link CompositeMediaSource} to wrap one or more child {@link MediaSource}s
* containing actual media. This wrapper {@link LoadedMediaSource} holds the expiration
* timestamp as a {@link ManagedMediaSource} to allow explicit playlist management under
* {@link ManagedMediaSourcePlaylist}.
@ -30,7 +36,7 @@ public class LoadedMediaSource extends WrappingMediaSource implements ManagedMed
@NonNull final MediaItemTag tag,
@NonNull final PlayQueueItem stream,
final long expireTimestamp) {
super(source);
this.source = source;
this.stream = stream;
this.expireTimestamp = expireTimestamp;
@ -45,6 +51,51 @@ public class LoadedMediaSource extends WrappingMediaSource implements ManagedMed
return System.currentTimeMillis() >= expireTimestamp;
}
/**
* Delegates the preparation of child {@link MediaSource}s to the
* {@link CompositeMediaSource} wrapper. Since all {@link LoadedMediaSource}s use only
* a single child media, the child id of 0 is always used (sonar doesn't like null as id here).
*
* @param mediaTransferListener A data transfer listener that will be registered by the
* {@link CompositeMediaSource} for child source preparation.
*/
@Override
protected void prepareSourceInternal(@Nullable final TransferListener mediaTransferListener) {
super.prepareSourceInternal(mediaTransferListener);
prepareChildSource(0, source);
}
/**
* When any child {@link MediaSource} is prepared, the refreshed {@link Timeline} can
* be listened to here. But since {@link LoadedMediaSource} has only a single child source,
* this method is called only once until {@link #releaseSourceInternal()} is called.
* <br><br>
* On refresh, the {@link CompositeMediaSource} delegate will be notified with the
* new {@link Timeline}, otherwise {@link #createPeriod(MediaPeriodId, Allocator, long)}
* will not be called and playback may be stalled.
*
* @param id The unique id used to prepare the child source.
* @param mediaSource The child source whose source info has been refreshed.
* @param timeline The new timeline of the child source.
*/
@Override
protected void onChildSourceInfoRefreshed(final Integer id,
final MediaSource mediaSource,
final Timeline timeline) {
refreshSourceInfo(timeline);
}
@Override
public MediaPeriod createPeriod(final MediaPeriodId id, final Allocator allocator,
final long startPositionUs) {
return source.createPeriod(id, allocator, startPositionUs);
}
@Override
public void releasePeriod(final MediaPeriod mediaPeriod) {
source.releasePeriod(mediaPeriod);
}
@NonNull
@Override
public MediaItem getMediaItem() {

View file

@ -518,12 +518,10 @@ public abstract class PlayQueue implements Serializable {
* This method also gives a chance to track history of items in a queue in
* VideoDetailFragment without duplicating items from two identical queues
*/
@Override
public boolean equals(@Nullable final Object obj) {
if (!(obj instanceof PlayQueue)) {
public boolean equalStreams(@Nullable final PlayQueue other) {
if (other == null) {
return false;
}
final PlayQueue other = (PlayQueue) obj;
if (size() != other.size()) {
return false;
}
@ -539,9 +537,11 @@ public abstract class PlayQueue implements Serializable {
return true;
}
@Override
public int hashCode() {
return streams.hashCode();
public boolean equalStreamsAndIndex(@Nullable final PlayQueue other) {
if (equalStreams(other)) {
return other.getIndex() == getIndex();
}
return false;
}
public boolean isDisposed() {