337 lines
13 KiB
Java
Raw Normal View History

2017-01-11 12:51:45 +00:00
package com.brentvatne.exoplayer;
2019-07-28 15:42:32 +02:00
import androidx.annotation.StringDef;
2017-01-11 12:51:45 +00:00
import android.view.View;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableArray;
2017-01-11 12:51:45 +00:00
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.android.exoplayer2.metadata.Metadata;
2020-08-17 16:28:36 +09:00
import com.google.android.exoplayer2.metadata.emsg.EventMessage;
import com.google.android.exoplayer2.metadata.id3.Id3Frame;
2017-03-21 20:25:17 +00:00
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
2017-01-11 12:51:45 +00:00
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.io.StringWriter;
import java.io.PrintWriter;
2017-01-11 12:51:45 +00:00
class VideoEventEmitter {
private final RCTEventEmitter eventEmitter;
private int viewId = View.NO_ID;
VideoEventEmitter(ReactContext reactContext) {
this.eventEmitter = reactContext.getJSModule(RCTEventEmitter.class);
}
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";
2018-11-01 21:41:57 +05:30
private static final String EVENT_BANDWIDTH = "onVideoBandwidthUpdate";
2017-01-11 12:51:45 +00:00
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";
2017-01-11 12:51:45 +00:00
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_BUFFER_PROGRESS = "onVideoBufferProgress";
2017-01-11 12:51:45 +00:00
private static final String EVENT_IDLE = "onVideoIdle";
private static final String EVENT_TIMED_METADATA = "onTimedMetadata";
2018-07-12 21:49:14 -07:00
private static final String EVENT_AUDIO_BECOMING_NOISY = "onVideoAudioBecomingNoisy";
2017-01-11 12:51:45 +00:00
private static final String EVENT_AUDIO_FOCUS_CHANGE = "onAudioFocusChanged";
private static final String EVENT_PLAYBACK_RATE_CHANGE = "onPlaybackRateChange";
2017-01-11 12:51:45 +00:00
static 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,
2017-01-11 12:51:45 +00:00
EVENT_STALLED,
EVENT_RESUME,
EVENT_READY,
EVENT_BUFFER,
EVENT_BUFFER_PROGRESS,
2017-01-11 12:51:45 +00:00
EVENT_IDLE,
EVENT_TIMED_METADATA,
2017-01-11 12:51:45 +00:00
EVENT_AUDIO_BECOMING_NOISY,
EVENT_AUDIO_FOCUS_CHANGE,
EVENT_PLAYBACK_RATE_CHANGE,
EVENT_BANDWIDTH,
2017-01-11 12:51:45 +00:00
};
@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,
2017-01-11 12:51:45 +00:00
EVENT_STALLED,
EVENT_RESUME,
EVENT_READY,
EVENT_BUFFER,
EVENT_BUFFER_PROGRESS,
2017-01-11 12:51:45 +00:00
EVENT_IDLE,
EVENT_TIMED_METADATA,
2017-01-11 12:51:45 +00:00
EVENT_AUDIO_BECOMING_NOISY,
EVENT_AUDIO_FOCUS_CHANGE,
EVENT_PLAYBACK_RATE_CHANGE,
EVENT_BANDWIDTH,
2017-01-11 12:51:45 +00:00
})
@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_BUFFER_START = "bufferStart";
private static final String EVENT_PROP_BUFFER_END = "bufferEnd";
2017-01-11 12:51:45 +00:00
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";
2017-01-11 12:51:45 +00:00
private static final String EVENT_PROP_CURRENT_TIME = "currentTime";
2020-05-15 12:55:19 +05:30
private static final String EVENT_PROP_CURRENT_PLAYBACK_TIME = "currentPlaybackTime";
2017-01-11 12:51:45 +00:00
private static final String EVENT_PROP_SEEK_TIME = "seekTime";
private static final String EVENT_PROP_NATURAL_SIZE = "naturalSize";
2020-05-15 12:55:19 +05:30
private static final String EVENT_PROP_TRACK_ID = "trackId";
2017-01-11 12:51:45 +00:00
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";
2017-01-11 12:51:45 +00:00
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";
2017-01-11 12:51:45 +00:00
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";
2017-01-11 12:51:45 +00:00
private static final String EVENT_PROP_TIMED_METADATA = "metadata";
private static final String EVENT_PROP_BITRATE = "bitrate";
2017-01-11 12:51:45 +00:00
void setViewId(int viewId) {
this.viewId = viewId;
}
void loadStart() {
receiveEvent(EVENT_LOAD_START, null);
}
void load(double duration, double currentPosition, int videoWidth, int videoHeight,
2020-05-15 12:55:19 +05:30
WritableArray audioTracks, WritableArray textTracks, WritableArray videoTracks, String trackId) {
2017-01-11 12:51:45 +00:00
WritableMap event = Arguments.createMap();
event.putDouble(EVENT_PROP_DURATION, duration / 1000D);
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
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 {
naturalSize.putString(EVENT_PROP_ORIENTATION, "portrait");
}
event.putMap(EVENT_PROP_NATURAL_SIZE, naturalSize);
2020-05-15 12:55:19 +05:30
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);
2017-01-11 12:51:45 +00:00
// 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);
}
2020-05-15 12:55:19 +05:30
void progressChanged(double currentPosition, double bufferedDuration, double seekableDuration, double currentPlaybackTime) {
2017-01-11 12:51:45 +00:00
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);
2020-05-15 12:55:19 +05:30
event.putDouble(EVENT_PROP_CURRENT_PLAYBACK_TIME, currentPlaybackTime);
2017-01-11 12:51:45 +00:00
receiveEvent(EVENT_PROGRESS, event);
}
2020-05-15 12:55:19 +05:30
void bandwidthReport(double bitRateEstimate, int height, int width, String id) {
WritableMap event = Arguments.createMap();
2018-12-31 22:08:18 -08:00
event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate);
2020-05-15 12:55:19 +05:30
event.putInt(EVENT_PROP_WIDTH, width);
event.putInt(EVENT_PROP_HEIGHT, height);
event.putString(EVENT_PROP_TRACK_ID, id);
receiveEvent(EVENT_BANDWIDTH, event);
}
2017-01-11 12:51:45 +00:00
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);
}
void ready() {
receiveEvent(EVENT_READY, null);
}
void buffering(boolean isBuffering) {
WritableMap map = Arguments.createMap();
map.putBoolean(EVENT_PROP_IS_BUFFERING, isBuffering);
receiveEvent(EVENT_BUFFER, map);
}
void bufferProgress(double start, double end) {
WritableMap map = Arguments.createMap();
map.putDouble(EVENT_PROP_BUFFER_START, start);
map.putDouble(EVENT_PROP_BUFFER_END, end);
receiveEvent(EVENT_BUFFER_PROGRESS, map);
}
2017-01-11 12:51:45 +00:00
void idle() {
receiveEvent(EVENT_IDLE, null);
}
void end() {
receiveEvent(EVENT_END, null);
}
void fullscreenWillPresent() {
receiveEvent(EVENT_FULLSCREEN_WILL_PRESENT, null);
}
void fullscreenDidPresent() {
receiveEvent(EVENT_FULLSCREEN_DID_PRESENT, null);
}
void fullscreenWillDismiss() {
receiveEvent(EVENT_FULLSCREEN_WILL_DISMISS, null);
}
void fullscreenDidDismiss() {
receiveEvent(EVENT_FULLSCREEN_DID_DISMISS, null);
}
2017-01-11 12:51:45 +00:00
void error(String errorString, Exception exception) {
_error(errorString, exception, "0001");
}
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();
2017-01-11 12:51:45 +00:00
WritableMap error = Arguments.createMap();
error.putString(EVENT_PROP_ERROR_STRING, errorString);
2020-05-15 12:55:19 +05:30
error.putString(EVENT_PROP_ERROR_EXCEPTION, exception.toString());
error.putString(EVENT_PROP_ERROR_CODE, errorCode);
error.putString(EVENT_PROP_ERROR_TRACE, stackTrace);
2017-01-11 12:51:45 +00:00
WritableMap event = Arguments.createMap();
event.putMap(EVENT_PROP_ERROR, error);
receiveEvent(EVENT_ERROR, event);
}
void playbackRateChange(float rate) {
WritableMap map = Arguments.createMap();
map.putDouble(EVENT_PROP_PLAYBACK_RATE, (double)rate);
receiveEvent(EVENT_PLAYBACK_RATE_CHANGE, map);
}
void timedMetadata(Metadata metadata) {
WritableArray metadataArray = Arguments.createArray();
for (int i = 0; i < metadata.length(); i++) {
2020-08-17 16:28:36 +09:00
Metadata.Entry entry = metadata.get(i);
2020-08-17 16:28:36 +09:00
if (entry instanceof Id3Frame) {
2020-08-17 16:28:36 +09:00
Id3Frame frame = (Id3Frame) entry;
2020-08-17 16:28:36 +09:00
String value = "";
2020-08-17 16:28:36 +09:00
if (frame instanceof TextInformationFrame) {
TextInformationFrame txxxFrame = (TextInformationFrame) frame;
value = txxxFrame.value;
}
2020-08-17 16:28:36 +09:00
String identifier = frame.id;
2020-08-17 16:28:36 +09:00
WritableMap map = Arguments.createMap();
map.putString("identifier", identifier);
map.putString("value", value);
2020-08-17 16:28:36 +09:00
metadataArray.pushMap(map);
} else if (entry instanceof EventMessage) {
EventMessage eventMessage = (EventMessage) entry;
WritableMap map = Arguments.createMap();
map.putString("identifier", eventMessage.schemeIdUri);
map.putString("value", eventMessage.value);
metadataArray.pushMap(map);
}
}
WritableMap event = Arguments.createMap();
event.putArray(EVENT_PROP_TIMED_METADATA, metadataArray);
receiveEvent(EVENT_TIMED_METADATA, event);
}
2017-01-11 12:51:45 +00:00
void audioFocusChanged(boolean hasFocus) {
WritableMap map = Arguments.createMap();
map.putBoolean(EVENT_PROP_HAS_AUDIO_FOCUS, hasFocus);
receiveEvent(EVENT_AUDIO_FOCUS_CHANGE, map);
}
void audioBecomingNoisy() {
receiveEvent(EVENT_AUDIO_BECOMING_NOISY, null);
}
private void receiveEvent(@VideoEvents String type, WritableMap event) {
eventEmitter.receiveEvent(viewId, type, event);
}
}