Skip to content

Commit

Permalink
Merge pull request #9285 from Isira-Seneviratne/Optional_cleanup
Browse files Browse the repository at this point in the history
Clean up Optional-related code.
  • Loading branch information
Stypox authored Jan 11, 2023
2 parents 1bb166a + 9c7ed80 commit 8797669
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 217 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,10 @@ public void onServiceConnected(final Player connectedPlayer,
playerUi.ifPresent(MainPlayerUi::toggleFullscreen);
}

//noinspection SimplifyOptionalCallChains
if (playAfterConnect
|| (currentInfo != null
&& isAutoplayEnabled()
&& !playerUi.isPresent())) {
&& playerUi.isEmpty())) {
autoPlayEnabled = true; // forcefully start playing
openVideoPlayerAutoFullscreen();
}
Expand Down Expand Up @@ -1174,16 +1173,15 @@ private void openMainPlayer() {
* 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();
}
Expand Down Expand Up @@ -1887,10 +1885,9 @@ public void onServiceStopped() {
@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) {
|| player.UIs().get(MainPlayerUi.class).isEmpty()
|| getRoot().flatMap(v -> Optional.ofNullable(v.getParent())).isEmpty()) {
return;
}

Expand Down Expand Up @@ -2429,23 +2426,20 @@ private void setOverlayElementsClickable(final boolean enable) {

// helpers to check the state of player and playerService
boolean isPlayerAvailable() {
return (player != null);
return player != null;
}

boolean isPlayerServiceAvailable() {
return (playerService != null);
return playerService != null;
}

boolean isPlayerAndPlayerServiceAvailable() {
return (player != null && playerService != null);
return player != null && playerService != null;
}

public Optional<View> getRoot() {
if (player == null) {
return Optional.empty();
}

return player.UIs().get(VideoPlayerUi.class)
return Optional.ofNullable(player)
.flatMap(player1 -> player1.UIs().get(VideoPlayerUi.class))
.map(playerUi -> playerUi.getBinding().getRoot());
}

Expand Down
116 changes: 52 additions & 64 deletions app/src/main/java/org/schabi/newpipe/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -1695,26 +1695,25 @@ private void registerStreamViewed() {
}

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() {
Expand Down Expand Up @@ -1876,23 +1875,16 @@ public void disablePreloadingOfCurrentTrack() {
loadController.disablePreloadingOfCurrentTrack();
}

@Nullable
public VideoStream getSelectedVideoStream() {
@Nullable final MediaItemTag.Quality quality = Optional.ofNullable(currentMetadata)
public Optional<VideoStream> getSelectedVideoStream() {
return Optional.ofNullable(currentMetadata)
.flatMap(MediaItemTag::getMaybeQuality)
.orElse(null);
if (quality == null) {
return null;
}

final List<VideoStream> availableStreams = quality.getSortedVideoStreams();
final int selectedStreamIndex = quality.getSelectedVideoStreamIndex();

if (selectedStreamIndex >= 0 && availableStreams.size() > selectedStreamIndex) {
return availableStreams.get(selectedStreamIndex);
} else {
return null;
}
.filter(quality -> {
final int selectedStreamIndex = quality.getSelectedVideoStreamIndex();
return selectedStreamIndex >= 0
&& selectedStreamIndex < quality.getSortedVideoStreams().size();
})
.map(quality -> quality.getSortedVideoStreams()
.get(quality.getSelectedVideoStreamIndex()));
}
//endregion

Expand Down Expand Up @@ -2036,40 +2028,36 @@ public void useVideoSource(final boolean videoEnabled) {
// 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<StreamInfo> optCurrentStreamInfo = getCurrentStreamInfo();
if (!optCurrentStreamInfo.isPresent()) {
reloadPlayQueueManager();
setRecovery();
return;
}

final StreamInfo info = optCurrentStreamInfo.get();

// 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);
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);

if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) {
reloadPlayQueueManager();
} else {
if (StreamTypeUtil.isAudio(info.getStreamType())) {
// Nothing to do more than setting the recovery position
setRecovery();
return;
}
if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) {
reloadPlayQueueManager();
} else {
if (StreamTypeUtil.isAudio(info.getStreamType())) {
// Nothing to do more than setting the recovery position
setRecovery();
return;
}

final DefaultTrackSelector.Parameters.Builder parametersBuilder =
trackSelector.buildUponParameters();
final var 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);
// 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);
}
trackSelector.setParameters(parametersBuilder);
}

