1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-12-23 08:30:44 +00:00

Merge pull request #9285 from Isira-Seneviratne/Optional_cleanup

Clean up Optional-related code.
This commit is contained in:
Stypox 2023-01-11 14:52:25 +01:00 committed by GitHub
commit 87976693f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 185 additions and 218 deletions

View File

@ -255,11 +255,10 @@ public final class VideoDetailFragment
playerUi.ifPresent(MainPlayerUi::toggleFullscreen); playerUi.ifPresent(MainPlayerUi::toggleFullscreen);
} }
//noinspection SimplifyOptionalCallChains
if (playAfterConnect if (playAfterConnect
|| (currentInfo != null || (currentInfo != null
&& isAutoplayEnabled() && isAutoplayEnabled()
&& !playerUi.isPresent())) { && playerUi.isEmpty())) {
autoPlayEnabled = true; // forcefully start playing autoPlayEnabled = true; // forcefully start playing
openVideoPlayerAutoFullscreen(); openVideoPlayerAutoFullscreen();
} }
@ -1174,16 +1173,15 @@ public final class VideoDetailFragment
* be reused in a few milliseconds and the flickering would be annoying. * be reused in a few milliseconds and the flickering would be annoying.
*/ */
private void hideMainPlayerOnLoadingNewStream() { private void hideMainPlayerOnLoadingNewStream() {
//noinspection SimplifyOptionalCallChains final var root = getRoot();
if (!isPlayerServiceAvailable() || !getRoot().isPresent() if (!isPlayerServiceAvailable() || root.isEmpty() || !player.videoPlayerSelected()) {
|| !player.videoPlayerSelected()) {
return; return;
} }
removeVideoPlayerView(); removeVideoPlayerView();
if (isAutoplayEnabled()) { if (isAutoplayEnabled()) {
playerService.stopForImmediateReusing(); playerService.stopForImmediateReusing();
getRoot().ifPresent(view -> view.setVisibility(View.GONE)); root.ifPresent(view -> view.setVisibility(View.GONE));
} else { } else {
playerHolder.stopService(); playerHolder.stopService();
} }
@ -1887,10 +1885,9 @@ public final class VideoDetailFragment
@Override @Override
public void onFullscreenStateChanged(final boolean fullscreen) { public void onFullscreenStateChanged(final boolean fullscreen) {
setupBrightness(); setupBrightness();
//noinspection SimplifyOptionalCallChains
if (!isPlayerAndPlayerServiceAvailable() if (!isPlayerAndPlayerServiceAvailable()
|| !player.UIs().get(MainPlayerUi.class).isPresent() || player.UIs().get(MainPlayerUi.class).isEmpty()
|| getRoot().map(View::getParent).orElse(null) == null) { || getRoot().flatMap(v -> Optional.ofNullable(v.getParent())).isEmpty()) {
return; return;
} }
@ -2429,23 +2426,20 @@ public final class VideoDetailFragment
// helpers to check the state of player and playerService // helpers to check the state of player and playerService
boolean isPlayerAvailable() { boolean isPlayerAvailable() {
return (player != null); return player != null;
} }
boolean isPlayerServiceAvailable() { boolean isPlayerServiceAvailable() {
return (playerService != null); return playerService != null;
} }
boolean isPlayerAndPlayerServiceAvailable() { boolean isPlayerAndPlayerServiceAvailable() {
return (player != null && playerService != null); return player != null && playerService != null;
} }
public Optional<View> getRoot() { public Optional<View> getRoot() {
if (player == null) { return Optional.ofNullable(player)
return Optional.empty(); .flatMap(player1 -> player1.UIs().get(VideoPlayerUi.class))
}
return player.UIs().get(VideoPlayerUi.class)
.map(playerUi -> playerUi.getBinding().getRoot()); .map(playerUi -> playerUi.getBinding().getRoot());
} }

View File

@ -1695,26 +1695,25 @@ public final class Player implements PlaybackListener, Listener {
} }
private void saveStreamProgressState(final long progressMillis) { private void saveStreamProgressState(final long progressMillis) {
//noinspection SimplifyOptionalCallChains getCurrentStreamInfo().ifPresent(info -> {
if (!getCurrentStreamInfo().isPresent() if (!prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)) {
|| !prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)) { return;
return; }
} if (DEBUG) {
if (DEBUG) { Log.d(TAG, "saveStreamProgressState() called with: progressMillis=" + progressMillis
Log.d(TAG, "saveStreamProgressState() called with: progressMillis=" + progressMillis + ", currentMetadata=[" + info.getName() + "]");
+ ", currentMetadata=[" + getCurrentStreamInfo().get().getName() + "]"); }
}
databaseUpdateDisposable databaseUpdateDisposable.add(recordManager.saveStreamState(info, progressMillis)
.add(recordManager.saveStreamState(getCurrentStreamInfo().get(), progressMillis) .observeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread()) .doOnError(e -> {
.doOnError(e -> { if (DEBUG) {
if (DEBUG) { e.printStackTrace();
e.printStackTrace(); }
} })
}) .onErrorComplete()
.onErrorComplete() .subscribe());
.subscribe()); });
} }
public void saveStreamProgressState() { public void saveStreamProgressState() {
@ -1876,23 +1875,16 @@ public final class Player implements PlaybackListener, Listener {
loadController.disablePreloadingOfCurrentTrack(); loadController.disablePreloadingOfCurrentTrack();
} }
@Nullable public Optional<VideoStream> getSelectedVideoStream() {
public VideoStream getSelectedVideoStream() { return Optional.ofNullable(currentMetadata)
@Nullable final MediaItemTag.Quality quality = Optional.ofNullable(currentMetadata)
.flatMap(MediaItemTag::getMaybeQuality) .flatMap(MediaItemTag::getMaybeQuality)
.orElse(null); .filter(quality -> {
if (quality == null) { final int selectedStreamIndex = quality.getSelectedVideoStreamIndex();
return null; return selectedStreamIndex >= 0
} && selectedStreamIndex < quality.getSortedVideoStreams().size();
})
final List<VideoStream> availableStreams = quality.getSortedVideoStreams(); .map(quality -> quality.getSortedVideoStreams()
final int selectedStreamIndex = quality.getSelectedVideoStreamIndex(); .get(quality.getSelectedVideoStreamIndex()));
if (selectedStreamIndex >= 0 && availableStreams.size() > selectedStreamIndex) {
return availableStreams.get(selectedStreamIndex);
} else {
return null;
}
} }
//endregion //endregion
@ -2036,40 +2028,36 @@ public final class Player implements PlaybackListener, Listener {
// in livestreams) so we will be not able to execute the block below. // 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 // 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. // index of the video renderer or playQueueManagerReloadingNeeded returns true.
final Optional<StreamInfo> optCurrentStreamInfo = getCurrentStreamInfo(); getCurrentStreamInfo().ifPresentOrElse(info -> {
if (!optCurrentStreamInfo.isPresent()) { // In the case we don't know the source type, fallback to the one with video with audio
reloadPlayQueueManager(); // or audio-only source.
setRecovery(); final SourceType sourceType = videoResolver.getStreamSourceType()
return; .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 final var parametersBuilder = trackSelector.buildUponParameters();
// audio-only source.
final SourceType sourceType = videoResolver.getStreamSourceType().orElse(
SourceType.VIDEO_WITH_AUDIO_OR_AUDIO_ONLY);
if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) { // Enable/disable the video track and the ability to select subtitles
reloadPlayQueueManager(); parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled);
} else { parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled);
if (StreamTypeUtil.isAudio(info.getStreamType())) {
// Nothing to do more than setting the recovery position trackSelector.setParameters(parametersBuilder);
setRecovery();
return;
} }
final DefaultTrackSelector.Parameters.Builder parametersBuilder = setRecovery();
trackSelector.buildUponParameters(); }, () -> {
// This is executed when the current stream info is not available.
// Enable/disable the video track and the ability to select subtitles reloadPlayQueueManager();
parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !videoEnabled); setRecovery();
parametersBuilder.setTrackTypeDisabled(C.TRACK_TYPE_VIDEO, !videoEnabled); });
trackSelector.setParameters(parametersBuilder);
}
setRecovery();
} }
/** /**

View File

@ -61,12 +61,11 @@ public interface MediaItemTag {
@NonNull @NonNull
static Optional<MediaItemTag> from(@Nullable final MediaItem mediaItem) { static Optional<MediaItemTag> from(@Nullable final MediaItem mediaItem) {
if (mediaItem == null || mediaItem.localConfiguration == null return Optional.ofNullable(mediaItem)
|| !(mediaItem.localConfiguration.tag instanceof MediaItemTag)) { .flatMap(item -> Optional.ofNullable(item.localConfiguration))
return Optional.empty(); .flatMap(localConfiguration -> Optional.ofNullable(localConfiguration.tag))
} .filter(MediaItemTag.class::isInstance)
.map(MediaItemTag.class::cast);
return Optional.of((MediaItemTag) mediaItem.localConfiguration.tag);
} }
@NonNull @NonNull

View File

@ -7,8 +7,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.collection.ArraySet; import androidx.collection.ArraySet;
import com.google.android.exoplayer2.source.MediaSource;
import org.reactivestreams.Subscriber; import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription; import org.reactivestreams.Subscription;
import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@ -23,10 +21,10 @@ import org.schabi.newpipe.player.playqueue.events.MoveEvent;
import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent; import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent;
import org.schabi.newpipe.player.playqueue.events.RemoveEvent; import org.schabi.newpipe.player.playqueue.events.RemoveEvent;
import org.schabi.newpipe.player.playqueue.events.ReorderEvent; import org.schabi.newpipe.player.playqueue.events.ReorderEvent;
import org.schabi.newpipe.util.ServiceHelper;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -43,6 +41,7 @@ import io.reactivex.rxjava3.subjects.PublishSubject;
import static org.schabi.newpipe.player.mediasource.FailedMediaSource.MediaSourceResolutionException; import static org.schabi.newpipe.player.mediasource.FailedMediaSource.MediaSourceResolutionException;
import static org.schabi.newpipe.player.mediasource.FailedMediaSource.StreamInfoLoadException; import static org.schabi.newpipe.player.mediasource.FailedMediaSource.StreamInfoLoadException;
import static org.schabi.newpipe.player.playqueue.PlayQueue.DEBUG; import static org.schabi.newpipe.player.playqueue.PlayQueue.DEBUG;
import static org.schabi.newpipe.util.ServiceHelper.getCacheExpirationMillis;
public class MediaSourceManager { public class MediaSourceManager {
@NonNull @NonNull
@ -421,31 +420,39 @@ public class MediaSourceManager {
} }
private Single<ManagedMediaSource> getLoadedMediaSource(@NonNull final PlayQueueItem stream) { private Single<ManagedMediaSource> getLoadedMediaSource(@NonNull final PlayQueueItem stream) {
return stream.getStream().map(streamInfo -> { return stream.getStream()
final MediaSource source = playbackListener.sourceOf(stream, streamInfo); .map(streamInfo -> Optional
if (source == null || !MediaItemTag.from(source.getMediaItem()).isPresent()) { .ofNullable(playbackListener.sourceOf(stream, streamInfo))
final String message = "Unable to resolve source from stream info. " .<ManagedMediaSource>flatMap(source ->
+ "URL: " + stream.getUrl() + ", " MediaItemTag.from(source.getMediaItem())
+ "audio count: " + streamInfo.getAudioStreams().size() + ", " .map(tag -> {
+ "video count: " + streamInfo.getVideoOnlyStreams().size() + ", " final int serviceId = streamInfo.getServiceId();
+ streamInfo.getVideoStreams().size(); final long expiration = System.currentTimeMillis()
return (ManagedMediaSource) + getCacheExpirationMillis(serviceId);
FailedMediaSource.of(stream, new MediaSourceResolutionException(message)); return new LoadedMediaSource(source, tag, stream,
} expiration);
})
final MediaItemTag tag = MediaItemTag.from(source.getMediaItem()).get(); )
final long expiration = System.currentTimeMillis() .orElseGet(() -> {
+ ServiceHelper.getCacheExpirationMillis(streamInfo.getServiceId()); final String message = "Unable to resolve source from stream info. "
return new LoadedMediaSource(source, tag, stream, expiration); + "URL: " + stream.getUrl()
}).onErrorReturn(throwable -> { + ", audio count: " + streamInfo.getAudioStreams().size()
if (throwable instanceof ExtractionException) { + ", video count: " + streamInfo.getVideoOnlyStreams().size()
return FailedMediaSource.of(stream, new StreamInfoLoadException(throwable)); + ", " + streamInfo.getVideoStreams().size();
} return FailedMediaSource.of(stream,
// Non-source related error expected here (e.g. network), new MediaSourceResolutionException(message));
// should allow retry shortly after the error. })
return FailedMediaSource.of(stream, new Exception(throwable), )
/*allowRetryIn=*/TimeUnit.MILLISECONDS.convert(3, TimeUnit.SECONDS)); .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, private void onMediaSourceReceived(@NonNull final PlayQueueItem item,

View File

@ -8,6 +8,7 @@ import android.widget.ImageView;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.BitmapCompat; import androidx.core.graphics.BitmapCompat;
import androidx.core.math.MathUtils; import androidx.core.math.MathUtils;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
@ -16,7 +17,6 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.DeviceUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.util.Optional;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;
import static java.lang.annotation.RetentionPolicy.SOURCE; import static java.lang.annotation.RetentionPolicy.SOURCE;
@ -66,21 +66,19 @@ public final class SeekbarPreviewThumbnailHelper {
public static void tryResizeAndSetSeekbarPreviewThumbnail( public static void tryResizeAndSetSeekbarPreviewThumbnail(
@NonNull final Context context, @NonNull final Context context,
@NonNull final Optional<Bitmap> optPreviewThumbnail, @Nullable final Bitmap previewThumbnail,
@NonNull final ImageView currentSeekbarPreviewThumbnail, @NonNull final ImageView currentSeekbarPreviewThumbnail,
@NonNull final IntSupplier baseViewWidthSupplier) { @NonNull final IntSupplier baseViewWidthSupplier) {
if (previewThumbnail == null) {
if (!optPreviewThumbnail.isPresent()) {
currentSeekbarPreviewThumbnail.setVisibility(View.GONE); currentSeekbarPreviewThumbnail.setVisibility(View.GONE);
return; return;
} }
currentSeekbarPreviewThumbnail.setVisibility(View.VISIBLE); currentSeekbarPreviewThumbnail.setVisibility(View.VISIBLE);
final Bitmap srcBitmap = optPreviewThumbnail.get();
// Resize original bitmap // Resize original bitmap
try { try {
final int srcWidth = srcBitmap.getWidth() > 0 ? srcBitmap.getWidth() : 1; final int srcWidth = previewThumbnail.getWidth() > 0 ? previewThumbnail.getWidth() : 1;
final int newWidth = MathUtils.clamp( final int newWidth = MathUtils.clamp(
// Use 1/4 of the width for the preview // Use 1/4 of the width for the preview
Math.round(baseViewWidthSupplier.getAsInt() / 4f), Math.round(baseViewWidthSupplier.getAsInt() / 4f),
@ -90,15 +88,15 @@ public final class SeekbarPreviewThumbnailHelper {
Math.round(srcWidth * 2.5f)); Math.round(srcWidth * 2.5f));
final float scaleFactor = (float) newWidth / srcWidth; 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, currentSeekbarPreviewThumbnail.setImageBitmap(BitmapCompat
newWidth, newHeight, null, true)); .createScaledBitmap(previewThumbnail, newWidth, newHeight, null, true));
} catch (final Exception ex) { } catch (final Exception ex) {
Log.e(TAG, "Failed to resize and set seekbar preview thumbnail", ex); Log.e(TAG, "Failed to resize and set seekbar preview thumbnail", ex);
currentSeekbarPreviewThumbnail.setVisibility(View.GONE); currentSeekbarPreviewThumbnail.setVisibility(View.GONE);
} finally { } finally {
srcBitmap.recycle(); previewThumbnail.recycle();
} }
} }
} }

