Add artwork support to SimpleExoPlayerView + misc improvements
This commit is contained in:
parent
0c8f3c7270
commit
c4b4e84579
@ -71,36 +71,30 @@ import com.google.android.exoplayer2.util.Util;
|
||||
// Standard genres.
|
||||
private static final String[] STANDARD_GENRES = new String[] {
|
||||
// These are the official ID3v1 genres.
|
||||
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
|
||||
"Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap",
|
||||
"Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
|
||||
"Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient",
|
||||
"Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical",
|
||||
"Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
|
||||
"AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative",
|
||||
"Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
|
||||
"Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
|
||||
"Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap",
|
||||
"Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave",
|
||||
"Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal",
|
||||
"Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll",
|
||||
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz",
|
||||
"Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
|
||||
"Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno",
|
||||
"Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
|
||||
"Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul",
|
||||
"Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic",
|
||||
"Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
|
||||
"Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
|
||||
"Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer",
|
||||
"Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll",
|
||||
"Hard Rock",
|
||||
// These were made up by the authors of Winamp but backported into the ID3 spec.
|
||||
"Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion",
|
||||
"Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
|
||||
"Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock",
|
||||
"Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
|
||||
"Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony",
|
||||
"Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club",
|
||||
"Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul",
|
||||
"Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
|
||||
"Dance Hall",
|
||||
// These were also invented by the Winamp folks but ignored by the ID3 authors.
|
||||
"Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
|
||||
"BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
|
||||
"Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
|
||||
"Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "Jpop",
|
||||
"Synthpop"
|
||||
// These were made up by the authors of Winamp and later added to the ID3 spec.
|
||||
"Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival",
|
||||
"Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
|
||||
"Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
|
||||
"Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
|
||||
"Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad",
|
||||
"Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella",
|
||||
"Euro-House", "Dance Hall",
|
||||
// These were med up by the authors of Winamp but have not been added to the ID3 spec.
|
||||
"Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk",
|
||||
"Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover",
|
||||
"Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime",
|
||||
"Jpop", "Synthpop"
|
||||
};
|
||||
|
||||
private static final String LANGUAGE_UNDEFINED = "und";
|
||||
|
@ -17,16 +17,26 @@ package com.google.android.exoplayer2.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.google.android.exoplayer2.R;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
|
||||
*/
|
||||
public final class AspectRatioFrameLayout extends FrameLayout {
|
||||
|
||||
/**
|
||||
* Resize modes for {@link AspectRatioFrameLayout}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({RESIZE_MODE_FIT, RESIZE_MODE_FIXED_WIDTH, RESIZE_MODE_FIXED_HEIGHT})
|
||||
public @interface ResizeMode {}
|
||||
|
||||
/**
|
||||
* Either the width or height is decreased to obtain the desired aspect ratio.
|
||||
*/
|
||||
@ -85,12 +95,11 @@ public final class AspectRatioFrameLayout extends FrameLayout {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resize mode which can be of value {@link #RESIZE_MODE_FIT},
|
||||
* {@link #RESIZE_MODE_FIXED_HEIGHT} or {@link #RESIZE_MODE_FIXED_WIDTH}.
|
||||
* Sets the resize mode.
|
||||
*
|
||||
* @param resizeMode The resize mode.
|
||||
*/
|
||||
public void setResizeMode(int resizeMode) {
|
||||
public void setResizeMode(@ResizeMode int resizeMode) {
|
||||
if (this.resizeMode != resizeMode) {
|
||||
this.resizeMode = resizeMode;
|
||||
requestLayout();
|
||||
|
@ -120,7 +120,7 @@ public class PlaybackControlView extends FrameLayout {
|
||||
public PlaybackControlView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
int layoutResourceId = R.layout.exo_playback_control_view;
|
||||
int controllerLayoutId = R.layout.exo_playback_control_view;
|
||||
rewindMs = DEFAULT_REWIND_MS;
|
||||
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
|
||||
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
|
||||
@ -132,8 +132,8 @@ public class PlaybackControlView extends FrameLayout {
|
||||
fastForwardMs = a.getInt(R.styleable.PlaybackControlView_fastforward_increment,
|
||||
fastForwardMs);
|
||||
showTimeoutMs = a.getInt(R.styleable.PlaybackControlView_show_timeout, showTimeoutMs);
|
||||
layoutResourceId = a.getResourceId(R.styleable.PlaybackControlView_controller_layout_id,
|
||||
layoutResourceId);
|
||||
controllerLayoutId = a.getResourceId(R.styleable.PlaybackControlView_controller_layout_id,
|
||||
controllerLayoutId);
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
@ -143,7 +143,7 @@ public class PlaybackControlView extends FrameLayout {
|
||||
formatter = new Formatter(formatBuilder, Locale.getDefault());
|
||||
componentListener = new ComponentListener();
|
||||
|
||||
LayoutInflater.from(context).inflate(layoutResourceId, this);
|
||||
LayoutInflater.from(context).inflate(controllerLayoutId, this);
|
||||
time = (TextView) findViewById(R.id.exo_time);
|
||||
timeCurrent = (TextView) findViewById(R.id.exo_time_current);
|
||||
progressBar = (SeekBar) findViewById(R.id.exo_progress);
|
||||
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.ui;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@ -27,16 +28,22 @@ import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.R;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.text.Cue;
|
||||
import com.google.android.exoplayer2.text.TextRenderer;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -45,15 +52,22 @@ import java.util.List;
|
||||
@TargetApi(16)
|
||||
public final class SimpleExoPlayerView extends FrameLayout {
|
||||
|
||||
private final View surfaceView;
|
||||
private static final int SURFACE_TYPE_NONE = 0;
|
||||
private static final int SURFACE_TYPE_SURFACE_VIEW = 1;
|
||||
private static final int SURFACE_TYPE_TEXTURE_VIEW = 2;
|
||||
|
||||
private final ViewGroup videoFrame;
|
||||
private final AspectRatioFrameLayout aspectRatioVideoFrame;
|
||||
private final View shutterView;
|
||||
private final SubtitleView subtitleLayout;
|
||||
private final AspectRatioFrameLayout layout;
|
||||
private final View surfaceView;
|
||||
private final ImageView artworkView;
|
||||
private final SubtitleView subtitleView;
|
||||
private final PlaybackControlView controller;
|
||||
private final ComponentListener componentListener;
|
||||
|
||||
private SimpleExoPlayer player;
|
||||
private boolean useController = true;
|
||||
private boolean useController;
|
||||
private boolean useArtwork;
|
||||
private int controllerShowTimeoutMs;
|
||||
|
||||
public SimpleExoPlayerView(Context context) {
|
||||
@ -67,7 +81,10 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
public SimpleExoPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
boolean useTextureView = false;
|
||||
int playerLayoutId = R.layout.exo_simple_player_view;
|
||||
boolean useArtwork = true;
|
||||
boolean useController = true;
|
||||
int surfaceType = SURFACE_TYPE_SURFACE_VIEW;
|
||||
int resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT;
|
||||
int rewindMs = PlaybackControlView.DEFAULT_REWIND_MS;
|
||||
int fastForwardMs = PlaybackControlView.DEFAULT_FAST_FORWARD_MS;
|
||||
@ -76,11 +93,12 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
|
||||
R.styleable.SimpleExoPlayerView, 0, 0);
|
||||
try {
|
||||
playerLayoutId = a.getResourceId(R.styleable.SimpleExoPlayerView_player_layout_id,
|
||||
playerLayoutId);
|
||||
useArtwork = a.getBoolean(R.styleable.SimpleExoPlayerView_use_artwork, useArtwork);
|
||||
useController = a.getBoolean(R.styleable.SimpleExoPlayerView_use_controller, useController);
|
||||
useTextureView = a.getBoolean(R.styleable.SimpleExoPlayerView_use_texture_view,
|
||||
useTextureView);
|
||||
resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode,
|
||||
AspectRatioFrameLayout.RESIZE_MODE_FIT);
|
||||
surfaceType = a.getInt(R.styleable.SimpleExoPlayerView_surface_type, surfaceType);
|
||||
resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode, resizeMode);
|
||||
rewindMs = a.getInt(R.styleable.SimpleExoPlayerView_rewind_increment, rewindMs);
|
||||
fastForwardMs = a.getInt(R.styleable.SimpleExoPlayerView_fastforward_increment,
|
||||
fastForwardMs);
|
||||
@ -91,35 +109,64 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.exo_simple_player_view, this);
|
||||
LayoutInflater.from(context).inflate(playerLayoutId, this);
|
||||
componentListener = new ComponentListener();
|
||||
layout = (AspectRatioFrameLayout) findViewById(R.id.exo_video_frame);
|
||||
layout.setResizeMode(resizeMode);
|
||||
shutterView = findViewById(R.id.exo_shutter);
|
||||
subtitleLayout = (SubtitleView) findViewById(R.id.exo_subtitles);
|
||||
subtitleLayout.setUserDefaultStyle();
|
||||
subtitleLayout.setUserDefaultTextSize();
|
||||
|
||||
View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder);
|
||||
videoFrame = (ViewGroup) findViewById(R.id.exo_video_frame);
|
||||
if (videoFrame != null) {
|
||||
if (videoFrame instanceof AspectRatioFrameLayout) {
|
||||
aspectRatioVideoFrame = (AspectRatioFrameLayout) videoFrame;
|
||||
setResizeModeRaw(aspectRatioVideoFrame, resizeMode);
|
||||
} else {
|
||||
aspectRatioVideoFrame = null;
|
||||
}
|
||||
shutterView = Assertions.checkNotNull(videoFrame.findViewById(R.id.exo_shutter));
|
||||
if (surfaceType != SURFACE_TYPE_NONE) {
|
||||
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
surfaceView = surfaceType == SURFACE_TYPE_TEXTURE_VIEW ? new TextureView(context)
|
||||
: new SurfaceView(context);
|
||||
surfaceView.setLayoutParams(params);
|
||||
videoFrame.addView(surfaceView, 0);
|
||||
} else {
|
||||
surfaceView = null;
|
||||
}
|
||||
} else {
|
||||
aspectRatioVideoFrame = null;
|
||||
shutterView = null;
|
||||
surfaceView = null;
|
||||
}
|
||||
|
||||
controller = new PlaybackControlView(context, attrs);
|
||||
artworkView = (ImageView) findViewById(R.id.exo_artwork);
|
||||
this.useArtwork = useArtwork && artworkView != null;
|
||||
|
||||
subtitleView = (SubtitleView) findViewById(R.id.exo_subtitles);
|
||||
if (subtitleView != null) {
|
||||
subtitleView.setUserDefaultStyle();
|
||||
subtitleView.setUserDefaultTextSize();
|
||||
}
|
||||
|
||||
PlaybackControlView controller = (PlaybackControlView) findViewById(R.id.exo_controller);
|
||||
if (controller != null) {
|
||||
controller.setRewindIncrementMs(rewindMs);
|
||||
controller.setFastForwardIncrementMs(fastForwardMs);
|
||||
} else {
|
||||
View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder);
|
||||
if (controllerPlaceholder != null) {
|
||||
// Note: rewindMs and fastForwardMs are passed via attrs, so we don't need to make explicit
|
||||
// calls to set them.
|
||||
controller = new PlaybackControlView(context, attrs);
|
||||
controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
|
||||
controller.hide();
|
||||
this.controllerShowTimeoutMs = controllerShowTimeoutMs;
|
||||
|
||||
ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent());
|
||||
int controllerIndex = parent.indexOfChild(controllerPlaceholder);
|
||||
parent.removeView(controllerPlaceholder);
|
||||
parent.addView(controller, controllerIndex);
|
||||
|
||||
View view = useTextureView ? new TextureView(context) : new SurfaceView(context);
|
||||
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
view.setLayoutParams(params);
|
||||
surfaceView = view;
|
||||
layout.addView(surfaceView, 0);
|
||||
}
|
||||
}
|
||||
this.controller = controller;
|
||||
this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
|
||||
this.useController = useController && controller != null;
|
||||
hideController();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,6 +197,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
if (useController) {
|
||||
controller.setPlayer(player);
|
||||
}
|
||||
if (shutterView != null) {
|
||||
shutterView.setVisibility(VISIBLE);
|
||||
}
|
||||
if (player != null) {
|
||||
if (surfaceView instanceof TextureView) {
|
||||
player.setVideoTextureView((TextureView) surfaceView);
|
||||
@ -160,21 +210,41 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
player.addListener(componentListener);
|
||||
player.setTextOutput(componentListener);
|
||||
maybeShowController(false);
|
||||
updateForCurrentTrackSelections();
|
||||
} else {
|
||||
shutterView.setVisibility(VISIBLE);
|
||||
controller.hide();
|
||||
hideController();
|
||||
hideArtwork();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resize mode which can be of value {@link AspectRatioFrameLayout#RESIZE_MODE_FIT},
|
||||
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_HEIGHT} or
|
||||
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_WIDTH}.
|
||||
* Sets the resize mode.
|
||||
*
|
||||
* @param resizeMode The resize mode.
|
||||
*/
|
||||
public void setResizeMode(int resizeMode) {
|
||||
layout.setResizeMode(resizeMode);
|
||||
public void setResizeMode(@ResizeMode int resizeMode) {
|
||||
Assertions.checkState(aspectRatioVideoFrame != null);
|
||||
aspectRatioVideoFrame.setResizeMode(resizeMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether artwork is displayed if present in the media.
|
||||
*/
|
||||
public boolean getUseArtwork() {
|
||||
return useArtwork;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether artwork is displayed if present in the media.
|
||||
*
|
||||
* @param useArtwork Whether artwork is displayed.
|
||||
*/
|
||||
public void setUseArtwork(boolean useArtwork) {
|
||||
Assertions.checkState(!useArtwork || artworkView != null);
|
||||
if (this.useArtwork != useArtwork) {
|
||||
this.useArtwork = useArtwork;
|
||||
updateForCurrentTrackSelections();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,13 +261,14 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
* @param useController Whether playback controls should be enabled.
|
||||
*/
|
||||
public void setUseController(boolean useController) {
|
||||
Assertions.checkState(!useController || controller != null);
|
||||
if (this.useController == useController) {
|
||||
return;
|
||||
}
|
||||
this.useController = useController;
|
||||
if (useController) {
|
||||
controller.setPlayer(player);
|
||||
} else {
|
||||
} else if (controller != null) {
|
||||
controller.hide();
|
||||
controller.setPlayer(null);
|
||||
}
|
||||
@ -223,6 +294,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
* the controller to remain visible indefinitely.
|
||||
*/
|
||||
public void setControllerShowTimeoutMs(int controllerShowTimeoutMs) {
|
||||
Assertions.checkState(controller != null);
|
||||
this.controllerShowTimeoutMs = controllerShowTimeoutMs;
|
||||
}
|
||||
|
||||
@ -232,6 +304,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
* @param listener The listener to be notified about visibility changes.
|
||||
*/
|
||||
public void setControllerVisibilityListener(PlaybackControlView.VisibilityListener listener) {
|
||||
Assertions.checkState(controller != null);
|
||||
controller.setVisibilityListener(listener);
|
||||
}
|
||||
|
||||
@ -241,6 +314,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
* @param rewindMs The rewind increment in milliseconds.
|
||||
*/
|
||||
public void setRewindIncrementMs(int rewindMs) {
|
||||
Assertions.checkState(controller != null);
|
||||
controller.setRewindIncrementMs(rewindMs);
|
||||
}
|
||||
|
||||
@ -250,6 +324,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
* @param fastForwardMs The fast forward increment in milliseconds.
|
||||
*/
|
||||
public void setFastForwardIncrementMs(int fastForwardMs) {
|
||||
Assertions.checkState(controller != null);
|
||||
controller.setFastForwardIncrementMs(fastForwardMs);
|
||||
}
|
||||
|
||||
@ -304,6 +379,67 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateForCurrentTrackSelections() {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
TrackSelectionArray selections = player.getCurrentTrackSelections();
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
|
||||
// Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in
|
||||
// onRenderedFirstFrame().
|
||||
hideArtwork();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Video disabled so the shutter must be closed.
|
||||
if (shutterView != null) {
|
||||
shutterView.setVisibility(VISIBLE);
|
||||
}
|
||||
// Display artwork if enabled and available, else hide it.
|
||||
if (useArtwork) {
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
TrackSelection selection = selections.get(i);
|
||||
if (selection != null) {
|
||||
for (int j = 0; j < selection.length(); j++) {
|
||||
Metadata metadata = selection.getFormat(j).metadata;
|
||||
if (metadata != null) {
|
||||
for (int k = 0; k < metadata.length(); k++) {
|
||||
Metadata.Entry metadataEntry = metadata.get(k);
|
||||
if (metadataEntry instanceof ApicFrame) {
|
||||
byte[] data = ((ApicFrame) metadataEntry).pictureData;;
|
||||
artworkView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
|
||||
artworkView.setVisibility(VISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Artwork disabled or unavailable.
|
||||
hideArtwork();
|
||||
}
|
||||
|
||||
private void hideArtwork() {
|
||||
if (artworkView != null) {
|
||||
artworkView.setImageResource(android.R.color.transparent); // Clears any bitmap reference.
|
||||
artworkView.setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideController() {
|
||||
if (controller != null) {
|
||||
controller.hide();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ResourceType")
|
||||
private static void setResizeModeRaw(AspectRatioFrameLayout aspectRatioFrame, int resizeMode) {
|
||||
aspectRatioFrame.setResizeMode(resizeMode);
|
||||
}
|
||||
|
||||
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
|
||||
TextRenderer.Output, ExoPlayer.EventListener {
|
||||
|
||||
@ -311,7 +447,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
|
||||
@Override
|
||||
public void onCues(List<Cue> cues) {
|
||||
subtitleLayout.onCues(cues);
|
||||
if (subtitleView != null) {
|
||||
subtitleView.onCues(cues);
|
||||
}
|
||||
}
|
||||
|
||||
// SimpleExoPlayer.VideoListener implementation
|
||||
@ -319,23 +457,22 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||
@Override
|
||||
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
|
||||
float pixelWidthHeightRatio) {
|
||||
layout.setAspectRatio(height == 0 ? 1 : (width * pixelWidthHeightRatio) / height);
|
||||
if (aspectRatioVideoFrame != null) {
|
||||
float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
|
||||
aspectRatioVideoFrame.setAspectRatio(aspectRatio);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderedFirstFrame() {
|
||||
shutterView.setVisibility(GONE);
|
||||
if (shutterView != null) {
|
||||
shutterView.setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) {
|
||||
for (int i = 0; i < selections.length; i++) {
|
||||
if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// No enabled video renderers. Close the shutter.
|
||||
shutterView.setVisibility(VISIBLE);
|
||||
updateForCurrentTrackSelections();
|
||||
}
|
||||
|
||||
// ExoPlayer.EventListener implementation
|
||||
|
@ -28,22 +28,22 @@
|
||||
android:paddingTop="4dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton android:id="@+id/exo_prev"
|
||||
<ImageButton android:id="@id/exo_prev"
|
||||
style="@style/ExoMediaButton.Previous"/>
|
||||
|
||||
<ImageButton android:id="@+id/exo_rew"
|
||||
<ImageButton android:id="@id/exo_rew"
|
||||
style="@style/ExoMediaButton.Rewind"/>
|
||||
|
||||
<ImageButton android:id="@+id/exo_play"
|
||||
<ImageButton android:id="@id/exo_play"
|
||||
style="@style/ExoMediaButton.Play"/>
|
||||
|
||||
<ImageButton android:id="@+id/exo_pause"
|
||||
<ImageButton android:id="@id/exo_pause"
|
||||
style="@style/ExoMediaButton.Pause"/>
|
||||
|
||||
<ImageButton android:id="@+id/exo_ffwd"
|
||||
<ImageButton android:id="@id/exo_ffwd"
|
||||
style="@style/ExoMediaButton.FastForward"/>
|
||||
|
||||
<ImageButton android:id="@+id/exo_next"
|
||||
<ImageButton android:id="@id/exo_next"
|
||||
style="@style/ExoMediaButton.Next"/>
|
||||
|
||||
</LinearLayout>
|
||||
@ -53,7 +53,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView android:id="@+id/exo_time_current"
|
||||
<TextView android:id="@id/exo_time_current"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
@ -64,13 +64,13 @@
|
||||
android:paddingEnd="4dp"
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
<SeekBar android:id="@+id/exo_progress"
|
||||
<SeekBar android:id="@id/exo_progress"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="32dp"
|
||||
style="?android:attr/progressBarStyleHorizontal"/>
|
||||
|
||||
<TextView android:id="@+id/exo_time"
|
||||
<TextView android:id="@id/exo_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
|
@ -17,23 +17,28 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout android:id="@+id/exo_video_frame"
|
||||
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout android:id="@id/exo_video_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center">
|
||||
|
||||
<View android:id="@+id/exo_shutter"
|
||||
<View android:id="@id/exo_shutter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"/>
|
||||
|
||||
<com.google.android.exoplayer2.ui.SubtitleView android:id="@+id/exo_subtitles"
|
||||
<com.google.android.exoplayer2.ui.SubtitleView android:id="@id/exo_subtitles"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
|
||||
|
||||
<View android:id="@+id/exo_controller_placeholder"
|
||||
<ImageView android:id="@id/exo_artwork"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<View android:id="@id/exo_controller_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
|
@ -14,24 +14,33 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<!-- Must be kept in sync with AspectRatioFrameLayout -->
|
||||
<attr name="resize_mode" format="enum">
|
||||
<enum name="fit" value="0"/>
|
||||
<enum name="fixed_width" value="1"/>
|
||||
<enum name="fixed_height" value="2"/>
|
||||
</attr>
|
||||
<!-- Must be kept in sync with SimpleExoPlayerView -->
|
||||
<attr name="surface_type" format="enum">
|
||||
<enum name="none" value="0"/>
|
||||
<enum name="surface_view" value="1"/>
|
||||
<enum name="texture_view" value="2"/>
|
||||
</attr>
|
||||
<attr name="show_timeout" format="integer"/>
|
||||
<attr name="rewind_increment" format="integer"/>
|
||||
<attr name="fastforward_increment" format="integer"/>
|
||||
<attr name="player_layout_id" format="reference"/>
|
||||
<attr name="controller_layout_id" format="reference"/>
|
||||
|
||||
<declare-styleable name="SimpleExoPlayerView">
|
||||
<attr name="use_artwork" format="boolean"/>
|
||||
<attr name="use_controller" format="boolean"/>
|
||||
<attr name="use_texture_view" format="boolean"/>
|
||||
<attr name="surface_type"/>
|
||||
<attr name="show_timeout"/>
|
||||
<attr name="rewind_increment"/>
|
||||
<attr name="fastforward_increment"/>
|
||||
<attr name="resize_mode"/>
|
||||
<attr name="player_layout_id"/>
|
||||
<attr name="controller_layout_id"/>
|
||||
</declare-styleable>
|
||||
|
||||
|
@ -14,6 +14,12 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<item name="exo_video_frame" type="id"/>
|
||||
<item name="exo_shutter" type="id"/>
|
||||
<item name="exo_subtitles" type="id"/>
|
||||
<item name="exo_artwork" type="id"/>
|
||||
<item name="exo_controller_placeholder" type="id"/>
|
||||
<item name="exo_controller" type="id"/>
|
||||
<item name="exo_play" type="id"/>
|
||||
<item name="exo_pause" type="id"/>
|
||||
<item name="exo_rew" type="id"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user