mirror of
https://github.com/androidx/media.git
synced 2025-05-05 06:30:24 +08:00
Trigger media item transition event in CastPlayer
#minor-release PiperOrigin-RevId: 361803897
This commit is contained in:
parent
ff8db9a4fe
commit
b74bfa1e9a
@ -63,6 +63,8 @@
|
|||||||
* Fix `onPositionDiscontinuity` event so that it is not triggered with
|
* Fix `onPositionDiscontinuity` event so that it is not triggered with
|
||||||
reason `DISCONTINUITY_REASON_PERIOD_TRANSITION` after a seek to another
|
reason `DISCONTINUITY_REASON_PERIOD_TRANSITION` after a seek to another
|
||||||
media item and so that it is not triggered after a timeline change.
|
media item and so that it is not triggered after a timeline change.
|
||||||
|
* Trigger `onMediaItemTransition` event for all reasons except
|
||||||
|
`MEDIA_ITEM_TRANSITION_REASON_REPEAT`.
|
||||||
|
|
||||||
### 2.13.2 (2021-02-25)
|
### 2.13.2 (2021-02-25)
|
||||||
|
|
||||||
|
@ -440,6 +440,13 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
if (getCurrentWindowIndex() != windowIndex) {
|
if (getCurrentWindowIndex() != windowIndex) {
|
||||||
remoteMediaClient.queueJumpToItem((int) currentTimeline.getPeriod(windowIndex, period).uid,
|
remoteMediaClient.queueJumpToItem((int) currentTimeline.getPeriod(windowIndex, period).uid,
|
||||||
positionMs, null).setResultCallback(seekResultCallback);
|
positionMs, null).setResultCallback(seekResultCallback);
|
||||||
|
// TODO(internal b/182261884): queue `onMediaItemTransition` event when the media item is
|
||||||
|
// repeated.
|
||||||
|
MediaItem mediaItem = currentTimeline.getWindow(windowIndex, window).mediaItem;
|
||||||
|
listeners.queueEvent(
|
||||||
|
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||||
|
listener ->
|
||||||
|
listener.onMediaItemTransition(mediaItem, MEDIA_ITEM_TRANSITION_REASON_SEEK));
|
||||||
} else {
|
} else {
|
||||||
remoteMediaClient.seek(positionMs).setResultCallback(seekResultCallback);
|
remoteMediaClient.seek(positionMs).setResultCallback(seekResultCallback);
|
||||||
}
|
}
|
||||||
@ -637,6 +644,11 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
Player.EVENT_POSITION_DISCONTINUITY,
|
Player.EVENT_POSITION_DISCONTINUITY,
|
||||||
listener -> listener.onPositionDiscontinuity(DISCONTINUITY_REASON_PERIOD_TRANSITION));
|
listener -> listener.onPositionDiscontinuity(DISCONTINUITY_REASON_PERIOD_TRANSITION));
|
||||||
|
listeners.queueEvent(
|
||||||
|
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||||
|
listener ->
|
||||||
|
listener.onMediaItemTransition(
|
||||||
|
getCurrentMediaItem(), MEDIA_ITEM_TRANSITION_REASON_AUTO));
|
||||||
}
|
}
|
||||||
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
if (updateTracksAndSelectionsAndNotifyIfChanged()) {
|
||||||
listeners.queueEvent(
|
listeners.queueEvent(
|
||||||
@ -681,6 +693,8 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||||
private void updateTimelineAndNotifyIfChanged() {
|
private void updateTimelineAndNotifyIfChanged() {
|
||||||
|
Timeline previousTimeline = currentTimeline;
|
||||||
|
int previousWindowIndex = currentWindowIndex;
|
||||||
if (updateTimeline()) {
|
if (updateTimeline()) {
|
||||||
// TODO: Differentiate TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED and
|
// TODO: Differentiate TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED and
|
||||||
// TIMELINE_CHANGE_REASON_SOURCE_UPDATE [see internal: b/65152553].
|
// TIMELINE_CHANGE_REASON_SOURCE_UPDATE [see internal: b/65152553].
|
||||||
@ -692,7 +706,26 @@ public final class CastPlayer extends BasePlayer {
|
|||||||
timeline, /* manifest= */ null, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
|
timeline, /* manifest= */ null, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
|
||||||
listener.onTimelineChanged(timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
|
listener.onTimelineChanged(timeline, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAvailableCommandsAndNotifyIfChanged();
|
updateAvailableCommandsAndNotifyIfChanged();
|
||||||
|
|
||||||
|
boolean mediaItemTransitioned;
|
||||||
|
if (currentTimeline.isEmpty() && previousTimeline.isEmpty()) {
|
||||||
|
mediaItemTransitioned = false;
|
||||||
|
} else if (currentTimeline.isEmpty() != previousTimeline.isEmpty()) {
|
||||||
|
mediaItemTransitioned = true;
|
||||||
|
} else {
|
||||||
|
Object previousWindowUid = previousTimeline.getWindow(previousWindowIndex, window).uid;
|
||||||
|
Object currentWindowUid = currentTimeline.getWindow(currentWindowIndex, window).uid;
|
||||||
|
mediaItemTransitioned = !currentWindowUid.equals(previousWindowUid);
|
||||||
|
}
|
||||||
|
if (mediaItemTransitioned) {
|
||||||
|
listeners.queueEvent(
|
||||||
|
Player.EVENT_MEDIA_ITEM_TRANSITION,
|
||||||
|
listener ->
|
||||||
|
listener.onMediaItemTransition(
|
||||||
|
getCurrentMediaItem(), MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +80,8 @@ public class CastPlayerTest {
|
|||||||
setResultCallbackArgumentCaptor;
|
setResultCallbackArgumentCaptor;
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<RemoteMediaClient.Callback> callbackArgumentCaptor;
|
@Captor private ArgumentCaptor<RemoteMediaClient.Callback> callbackArgumentCaptor;
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<MediaQueueItem[]> queueItemsArgumentCaptor;
|
@Captor private ArgumentCaptor<MediaQueueItem[]> queueItemsArgumentCaptor;
|
||||||
|
@Captor private ArgumentCaptor<MediaItem> mediaItemCaptor;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Before
|
@Before
|
||||||
@ -457,9 +457,107 @@ public class CastPlayerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addMediaItems_notifiesMediaItemTransition() {
|
||||||
|
MediaItem mediaItem = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||||
|
List<MediaItem> mediaItems = ImmutableList.of(mediaItem);
|
||||||
|
int[] mediaQueueItemIds = new int[] {1};
|
||||||
|
|
||||||
|
addMediaItemsAndUpdateTimeline(mediaItems, mediaQueueItemIds);
|
||||||
|
|
||||||
|
verify(mockListener)
|
||||||
|
.onMediaItemTransition(
|
||||||
|
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||||
|
assertThat(mediaItemCaptor.getValue().playbackProperties.tag)
|
||||||
|
.isEqualTo(mediaItem.playbackProperties.tag);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clearMediaItems_notifiesMediaItemTransition() {
|
||||||
|
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||||
|
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
|
||||||
|
|
||||||
|
addMediaItemsAndUpdateTimeline(mediaItems, mediaQueueItemIds);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
|
||||||
|
clearMediaItemsAndUpdateTimeline();
|
||||||
|
verify(mockListener)
|
||||||
|
.onMediaItemTransition(
|
||||||
|
/* mediaItem= */ null, Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
|
||||||
|
verify(mockListener, times(2)).onMediaItemTransition(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void removeCurrentMediaItem_notifiesMediaItemTransition() {
|
||||||
|
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||||
|
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||||
|
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||||
|
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||||
|
|
||||||
|
addMediaItemsAndUpdateTimeline(mediaItems, mediaQueueItemIds);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
|
||||||
|
removeMediaItemsAndUpdateTimeline(
|
||||||
|
mediaItems, mediaQueueItemIds, /* fromIndex= */ 0, /* toIndex= */ 1);
|
||||||
|
verify(mockListener, times(2))
|
||||||
|
.onMediaItemTransition(
|
||||||
|
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED));
|
||||||
|
assertThat(mediaItemCaptor.getValue().playbackProperties.tag)
|
||||||
|
.isEqualTo(mediaItem2.playbackProperties.tag);
|
||||||
|
verify(mockListener, times(2)).onMediaItemTransition(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void removeNonCurrentMediaItem_doesNotNotifyMediaItemTransition() {
|
||||||
|
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||||
|
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
|
||||||
|
|
||||||
|
addMediaItemsAndUpdateTimeline(mediaItems, mediaQueueItemIds);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
|
||||||
|
removeMediaItemsAndUpdateTimeline(
|
||||||
|
mediaItems, mediaQueueItemIds, /* fromIndex= */ 1, /* toIndex= */ 2);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void seekTo_otherWindow_notifiesMediaItemTransition() {
|
||||||
|
when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null)))
|
||||||
|
.thenReturn(mockPendingResult);
|
||||||
|
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||||
|
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||||
|
List<MediaItem> mediaItems = ImmutableList.of(mediaItem1, mediaItem2);
|
||||||
|
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||||
|
|
||||||
|
addMediaItemsAndUpdateTimeline(mediaItems, mediaQueueItemIds);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
|
||||||
|
castPlayer.seekTo(/* windowIndex= */ 1, /* positionMs= */ 0);
|
||||||
|
verify(mockListener)
|
||||||
|
.onMediaItemTransition(
|
||||||
|
mediaItemCaptor.capture(), eq(Player.MEDIA_ITEM_TRANSITION_REASON_SEEK));
|
||||||
|
assertThat(mediaItemCaptor.getValue().playbackProperties.tag)
|
||||||
|
.isEqualTo(mediaItem2.playbackProperties.tag);
|
||||||
|
verify(mockListener, times(2)).onMediaItemTransition(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
|
||||||
|
public void seekTo_sameWindow_doesNotNotifyMediaItemTransition() {
|
||||||
|
when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult);
|
||||||
|
int[] mediaQueueItemIds = new int[] {1, 2};
|
||||||
|
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
|
||||||
|
|
||||||
|
addMediaItemsAndUpdateTimeline(mediaItems, mediaQueueItemIds);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
|
||||||
|
castPlayer.seekTo(/* windowIndex= */ 0, /* positionMs= */ 0);
|
||||||
|
verify(mockListener).onMediaItemTransition(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seekTo_otherWindow_notifiesAvailableCommandsChanged() {
|
public void seekTo_otherWindow_notifiesAvailableCommandsChanged() {
|
||||||
when(mockRemoteMediaClient.play()).thenReturn(mockPendingResult);
|
|
||||||
when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null)))
|
when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null)))
|
||||||
.thenReturn(mockPendingResult);
|
.thenReturn(mockPendingResult);
|
||||||
Player.Commands commandsWithHasNext =
|
Player.Commands commandsWithHasNext =
|
||||||
@ -488,7 +586,6 @@ public class CastPlayerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addMediaItems_whenLastPlaying_notifiesAvailableCommandsChanged() {
|
public void addMediaItems_whenLastPlaying_notifiesAvailableCommandsChanged() {
|
||||||
when(mockRemoteMediaClient.play()).thenReturn(mockPendingResult);
|
|
||||||
Player.Commands commandsWithHasNext =
|
Player.Commands commandsWithHasNext =
|
||||||
new Player.Commands.Builder().add(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM).build();
|
new Player.Commands.Builder().add(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM).build();
|
||||||
int[] mediaQueueItemIds = new int[] {1};
|
int[] mediaQueueItemIds = new int[] {1};
|
||||||
@ -519,7 +616,6 @@ public class CastPlayerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void removeMediaItems_followingCurrent_notifiesAvailableCommandsChanged() {
|
public void removeMediaItems_followingCurrent_notifiesAvailableCommandsChanged() {
|
||||||
when(mockRemoteMediaClient.play()).thenReturn(mockPendingResult);
|
|
||||||
Player.Commands commandsWithHasNext =
|
Player.Commands commandsWithHasNext =
|
||||||
new Player.Commands.Builder().add(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM).build();
|
new Player.Commands.Builder().add(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM).build();
|
||||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||||
@ -550,7 +646,6 @@ public class CastPlayerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setRepeatMode_all_notifiesAvailableCommandsChanged() {
|
public void setRepeatMode_all_notifiesAvailableCommandsChanged() {
|
||||||
when(mockRemoteMediaClient.play()).thenReturn(mockPendingResult);
|
|
||||||
when(mockRemoteMediaClient.queueSetRepeatMode(anyInt(), eq(null)))
|
when(mockRemoteMediaClient.queueSetRepeatMode(anyInt(), eq(null)))
|
||||||
.thenReturn(mockPendingResult);
|
.thenReturn(mockPendingResult);
|
||||||
Player.Commands commandsWithHasNext =
|
Player.Commands commandsWithHasNext =
|
||||||
@ -568,7 +663,6 @@ public class CastPlayerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void setRepeatMode_one_doesNotNotifyAvailableCommandsChanged() {
|
public void setRepeatMode_one_doesNotNotifyAvailableCommandsChanged() {
|
||||||
when(mockRemoteMediaClient.play()).thenReturn(mockPendingResult);
|
|
||||||
when(mockRemoteMediaClient.queueSetRepeatMode(anyInt(), eq(null)))
|
when(mockRemoteMediaClient.queueSetRepeatMode(anyInt(), eq(null)))
|
||||||
.thenReturn(mockPendingResult);
|
.thenReturn(mockPendingResult);
|
||||||
int[] mediaQueueItemIds = new int[] {1};
|
int[] mediaQueueItemIds = new int[] {1};
|
||||||
@ -658,6 +752,11 @@ public class CastPlayerTest {
|
|||||||
updateTimeLine(mediaItems, mediaQueueItemIds);
|
updateTimeLine(mediaItems, mediaQueueItemIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void clearMediaItemsAndUpdateTimeline() {
|
||||||
|
castPlayer.clearMediaItems();
|
||||||
|
updateTimeLine(ImmutableList.of(), new int[0]);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateTimeLine(List<MediaItem> mediaItems, int[] mediaQueueItemIds) {
|
private void updateTimeLine(List<MediaItem> mediaItems, int[] mediaQueueItemIds) {
|
||||||
List<MediaQueueItem> queueItems = new ArrayList<>();
|
List<MediaQueueItem> queueItems = new ArrayList<>();
|
||||||
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
|
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user