From 74c6dd62797fb1d29e0f03b5483f57fa065e8d93 Mon Sep 17 00:00:00 2001 From: Seyed Mostafa Hasani Date: Fri, 2 Aug 2024 12:22:08 +0330 Subject: [PATCH] refactor(android): migrate ReactExoplayerViewManager to Kotlin (#4011) * Rename .java to .kt * refactor(android): migrate ReactExoplayerViewManager to Kotlin * fix: lint error * refactor: setPreventsDisplaySleepDuringVideoPlayback function --- .../exoplayer/ReactExoplayerViewManager.java | 346 ------------------ .../exoplayer/ReactExoplayerViewManager.kt | 312 ++++++++++++++++ .../react/ReactNativeVideoManager.kt | 18 +- 3 files changed, 320 insertions(+), 356 deletions(-) delete mode 100644 android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java create mode 100644 android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.kt diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java deleted file mode 100644 index e9ae70bc..00000000 --- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ /dev/null @@ -1,346 +0,0 @@ -package com.brentvatne.exoplayer; - -import android.content.Context; -import android.graphics.Color; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.brentvatne.common.api.BufferConfig; -import com.brentvatne.common.api.BufferingStrategy; -import com.brentvatne.common.api.ControlsConfig; -import com.brentvatne.common.api.DRMProps; -import com.brentvatne.common.api.ResizeMode; -import com.brentvatne.common.api.SideLoadedTextTrackList; -import com.brentvatne.common.api.Source; -import com.brentvatne.common.api.SubtitleStyle; -import com.brentvatne.common.api.ViewType; -import com.brentvatne.common.react.EventTypes; -import com.brentvatne.common.toolbox.DebugLog; -import com.brentvatne.common.toolbox.ReactBridgeUtils; -import com.brentvatne.react.ReactNativeVideoManager; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.annotations.ReactProp; - -import java.util.Map; - -import javax.annotation.Nullable; - -public class ReactExoplayerViewManager extends ViewGroupManager { - - private static final String TAG = "ExoViewManager"; - private static final String REACT_CLASS = "RCTVideo"; - private static final String PROP_SRC = "src"; - private static final String PROP_AD_TAG_URL = "adTagUrl"; - private static final String PROP_RESIZE_MODE = "resizeMode"; - private static final String PROP_REPEAT = "repeat"; - private static final String PROP_SELECTED_AUDIO_TRACK = "selectedAudioTrack"; - private static final String PROP_SELECTED_AUDIO_TRACK_TYPE = "type"; - private static final String PROP_SELECTED_AUDIO_TRACK_VALUE = "value"; - private static final String PROP_SELECTED_TEXT_TRACK = "selectedTextTrack"; - private static final String PROP_SELECTED_TEXT_TRACK_TYPE = "type"; - private static final String PROP_SELECTED_TEXT_TRACK_VALUE = "value"; - private static final String PROP_TEXT_TRACKS = "textTracks"; - private static final String PROP_PAUSED = "paused"; - private static final String PROP_MUTED = "muted"; - private static final String PROP_AUDIO_OUTPUT = "audioOutput"; - private static final String PROP_VOLUME = "volume"; - private static final String PROP_BUFFER_CONFIG = "bufferConfig"; - private static final String PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = "preventsDisplaySleepDuringVideoPlayback"; - private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval"; - private static final String PROP_REPORT_BANDWIDTH = "reportBandwidth"; - private static final String PROP_RATE = "rate"; - private static final String PROP_MIN_LOAD_RETRY_COUNT = "minLoadRetryCount"; - private static final String PROP_MAXIMUM_BIT_RATE = "maxBitRate"; - private static final String PROP_PLAY_IN_BACKGROUND = "playInBackground"; - private static final String PROP_CONTENT_START_TIME = "contentStartTime"; - private static final String PROP_DISABLE_FOCUS = "disableFocus"; - private static final String PROP_BUFFERING_STRATEGY = "bufferingStrategy"; - private static final String PROP_DISABLE_DISCONNECT_ERROR = "disableDisconnectError"; - private static final String PROP_FOCUSABLE = "focusable"; - private static final String PROP_FULLSCREEN = "fullscreen"; - private static final String PROP_VIEW_TYPE = "viewType"; - private static final String PROP_SELECTED_VIDEO_TRACK = "selectedVideoTrack"; - private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type"; - private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value"; - 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 static final String PROP_SHUTTER_COLOR = "shutterColor"; - private static final String PROP_SHOW_NOTIFICATION_CONTROLS = "showNotificationControls"; - private static final String PROP_DEBUG = "debug"; - private static final String PROP_CONTROLS_STYLES = "controlsStyles"; - - private final ReactExoplayerConfig config; - - public ReactExoplayerViewManager(ReactExoplayerConfig config) { - this.config = config; - } - - @NonNull - @Override - public String getName() { - return REACT_CLASS; - } - - @NonNull - @Override - protected ReactExoplayerView createViewInstance(@NonNull ThemedReactContext themedReactContext) { - ReactNativeVideoManager.Companion.getInstance().registerView(this); - return new ReactExoplayerView(themedReactContext, config); - } - - @Override - public void onDropViewInstance(ReactExoplayerView view) { - view.cleanUpResources(); - ReactNativeVideoManager.Companion.getInstance().unregisterView(this); - } - - @Override - public @Nullable Map getExportedCustomDirectEventTypeConstants() { - return EventTypes.Companion.toMap(); - } - - @Override - public void addEventEmitters(@NonNull ThemedReactContext reactContext, @NonNull ReactExoplayerView view) { - super.addEventEmitters(reactContext, view); - view.eventEmitter.addEventEmitters(reactContext, view); - } - - @ReactProp(name = PROP_SRC) - public void setSrc(final ReactExoplayerView videoView, @Nullable ReadableMap src) { - Context context = videoView.getContext().getApplicationContext(); - Source source = Source.parse(src, context); - if (source.getUri() == null) { - videoView.clearSrc(); - } else { - videoView.setSrc(source); - } - } - - @ReactProp(name = PROP_AD_TAG_URL) - public void setAdTagUrl(final ReactExoplayerView videoView, final String uriString) { - if (TextUtils.isEmpty(uriString)) { - videoView.setAdTagUrl(null); - return; - } - - Uri adTagUrl = Uri.parse(uriString); - - videoView.setAdTagUrl(adTagUrl); - } - - @ReactProp(name = PROP_RESIZE_MODE) - public void setResizeMode(final ReactExoplayerView videoView, final String resizeMode) { - switch (resizeMode) { - case "none": - case "contain": - videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_FIT); - break; - case "cover": - videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_CENTER_CROP); - break; - case "stretch": - videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_FILL); - break; - default: - DebugLog.w(TAG, "Unsupported resize mode: " + resizeMode + " - falling back to fit"); - videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_FIT); - break; - } - } - - @ReactProp(name = PROP_REPEAT, defaultBoolean = false) - public void setRepeat(final ReactExoplayerView videoView, final boolean repeat) { - videoView.setRepeatModifier(repeat); - } - - @ReactProp(name = PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK, defaultBoolean = false) - public void setPreventsDisplaySleepDuringVideoPlayback(final ReactExoplayerView videoView, final boolean preventsSleep) { - videoView.setPreventsDisplaySleepDuringVideoPlayback(preventsSleep); - } - - @ReactProp(name = PROP_SELECTED_VIDEO_TRACK) - public void setSelectedVideoTrack(final ReactExoplayerView videoView, - @Nullable ReadableMap selectedVideoTrack) { - String typeString = null; - String value = null; - if (selectedVideoTrack != null) { - typeString = ReactBridgeUtils.safeGetString(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_TYPE); - value = ReactBridgeUtils.safeGetString(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_VALUE); - } - videoView.setSelectedVideoTrack(typeString, value); - } - - @ReactProp(name = PROP_SELECTED_AUDIO_TRACK) - public void setSelectedAudioTrack(final ReactExoplayerView videoView, - @Nullable ReadableMap selectedAudioTrack) { - String typeString = null; - String value = null; - if (selectedAudioTrack != null) { - typeString = ReactBridgeUtils.safeGetString(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_TYPE); - value = ReactBridgeUtils.safeGetString(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_VALUE); - } - videoView.setSelectedAudioTrack(typeString, value); - } - - @ReactProp(name = PROP_SELECTED_TEXT_TRACK) - public void setSelectedTextTrack(final ReactExoplayerView videoView, - @Nullable ReadableMap selectedTextTrack) { - String typeString = null; - String value = null; - if (selectedTextTrack != null) { - typeString = ReactBridgeUtils.safeGetString(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_TYPE); - value = ReactBridgeUtils.safeGetString(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_VALUE); - } - videoView.setSelectedTextTrack(typeString, value); - } - - @ReactProp(name = PROP_TEXT_TRACKS) - public void setTextTracks(final ReactExoplayerView videoView, - @Nullable ReadableArray textTracks) { - SideLoadedTextTrackList sideLoadedTextTracks = SideLoadedTextTrackList.Companion.parse(textTracks); - videoView.setTextTracks(sideLoadedTextTracks); - } - - @ReactProp(name = PROP_PAUSED, defaultBoolean = false) - public void setPaused(final ReactExoplayerView videoView, final boolean paused) { - videoView.setPausedModifier(paused); - } - - @ReactProp(name = PROP_MUTED, defaultBoolean = false) - public void setMuted(final ReactExoplayerView videoView, final boolean muted) { - videoView.setMutedModifier(muted); - } - - @ReactProp(name = PROP_AUDIO_OUTPUT) - public void setAudioOutput(final ReactExoplayerView videoView, final String audioOutput) { - videoView.setAudioOutput(AudioOutput.get(audioOutput)); - } - - @ReactProp(name = PROP_VOLUME, defaultFloat = 1.0f) - public void setVolume(final ReactExoplayerView videoView, final float volume) { - videoView.setVolumeModifier(volume); - } - - @ReactProp(name = PROP_PROGRESS_UPDATE_INTERVAL, defaultFloat = 250.0f) - public void setProgressUpdateInterval(final ReactExoplayerView videoView, final float progressUpdateInterval) { - videoView.setProgressUpdateInterval(progressUpdateInterval); - } - - @ReactProp(name = PROP_REPORT_BANDWIDTH, defaultBoolean = false) - public void setReportBandwidth(final ReactExoplayerView videoView, final boolean reportBandwidth) { - videoView.setReportBandwidth(reportBandwidth); - } - - @ReactProp(name = PROP_RATE) - public void setRate(final ReactExoplayerView videoView, final float rate) { - videoView.setRateModifier(rate); - } - - @ReactProp(name = PROP_MAXIMUM_BIT_RATE) - public void setMaxBitRate(final ReactExoplayerView videoView, final float maxBitRate) { - videoView.setMaxBitRateModifier((int)maxBitRate); - } - - @ReactProp(name = PROP_MIN_LOAD_RETRY_COUNT) - public void setMinLoadRetryCount(final ReactExoplayerView videoView, final int minLoadRetryCount) { - videoView.setMinLoadRetryCountModifier(minLoadRetryCount); - } - - @ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false) - public void setPlayInBackground(final ReactExoplayerView videoView, final boolean playInBackground) { - videoView.setPlayInBackground(playInBackground); - } - - @ReactProp(name = PROP_DISABLE_FOCUS, defaultBoolean = false) - public void setDisableFocus(final ReactExoplayerView videoView, final boolean disableFocus) { - videoView.setDisableFocus(disableFocus); - } - - @ReactProp(name = PROP_FOCUSABLE, defaultBoolean = true) - public void setFocusable(final ReactExoplayerView videoView, final boolean focusable) { - videoView.setFocusable(focusable); - } - - @ReactProp(name = PROP_CONTENT_START_TIME, defaultInt = -1) - public void setContentStartTime(final ReactExoplayerView videoView, final int contentStartTime) { - videoView.setContentStartTime(contentStartTime); - } - - @ReactProp(name = PROP_BUFFERING_STRATEGY) - public void setBufferingStrategy(final ReactExoplayerView videoView, final String bufferingStrategy) { - BufferingStrategy.BufferingStrategyEnum strategy = BufferingStrategy.Companion.parse(bufferingStrategy); - videoView.setBufferingStrategy(strategy); - } - - @ReactProp(name = PROP_DISABLE_DISCONNECT_ERROR, defaultBoolean = false) - public void setDisableDisconnectError(final ReactExoplayerView videoView, final boolean disableDisconnectError) { - videoView.setDisableDisconnectError(disableDisconnectError); - } - - @ReactProp(name = PROP_FULLSCREEN, defaultBoolean = false) - public void setFullscreen(final ReactExoplayerView videoView, final boolean fullscreen) { - videoView.setFullscreen(fullscreen); - } - - @ReactProp(name = PROP_VIEW_TYPE, defaultInt = ViewType.VIEW_TYPE_SURFACE) - public void setViewType(final ReactExoplayerView videoView, final int viewType) { - videoView.setViewType(viewType); - } - - @ReactProp(name = PROP_HIDE_SHUTTER_VIEW, defaultBoolean = false) - public void setHideShutterView(final ReactExoplayerView videoView, final boolean hideShutterView) { - videoView.setHideShutterView(hideShutterView); - } - - @ReactProp(name = PROP_CONTROLS, defaultBoolean = false) - public void setControls(final ReactExoplayerView videoView, final boolean controls) { - 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_SHUTTER_COLOR, defaultInt = 0) - public void setShutterColor(final ReactExoplayerView videoView, final int color) { - videoView.setShutterColor(color == 0 ? Color.BLACK : color); - } - - @ReactProp(name = PROP_BUFFER_CONFIG) - public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) { - BufferConfig config = BufferConfig.parse(bufferConfig); - videoView.setBufferConfig(config); - } - - @ReactProp(name = PROP_SHOW_NOTIFICATION_CONTROLS) - public void setShowNotificationControls(final ReactExoplayerView videoView, final boolean showNotificationControls) { - videoView.setShowNotificationControls(showNotificationControls); - } - - @ReactProp(name = PROP_DEBUG, defaultBoolean = false) - public void setDebug(final ReactExoplayerView videoView, - @Nullable final ReadableMap debugConfig) { - boolean enableDebug = ReactBridgeUtils.safeGetBool(debugConfig, "enable", false); - boolean enableThreadDebug = ReactBridgeUtils.safeGetBool(debugConfig, "thread", false); - if (enableDebug) { - DebugLog.setConfig(Log.VERBOSE, enableThreadDebug); - } else { - DebugLog.setConfig(Log.WARN, enableThreadDebug); - } - videoView.setDebug(enableDebug); - } - - @ReactProp(name = PROP_CONTROLS_STYLES) - public void setControlsStyles(final ReactExoplayerView videoView, @Nullable ReadableMap controlsStyles) { - ControlsConfig controlsConfig = ControlsConfig.parse(controlsStyles); - videoView.setControlsStyles(controlsConfig); - } -} \ No newline at end of file diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.kt b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.kt new file mode 100644 index 00000000..8299c345 --- /dev/null +++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.kt @@ -0,0 +1,312 @@ +package com.brentvatne.exoplayer + +import android.graphics.Color +import android.net.Uri +import android.text.TextUtils +import android.util.Log +import com.brentvatne.common.api.BufferConfig +import com.brentvatne.common.api.BufferingStrategy +import com.brentvatne.common.api.ControlsConfig +import com.brentvatne.common.api.ResizeMode +import com.brentvatne.common.api.SideLoadedTextTrackList +import com.brentvatne.common.api.Source +import com.brentvatne.common.api.SubtitleStyle +import com.brentvatne.common.api.ViewType +import com.brentvatne.common.react.EventTypes +import com.brentvatne.common.toolbox.DebugLog +import com.brentvatne.common.toolbox.ReactBridgeUtils +import com.brentvatne.react.ReactNativeVideoManager +import com.facebook.react.bridge.ReadableArray +import com.facebook.react.bridge.ReadableMap +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.ViewGroupManager +import com.facebook.react.uimanager.annotations.ReactProp + +class ReactExoplayerViewManager(private val config: ReactExoplayerConfig) : ViewGroupManager() { + + companion object { + private const val TAG = "ExoViewManager" + private const val REACT_CLASS = "RCTVideo" + private const val PROP_SRC = "src" + private const val PROP_AD_TAG_URL = "adTagUrl" + private const val PROP_RESIZE_MODE = "resizeMode" + private const val PROP_REPEAT = "repeat" + private const val PROP_SELECTED_AUDIO_TRACK = "selectedAudioTrack" + private const val PROP_SELECTED_AUDIO_TRACK_TYPE = "type" + private const val PROP_SELECTED_AUDIO_TRACK_VALUE = "value" + private const val PROP_SELECTED_TEXT_TRACK = "selectedTextTrack" + private const val PROP_SELECTED_TEXT_TRACK_TYPE = "type" + private const val PROP_SELECTED_TEXT_TRACK_VALUE = "value" + private const val PROP_TEXT_TRACKS = "textTracks" + private const val PROP_PAUSED = "paused" + private const val PROP_MUTED = "muted" + private const val PROP_AUDIO_OUTPUT = "audioOutput" + private const val PROP_VOLUME = "volume" + private const val PROP_BUFFER_CONFIG = "bufferConfig" + private const val PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK = + "preventsDisplaySleepDuringVideoPlayback" + private const val PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval" + private const val PROP_REPORT_BANDWIDTH = "reportBandwidth" + private const val PROP_RATE = "rate" + private const val PROP_MIN_LOAD_RETRY_COUNT = "minLoadRetryCount" + private const val PROP_MAXIMUM_BIT_RATE = "maxBitRate" + private const val PROP_PLAY_IN_BACKGROUND = "playInBackground" + private const val PROP_CONTENT_START_TIME = "contentStartTime" + private const val PROP_DISABLE_FOCUS = "disableFocus" + private const val PROP_BUFFERING_STRATEGY = "bufferingStrategy" + private const val PROP_DISABLE_DISCONNECT_ERROR = "disableDisconnectError" + private const val PROP_FOCUSABLE = "focusable" + private const val PROP_FULLSCREEN = "fullscreen" + private const val PROP_VIEW_TYPE = "viewType" + private const val PROP_SELECTED_VIDEO_TRACK = "selectedVideoTrack" + private const val PROP_SELECTED_VIDEO_TRACK_TYPE = "type" + private const val PROP_SELECTED_VIDEO_TRACK_VALUE = "value" + private const val PROP_HIDE_SHUTTER_VIEW = "hideShutterView" + private const val PROP_CONTROLS = "controls" + private const val PROP_SUBTITLE_STYLE = "subtitleStyle" + private const val PROP_SHUTTER_COLOR = "shutterColor" + private const val PROP_SHOW_NOTIFICATION_CONTROLS = "showNotificationControls" + private const val PROP_DEBUG = "debug" + private const val PROP_CONTROLS_STYLES = "controlsStyles" + } + + override fun getName(): String = REACT_CLASS + + override fun createViewInstance(themedReactContext: ThemedReactContext): ReactExoplayerView { + ReactNativeVideoManager.getInstance().registerView(this) + return ReactExoplayerView(themedReactContext, config) + } + + override fun onDropViewInstance(view: ReactExoplayerView) { + view.cleanUpResources() + ReactNativeVideoManager.getInstance().unregisterView(this) + } + + override fun getExportedCustomDirectEventTypeConstants(): Map = EventTypes.toMap() + + override fun addEventEmitters(reactContext: ThemedReactContext, view: ReactExoplayerView) { + super.addEventEmitters(reactContext, view) + view.eventEmitter.addEventEmitters(reactContext, view) + } + + @ReactProp(name = PROP_SRC) + fun setSrc(videoView: ReactExoplayerView, src: ReadableMap?) { + val context = videoView.context.applicationContext + val source = Source.parse(src, context) + if (source.uri == null) { + videoView.clearSrc() + } else { + videoView.setSrc(source) + } + } + + @ReactProp(name = PROP_AD_TAG_URL) + fun setAdTagUrl(videoView: ReactExoplayerView, uriString: String?) { + if (TextUtils.isEmpty(uriString)) { + videoView.setAdTagUrl(null) + return + } + val adTagUrl = Uri.parse(uriString) + videoView.setAdTagUrl(adTagUrl) + } + + @ReactProp(name = PROP_RESIZE_MODE) + fun setResizeMode(videoView: ReactExoplayerView, resizeMode: String) { + when (resizeMode) { + "none", "contain" -> videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_FIT) + + "cover" -> videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_CENTER_CROP) + + "stretch" -> videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_FILL) + + else -> { + DebugLog.w(TAG, "Unsupported resize mode: $resizeMode - falling back to fit") + videoView.setResizeModeModifier(ResizeMode.RESIZE_MODE_FIT) + } + } + } + + @ReactProp(name = PROP_REPEAT, defaultBoolean = false) + fun setRepeat(videoView: ReactExoplayerView, repeat: Boolean) { + videoView.setRepeatModifier(repeat) + } + + @ReactProp(name = PROP_PREVENTS_DISPLAY_SLEEP_DURING_VIDEO_PLAYBACK, defaultBoolean = false) + fun setPreventsDisplaySleepDuringVideoPlayback(videoView: ReactExoplayerView, preventsSleep: Boolean) { + videoView.preventsDisplaySleepDuringVideoPlayback = preventsSleep + } + + @ReactProp(name = PROP_SELECTED_VIDEO_TRACK) + fun setSelectedVideoTrack(videoView: ReactExoplayerView, selectedVideoTrack: ReadableMap?) { + var typeString: String? = null + var value: String? = null + if (selectedVideoTrack != null) { + typeString = ReactBridgeUtils.safeGetString(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_TYPE) + value = ReactBridgeUtils.safeGetString(selectedVideoTrack, PROP_SELECTED_VIDEO_TRACK_VALUE) + } + videoView.setSelectedVideoTrack(typeString, value) + } + + @ReactProp(name = PROP_SELECTED_AUDIO_TRACK) + fun setSelectedAudioTrack(videoView: ReactExoplayerView, selectedAudioTrack: ReadableMap?) { + var typeString: String? = null + var value: String? = null + if (selectedAudioTrack != null) { + typeString = ReactBridgeUtils.safeGetString(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_TYPE) + value = ReactBridgeUtils.safeGetString(selectedAudioTrack, PROP_SELECTED_AUDIO_TRACK_VALUE) + } + videoView.setSelectedAudioTrack(typeString, value) + } + + @ReactProp(name = PROP_SELECTED_TEXT_TRACK) + fun setSelectedTextTrack(videoView: ReactExoplayerView, selectedTextTrack: ReadableMap?) { + var typeString: String? = null + var value: String? = null + if (selectedTextTrack != null) { + typeString = ReactBridgeUtils.safeGetString(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_TYPE) + value = ReactBridgeUtils.safeGetString(selectedTextTrack, PROP_SELECTED_TEXT_TRACK_VALUE) + } + videoView.setSelectedTextTrack(typeString, value) + } + + @ReactProp(name = PROP_TEXT_TRACKS) + fun setTextTracks(videoView: ReactExoplayerView, textTracks: ReadableArray?) { + val sideLoadedTextTracks = SideLoadedTextTrackList.parse(textTracks) + videoView.setTextTracks(sideLoadedTextTracks) + } + + @ReactProp(name = PROP_PAUSED, defaultBoolean = false) + fun setPaused(videoView: ReactExoplayerView, paused: Boolean) { + videoView.setPausedModifier(paused) + } + + @ReactProp(name = PROP_MUTED, defaultBoolean = false) + fun setMuted(videoView: ReactExoplayerView, muted: Boolean) { + videoView.setMutedModifier(muted) + } + + @ReactProp(name = PROP_AUDIO_OUTPUT) + fun setAudioOutput(videoView: ReactExoplayerView, audioOutput: String) { + videoView.setAudioOutput(AudioOutput.get(audioOutput)) + } + + @ReactProp(name = PROP_VOLUME, defaultFloat = 1.0f) + fun setVolume(videoView: ReactExoplayerView, volume: Float) { + videoView.setVolumeModifier(volume) + } + + @ReactProp(name = PROP_PROGRESS_UPDATE_INTERVAL, defaultFloat = 250.0f) + fun setProgressUpdateInterval(videoView: ReactExoplayerView, progressUpdateInterval: Float) { + videoView.setProgressUpdateInterval(progressUpdateInterval) + } + + @ReactProp(name = PROP_REPORT_BANDWIDTH, defaultBoolean = false) + fun setReportBandwidth(videoView: ReactExoplayerView, reportBandwidth: Boolean) { + videoView.setReportBandwidth(reportBandwidth) + } + + @ReactProp(name = PROP_RATE) + fun setRate(videoView: ReactExoplayerView, rate: Float) { + videoView.setRateModifier(rate) + } + + @ReactProp(name = PROP_MAXIMUM_BIT_RATE) + fun setMaxBitRate(videoView: ReactExoplayerView, maxBitRate: Float) { + videoView.setMaxBitRateModifier(maxBitRate.toInt()) + } + + @ReactProp(name = PROP_MIN_LOAD_RETRY_COUNT) + fun setMinLoadRetryCount(videoView: ReactExoplayerView, minLoadRetryCount: Int) { + videoView.setMinLoadRetryCountModifier(minLoadRetryCount) + } + + @ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false) + fun setPlayInBackground(videoView: ReactExoplayerView, playInBackground: Boolean) { + videoView.setPlayInBackground(playInBackground) + } + + @ReactProp(name = PROP_DISABLE_FOCUS, defaultBoolean = false) + fun setDisableFocus(videoView: ReactExoplayerView, disableFocus: Boolean) { + videoView.setDisableFocus(disableFocus) + } + + @ReactProp(name = PROP_FOCUSABLE, defaultBoolean = true) + fun setFocusable(videoView: ReactExoplayerView, focusable: Boolean) { + videoView.setFocusable(focusable) + } + + @ReactProp(name = PROP_CONTENT_START_TIME, defaultInt = -1) + fun setContentStartTime(videoView: ReactExoplayerView, contentStartTime: Int) { + videoView.setContentStartTime(contentStartTime) + } + + @ReactProp(name = PROP_BUFFERING_STRATEGY) + fun setBufferingStrategy(videoView: ReactExoplayerView, bufferingStrategy: String) { + val strategy = BufferingStrategy.parse(bufferingStrategy) + videoView.setBufferingStrategy(strategy) + } + + @ReactProp(name = PROP_DISABLE_DISCONNECT_ERROR, defaultBoolean = false) + fun setDisableDisconnectError(videoView: ReactExoplayerView, disableDisconnectError: Boolean) { + videoView.setDisableDisconnectError(disableDisconnectError) + } + + @ReactProp(name = PROP_FULLSCREEN, defaultBoolean = false) + fun setFullscreen(videoView: ReactExoplayerView, fullscreen: Boolean) { + videoView.setFullscreen(fullscreen) + } + + @ReactProp(name = PROP_VIEW_TYPE, defaultInt = ViewType.VIEW_TYPE_SURFACE) + fun setViewType(videoView: ReactExoplayerView, viewType: Int) { + videoView.setViewType(viewType) + } + + @ReactProp(name = PROP_HIDE_SHUTTER_VIEW, defaultBoolean = false) + fun setHideShutterView(videoView: ReactExoplayerView, hideShutterView: Boolean) { + videoView.setHideShutterView(hideShutterView) + } + + @ReactProp(name = PROP_CONTROLS, defaultBoolean = false) + fun setControls(videoView: ReactExoplayerView, controls: Boolean) { + videoView.setControls(controls) + } + + @ReactProp(name = PROP_SUBTITLE_STYLE) + fun setSubtitleStyle(videoView: ReactExoplayerView, src: ReadableMap?) { + videoView.setSubtitleStyle(SubtitleStyle.parse(src)) + } + + @ReactProp(name = PROP_SHUTTER_COLOR, defaultInt = 0) + fun setShutterColor(videoView: ReactExoplayerView, color: Int) { + videoView.setShutterColor(if (color == 0) Color.BLACK else color) + } + + @ReactProp(name = PROP_BUFFER_CONFIG) + fun setBufferConfig(videoView: ReactExoplayerView, bufferConfig: ReadableMap?) { + val config = BufferConfig.parse(bufferConfig) + videoView.setBufferConfig(config) + } + + @ReactProp(name = PROP_SHOW_NOTIFICATION_CONTROLS) + fun setShowNotificationControls(videoView: ReactExoplayerView, showNotificationControls: Boolean) { + videoView.setShowNotificationControls(showNotificationControls) + } + + @ReactProp(name = PROP_DEBUG, defaultBoolean = false) + fun setDebug(videoView: ReactExoplayerView, debugConfig: ReadableMap?) { + val enableDebug = ReactBridgeUtils.safeGetBool(debugConfig, "enable", false) + val enableThreadDebug = ReactBridgeUtils.safeGetBool(debugConfig, "thread", false) + if (enableDebug) { + DebugLog.setConfig(Log.VERBOSE, enableThreadDebug) + } else { + DebugLog.setConfig(Log.WARN, enableThreadDebug) + } + videoView.setDebug(enableDebug) + } + + @ReactProp(name = PROP_CONTROLS_STYLES) + fun setControlsStyles(videoView: ReactExoplayerView, controlsStyles: ReadableMap?) { + val controlsConfig = ControlsConfig.parse(controlsStyles) + videoView.setControlsStyles(controlsConfig) + } +} diff --git a/android/src/main/java/com/brentvatne/react/ReactNativeVideoManager.kt b/android/src/main/java/com/brentvatne/react/ReactNativeVideoManager.kt index d2792643..73a4f10c 100644 --- a/android/src/main/java/com/brentvatne/react/ReactNativeVideoManager.kt +++ b/android/src/main/java/com/brentvatne/react/ReactNativeVideoManager.kt @@ -29,21 +29,19 @@ class ReactNativeVideoManager : RNVPlugin { /** * register a new ReactExoplayerViewManager in the managed list */ - fun registerView(newInstance: ReactExoplayerViewManager): () -> Boolean = - { - if (instanceList.size > 2) { - DebugLog.d(TAG, "multiple Video displayed ?") - } - instanceList.add(newInstance) + fun registerView(newInstance: ReactExoplayerViewManager) { + if (instanceList.size > 2) { + DebugLog.d(TAG, "multiple Video displayed ?") } + instanceList.add(newInstance) + } /** * unregister existing ReactExoplayerViewManager in the managed list */ - fun unregisterView(newInstance: ReactExoplayerViewManager): () -> Boolean = - { - instanceList.remove(newInstance) - } + fun unregisterView(newInstance: ReactExoplayerViewManager) { + instanceList.remove(newInstance) + } /** * register a new plugin in the managed list