mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	-Refactored synchronization checks out from MediaSourceManager to ManagedMediaSource.
-Fixed null input causing potential NPE on PlayQueueItem.
This commit is contained in:
		| @@ -72,7 +72,13 @@ public class FailedMediaSource implements ManagedMediaSource { | |||||||
|     public void releaseSource() {} |     public void releaseSource() {} | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean canReplace(@NonNull final PlayQueueItem newIdentity) { |     public boolean shouldBeReplacedWith(@NonNull final PlayQueueItem newIdentity, | ||||||
|  |                                         final boolean isInterruptable) { | ||||||
|         return newIdentity != playQueueItem || canRetry(); |         return newIdentity != playQueueItem || canRetry(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean isStreamEqual(@NonNull PlayQueueItem stream) { | ||||||
|  |         return playQueueItem == stream; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -59,7 +59,13 @@ public class LoadedMediaSource implements ManagedMediaSource { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean canReplace(@NonNull final PlayQueueItem newIdentity) { |     public boolean shouldBeReplacedWith(@NonNull PlayQueueItem newIdentity, | ||||||
|         return newIdentity != stream || isExpired(); |                                         final boolean isInterruptable) { | ||||||
|  |         return newIdentity != stream || (isInterruptable && isExpired()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean isStreamEqual(@NonNull PlayQueueItem stream) { | ||||||
|  |         return this.stream == stream; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,5 +7,21 @@ import com.google.android.exoplayer2.source.MediaSource; | |||||||
| import org.schabi.newpipe.playlist.PlayQueueItem; | import org.schabi.newpipe.playlist.PlayQueueItem; | ||||||
|  |  | ||||||
| public interface ManagedMediaSource extends MediaSource { | public interface ManagedMediaSource extends MediaSource { | ||||||
|     boolean canReplace(@NonNull final PlayQueueItem newIdentity); |     /** | ||||||
|  |      * Determines whether or not this {@link ManagedMediaSource} can be replaced. | ||||||
|  |      * | ||||||
|  |      * @param newIdentity a stream the {@link ManagedMediaSource} should encapsulate over, if | ||||||
|  |      *                    it is different from the existing stream in the | ||||||
|  |      *                    {@link ManagedMediaSource}, then it should be replaced. | ||||||
|  |      * @param isInterruptable specifies if this {@link ManagedMediaSource} potentially | ||||||
|  |      *                        being played. | ||||||
|  |      * */ | ||||||
|  |     boolean shouldBeReplacedWith(@NonNull final PlayQueueItem newIdentity, | ||||||
|  |                                  final boolean isInterruptable); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Determines if the {@link PlayQueueItem} is the one the | ||||||
|  |      * {@link ManagedMediaSource} encapsulates over. | ||||||
|  |      * */ | ||||||
|  |     boolean isStreamEqual(@NonNull final PlayQueueItem stream); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,7 +19,13 @@ public class PlaceholderMediaSource implements ManagedMediaSource { | |||||||
|     @Override public void releaseSource() {} |     @Override public void releaseSource() {} | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean canReplace(@NonNull final PlayQueueItem newIdentity) { |     public boolean shouldBeReplacedWith(@NonNull PlayQueueItem newIdentity, | ||||||
|  |                                         final boolean isInterruptable) { | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public boolean isStreamEqual(@NonNull PlayQueueItem stream) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -268,15 +268,10 @@ public class MediaSourceManager { | |||||||
|     private boolean isPlaybackReady() { |     private boolean isPlaybackReady() { | ||||||
|         if (sources.getSize() != playQueue.size()) return false; |         if (sources.getSize() != playQueue.size()) return false; | ||||||
|  |  | ||||||
|         final MediaSource mediaSource = sources.getMediaSource(playQueue.getIndex()); |         final ManagedMediaSource mediaSource = | ||||||
|  |                 (ManagedMediaSource) sources.getMediaSource(playQueue.getIndex()); | ||||||
|         final PlayQueueItem playQueueItem = playQueue.getItem(); |         final PlayQueueItem playQueueItem = playQueue.getItem(); | ||||||
|  |         return mediaSource.isStreamEqual(playQueueItem); | ||||||
|         if (mediaSource instanceof LoadedMediaSource) { |  | ||||||
|             return playQueueItem == ((LoadedMediaSource) mediaSource).getStream(); |  | ||||||
|         } else if (mediaSource instanceof FailedMediaSource) { |  | ||||||
|             return playQueueItem == ((FailedMediaSource) mediaSource).getStream(); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void maybeBlock() { |     private void maybeBlock() { | ||||||
| @@ -453,12 +448,8 @@ public class MediaSourceManager { | |||||||
|         if (index == -1 || index >= sources.getSize()) return false; |         if (index == -1 || index >= sources.getSize()) return false; | ||||||
|  |  | ||||||
|         final ManagedMediaSource mediaSource = (ManagedMediaSource) sources.getMediaSource(index); |         final ManagedMediaSource mediaSource = (ManagedMediaSource) sources.getMediaSource(index); | ||||||
|  |         return mediaSource.shouldBeReplacedWith(item, | ||||||
|         if (index == playQueue.getIndex() && mediaSource instanceof LoadedMediaSource) { |                 /*mightBeInProgress=*/index != playQueue.getIndex()); | ||||||
|             return item != ((LoadedMediaSource) mediaSource).getStream(); |  | ||||||
|         } else { |  | ||||||
|             return mediaSource.canReplace(item); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -479,7 +470,7 @@ public class MediaSourceManager { | |||||||
|         final ManagedMediaSource currentSource = |         final ManagedMediaSource currentSource = | ||||||
|                 (ManagedMediaSource) sources.getMediaSource(currentIndex); |                 (ManagedMediaSource) sources.getMediaSource(currentIndex); | ||||||
|         final PlayQueueItem currentItem = playQueue.getItem(); |         final PlayQueueItem currentItem = playQueue.getItem(); | ||||||
|         if (!currentSource.canReplace(currentItem)) { |         if (!currentSource.shouldBeReplacedWith(currentItem, /*canInterruptOnRenew=*/true)) { | ||||||
|             maybeSynchronizePlayer(); |             maybeSynchronizePlayer(); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -11,20 +11,19 @@ import org.schabi.newpipe.util.ExtractorHelper; | |||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
|  |  | ||||||
| import io.reactivex.Single; | import io.reactivex.Single; | ||||||
| import io.reactivex.android.schedulers.AndroidSchedulers; |  | ||||||
| import io.reactivex.functions.Consumer; |  | ||||||
| import io.reactivex.schedulers.Schedulers; | import io.reactivex.schedulers.Schedulers; | ||||||
|  |  | ||||||
| public class PlayQueueItem implements Serializable { | public class PlayQueueItem implements Serializable { | ||||||
|     final public static long RECOVERY_UNSET = Long.MIN_VALUE; |     public final static long RECOVERY_UNSET = Long.MIN_VALUE; | ||||||
|  |     private final static String EMPTY_STRING = ""; | ||||||
|  |  | ||||||
|     final private String title; |     @NonNull final private String title; | ||||||
|     final private String url; |     @NonNull final private String url; | ||||||
|     final private int serviceId; |     final private int serviceId; | ||||||
|     final private long duration; |     final private long duration; | ||||||
|     final private String thumbnailUrl; |     @NonNull final private String thumbnailUrl; | ||||||
|     final private String uploader; |     @NonNull final private String uploader; | ||||||
|     final private StreamType streamType; |     @NonNull final private StreamType streamType; | ||||||
|  |  | ||||||
|     private long recoveryPosition; |     private long recoveryPosition; | ||||||
|     private Throwable error; |     private Throwable error; | ||||||
| @@ -42,15 +41,16 @@ public class PlayQueueItem implements Serializable { | |||||||
|                 item.getThumbnailUrl(), item.getUploaderName(), item.getStreamType()); |                 item.getThumbnailUrl(), item.getUploaderName(), item.getStreamType()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private PlayQueueItem(final String name, final String url, final int serviceId, |     private PlayQueueItem(@Nullable final String name, @Nullable final String url, | ||||||
|                           final long duration, final String thumbnailUrl, final String uploader, |                           final int serviceId, final long duration, | ||||||
|                           final StreamType streamType) { |                           @Nullable final String thumbnailUrl, @Nullable final String uploader, | ||||||
|         this.title = name; |                           @NonNull final StreamType streamType) { | ||||||
|         this.url = url; |         this.title = name != null ? name : EMPTY_STRING; | ||||||
|  |         this.url = url != null ? url : EMPTY_STRING; | ||||||
|         this.serviceId = serviceId; |         this.serviceId = serviceId; | ||||||
|         this.duration = duration; |         this.duration = duration; | ||||||
|         this.thumbnailUrl = thumbnailUrl; |         this.thumbnailUrl = thumbnailUrl != null ? thumbnailUrl : EMPTY_STRING; | ||||||
|         this.uploader = uploader; |         this.uploader = uploader != null ? uploader : EMPTY_STRING; | ||||||
|         this.streamType = streamType; |         this.streamType = streamType; | ||||||
|  |  | ||||||
|         this.recoveryPosition = RECOVERY_UNSET; |         this.recoveryPosition = RECOVERY_UNSET; | ||||||
| @@ -84,6 +84,7 @@ public class PlayQueueItem implements Serializable { | |||||||
|         return uploader; |         return uploader; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @NonNull | ||||||
|     public StreamType getStreamType() { |     public StreamType getStreamType() { | ||||||
|         return streamType; |         return streamType; | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 John Zhen Mo
					John Zhen Mo