Merge branch 'master' of https://github.com/react-native-video/react-native-video into feature/add_api_to_retrieve_decoder_capabilities
This commit is contained in:
22
android/src/main/java/com/brentvatne/ReactBridgeUtils.java
Normal file
22
android/src/main/java/com/brentvatne/ReactBridgeUtils.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.brentvatne;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/*
|
||||
* This file define static helpers to parse in an easier way input props
|
||||
*/
|
||||
public class ReactBridgeUtils {
|
||||
/*
|
||||
retrieve key from map as int. fallback is returned if not available
|
||||
*/
|
||||
static public int safeGetInt(ReadableMap map, String key, int fallback) {
|
||||
return map != null && map.hasKey(key) && !map.isNull(key) ? map.getInt(key) : fallback;
|
||||
}
|
||||
|
||||
/*
|
||||
retrieve key from map as double. fallback is returned if not available
|
||||
*/
|
||||
static public double safeGetDouble(ReadableMap map, String key, double fallback) {
|
||||
return map != null && map.hasKey(key) && !map.isNull(key) ? map.getDouble(key) : fallback;
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ import android.content.Context;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.TextureView;
|
||||
@@ -100,6 +101,16 @@ public final class ExoPlayerView extends FrameLayout {
|
||||
player.setVideoSurfaceView((SurfaceView) surfaceView);
|
||||
}
|
||||
}
|
||||
public void setSubtitleStyle(SubtitleStyle style) {
|
||||
// ensure we reset subtile style before reapplying it
|
||||
subtitleLayout.setUserDefaultStyle();
|
||||
subtitleLayout.setUserDefaultTextSize();
|
||||
|
||||
if (style.getFontSize() > 0) {
|
||||
subtitleLayout.setFixedTextSize(TypedValue.COMPLEX_UNIT_SP, style.getFontSize());
|
||||
}
|
||||
subtitleLayout.setPadding(style.getPaddingLeft(), style.getPaddingTop(), style.getPaddingRight(), style.getPaddingBottom());
|
||||
}
|
||||
|
||||
private void updateSurfaceView() {
|
||||
View view;
|
||||
|
@@ -205,18 +205,29 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
private final AudioManager audioManager;
|
||||
private final AudioBecomingNoisyReceiver audioBecomingNoisyReceiver;
|
||||
|
||||
// store last progress event values to avoid sending unnecessary messages
|
||||
private long lastPos = -1;
|
||||
private long lastBufferDuration = -1;
|
||||
private long lastDuration = -1;
|
||||
|
||||
private final Handler progressHandler = new Handler(Looper.getMainLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case SHOW_PROGRESS:
|
||||
if (player != null
|
||||
&& player.getPlaybackState() == Player.STATE_READY
|
||||
&& player.getPlayWhenReady()
|
||||
) {
|
||||
if (player != null) {
|
||||
long pos = player.getCurrentPosition();
|
||||
long bufferedDuration = player.getBufferedPercentage() * player.getDuration() / 100;
|
||||
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
|
||||
long duration = player.getDuration();
|
||||
|
||||
if (lastPos != pos
|
||||
|| lastBufferDuration != bufferedDuration
|
||||
|| lastDuration != duration) {
|
||||
lastPos = pos;
|
||||
lastBufferDuration = bufferedDuration;
|
||||
lastDuration = duration;
|
||||
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
|
||||
}
|
||||
msg = obtainMessage(SHOW_PROGRESS);
|
||||
sendMessageDelayed(msg, Math.round(mProgressUpdateInterval));
|
||||
}
|
||||
@@ -392,6 +403,15 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
eventListener = new Player.Listener() {
|
||||
@Override
|
||||
public void onPlaybackStateChanged(int playbackState) {
|
||||
View playButton = playerControlView.findViewById(R.id.exo_play);
|
||||
View pauseButton = playerControlView.findViewById(R.id.exo_pause);
|
||||
if (playButton != null && playButton.getVisibility() == GONE) {
|
||||
playButton.setVisibility(INVISIBLE);
|
||||
}
|
||||
if (pauseButton != null && pauseButton.getVisibility() == GONE) {
|
||||
pauseButton.setVisibility(INVISIBLE);
|
||||
}
|
||||
|
||||
reLayout(playPauseControlContainer);
|
||||
//Remove this eventListener once its executed. since UI will work fine once after the reLayout is done
|
||||
player.removeListener(eventListener);
|
||||
@@ -804,7 +824,10 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
player.setPlayWhenReady(true);
|
||||
}
|
||||
} else {
|
||||
player.setPlayWhenReady(false);
|
||||
// ensure playback is not ENDED, else it will trigger another ended event
|
||||
if (player.getPlaybackState() != Player.STATE_ENDED) {
|
||||
player.setPlayWhenReady(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -945,6 +968,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
int playbackState = player.getPlaybackState();
|
||||
boolean playWhenReady = player.getPlayWhenReady();
|
||||
String text = "onStateChanged: playWhenReady=" + playWhenReady + ", playbackState=";
|
||||
eventEmitter.playbackRateChange(playWhenReady && playbackState == ExoPlayer.STATE_READY ? 1.0f : 0.0f);
|
||||
switch (playbackState) {
|
||||
case Player.STATE_IDLE:
|
||||
text += "idle";
|
||||
@@ -1005,9 +1029,15 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
private void videoLoaded() {
|
||||
if (loadVideoStarted) {
|
||||
loadVideoStarted = false;
|
||||
setSelectedAudioTrack(audioTrackType, audioTrackValue);
|
||||
setSelectedVideoTrack(videoTrackType, videoTrackValue);
|
||||
setSelectedTextTrack(textTrackType, textTrackValue);
|
||||
if (audioTrackType != null) {
|
||||
setSelectedAudioTrack(audioTrackType, audioTrackValue);
|
||||
}
|
||||
if (videoTrackType != null) {
|
||||
setSelectedVideoTrack(videoTrackType, videoTrackValue);
|
||||
}
|
||||
if (textTrackType != null) {
|
||||
setSelectedTextTrack(textTrackType, textTrackValue);
|
||||
}
|
||||
Format videoFormat = player.getVideoFormat();
|
||||
int width = videoFormat != null ? videoFormat.width : 0;
|
||||
int height = videoFormat != null ? videoFormat.height : 0;
|
||||
@@ -1826,4 +1856,8 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSubtitleStyle(SubtitleStyle style) {
|
||||
exoPlayerView.setSubtitleStyle(style);
|
||||
}
|
||||
}
|
||||
|
@@ -79,6 +79,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_HIDE_SHUTTER_VIEW = "hideShutterView";
|
||||
private static final String PROP_CONTROLS = "controls";
|
||||
|
||||
private static final String PROP_SUBTITLE_STYLE = "subtitleStyle";
|
||||
|
||||
private ReactExoplayerConfig config;
|
||||
|
||||
public ReactExoplayerViewManager(ReactExoplayerConfig config) {
|
||||
@@ -347,6 +349,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
videoView.setControls(controls);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_SUBTITLE_STYLE)
|
||||
public void setSubtitleStyle(final ReactExoplayerView videoView, @Nullable final ReadableMap src) {
|
||||
videoView.setSubtitleStyle(SubtitleStyle.parse(src));
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_BUFFER_CONFIG)
|
||||
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
||||
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||
|
@@ -0,0 +1,38 @@
|
||||
package com.brentvatne.exoplayer;
|
||||
import com.brentvatne.ReactBridgeUtils;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/**
|
||||
* Helper file to parse SubtitleStyle prop and build a dedicated class
|
||||
*/
|
||||
public class SubtitleStyle {
|
||||
private static final String PROP_FONT_SIZE_TRACK = "fontSize";
|
||||
private static final String PROP_PADDING_BOTTOM = "paddingBottom";
|
||||
private static final String PROP_PADDING_TOP = "paddingTop";
|
||||
private static final String PROP_PADDING_LEFT = "paddingLeft";
|
||||
private static final String PROP_PADDING_RIGHT = "paddingRight";
|
||||
|
||||
private int fontSize = -1;
|
||||
private int paddingLeft = 0;
|
||||
private int paddingRight = 0;
|
||||
private int paddingTop = 0;
|
||||
private int paddingBottom = 0;
|
||||
|
||||
private SubtitleStyle() {}
|
||||
|
||||
int getFontSize() {return fontSize;}
|
||||
int getPaddingBottom() {return paddingBottom;}
|
||||
int getPaddingTop() {return paddingTop;}
|
||||
int getPaddingLeft() {return paddingLeft;}
|
||||
int getPaddingRight() {return paddingRight;}
|
||||
|
||||
public static SubtitleStyle parse(ReadableMap src) {
|
||||
SubtitleStyle subtitleStyle = new SubtitleStyle();
|
||||
subtitleStyle.fontSize = ReactBridgeUtils.safeGetInt(src, PROP_FONT_SIZE_TRACK, -1);
|
||||
subtitleStyle.paddingBottom = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_BOTTOM, 0);
|
||||
subtitleStyle.paddingTop = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_TOP, 0);
|
||||
subtitleStyle.paddingLeft = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_LEFT, 0);
|
||||
subtitleStyle.paddingRight = ReactBridgeUtils.safeGetInt(src, PROP_PADDING_RIGHT, 0);
|
||||
return subtitleStyle;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user