Add some javadocs; move preparing player uis to PlayerUiList
This commit is contained in:
parent
6559416bd8
commit
1b39b5376f
3 changed files with 138 additions and 22 deletions
|
@ -447,7 +447,7 @@ public final class Player implements PlaybackListener, Listener {
|
||||||
private void initUIsForCurrentPlayerType() {
|
private void initUIsForCurrentPlayerType() {
|
||||||
//noinspection SimplifyOptionalCallChains
|
//noinspection SimplifyOptionalCallChains
|
||||||
if (!UIs.get(NotificationPlayerUi.class).isPresent()) {
|
if (!UIs.get(NotificationPlayerUi.class).isPresent()) {
|
||||||
UIs.add(new NotificationPlayerUi(this));
|
UIs.addAndPrepare(new NotificationPlayerUi(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((UIs.get(MainPlayerUi.class).isPresent() && playerType == PlayerType.MAIN)
|
if ((UIs.get(MainPlayerUi.class).isPresent() && playerType == PlayerType.MAIN)
|
||||||
|
@ -469,24 +469,15 @@ public final class Player implements PlaybackListener, Listener {
|
||||||
switch (playerType) {
|
switch (playerType) {
|
||||||
case MAIN:
|
case MAIN:
|
||||||
UIs.destroyAll(PopupPlayerUi.class);
|
UIs.destroyAll(PopupPlayerUi.class);
|
||||||
UIs.add(new MainPlayerUi(this, binding));
|
UIs.addAndPrepare(new MainPlayerUi(this, binding));
|
||||||
|
break;
|
||||||
|
case POPUP:
|
||||||
|
UIs.destroyAll(MainPlayerUi.class);
|
||||||
|
UIs.addAndPrepare(new PopupPlayerUi(this, binding));
|
||||||
break;
|
break;
|
||||||
case AUDIO:
|
case AUDIO:
|
||||||
UIs.destroyAll(VideoPlayerUi.class);
|
UIs.destroyAll(VideoPlayerUi.class);
|
||||||
break;
|
break;
|
||||||
case POPUP:
|
|
||||||
UIs.destroyAll(MainPlayerUi.class);
|
|
||||||
UIs.add(new PopupPlayerUi(this, binding));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fragmentListener != null) {
|
|
||||||
// make sure UIs know whether a service is connected or not
|
|
||||||
UIs.call(PlayerUi::onFragmentListenerSet);
|
|
||||||
}
|
|
||||||
if (!exoPlayerIsNull()) {
|
|
||||||
UIs.call(PlayerUi::initPlayer);
|
|
||||||
UIs.call(PlayerUi::initPlayback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,9 +1959,9 @@ public final class Player implements PlaybackListener, Listener {
|
||||||
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Video size, resize, orientation, fullscreen
|
// Video size
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
//region Video size, resize, orientation, fullscreen
|
//region Video size
|
||||||
@Override // exoplayer listener
|
@Override // exoplayer listener
|
||||||
public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
|
public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
|
|
@ -18,50 +18,105 @@ import org.schabi.newpipe.player.Player;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A player UI is a component that can seamlessly connect and disconnect from the {@link Player} and
|
||||||
|
* provide a user interface of some sort. Try to extend this class instead of adding more code to
|
||||||
|
* {@link Player}!
|
||||||
|
*/
|
||||||
public abstract class PlayerUi {
|
public abstract class PlayerUi {
|
||||||
|
|
||||||
@NonNull protected Context context;
|
@NonNull protected final Context context;
|
||||||
@NonNull protected Player player;
|
@NonNull protected final Player player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param player the player instance that will be usable throughout the lifetime of this UI
|
||||||
|
*/
|
||||||
public PlayerUi(@NonNull final Player player) {
|
public PlayerUi(@NonNull final Player player) {
|
||||||
this.context = player.getContext();
|
this.context = player.getContext();
|
||||||
this.player = player;
|
this.player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the player instance this UI was constructed with
|
||||||
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Player getPlayer() {
|
public Player getPlayer() {
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after the player received an intent and processed it
|
||||||
|
*/
|
||||||
public void setupAfterIntent() {
|
public void setupAfterIntent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called right after the exoplayer instance is constructed, or right after this UI is
|
||||||
|
* constructed if the exoplayer is already available then. Note that the exoplayer instance
|
||||||
|
* could be built and destroyed multiple times during the lifetime of the player, so this method
|
||||||
|
* might be called multiple times.
|
||||||
|
*/
|
||||||
public void initPlayer() {
|
public void initPlayer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when playback in the exoplayer is about to start, or right after this UI is
|
||||||
|
* constructed if the exoplayer and the play queue are already available then. The play queue
|
||||||
|
* will therefore always be not null.
|
||||||
|
*/
|
||||||
public void initPlayback() {
|
public void initPlayback() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the exoplayer instance is about to be destroyed. Note that the exoplayer instance
|
||||||
|
* could be built and destroyed multiple times during the lifetime of the player, so this method
|
||||||
|
* might be called multiple times. Be sure to unset any video surface view or play queue
|
||||||
|
* listeners! This will also be called when this UI is being discarded, just before {@link
|
||||||
|
* #destroy()}.
|
||||||
|
*/
|
||||||
public void destroyPlayer() {
|
public void destroyPlayer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this UI is being discarded, either because the player is switching to a different
|
||||||
|
* UI or because the player is shutting down completely
|
||||||
|
*/
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the player is smooth-stopping, that is, transitioning smoothly to a new play
|
||||||
|
* queue after the user tapped on a new video stream while a stream was playing in the video
|
||||||
|
* detail fragment
|
||||||
|
*/
|
||||||
public void smoothStopForImmediateReusing() {
|
public void smoothStopForImmediateReusing() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the video detail fragment listener is connected with the player, or right after
|
||||||
|
* this UI is constructed if the listener is already connected then
|
||||||
|
*/
|
||||||
public void onFragmentListenerSet() {
|
public void onFragmentListenerSet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If you want to register new broadcast actions to receive here, add them to
|
* Broadcasts that the player receives will also be notified to UIs here. If you want to
|
||||||
* {@link Player#setupBroadcastReceiver()}.
|
* register new broadcast actions to receive here, add them to {@link
|
||||||
|
* Player#setupBroadcastReceiver()}.
|
||||||
*/
|
*/
|
||||||
public void onBroadcastReceived(final Intent intent) {
|
public void onBroadcastReceived(final Intent intent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when stream progress (i.e. the current time in the seekbar) or stream duration change.
|
||||||
|
* Will surely be called every {@link Player#PROGRESS_LOOP_INTERVAL_MILLIS} while a stream is
|
||||||
|
* playing.
|
||||||
|
* @param currentProgress the current progress in milliseconds
|
||||||
|
* @param duration the duration of the stream being played
|
||||||
|
* @param bufferPercent the percentage of stream already buffered, see {@link
|
||||||
|
* com.google.android.exoplayer2.BasePlayer#getBufferedPercentage()}
|
||||||
|
*/
|
||||||
public void onUpdateProgress(final int currentProgress,
|
public void onUpdateProgress(final int currentProgress,
|
||||||
final int duration,
|
final int duration,
|
||||||
final int bufferPercent) {
|
final int bufferPercent) {
|
||||||
|
@ -97,27 +152,56 @@ public abstract class PlayerUi {
|
||||||
public void onMuteUnmuteChanged(final boolean isMuted) {
|
public void onMuteUnmuteChanged(final boolean isMuted) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see com.google.android.exoplayer2.Player.Listener#onTracksChanged(Tracks)
|
||||||
|
*/
|
||||||
public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
|
public void onTextTracksChanged(@NonNull final Tracks currentTracks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see com.google.android.exoplayer2.Player.Listener#onPlaybackParametersChanged
|
||||||
|
*/
|
||||||
public void onPlaybackParametersChanged(@NonNull final PlaybackParameters playbackParameters) {
|
public void onPlaybackParametersChanged(@NonNull final PlaybackParameters playbackParameters) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see com.google.android.exoplayer2.Player.Listener#onRenderedFirstFrame
|
||||||
|
*/
|
||||||
public void onRenderedFirstFrame() {
|
public void onRenderedFirstFrame() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see com.google.android.exoplayer2.text.TextOutput#onCues
|
||||||
|
*/
|
||||||
public void onCues(@NonNull final List<Cue> cues) {
|
public void onCues(@NonNull final List<Cue> cues) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the stream being played changes
|
||||||
|
* @param info the {@link StreamInfo} metadata object, along with data about the selected and
|
||||||
|
* available video streams (to be used to build the resolution menus, for example)
|
||||||
|
*/
|
||||||
public void onMetadataChanged(@NonNull final StreamInfo info) {
|
public void onMetadataChanged(@NonNull final StreamInfo info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the thumbnail for the current metadata was loaded
|
||||||
|
* @param bitmap the thumbnail to process, or null if there is no thumbnail or there was an
|
||||||
|
* error when loading the thumbnail
|
||||||
|
*/
|
||||||
public void onThumbnailLoaded(@Nullable final Bitmap bitmap) {
|
public void onThumbnailLoaded(@Nullable final Bitmap bitmap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the play queue was edited: a stream was appended, moved or removed.
|
||||||
|
*/
|
||||||
public void onPlayQueueEdited() {
|
public void onPlayQueueEdited() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param videoSize the new video size, useful to set the surface aspect ratio
|
||||||
|
* @see com.google.android.exoplayer2.Player.Listener#onVideoSizeChanged
|
||||||
|
*/
|
||||||
public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
|
public void onVideoSizeChanged(@NonNull final VideoSize videoSize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,39 @@ import java.util.function.Consumer;
|
||||||
public final class PlayerUiList {
|
public final class PlayerUiList {
|
||||||
final List<PlayerUi> playerUis = new ArrayList<>();
|
final List<PlayerUi> playerUis = new ArrayList<>();
|
||||||
|
|
||||||
public void add(final PlayerUi playerUi) {
|
/**
|
||||||
|
* Adds the provided player ui to the list and calls on it the initialization functions that
|
||||||
|
* apply based on the current player state. The preparation step needs to be done since when UIs
|
||||||
|
* are removed and re-added, the player will not call e.g. initPlayer again since the exoplayer
|
||||||
|
* is already initialized, but we need to notify the newly built UI that the player is ready
|
||||||
|
* nonetheless.
|
||||||
|
* @param playerUi the player ui to prepare and add to the list; its {@link
|
||||||
|
* PlayerUi#getPlayer()} will be used to query information about the player
|
||||||
|
* state
|
||||||
|
*/
|
||||||
|
public void addAndPrepare(final PlayerUi playerUi) {
|
||||||
|
if (playerUi.getPlayer().getFragmentListener().isPresent()) {
|
||||||
|
// make sure UIs know whether a service is connected or not
|
||||||
|
playerUi.onFragmentListenerSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!playerUi.getPlayer().exoPlayerIsNull()) {
|
||||||
|
playerUi.initPlayer();
|
||||||
|
if (playerUi.getPlayer().getPlayQueue() != null) {
|
||||||
|
playerUi.initPlayback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
playerUis.add(playerUi);
|
playerUis.add(playerUi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys all matching player UIs and removes them from the list
|
||||||
|
* @param playerUiType the class of the player UI to destroy; the {@link
|
||||||
|
* Class#isInstance(Object)} method will be used, so even subclasses will be
|
||||||
|
* destroyed and removed
|
||||||
|
* @param <T> the class type parameter
|
||||||
|
*/
|
||||||
public <T> void destroyAll(final Class<T> playerUiType) {
|
public <T> void destroyAll(final Class<T> playerUiType) {
|
||||||
playerUis.stream()
|
playerUis.stream()
|
||||||
.filter(playerUiType::isInstance)
|
.filter(playerUiType::isInstance)
|
||||||
|
@ -22,6 +51,14 @@ public final class PlayerUiList {
|
||||||
playerUis.removeIf(playerUiType::isInstance);
|
playerUis.removeIf(playerUiType::isInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param playerUiType the class of the player UI to return; the {@link
|
||||||
|
* Class#isInstance(Object)} method will be used, so even subclasses could
|
||||||
|
* be returned
|
||||||
|
* @param <T> the class type parameter
|
||||||
|
* @return the first player UI of the required type found in the list, or an empty {@link
|
||||||
|
* Optional} otherwise
|
||||||
|
*/
|
||||||
public <T> Optional<T> get(final Class<T> playerUiType) {
|
public <T> Optional<T> get(final Class<T> playerUiType) {
|
||||||
return playerUis.stream()
|
return playerUis.stream()
|
||||||
.filter(playerUiType::isInstance)
|
.filter(playerUiType::isInstance)
|
||||||
|
@ -29,6 +66,10 @@ public final class PlayerUiList {
|
||||||
.findFirst();
|
.findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the provided consumer on all player UIs in the list
|
||||||
|
* @param consumer the consumer to call with player UIs
|
||||||
|
*/
|
||||||
public void call(final Consumer<PlayerUi> consumer) {
|
public void call(final Consumer<PlayerUi> consumer) {
|
||||||
//noinspection SimplifyStreamApiCallChains
|
//noinspection SimplifyStreamApiCallChains
|
||||||
playerUis.stream().forEach(consumer);
|
playerUis.stream().forEach(consumer);
|
||||||
|
|
Loading…
Reference in a new issue