refactor(android): migrate VideoEventEmitter to Kotlin (#3962)
* refactor(android): migrate VideoEventEmitter to Kotlin * feat(android): apply rewritten EventEmitter's functions * refactor(android): remove duplicated code * fix(android): fix lint error * fix(android): fix event name value * refactor(android): rename of event constants for Fabric - https://github.com/facebook/react-native/blob/v0.74.3/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java#L136-L138
This commit is contained in:
parent
7def3ac387
commit
3c9b1b571a
@ -1,489 +0,0 @@
|
|||||||
package com.brentvatne.common.react;
|
|
||||||
|
|
||||||
import androidx.annotation.StringDef;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.brentvatne.common.api.TimedMetadata;
|
|
||||||
import com.brentvatne.common.api.Track;
|
|
||||||
import com.brentvatne.common.api.VideoTrack;
|
|
||||||
import com.facebook.react.bridge.Arguments;
|
|
||||||
import com.facebook.react.bridge.ReactContext;
|
|
||||||
import com.facebook.react.bridge.UIManager;
|
|
||||||
import com.facebook.react.bridge.WritableArray;
|
|
||||||
import com.facebook.react.bridge.WritableMap;
|
|
||||||
import com.facebook.react.uimanager.UIManagerHelper;
|
|
||||||
import com.facebook.react.uimanager.common.ViewUtil;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class VideoEventEmitter {
|
|
||||||
|
|
||||||
private final ReactContext mReactContext;
|
|
||||||
|
|
||||||
private int viewId = View.NO_ID;
|
|
||||||
|
|
||||||
public VideoEventEmitter(ReactContext reactContext) {
|
|
||||||
this.mReactContext = reactContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String EVENT_LOAD_START = "onVideoLoadStart";
|
|
||||||
private static final String EVENT_LOAD = "onVideoLoad";
|
|
||||||
private static final String EVENT_ERROR = "onVideoError";
|
|
||||||
private static final String EVENT_PROGRESS = "onVideoProgress";
|
|
||||||
private static final String EVENT_BANDWIDTH = "onVideoBandwidthUpdate";
|
|
||||||
private static final String EVENT_CONTROLS_VISIBILITY_CHANGE = "onControlsVisibilityChange";
|
|
||||||
private static final String EVENT_SEEK = "onVideoSeek";
|
|
||||||
private static final String EVENT_END = "onVideoEnd";
|
|
||||||
private static final String EVENT_FULLSCREEN_WILL_PRESENT = "onVideoFullscreenPlayerWillPresent";
|
|
||||||
private static final String EVENT_FULLSCREEN_DID_PRESENT = "onVideoFullscreenPlayerDidPresent";
|
|
||||||
private static final String EVENT_FULLSCREEN_WILL_DISMISS = "onVideoFullscreenPlayerWillDismiss";
|
|
||||||
private static final String EVENT_FULLSCREEN_DID_DISMISS = "onVideoFullscreenPlayerDidDismiss";
|
|
||||||
|
|
||||||
private static final String EVENT_STALLED = "onPlaybackStalled";
|
|
||||||
private static final String EVENT_RESUME = "onPlaybackResume";
|
|
||||||
private static final String EVENT_READY = "onReadyForDisplay";
|
|
||||||
private static final String EVENT_BUFFER = "onVideoBuffer";
|
|
||||||
private static final String EVENT_PLAYBACK_STATE_CHANGED = "onVideoPlaybackStateChanged";
|
|
||||||
private static final String EVENT_IDLE = "onVideoIdle";
|
|
||||||
private static final String EVENT_TIMED_METADATA = "onTimedMetadata";
|
|
||||||
private static final String EVENT_AUDIO_BECOMING_NOISY = "onVideoAudioBecomingNoisy";
|
|
||||||
private static final String EVENT_AUDIO_FOCUS_CHANGE = "onAudioFocusChanged";
|
|
||||||
private static final String EVENT_PLAYBACK_RATE_CHANGE = "onPlaybackRateChange";
|
|
||||||
private static final String EVENT_VOLUME_CHANGE = "onVolumeChange";
|
|
||||||
private static final String EVENT_AUDIO_TRACKS = "onAudioTracks";
|
|
||||||
private static final String EVENT_TEXT_TRACKS = "onTextTracks";
|
|
||||||
|
|
||||||
private static final String EVENT_TEXT_TRACK_DATA_CHANGED = "onTextTrackDataChanged";
|
|
||||||
private static final String EVENT_VIDEO_TRACKS = "onVideoTracks";
|
|
||||||
private static final String EVENT_ON_RECEIVE_AD_EVENT = "onReceiveAdEvent";
|
|
||||||
|
|
||||||
static public final String[] Events = {
|
|
||||||
EVENT_LOAD_START,
|
|
||||||
EVENT_LOAD,
|
|
||||||
EVENT_ERROR,
|
|
||||||
EVENT_PROGRESS,
|
|
||||||
EVENT_SEEK,
|
|
||||||
EVENT_END,
|
|
||||||
EVENT_FULLSCREEN_WILL_PRESENT,
|
|
||||||
EVENT_FULLSCREEN_DID_PRESENT,
|
|
||||||
EVENT_FULLSCREEN_WILL_DISMISS,
|
|
||||||
EVENT_FULLSCREEN_DID_DISMISS,
|
|
||||||
EVENT_STALLED,
|
|
||||||
EVENT_RESUME,
|
|
||||||
EVENT_READY,
|
|
||||||
EVENT_BUFFER,
|
|
||||||
EVENT_PLAYBACK_STATE_CHANGED,
|
|
||||||
EVENT_IDLE,
|
|
||||||
EVENT_TIMED_METADATA,
|
|
||||||
EVENT_AUDIO_BECOMING_NOISY,
|
|
||||||
EVENT_AUDIO_FOCUS_CHANGE,
|
|
||||||
EVENT_PLAYBACK_RATE_CHANGE,
|
|
||||||
EVENT_VOLUME_CHANGE,
|
|
||||||
EVENT_AUDIO_TRACKS,
|
|
||||||
EVENT_TEXT_TRACKS,
|
|
||||||
EVENT_TEXT_TRACK_DATA_CHANGED,
|
|
||||||
EVENT_VIDEO_TRACKS,
|
|
||||||
EVENT_BANDWIDTH,
|
|
||||||
EVENT_CONTROLS_VISIBILITY_CHANGE,
|
|
||||||
EVENT_ON_RECEIVE_AD_EVENT
|
|
||||||
};
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
@StringDef({
|
|
||||||
EVENT_LOAD_START,
|
|
||||||
EVENT_LOAD,
|
|
||||||
EVENT_ERROR,
|
|
||||||
EVENT_PROGRESS,
|
|
||||||
EVENT_SEEK,
|
|
||||||
EVENT_END,
|
|
||||||
EVENT_FULLSCREEN_WILL_PRESENT,
|
|
||||||
EVENT_FULLSCREEN_DID_PRESENT,
|
|
||||||
EVENT_FULLSCREEN_WILL_DISMISS,
|
|
||||||
EVENT_FULLSCREEN_DID_DISMISS,
|
|
||||||
EVENT_STALLED,
|
|
||||||
EVENT_RESUME,
|
|
||||||
EVENT_READY,
|
|
||||||
EVENT_BUFFER,
|
|
||||||
EVENT_PLAYBACK_STATE_CHANGED,
|
|
||||||
EVENT_IDLE,
|
|
||||||
EVENT_TIMED_METADATA,
|
|
||||||
EVENT_AUDIO_BECOMING_NOISY,
|
|
||||||
EVENT_AUDIO_FOCUS_CHANGE,
|
|
||||||
EVENT_PLAYBACK_RATE_CHANGE,
|
|
||||||
EVENT_VOLUME_CHANGE,
|
|
||||||
EVENT_AUDIO_TRACKS,
|
|
||||||
EVENT_TEXT_TRACKS,
|
|
||||||
EVENT_TEXT_TRACK_DATA_CHANGED,
|
|
||||||
EVENT_VIDEO_TRACKS,
|
|
||||||
EVENT_BANDWIDTH,
|
|
||||||
EVENT_CONTROLS_VISIBILITY_CHANGE,
|
|
||||||
EVENT_ON_RECEIVE_AD_EVENT
|
|
||||||
})
|
|
||||||
@interface VideoEvents {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String EVENT_PROP_FAST_FORWARD = "canPlayFastForward";
|
|
||||||
private static final String EVENT_PROP_SLOW_FORWARD = "canPlaySlowForward";
|
|
||||||
private static final String EVENT_PROP_SLOW_REVERSE = "canPlaySlowReverse";
|
|
||||||
private static final String EVENT_PROP_REVERSE = "canPlayReverse";
|
|
||||||
private static final String EVENT_PROP_STEP_FORWARD = "canStepForward";
|
|
||||||
private static final String EVENT_PROP_STEP_BACKWARD = "canStepBackward";
|
|
||||||
|
|
||||||
private static final String EVENT_PROP_DURATION = "duration";
|
|
||||||
private static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration";
|
|
||||||
private static final String EVENT_PROP_SEEKABLE_DURATION = "seekableDuration";
|
|
||||||
private static final String EVENT_PROP_CURRENT_TIME = "currentTime";
|
|
||||||
private static final String EVENT_PROP_CURRENT_PLAYBACK_TIME = "currentPlaybackTime";
|
|
||||||
private static final String EVENT_PROP_SEEK_TIME = "seekTime";
|
|
||||||
private static final String EVENT_PROP_NATURAL_SIZE = "naturalSize";
|
|
||||||
private static final String EVENT_PROP_TRACK_ID = "trackId";
|
|
||||||
private static final String EVENT_PROP_WIDTH = "width";
|
|
||||||
private static final String EVENT_PROP_HEIGHT = "height";
|
|
||||||
private static final String EVENT_PROP_ORIENTATION = "orientation";
|
|
||||||
private static final String EVENT_PROP_VIDEO_TRACKS = "videoTracks";
|
|
||||||
private static final String EVENT_PROP_AUDIO_TRACKS = "audioTracks";
|
|
||||||
private static final String EVENT_PROP_TEXT_TRACKS = "textTracks";
|
|
||||||
private static final String EVENT_PROP_TEXT_TRACK_DATA = "subtitleTracks";
|
|
||||||
private static final String EVENT_PROP_HAS_AUDIO_FOCUS = "hasAudioFocus";
|
|
||||||
private static final String EVENT_PROP_IS_BUFFERING = "isBuffering";
|
|
||||||
private static final String EVENT_PROP_PLAYBACK_RATE = "playbackRate";
|
|
||||||
private static final String EVENT_PROP_VOLUME = "volume";
|
|
||||||
|
|
||||||
private static final String EVENT_PROP_ERROR = "error";
|
|
||||||
private static final String EVENT_PROP_ERROR_STRING = "errorString";
|
|
||||||
private static final String EVENT_PROP_ERROR_EXCEPTION = "errorException";
|
|
||||||
private static final String EVENT_PROP_ERROR_TRACE = "errorStackTrace";
|
|
||||||
private static final String EVENT_PROP_ERROR_CODE = "errorCode";
|
|
||||||
|
|
||||||
private static final String EVENT_PROP_TIMED_METADATA = "metadata";
|
|
||||||
|
|
||||||
private static final String EVENT_PROP_BITRATE = "bitrate";
|
|
||||||
|
|
||||||
private static final String EVENT_PROP_IS_PLAYING = "isPlaying";
|
|
||||||
|
|
||||||
private static final String EVENT_CONTROLS_VISIBLE = "isVisible";
|
|
||||||
|
|
||||||
public void setViewId(int viewId) {
|
|
||||||
this.viewId = viewId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadStart() {
|
|
||||||
receiveEvent(EVENT_LOAD_START, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableMap aspectRatioToNaturalSize(int videoWidth, int videoHeight) {
|
|
||||||
WritableMap naturalSize = Arguments.createMap();
|
|
||||||
naturalSize.putInt(EVENT_PROP_WIDTH, videoWidth);
|
|
||||||
naturalSize.putInt(EVENT_PROP_HEIGHT, videoHeight);
|
|
||||||
if (videoWidth > videoHeight) {
|
|
||||||
naturalSize.putString(EVENT_PROP_ORIENTATION, "landscape");
|
|
||||||
} else if (videoWidth < videoHeight) {
|
|
||||||
naturalSize.putString(EVENT_PROP_ORIENTATION, "portrait");
|
|
||||||
} else {
|
|
||||||
naturalSize.putString(EVENT_PROP_ORIENTATION, "square");
|
|
||||||
}
|
|
||||||
return naturalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableArray audioTracksToArray(ArrayList<Track> audioTracks) {
|
|
||||||
WritableArray waAudioTracks = Arguments.createArray();
|
|
||||||
if( audioTracks != null ){
|
|
||||||
for (int i = 0; i < audioTracks.size(); ++i) {
|
|
||||||
Track format = audioTracks.get(i);
|
|
||||||
WritableMap audioTrack = Arguments.createMap();
|
|
||||||
audioTrack.putInt("index", i);
|
|
||||||
audioTrack.putString("title", format.getTitle());
|
|
||||||
if (format.getMimeType() != null) {
|
|
||||||
audioTrack.putString("type", format.getMimeType());
|
|
||||||
}
|
|
||||||
if (format.getLanguage() != null) {
|
|
||||||
audioTrack.putString("language", format.getLanguage());
|
|
||||||
}
|
|
||||||
if (format.getBitrate() > 0) {
|
|
||||||
audioTrack.putInt("bitrate", format.getBitrate());
|
|
||||||
}
|
|
||||||
audioTrack.putBoolean("selected", format.isSelected());
|
|
||||||
waAudioTracks.pushMap(audioTrack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return waAudioTracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableArray videoTracksToArray(ArrayList<VideoTrack> videoTracks) {
|
|
||||||
WritableArray waVideoTracks = Arguments.createArray();
|
|
||||||
if( videoTracks != null ){
|
|
||||||
for (int i = 0; i < videoTracks.size(); ++i) {
|
|
||||||
VideoTrack vTrack = videoTracks.get(i);
|
|
||||||
WritableMap videoTrack = Arguments.createMap();
|
|
||||||
videoTrack.putInt("width", vTrack.getWidth());
|
|
||||||
videoTrack.putInt("height",vTrack.getHeight());
|
|
||||||
videoTrack.putInt("bitrate", vTrack.getBitrate());
|
|
||||||
videoTrack.putString("codecs", vTrack.getCodecs());
|
|
||||||
videoTrack.putString("trackId", vTrack.getTrackId());
|
|
||||||
videoTrack.putInt("index", vTrack.getIndex());
|
|
||||||
videoTrack.putBoolean("selected", vTrack.isSelected());
|
|
||||||
videoTrack.putInt("rotation", vTrack.getRotation());
|
|
||||||
waVideoTracks.pushMap(videoTrack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return waVideoTracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableArray textTracksToArray(ArrayList<Track> textTracks) {
|
|
||||||
WritableArray waTextTracks = Arguments.createArray();
|
|
||||||
if (textTracks != null) {
|
|
||||||
for (int i = 0; i < textTracks.size(); ++i) {
|
|
||||||
Track format = textTracks.get(i);
|
|
||||||
WritableMap textTrack = Arguments.createMap();
|
|
||||||
textTrack.putInt("index", i);
|
|
||||||
textTrack.putString("title", format.getTitle());
|
|
||||||
textTrack.putString("type", format.getMimeType());
|
|
||||||
textTrack.putString("language", format.getLanguage());
|
|
||||||
textTrack.putBoolean("selected", format.isSelected());
|
|
||||||
waTextTracks.pushMap(textTrack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return waTextTracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(double duration, double currentPosition, int videoWidth, int videoHeight,
|
|
||||||
ArrayList<Track> audioTracks, ArrayList<Track> textTracks, ArrayList<VideoTrack> videoTracks, String trackId){
|
|
||||||
WritableArray waAudioTracks = audioTracksToArray(audioTracks);
|
|
||||||
WritableArray waVideoTracks = videoTracksToArray(videoTracks);
|
|
||||||
WritableArray waTextTracks = textTracksToArray(textTracks);
|
|
||||||
|
|
||||||
load( duration, currentPosition, videoWidth, videoHeight, waAudioTracks, waTextTracks, waVideoTracks, trackId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void load(double duration, double currentPosition, int videoWidth, int videoHeight,
|
|
||||||
WritableArray audioTracks, WritableArray textTracks, WritableArray videoTracks, String trackId) {
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putDouble(EVENT_PROP_DURATION, duration / 1000D);
|
|
||||||
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
|
||||||
|
|
||||||
WritableMap naturalSize = aspectRatioToNaturalSize(videoWidth, videoHeight);
|
|
||||||
event.putMap(EVENT_PROP_NATURAL_SIZE, naturalSize);
|
|
||||||
event.putString(EVENT_PROP_TRACK_ID, trackId);
|
|
||||||
event.putArray(EVENT_PROP_VIDEO_TRACKS, videoTracks);
|
|
||||||
event.putArray(EVENT_PROP_AUDIO_TRACKS, audioTracks);
|
|
||||||
event.putArray(EVENT_PROP_TEXT_TRACKS, textTracks);
|
|
||||||
|
|
||||||
// TODO: Actually check if you can.
|
|
||||||
event.putBoolean(EVENT_PROP_FAST_FORWARD, true);
|
|
||||||
event.putBoolean(EVENT_PROP_SLOW_FORWARD, true);
|
|
||||||
event.putBoolean(EVENT_PROP_SLOW_REVERSE, true);
|
|
||||||
event.putBoolean(EVENT_PROP_REVERSE, true);
|
|
||||||
event.putBoolean(EVENT_PROP_FAST_FORWARD, true);
|
|
||||||
event.putBoolean(EVENT_PROP_STEP_BACKWARD, true);
|
|
||||||
event.putBoolean(EVENT_PROP_STEP_FORWARD, true);
|
|
||||||
|
|
||||||
receiveEvent(EVENT_LOAD, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableMap arrayToObject(String field, WritableArray array) {
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putArray(field, array);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void audioTracks(ArrayList<Track> audioTracks){
|
|
||||||
receiveEvent(EVENT_AUDIO_TRACKS, arrayToObject(EVENT_PROP_AUDIO_TRACKS, audioTracksToArray(audioTracks)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void textTracks(ArrayList<Track> textTracks){
|
|
||||||
receiveEvent(EVENT_TEXT_TRACKS, arrayToObject(EVENT_PROP_TEXT_TRACKS, textTracksToArray(textTracks)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void textTrackDataChanged(String textTrackData){
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putString(EVENT_PROP_TEXT_TRACK_DATA, textTrackData);
|
|
||||||
receiveEvent(EVENT_TEXT_TRACK_DATA_CHANGED, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void videoTracks(ArrayList<VideoTrack> videoTracks){
|
|
||||||
receiveEvent(EVENT_VIDEO_TRACKS, arrayToObject(EVENT_PROP_VIDEO_TRACKS, videoTracksToArray(videoTracks)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void progressChanged(double currentPosition, double bufferedDuration, double seekableDuration, double currentPlaybackTime) {
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
|
||||||
event.putDouble(EVENT_PROP_PLAYABLE_DURATION, bufferedDuration / 1000D);
|
|
||||||
event.putDouble(EVENT_PROP_SEEKABLE_DURATION, seekableDuration / 1000D);
|
|
||||||
event.putDouble(EVENT_PROP_CURRENT_PLAYBACK_TIME, currentPlaybackTime);
|
|
||||||
receiveEvent(EVENT_PROGRESS, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bandwidthReport(double bitRateEstimate, int height, int width, String id) {
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate);
|
|
||||||
event.putInt(EVENT_PROP_WIDTH, width);
|
|
||||||
event.putInt(EVENT_PROP_HEIGHT, height);
|
|
||||||
event.putString(EVENT_PROP_TRACK_ID, id);
|
|
||||||
receiveEvent(EVENT_BANDWIDTH, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void seek(long currentPosition, long seekTime) {
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
|
|
||||||
event.putDouble(EVENT_PROP_SEEK_TIME, seekTime / 1000D);
|
|
||||||
receiveEvent(EVENT_SEEK, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ready() {
|
|
||||||
receiveEvent(EVENT_READY, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void buffering(boolean isBuffering) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putBoolean(EVENT_PROP_IS_BUFFERING, isBuffering);
|
|
||||||
receiveEvent(EVENT_BUFFER, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playbackStateChanged(boolean isPlaying) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putBoolean(EVENT_PROP_IS_PLAYING, isPlaying);
|
|
||||||
receiveEvent(EVENT_PLAYBACK_STATE_CHANGED, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void idle() {
|
|
||||||
receiveEvent(EVENT_IDLE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void end() {
|
|
||||||
receiveEvent(EVENT_END, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void controlsVisibilityChanged(boolean isVisible) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putBoolean(EVENT_CONTROLS_VISIBLE, isVisible);
|
|
||||||
receiveEvent(EVENT_CONTROLS_VISIBILITY_CHANGE, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fullscreenWillPresent() {
|
|
||||||
receiveEvent(EVENT_FULLSCREEN_WILL_PRESENT, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fullscreenDidPresent() {
|
|
||||||
receiveEvent(EVENT_FULLSCREEN_DID_PRESENT, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fullscreenWillDismiss() {
|
|
||||||
receiveEvent(EVENT_FULLSCREEN_WILL_DISMISS, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void fullscreenDidDismiss() {
|
|
||||||
receiveEvent(EVENT_FULLSCREEN_DID_DISMISS, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void error(String errorString, Exception exception) {
|
|
||||||
_error(errorString, exception, "0001");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void error(String errorString, Exception exception, String errorCode) {
|
|
||||||
_error(errorString, exception, errorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _error(String errorString, Exception exception, String errorCode) {
|
|
||||||
// Prepare stack trace
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
|
||||||
exception.printStackTrace(pw);
|
|
||||||
String stackTrace = sw.toString();
|
|
||||||
|
|
||||||
WritableMap error = Arguments.createMap();
|
|
||||||
error.putString(EVENT_PROP_ERROR_STRING, errorString);
|
|
||||||
error.putString(EVENT_PROP_ERROR_EXCEPTION, exception.toString());
|
|
||||||
error.putString(EVENT_PROP_ERROR_CODE, errorCode);
|
|
||||||
error.putString(EVENT_PROP_ERROR_TRACE, stackTrace);
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putMap(EVENT_PROP_ERROR, error);
|
|
||||||
receiveEvent(EVENT_ERROR, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playbackRateChange(float rate) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putDouble(EVENT_PROP_PLAYBACK_RATE, (double)rate);
|
|
||||||
receiveEvent(EVENT_PLAYBACK_RATE_CHANGE, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void volumeChange(float volume) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putDouble(EVENT_PROP_VOLUME, volume);
|
|
||||||
receiveEvent(EVENT_VOLUME_CHANGE, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void timedMetadata(ArrayList<TimedMetadata> _metadataArrayList) {
|
|
||||||
if (_metadataArrayList.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WritableArray metadataArray = Arguments.createArray();
|
|
||||||
|
|
||||||
for (int i = 0; i < _metadataArrayList.size(); i++) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putString("identifier", _metadataArrayList.get(i).getIdentifier());
|
|
||||||
map.putString("value", _metadataArrayList.get(i).getValue());
|
|
||||||
metadataArray.pushMap(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
WritableMap event = Arguments.createMap();
|
|
||||||
event.putArray(EVENT_PROP_TIMED_METADATA, metadataArray);
|
|
||||||
receiveEvent(EVENT_TIMED_METADATA, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void audioFocusChanged(boolean hasFocus) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putBoolean(EVENT_PROP_HAS_AUDIO_FOCUS, hasFocus);
|
|
||||||
receiveEvent(EVENT_AUDIO_FOCUS_CHANGE, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void audioBecomingNoisy() {
|
|
||||||
receiveEvent(EVENT_AUDIO_BECOMING_NOISY, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void receiveAdEvent(String event, Map<String, String> data) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putString("event", event);
|
|
||||||
|
|
||||||
WritableMap dataMap = Arguments.createMap();
|
|
||||||
for (Map.Entry<String, String> entry : data.entrySet()) {
|
|
||||||
dataMap.putString(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
map.putMap("data", dataMap);
|
|
||||||
|
|
||||||
receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void receiveAdEvent(String event) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putString("event", event);
|
|
||||||
|
|
||||||
receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void receiveAdErrorEvent(String message, String code, String type) {
|
|
||||||
WritableMap map = Arguments.createMap();
|
|
||||||
map.putString("event", "ERROR");
|
|
||||||
|
|
||||||
WritableMap dataMap = Arguments.createMap();
|
|
||||||
dataMap.putString("message", message);
|
|
||||||
dataMap.putString("code", code);
|
|
||||||
dataMap.putString("type", type);
|
|
||||||
map.putMap("data", dataMap);
|
|
||||||
|
|
||||||
receiveEvent(EVENT_ON_RECEIVE_AD_EVENT, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void receiveEvent(@VideoEvents String type, WritableMap event) {
|
|
||||||
UIManager uiManager = UIManagerHelper.getUIManager(mReactContext, ViewUtil.getUIManagerType(viewId));
|
|
||||||
|
|
||||||
if(uiManager != null) {
|
|
||||||
uiManager.receiveEvent(UIManagerHelper.getSurfaceId(mReactContext), viewId, type, event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,349 @@
|
|||||||
|
package com.brentvatne.common.react
|
||||||
|
|
||||||
|
import com.brentvatne.common.api.TimedMetadata
|
||||||
|
import com.brentvatne.common.api.Track
|
||||||
|
import com.brentvatne.common.api.VideoTrack
|
||||||
|
import com.brentvatne.exoplayer.ReactExoplayerView
|
||||||
|
import com.facebook.react.bridge.Arguments
|
||||||
|
import com.facebook.react.bridge.WritableArray
|
||||||
|
import com.facebook.react.bridge.WritableMap
|
||||||
|
import com.facebook.react.uimanager.ThemedReactContext
|
||||||
|
import com.facebook.react.uimanager.UIManagerHelper
|
||||||
|
import com.facebook.react.uimanager.events.Event
|
||||||
|
import com.facebook.react.uimanager.events.EventDispatcher
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.io.StringWriter
|
||||||
|
|
||||||
|
enum class EventTypes(val eventName: String) {
|
||||||
|
EVENT_LOAD_START("onVideoLoadStart"),
|
||||||
|
EVENT_LOAD("onVideoLoad"),
|
||||||
|
EVENT_ERROR("onVideoError"),
|
||||||
|
EVENT_PROGRESS("onVideoProgress"),
|
||||||
|
EVENT_BANDWIDTH("onVideoBandwidthUpdate"),
|
||||||
|
EVENT_CONTROLS_VISIBILITY_CHANGE("onControlsVisibilityChange"),
|
||||||
|
EVENT_SEEK("onVideoSeek"),
|
||||||
|
EVENT_END("onVideoEnd"),
|
||||||
|
EVENT_FULLSCREEN_WILL_PRESENT("onVideoFullscreenPlayerWillPresent"),
|
||||||
|
EVENT_FULLSCREEN_DID_PRESENT("onVideoFullscreenPlayerDidPresent"),
|
||||||
|
EVENT_FULLSCREEN_WILL_DISMISS("onVideoFullscreenPlayerWillDismiss"),
|
||||||
|
EVENT_FULLSCREEN_DID_DISMISS("onVideoFullscreenPlayerDidDismiss"),
|
||||||
|
|
||||||
|
EVENT_READY("onReadyForDisplay"),
|
||||||
|
EVENT_BUFFER("onVideoBuffer"),
|
||||||
|
EVENT_PLAYBACK_STATE_CHANGED("onVideoPlaybackStateChanged"),
|
||||||
|
EVENT_IDLE("onVideoIdle"),
|
||||||
|
EVENT_TIMED_METADATA("onTimedMetadata"),
|
||||||
|
EVENT_AUDIO_BECOMING_NOISY("onVideoAudioBecomingNoisy"),
|
||||||
|
EVENT_AUDIO_FOCUS_CHANGE("onAudioFocusChanged"),
|
||||||
|
EVENT_PLAYBACK_RATE_CHANGE("onPlaybackRateChange"),
|
||||||
|
EVENT_VOLUME_CHANGE("onVolumeChange"),
|
||||||
|
EVENT_AUDIO_TRACKS("onAudioTracks"),
|
||||||
|
EVENT_TEXT_TRACKS("onTextTracks"),
|
||||||
|
|
||||||
|
EVENT_TEXT_TRACK_DATA_CHANGED("onTextTrackDataChanged"),
|
||||||
|
EVENT_VIDEO_TRACKS("onVideoTracks"),
|
||||||
|
EVENT_ON_RECEIVE_AD_EVENT("onReceiveAdEvent");
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun toMap() =
|
||||||
|
mutableMapOf<String, Any>().apply {
|
||||||
|
EventTypes.entries.forEach { eventType ->
|
||||||
|
put("top${eventType.eventName.removePrefix("on")}", mapOf("registrationName" to eventType.eventName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VideoEventEmitter {
|
||||||
|
lateinit var onVideoLoadStart: () -> Unit
|
||||||
|
lateinit var onVideoLoad: (
|
||||||
|
duration: Long,
|
||||||
|
currentPosition: Long,
|
||||||
|
videoWidth: Int,
|
||||||
|
videoHeight: Int,
|
||||||
|
audioTracks: ArrayList<Track>,
|
||||||
|
textTracks: ArrayList<Track>,
|
||||||
|
videoTracks: ArrayList<VideoTrack>,
|
||||||
|
trackId: String
|
||||||
|
) -> Unit
|
||||||
|
lateinit var onVideoError: (errorString: String, exception: Exception, errorCode: String) -> Unit
|
||||||
|
lateinit var onVideoProgress: (currentPosition: Long, bufferedDuration: Long, seekableDuration: Long, currentPlaybackTime: Double) -> Unit
|
||||||
|
lateinit var onVideoBandwidthUpdate: (bitRateEstimate: Long, height: Int, width: Int, trackId: String) -> Unit
|
||||||
|
lateinit var onVideoPlaybackStateChanged: (isPlaying: Boolean) -> Unit
|
||||||
|
lateinit var onVideoSeek: (currentPosition: Long, seekTime: Long) -> Unit
|
||||||
|
lateinit var onVideoEnd: () -> Unit
|
||||||
|
lateinit var onVideoFullscreenPlayerWillPresent: () -> Unit
|
||||||
|
lateinit var onVideoFullscreenPlayerDidPresent: () -> Unit
|
||||||
|
lateinit var onVideoFullscreenPlayerWillDismiss: () -> Unit
|
||||||
|
lateinit var onVideoFullscreenPlayerDidDismiss: () -> Unit
|
||||||
|
lateinit var onReadyForDisplay: () -> Unit
|
||||||
|
lateinit var onVideoBuffer: (isBuffering: Boolean) -> Unit
|
||||||
|
lateinit var onControlsVisibilityChange: (isVisible: Boolean) -> Unit
|
||||||
|
lateinit var onVideoIdle: () -> Unit
|
||||||
|
lateinit var onTimedMetadata: (metadataArrayList: ArrayList<TimedMetadata>) -> Unit
|
||||||
|
lateinit var onVideoAudioBecomingNoisy: () -> Unit
|
||||||
|
lateinit var onAudioFocusChanged: (hasFocus: Boolean) -> Unit
|
||||||
|
lateinit var onPlaybackRateChange: (rate: Float) -> Unit
|
||||||
|
lateinit var onVolumeChange: (volume: Float) -> Unit
|
||||||
|
lateinit var onAudioTracks: (audioTracks: ArrayList<Track>?) -> Unit
|
||||||
|
lateinit var onTextTracks: (textTracks: ArrayList<Track>?) -> Unit
|
||||||
|
lateinit var onVideoTracks: (videoTracks: ArrayList<VideoTrack>?) -> Unit
|
||||||
|
lateinit var onTextTrackDataChanged: (textTrackData: String) -> Unit
|
||||||
|
lateinit var onReceiveAdEvent: (adEvent: String, adData: Map<String?, String?>?) -> Unit
|
||||||
|
|
||||||
|
fun addEventEmitters(reactContext: ThemedReactContext, view: ReactExoplayerView) {
|
||||||
|
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id)
|
||||||
|
val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
|
||||||
|
|
||||||
|
if (dispatcher != null) {
|
||||||
|
val event = EventBuilder(surfaceId, view.id, dispatcher)
|
||||||
|
|
||||||
|
onVideoLoadStart = {
|
||||||
|
event.dispatch(EventTypes.EVENT_LOAD_START)
|
||||||
|
}
|
||||||
|
onVideoLoad = { duration, currentPosition, videoWidth, videoHeight, audioTracks, textTracks, videoTracks, trackId ->
|
||||||
|
event.dispatch(EventTypes.EVENT_LOAD) {
|
||||||
|
putDouble("duration", duration / 1000.0)
|
||||||
|
putDouble("playableDuration", currentPosition / 1000.0)
|
||||||
|
|
||||||
|
val naturalSize: WritableMap = aspectRatioToNaturalSize(videoWidth, videoHeight)
|
||||||
|
putMap("seekableDuration", naturalSize)
|
||||||
|
putString("trackId", trackId)
|
||||||
|
putArray("videoTracks", videoTracksToArray(videoTracks))
|
||||||
|
putArray("audioTracks", audioTracksToArray(audioTracks))
|
||||||
|
putArray("textTracks", textTracksToArray(textTracks))
|
||||||
|
|
||||||
|
// TODO: Actually check if you can.
|
||||||
|
putBoolean("canPlayFastForward", true)
|
||||||
|
putBoolean("canPlaySlowForward", true)
|
||||||
|
putBoolean("canPlaySlowReverse", true)
|
||||||
|
putBoolean("canPlayReverse", true)
|
||||||
|
putBoolean("canPlayFastForward", true)
|
||||||
|
putBoolean("canStepBackward", true)
|
||||||
|
putBoolean("canStepForward", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoError = { errorString, exception, errorCode ->
|
||||||
|
event.dispatch(EventTypes.EVENT_ERROR) {
|
||||||
|
putMap(
|
||||||
|
"error",
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
// Prepare stack trace
|
||||||
|
val sw = StringWriter()
|
||||||
|
val pw = PrintWriter(sw)
|
||||||
|
exception.printStackTrace(pw)
|
||||||
|
val stackTrace = sw.toString()
|
||||||
|
|
||||||
|
putString("errorString", errorString)
|
||||||
|
putString("errorException", exception.toString())
|
||||||
|
putString("errorCode", errorCode)
|
||||||
|
putString("errorStackTrace", stackTrace)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoProgress = { currentPosition, bufferedDuration, seekableDuration, currentPlaybackTime ->
|
||||||
|
event.dispatch(EventTypes.EVENT_PROGRESS) {
|
||||||
|
putDouble("currentTime", currentPosition / 1000.0)
|
||||||
|
putDouble("playableDuration", bufferedDuration / 1000.0)
|
||||||
|
putDouble("seekableDuration", seekableDuration / 1000.0)
|
||||||
|
putDouble("currentPlaybackTime", currentPlaybackTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoBandwidthUpdate = { bitRateEstimate, height, width, trackId ->
|
||||||
|
event.dispatch(EventTypes.EVENT_BANDWIDTH) {
|
||||||
|
putDouble("bitrate", bitRateEstimate.toDouble())
|
||||||
|
putInt("width", width)
|
||||||
|
putInt("height", height)
|
||||||
|
putString("trackId", trackId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoPlaybackStateChanged = { isPlaying ->
|
||||||
|
event.dispatch(EventTypes.EVENT_PLAYBACK_STATE_CHANGED) {
|
||||||
|
putBoolean("isPlaying", isPlaying)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoSeek = { currentPosition, seekTime ->
|
||||||
|
event.dispatch(EventTypes.EVENT_SEEK) {
|
||||||
|
putDouble("currentTime", currentPosition / 1000.0)
|
||||||
|
putDouble("seekTime", seekTime / 1000.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoEnd = {
|
||||||
|
event.dispatch(EventTypes.EVENT_END)
|
||||||
|
}
|
||||||
|
onVideoFullscreenPlayerWillPresent = {
|
||||||
|
event.dispatch(EventTypes.EVENT_FULLSCREEN_WILL_PRESENT)
|
||||||
|
}
|
||||||
|
onVideoFullscreenPlayerDidPresent = {
|
||||||
|
event.dispatch(EventTypes.EVENT_FULLSCREEN_DID_PRESENT)
|
||||||
|
}
|
||||||
|
onVideoFullscreenPlayerWillDismiss = {
|
||||||
|
event.dispatch(EventTypes.EVENT_FULLSCREEN_WILL_DISMISS)
|
||||||
|
}
|
||||||
|
onVideoFullscreenPlayerDidDismiss = {
|
||||||
|
event.dispatch(EventTypes.EVENT_FULLSCREEN_DID_DISMISS)
|
||||||
|
}
|
||||||
|
onReadyForDisplay = {
|
||||||
|
event.dispatch(EventTypes.EVENT_READY)
|
||||||
|
}
|
||||||
|
onVideoBuffer = { isBuffering ->
|
||||||
|
event.dispatch(EventTypes.EVENT_BUFFER) {
|
||||||
|
putBoolean("isBuffering", isBuffering)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onControlsVisibilityChange = { isVisible ->
|
||||||
|
event.dispatch(EventTypes.EVENT_CONTROLS_VISIBILITY_CHANGE) {
|
||||||
|
putBoolean("isVisible", isVisible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoIdle = {
|
||||||
|
event.dispatch(EventTypes.EVENT_IDLE)
|
||||||
|
}
|
||||||
|
onTimedMetadata = fn@{ metadataArrayList ->
|
||||||
|
if (metadataArrayList.size == 0) {
|
||||||
|
return@fn
|
||||||
|
}
|
||||||
|
event.dispatch(EventTypes.EVENT_TIMED_METADATA) {
|
||||||
|
putArray(
|
||||||
|
"metadata",
|
||||||
|
Arguments.createArray().apply {
|
||||||
|
metadataArrayList.forEachIndexed { i, metadata ->
|
||||||
|
pushMap(
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
putString("identifier", metadata.identifier)
|
||||||
|
putString("value", metadata.value)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoAudioBecomingNoisy = {
|
||||||
|
event.dispatch(EventTypes.EVENT_AUDIO_BECOMING_NOISY)
|
||||||
|
}
|
||||||
|
onAudioFocusChanged = { hasFocus ->
|
||||||
|
event.dispatch(EventTypes.EVENT_AUDIO_FOCUS_CHANGE) {
|
||||||
|
putBoolean("hasAudioFocus", hasFocus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onPlaybackRateChange = { rate ->
|
||||||
|
event.dispatch(EventTypes.EVENT_PLAYBACK_RATE_CHANGE) {
|
||||||
|
putDouble("playbackRate", rate.toDouble())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVolumeChange = { volume ->
|
||||||
|
event.dispatch(EventTypes.EVENT_VOLUME_CHANGE) {
|
||||||
|
putDouble("volume", volume.toDouble())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onAudioTracks = { audioTracks ->
|
||||||
|
event.dispatch(EventTypes.EVENT_AUDIO_TRACKS) {
|
||||||
|
putArray("audioTracks", audioTracksToArray(audioTracks))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onTextTracks = { textTracks ->
|
||||||
|
event.dispatch(EventTypes.EVENT_TEXT_TRACKS) {
|
||||||
|
putArray("textTracks", textTracksToArray(textTracks))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onVideoTracks = { videoTracks ->
|
||||||
|
event.dispatch(EventTypes.EVENT_VIDEO_TRACKS) {
|
||||||
|
putArray("videoTracks", videoTracksToArray(videoTracks))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onTextTrackDataChanged = { textTrackData ->
|
||||||
|
event.dispatch(EventTypes.EVENT_TEXT_TRACK_DATA_CHANGED) {
|
||||||
|
putString("subtitleTracks", textTrackData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onReceiveAdEvent = { adEvent, adData ->
|
||||||
|
event.dispatch(EventTypes.EVENT_ON_RECEIVE_AD_EVENT) {
|
||||||
|
putString("event", adEvent)
|
||||||
|
putMap(
|
||||||
|
"data",
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
adData?.let { data ->
|
||||||
|
for ((key, value) in data) {
|
||||||
|
putString(key!!, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class EventBuilder(private val surfaceId: Int, private val viewId: Int, private val dispatcher: EventDispatcher) {
|
||||||
|
fun dispatch(event: EventTypes, paramsSetter: (WritableMap.() -> Unit)? = null) =
|
||||||
|
dispatcher.dispatchEvent(object : Event<Event<*>>(surfaceId, viewId) {
|
||||||
|
override fun getEventName() = "top${event.eventName.removePrefix("on")}"
|
||||||
|
override fun getEventData() = Arguments.createMap().apply(paramsSetter ?: {})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun audioTracksToArray(audioTracks: java.util.ArrayList<Track>?): WritableArray =
|
||||||
|
Arguments.createArray().apply {
|
||||||
|
audioTracks?.forEachIndexed { i, format ->
|
||||||
|
pushMap(
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
putInt("index", i)
|
||||||
|
putString("title", format.title)
|
||||||
|
format.mimeType?.let { putString("type", it) }
|
||||||
|
format.language?.let { putString("language", it) }
|
||||||
|
if (format.bitrate > 0) putInt("bitrate", format.bitrate)
|
||||||
|
putBoolean("selected", format.isSelected)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun videoTracksToArray(videoTracks: java.util.ArrayList<VideoTrack>?): WritableArray =
|
||||||
|
Arguments.createArray().apply {
|
||||||
|
videoTracks?.forEachIndexed { i, vTrack ->
|
||||||
|
pushMap(
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
putInt("width", vTrack.width)
|
||||||
|
putInt("height", vTrack.height)
|
||||||
|
putInt("bitrate", vTrack.bitrate)
|
||||||
|
putString("codecs", vTrack.codecs)
|
||||||
|
putString("trackId", vTrack.trackId)
|
||||||
|
putInt("index", vTrack.index)
|
||||||
|
putBoolean("selected", vTrack.isSelected)
|
||||||
|
putInt("rotation", vTrack.rotation)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun textTracksToArray(textTracks: ArrayList<Track>?): WritableArray =
|
||||||
|
Arguments.createArray().apply {
|
||||||
|
textTracks?.forEachIndexed { i, format ->
|
||||||
|
pushMap(
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
putInt("index", i)
|
||||||
|
putString("title", format.title)
|
||||||
|
putString("type", format.mimeType)
|
||||||
|
putString("language", format.language)
|
||||||
|
putBoolean("selected", format.isSelected)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun aspectRatioToNaturalSize(videoWidth: Int, videoHeight: Int): WritableMap =
|
||||||
|
Arguments.createMap().apply {
|
||||||
|
putInt("width", videoWidth)
|
||||||
|
putInt("height", videoHeight)
|
||||||
|
val orientation = if (videoWidth > videoHeight) {
|
||||||
|
"landscape"
|
||||||
|
} else if (videoWidth < videoHeight) {
|
||||||
|
"portrait"
|
||||||
|
} else {
|
||||||
|
"square"
|
||||||
|
}
|
||||||
|
putString("orientation", orientation)
|
||||||
|
}
|
||||||
|
}
|
@ -142,6 +142,7 @@ import java.lang.Math;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@ -173,7 +174,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
|
DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final VideoEventEmitter eventEmitter;
|
protected final VideoEventEmitter eventEmitter;
|
||||||
private final ReactExoplayerConfig config;
|
private final ReactExoplayerConfig config;
|
||||||
private final DefaultBandwidthMeter bandwidthMeter;
|
private final DefaultBandwidthMeter bandwidthMeter;
|
||||||
private LegacyPlayerControlView playerControlView;
|
private LegacyPlayerControlView playerControlView;
|
||||||
@ -280,7 +281,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
lastPos = pos;
|
lastPos = pos;
|
||||||
lastBufferDuration = bufferedDuration;
|
lastBufferDuration = bufferedDuration;
|
||||||
lastDuration = duration;
|
lastDuration = duration;
|
||||||
eventEmitter.progressChanged(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
|
eventEmitter.onVideoProgress.invoke(pos, bufferedDuration, player.getDuration(), getPositionInFirstPeriodMsForCurrentWindow(pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,7 +308,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig config) {
|
public ReactExoplayerView(ThemedReactContext context, ReactExoplayerConfig config) {
|
||||||
super(context);
|
super(context);
|
||||||
this.themedReactContext = context;
|
this.themedReactContext = context;
|
||||||
this.eventEmitter = new VideoEventEmitter(context);
|
this.eventEmitter = new VideoEventEmitter();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.bandwidthMeter = config.getBandwidthMeter();
|
this.bandwidthMeter = config.getBandwidthMeter();
|
||||||
|
|
||||||
@ -323,12 +324,6 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
return player != null && player.isPlayingAd();
|
return player != null && player.isPlayingAd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setId(int id) {
|
|
||||||
super.setId(id);
|
|
||||||
eventEmitter.setViewId(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createViews() {
|
private void createViews() {
|
||||||
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
|
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
|
||||||
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
|
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
|
||||||
@ -388,13 +383,13 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
|
public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
|
||||||
if (mReportBandwidth) {
|
if (mReportBandwidth) {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
eventEmitter.bandwidthReport(bitrate, 0, 0, "-1");
|
eventEmitter.onVideoBandwidthUpdate.invoke(bitrate, 0, 0, "-1");
|
||||||
} else {
|
} else {
|
||||||
Format videoFormat = player.getVideoFormat();
|
Format videoFormat = player.getVideoFormat();
|
||||||
int width = videoFormat != null ? videoFormat.width : 0;
|
int width = videoFormat != null ? videoFormat.width : 0;
|
||||||
int height = videoFormat != null ? videoFormat.height : 0;
|
int height = videoFormat != null ? videoFormat.height : 0;
|
||||||
String trackId = videoFormat != null ? videoFormat.id : "-1";
|
String trackId = videoFormat != null ? videoFormat.id : "-1";
|
||||||
eventEmitter.bandwidthReport(bitrate, height, width, trackId);
|
eventEmitter.onVideoBandwidthUpdate.invoke(bitrate, height, width, trackId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +418,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
playerControlView.addVisibilityListener(new LegacyPlayerControlView.VisibilityListener() {
|
playerControlView.addVisibilityListener(new LegacyPlayerControlView.VisibilityListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onVisibilityChange(int visibility) {
|
public void onVisibilityChange(int visibility) {
|
||||||
eventEmitter.controlsVisibilityChanged(visibility == View.VISIBLE);
|
eventEmitter.onControlsVisibilityChange.invoke(visibility == View.VISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -682,7 +677,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
DebugLog.e(TAG, "Failed to initialize Player!, null activity");
|
DebugLog.e(TAG, "Failed to initialize Player!, null activity");
|
||||||
eventEmitter.error("Failed to initialize Player!", new Exception("Current Activity is null!"), "1001");
|
eventEmitter.onVideoError.invoke("Failed to initialize Player!", new Exception("Current Activity is null!"), "1001");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,7 +694,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
DebugLog.e(TAG, "Failed to initialize Player! 1");
|
DebugLog.e(TAG, "Failed to initialize Player! 1");
|
||||||
DebugLog.e(TAG, ex.toString());
|
DebugLog.e(TAG, ex.toString());
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
self.eventEmitter.error(ex.toString(), ex, "1001");
|
eventEmitter.onVideoError.invoke(ex.toString(), ex, "1001");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -711,7 +706,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
DebugLog.e(TAG, "Failed to initialize Player! 2");
|
DebugLog.e(TAG, "Failed to initialize Player! 2");
|
||||||
DebugLog.e(TAG, ex.toString());
|
DebugLog.e(TAG, ex.toString());
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
eventEmitter.error(ex.toString(), ex, "1001");
|
eventEmitter.onVideoError.invoke(ex.toString(), ex, "1001");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mainHandler.postDelayed(mainRunnable, 1);
|
mainHandler.postDelayed(mainRunnable, 1);
|
||||||
@ -797,7 +792,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
int errorStringId = Util.SDK_INT < 18 ? R.string.error_drm_not_supported
|
int errorStringId = Util.SDK_INT < 18 ? R.string.error_drm_not_supported
|
||||||
: (e.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME
|
: (e.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME
|
||||||
? R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown);
|
? R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown);
|
||||||
eventEmitter.error(getResources().getString(errorStringId), e, "3003");
|
eventEmitter.onVideoError.invoke(getResources().getString(errorStringId), e, "3003");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -812,7 +807,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
if (drmSessionManager == null && drmProps != null && drmProps.getDrmUUID() != null) {
|
if (drmSessionManager == null && drmProps != null && drmProps.getDrmUUID() != null) {
|
||||||
// Failed to intialize DRM session manager - cannot continue
|
// Failed to intialize DRM session manager - cannot continue
|
||||||
DebugLog.e(TAG, "Failed to initialize DRM Session Manager Framework!");
|
DebugLog.e(TAG, "Failed to initialize DRM Session Manager Framework!");
|
||||||
eventEmitter.error("Failed to initialize DRM Session Manager Framework!", new Exception("DRM Session Manager Framework failure!"), "3003");
|
eventEmitter.onVideoError.invoke("Failed to initialize DRM Session Manager Framework!", new Exception("DRM Session Manager Framework failure!"), "3003");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,7 +868,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
|
|
||||||
reLayoutControls();
|
reLayoutControls();
|
||||||
|
|
||||||
eventEmitter.loadStart();
|
eventEmitter.onVideoLoadStart.invoke();
|
||||||
loadVideoStarted = true;
|
loadVideoStarted = true;
|
||||||
|
|
||||||
finishPlayerInitialization();
|
finishPlayerInitialization();
|
||||||
@ -985,7 +980,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
return buildDrmSessionManager(uuid, licenseUrl, keyRequestPropertiesArray, ++retryCount);
|
return buildDrmSessionManager(uuid, licenseUrl, keyRequestPropertiesArray, ++retryCount);
|
||||||
}
|
}
|
||||||
// Handle the unknow exception and emit to JS
|
// Handle the unknow exception and emit to JS
|
||||||
eventEmitter.error(ex.toString(), ex, "3006");
|
eventEmitter.onVideoError.invoke(ex.toString(), ex, "3006");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1193,7 +1188,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
switch (focusChange) {
|
switch (focusChange) {
|
||||||
case AudioManager.AUDIOFOCUS_LOSS:
|
case AudioManager.AUDIOFOCUS_LOSS:
|
||||||
view.hasAudioFocus = false;
|
view.hasAudioFocus = false;
|
||||||
view.eventEmitter.audioFocusChanged(false);
|
view.eventEmitter.onAudioFocusChanged.invoke(false);
|
||||||
// FIXME this pause can cause issue if content doesn't have pause capability (can happen on live channel)
|
// FIXME this pause can cause issue if content doesn't have pause capability (can happen on live channel)
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
activity.runOnUiThread(view::pausePlayback);
|
activity.runOnUiThread(view::pausePlayback);
|
||||||
@ -1201,11 +1196,11 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
view.audioManager.abandonAudioFocus(this);
|
view.audioManager.abandonAudioFocus(this);
|
||||||
break;
|
break;
|
||||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||||
view.eventEmitter.audioFocusChanged(false);
|
view.eventEmitter.onAudioFocusChanged.invoke(false);
|
||||||
break;
|
break;
|
||||||
case AudioManager.AUDIOFOCUS_GAIN:
|
case AudioManager.AUDIOFOCUS_GAIN:
|
||||||
view.hasAudioFocus = true;
|
view.hasAudioFocus = true;
|
||||||
view.eventEmitter.audioFocusChanged(true);
|
view.eventEmitter.onAudioFocusChanged.invoke(true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1326,7 +1321,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
// AudioBecomingNoisyListener implementation
|
// AudioBecomingNoisyListener implementation
|
||||||
@Override
|
@Override
|
||||||
public void onAudioBecomingNoisy() {
|
public void onAudioBecomingNoisy() {
|
||||||
eventEmitter.audioBecomingNoisy();
|
eventEmitter.onVideoAudioBecomingNoisy.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player.Listener implementation
|
// Player.Listener implementation
|
||||||
@ -1341,11 +1336,11 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
int playbackState = player.getPlaybackState();
|
int playbackState = player.getPlaybackState();
|
||||||
boolean playWhenReady = player.getPlayWhenReady();
|
boolean playWhenReady = player.getPlayWhenReady();
|
||||||
String text = "onStateChanged: playWhenReady=" + playWhenReady + ", playbackState=";
|
String text = "onStateChanged: playWhenReady=" + playWhenReady + ", playbackState=";
|
||||||
eventEmitter.playbackRateChange(playWhenReady && playbackState == ExoPlayer.STATE_READY ? 1.0f : 0.0f);
|
eventEmitter.onPlaybackRateChange.invoke(playWhenReady && playbackState == ExoPlayer.STATE_READY ? 1.0f : 0.0f);
|
||||||
switch (playbackState) {
|
switch (playbackState) {
|
||||||
case Player.STATE_IDLE:
|
case Player.STATE_IDLE:
|
||||||
text += "idle";
|
text += "idle";
|
||||||
eventEmitter.idle();
|
eventEmitter.onVideoIdle.invoke();
|
||||||
clearProgressMessageHandler();
|
clearProgressMessageHandler();
|
||||||
if (!player.getPlayWhenReady()) {
|
if (!player.getPlayWhenReady()) {
|
||||||
setKeepScreenOn(false);
|
setKeepScreenOn(false);
|
||||||
@ -1359,7 +1354,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
break;
|
break;
|
||||||
case Player.STATE_READY:
|
case Player.STATE_READY:
|
||||||
text += "ready";
|
text += "ready";
|
||||||
eventEmitter.ready();
|
eventEmitter.onReadyForDisplay.invoke();
|
||||||
onBuffering(false);
|
onBuffering(false);
|
||||||
clearProgressMessageHandler(); // ensure there is no other message
|
clearProgressMessageHandler(); // ensure there is no other message
|
||||||
startProgressHandler();
|
startProgressHandler();
|
||||||
@ -1377,7 +1372,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
case Player.STATE_ENDED:
|
case Player.STATE_ENDED:
|
||||||
text += "ended";
|
text += "ended";
|
||||||
updateProgress();
|
updateProgress();
|
||||||
eventEmitter.end();
|
eventEmitter.onVideoEnd.invoke();
|
||||||
onStopPlayback();
|
onStopPlayback();
|
||||||
setKeepScreenOn(false);
|
setKeepScreenOn(false);
|
||||||
break;
|
break;
|
||||||
@ -1434,7 +1429,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
if (videoTracks != null) {
|
if (videoTracks != null) {
|
||||||
isUsingContentResolution = true;
|
isUsingContentResolution = true;
|
||||||
}
|
}
|
||||||
eventEmitter.load(duration, currentPosition, width, height,
|
eventEmitter.onVideoLoad.invoke(duration, currentPosition, width, height,
|
||||||
audioTracks, textTracks, videoTracks, trackId );
|
audioTracks, textTracks, videoTracks, trackId );
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -1443,7 +1438,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
|
|
||||||
ArrayList<VideoTrack> videoTracks = getVideoTrackInfo();
|
ArrayList<VideoTrack> videoTracks = getVideoTrackInfo();
|
||||||
|
|
||||||
eventEmitter.load(duration, currentPosition, width, height,
|
eventEmitter.onVideoLoad.invoke(duration, currentPosition, width, height,
|
||||||
audioTracks, textTracks, videoTracks, trackId);
|
audioTracks, textTracks, videoTracks, trackId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1626,13 +1621,13 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
isBuffering = buffering;
|
isBuffering = buffering;
|
||||||
eventEmitter.buffering(buffering);
|
eventEmitter.onVideoBuffer.invoke(buffering);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition, @NonNull Player.PositionInfo newPosition, @Player.DiscontinuityReason int reason) {
|
public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition, @NonNull Player.PositionInfo newPosition, @Player.DiscontinuityReason int reason) {
|
||||||
if (reason == Player.DISCONTINUITY_REASON_SEEK) {
|
if (reason == Player.DISCONTINUITY_REASON_SEEK) {
|
||||||
eventEmitter.seek(player.getCurrentPosition(), newPosition.positionMs % 1000); // time are in seconds /°\
|
eventEmitter.onVideoSeek.invoke(player.getCurrentPosition(), newPosition.positionMs % 1000); // time are in seconds /°\
|
||||||
if (isUsingContentResolution) {
|
if (isUsingContentResolution) {
|
||||||
// We need to update the selected track to make sure that it still matches user selection if track list has changed in this period
|
// We need to update the selected track to make sure that it still matches user selection if track list has changed in this period
|
||||||
setSelectedTrack(C.TRACK_TYPE_VIDEO, videoTrackType, videoTrackValue);
|
setSelectedTrack(C.TRACK_TYPE_VIDEO, videoTrackType, videoTrackValue);
|
||||||
@ -1655,7 +1650,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
|
if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION
|
||||||
&& player.getRepeatMode() == Player.REPEAT_MODE_ONE) {
|
&& player.getRepeatMode() == Player.REPEAT_MODE_ONE) {
|
||||||
updateProgress();
|
updateProgress();
|
||||||
eventEmitter.end();
|
eventEmitter.onVideoEnd.invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1666,24 +1661,24 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTracksChanged(@NonNull Tracks tracks) {
|
public void onTracksChanged(@NonNull Tracks tracks) {
|
||||||
eventEmitter.textTracks(getTextTrackInfo());
|
eventEmitter.onTextTracks.invoke(getTextTrackInfo());
|
||||||
eventEmitter.audioTracks(getAudioTrackInfo());
|
eventEmitter.onAudioTracks.invoke(getAudioTrackInfo());
|
||||||
eventEmitter.videoTracks(getVideoTrackInfo());
|
eventEmitter.onVideoTracks.invoke(getVideoTrackInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlaybackParametersChanged(PlaybackParameters params) {
|
public void onPlaybackParametersChanged(PlaybackParameters params) {
|
||||||
eventEmitter.playbackRateChange(params.speed);
|
eventEmitter.onPlaybackRateChange.invoke(params.speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVolumeChanged(float volume) {
|
public void onVolumeChanged(float volume) {
|
||||||
eventEmitter.volumeChange(volume);
|
eventEmitter.onVolumeChange.invoke(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIsPlayingChanged(boolean isPlaying) {
|
public void onIsPlayingChanged(boolean isPlaying) {
|
||||||
eventEmitter.playbackStateChanged(isPlaying);
|
eventEmitter.onVideoPlaybackStateChanged.invoke(isPlaying);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1709,7 +1704,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
eventEmitter.error(errorString, e, errorCode);
|
eventEmitter.onVideoError.invoke(errorString, e, errorCode);
|
||||||
playerNeedsSource = true;
|
playerNeedsSource = true;
|
||||||
if (isBehindLiveWindow(e)) {
|
if (isBehindLiveWindow(e)) {
|
||||||
clearResumePosition();
|
clearResumePosition();
|
||||||
@ -1760,13 +1755,13 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
DebugLog.d(TAG, "unhandled metadata " + entry);
|
DebugLog.d(TAG, "unhandled metadata " + entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eventEmitter.timedMetadata(metadataArray);
|
eventEmitter.onTimedMetadata.invoke(metadataArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCues(CueGroup cueGroup) {
|
public void onCues(CueGroup cueGroup) {
|
||||||
if (!cueGroup.cues.isEmpty() && cueGroup.cues.get(0).text != null) {
|
if (!cueGroup.cues.isEmpty() && cueGroup.cues.get(0).text != null) {
|
||||||
String subtitleText = cueGroup.cues.get(0).text.toString();
|
String subtitleText = cueGroup.cues.get(0).text.toString();
|
||||||
eventEmitter.textTrackDataChanged(subtitleText);
|
eventEmitter.onTextTrackDataChanged.invoke(subtitleText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2220,7 +2215,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
Window window = activity.getWindow();
|
Window window = activity.getWindow();
|
||||||
WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(window, window.getDecorView());
|
WindowInsetsControllerCompat controller = new WindowInsetsControllerCompat(window, window.getDecorView());
|
||||||
if (isFullscreen) {
|
if (isFullscreen) {
|
||||||
eventEmitter.fullscreenWillPresent();
|
eventEmitter.onVideoFullscreenPlayerWillPresent.invoke();
|
||||||
if (fullScreenPlayerView != null) {
|
if (fullScreenPlayerView != null) {
|
||||||
fullScreenPlayerView.show();
|
fullScreenPlayerView.show();
|
||||||
}
|
}
|
||||||
@ -2228,10 +2223,10 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
WindowCompat.setDecorFitsSystemWindows(window, false);
|
WindowCompat.setDecorFitsSystemWindows(window, false);
|
||||||
controller.hide(WindowInsetsCompat.Type.systemBars());
|
controller.hide(WindowInsetsCompat.Type.systemBars());
|
||||||
controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
controller.setSystemBarsBehavior(WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
||||||
eventEmitter.fullscreenDidPresent();
|
eventEmitter.onVideoFullscreenPlayerDidPresent.invoke();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
eventEmitter.fullscreenWillDismiss();
|
eventEmitter.onVideoFullscreenPlayerWillDismiss.invoke();
|
||||||
if (fullScreenPlayerView != null) {
|
if (fullScreenPlayerView != null) {
|
||||||
fullScreenPlayerView.dismiss();
|
fullScreenPlayerView.dismiss();
|
||||||
reLayoutControls();
|
reLayoutControls();
|
||||||
@ -2240,7 +2235,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
UiThreadUtil.runOnUiThread(() -> {
|
UiThreadUtil.runOnUiThread(() -> {
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, true);
|
WindowCompat.setDecorFitsSystemWindows(window, true);
|
||||||
controller.show(WindowInsetsCompat.Type.systemBars());
|
controller.show(WindowInsetsCompat.Type.systemBars());
|
||||||
eventEmitter.fullscreenDidDismiss();
|
eventEmitter.onVideoFullscreenPlayerDidDismiss.invoke();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// need to be done at the end to avoid hiding fullscreen control button when fullScreenPlayerView is shown
|
// need to be done at the end to avoid hiding fullscreen control button when fullScreenPlayerView is shown
|
||||||
@ -2291,7 +2286,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
@Override
|
@Override
|
||||||
public void onDrmSessionManagerError(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @NonNull Exception e) {
|
public void onDrmSessionManagerError(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId, @NonNull Exception e) {
|
||||||
DebugLog.d("DRM Info", "onDrmSessionManagerError");
|
DebugLog.d("DRM Info", "onDrmSessionManagerError");
|
||||||
eventEmitter.error("onDrmSessionManagerError", e, "3002");
|
eventEmitter.onVideoError.invoke("onDrmSessionManagerError", e, "3002");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2333,16 +2328,21 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
@Override
|
@Override
|
||||||
public void onAdEvent(AdEvent adEvent) {
|
public void onAdEvent(AdEvent adEvent) {
|
||||||
if (adEvent.getAdData() != null) {
|
if (adEvent.getAdData() != null) {
|
||||||
eventEmitter.receiveAdEvent(adEvent.getType().name(), adEvent.getAdData());
|
eventEmitter.onReceiveAdEvent.invoke(adEvent.getType().name(), adEvent.getAdData());
|
||||||
} else {
|
} else {
|
||||||
eventEmitter.receiveAdEvent(adEvent.getType().name());
|
eventEmitter.onReceiveAdEvent.invoke(adEvent.getType().name(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAdError(AdErrorEvent adErrorEvent) {
|
public void onAdError(AdErrorEvent adErrorEvent) {
|
||||||
AdError error = adErrorEvent.getError();
|
AdError error = adErrorEvent.getError();
|
||||||
eventEmitter.receiveAdErrorEvent(error.getMessage(), String.valueOf(error.getErrorCode()), String.valueOf(error.getErrorType()));
|
Map<String, String> errMap = Map.of(
|
||||||
|
"message", error.getMessage(),
|
||||||
|
"code", String.valueOf(error.getErrorCode()),
|
||||||
|
"type", String.valueOf(error.getErrorType())
|
||||||
|
);
|
||||||
|
eventEmitter.onReceiveAdEvent.invoke("ERROR", errMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setControlsStyles(ControlsConfig controlsStyles) {
|
public void setControlsStyles(ControlsConfig controlsStyles) {
|
||||||
|
@ -18,13 +18,12 @@ import com.brentvatne.common.api.SideLoadedTextTrackList;
|
|||||||
import com.brentvatne.common.api.Source;
|
import com.brentvatne.common.api.Source;
|
||||||
import com.brentvatne.common.api.SubtitleStyle;
|
import com.brentvatne.common.api.SubtitleStyle;
|
||||||
import com.brentvatne.common.api.ViewType;
|
import com.brentvatne.common.api.ViewType;
|
||||||
import com.brentvatne.common.react.VideoEventEmitter;
|
import com.brentvatne.common.react.EventTypes;
|
||||||
import com.brentvatne.common.toolbox.DebugLog;
|
import com.brentvatne.common.toolbox.DebugLog;
|
||||||
import com.brentvatne.common.toolbox.ReactBridgeUtils;
|
import com.brentvatne.common.toolbox.ReactBridgeUtils;
|
||||||
import com.brentvatne.react.ReactNativeVideoManager;
|
import com.brentvatne.react.ReactNativeVideoManager;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.common.MapBuilder;
|
|
||||||
import com.facebook.react.uimanager.ThemedReactContext;
|
import com.facebook.react.uimanager.ThemedReactContext;
|
||||||
import com.facebook.react.uimanager.ViewGroupManager;
|
import com.facebook.react.uimanager.ViewGroupManager;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
@ -110,11 +109,13 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
public @Nullable Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
||||||
MapBuilder.Builder<String, Object> builder = MapBuilder.builder();
|
return EventTypes.Companion.toMap();
|
||||||
for (String event : VideoEventEmitter.Events) {
|
|
||||||
builder.put(event, MapBuilder.of("registrationName", event));
|
|
||||||
}
|
}
|
||||||
return builder.build();
|
|
||||||
|
@Override
|
||||||
|
public void addEventEmitters(@NonNull ThemedReactContext reactContext, @NonNull ReactExoplayerView view) {
|
||||||
|
super.addEventEmitters(reactContext, view);
|
||||||
|
view.eventEmitter.addEventEmitters(reactContext, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_DRM)
|
@ReactProp(name = PROP_DRM)
|
||||||
|
Loading…
Reference in New Issue
Block a user