1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-12-23 00:20:32 +00:00

updated: onPlayerError to not catch unspecified source errors so notifications are created.

updated: Throwable usage to Exceptions.
updated: minor styles and documentations.
This commit is contained in:
karyogamy 2022-03-26 20:17:52 -04:00
parent b81eb35f3d
commit d289dc8a53
7 changed files with 44 additions and 40 deletions

View File

@ -1961,13 +1961,12 @@ public final class Player implements
final boolean showPrev = playQueue.getIndex() != 0; final boolean showPrev = playQueue.getIndex() != 0;
final boolean showNext = playQueue.getIndex() + 1 != playQueue.getStreams().size(); final boolean showNext = playQueue.getIndex() + 1 != playQueue.getStreams().size();
final boolean showQueue = playQueue.getStreams().size() > 1 && !popupPlayerSelected(); final boolean showQueue = playQueue.getStreams().size() > 1 && !popupPlayerSelected();
boolean showSegment = false; /* only when stream has segments and is not playing in popup player */
showSegment = /*only when stream has segment and playing in fullscreen player*/ final boolean showSegment = !popupPlayerSelected()
!popupPlayerSelected() && !getCurrentStreamInfo()
&& !getCurrentStreamInfo() .map(StreamInfo::getStreamSegments)
.map(StreamInfo::getStreamSegments) .map(List::isEmpty)
.map(List::isEmpty) .orElse(/*no stream info=*/true);
.orElse(/*no stream info=*/true);
binding.playPreviousButton.setVisibility(showPrev ? View.VISIBLE : View.INVISIBLE); binding.playPreviousButton.setVisibility(showPrev ? View.VISIBLE : View.INVISIBLE);
binding.playPreviousButton.setAlpha(showPrev ? 1.0f : 0.0f); binding.playPreviousButton.setAlpha(showPrev ? 1.0f : 0.0f);
@ -2014,7 +2013,7 @@ public final class Player implements
+ "playWhenReady = [" + playWhenReady + "], " + "playWhenReady = [" + playWhenReady + "], "
+ "reason = [" + reason + "]"); + "reason = [" + reason + "]");
} }
final int playbackState = simpleExoPlayer == null final int playbackState = exoPlayerIsNull()
? com.google.android.exoplayer2.Player.STATE_IDLE ? com.google.android.exoplayer2.Player.STATE_IDLE
: simpleExoPlayer.getPlaybackState(); : simpleExoPlayer.getPlaybackState();
updatePlaybackState(playWhenReady, playbackState); updatePlaybackState(playWhenReady, playbackState);
@ -2026,8 +2025,7 @@ public final class Player implements
Log.d(TAG, "ExoPlayer - onPlaybackStateChanged() called with: " Log.d(TAG, "ExoPlayer - onPlaybackStateChanged() called with: "
+ "playbackState = [" + playbackState + "]"); + "playbackState = [" + playbackState + "]");
} }
final boolean playWhenReady = simpleExoPlayer != null && simpleExoPlayer.getPlayWhenReady(); updatePlaybackState(getPlayWhenReady(), playbackState);
updatePlaybackState(playWhenReady, playbackState);
} }
private void updatePlaybackState(final boolean playWhenReady, final int playbackState) { private void updatePlaybackState(final boolean playWhenReady, final int playbackState) {
@ -2486,6 +2484,19 @@ public final class Player implements
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
//region ExoPlayer listeners (that didn't fit in other categories) //region ExoPlayer listeners (that didn't fit in other categories)
/**
* <p>Listens for event or state changes on ExoPlayer. When any event happens, we check for
* changes in the currently-playing metadata and update the encapsulating
* {@link Player}. Downstream listeners are also informed.
*
* <p>When the renewed metadata contains any error, it is reported as a notification.
* This is done because not all source resolution errors are {@link PlaybackException}, which
* are also captured by {@link ExoPlayer} and stops the playback.
*
* @param player The {@link com.google.android.exoplayer2.Player} whose state changed.
* @param events The {@link com.google.android.exoplayer2.Player.Events} that has triggered
* the player state changes.
**/
@Override @Override
public void onEvents(@NonNull final com.google.android.exoplayer2.Player player, public void onEvents(@NonNull final com.google.android.exoplayer2.Player player,
@NonNull final com.google.android.exoplayer2.Player.Events events) { @NonNull final com.google.android.exoplayer2.Player.Events events) {
@ -2602,11 +2613,12 @@ public final class Player implements
* <li>{@link PlaybackException#ERROR_CODE_BEHIND_LIVE_WINDOW BEHIND_LIVE_WINDOW}: * <li>{@link PlaybackException#ERROR_CODE_BEHIND_LIVE_WINDOW BEHIND_LIVE_WINDOW}:
* If the playback on livestreams are lagged too far behind the current playable * If the playback on livestreams are lagged too far behind the current playable
* window. Then we seek to the latest timestamp and restart the playback. * window. Then we seek to the latest timestamp and restart the playback.
* This error is <b>catchable</b>.
* </li> * </li>
* <li>From {@link PlaybackException#ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE BAD_IO} to * <li>From {@link PlaybackException#ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE BAD_IO} to
* {@link PlaybackException#ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED UNSUPPORTED_FORMATS}: * {@link PlaybackException#ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED UNSUPPORTED_FORMATS}:
* If the stream source is validated by the extractor but not recognized by the player, * If the stream source is validated by the extractor but not recognized by the player,
* then we can try to recover playback by signal an error on the {@link PlayQueue}.</li> * then we can try to recover playback by signalling an error on the {@link PlayQueue}.</li>
* <li>For {@link PlaybackException#ERROR_CODE_TIMEOUT PLAYER_TIMEOUT}, * <li>For {@link PlaybackException#ERROR_CODE_TIMEOUT PLAYER_TIMEOUT},
* {@link PlaybackException#ERROR_CODE_IO_UNSPECIFIED MEDIA_SOURCE_RESOLVER_TIMEOUT} and * {@link PlaybackException#ERROR_CODE_IO_UNSPECIFIED MEDIA_SOURCE_RESOLVER_TIMEOUT} and
* {@link PlaybackException#ERROR_CODE_IO_NETWORK_CONNECTION_FAILED NO_NETWORK}: * {@link PlaybackException#ERROR_CODE_IO_NETWORK_CONNECTION_FAILED NO_NETWORK}:
@ -2617,8 +2629,8 @@ public final class Player implements
* We terminate the playback.</li> * We terminate the playback.</li>
* <li>For any other unspecified issue internal: We set a recovery and try to restart * <li>For any other unspecified issue internal: We set a recovery and try to restart
* the playback.</li> * the playback.</li>
* In the case of decoder/renderer or unspecified errors, the player will create a * For any error above that is <b>not</b> explicitly <b>catchable</b>, the player will
* notification so the users are aware. * create a notification so users are aware.
* </ul> * </ul>
* @see com.google.android.exoplayer2.Player.Listener#onPlayerError(PlaybackException) * @see com.google.android.exoplayer2.Player.Listener#onPlayerError(PlaybackException)
* */ * */
@ -2627,7 +2639,6 @@ public final class Player implements
public void onPlayerError(@NonNull final PlaybackException error) { public void onPlayerError(@NonNull final PlaybackException error) {
Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error); Log.e(TAG, "ExoPlayer - onPlayerError() called with:", error);
setRecovery();
saveStreamProgressState(); saveStreamProgressState();
boolean isCatchableException = false; boolean isCatchableException = false;
@ -2652,7 +2663,6 @@ public final class Player implements
case ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED: case ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED:
// Source errors, signal on playQueue and move on: // Source errors, signal on playQueue and move on:
if (!exoPlayerIsNull() && playQueue != null) { if (!exoPlayerIsNull() && playQueue != null) {
isCatchableException = true;
playQueue.error(); playQueue.error();
} }
break; break;
@ -2660,11 +2670,6 @@ public final class Player implements
case ERROR_CODE_IO_UNSPECIFIED: case ERROR_CODE_IO_UNSPECIFIED:
case ERROR_CODE_IO_NETWORK_CONNECTION_FAILED: case ERROR_CODE_IO_NETWORK_CONNECTION_FAILED:
case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT: case ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT:
// Don't create notification on timeout/networking errors:
isCatchableException = true;
setRecovery();
reloadPlayQueueManager();
break;
case ERROR_CODE_UNSPECIFIED: case ERROR_CODE_UNSPECIFIED:
// Reload playback on unexpected errors: // Reload playback on unexpected errors:
setRecovery(); setRecovery();
@ -3010,10 +3015,9 @@ public final class Player implements
} }
public void saveStreamProgressStateCompleted() { public void saveStreamProgressStateCompleted() {
getCurrentStreamInfo().ifPresent(info -> { // current stream has ended, so the progress is its duration (+1 to overcome rounding)
// current stream has ended, so the progress is its duration (+1 to overcome rounding) getCurrentStreamInfo().ifPresent(info ->
saveStreamProgressState((info.getDuration() + 1) * 1000); saveStreamProgressState((info.getDuration() + 1) * 1000));
});
} }
//endregion //endregion
@ -3414,7 +3418,8 @@ public final class Player implements
case VIDEO_STREAM: case VIDEO_STREAM:
if (currentMetadata == null if (currentMetadata == null
|| !currentMetadata.getMaybeQuality().isPresent() || !currentMetadata.getMaybeQuality().isPresent()
|| info.getVideoStreams().size() + info.getVideoOnlyStreams().size() == 0) { || (info.getVideoStreams().isEmpty()
&& info.getVideoOnlyStreams().isEmpty())) {
break; break;
} }
@ -3684,10 +3689,8 @@ public final class Player implements
} }
// Normalize mismatching language strings // Normalize mismatching language strings
final List<String> preferredLanguages = final String preferredLanguage = trackSelector.getParameters()
trackSelector.getParameters().preferredTextLanguages; .preferredTextLanguages.stream().findFirst().orElse(null);
final String preferredLanguage =
preferredLanguages.isEmpty() ? null : preferredLanguages.get(0);
// Build UI // Build UI
buildCaptionMenu(availableLanguages); buildCaptionMenu(availableLanguages);
if (trackSelector.getParameters().getRendererDisabled(textRenderer) if (trackSelector.getParameters().getRendererDisabled(textRenderer)

View File

@ -24,12 +24,12 @@ public final class ExceptionTag implements MediaItemTag {
@NonNull @NonNull
private final PlayQueueItem item; private final PlayQueueItem item;
@NonNull @NonNull
private final List<Throwable> errors; private final List<Exception> errors;
@Nullable @Nullable
private final Object extras; private final Object extras;
private ExceptionTag(@NonNull final PlayQueueItem item, private ExceptionTag(@NonNull final PlayQueueItem item,
@NonNull final List<Throwable> errors, @NonNull final List<Exception> errors,
@Nullable final Object extras) { @Nullable final Object extras) {
this.item = item; this.item = item;
this.errors = errors; this.errors = errors;
@ -37,13 +37,13 @@ public final class ExceptionTag implements MediaItemTag {
} }
public static ExceptionTag of(@NonNull final PlayQueueItem playQueueItem, public static ExceptionTag of(@NonNull final PlayQueueItem playQueueItem,
@NonNull final List<Throwable> errors) { @NonNull final List<Exception> errors) {
return new ExceptionTag(playQueueItem, errors, null); return new ExceptionTag(playQueueItem, errors, null);
} }
@NonNull @NonNull
@Override @Override
public List<Throwable> getErrors() { public List<Exception> getErrors() {
return errors; return errors;
} }

View File

@ -26,7 +26,7 @@ import androidx.annotation.Nullable;
**/ **/
public interface MediaItemTag { public interface MediaItemTag {
List<Throwable> getErrors(); List<Exception> getErrors();
int getServiceId(); int getServiceId();

View File

@ -29,7 +29,7 @@ public final class PlaceholderTag implements MediaItemTag {
@NonNull @NonNull
@Override @Override
public List<Throwable> getErrors() { public List<Exception> getErrors() {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -47,7 +47,7 @@ public final class StreamInfoTag implements MediaItemTag {
} }
@Override @Override
public List<Throwable> getErrors() { public List<Exception> getErrors() {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -36,7 +36,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode()); private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode());
private final PlayQueueItem playQueueItem; private final PlayQueueItem playQueueItem;
private final Throwable error; private final Exception error;
private final long retryTimestamp; private final long retryTimestamp;
private final MediaItem mediaItem; private final MediaItem mediaItem;
/** /**
@ -51,7 +51,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
* @param retryTimestamp epoch timestamp when this MediaSource can be refreshed * @param retryTimestamp epoch timestamp when this MediaSource can be refreshed
*/ */
public FailedMediaSource(@NonNull final PlayQueueItem playQueueItem, public FailedMediaSource(@NonNull final PlayQueueItem playQueueItem,
@NonNull final Throwable error, @NonNull final Exception error,
final long retryTimestamp) { final long retryTimestamp) {
this.playQueueItem = playQueueItem; this.playQueueItem = playQueueItem;
this.error = error; this.error = error;
@ -68,7 +68,7 @@ public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSo
} }
public static FailedMediaSource of(@NonNull final PlayQueueItem playQueueItem, public static FailedMediaSource of(@NonNull final PlayQueueItem playQueueItem,
@NonNull final Throwable error, @NonNull final Exception error,
final long retryWaitMillis) { final long retryWaitMillis) {
return new FailedMediaSource(playQueueItem, error, return new FailedMediaSource(playQueueItem, error,
System.currentTimeMillis() + retryWaitMillis); System.currentTimeMillis() + retryWaitMillis);

View File

@ -441,7 +441,8 @@ public class MediaSourceManager {
if (throwable instanceof ExtractionException) { if (throwable instanceof ExtractionException) {
return FailedMediaSource.of(stream, new StreamInfoLoadException(throwable)); return FailedMediaSource.of(stream, new StreamInfoLoadException(throwable));
} }
return FailedMediaSource.of(stream, throwable, /*immediatelyRetryable=*/0L); return FailedMediaSource
.of(stream, new Exception(throwable), /*immediatelyRetryable=*/0L);
}); });
} }