Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
b74bfa1e
authored
Mar 09, 2021
by
kimvde
Committed by
Ian Baker
Mar 12, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Trigger media item transition event in CastPlayer
#minor-release PiperOrigin-RevId: 361803897
parent
ff8db9a4
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
140 additions
and
6 deletions
RELEASENOTES.md
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
RELEASENOTES.md
View file @
b74bfa1e
...
...
@@ -63,6 +63,8 @@
*
Fix
`onPositionDiscontinuity`
event so that it is not triggered with
reason
`DISCONTINUITY_REASON_PERIOD_TRANSITION`
after a seek to another
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)
...
...
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
View file @
b74bfa1e
...
...
@@ -440,6 +440,13 @@ public final class CastPlayer extends BasePlayer {
if
(
getCurrentWindowIndex
()
!=
windowIndex
)
{
remoteMediaClient
.
queueJumpToItem
((
int
)
currentTimeline
.
getPeriod
(
windowIndex
,
period
).
uid
,
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
{
remoteMediaClient
.
seek
(
positionMs
).
setResultCallback
(
seekResultCallback
);
}
...
...
@@ -637,6 +644,11 @@ public final class CastPlayer extends BasePlayer {
listeners
.
queueEvent
(
Player
.
EVENT_POSITION_DISCONTINUITY
,
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
())
{
listeners
.
queueEvent
(
...
...
@@ -681,6 +693,8 @@ public final class CastPlayer extends BasePlayer {
@SuppressWarnings
(
"deprecation"
)
// Calling deprecated listener method.
private
void
updateTimelineAndNotifyIfChanged
()
{
Timeline
previousTimeline
=
currentTimeline
;
int
previousWindowIndex
=
currentWindowIndex
;
if
(
updateTimeline
())
{
// TODO: Differentiate TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED and
// 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
);
listener
.
onTimelineChanged
(
timeline
,
Player
.
TIMELINE_CHANGE_REASON_SOURCE_UPDATE
);
});
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
));
}
}
}
...
...
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
View file @
b74bfa1e
...
...
@@ -80,8 +80,8 @@ public class CastPlayerTest {
setResultCallbackArgumentCaptor
;
@Captor
private
ArgumentCaptor
<
RemoteMediaClient
.
Callback
>
callbackArgumentCaptor
;
@Captor
private
ArgumentCaptor
<
MediaQueueItem
[]>
queueItemsArgumentCaptor
;
@Captor
private
ArgumentCaptor
<
MediaItem
>
mediaItemCaptor
;
@SuppressWarnings
(
"deprecation"
)
@Before
...
...
@@ -458,8 +458,106 @@ 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
public
void
seekTo_otherWindow_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
play
()).
thenReturn
(
mockPendingResult
);
when
(
mockRemoteMediaClient
.
queueJumpToItem
(
anyInt
(),
anyLong
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
...
...
@@ -488,7 +586,6 @@ public class CastPlayerTest {
@Test
public
void
addMediaItems_whenLastPlaying_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
play
()).
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
...
...
@@ -519,7 +616,6 @@ public class CastPlayerTest {
@Test
public
void
removeMediaItems_followingCurrent_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
play
()).
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
MediaItem
mediaItem1
=
createMediaItem
(
/* mediaQueueItemId= */
1
);
...
...
@@ -550,7 +646,6 @@ public class CastPlayerTest {
@Test
public
void
setRepeatMode_all_notifiesAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
play
()).
thenReturn
(
mockPendingResult
);
when
(
mockRemoteMediaClient
.
queueSetRepeatMode
(
anyInt
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
Player
.
Commands
commandsWithHasNext
=
...
...
@@ -568,7 +663,6 @@ public class CastPlayerTest {
@Test
public
void
setRepeatMode_one_doesNotNotifyAvailableCommandsChanged
()
{
when
(
mockRemoteMediaClient
.
play
()).
thenReturn
(
mockPendingResult
);
when
(
mockRemoteMediaClient
.
queueSetRepeatMode
(
anyInt
(),
eq
(
null
)))
.
thenReturn
(
mockPendingResult
);
int
[]
mediaQueueItemIds
=
new
int
[]
{
1
};
...
...
@@ -658,6 +752,11 @@ public class CastPlayerTest {
updateTimeLine
(
mediaItems
,
mediaQueueItemIds
);
}
private
void
clearMediaItemsAndUpdateTimeline
()
{
castPlayer
.
clearMediaItems
();
updateTimeLine
(
ImmutableList
.
of
(),
new
int
[
0
]);
}
private
void
updateTimeLine
(
List
<
MediaItem
>
mediaItems
,
int
[]
mediaQueueItemIds
)
{
List
<
MediaQueueItem
>
queueItems
=
new
ArrayList
<>();
DefaultMediaItemConverter
converter
=
new
DefaultMediaItemConverter
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment