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 80230d0f7..c62382782 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 @@ -88,6 +88,12 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh // fullscreen player private ItemTouchHelper itemTouchHelper; + + /*////////////////////////////////////////////////////////////////////////// + // Constructor, setup, destroy + //////////////////////////////////////////////////////////////////////////*/ + //region Constructor, setup, destroy + public MainPlayerUi(@NonNull final Player player, @NonNull final PlayerBinding playerBinding) { super(player, playerBinding); @@ -272,12 +278,14 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh resources.getDimensionPixelSize(R.dimen.player_main_buttons_padding) ); } + //endregion /*////////////////////////////////////////////////////////////////////////// // Broadcast receiver //////////////////////////////////////////////////////////////////////////*/ //region Broadcast receiver + @Override public void onBroadcastReceived(final Intent intent) { super.onBroadcastReceived(intent); @@ -313,6 +321,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh // Fragment binding //////////////////////////////////////////////////////////////////////////*/ //region Fragment binding + @Override public void onFragmentListenerSet() { super.onFragmentListenerSet(); @@ -351,13 +360,11 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } //endregion - private void showHideKodiButton() { - // show kodi button if it supports the current service and it is enabled in settings - @Nullable final PlayQueue playQueue = player.getPlayQueue(); - binding.playWithKodi.setVisibility(playQueue != null && playQueue.getItem() != null - && KoreUtils.shouldShowPlayWithKodi(context, playQueue.getItem().getServiceId()) - ? View.VISIBLE : View.GONE); - } + + /*////////////////////////////////////////////////////////////////////////// + // Playback states + //////////////////////////////////////////////////////////////////////////*/ + //region Playback states @Override public void onUpdateProgress(final int currentProgress, @@ -373,6 +380,22 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh } } + @Override + public void onPlaying() { + super.onPlaying(); + checkLandscape(); + } + + @Override + public void onCompleted() { + super.onCompleted(); + if (isFullscreen) { + toggleFullscreen(); + } + } + //endregion + + /*////////////////////////////////////////////////////////////////////////// // Controls showing / hiding //////////////////////////////////////////////////////////////////////////*/ @@ -457,22 +480,21 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh return Math.min(bitmap.getHeight(), screenHeight); } } + + private void showHideKodiButton() { + // show kodi button if it supports the current service and it is enabled in settings + @Nullable final PlayQueue playQueue = player.getPlayQueue(); + binding.playWithKodi.setVisibility(playQueue != null && playQueue.getItem() != null + && KoreUtils.shouldShowPlayWithKodi(context, playQueue.getItem().getServiceId()) + ? View.VISIBLE : View.GONE); + } //endregion - @Override - public void onPlaying() { - super.onPlaying(); - checkLandscape(); - } - - @Override - public void onCompleted() { - super.onCompleted(); - if (isFullscreen) { - toggleFullscreen(); - } - } + /*////////////////////////////////////////////////////////////////////////// + // Captions (text tracks) + //////////////////////////////////////////////////////////////////////////*/ + //region Captions (text tracks) @Override protected void setupSubtitleView(float captionScale) { @@ -482,8 +504,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh binding.subtitleView.setFixedTextSize( TypedValue.COMPLEX_UNIT_PX, minimumLength / captionRatioInverse); } - - + //endregion /*////////////////////////////////////////////////////////////////////////// @@ -798,6 +819,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh // Click listeners //////////////////////////////////////////////////////////////////////////*/ //region Click listeners + @Override public void onClick(final View v) { if (v.getId() == binding.screenRotationButton.getId()) { @@ -855,9 +877,9 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh /*////////////////////////////////////////////////////////////////////////// - // Video size, resize, orientation, fullscreen + // Video size, orientation, fullscreen //////////////////////////////////////////////////////////////////////////*/ - //region Video size, resize, orientation, fullscreen + //region Video size, orientation, fullscreen private void setupScreenRotationButton() { binding.screenRotationButton.setVisibility(globalScreenOrientationLocked(context) @@ -941,9 +963,6 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh // Getters //////////////////////////////////////////////////////////////////////////*/ //region Getters - public PlayerBinding getBinding() { - return binding; - } public Optional getParentActivity() { final ViewParent rootParent = binding.getRoot().getParent(); diff --git a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java index 7df9102b7..43440b873 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java +++ b/app/src/main/java/org/schabi/newpipe/player/ui/PopupPlayerUi.java @@ -8,7 +8,6 @@ import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutP import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.SuppressLint; -import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; @@ -61,6 +60,12 @@ public final class PopupPlayerUi extends VideoPlayerUi { private WindowManager.LayoutParams popupLayoutParams; // null if player is not popup private final WindowManager windowManager; + + /*////////////////////////////////////////////////////////////////////////// + // Constructor, setup, destroy + //////////////////////////////////////////////////////////////////////////*/ + //region Constructor, setup, destroy + public PopupPlayerUi(@NonNull final Player player, @NonNull final PlayerBinding playerBinding) { super(player, playerBinding); @@ -173,11 +178,14 @@ public final class PopupPlayerUi extends VideoPlayerUi { super.destroy(); removePopupFromView(); } + //endregion + /*////////////////////////////////////////////////////////////////////////// // Broadcast receiver //////////////////////////////////////////////////////////////////////////*/ //region Broadcast receiver + @Override public void onBroadcastReceived(final Intent intent) { super.onBroadcastReceived(intent); @@ -200,6 +208,11 @@ public final class PopupPlayerUi extends VideoPlayerUi { //endregion + /*////////////////////////////////////////////////////////////////////////// + // Popup position and size + //////////////////////////////////////////////////////////////////////////*/ + //region Popup position and size + /** * Check if {@link #popupLayoutParams}' position is within a arbitrary boundary * that goes from (0, 0) to (screenWidth, screenHeight). @@ -272,16 +285,19 @@ public final class PopupPlayerUi extends VideoPlayerUi { windowManager.updateViewLayout(binding.getRoot(), popupLayoutParams); } - private void changePopupWindowFlags(final int flags) { - if (DEBUG) { - Log.d(TAG, "changePopupWindowFlags() called with: flags = [" + flags + "]"); - } - - if (!anyPopupViewIsNull()) { - popupLayoutParams.flags = flags; - windowManager.updateViewLayout(binding.getRoot(), popupLayoutParams); - } + @Override + protected float calculateMaxEndScreenThumbnailHeight(@NonNull final Bitmap bitmap) { + // no need for the end screen thumbnail to be resized on popup player: it's only needed + // for the main player so that it is enlarged correctly inside the fragment + return bitmap.getHeight(); } + //endregion + + + /*////////////////////////////////////////////////////////////////////////// + // Popup closing + //////////////////////////////////////////////////////////////////////////*/ + //region Popup closing public void closePopup() { if (DEBUG) { @@ -351,23 +367,22 @@ public final class PopupPlayerUi extends VideoPlayerUi { } }).start(); } + //endregion - @Override - protected float calculateMaxEndScreenThumbnailHeight(@NonNull final Bitmap bitmap) { - // no need for the end screen thumbnail to be resized on popup player: it's only needed - // for the main player so that it is enlarged correctly inside the fragment - return bitmap.getHeight(); - } + /*////////////////////////////////////////////////////////////////////////// + // Playback states + //////////////////////////////////////////////////////////////////////////*/ + //region Playback states - private boolean popupHasParent() { - return binding != null - && binding.getRoot().getLayoutParams() instanceof WindowManager.LayoutParams - && binding.getRoot().getParent() != null; - } + private void changePopupWindowFlags(final int flags) { + if (DEBUG) { + Log.d(TAG, "changePopupWindowFlags() called with: flags = [" + flags + "]"); + } - private boolean anyPopupViewIsNull() { - return popupLayoutParams == null || windowManager == null - || binding.getRoot().getParent() == null; + if (!anyPopupViewIsNull()) { + popupLayoutParams.flags = flags; + windowManager.updateViewLayout(binding.getRoot(), popupLayoutParams); + } } @Override @@ -400,11 +415,14 @@ public final class PopupPlayerUi extends VideoPlayerUi { playbackSpeedPopupMenu.show(); isSomePopupMenuVisible = true; } + //endregion + /*////////////////////////////////////////////////////////////////////////// // Gestures //////////////////////////////////////////////////////////////////////////*/ //region Gestures + private int distanceFromCloseButton(@NonNull final MotionEvent popupMotionEvent) { final int closeOverlayButtonX = closeOverlayBinding.closeButton.getLeft() + closeOverlayBinding.closeButton.getWidth() / 2; @@ -433,7 +451,19 @@ public final class PopupPlayerUi extends VideoPlayerUi { /*////////////////////////////////////////////////////////////////////////// // Getters //////////////////////////////////////////////////////////////////////////*/ - //region Gestures + //region Getters + + private boolean popupHasParent() { + return binding != null + && binding.getRoot().getLayoutParams() instanceof WindowManager.LayoutParams + && binding.getRoot().getParent() != null; + } + + private boolean anyPopupViewIsNull() { + return popupLayoutParams == null || windowManager == null + || binding.getRoot().getParent() == null; + } + public PlayerPopupCloseOverlayBinding getCloseOverlayBinding() { return closeOverlayBinding; } 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 24cdb8908..f4ebc3304 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 @@ -135,6 +135,12 @@ public abstract class VideoPlayerUi extends PlayerUi @NonNull private final SeekbarPreviewThumbnailHolder seekbarPreviewThumbnailHolder = new SeekbarPreviewThumbnailHolder(); + + /*////////////////////////////////////////////////////////////////////////// + // Constructor, setup, destroy + //////////////////////////////////////////////////////////////////////////*/ + //region Constructor, setup, destroy + public VideoPlayerUi(@NonNull final Player player, @NonNull final PlayerBinding playerBinding) { super(player); @@ -142,11 +148,6 @@ public abstract class VideoPlayerUi extends PlayerUi setupFromView(); } - - /*////////////////////////////////////////////////////////////////////////// - // Setup - //////////////////////////////////////////////////////////////////////////*/ - //region Setup public void setupFromView() { initViews(); initListeners(); @@ -414,6 +415,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Broadcast receiver //////////////////////////////////////////////////////////////////////////*/ //region Broadcast receiver + @Override public void onBroadcastReceived(final Intent intent) { super.onBroadcastReceived(intent); @@ -433,6 +435,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Thumbnail //////////////////////////////////////////////////////////////////////////*/ //region Thumbnail + /** * Scale the player audio / end screen thumbnail down if necessary. *

