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
0dcdbf0a
authored
Mar 05, 2021
by
kimvde
Committed by
Ian Baker
Mar 12, 2021
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add Player onAvailableCommandsChanged callback
PiperOrigin-RevId: 361122259
parent
3de81c6d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
316 additions
and
11 deletions
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
library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java
library/common/src/main/java/com/google/android/exoplayer2/Player.java
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java
extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java
View file @
0dcdbf0a
...
@@ -105,6 +105,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -105,6 +105,7 @@ public final class CastPlayer extends BasePlayer {
private
CastTimeline
currentTimeline
;
private
CastTimeline
currentTimeline
;
private
TrackGroupArray
currentTrackGroups
;
private
TrackGroupArray
currentTrackGroups
;
private
TrackSelectionArray
currentTrackSelection
;
private
TrackSelectionArray
currentTrackSelection
;
private
Commands
availableCommands
;
@Player
.
State
private
int
playbackState
;
@Player
.
State
private
int
playbackState
;
private
int
currentWindowIndex
;
private
int
currentWindowIndex
;
private
long
lastReportedPositionMs
;
private
long
lastReportedPositionMs
;
...
@@ -147,6 +148,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -147,6 +148,7 @@ public final class CastPlayer extends BasePlayer {
currentTimeline
=
CastTimeline
.
EMPTY_CAST_TIMELINE
;
currentTimeline
=
CastTimeline
.
EMPTY_CAST_TIMELINE
;
currentTrackGroups
=
TrackGroupArray
.
EMPTY
;
currentTrackGroups
=
TrackGroupArray
.
EMPTY
;
currentTrackSelection
=
EMPTY_TRACK_SELECTION_ARRAY
;
currentTrackSelection
=
EMPTY_TRACK_SELECTION_ARRAY
;
availableCommands
=
Commands
.
EMPTY
;
pendingSeekWindowIndex
=
C
.
INDEX_UNSET
;
pendingSeekWindowIndex
=
C
.
INDEX_UNSET
;
pendingSeekPositionMs
=
C
.
TIME_UNSET
;
pendingSeekPositionMs
=
C
.
TIME_UNSET
;
...
@@ -370,6 +372,11 @@ public final class CastPlayer extends BasePlayer {
...
@@ -370,6 +372,11 @@ public final class CastPlayer extends BasePlayer {
}
}
@Override
@Override
public
boolean
isCommandAvailable
(
@Command
int
command
)
{
return
availableCommands
.
contains
(
command
);
}
@Override
public
void
prepare
()
{
public
void
prepare
()
{
// Do nothing.
// Do nothing.
}
}
...
@@ -452,6 +459,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -452,6 +459,7 @@ public final class CastPlayer extends BasePlayer {
listeners
.
queueEvent
(
listeners
.
queueEvent
(
Player
.
EVENT_POSITION_DISCONTINUITY
,
Player
.
EVENT_POSITION_DISCONTINUITY
,
listener
->
listener
.
onPositionDiscontinuity
(
DISCONTINUITY_REASON_SEEK
));
listener
->
listener
.
onPositionDiscontinuity
(
DISCONTINUITY_REASON_SEEK
));
updateAvailableCommandsAndNotifyIfChanged
();
}
else
if
(
pendingSeekCount
==
0
)
{
}
else
if
(
pendingSeekCount
==
0
)
{
listeners
.
queueEvent
(
/* eventFlag= */
C
.
INDEX_UNSET
,
EventListener:
:
onSeekProcessed
);
listeners
.
queueEvent
(
/* eventFlag= */
C
.
INDEX_UNSET
,
EventListener:
:
onSeekProcessed
);
}
}
...
@@ -645,6 +653,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -645,6 +653,7 @@ public final class CastPlayer extends BasePlayer {
Player
.
EVENT_TRACKS_CHANGED
,
Player
.
EVENT_TRACKS_CHANGED
,
listener
->
listener
.
onTracksChanged
(
currentTrackGroups
,
currentTrackSelection
));
listener
->
listener
.
onTracksChanged
(
currentTrackGroups
,
currentTrackSelection
));
}
}
updateAvailableCommandsAndNotifyIfChanged
();
listeners
.
flushEvents
();
listeners
.
flushEvents
();
}
}
...
@@ -693,6 +702,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -693,6 +702,7 @@ 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
();
}
}
}
}
...
@@ -762,6 +772,16 @@ public final class CastPlayer extends BasePlayer {
...
@@ -762,6 +772,16 @@ public final class CastPlayer extends BasePlayer {
return
false
;
return
false
;
}
}
private
void
updateAvailableCommandsAndNotifyIfChanged
()
{
Commands
previousAvailableCommands
=
availableCommands
;
availableCommands
=
getAvailableCommands
();
if
(!
availableCommands
.
equals
(
previousAvailableCommands
))
{
listeners
.
queueEvent
(
Player
.
EVENT_AVAILABLE_COMMANDS_CHANGED
,
listener
->
listener
.
onAvailableCommandsChanged
(
availableCommands
));
}
}
@Nullable
@Nullable
private
PendingResult
<
MediaChannelResult
>
setMediaItemsInternal
(
private
PendingResult
<
MediaChannelResult
>
setMediaItemsInternal
(
MediaQueueItem
[]
mediaQueueItems
,
MediaQueueItem
[]
mediaQueueItems
,
...
@@ -819,6 +839,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -819,6 +839,7 @@ public final class CastPlayer extends BasePlayer {
this
.
repeatMode
.
value
=
repeatMode
;
this
.
repeatMode
.
value
=
repeatMode
;
listeners
.
queueEvent
(
listeners
.
queueEvent
(
Player
.
EVENT_REPEAT_MODE_CHANGED
,
listener
->
listener
.
onRepeatModeChanged
(
repeatMode
));
Player
.
EVENT_REPEAT_MODE_CHANGED
,
listener
->
listener
.
onRepeatModeChanged
(
repeatMode
));
updateAvailableCommandsAndNotifyIfChanged
();
}
}
}
}
...
@@ -1003,6 +1024,7 @@ public final class CastPlayer extends BasePlayer {
...
@@ -1003,6 +1024,7 @@ public final class CastPlayer extends BasePlayer {
@Override
@Override
public
void
onQueueStatusUpdated
()
{
public
void
onQueueStatusUpdated
()
{
updateTimelineAndNotifyIfChanged
();
updateTimelineAndNotifyIfChanged
();
listeners
.
flushEvents
();
}
}
@Override
@Override
...
...
extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java
View file @
0dcdbf0a
This diff is collapsed.
Click to expand it.
library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java
View file @
0dcdbf0a
...
@@ -72,14 +72,6 @@ public abstract class BasePlayer implements Player {
...
@@ -72,14 +72,6 @@ public abstract class BasePlayer implements Player {
}
}
@Override
@Override
public
boolean
isCommandAvailable
(
@Command
int
command
)
{
if
(
command
==
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
)
{
return
hasNext
();
}
throw
new
IllegalArgumentException
();
}
@Override
public
final
void
play
()
{
public
final
void
play
()
{
setPlayWhenReady
(
true
);
setPlayWhenReady
(
true
);
}
}
...
@@ -262,4 +254,8 @@ public abstract class BasePlayer implements Player {
...
@@ -262,4 +254,8 @@ public abstract class BasePlayer implements Player {
@RepeatMode
int
repeatMode
=
getRepeatMode
();
@RepeatMode
int
repeatMode
=
getRepeatMode
();
return
repeatMode
==
REPEAT_MODE_ONE
?
REPEAT_MODE_OFF
:
repeatMode
;
return
repeatMode
==
REPEAT_MODE_ONE
?
REPEAT_MODE_OFF
:
repeatMode
;
}
}
protected
Commands
getAvailableCommands
()
{
return
new
Commands
.
Builder
().
addIf
(
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
,
hasNext
()).
build
();
}
}
}
library/common/src/main/java/com/google/android/exoplayer2/Player.java
View file @
0dcdbf0a
...
@@ -15,8 +15,11 @@
...
@@ -15,8 +15,11 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
;
package
com
.
google
.
android
.
exoplayer2
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkState
;
import
android.content.Context
;
import
android.content.Context
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.util.SparseBooleanArray
;
import
android.view.Surface
;
import
android.view.Surface
;
import
android.view.SurfaceHolder
;
import
android.view.SurfaceHolder
;
import
android.view.SurfaceView
;
import
android.view.SurfaceView
;
...
@@ -482,6 +485,17 @@ public interface Player {
...
@@ -482,6 +485,17 @@ public interface Player {
default
void
onLoadingChanged
(
boolean
isLoading
)
{}
default
void
onLoadingChanged
(
boolean
isLoading
)
{}
/**
/**
* Called when the value returned from {@link #isCommandAvailable(int)} changes for at least one
* {@link Command}.
*
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
* other events that happen in the same {@link Looper} message queue iteration.
*
* @param availableCommands The available {@link Commands}.
*/
default
void
onAvailableCommandsChanged
(
Commands
availableCommands
)
{}
/**
* @deprecated Use {@link #onPlaybackStateChanged(int)} and {@link
* @deprecated Use {@link #onPlaybackStateChanged(int)} and {@link
* #onPlayWhenReadyChanged(boolean, int)} instead.
* #onPlayWhenReadyChanged(boolean, int)} instead.
*/
*/
...
@@ -693,6 +707,105 @@ public interface Player {
...
@@ -693,6 +707,105 @@ public interface Player {
}
}
/**
/**
* A set of {@link Command commands}.
*
* <p>Instances are immutable.
*/
final
class
Commands
{
/** A builder for {@link Commands} instances. */
public
static
final
class
Builder
{
private
final
SparseBooleanArray
commandsArray
;
private
boolean
buildCalled
;
/** Creates a builder. */
public
Builder
()
{
commandsArray
=
new
SparseBooleanArray
();
}
/** Creates a builder with the values of the provided {@link Commands}. */
private
Builder
(
Commands
commands
)
{
this
.
commandsArray
=
commands
.
commandsArray
.
clone
();
}
/**
* Adds a {@link Command}.
*
* @param command A {@link Command}.
* @return This builder.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
public
Builder
add
(
@Command
int
command
)
{
checkState
(!
buildCalled
);
commandsArray
.
append
(
command
,
/* value= */
true
);
return
this
;
}
/**
* Adds a {@link Command} if the provided condition is true. Does nothing otherwise.
*
* @param command A {@link Command}.
* @param condition A condition.
* @return This builder.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
public
Builder
addIf
(
@Command
int
command
,
boolean
condition
)
{
checkState
(!
buildCalled
);
if
(
condition
)
{
commandsArray
.
append
(
command
,
/* value= */
true
);
}
return
this
;
}
/** Builds a {@link Commands} instance. */
public
Commands
build
()
{
checkState
(!
buildCalled
);
buildCalled
=
true
;
return
new
Commands
(
commandsArray
);
}
}
/** An empty set of commands. */
public
static
final
Commands
EMPTY
=
new
Commands
.
Builder
().
build
();
// A SparseBooleanArray is used instead of a Set to avoid auto-boxing the Command values.
private
final
SparseBooleanArray
commandsArray
;
private
Commands
(
SparseBooleanArray
commandsArray
)
{
this
.
commandsArray
=
commandsArray
;
}
/** Returns a {@link Commands.Builder} initialized with the values of this instance. */
public
Builder
buildUpon
()
{
return
new
Builder
(
this
);
}
/** Returns whether the set of commands contains the specified {@link Command}. */
public
boolean
contains
(
@Command
int
command
)
{
return
commandsArray
.
get
(
command
);
}
@Override
public
boolean
equals
(
@Nullable
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
Commands
))
{
return
false
;
}
Commands
commands
=
(
Commands
)
obj
;
return
this
.
commandsArray
.
equals
(
commands
.
commandsArray
);
}
@Override
public
int
hashCode
()
{
return
commandsArray
.
hashCode
();
}
}
/**
* Playback state. One of {@link #STATE_IDLE}, {@link #STATE_BUFFERING}, {@link #STATE_READY} or
* Playback state. One of {@link #STATE_IDLE}, {@link #STATE_BUFFERING}, {@link #STATE_READY} or
* {@link #STATE_ENDED}.
* {@link #STATE_ENDED}.
*/
*/
...
@@ -881,7 +994,8 @@ public interface Player {
...
@@ -881,7 +994,8 @@ public interface Player {
EVENT_SHUFFLE_MODE_ENABLED_CHANGED
,
EVENT_SHUFFLE_MODE_ENABLED_CHANGED
,
EVENT_PLAYER_ERROR
,
EVENT_PLAYER_ERROR
,
EVENT_POSITION_DISCONTINUITY
,
EVENT_POSITION_DISCONTINUITY
,
EVENT_PLAYBACK_PARAMETERS_CHANGED
EVENT_PLAYBACK_PARAMETERS_CHANGED
,
EVENT_AVAILABLE_COMMANDS_CHANGED
})
})
@interface
EventFlags
{}
@interface
EventFlags
{}
/** {@link #getCurrentTimeline()} changed. */
/** {@link #getCurrentTimeline()} changed. */
...
@@ -912,6 +1026,8 @@ public interface Player {
...
@@ -912,6 +1026,8 @@ public interface Player {
int
EVENT_POSITION_DISCONTINUITY
=
12
;
int
EVENT_POSITION_DISCONTINUITY
=
12
;
/** {@link #getPlaybackParameters()} changed. */
/** {@link #getPlaybackParameters()} changed. */
int
EVENT_PLAYBACK_PARAMETERS_CHANGED
=
13
;
int
EVENT_PLAYBACK_PARAMETERS_CHANGED
=
13
;
/** {@link #isCommandAvailable(int)} changed for at least one {@link Command}. */
int
EVENT_AVAILABLE_COMMANDS_CHANGED
=
14
;
/**
/**
* Commands that can be executed on a {@code Player}. One of {@link
* Commands that can be executed on a {@code Player}. One of {@link
...
@@ -1105,6 +1221,7 @@ public interface Player {
...
@@ -1105,6 +1221,7 @@ public interface Player {
*
*
* @param command A {@link Command}.
* @param command A {@link Command}.
* @return Whether the {@link Command} is available.
* @return Whether the {@link Command} is available.
* @see EventListener#onAvailableCommandsChanged(Commands)
*/
*/
boolean
isCommandAvailable
(
@Command
int
command
);
boolean
isCommandAvailable
(
@Command
int
command
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java
View file @
0dcdbf0a
...
@@ -91,6 +91,7 @@ import java.util.List;
...
@@ -91,6 +91,7 @@ import java.util.List;
private
SeekParameters
seekParameters
;
private
SeekParameters
seekParameters
;
private
ShuffleOrder
shuffleOrder
;
private
ShuffleOrder
shuffleOrder
;
private
boolean
pauseAtEndOfMediaItems
;
private
boolean
pauseAtEndOfMediaItems
;
private
Commands
availableCommands
;
// Playback information when there is no pending seek/set source operation.
// Playback information when there is no pending seek/set source operation.
private
PlaybackInfo
playbackInfo
;
private
PlaybackInfo
playbackInfo
;
...
@@ -174,6 +175,7 @@ import java.util.List;
...
@@ -174,6 +175,7 @@ import java.util.List;
new
ExoTrackSelection
[
renderers
.
length
],
new
ExoTrackSelection
[
renderers
.
length
],
/* info= */
null
);
/* info= */
null
);
period
=
new
Timeline
.
Period
();
period
=
new
Timeline
.
Period
();
availableCommands
=
Commands
.
EMPTY
;
maskingWindowIndex
=
C
.
INDEX_UNSET
;
maskingWindowIndex
=
C
.
INDEX_UNSET
;
playbackInfoUpdateHandler
=
clock
.
createHandler
(
applicationLooper
,
/* callback= */
null
);
playbackInfoUpdateHandler
=
clock
.
createHandler
(
applicationLooper
,
/* callback= */
null
);
playbackInfoUpdateListener
=
playbackInfoUpdateListener
=
...
@@ -284,6 +286,11 @@ import java.util.List;
...
@@ -284,6 +286,11 @@ import java.util.List;
}
}
@Override
@Override
public
boolean
isCommandAvailable
(
@Command
int
command
)
{
return
availableCommands
.
contains
(
command
);
}
@Override
@State
@State
public
int
getPlaybackState
()
{
public
int
getPlaybackState
()
{
return
playbackInfo
.
playbackState
;
return
playbackInfo
.
playbackState
;
...
@@ -573,8 +580,10 @@ import java.util.List;
...
@@ -573,8 +580,10 @@ import java.util.List;
if
(
this
.
repeatMode
!=
repeatMode
)
{
if
(
this
.
repeatMode
!=
repeatMode
)
{
this
.
repeatMode
=
repeatMode
;
this
.
repeatMode
=
repeatMode
;
internalPlayer
.
setRepeatMode
(
repeatMode
);
internalPlayer
.
setRepeatMode
(
repeatMode
);
listeners
.
send
Event
(
listeners
.
queue
Event
(
Player
.
EVENT_REPEAT_MODE_CHANGED
,
listener
->
listener
.
onRepeatModeChanged
(
repeatMode
));
Player
.
EVENT_REPEAT_MODE_CHANGED
,
listener
->
listener
.
onRepeatModeChanged
(
repeatMode
));
updateAvailableCommands
();
listeners
.
flushEvents
();
}
}
}
}
...
@@ -588,9 +597,11 @@ import java.util.List;
...
@@ -588,9 +597,11 @@ import java.util.List;
if
(
this
.
shuffleModeEnabled
!=
shuffleModeEnabled
)
{
if
(
this
.
shuffleModeEnabled
!=
shuffleModeEnabled
)
{
this
.
shuffleModeEnabled
=
shuffleModeEnabled
;
this
.
shuffleModeEnabled
=
shuffleModeEnabled
;
internalPlayer
.
setShuffleModeEnabled
(
shuffleModeEnabled
);
internalPlayer
.
setShuffleModeEnabled
(
shuffleModeEnabled
);
listeners
.
send
Event
(
listeners
.
queue
Event
(
Player
.
EVENT_SHUFFLE_MODE_ENABLED_CHANGED
,
Player
.
EVENT_SHUFFLE_MODE_ENABLED_CHANGED
,
listener
->
listener
.
onShuffleModeEnabledChanged
(
shuffleModeEnabled
));
listener
->
listener
.
onShuffleModeEnabledChanged
(
shuffleModeEnabled
));
updateAvailableCommands
();
listeners
.
flushEvents
();
}
}
}
}
...
@@ -1110,6 +1121,7 @@ import java.util.List;
...
@@ -1110,6 +1121,7 @@ import java.util.List;
listener
->
listener
->
listener
.
onExperimentalSleepingForOffloadChanged
(
newPlaybackInfo
.
sleepingForOffload
));
listener
.
onExperimentalSleepingForOffloadChanged
(
newPlaybackInfo
.
sleepingForOffload
));
}
}
updateAvailableCommands
();
listeners
.
flushEvents
();
listeners
.
flushEvents
();
}
}
...
@@ -1159,6 +1171,16 @@ import java.util.List;
...
@@ -1159,6 +1171,16 @@ import java.util.List;
return
new
Pair
<>(
/* isTransitioning */
false
,
/* mediaItemTransitionReason */
C
.
INDEX_UNSET
);
return
new
Pair
<>(
/* isTransitioning */
false
,
/* mediaItemTransitionReason */
C
.
INDEX_UNSET
);
}
}
private
void
updateAvailableCommands
()
{
Commands
previousAvailableCommands
=
availableCommands
;
availableCommands
=
getAvailableCommands
();
if
(!
availableCommands
.
equals
(
previousAvailableCommands
))
{
listeners
.
queueEvent
(
Player
.
EVENT_AVAILABLE_COMMANDS_CHANGED
,
listener
->
listener
.
onAvailableCommandsChanged
(
availableCommands
));
}
}
private
void
setMediaSourcesInternal
(
private
void
setMediaSourcesInternal
(
List
<
MediaSource
>
mediaSources
,
List
<
MediaSource
>
mediaSources
,
int
startWindowIndex
,
int
startWindowIndex
,
...
...
library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java
View file @
0dcdbf0a
...
@@ -1258,6 +1258,12 @@ public class SimpleExoPlayer extends BasePlayer
...
@@ -1258,6 +1258,12 @@ public class SimpleExoPlayer extends BasePlayer
}
}
@Override
@Override
public
boolean
isCommandAvailable
(
@Command
int
command
)
{
verifyApplicationThread
();
return
player
.
isCommandAvailable
(
command
);
}
@Override
public
void
prepare
()
{
public
void
prepare
()
{
verifyApplicationThread
();
verifyApplicationThread
();
boolean
playWhenReady
=
getPlayWhenReady
();
boolean
playWhenReady
=
getPlayWhenReady
();
...
...
library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
View file @
0dcdbf0a
...
@@ -8079,6 +8079,143 @@ public final class ExoPlayerTest {
...
@@ -8079,6 +8079,143 @@ public final class ExoPlayerTest {
}
}
@Test
@Test
public
void
seekTo_otherWindow_notifiesAvailableCommandsChanged
()
{
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
2
,
/* positionMs= */
0
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
1
,
/* positionMs= */
0
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
player
.
seekTo
(
/* windowIndex= */
0
,
/* positionMs= */
0
);
verify
(
mockListener
,
times
(
3
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
automaticWindowTransition_notifiesAvailableCommandsChanged
()
throws
Exception
{
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
prepare
();
player
.
play
();
runUntilPlaybackState
(
player
,
Player
.
STATE_ENDED
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
addMediaItems_whenLastPlaying_notifiesAvailableCommandsChanged
()
throws
Exception
{
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSource
(
new
FakeMediaSource
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
player
.
addMediaSource
(
new
FakeMediaSource
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
addMediaSource
(
new
FakeMediaSource
());
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
removeMediaItems_followingCurrent_notifiesAvailableCommandsChanged
()
throws
Exception
{
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSources
(
ImmutableList
.
of
(
new
FakeMediaSource
(),
new
FakeMediaSource
(),
new
FakeMediaSource
()));
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
2
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
player
.
removeMediaItem
(
/* index= */
1
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
verify
(
mockListener
,
times
(
2
)).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
setRepeatMode_all_notifiesAvailableCommandsChanged
()
throws
Exception
{
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSource
(
new
FakeMediaSource
());
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
player
.
setRepeatMode
(
Player
.
REPEAT_MODE_ALL
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
setRepeatMode_one_doesNotNotifyAvailableCommandsChanged
()
throws
Exception
{
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
player
.
addMediaSource
(
new
FakeMediaSource
());
player
.
setRepeatMode
(
Player
.
REPEAT_MODE_ONE
);
verify
(
mockListener
,
never
()).
onAvailableCommandsChanged
(
any
());
}
@Test
public
void
setShuffleModeEnabled_notifiesAvailableCommandsChanged
()
throws
Exception
{
Player
.
Commands
commandsWithHasNext
=
new
Player
.
Commands
.
Builder
().
add
(
Player
.
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
).
build
();
Player
.
EventListener
mockListener
=
mock
(
Player
.
EventListener
.
class
);
ExoPlayer
player
=
new
TestExoPlayerBuilder
(
context
).
build
();
player
.
addListener
(
mockListener
);
MediaSource
mediaSource
=
new
ConcatenatingMediaSource
(
false
,
new
FakeShuffleOrder
(
/* length= */
2
),
new
FakeMediaSource
(),
new
FakeMediaSource
());
player
.
addMediaSource
(
mediaSource
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
commandsWithHasNext
);
player
.
setShuffleModeEnabled
(
true
);
verify
(
mockListener
).
onAvailableCommandsChanged
(
Player
.
Commands
.
EMPTY
);
}
@Test
public
void
public
void
mediaSourceMaybeThrowSourceInfoRefreshError_isNotThrownUntilPlaybackReachedFailingItem
()
mediaSourceMaybeThrowSourceInfoRefreshError_isNotThrownUntilPlaybackReachedFailingItem
()
throws
Exception
{
throws
Exception
{
...
...
testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java
View file @
0dcdbf0a
...
@@ -238,6 +238,11 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
...
@@ -238,6 +238,11 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
}
}
@Override
@Override
public
boolean
isCommandAvailable
(
int
command
)
{
throw
new
UnsupportedOperationException
();
}
@Override
public
void
setPlayWhenReady
(
boolean
playWhenReady
)
{
public
void
setPlayWhenReady
(
boolean
playWhenReady
)
{
throw
new
UnsupportedOperationException
();
throw
new
UnsupportedOperationException
();
}
}
...
...
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