diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 679084bdf..abb995ecd 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -255,11 +255,8 @@ public final class VideoDetailFragment playerUi.ifPresent(MainPlayerUi::toggleFullscreen); } - //noinspection SimplifyOptionalCallChains - if (playAfterConnect - || (currentInfo != null - && isAutoplayEnabled() - && !playerUi.isPresent())) { + if (playAfterConnect || (currentInfo != null && isAutoplayEnabled() + && playerUi.isEmpty())) { autoPlayEnabled = true; // forcefully start playing openVideoPlayerAutoFullscreen(); } @@ -1174,16 +1171,15 @@ public final class VideoDetailFragment * be reused in a few milliseconds and the flickering would be annoying. */ private void hideMainPlayerOnLoadingNewStream() { - //noinspection SimplifyOptionalCallChains - if (!isPlayerServiceAvailable() || !getRoot().isPresent() - || !player.videoPlayerSelected()) { + final var root = getRoot(); + if (!isPlayerServiceAvailable() || root.isEmpty() || !player.videoPlayerSelected()) { return; } removeVideoPlayerView(); if (isAutoplayEnabled()) { playerService.stopForImmediateReusing(); - getRoot().ifPresent(view -> view.setVisibility(View.GONE)); + root.ifPresent(view -> view.setVisibility(View.GONE)); } else { playerHolder.stopService(); } @@ -1887,10 +1883,8 @@ public final class VideoDetailFragment @Override public void onFullscreenStateChanged(final boolean fullscreen) { setupBrightness(); - //noinspection SimplifyOptionalCallChains - if (!isPlayerAndPlayerServiceAvailable() - || !player.UIs().get(MainPlayerUi.class).isPresent() - || getRoot().map(View::getParent).orElse(null) == null) { + if (!isPlayerAndPlayerServiceAvailable() || player.UIs().get(MainPlayerUi.class).isEmpty() + || getRoot().map(View::getParent).isEmpty()) { return; } diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 95520ba1e..da337b394 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -1695,26 +1695,25 @@ public final class Player implements PlaybackListener, Listener { } private void saveStreamProgressState(final long progressMillis) { - //noinspection SimplifyOptionalCallChains - if (!getCurrentStreamInfo().isPresent() - || !prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)) { - return; - } - if (DEBUG) { - Log.d(TAG, "saveStreamProgressState() called with: progressMillis=" + progressMillis - + ", currentMetadata=[" + getCurrentStreamInfo().get().getName() + "]"); - } + getCurrentStreamInfo().ifPresent(info -> { + if (!prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)) { + return; + } + if (DEBUG) { + Log.d(TAG, "saveStreamProgressState() called with: progressMillis=" + progressMillis + + ", currentMetadata=[" + info.getName() + "]"); + } - databaseUpdateDisposable - .add(recordManager.saveStreamState(getCurrentStreamInfo().get(), progressMillis) - .observeOn(AndroidSchedulers.mainThread()) - .doOnError(e -> { - if (DEBUG) { - e.printStackTrace(); - } - }) - .onErrorComplete() - .subscribe()); + databaseUpdateDisposable.add(recordManager.saveStreamState(info, progressMillis) + .observeOn(AndroidSchedulers.mainThread()) + .doOnError(e -> { + if (DEBUG) { + e.printStackTrace(); + } + }) + .onErrorComplete() + .subscribe()); + }); } public void saveStreamProgressState() { @@ -2036,40 +2035,35 @@ public final class Player implements PlaybackListener, Listener { // in livestreams) so we will be not able to execute the block below. // Reload the play queue manager in this case, which is the behavior when we don't know the // index of the video renderer or playQueueManagerReloadingNeeded returns true. - final Optional optCurrentStreamInfo = getCurrentStreamInfo(); - if (!optCurrentStreamInfo.isPresent()) { - reloadPlayQueueManager(); - setRecovery(); - return; - } + getCurrentStreamInfo().ifPresentOrElse(info -> { + // In the case we don't know the source type, fallback to the one with video with audio + // or audio-only source. + final SourceType sourceType = videoResolver.getStreamSourceType() + .orElse(SourceType.VIDEO_WITH_AUDIO_OR_AUDIO_ONLY); - final StreamInfo info = optCurrentStreamInfo.get(); + if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) { + reloadPlayQueueManager(); + } else { + if (StreamTypeUtil.isAudio(info.getStreamType())) { + // Nothing to do more than setting the recovery position + setRecovery(); + return; + } - // In the case we don't know the source type, fallback to the one with video with audio or - // audio-only source. - final SourceType sourceType = videoResolver.getStreamSourceType().orElse( - SourceType.VIDEO_WITH_AUDIO_OR_AUDIO_ONLY); + final var parametersBuilder = trackSelector.buildUponParameters(); - if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) { - reloadPlayQueueManager(); - } else { - if (StreamTypeUtil.isAudio(info.getStreamType())) { - // Nothing to do more than setting the recovery position - setRecovery(); - return; + // Enable/disable the video track and the ability to select subtitles + parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled); + parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled); + + trackSelector.setParameters(parametersBuilder); } - final DefaultTrackSelector.Parameters.Builder parametersBuilder = - trackSelector.buildUponParameters(); - - // Enable/disable the video track and the ability to select subtitles - parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled); - parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled); - - trackSelector.setParameters(parametersBuilder); - } - - setRecovery(); + setRecovery(); + }, () -> { + reloadPlayQueueManager(); + setRecovery(); + }); } /** diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index 9b13bb3d7..f58aa6e91 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -423,7 +423,7 @@ public class MediaSourceManager { private Single getLoadedMediaSource(@NonNull final PlayQueueItem stream) { return stream.getStream().map(streamInfo -> { final MediaSource source = playbackListener.sourceOf(stream, streamInfo); - if (source == null || !MediaItemTag.from(source.getMediaItem()).isPresent()) { + if (source == null || MediaItemTag.from(source.getMediaItem()).isEmpty()) { final String message = "Unable to resolve source from stream info. " + "URL: " + stream.getUrl() + ", " + "audio count: " + streamInfo.getAudioStreams().size() + ", " diff --git a/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHelper.java b/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHelper.java index 9eea89e78..b7441c272 100644 --- a/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHelper.java @@ -8,6 +8,7 @@ import android.widget.ImageView; import androidx.annotation.IntDef; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.graphics.BitmapCompat; import androidx.core.math.MathUtils; import androidx.preference.PreferenceManager; @@ -16,7 +17,6 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.util.DeviceUtils; import java.lang.annotation.Retention; -import java.util.Optional; import java.util.function.IntSupplier; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -66,21 +66,19 @@ public final class SeekbarPreviewThumbnailHelper { public static void tryResizeAndSetSeekbarPreviewThumbnail( @NonNull final Context context, - @NonNull final Optional optPreviewThumbnail, + @Nullable final Bitmap previewThumbnail, @NonNull final ImageView currentSeekbarPreviewThumbnail, @NonNull final IntSupplier baseViewWidthSupplier) { - - if (!optPreviewThumbnail.isPresent()) { + if (previewThumbnail == null) { currentSeekbarPreviewThumbnail.setVisibility(View.GONE); return; } currentSeekbarPreviewThumbnail.setVisibility(View.VISIBLE); - final Bitmap srcBitmap = optPreviewThumbnail.get(); // Resize original bitmap try { - final int srcWidth = srcBitmap.getWidth() > 0 ? srcBitmap.getWidth() : 1; + final int srcWidth = previewThumbnail.getWidth() > 0 ? previewThumbnail.getWidth() : 1; final int newWidth = MathUtils.clamp( // Use 1/4 of the width for the preview Math.round(baseViewWidthSupplier.getAsInt() / 4f), @@ -90,15 +88,16 @@ public final class SeekbarPreviewThumbnailHelper { Math.round(srcWidth * 2.5f)); final float scaleFactor = (float) newWidth / srcWidth; - final int newHeight = (int) (srcBitmap.getHeight() * scaleFactor); + final int newHeight = (int) (previewThumbnail.getHeight() * scaleFactor); - currentSeekbarPreviewThumbnail.setImageBitmap(BitmapCompat.createScaledBitmap(srcBitmap, - newWidth, newHeight, null, true)); + currentSeekbarPreviewThumbnail.setImageBitmap( + BitmapCompat.createScaledBitmap(previewThumbnail, newWidth, newHeight, null, + true)); } catch (final Exception ex) { Log.e(TAG, "Failed to resize and set seekbar preview thumbnail", ex); currentSeekbarPreviewThumbnail.setVisibility(View.GONE); } finally { - srcBitmap.recycle(); + previewThumbnail.recycle(); } } } diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java index 6226900f6..eadb1ac99 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java @@ -74,6 +74,7 @@ import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -746,15 +747,10 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } private int getNearestStreamSegmentPosition(final long playbackPosition) { - //noinspection SimplifyOptionalCallChains - if (!player.getCurrentStreamInfo().isPresent()) { - return 0; - } - int nearestPosition = 0; final List segments = player.getCurrentStreamInfo() - .get() - .getStreamSegments(); + .map(StreamInfo::getStreamSegments) + .orElse(Collections.emptyList()); for (int i = 0; i < segments.size(); i++) { if (segments.get(i).getStartTimeSeconds() * 1000L > playbackPosition) { diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java index bce75d77f..896bb4e70 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/VideoPlayerUi.java @@ -566,7 +566,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa SeekbarPreviewThumbnailHelper .tryResizeAndSetSeekbarPreviewThumbnail( player.getContext(), - seekbarPreviewThumbnailHolder.getBitmapAt(progress), + seekbarPreviewThumbnailHolder.getBitmapAt(progress).orElse(null), binding.currentSeekbarPreviewThumbnail, binding.subtitleView::getWidth); @@ -982,61 +982,56 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa } private void updateStreamRelatedViews() { - //noinspection SimplifyOptionalCallChains - if (!player.getCurrentStreamInfo().isPresent()) { - return; - } - final StreamInfo info = player.getCurrentStreamInfo().get(); + player.getCurrentStreamInfo().ifPresent(info -> { + binding.qualityTextView.setVisibility(View.GONE); + binding.playbackSpeed.setVisibility(View.GONE); - binding.qualityTextView.setVisibility(View.GONE); - binding.playbackSpeed.setVisibility(View.GONE); + binding.playbackEndTime.setVisibility(View.GONE); + binding.playbackLiveSync.setVisibility(View.GONE); - binding.playbackEndTime.setVisibility(View.GONE); - binding.playbackLiveSync.setVisibility(View.GONE); - - switch (info.getStreamType()) { - case AUDIO_STREAM: - case POST_LIVE_AUDIO_STREAM: - binding.surfaceView.setVisibility(View.GONE); - binding.endScreen.setVisibility(View.VISIBLE); - binding.playbackEndTime.setVisibility(View.VISIBLE); - break; - - case AUDIO_LIVE_STREAM: - binding.surfaceView.setVisibility(View.GONE); - binding.endScreen.setVisibility(View.VISIBLE); - binding.playbackLiveSync.setVisibility(View.VISIBLE); - break; - - case LIVE_STREAM: - binding.surfaceView.setVisibility(View.VISIBLE); - binding.endScreen.setVisibility(View.GONE); - binding.playbackLiveSync.setVisibility(View.VISIBLE); - break; - - case VIDEO_STREAM: - case POST_LIVE_STREAM: - //noinspection SimplifyOptionalCallChains - if (player.getCurrentMetadata() != null - && !player.getCurrentMetadata().getMaybeQuality().isPresent() - || (info.getVideoStreams().isEmpty() - && info.getVideoOnlyStreams().isEmpty())) { + switch (info.getStreamType()) { + case AUDIO_STREAM: + case POST_LIVE_AUDIO_STREAM: + binding.surfaceView.setVisibility(View.GONE); + binding.endScreen.setVisibility(View.VISIBLE); + binding.playbackEndTime.setVisibility(View.VISIBLE); break; - } - buildQualityMenu(); + case AUDIO_LIVE_STREAM: + binding.surfaceView.setVisibility(View.GONE); + binding.endScreen.setVisibility(View.VISIBLE); + binding.playbackLiveSync.setVisibility(View.VISIBLE); + break; - binding.qualityTextView.setVisibility(View.VISIBLE); - binding.surfaceView.setVisibility(View.VISIBLE); - // fallthrough - default: - binding.endScreen.setVisibility(View.GONE); - binding.playbackEndTime.setVisibility(View.VISIBLE); - break; - } + case LIVE_STREAM: + binding.surfaceView.setVisibility(View.VISIBLE); + binding.endScreen.setVisibility(View.GONE); + binding.playbackLiveSync.setVisibility(View.VISIBLE); + break; - buildPlaybackSpeedMenu(); - binding.playbackSpeed.setVisibility(View.VISIBLE); + case VIDEO_STREAM: + case POST_LIVE_STREAM: + if (player.getCurrentMetadata() != null + && player.getCurrentMetadata().getMaybeQuality().isEmpty() + || (info.getVideoStreams().isEmpty() + && info.getVideoOnlyStreams().isEmpty())) { + break; + } + + buildQualityMenu(); + + binding.qualityTextView.setVisibility(View.VISIBLE); + binding.surfaceView.setVisibility(View.VISIBLE); + // fallthrough + default: + binding.endScreen.setVisibility(View.GONE); + binding.playbackEndTime.setVisibility(View.VISIBLE); + break; + } + + buildPlaybackSpeedMenu(); + binding.playbackSpeed.setVisibility(View.VISIBLE); + }); } //endregion @@ -1198,8 +1193,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa if (menuItem.getGroupId() == POPUP_MENU_ID_QUALITY) { final int menuItemIndex = menuItem.getItemId(); @Nullable final MediaItemTag currentMetadata = player.getCurrentMetadata(); - //noinspection SimplifyOptionalCallChains - if (currentMetadata == null || !currentMetadata.getMaybeQuality().isPresent()) { + if (currentMetadata == null || currentMetadata.getMaybeQuality().isEmpty()) { return true; } @@ -1300,9 +1294,8 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa // Build UI buildCaptionMenu(availableLanguages); - //noinspection SimplifyOptionalCallChains if (player.getTrackSelector().getParameters().getRendererDisabled( - player.getCaptionRendererIndex()) || !selectedTracks.isPresent()) { + player.getCaptionRendererIndex()) || selectedTracks.isEmpty()) { binding.captionTextView.setText(R.string.caption_none); } else { binding.captionTextView.setText(selectedTracks.get().language);