diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 748ef00c5..c24a46049 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -590,12 +590,12 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen if (DEBUG) Log.d(TAG, "onPositionDiscontinuity() called with window index = [" + newWindowIndex + "]"); // If the user selects a new track, then the discontinuity occurs after the index is changed. - // Therefore, the only source that causes a discrepancy would be autoplay, + // Therefore, the only source that causes a discrepancy would be gapless transition, // which can only offset the current track by +1. - if (newWindowIndex != playQueue.getIndex() && playbackManager != null) { + if (newWindowIndex == playQueue.getIndex() + 1) { playQueue.offsetIndex(+1); - playbackManager.load(); } + playbackManager.load(); } @Override @@ -612,6 +612,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen if (simpleExoPlayer == null) return; if (DEBUG) Log.d(TAG, "Blocking..."); + currentItem = null; + currentInfo = null; simpleExoPlayer.stop(); isPrepared = false; @@ -642,8 +644,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen // Check if on wrong window final int currentSourceIndex = playQueue.indexOf(item); if (currentSourceIndex != playQueue.getIndex()) { - throw new IllegalStateException("Play Queue may be desynchronized: item index=[" + - currentSourceIndex + "], queue index=[" + playQueue.getIndex() + "]"); + Log.e(TAG, "Play Queue may be desynchronized: item index=[" + currentSourceIndex + + "], queue index=[" + playQueue.getIndex() + "]"); } else if (simpleExoPlayer.getCurrentWindowIndex() != currentSourceIndex) { final long startPos = info != null ? info.start_position : 0; if (DEBUG) Log.d(TAG, "Rewinding to correct window: " + currentSourceIndex + " at: " + getTimeString((int)startPos)); @@ -829,15 +831,15 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } public String getVideoUrl() { - return currentItem == null ? null : currentItem.getUrl(); + return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUrl(); } public String getVideoTitle() { - return currentItem == null ? null : currentItem.getTitle(); + return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getTitle(); } public String getUploaderName() { - return currentItem == null ? null : currentItem.getUploader(); + return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUploader(); } public boolean isCompleted() { @@ -873,8 +875,10 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen } public PlaybackParameters getPlaybackParameters() { + final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f); + if (simpleExoPlayer == null) return defaultParameters; final PlaybackParameters parameters = simpleExoPlayer.getPlaybackParameters(); - return parameters == null ? new PlaybackParameters(1f, 1f) : parameters; + return parameters == null ? defaultParameters : parameters; } public void setPlaybackParameters(float speed, float pitch) { @@ -903,7 +907,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen final int queuePos = playQueue.getIndex(); final long windowPos = simpleExoPlayer.getCurrentPosition(); - if (windowPos > 0) { + if (windowPos > 0 && windowPos <= simpleExoPlayer.getDuration()) { setRecovery(queuePos, windowPos); } } diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 89d58141d..71068dbea 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -65,6 +65,7 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.player.event.PlayerEventListener; +import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.old.PlayVideoActivity; import org.schabi.newpipe.player.helper.LockManager; import org.schabi.newpipe.playlist.PlayQueueItem; @@ -96,7 +97,6 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView; public final class PopupVideoPlayer extends Service { private static final String TAG = ".PopupVideoPlayer"; private static final boolean DEBUG = BasePlayer.DEBUG; - private static final int SHUTDOWN_FLING_VELOCITY = 10000; private static final int NOTIFICATION_ID = 40028922; public static final String ACTION_CLOSE = "org.schabi.newpipe.player.PopupVideoPlayer.CLOSE"; @@ -112,6 +112,9 @@ public final class PopupVideoPlayer extends Service { private WindowManager.LayoutParams windowLayoutParams; private GestureDetector gestureDetector; + private int shutdownFlingVelocity; + private int tossFlingVelocity; + private float screenWidth, screenHeight; private float popupWidth, popupHeight; @@ -211,12 +214,14 @@ public final class PopupVideoPlayer extends Service { View rootView = View.inflate(this, R.layout.player_popup, null); playerImpl.setup(rootView); + shutdownFlingVelocity = PlayerHelper.getShutdownFlingVelocity(this); + tossFlingVelocity = PlayerHelper.getTossFlingVelocity(this); + updateScreenSize(); + final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(this); + final float defaultSize = getResources().getDimension(R.dimen.popup_default_width); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); - boolean popupRememberSizeAndPos = sharedPreferences.getBoolean(getString(R.string.popup_remember_size_pos_key), true); - - float defaultSize = getResources().getDimension(R.dimen.popup_default_width); popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize; final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_PHONE : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; @@ -791,11 +796,20 @@ public final class PopupVideoPlayer extends Service { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (DEBUG) Log.d(TAG, "Fling velocity: dX=[" + velocityX + "], dY=[" + velocityY + "]"); if (playerImpl == null) return false; - if (Math.abs(velocityX) > SHUTDOWN_FLING_VELOCITY) { - if (DEBUG) Log.d(TAG, "Popup close fling velocity= " + velocityX); + + final float absVelocityX = Math.abs(velocityX); + final float absVelocityY = Math.abs(velocityY); + if (absVelocityX > shutdownFlingVelocity) { onClose(); return true; + } else if (Math.max(absVelocityX, absVelocityY) > tossFlingVelocity) { + if (absVelocityX > tossFlingVelocity) windowLayoutParams.x = (int) velocityX; + if (absVelocityY > tossFlingVelocity) windowLayoutParams.y = (int) velocityY; + checkPositionBounds(); + windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); + return true; } return false; } diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index ef77cdda2..4fe228dfc 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -286,6 +286,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (player == null) return false; + player.setPlaybackSpeed(playbackSpeed); return true; } @@ -304,6 +306,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (player == null) return false; + player.setPlaybackPitch(playbackPitch); return true; } @@ -317,6 +321,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity remove.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { + if (player == null) return false; + final int index = player.getPlayQueue().indexOf(item); if (index != -1) player.getPlayQueue().remove(index); return true; @@ -349,7 +355,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity final int sourceIndex = source.getLayoutPosition(); final int targetIndex = target.getLayoutPosition(); - player.getPlayQueue().move(sourceIndex, targetIndex); + if (player != null) player.getPlayQueue().move(sourceIndex, targetIndex); return true; } @@ -372,11 +378,13 @@ public abstract class ServicePlayerActivity extends AppCompatActivity return new PlayQueueItemBuilder.OnSelectedListener() { @Override public void selected(PlayQueueItem item, View view) { - player.onSelected(item); + if (player != null) player.onSelected(item); } @Override public void held(PlayQueueItem item, View view) { + if (player == null) return; + final int index = player.getPlayQueue().indexOf(item); if (index != -1) buildItemPopupMenu(item, view); } @@ -403,19 +411,19 @@ public abstract class ServicePlayerActivity extends AppCompatActivity @Override public void onClick(View view) { if (view.getId() == repeatButton.getId()) { - player.onRepeatClicked(); + if (player != null) player.onRepeatClicked(); } else if (view.getId() == backwardButton.getId()) { - player.onPlayPrevious(); + if (player != null) player.onPlayPrevious(); } else if (view.getId() == playPauseButton.getId()) { - player.onVideoPlayPause(); + if (player != null) player.onVideoPlayPause(); } else if (view.getId() == forwardButton.getId()) { - player.onPlayNext(); + if (player != null) player.onPlayNext(); } else if (view.getId() == shuffleButton.getId()) { - player.onShuffleClicked(); + if (player != null) player.onShuffleClicked(); } else if (view.getId() == playbackSpeedButton.getId()) { playbackSpeedPopupMenu.show(); @@ -450,7 +458,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity @Override public void onStopTrackingTouch(SeekBar seekBar) { - player.simpleExoPlayer.seekTo(seekBar.getProgress()); + if (player != null) player.simpleExoPlayer.seekTo(seekBar.getProgress()); seekDisplay.setVisibility(View.GONE); seeking = false; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 558f82b43..40063ba40 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -12,6 +12,8 @@ import java.text.NumberFormat; import java.util.Formatter; import java.util.Locale; +import javax.annotation.Nonnull; + public class PlayerHelper { private PlayerHelper() {} @@ -56,6 +58,10 @@ public class PlayerHelper { return isUsingOldPlayer(context, false); } + public static boolean isRememberingPopupDimensions(@Nonnull final Context context) { + return isRememberingPopupDimensions(context, true); + } + public static long getPreferredCacheSize(@NonNull final Context context) { return 64 * 1024 * 1024L; } @@ -83,6 +89,15 @@ public class PlayerHelper { public static boolean isUsingDSP(@NonNull final Context context) { return true; } + + public static int getShutdownFlingVelocity(@Nonnull final Context context) { + return 10000; + } + + public static int getTossFlingVelocity(@Nonnull final Context context) { + return 2500; + } + //////////////////////////////////////////////////////////////////////////// // Private helpers //////////////////////////////////////////////////////////////////////////// @@ -103,4 +118,8 @@ public class PlayerHelper { private static boolean isUsingOldPlayer(@NonNull final Context context, final boolean b) { return getPreferences(context).getBoolean(context.getString(R.string.use_old_player_key), b); } + + private static boolean isRememberingPopupDimensions(@Nonnull final Context context, final boolean b) { + return getPreferences(context).getBoolean(context.getString(R.string.popup_remember_size_pos_key), b); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ad69915b9..7092feaf5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -122,6 +122,8 @@ NewPipe Notification Notifications for NewPipe Background and Popup Players + [Unknown] + Error Network error