setRecovery();
setRecovery();
}, () -> {
// This is executed when the current stream info is not available.
reloadPlayQueueManager();
setRecovery();
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,11 @@ default Optional<Quality> getMaybeQuality() {

@NonNull
static Optional<MediaItemTag> from(@Nullable final MediaItem mediaItem) {
if (mediaItem == null || mediaItem.localConfiguration == null
|| !(mediaItem.localConfiguration.tag instanceof MediaItemTag)) {
return Optional.empty();
}

return Optional.of((MediaItemTag) mediaItem.localConfiguration.tag);
return Optional.ofNullable(mediaItem)
.flatMap(item -> Optional.ofNullable(item.localConfiguration))
.flatMap(localConfiguration -> Optional.ofNullable(localConfiguration.tag))
.filter(MediaItemTag.class::isInstance)
.map(MediaItemTag.class::cast);
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import androidx.annotation.Nullable;
import androidx.collection.ArraySet;

import com.google.android.exoplayer2.source.MediaSource;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
Expand All @@ -23,10 +21,10 @@
import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent;
import org.schabi.newpipe.player.playqueue.events.RemoveEvent;
import org.schabi.newpipe.player.playqueue.events.ReorderEvent;
import org.schabi.newpipe.util.ServiceHelper;

import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
Expand All @@ -43,6 +41,7 @@
import static org.schabi.newpipe.player.mediasource.FailedMediaSource.MediaSourceResolutionException;
import static org.schabi.newpipe.player.mediasource.FailedMediaSource.StreamInfoLoadException;
import static org.schabi.newpipe.player.playqueue.PlayQueue.DEBUG;
import static org.schabi.newpipe.util.ServiceHelper.getCacheExpirationMillis;

public class MediaSourceManager {
@NonNull
Expand Down Expand Up @@ -421,31 +420,39 @@ private void maybeLoadItem(@NonNull final PlayQueueItem item) {
}

private Single<ManagedMediaSource> 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()) {
final String message = "Unable to resolve source from stream info. "
+ "URL: " + stream.getUrl() + ", "
+ "audio count: " + streamInfo.getAudioStreams().size() + ", "
+ "video count: " + streamInfo.getVideoOnlyStreams().size() + ", "
+ streamInfo.getVideoStreams().size();
return (ManagedMediaSource)
FailedMediaSource.of(stream, new MediaSourceResolutionException(message));
}

final MediaItemTag tag = MediaItemTag.from(source.getMediaItem()).get();
final long expiration = System.currentTimeMillis()
+ ServiceHelper.getCacheExpirationMillis(streamInfo.getServiceId());
return new LoadedMediaSource(source, tag, stream, expiration);
}).onErrorReturn(throwable -> {
if (throwable instanceof ExtractionException) {
return FailedMediaSource.of(stream, new StreamInfoLoadException(throwable));
}
// Non-source related error expected here (e.g. network),
// should allow retry shortly after the error.
return FailedMediaSource.of(stream, new Exception(throwable),
/*allowRetryIn=*/TimeUnit.MILLISECONDS.convert(3, TimeUnit.SECONDS));
});
return stream.getStream()
.map(streamInfo -> Optional
.ofNullable(playbackListener.sourceOf(stream, streamInfo))
.<ManagedMediaSource>flatMap(source ->
MediaItemTag.from(source.getMediaItem())
.map(tag -> {
final int serviceId = streamInfo.getServiceId();
final long expiration = System.currentTimeMillis()
+ getCacheExpirationMillis(serviceId);
return new LoadedMediaSource(source, tag, stream,
expiration);
})
)
.orElseGet(() -> {
final String message = "Unable to resolve source from stream info. "
+ "URL: " + stream.getUrl()
+ ", audio count: " + streamInfo.getAudioStreams().size()
+ ", video count: " + streamInfo.getVideoOnlyStreams().size()
+ ", " + streamInfo.getVideoStreams().size();
return FailedMediaSource.of(stream,
new MediaSourceResolutionException(message));
})
)
.onErrorReturn(throwable -> {
if (throwable instanceof ExtractionException) {
return FailedMediaSource.of(stream, new StreamInfoLoadException(throwable));
}
// Non-source related error expected here (e.g. network),
// should allow retry shortly after the error.
final long allowRetryIn = TimeUnit.MILLISECONDS.convert(3,
TimeUnit.SECONDS);
return FailedMediaSource.of(stream, new Exception(throwable), allowRetryIn);
});
}

private void onMediaSourceReceived(@NonNull final PlayQueueItem item,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

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;
Expand All @@ -16,7 +17,6 @@
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;
Expand Down Expand Up @@ -66,21 +66,19 @@ public static int getSeekbarPreviewThumbnailType(@NonNull final Context context)

public static void tryResizeAndSetSeekbarPreviewThumbnail(
@NonNull final Context context,
@NonNull final Optional<Bitmap> 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),
Expand All @@ -90,15 +88,15 @@ public static void tryResizeAndSetSeekbarPreviewThumbnail(
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();
}
}
}
Loading

0 comments on commit 8797669

Please sign in to comment.