@@ -481,6 +484,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Progress loop and updates //////////////////////////////////////////////////////////////////////////*/ //region Progress loop and updates + @Override public void onUpdateProgress(final int currentProgress, final int duration, @@ -744,6 +748,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Playback states //////////////////////////////////////////////////////////////////////////*/ //region Playback states + @Override public void onPrepared() { super.onPrepared(); @@ -885,7 +890,8 @@ public abstract class VideoPlayerUi extends PlayerUi /*////////////////////////////////////////////////////////////////////////// // Repeat, shuffle, mute //////////////////////////////////////////////////////////////////////////*/ - //region Repeat and shuffle + //region Repeat, shuffle, mute + public void onRepeatClicked() { if (DEBUG) { Log.d(TAG, "onRepeatClicked() called"); @@ -945,52 +951,9 @@ public abstract class VideoPlayerUi extends PlayerUi /*////////////////////////////////////////////////////////////////////////// - // ExoPlayer listeners (that didn't fit in other categories) + // Other player listeners //////////////////////////////////////////////////////////////////////////*/ - //region ExoPlayer listeners (that didn't fit in other categories) - @Override - public void onTextTracksChanged(@NonNull final Tracks currentTracks) { - super.onTextTracksChanged(currentTracks); - - final boolean trackTypeTextSupported = !currentTracks.containsType(C.TRACK_TYPE_TEXT) - || currentTracks.isTypeSupported(C.TRACK_TYPE_TEXT, false); - if (getPlayer().getTrackSelector().getCurrentMappedTrackInfo() == null - || !trackTypeTextSupported) { - binding.captionTextView.setVisibility(View.GONE); - return; - } - - // Extract all loaded languages - final List textTracks = currentTracks - .getGroups() - .stream() - .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getType()) - .collect(Collectors.toList()); - final List availableLanguages = textTracks.stream() - .map(Tracks.Group::getMediaTrackGroup) - .filter(textTrack -> textTrack.length > 0) - .map(textTrack -> textTrack.getFormat(0).language) - .collect(Collectors.toList()); - - // Find selected text track - final Optional selectedTracks = textTracks.stream() - .filter(Tracks.Group::isSelected) - .filter(info -> info.getMediaTrackGroup().length >= 1) - .map(info -> info.getMediaTrackGroup().getFormat(0)) - .findFirst(); - - // Build UI - buildCaptionMenu(availableLanguages); - //noinspection SimplifyOptionalCallChains - if (player.getTrackSelector().getParameters().getRendererDisabled( - player.getCaptionRendererIndex()) || !selectedTracks.isPresent()) { - binding.captionTextView.setText(R.string.caption_none); - } else { - binding.captionTextView.setText(selectedTracks.get().language); - } - binding.captionTextView.setVisibility( - availableLanguages.isEmpty() ? View.GONE : View.VISIBLE); - } + //region Other player listeners @Override public void onPlaybackParametersChanged(@NonNull final PlaybackParameters playbackParameters) { @@ -1004,12 +967,6 @@ public abstract class VideoPlayerUi extends PlayerUi //TODO check if this causes black screen when switching to fullscreen animate(binding.surfaceForeground, false, DEFAULT_CONTROLS_DURATION); } - - @Override - public void onCues(@NonNull List cues) { - super.onCues(cues); - binding.subtitleView.setCues(cues); - } //endregion @@ -1017,6 +974,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Metadata & stream related views //////////////////////////////////////////////////////////////////////////*/ //region Metadata & stream related views + @Override public void onMetadataChanged(@NonNull final StreamInfo info) { super.onMetadataChanged(info); @@ -1092,6 +1050,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Popup menus ("popup" means that they pop up, not that they belong to the popup player) //////////////////////////////////////////////////////////////////////////*/ //region Popup menus ("popup" means that they pop up, not that they belong to the popup player) + private void buildQualityMenu() { if (qualityPopupMenu == null) { return; @@ -1315,6 +1274,57 @@ public abstract class VideoPlayerUi extends PlayerUi // Captions (text tracks) //////////////////////////////////////////////////////////////////////////*/ //region Captions (text tracks) + + @Override + public void onTextTracksChanged(@NonNull final Tracks currentTracks) { + super.onTextTracksChanged(currentTracks); + + final boolean trackTypeTextSupported = !currentTracks.containsType(C.TRACK_TYPE_TEXT) + || currentTracks.isTypeSupported(C.TRACK_TYPE_TEXT, false); + if (getPlayer().getTrackSelector().getCurrentMappedTrackInfo() == null + || !trackTypeTextSupported) { + binding.captionTextView.setVisibility(View.GONE); + return; + } + + // Extract all loaded languages + final List textTracks = currentTracks + .getGroups() + .stream() + .filter(trackGroupInfo -> C.TRACK_TYPE_TEXT == trackGroupInfo.getType()) + .collect(Collectors.toList()); + final List availableLanguages = textTracks.stream() + .map(Tracks.Group::getMediaTrackGroup) + .filter(textTrack -> textTrack.length > 0) + .map(textTrack -> textTrack.getFormat(0).language) + .collect(Collectors.toList()); + + // Find selected text track + final Optional selectedTracks = textTracks.stream() + .filter(Tracks.Group::isSelected) + .filter(info -> info.getMediaTrackGroup().length >= 1) + .map(info -> info.getMediaTrackGroup().getFormat(0)) + .findFirst(); + + // Build UI + buildCaptionMenu(availableLanguages); + //noinspection SimplifyOptionalCallChains + if (player.getTrackSelector().getParameters().getRendererDisabled( + player.getCaptionRendererIndex()) || !selectedTracks.isPresent()) { + binding.captionTextView.setText(R.string.caption_none); + } else { + binding.captionTextView.setText(selectedTracks.get().language); + } + binding.captionTextView.setVisibility( + availableLanguages.isEmpty() ? View.GONE : View.VISIBLE); + } + + @Override + public void onCues(@NonNull List cues) { + super.onCues(cues); + binding.subtitleView.setCues(cues); + } + private void setupSubtitleView() { setupSubtitleView(PlayerHelper.getCaptionScale(context)); final CaptionStyleCompat captionStyle = PlayerHelper.getCaptionStyle(context); @@ -1330,6 +1340,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Click listeners //////////////////////////////////////////////////////////////////////////*/ //region Click listeners + @Override public void onClick(final View v) { if (DEBUG) { @@ -1493,9 +1504,10 @@ public abstract class VideoPlayerUi extends PlayerUi /*////////////////////////////////////////////////////////////////////////// - // Video size, resize, orientation, fullscreen + // Video size //////////////////////////////////////////////////////////////////////////*/ - //region Video size, resize, orientation, fullscreen + //region Video size + protected void setResizeMode(@AspectRatioFrameLayout.ResizeMode final int resizeMode) { binding.surfaceView.setResizeMode(resizeMode); binding.resizeTextView.setText(PlayerHelper.resizeTypeOf(context, resizeMode)); @@ -1569,6 +1581,7 @@ public abstract class VideoPlayerUi extends PlayerUi // Getters //////////////////////////////////////////////////////////////////////////*/ //region Getters + public PlayerBinding getBinding() { return binding; }