View File

@ -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.KoreUtils;
import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
@ -746,15 +747,10 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
} }
private int getNearestStreamSegmentPosition(final long playbackPosition) { private int getNearestStreamSegmentPosition(final long playbackPosition) {
//noinspection SimplifyOptionalCallChains
if (!player.getCurrentStreamInfo().isPresent()) {
return 0;
}
int nearestPosition = 0; int nearestPosition = 0;
final List<StreamSegment> segments = player.getCurrentStreamInfo() final List<StreamSegment> segments = player.getCurrentStreamInfo()
.get() .map(StreamInfo::getStreamSegments)
.getStreamSegments(); .orElse(Collections.emptyList());
for (int i = 0; i < segments.size(); i++) { for (int i = 0; i < segments.size(); i++) {
if (segments.get(i).getStartTimeSeconds() * 1000L > playbackPosition) { if (segments.get(i).getStartTimeSeconds() * 1000L > playbackPosition) {
@ -866,14 +862,11 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
@Override @Override
protected void onPlaybackSpeedClicked() { protected void onPlaybackSpeedClicked() {
final AppCompatActivity activity = getParentActivity().orElse(null); getParentActivity().ifPresent(activity ->
if (activity == null) { PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(),
return; player.getPlaybackPitch(), player.getPlaybackSkipSilence(),
} player::setPlaybackParameters)
.show(activity.getSupportFragmentManager(), null));
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(), player.getPlaybackPitch(),
player.getPlaybackSkipSilence(), player::setPlaybackParameters)
.show(activity.getSupportFragmentManager(), null);
} }
@Override @Override
@ -973,22 +966,22 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
//region Getters //region Getters
private Optional<Context> getParentContext() {
return Optional.ofNullable(binding.getRoot().getParent())
.filter(ViewGroup.class::isInstance)
.map(parent -> ((ViewGroup) parent).getContext());
}
public Optional<AppCompatActivity> getParentActivity() { public Optional<AppCompatActivity> getParentActivity() {
final ViewParent rootParent = binding.getRoot().getParent(); return getParentContext()
if (rootParent instanceof ViewGroup) { .filter(AppCompatActivity.class::isInstance)
final Context activity = ((ViewGroup) rootParent).getContext(); .map(AppCompatActivity.class::cast);
if (activity instanceof AppCompatActivity) {
return Optional.of((AppCompatActivity) activity);
}
}
return Optional.empty();
} }
public boolean isLandscape() { public boolean isLandscape() {
// DisplayMetrics from activity context knows about MultiWindow feature // DisplayMetrics from activity context knows about MultiWindow feature
// while DisplayMetrics from app context doesn't // while DisplayMetrics from app context doesn't
return DeviceUtils.isLandscape( return DeviceUtils.isLandscape(getParentContext().orElse(player.getService()));
getParentActivity().map(Context.class::cast).orElse(player.getService()));
} }
//endregion //endregion
} }

View File

@ -566,7 +566,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
SeekbarPreviewThumbnailHelper SeekbarPreviewThumbnailHelper
.tryResizeAndSetSeekbarPreviewThumbnail( .tryResizeAndSetSeekbarPreviewThumbnail(
player.getContext(), player.getContext(),
seekbarPreviewThumbnailHolder.getBitmapAt(progress), seekbarPreviewThumbnailHolder.getBitmapAt(progress).orElse(null),
binding.currentSeekbarPreviewThumbnail, binding.currentSeekbarPreviewThumbnail,
binding.subtitleView::getWidth); binding.subtitleView::getWidth);
@ -982,61 +982,56 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
} }
private void updateStreamRelatedViews() { private void updateStreamRelatedViews() {
//noinspection SimplifyOptionalCallChains player.getCurrentStreamInfo().ifPresent(info -> {
if (!player.getCurrentStreamInfo().isPresent()) { binding.qualityTextView.setVisibility(View.GONE);
return; binding.playbackSpeed.setVisibility(View.GONE);
}
final StreamInfo info = player.getCurrentStreamInfo().get();
binding.qualityTextView.setVisibility(View.GONE); binding.playbackEndTime.setVisibility(View.GONE);
binding.playbackSpeed.setVisibility(View.GONE); binding.playbackLiveSync.setVisibility(View.GONE);
binding.playbackEndTime.setVisibility(View.GONE); switch (info.getStreamType()) {
binding.playbackLiveSync.setVisibility(View.GONE); case AUDIO_STREAM:
case POST_LIVE_AUDIO_STREAM:
switch (info.getStreamType()) { binding.surfaceView.setVisibility(View.GONE);
case AUDIO_STREAM: binding.endScreen.setVisibility(View.VISIBLE);
case POST_LIVE_AUDIO_STREAM: binding.playbackEndTime.setVisibility(View.VISIBLE);
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())) {
break; 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); case LIVE_STREAM:
binding.surfaceView.setVisibility(View.VISIBLE); binding.surfaceView.setVisibility(View.VISIBLE);
// fallthrough binding.endScreen.setVisibility(View.GONE);
default: binding.playbackLiveSync.setVisibility(View.VISIBLE);
binding.endScreen.setVisibility(View.GONE); break;
binding.playbackEndTime.setVisibility(View.VISIBLE);
break;
}
buildPlaybackSpeedMenu(); case VIDEO_STREAM:
binding.playbackSpeed.setVisibility(View.VISIBLE); 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 //endregion
@ -1065,12 +1060,11 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
qualityPopupMenu.getMenu().add(POPUP_MENU_ID_QUALITY, i, Menu.NONE, MediaFormat qualityPopupMenu.getMenu().add(POPUP_MENU_ID_QUALITY, i, Menu.NONE, MediaFormat
.getNameById(videoStream.getFormatId()) + " " + videoStream.getResolution()); .getNameById(videoStream.getFormatId()) + " " + videoStream.getResolution());
} }
final VideoStream selectedVideoStream = player.getSelectedVideoStream();
if (selectedVideoStream != null) {
binding.qualityTextView.setText(selectedVideoStream.getResolution());
}
qualityPopupMenu.setOnMenuItemClickListener(this); qualityPopupMenu.setOnMenuItemClickListener(this);
qualityPopupMenu.setOnDismissListener(this); qualityPopupMenu.setOnDismissListener(this);
player.getSelectedVideoStream()
.ifPresent(s -> binding.qualityTextView.setText(s.getResolution()));
} }
private void buildPlaybackSpeedMenu() { private void buildPlaybackSpeedMenu() {
@ -1176,12 +1170,9 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
qualityPopupMenu.show(); qualityPopupMenu.show();
isSomePopupMenuVisible = true; isSomePopupMenuVisible = true;
final VideoStream videoStream = player.getSelectedVideoStream(); player.getSelectedVideoStream()
if (videoStream != null) { .map(s -> MediaFormat.getNameById(s.getFormatId()) + " " + s.getResolution())
//noinspection SetTextI18n .ifPresent(binding.qualityTextView::setText);
binding.qualityTextView.setText(MediaFormat.getNameById(videoStream.getFormatId())
+ " " + videoStream.getResolution());
}
} }
/** /**
@ -1198,8 +1189,7 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
if (menuItem.getGroupId() == POPUP_MENU_ID_QUALITY) { if (menuItem.getGroupId() == POPUP_MENU_ID_QUALITY) {
final int menuItemIndex = menuItem.getItemId(); final int menuItemIndex = menuItem.getItemId();
@Nullable final MediaItemTag currentMetadata = player.getCurrentMetadata(); @Nullable final MediaItemTag currentMetadata = player.getCurrentMetadata();
//noinspection SimplifyOptionalCallChains if (currentMetadata == null || currentMetadata.getMaybeQuality().isEmpty()) {
if (currentMetadata == null || !currentMetadata.getMaybeQuality().isPresent()) {
return true; return true;
} }
@ -1238,10 +1228,9 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
Log.d(TAG, "onDismiss() called with: menu = [" + menu + "]"); Log.d(TAG, "onDismiss() called with: menu = [" + menu + "]");
} }
isSomePopupMenuVisible = false; //TODO check if this works isSomePopupMenuVisible = false; //TODO check if this works
final VideoStream selectedVideoStream = player.getSelectedVideoStream(); player.getSelectedVideoStream()
if (selectedVideoStream != null) { .ifPresent(s -> binding.qualityTextView.setText(s.getResolution()));
binding.qualityTextView.setText(selectedVideoStream.getResolution());
}
if (player.isPlaying()) { if (player.isPlaying()) {
hideControls(DEFAULT_CONTROLS_DURATION, 0); hideControls(DEFAULT_CONTROLS_DURATION, 0);
hideSystemUIIfNeeded(); hideSystemUIIfNeeded();
@ -1300,9 +1289,8 @@ public abstract class VideoPlayerUi extends PlayerUi implements SeekBar.OnSeekBa
// Build UI // Build UI
buildCaptionMenu(availableLanguages); buildCaptionMenu(availableLanguages);
//noinspection SimplifyOptionalCallChains
if (player.getTrackSelector().getParameters().getRendererDisabled( if (player.getTrackSelector().getParameters().getRendererDisabled(
player.getCaptionRendererIndex()) || !selectedTracks.isPresent()) { player.getCaptionRendererIndex()) || selectedTracks.isEmpty()) {
binding.captionTextView.setText(R.string.caption_none); binding.captionTextView.setText(R.string.caption_none);
} else { } else {
binding.captionTextView.setText(selectedTracks.get().language); binding.captionTextView.setText(selectedTracks.get().language);