From 0806344ffbfe4dee04c353ee75650bc6f646d6d5 Mon Sep 17 00:00:00 2001 From: John Zhen Mo Date: Tue, 24 Oct 2017 21:47:14 -0700 Subject: [PATCH] -Changed quality resolution to persist across player. -Updated ExoPlayer to 2.5.4. -Expanded button size in main video player play queue. -Removed Quality event. -Extracted player error strings to xml. --- app/build.gradle | 2 +- .../fragments/detail/VideoDetailFragment.java | 8 +-- .../newpipe/player/BackgroundPlayer.java | 14 ++++- .../org/schabi/newpipe/player/BasePlayer.java | 42 +++++++++---- .../newpipe/player/MainVideoPlayer.java | 23 +++++++- .../newpipe/player/PopupVideoPlayer.java | 23 +++++++- .../schabi/newpipe/player/VideoPlayer.java | 59 ++++++++++++++----- .../player/playback/MediaSourceManager.java | 3 +- .../schabi/newpipe/playlist/PlayQueue.java | 31 ++++------ .../newpipe/playlist/PlayQueueAdapter.java | 7 ++- .../newpipe/playlist/PlayQueueItem.java | 16 ----- .../newpipe/playlist/SinglePlayQueue.java | 4 -- .../newpipe/playlist/events/ErrorEvent.java | 8 ++- .../playlist/events/PlayQueueEventType.java | 3 - .../newpipe/playlist/events/QualityEvent.java | 31 ---------- .../org/schabi/newpipe/util/ListHelper.java | 14 +++++ .../schabi/newpipe/util/NavigationHelper.java | 31 ++++++---- .../main/res/layout/activity_main_player.xml | 29 +++++---- app/src/main/res/values/strings.xml | 4 ++ 19 files changed, 210 insertions(+), 142 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/playlist/events/QualityEvent.java diff --git a/app/build.gradle b/app/build.gradle index b38771560..2f5a06f15 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,7 +66,7 @@ dependencies { compile 'de.hdodenhof:circleimageview:2.1.0' compile 'com.github.nirhart:parallaxscroll:1.0' compile 'com.nononsenseapps:filepicker:3.0.1' - compile 'com.google.android.exoplayer:exoplayer:r2.5.3' + compile 'com.google.android.exoplayer:exoplayer:r2.5.4' debugCompile 'com.facebook.stetho:stetho:1.5.0' debugCompile 'com.facebook.stetho:stetho-urlconnection:1.5.0' 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 72fb47cde..1efab5790 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 @@ -788,14 +788,14 @@ public class VideoDetailFragment extends BaseStateFragment implement ((HistoryListener) activity).onVideoPlayed(currentInfo, getSelectedVideoStream()); } - final PlayQueue playQueue = new SinglePlayQueue(currentInfo, actionBarHandler.getSelectedVideoStream()); + final PlayQueue playQueue = new SinglePlayQueue(currentInfo); final Intent intent; if (append) { Toast.makeText(activity, R.string.popup_playing_append, Toast.LENGTH_SHORT).show(); intent = NavigationHelper.getPlayerEnqueueIntent(activity, PopupVideoPlayer.class, playQueue); } else { Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show(); - intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue); + intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue, getSelectedVideoStream().resolution); } activity.startService(intent); } @@ -866,8 +866,8 @@ public class VideoDetailFragment extends BaseStateFragment implement || (Build.VERSION.SDK_INT < 16); if (!useOldPlayer) { // ExoPlayer - final PlayQueue playQueue = new SinglePlayQueue(currentInfo, actionBarHandler.getSelectedVideoStream()); - mIntent = NavigationHelper.getPlayerIntent(activity, MainVideoPlayer.class, playQueue); + final PlayQueue playQueue = new SinglePlayQueue(currentInfo); + mIntent = NavigationHelper.getPlayerIntent(activity, MainVideoPlayer.class, playQueue, getSelectedVideoStream().resolution); } else { // Internal Player mIntent = new Intent(activity, PlayVideoActivity.class) diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java index ce13b02fa..5ef890579 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -388,13 +388,23 @@ public final class BackgroundPlayer extends Service { @Override public void onRecoverableError(Exception exception) { exception.printStackTrace(); - Toast.makeText(context, "Failed to play this audio", Toast.LENGTH_SHORT).show(); + + if (errorToast == null) { + errorToast = Toast.makeText(context, R.string.player_audio_failure, Toast.LENGTH_SHORT); + errorToast.show(); + } } @Override public void onUnrecoverableError(Exception exception) { exception.printStackTrace(); - Toast.makeText(context, "Unexpected error occurred", Toast.LENGTH_SHORT).show(); + + if (errorToast != null) { + errorToast.cancel(); + } + errorToast = Toast.makeText(context, R.string.player_unexpected_failure, Toast.LENGTH_SHORT); + errorToast.show(); + shutdown(); } 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 cffd024b5..114ed8f7f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -36,6 +36,7 @@ import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import android.view.View; +import android.widget.Toast; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; @@ -125,6 +126,7 @@ public abstract class BasePlayer implements Player.EventListener, public static final String REPEAT_MODE = "repeat_mode"; public static final String PLAYBACK_PITCH = "playback_pitch"; public static final String PLAYBACK_SPEED = "playback_speed"; + public static final String PLAYBACK_QUALITY = "playback_quality"; public static final String PLAY_QUEUE = "play_queue"; public static final String APPEND_ONLY = "append_only"; @@ -141,6 +143,7 @@ public abstract class BasePlayer implements Player.EventListener, protected StreamInfo currentInfo; protected PlayQueueItem currentItem; + protected Toast errorToast; /*////////////////////////////////////////////////////////////////////////// // Player //////////////////////////////////////////////////////////////////////////*/ @@ -659,8 +662,8 @@ public abstract class BasePlayer implements Player.EventListener, * {@link ExoPlaybackException#TYPE_SOURCE TYPE_SOURCE}:

* If the current {@link com.google.android.exoplayer2.Timeline.Window window} has * duration and position greater than 0, then we know the current window is working correctly - * and the error is produced by transitioning into a bad window, therefore we simply increment - * the current index. Otherwise, we report an error to the play queue. + * and the error is produced by transitioning into a bad window, therefore we report an error + * to the play queue based on if the current error can be skipped. * * This is done because ExoPlayer reports the source exceptions before window is * transitioned on seamless playback. @@ -668,27 +671,33 @@ public abstract class BasePlayer implements Player.EventListener, * Because player error causes ExoPlayer to go back to {@link Player#STATE_IDLE STATE_IDLE}, * we reset and prepare the media source again to resume playback.

* - * {@link ExoPlaybackException#TYPE_RENDERER TYPE_RENDERER} and * {@link ExoPlaybackException#TYPE_UNEXPECTED TYPE_UNEXPECTED}:

- * If renderer failed or unexpected exceptions occurred, treat the error as unrecoverable. + * If a runtime error occurred, then we can try to recover it by restarting the playback + * after setting the timestamp recovery. + * + * {@link ExoPlaybackException#TYPE_RENDERER TYPE_RENDERER}:

+ * If the renderer failed, treat the error as unrecoverable. * * @see Player.EventListener#onPlayerError(ExoPlaybackException) * */ @Override public void onPlayerError(ExoPlaybackException error) { if (DEBUG) Log.d(TAG, "onPlayerError() called with: error = [" + error + "]"); + if (errorToast != null) { + errorToast.cancel(); + errorToast = null; + } switch (error.type) { case ExoPlaybackException.TYPE_SOURCE: - if (simpleExoPlayer.getDuration() < 0 || simpleExoPlayer.getCurrentPosition() < 0) { - playQueue.error(); - onRecoverableError(error); - } else { - playQueue.offsetIndex(+1); - } - - playbackManager.reset(); - playbackManager.load(); + final boolean skippable = simpleExoPlayer.getDuration() >= 0 && simpleExoPlayer.getCurrentPosition() >= 0; + playQueue.error(skippable); + onRecoverableError(error); + break; + case ExoPlaybackException.TYPE_UNEXPECTED: + onRecoverableError(error); + setRecovery(); + reload(); break; default: onUnrecoverableError(error); @@ -883,6 +892,13 @@ public abstract class BasePlayer implements Player.EventListener, return pitchFormatter.format(pitch); } + protected void reload() { + if (playbackManager != null) { + playbackManager.reset(); + playbackManager.load(); + } + } + protected void startProgressLoop() { if (progressUpdateReactor != null) progressUpdateReactor.dispose(); progressUpdateReactor = getProgressReactor(); diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index e424e57b5..4a4de3d05 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -344,7 +344,8 @@ public final class MainVideoPlayer extends Activity { this.getPlayQueue(), this.simpleExoPlayer.getRepeatMode(), this.getPlaybackSpeed(), - this.getPlaybackPitch() + this.getPlaybackPitch(), + this.getPlaybackQuality() ); context.startService(intent); destroyPlayer(); @@ -432,13 +433,23 @@ public final class MainVideoPlayer extends Activity { @Override public void onRecoverableError(Exception exception) { exception.printStackTrace(); - Toast.makeText(context, "Failed to play this video", Toast.LENGTH_SHORT).show(); + + if (errorToast == null) { + errorToast = Toast.makeText(context, R.string.player_video_failure, Toast.LENGTH_SHORT); + errorToast.show(); + } } @Override public void onUnrecoverableError(Exception exception) { exception.printStackTrace(); - Toast.makeText(context, "Unexpected error occurred", Toast.LENGTH_SHORT).show(); + + if (errorToast != null) { + errorToast.cancel(); + } + errorToast = Toast.makeText(context, R.string.player_unexpected_failure, Toast.LENGTH_SHORT); + errorToast.show(); + shutdown(); } @@ -447,6 +458,12 @@ public final class MainVideoPlayer extends Activity { return ListHelper.getDefaultResolutionIndex(context, sortedVideos); } + @Override + protected int getOverrideResolutionIndex(final List sortedVideos, + final String playbackQuality) { + return ListHelper.getDefaultResolutionIndex(context, sortedVideos, playbackQuality); + } + /*////////////////////////////////////////////////////////////////////////// // States //////////////////////////////////////////////////////////////////////////*/ 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 0983da4ef..34b223f2b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -441,7 +441,8 @@ public final class PopupVideoPlayer extends Service { this.getPlayQueue(), this.simpleExoPlayer.getRepeatMode(), this.getPlaybackSpeed(), - this.getPlaybackPitch() + this.getPlaybackPitch(), + this.getPlaybackQuality() ); if (!isStartedFromNewPipe()) intent.putExtra(VideoPlayer.STARTED_FROM_NEWPIPE, false); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -468,13 +469,23 @@ public final class PopupVideoPlayer extends Service { @Override public void onRecoverableError(Exception exception) { exception.printStackTrace(); - Toast.makeText(context, "Failed to play this video", Toast.LENGTH_SHORT).show(); + + if (errorToast == null) { + errorToast = Toast.makeText(context, R.string.player_video_failure, Toast.LENGTH_SHORT); + errorToast.show(); + } } @Override public void onUnrecoverableError(Exception exception) { exception.printStackTrace(); - Toast.makeText(context, "Unexpected error occurred", Toast.LENGTH_SHORT).show(); + + if (errorToast != null) { + errorToast.cancel(); + } + errorToast = Toast.makeText(context, R.string.player_unexpected_failure, Toast.LENGTH_SHORT); + errorToast.show(); + shutdown(); } @@ -503,6 +514,12 @@ public final class PopupVideoPlayer extends Service { return ListHelper.getPopupDefaultResolutionIndex(context, sortedVideos); } + @Override + protected int getOverrideResolutionIndex(final List sortedVideos, + final String playbackQuality) { + return ListHelper.getPopupDefaultResolutionIndex(context, sortedVideos, playbackQuality); + } + /*////////////////////////////////////////////////////////////////////////// // Activity Event Listener //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java index 84a2519f7..aebc1b55c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java @@ -25,6 +25,7 @@ import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.PorterDuff; @@ -48,6 +49,7 @@ import android.widget.TextView; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.ConcatenatingMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MergingMediaSource; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; @@ -82,15 +84,17 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. public static final String STARTED_FROM_NEWPIPE = "started_from_newpipe"; - private ArrayList availableStreams; - private int selectedStreamIndex; - /*////////////////////////////////////////////////////////////////////////// // Player //////////////////////////////////////////////////////////////////////////*/ public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds + private ArrayList availableStreams; + private int selectedStreamIndex; + + protected String playbackQuality; + private boolean startedFromNewPipe = true; protected boolean wasPlaying = false; @@ -125,7 +129,6 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. private Handler controlsVisibilityHandler = new Handler(); private boolean isSomePopupMenuVisible = false; - private boolean qualityChanged = false; private int qualityPopupMenuGroupId = 69; private PopupMenu qualityPopupMenu; @@ -197,6 +200,17 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. } } + @Override + public void handleIntent(final Intent intent) { + if (intent == null) return; + + if (intent.hasExtra(PLAYBACK_QUALITY)) { + setPlaybackQuality(intent.getStringExtra(PLAYBACK_QUALITY)); + } + + super.handleIntent(intent); + } + /*////////////////////////////////////////////////////////////////////////// // UI Builders //////////////////////////////////////////////////////////////////////////*/ @@ -232,6 +246,8 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. protected abstract int getDefaultResolutionIndex(final List sortedVideos); + protected abstract int getOverrideResolutionIndex(final List sortedVideos, final String playbackQuality); + @Override public void sync(@NonNull final PlayQueueItem item, @Nullable final StreamInfo info) { super.sync(item, info); @@ -241,11 +257,10 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. if (info != null) { final List videos = ListHelper.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false); availableStreams = new ArrayList<>(videos); - final int qualityIndex = item.getQualityIndex(); - if (qualityIndex == PlayQueueItem.DEFAULT_QUALITY) { + if (playbackQuality == null) { selectedStreamIndex = getDefaultResolutionIndex(videos); } else { - selectedStreamIndex = qualityIndex; + selectedStreamIndex = getOverrideResolutionIndex(videos, getPlaybackQuality()); } buildQualityMenu(); @@ -255,17 +270,17 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. } } + @Override public MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info) { final List videos = ListHelper.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false); - final int sortedStreamsIndex = item.getQualityIndex(); - if (videos.isEmpty() || sortedStreamsIndex >= videos.size()) return null; final VideoStream video; - if (sortedStreamsIndex == PlayQueueItem.DEFAULT_QUALITY) { + if (playbackQuality == null) { final int index = getDefaultResolutionIndex(videos); video = videos.get(index); } else { - video = videos.get(sortedStreamsIndex); + final int index = getOverrideResolutionIndex(videos, getPlaybackQuality()); + video = videos.get(index); } final MediaSource streamSource = buildMediaSource(video.url, MediaFormat.getSuffixById(video.format)); @@ -455,10 +470,15 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. Log.d(TAG, "onMenuItemClick() called with: menuItem = [" + menuItem + "], menuItem.getItemId = [" + menuItem.getItemId() + "]"); if (qualityPopupMenuGroupId == menuItem.getGroupId()) { - if (selectedStreamIndex == menuItem.getItemId()) return true; + final int menuItemIndex = menuItem.getItemId(); + if (selectedStreamIndex == menuItemIndex || + availableStreams == null || availableStreams.size() <= menuItemIndex) return true; + final String oldResolution = getPlaybackQuality(); + final String newResolution = availableStreams.get(menuItemIndex).resolution; setRecovery(); - playQueue.setQuality(playQueue.getIndex(), menuItem.getItemId()); + setPlaybackQuality(newResolution); + reload(); qualityTextView.setText(menuItem.getTitle()); return true; @@ -489,8 +509,9 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. isSomePopupMenuVisible = true; showControls(300); - VideoStream videoStream = getSelectedVideoStream(); - qualityTextView.setText(MediaFormat.getNameById(videoStream.format) + " " + videoStream.resolution); + final VideoStream videoStream = getSelectedVideoStream(); + final String qualityText = MediaFormat.getNameById(videoStream.format) + " " + videoStream.resolution; + qualityTextView.setText(qualityText); wasPlaying = simpleExoPlayer.getPlayWhenReady(); } @@ -648,6 +669,14 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. // Getters and Setters //////////////////////////////////////////////////////////////////////////*/ + public void setPlaybackQuality(final String quality) { + this.playbackQuality = quality; + } + + public String getPlaybackQuality() { + return playbackQuality; + } + public AspectRatioFrameLayout getAspectRatioFrameLayout() { return aspectRatioFrameLayout; } 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 dd4c6fac6..979f7e96c 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 @@ -158,8 +158,8 @@ public class MediaSourceManager implements DeferredMediaSource.Callback { // why no pattern matching in Java =( switch (event.type()) { case INIT: - case QUALITY: case REORDER: + case ERROR: reset(); break; case APPEND: @@ -177,7 +177,6 @@ public class MediaSourceManager implements DeferredMediaSource.Callback { final MoveEvent moveEvent = (MoveEvent) event; move(moveEvent.getFromIndex(), moveEvent.getToIndex()); break; - case ERROR: case RECOVERY: default: break; diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java index a7de95721..09481cb71 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java @@ -14,7 +14,6 @@ import org.schabi.newpipe.playlist.events.RecoveryEvent; import org.schabi.newpipe.playlist.events.RemoveEvent; import org.schabi.newpipe.playlist.events.ReorderEvent; import org.schabi.newpipe.playlist.events.SelectEvent; -import org.schabi.newpipe.playlist.events.QualityEvent; import java.io.Serializable; import java.util.ArrayList; @@ -247,15 +246,22 @@ public abstract class PlayQueue implements Serializable { } /** - * Report an exception for the item at the current index in order to remove it. + * Report an exception for the item at the current index in order and the course of action: + * if the error can be skipped or the current item should be removed. * * This is done as a separate event as the underlying manager may have * different implementation regarding exceptions. * */ - public synchronized void error() { + public synchronized void error(final boolean skippable) { final int index = getIndex(); - removeInternal(index); - broadcast(new ErrorEvent(index)); + + if (skippable) { + queueIndex.incrementAndGet(); + } else { + removeInternal(index); + } + + broadcast(new ErrorEvent(index, skippable)); } private synchronized void removeInternal(final int index) { @@ -301,21 +307,6 @@ public abstract class PlayQueue implements Serializable { broadcast(new MoveEvent(source, target)); } - /** - * Updates the quality index at the given item index. - * - * Broadcasts an update event, signalling to all recipients that they should reset. - * */ - public synchronized void setQuality(final int queueIndex, final int qualityIndex) { - if (queueIndex < 0 || queueIndex >= streams.size()) return; - - final PlayQueueItem item = streams.get(queueIndex); - final int oldQualityIndex = item.getQualityIndex(); - - item.setQualityIndex(qualityIndex); - broadcast(new QualityEvent(queueIndex, oldQualityIndex, qualityIndex)); - } - /** * Sets the recovery record of the item at the index. * diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java index cabcca157..9a856cbb9 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java @@ -102,7 +102,6 @@ public class PlayQueueAdapter extends RecyclerView.Adapter videoStreams, String defaultResolution) { return getDefaultResolutionWithDefaultFormat(context, defaultResolution, videoStreams); } @@ -67,6 +74,13 @@ public final class ListHelper { if (defaultPreferences == null) return 0; String defaultResolution = defaultPreferences.getString(context.getString(R.string.default_popup_resolution_key), context.getString(R.string.default_popup_resolution_value)); + return getPopupDefaultResolutionIndex(context, videoStreams, defaultResolution); + } + + /** + * @see #getDefaultResolutionIndex(String, String, MediaFormat, List) + */ + public static int getPopupDefaultResolutionIndex(Context context, List videoStreams, String defaultResolution) { return getDefaultResolutionWithDefaultFormat(context, defaultResolution, videoStreams); } diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 6cbefaf0f..f287c3a96 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -39,21 +39,19 @@ public class NavigationHelper { //////////////////////////////////////////////////////////////////////////*/ public static Intent getPlayerIntent(final Context context, final Class targetClazz, - final PlayQueue playQueue) { - return new Intent(context, targetClazz) + final PlayQueue playQueue, + final String quality) { + Intent intent = new Intent(context, targetClazz) .putExtra(VideoPlayer.PLAY_QUEUE, playQueue); + if (quality != null) intent.putExtra(VideoPlayer.PLAYBACK_QUALITY, quality); + + return intent; } public static Intent getPlayerIntent(final Context context, final Class targetClazz, - final PlayQueue playQueue, - final int repeatMode, - final float playbackSpeed, - final float playbackPitch) { - return getPlayerIntent(context, targetClazz, playQueue) - .putExtra(BasePlayer.REPEAT_MODE, repeatMode) - .putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed) - .putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch); + final PlayQueue playQueue) { + return getPlayerIntent(context, targetClazz, playQueue, null); } public static Intent getPlayerEnqueueIntent(final Context context, @@ -63,6 +61,19 @@ public class NavigationHelper { .putExtra(BasePlayer.APPEND_ONLY, true); } + public static Intent getPlayerIntent(final Context context, + final Class targetClazz, + final PlayQueue playQueue, + final int repeatMode, + final float playbackSpeed, + final float playbackPitch, + final String playbackQuality) { + return getPlayerIntent(context, targetClazz, playQueue, playbackQuality) + .putExtra(BasePlayer.REPEAT_MODE, repeatMode) + .putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed) + .putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch); + } + /*////////////////////////////////////////////////////////////////////////// // Through FragmentManager //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/res/layout/activity_main_player.xml b/app/src/main/res/layout/activity_main_player.xml index d3dd2ed83..1c3e8eda6 100644 --- a/app/src/main/res/layout/activity_main_player.xml +++ b/app/src/main/res/layout/activity_main_player.xml @@ -57,13 +57,14 @@ @@ -315,7 +318,9 @@ android:layout_centerInParent="true" android:layout_toLeftOf="@id/playPauseButton" android:layout_toStartOf="@id/playPauseButton" - android:background="#00000000" + android:clickable="true" + android:focusable="true" + android:background="?attr/selectableItemBackgroundBorderless" android:scaleType="fitXY" android:src="@drawable/exo_controls_previous" tools:ignore="ContentDescription"/> @@ -329,7 +334,9 @@ android:layout_centerInParent="true" android:layout_toRightOf="@id/playPauseButton" android:layout_toEndOf="@id/playPauseButton" - android:background="#00000000" + android:clickable="true" + android:focusable="true" + android:background="?attr/selectableItemBackgroundBorderless" android:scaleType="fitXY" android:src="@drawable/exo_controls_next" tools:ignore="ContentDescription"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 31547873d..b9b3cded4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -136,6 +136,10 @@ Could not get any stream Could not load image App/UI crashed + Failed to play this video + Failed to play this audio + Unexpected player error occurred + Sorry, that should not have happened. Guru Meditation.