mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	-Fixed potential NPE when obtaining broadcast receiver.
-Extracted expiration time in media source manager. -Re-enabled long click on live stream info items. -Fixed dash source building to use mpd instead of extractor.
This commit is contained in:
		| @@ -59,23 +59,20 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { | ||||
|         itemBuilder.getImageLoader() | ||||
|                 .displayImage(item.thumbnail_url, itemThumbnailView, StreamInfoItemHolder.DISPLAY_THUMBNAIL_OPTIONS); | ||||
|  | ||||
|         itemView.setOnClickListener(new View.OnClickListener() { | ||||
|             @Override | ||||
|             public void onClick(View view) { | ||||
|         itemView.setOnClickListener(view -> { | ||||
|             if (itemBuilder.getOnStreamSelectedListener() != null) { | ||||
|                 itemBuilder.getOnStreamSelectedListener().selected(item); | ||||
|             } | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         switch (item.stream_type) { | ||||
|             case AUDIO_STREAM: | ||||
|             case VIDEO_STREAM: | ||||
|             case FILE: | ||||
|                 enableLongClick(item); | ||||
|                 break; | ||||
|             case LIVE_STREAM: | ||||
|             case AUDIO_LIVE_STREAM: | ||||
|                 enableLongClick(item); | ||||
|                 break; | ||||
|             case FILE: | ||||
|             case NONE: | ||||
|             default: | ||||
|                 disableLongClick(); | ||||
| @@ -85,14 +82,11 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { | ||||
|  | ||||
|     private void enableLongClick(final StreamInfoItem item) { | ||||
|         itemView.setLongClickable(true); | ||||
|         itemView.setOnLongClickListener(new View.OnLongClickListener() { | ||||
|             @Override | ||||
|             public boolean onLongClick(View view) { | ||||
|         itemView.setOnLongClickListener(view -> { | ||||
|             if (itemBuilder.getOnStreamSelectedListener() != null) { | ||||
|                 itemBuilder.getOnStreamSelectedListener().held(item); | ||||
|             } | ||||
|             return true; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -319,35 +319,27 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen | ||||
|         recordManager = null; | ||||
|     } | ||||
|  | ||||
|     public MediaSource buildMediaSource(String url) { | ||||
|         return buildMediaSource(url, ""); | ||||
|     } | ||||
|  | ||||
|     public MediaSource buildMediaSource(String url, String overrideExtension) { | ||||
|         if (DEBUG) { | ||||
|             Log.d(TAG, "buildMediaSource() called with: url = [" + url + "], overrideExtension = [" + overrideExtension + "]"); | ||||
|             Log.d(TAG, "buildMediaSource() called with: url = [" + url + | ||||
|                     "], overrideExtension = [" + overrideExtension + "]"); | ||||
|         } | ||||
|         Uri uri = Uri.parse(url); | ||||
|         int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri) : Util.inferContentType("." + overrideExtension); | ||||
|         MediaSource mediaSource; | ||||
|         int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri) : | ||||
|                 Util.inferContentType("." + overrideExtension); | ||||
|         switch (type) { | ||||
|             case C.TYPE_SS: | ||||
|                 mediaSource = ssMediaSourceFactory.createMediaSource(uri); | ||||
|                 break; | ||||
|                 return ssMediaSourceFactory.createMediaSource(uri); | ||||
|             case C.TYPE_DASH: | ||||
|                 mediaSource = dashMediaSourceFactory.createMediaSource(uri); | ||||
|                 break; | ||||
|                 return dashMediaSourceFactory.createMediaSource(uri); | ||||
|             case C.TYPE_HLS: | ||||
|                 mediaSource = hlsMediaSourceFactory.createMediaSource(uri); | ||||
|                 break; | ||||
|                 return hlsMediaSourceFactory.createMediaSource(uri); | ||||
|             case C.TYPE_OTHER: | ||||
|                 mediaSource = extractorMediaSourceFactory.createMediaSource(uri); | ||||
|                 break; | ||||
|                 return extractorMediaSourceFactory.createMediaSource(uri); | ||||
|             default: { | ||||
|                 throw new IllegalStateException("Unsupported type: " + type); | ||||
|             } | ||||
|         } | ||||
|         return mediaSource; | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
| @@ -514,8 +506,13 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen | ||||
|     public void onTimelineChanged(Timeline timeline, Object manifest, int reason) { | ||||
|         if (DEBUG) Log.d(TAG, "onTimelineChanged(), timeline size = " + timeline.getWindowCount()); | ||||
|  | ||||
|         if (playbackManager != null) { | ||||
|             playbackManager.load(); | ||||
|         switch (reason) { | ||||
|             case Player.TIMELINE_CHANGE_REASON_PREPARED: | ||||
|             case Player.TIMELINE_CHANGE_REASON_RESET: | ||||
|             case Player.TIMELINE_CHANGE_REASON_DYNAMIC: | ||||
|             default: | ||||
|                 if (playbackManager != null) playbackManager.load(); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -526,7 +523,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen | ||||
|  | ||||
|     @Override | ||||
|     public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { | ||||
|         if (DEBUG) Log.d(TAG, "playbackParameters(), speed: " + playbackParameters.speed + ", pitch: " + playbackParameters.pitch); | ||||
|         if (DEBUG) Log.d(TAG, "playbackParameters(), speed: " + playbackParameters.speed + | ||||
|                 ", pitch: " + playbackParameters.pitch); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -732,9 +730,9 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen | ||||
|     @Override | ||||
|     public MediaSource sourceOf(PlayQueueItem item, StreamInfo info) { | ||||
|         if (!info.getHlsUrl().isEmpty()) { | ||||
|             return buildMediaSource(info.getHlsUrl()); | ||||
|             return buildMediaSource(info.getHlsUrl(), "m3u8"); | ||||
|         } else if (!info.getDashMpdUrl().isEmpty()) { | ||||
|             return buildMediaSource(info.getDashMpdUrl()); | ||||
|             return buildMediaSource(info.getDashMpdUrl(), "mpd"); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|   | ||||
| @@ -25,6 +25,10 @@ public class FailedMediaSource implements ManagedMediaSource { | ||||
|         this.retryTimestamp = retryTimestamp; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Permanently fail the play queue item associated with this source, with no hope of retrying. | ||||
|      * The error will always be propagated to ExoPlayer. | ||||
|      * */ | ||||
|     public FailedMediaSource(@NonNull final PlayQueueItem playQueueItem, | ||||
|                              @NonNull final Throwable error) { | ||||
|         this.playQueueItem = playQueueItem; | ||||
|   | ||||
| @@ -40,6 +40,8 @@ public class MediaSourceManager { | ||||
|     private final int windowSize; | ||||
|     private final PlaybackListener playbackListener; | ||||
|     private final PlayQueue playQueue; | ||||
|     private final long expirationTimeMillis; | ||||
|     private final TimeUnit expirationTimeUnit; | ||||
|  | ||||
|     // Process only the last load order when receiving a stream of load orders (lessens I/O) | ||||
|     // The higher it is, the less loading occurs during rapid noncritical timeline changes | ||||
| @@ -61,13 +63,15 @@ public class MediaSourceManager { | ||||
|  | ||||
|     public MediaSourceManager(@NonNull final PlaybackListener listener, | ||||
|                               @NonNull final PlayQueue playQueue) { | ||||
|         this(listener, playQueue, 1, 400L); | ||||
|         this(listener, playQueue, 1, 400L, 2, TimeUnit.HOURS); | ||||
|     } | ||||
|  | ||||
|     private MediaSourceManager(@NonNull final PlaybackListener listener, | ||||
|                                @NonNull final PlayQueue playQueue, | ||||
|                                final int windowSize, | ||||
|                                final long loadDebounceMillis) { | ||||
|                                final long loadDebounceMillis, | ||||
|                                final long expirationTimeMillis, | ||||
|                                @NonNull final TimeUnit expirationTimeUnit) { | ||||
|         if (windowSize <= 0) { | ||||
|             throw new UnsupportedOperationException( | ||||
|                     "MediaSourceManager window size must be greater than 0"); | ||||
| @@ -77,6 +81,8 @@ public class MediaSourceManager { | ||||
|         this.playQueue = playQueue; | ||||
|         this.windowSize = windowSize; | ||||
|         this.loadDebounceMillis = loadDebounceMillis; | ||||
|         this.expirationTimeMillis = expirationTimeMillis; | ||||
|         this.expirationTimeUnit = expirationTimeUnit; | ||||
|  | ||||
|         this.loaderReactor = new CompositeDisposable(); | ||||
|         this.debouncedLoadSignal = PublishSubject.create(); | ||||
| @@ -87,10 +93,12 @@ public class MediaSourceManager { | ||||
|         this.syncReactor = new SerialDisposable(); | ||||
|         this.loadingItems = Collections.synchronizedSet(new HashSet<>()); | ||||
|  | ||||
|         if (playQueue.getBroadcastReceiver() != null) { | ||||
|             playQueue.getBroadcastReceiver() | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(getReactor()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
|     // Exposed Methods | ||||
| @@ -225,7 +233,7 @@ public class MediaSourceManager { | ||||
|         return playQueue.isComplete() || isWindowLoaded; | ||||
|     } | ||||
|  | ||||
|     // Checks if the current playback media source is a placeholder, if so, then it is not ready | ||||
|     // Checks if the current playback media source is a placeholder, if so, then it is not ready. | ||||
|     private boolean isPlaybackReady() { | ||||
|         return sources != null && playQueue != null && sources.getSize() > playQueue.getIndex() && | ||||
|                 !(sources.getMediaSource(playQueue.getIndex()) instanceof PlaceholderMediaSource); | ||||
| @@ -351,11 +359,11 @@ public class MediaSourceManager { | ||||
|             final MediaSource source = playbackListener.sourceOf(stream, streamInfo); | ||||
|             if (source == null) { | ||||
|                 return new FailedMediaSource(stream, new IllegalStateException( | ||||
|                         "MediaSource resolution is null")); | ||||
|                         "MediaSource cannot be resolved")); | ||||
|             } | ||||
|  | ||||
|             final long expiration = System.currentTimeMillis() + | ||||
|                     TimeUnit.MILLISECONDS.convert(2, TimeUnit.HOURS); | ||||
|                     TimeUnit.MILLISECONDS.convert(expirationTimeMillis, expirationTimeUnit); | ||||
|             return new LoadedMediaSource(source, expiration); | ||||
|         }).onErrorReturn(throwable -> new FailedMediaSource(stream, throwable)); | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package org.schabi.newpipe.playlist; | ||||
|  | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.util.Log; | ||||
|  | ||||
| import org.reactivestreams.Subscriber; | ||||
| @@ -170,7 +171,7 @@ public abstract class PlayQueue implements Serializable { | ||||
|      * Returns the play queue's update broadcast. | ||||
|      * May be null if the play queue message bus is not initialized. | ||||
|      * */ | ||||
|     @NonNull | ||||
|     @Nullable | ||||
|     public Flowable<PlayQueueEvent> getBroadcastReceiver() { | ||||
|         return broadcastReceiver; | ||||
|     } | ||||
|   | ||||
| @@ -99,8 +99,10 @@ public class PlayQueueAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         if (playQueue.getBroadcastReceiver() != null) { | ||||
|             playQueue.getBroadcastReceiver().toObservable().subscribe(observer); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void onPlayQueueChanged(final PlayQueueEvent message) { | ||||
|         switch (message.type()) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 John Zhen Mo
					John Zhen Mo