Mask playWhenReady state in CastPlayer

When the user calls setPlayWhenReady, the state modifications are
observed as immediate, in spite of being sent to the receiver app
as asynchronous operations.

PiperOrigin-RevId: 273289768
This commit is contained in:
aquilescanta 2019-10-07 15:47:21 +01:00 committed by Oliver Woodman
parent 29eebca5c5
commit dddce4307b

View File

@ -50,12 +50,13 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** /**
* {@link Player} implementation that communicates with a Cast receiver app. * {@link Player} implementation that communicates with a Cast receiver app.
* *
* <p>The behavior of this class depends on the underlying Cast session, which is obtained from the * <p>The behavior of this class depends on the underlying Cast session, which is obtained from the
* Cast context passed to {@link #CastPlayer}. To keep track of the session, {@link * Cast context passed to {@link #@}. To keep track of the session, {@link
* #isCastSessionAvailable()} can be queried and {@link SessionAvailabilityListener} can be * #isCastSessionAvailable()} can be queried and {@link SessionAvailabilityListener} can be
* implemented and attached to the player. * implemented and attached to the player.
* *
@ -133,7 +134,7 @@ public final class CastPlayer extends BasePlayer {
currentTrackSelection = EMPTY_TRACK_SELECTION_ARRAY; currentTrackSelection = EMPTY_TRACK_SELECTION_ARRAY;
pendingSeekWindowIndex = C.INDEX_UNSET; pendingSeekWindowIndex = C.INDEX_UNSET;
pendingSeekPositionMs = C.TIME_UNSET; pendingSeekPositionMs = C.TIME_UNSET;
updateInternalState(); maybeUpdateInternalState();
} }
// Media Queue manipulation methods. // Media Queue manipulation methods.
@ -323,7 +324,7 @@ public final class CastPlayer extends BasePlayer {
} }
@Override @Override
@State @Player.State
public int getPlaybackState() { public int getPlaybackState() {
return playbackState; return playbackState;
} }
@ -345,11 +346,19 @@ public final class CastPlayer extends BasePlayer {
if (remoteMediaClient == null) { if (remoteMediaClient == null) {
return; return;
} }
if (playWhenReady) { // We send the message to the receiver app and update the local state, which will cause the
remoteMediaClient.play(); // operation to be perceived as synchronous by the user.
} else { PendingResult<MediaChannelResult> pendingResult =
remoteMediaClient.pause(); playWhenReady ? remoteMediaClient.play() : remoteMediaClient.pause();
} pendingResult.setResultCallback(
mediaChannelResult -> {
if (remoteMediaClient != null) {
maybeUpdatePlayerStateAndNotify();
flushNotifications();
}
});
maybeSetPlayerStateAndNotify(playWhenReady, playbackState);
flushNotifications();
} }
@Override @Override
@ -538,23 +547,14 @@ public final class CastPlayer extends BasePlayer {
// Internal methods. // Internal methods.
private void updateInternalState() { private void maybeUpdateInternalState() {
if (remoteMediaClient == null) { if (remoteMediaClient == null) {
// There is no session. We leave the state of the player as it is now. // There is no session. We leave the state of the player as it is now.
return; return;
} }
boolean wasPlaying = playbackState == Player.STATE_READY && playWhenReady; boolean wasPlaying = playbackState == Player.STATE_READY && playWhenReady;
int playbackState = fetchPlaybackState(remoteMediaClient); maybeUpdatePlayerStateAndNotify();
boolean playWhenReady = !remoteMediaClient.isPaused();
if (this.playbackState != playbackState
|| this.playWhenReady != playWhenReady) {
this.playbackState = playbackState;
this.playWhenReady = playWhenReady;
notificationsBatch.add(
new ListenerNotificationTask(
listener -> listener.onPlayerStateChanged(this.playWhenReady, this.playbackState)));
}
boolean isPlaying = playbackState == Player.STATE_READY && playWhenReady; boolean isPlaying = playbackState == Player.STATE_READY && playWhenReady;
if (wasPlaying != isPlaying) { if (wasPlaying != isPlaying) {
notificationsBatch.add( notificationsBatch.add(
@ -592,6 +592,12 @@ public final class CastPlayer extends BasePlayer {
flushNotifications(); flushNotifications();
} }
@RequiresNonNull("remoteMediaClient")
private void maybeUpdatePlayerStateAndNotify() {
maybeSetPlayerStateAndNotify(
!remoteMediaClient.isPaused(), fetchPlaybackState(remoteMediaClient));
}
private void maybeUpdateTimelineAndNotify() { private void maybeUpdateTimelineAndNotify() {
if (updateTimeline()) { if (updateTimeline()) {
@Player.TimelineChangeReason @Player.TimelineChangeReason
@ -668,6 +674,17 @@ public final class CastPlayer extends BasePlayer {
return false; return false;
} }
private void maybeSetPlayerStateAndNotify(
boolean playWhenReady, @Player.State int playbackState) {
if (this.playWhenReady != playWhenReady || this.playbackState != playbackState) {
this.playWhenReady = playWhenReady;
this.playbackState = playbackState;
notificationsBatch.add(
new ListenerNotificationTask(
listener -> listener.onPlayerStateChanged(playWhenReady, playbackState)));
}
}
private void setRemoteMediaClient(@Nullable RemoteMediaClient remoteMediaClient) { private void setRemoteMediaClient(@Nullable RemoteMediaClient remoteMediaClient) {
if (this.remoteMediaClient == remoteMediaClient) { if (this.remoteMediaClient == remoteMediaClient) {
// Do nothing. // Do nothing.
@ -684,7 +701,7 @@ public final class CastPlayer extends BasePlayer {
} }
remoteMediaClient.addListener(statusListener); remoteMediaClient.addListener(statusListener);
remoteMediaClient.addProgressListener(statusListener, PROGRESS_REPORT_PERIOD_MS); remoteMediaClient.addProgressListener(statusListener, PROGRESS_REPORT_PERIOD_MS);
updateInternalState(); maybeUpdateInternalState();
} else { } else {
if (sessionAvailabilityListener != null) { if (sessionAvailabilityListener != null) {
sessionAvailabilityListener.onCastSessionUnavailable(); sessionAvailabilityListener.onCastSessionUnavailable();
@ -803,7 +820,7 @@ public final class CastPlayer extends BasePlayer {
@Override @Override
public void onStatusUpdated() { public void onStatusUpdated() {
updateInternalState(); maybeUpdateInternalState();
} }
@Override @Override
@ -908,5 +925,4 @@ public final class CastPlayer extends BasePlayer {
} }
} }
} }
} }