From d69a73db44ba1a400a89adb3641cd272f830fec1 Mon Sep 17 00:00:00 2001 From: HUI Date: Sun, 27 Sep 2020 22:52:55 +0800 Subject: [PATCH] android finished --- Annotations.java | 84 ++-- BeanCovertor.kt | 8 + EnumCovertor.kt | 10 + RtcChannel.kt | 354 +++++++++++------ RtcChannelEvent.kt | 32 +- RtcEngine.kt | 943 +++++++++++++++++++++++++++++++++------------ RtcEngineEvent.kt | 46 ++- RtcSurfaceView.kt | 3 +- RtcTextureView.kt | 66 ++-- 9 files changed, 1123 insertions(+), 423 deletions(-) diff --git a/Annotations.java b/Annotations.java index d1e6fd652..d087693d8 100644 --- a/Annotations.java +++ b/Annotations.java @@ -1,18 +1,17 @@ package io.agora.rtc.base; import androidx.annotation.IntDef; -import androidx.annotation.StringDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import io.agora.rtc.Constants; -import io.agora.rtc.IMetadataObserver; +import io.agora.rtc.RtcEngineConfig; import io.agora.rtc.video.BeautyOptions; import io.agora.rtc.video.VideoCanvas; +@SuppressWarnings("deprecation") public class Annotations { - @IntDef({ AgoraRtcAppType.NATIVE, AgoraRtcAppType.COCOS, @@ -131,15 +130,6 @@ public class Annotations { public @interface AgoraAudioProfile { } - @IntDef({ - Constants.RAW_AUDIO_FRAME_OP_MODE_READ_ONLY, - Constants.RAW_AUDIO_FRAME_OP_MODE_WRITE_ONLY, - Constants.RAW_AUDIO_FRAME_OP_MODE_READ_WRITE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioRawFrameOperationMode { - } - @IntDef({ Constants.AUDIO_RECORDING_QUALITY_LOW, Constants.AUDIO_RECORDING_QUALITY_MEDIUM, @@ -386,16 +376,20 @@ public class Annotations { int MAINTAIN_BALANCED = 2; } - @StringDef({ + @IntDef({ + AgoraEncryptionMode.NONE, AgoraEncryptionMode.AES128XTS, - AgoraEncryptionMode.AES256XTS, AgoraEncryptionMode.AES128ECB, + AgoraEncryptionMode.AES256XTS, + AgoraEncryptionMode.SM4128ECB, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraEncryptionMode { - String AES128XTS = "aes-128-xts"; - String AES256XTS = "aes-256-xts"; - String AES128ECB = "aes-128-ecb"; + int NONE = 0; + int AES128XTS = 1; + int AES128ECB = 2; + int AES256XTS = 3; + int SM4128ECB = 4; } @IntDef({ @@ -419,6 +413,7 @@ public class Annotations { Constants.ERR_ALREADY_IN_USE, Constants.ERR_INVALID_APP_ID, Constants.ERR_INVALID_CHANNEL_NAME, + Constants.ERR_NO_SERVER_RESOURCES, Constants.ERR_TOKEN_EXPIRED, Constants.ERR_INVALID_TOKEN, Constants.ERR_CONNECTION_INTERRUPTED, @@ -543,24 +538,6 @@ public class Annotations { public @interface AgoraLogFilter { } - @IntDef({ - Constants.MEDIA_TYPE_NONE, - Constants.MEDIA_TYPE_AUDIO_ONLY, - Constants.MEDIA_TYPE_VIDEO_ONLY, - Constants.MEDIA_TYPE_AUDIO_AND_VIDEO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraMediaType { - } - - @IntDef({ - IMetadataObserver.UNKNOWN_METADATA, - IMetadataObserver.VIDEO_METADATA, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface AgoraMetadataType { - } - @IntDef({ Constants.QUALITY_UNKNOWN, Constants.QUALITY_EXCELLENT, @@ -766,15 +743,50 @@ public class Annotations { Constants.WARN_ADM_RUNTIME_PLAYOUT_WARNING, Constants.WARN_ADM_RUNTIME_RECORDING_WARNING, Constants.WARN_ADM_RECORD_AUDIO_SILENCE, + Constants.WARN_ADM_PLAYOUT_ABNORMAL_FREQUENCY, + Constants.WARN_ADM_RECORD_ABNORMAL_FREQUENCY, Constants.WARN_ADM_CALL_INTERRUPTION, Constants.WARN_ADM_RECORD_AUDIO_LOWLEVEL, Constants.WARN_ADM_PLAYOUT_AUDIO_LOWLEVEL, Constants.WARN_ADM_RECORD_IS_OCCUPIED, Constants.WARN_APM_HOWLING, Constants.WARN_ADM_GLITCH_STATE, - Constants.WARN_ADM_IMPROPER_SETTINGS, + Constants.WARN_APM_RESIDUAL_ECHO, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraWarningCode { } + + @IntDef({ + RtcEngineConfig.AreaCode.AREA_CODE_CN, + RtcEngineConfig.AreaCode.AREA_CODE_NA, + RtcEngineConfig.AreaCode.AREA_CODE_EU, + RtcEngineConfig.AreaCode.AREA_CODE_AS, + RtcEngineConfig.AreaCode.AREA_CODE_JP, + RtcEngineConfig.AreaCode.AREA_CODE_IN, + RtcEngineConfig.AreaCode.AREA_CODE_GLOB, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraAreaCode { + } + + @IntDef({ + Constants.SUB_STATE_IDLE, + Constants.SUB_STATE_NO_SUBSCRIBED, + Constants.SUB_STATE_SUBSCRIBING, + Constants.SUB_STATE_SUBSCRIBED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraStreamSubscribeState { + } + + @IntDef({ + Constants.PUB_STATE_IDLE, + Constants.PUB_STATE_NO_PUBLISHED, + Constants.PUB_STATE_PUBLISHING, + Constants.PUB_STATE_PUBLISHED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraStreamPublishState { + } } diff --git a/BeanCovertor.kt b/BeanCovertor.kt index 978eff655..bd346c5e1 100644 --- a/BeanCovertor.kt +++ b/BeanCovertor.kt @@ -1,6 +1,7 @@ package io.agora.rtc.base import android.graphics.Color +import io.agora.rtc.internal.EncryptionConfig import io.agora.rtc.internal.LastmileProbeConfig import io.agora.rtc.live.LiveInjectStreamConfig import io.agora.rtc.live.LiveTranscoding @@ -169,3 +170,10 @@ fun mapToChannelMediaOptions(map: Map<*, *>): ChannelMediaOptions { (map["autoSubscribeVideo"] as? Boolean)?.let { autoSubscribeVideo = it } } } + +fun mapToEncryptionConfig(map: Map<*, *>): EncryptionConfig { + return EncryptionConfig().apply { + (map["encryptionMode"] as? Number)?.let { encryptionMode = intToEncryptionMode(it.toInt()) } + (map["encryptionKey"] as? String)?.let { encryptionKey = it } + } +} diff --git a/EnumCovertor.kt b/EnumCovertor.kt index b44665390..a6306629c 100644 --- a/EnumCovertor.kt +++ b/EnumCovertor.kt @@ -1,5 +1,6 @@ package io.agora.rtc.base +import io.agora.rtc.internal.EncryptionConfig import io.agora.rtc.live.LiveInjectStreamConfig import io.agora.rtc.live.LiveTranscoding import io.agora.rtc.video.CameraCapturerConfiguration @@ -85,3 +86,12 @@ fun intToCameraDirection(@Annotations.AgoraCameraDirection intValue: Int): Camer } throw RuntimeException("CameraCapturerConfiguration.CAMERA_DIRECTION not contains $intValue") } + +fun intToEncryptionMode(@Annotations.AgoraEncryptionMode intValue: Int): EncryptionConfig.EncryptionMode { + for (value in EncryptionConfig.EncryptionMode.values()) { + if (value.value == intValue) { + return value + } + } + throw RuntimeException("EncryptionConfig.EncryptionMode not contains $intValue") +} diff --git a/RtcChannel.kt b/RtcChannel.kt index be3a45cb1..53ff54bbf 100644 --- a/RtcChannel.kt +++ b/RtcChannel.kt @@ -1,68 +1,125 @@ package io.agora.rtc.base -import androidx.annotation.FloatRange -import androidx.annotation.IntRange import io.agora.rtc.Constants import io.agora.rtc.IMetadataObserver import io.agora.rtc.RtcChannel import io.agora.rtc.RtcEngine +import io.agora.rtc.internal.EncryptionConfig import java.util.* -interface RtcChannelInterface : - RtcChannelManager.RtcAudioInterface, - RtcChannelManager.RtcVideoInterface, - RtcChannelManager.RtcVoicePositionInterface, - RtcChannelManager.RtcPublishStreamInterface, - RtcChannelManager.RtcMediaRelayInterface, - RtcChannelManager.RtcDualStreamInterface, - RtcChannelManager.RtcFallbackInterface, - RtcChannelManager.RtcMediaMetadataInterface, - RtcChannelManager.RtcEncryptionInterface, - RtcChannelManager.RtcInjectStreamInterface, - RtcChannelManager.RtcStreamMessageInterface { - fun create(channelId: String, callback: Callback?) +class RtcChannelInterface { + interface RtcChannelInterface : RtcAudioInterface, RtcVideoInterface, RtcVoicePositionInterface, + RtcPublishStreamInterface, RtcMediaRelayInterface, RtcDualStreamInterface, + RtcFallbackInterface, RtcMediaMetadataInterface, RtcEncryptionInterface, + RtcInjectStreamInterface, RtcStreamMessageInterface { + fun create(params: Map, callback: Callback) - fun destroy(channelId: String, callback: Callback?) + fun destroy(params: Map, callback: Callback) - fun setClientRole(channelId: String, @Annotations.AgoraClientRole role: Int, callback: Callback?) + fun setClientRole(params: Map, callback: Callback) - fun joinChannel(channelId: String, token: String?, optionalInfo: String?, optionalUid: Int, options: Map, callback: Callback?) + fun joinChannel(params: Map, callback: Callback) - fun joinChannelWithUserAccount(channelId: String, token: String?, userAccount: String, options: Map, callback: Callback?) + fun joinChannelWithUserAccount(params: Map, callback: Callback) - fun leaveChannel(channelId: String, callback: Callback?) + fun leaveChannel(params: Map, callback: Callback) - fun renewToken(channelId: String, token: String, callback: Callback?) + fun renewToken(params: Map, callback: Callback) - fun getConnectionState(channelId: String, callback: Callback?) + fun getConnectionState(params: Map, callback: Callback) - fun publish(channelId: String, callback: Callback?) + fun publish(params: Map, callback: Callback) - fun unpublish(channelId: String, callback: Callback?) + fun unpublish(params: Map, callback: Callback) - fun getCallId(channelId: String, callback: Callback?) -} + fun getCallId(params: Map, callback: Callback) + } -class RtcChannelManager { - private val rtcChannelMap = Collections.synchronizedMap(mutableMapOf()) - private val mediaObserverMap = Collections.synchronizedMap(mutableMapOf()) + interface RtcAudioInterface { + fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) - fun create(engine: RtcEngine, channelId: String, emit: (methodName: String, data: Map?) -> Unit) { - engine.createRtcChannel(channelId)?.let { - it.setRtcChannelEventHandler(RtcChannelEventHandler { methodName, data -> emit(methodName, data) }) - rtcChannelMap[channelId] = it - } + fun muteRemoteAudioStream(params: Map, callback: Callback) + + fun muteAllRemoteAudioStreams(params: Map, callback: Callback) + + fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) } - fun destroy(channelId: String): Int { - this[channelId]?.let { - val res = it.destroy() - if (res == 0) rtcChannelMap.remove(channelId) - return@destroy res - } - return Constants.ERR_NOT_INITIALIZED + interface RtcVideoInterface { + fun muteRemoteVideoStream(params: Map, callback: Callback) + + fun muteAllRemoteVideoStreams(params: Map, callback: Callback) + + fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) + } + + interface RtcVoicePositionInterface { + fun setRemoteVoicePosition(params: Map, callback: Callback) + } + + interface RtcPublishStreamInterface { + fun setLiveTranscoding(params: Map, callback: Callback) + + fun addPublishStreamUrl(params: Map, callback: Callback) + + fun removePublishStreamUrl(params: Map, callback: Callback) + } + + interface RtcMediaRelayInterface { + fun startChannelMediaRelay(params: Map, callback: Callback) + + fun updateChannelMediaRelay(params: Map, callback: Callback) + + fun stopChannelMediaRelay(params: Map, callback: Callback) + } + + interface RtcDualStreamInterface { + fun setRemoteVideoStreamType(params: Map, callback: Callback) + + fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) + } + + interface RtcFallbackInterface { + fun setRemoteUserPriority(params: Map, callback: Callback) } + interface RtcMediaMetadataInterface { + fun registerMediaMetadataObserver(params: Map, callback: Callback) + + fun unregisterMediaMetadataObserver(params: Map, callback: Callback) + + fun setMaxMetadataSize(params: Map, callback: Callback) + + fun sendMetadata(params: Map, callback: Callback) + } + + interface RtcEncryptionInterface { + fun setEncryptionSecret(params: Map, callback: Callback) + + fun setEncryptionMode(params: Map, callback: Callback) + + fun enableEncryption(params: Map, callback: Callback) + } + + interface RtcInjectStreamInterface { + fun addInjectStreamUrl(params: Map, callback: Callback) + + fun removeInjectStreamUrl(params: Map, callback: Callback) + } + + interface RtcStreamMessageInterface { + fun createDataStream(params: Map, callback: Callback) + + fun sendStreamMessage(params: Map, callback: Callback) + } +} + +class RtcChannelManager( + private val emit: (methodName: String, data: Map?) -> Unit +) : RtcChannelInterface.RtcChannelInterface { + private val rtcChannelMap = Collections.synchronizedMap(mutableMapOf()) + private val mediaObserverMap = Collections.synchronizedMap(mutableMapOf()) + fun release() { rtcChannelMap.forEach { it.value.destroy() } rtcChannelMap.clear() @@ -73,130 +130,197 @@ class RtcChannelManager { return rtcChannelMap[channelId] } - fun registerMediaMetadataObserver(channelId: String, emit: (methodName: String, data: Map?) -> Unit): Int { - this[channelId]?.let { - val mediaObserver = MediaObserver { data -> - emit(RtcChannelEvents.MetadataReceived, data?.toMutableMap()?.apply { put("channelId", channelId) }) + override fun create(params: Map, callback: Callback) { + callback.resolve(params["engine"] as RtcEngine) { e -> + e.createRtcChannel(params["channelId"] as String)?.let { + it.setRtcChannelEventHandler(RtcChannelEventHandler { methodName, data -> emit(methodName, data) }) + rtcChannelMap[it.channelId()] = it } - val res = it.registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA) - if (res == 0) mediaObserverMap[channelId] = mediaObserver - return@registerMediaMetadataObserver res + Unit } - return Constants.ERR_NOT_INITIALIZED } - fun unregisterMediaMetadataObserver(channelId: String): Int { - this[channelId]?.let { - val res = it.registerMediaMetadataObserver(null, IMetadataObserver.VIDEO_METADATA) - if (res == 0) mediaObserverMap.remove(channelId) - return@unregisterMediaMetadataObserver res + override fun destroy(params: Map, callback: Callback) { + var code: Int? = -Constants.ERR_NOT_INITIALIZED + this[params["channelId"] as String]?.let { + code = rtcChannelMap.remove(it.channelId())?.destroy() } - return Constants.ERR_NOT_INITIALIZED + callback.code(code) } - fun setMaxMetadataSize(channelId: String, @IntRange(from = 0, to = 1024) size: Int): Int { - mediaObserverMap[channelId]?.let { - it.maxMetadataSize = size - return@setMaxMetadataSize 0 - } - return Constants.ERR_NOT_INITIALIZED + override fun setClientRole(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setClientRole((params["role"] as Number).toInt())) } - fun addMetadata(channelId: String, metadata: String): Int { - mediaObserverMap[channelId]?.let { - it.addMetadata(metadata) - return@addMetadata 0 - } - return Constants.ERR_NOT_INITIALIZED + override fun joinChannel(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.joinChannel(params["token"] as? String, params["optionalInfo"] as? String, (params["optionalUid"] as Number).toInt(), mapToChannelMediaOptions(params["options"] as Map<*, *>))) } - fun createDataStream(channelId: String, reliable: Boolean, ordered: Boolean): Int { - this[channelId]?.let { - return@createDataStream it.createDataStream(reliable, ordered) - } - return Constants.ERR_NOT_INITIALIZED + override fun joinChannelWithUserAccount(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.joinChannelWithUserAccount(params["token"] as? String, params["userAccount"] as String, mapToChannelMediaOptions(params["options"] as Map<*, *>))) } - fun sendStreamMessage(channelId: String, streamId: Int, message: String): Int { - this[channelId]?.let { - return@sendStreamMessage it.sendStreamMessage(streamId, message.toByteArray()) - } - return Constants.ERR_NOT_INITIALIZED + override fun leaveChannel(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.leaveChannel()) } - interface RtcAudioInterface { - fun adjustUserPlaybackSignalVolume(channelId: String, uid: Int, @IntRange(from = 0, to = 100) volume: Int, callback: Callback?) + override fun renewToken(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.renewToken(params["token"] as String)) + } - fun muteRemoteAudioStream(channelId: String, uid: Int, muted: Boolean, callback: Callback?) + override fun getConnectionState(params: Map, callback: Callback) { + callback.resolve(this[params["channelId"] as String]) { it.connectionState } + } + + override fun publish(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.publish()) + } + + override fun unpublish(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.unpublish()) + } + + override fun getCallId(params: Map, callback: Callback) { + callback.resolve(this[params["channelId"] as String]) { it.callId } + } + + override fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.adjustUserPlaybackSignalVolume((params["uid"] as Number).toInt(), (params["volume"] as Number).toInt())) + } + + override fun muteRemoteAudioStream(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.muteRemoteAudioStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + } + + override fun muteAllRemoteAudioStreams(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.muteAllRemoteAudioStreams(params["muted"] as Boolean)) + } - fun muteAllRemoteAudioStreams(channelId: String, muted: Boolean, callback: Callback?) + override fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as Boolean)) + } - fun setDefaultMuteAllRemoteAudioStreams(channelId: String, muted: Boolean, callback: Callback?) + override fun muteRemoteVideoStream(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.muteRemoteVideoStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) } - interface RtcVideoInterface { - fun muteRemoteVideoStream(channelId: String, uid: Int, muted: Boolean, callback: Callback?) + override fun muteAllRemoteVideoStreams(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.muteAllRemoteVideoStreams(params["muted"] as Boolean)) + } - fun muteAllRemoteVideoStreams(channelId: String, muted: Boolean, callback: Callback?) + override fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as Boolean)) + } - fun setDefaultMuteAllRemoteVideoStreams(channelId: String, muted: Boolean, callback: Callback?) + override fun setRemoteVoicePosition(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setRemoteVoicePosition((params["uid"] as Number).toInt(), (params["pan"] as Number).toDouble(), (params["gain"] as Number).toDouble())) } - interface RtcVoicePositionInterface { - fun setRemoteVoicePosition(channelId: String, uid: Int, @FloatRange(from = -1.0, to = 1.0) pan: Double, @FloatRange(from = 0.0, to = 100.0) gain: Double, callback: Callback?) + override fun setLiveTranscoding(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as Map<*, *>))) } - interface RtcPublishStreamInterface { - fun setLiveTranscoding(channelId: String, transcoding: Map, callback: Callback?) + override fun addPublishStreamUrl(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.addPublishStreamUrl(params["url"] as String, params["transcodingEnabled"] as Boolean)) + } - fun addPublishStreamUrl(channelId: String, url: String, transcodingEnabled: Boolean, callback: Callback?) + override fun removePublishStreamUrl(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.removePublishStreamUrl(params["url"] as String)) + } - fun removePublishStreamUrl(channelId: String, url: String, callback: Callback?) + override fun startChannelMediaRelay(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) } - interface RtcMediaRelayInterface { - fun startChannelMediaRelay(channelId: String, channelMediaRelayConfiguration: Map, callback: Callback?) + override fun updateChannelMediaRelay(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) + } - fun updateChannelMediaRelay(channelId: String, channelMediaRelayConfiguration: Map, callback: Callback?) + override fun stopChannelMediaRelay(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.stopChannelMediaRelay()) + } - fun stopChannelMediaRelay(channelId: String, callback: Callback?) + override fun setRemoteVideoStreamType(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setRemoteVideoStreamType((params["uid"] as Number).toInt(), (params["streamType"] as Number).toInt())) } - interface RtcDualStreamInterface { - fun setRemoteVideoStreamType(channelId: String, uid: Int, @Annotations.AgoraVideoStreamType streamType: Int, callback: Callback?) + override fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setRemoteDefaultVideoStreamType((params["streamType"] as Number).toInt())) + } - fun setRemoteDefaultVideoStreamType(channelId: String, @Annotations.AgoraVideoStreamType streamType: Int, callback: Callback?) + override fun setRemoteUserPriority(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setRemoteUserPriority((params["uid"] as Number).toInt(), (params["userPriority"] as Number).toInt())) } - interface RtcFallbackInterface { - fun setRemoteUserPriority(channelId: String, uid: Int, @Annotations.AgoraUserPriority userPriority: Int, callback: Callback?) + override fun registerMediaMetadataObserver(params: Map, callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + this[params["channelId"] as String]?.let { + val mediaObserver = MediaObserver { data -> + emit(RtcChannelEvents.MetadataReceived, data?.toMutableMap()?.apply { put("channelId", it.channelId()) }) + } + code = it.registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA) + if (code == 0) mediaObserverMap[it.channelId()] = mediaObserver + } + callback.code(code) } - interface RtcMediaMetadataInterface { - fun registerMediaMetadataObserver(channelId: String, callback: Callback?) + override fun unregisterMediaMetadataObserver(params: Map, callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + this[params["channelId"] as String]?.let { + code = it.registerMediaMetadataObserver(null, IMetadataObserver.VIDEO_METADATA) + if (code == 0) mediaObserverMap.remove(it.channelId()) + } + callback.code(code) + } - fun unregisterMediaMetadataObserver(channelId: String, callback: Callback?) + override fun setMaxMetadataSize(params: Map, callback: Callback) { + callback.resolve(mediaObserverMap[params["channelId"] as String]) { + it.maxMetadataSize = (params["size"] as Number).toInt() + Unit + } + } - fun setMaxMetadataSize(channelId: String, @IntRange(from = 0, to = 1024) size: Int, callback: Callback?) + override fun sendMetadata(params: Map, callback: Callback) { + callback.resolve(mediaObserverMap[params["channelId"] as String]) { + it.addMetadata(params["metadata"] as String) + Unit + } + } - fun sendMetadata(channelId: String, metadata: String, callback: Callback?) + override fun setEncryptionSecret(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setEncryptionSecret(params["secret"] as String)) } - interface RtcEncryptionInterface { - fun setEncryptionSecret(channelId: String, secret: String, callback: Callback?) + override fun setEncryptionMode(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.setEncryptionMode(when ((params["encryptionMode"] as Number).toInt()) { + EncryptionConfig.EncryptionMode.AES_128_XTS.value -> "aes-128-xts" + EncryptionConfig.EncryptionMode.AES_128_ECB.value -> "aes-128-ecb" + EncryptionConfig.EncryptionMode.AES_256_XTS.value -> "aes-256-xts" + else -> "" + })) + } - fun setEncryptionMode(channelId: String, @Annotations.AgoraEncryptionMode encryptionMode: String, callback: Callback?) + override fun enableEncryption(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.enableEncryption(params["enabled"] as Boolean, mapToEncryptionConfig(params["config"] as Map<*, *>))) } - interface RtcInjectStreamInterface { - fun addInjectStreamUrl(channelId: String, url: String, config: Map, callback: Callback?) + override fun addInjectStreamUrl(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.addInjectStreamUrl(params["url"] as String, mapToLiveInjectStreamConfig(params["config"] as Map<*, *>))) + } - fun removeInjectStreamUrl(channelId: String, url: String, callback: Callback?) + override fun removeInjectStreamUrl(params: Map, callback: Callback) { + callback.code(this[params["channelId"] as String]?.removeInjectStreamUrl(params["url"] as String)) } - interface RtcStreamMessageInterface { - fun createDataStream(channelId: String, reliable: Boolean, ordered: Boolean, callback: Callback?) + override fun createDataStream(params: Map, callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + this[params["channelId"] as String]?.let { + code= it.createDataStream(reliable, ordered) + } + callback.code(manager.createDataStream(channelId, reliable, ordered)) { it } + } - fun sendStreamMessage(channelId: String, streamId: Int, message: String, callback: Callback?) + override fun sendStreamMessage(params: Map, callback: Callback) { + callback.code(manager.sendStreamMessage(channelId, streamId, message)) } } diff --git a/RtcChannelEvent.kt b/RtcChannelEvent.kt index 2b471ac45..3a1088ca4 100644 --- a/RtcChannelEvent.kt +++ b/RtcChannelEvent.kt @@ -37,6 +37,11 @@ class RtcChannelEvents { const val ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" const val ChannelMediaRelayEvent = "ChannelMediaRelayEvent" const val MetadataReceived = "MetadataReceived" + const val AudioPublishStateChanged = "AudioPublishStateChanged" + const val VideoPublishStateChanged = "VideoPublishStateChanged" + const val AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + const val VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + const val RtmpStreamingEvent = "RtmpStreamingEvent" fun toMap(): Map { return hashMapOf( @@ -69,7 +74,12 @@ class RtcChannelEvents { "StreamMessageError" to StreamMessageError, "ChannelMediaRelayStateChanged" to ChannelMediaRelayStateChanged, "ChannelMediaRelayEvent" to ChannelMediaRelayEvent, - "MetadataReceived" to MetadataReceived + "MetadataReceived" to MetadataReceived, + "AudioPublishStateChanged" to AudioPublishStateChanged, + "VideoPublishStateChanged" to VideoPublishStateChanged, + "AudioSubscribeStateChanged" to AudioSubscribeStateChanged, + "VideoSubscribeStateChanged" to VideoSubscribeStateChanged, + "RtmpStreamingEvent" to RtmpStreamingEvent ) } } @@ -206,4 +216,24 @@ class RtcChannelEventHandler( override fun onChannelMediaRelayEvent(rtcChannel: RtcChannel?, @Annotations.AgoraChannelMediaRelayEvent code: Int) { callback(RtcChannelEvents.ChannelMediaRelayEvent, rtcChannel, code) } + + override fun onAudioPublishStateChanged(rtcChannel: RtcChannel?, @Annotations.AgoraStreamPublishState oldState: Int, @Annotations.AgoraStreamPublishState newState: Int, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioPublishStateChanged, rtcChannel, oldState, newState, elapseSinceLastState) + } + + override fun onVideoPublishStateChanged(rtcChannel: RtcChannel?, @Annotations.AgoraStreamPublishState oldState: Int, @Annotations.AgoraStreamPublishState newState: Int, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoPublishStateChanged, rtcChannel, oldState, newState, elapseSinceLastState) + } + + override fun onAudioSubscribeStateChanged(rtcChannel: RtcChannel?, uid: Int, @Annotations.AgoraStreamSubscribeState oldState: Int, @Annotations.AgoraStreamSubscribeState newState: Int, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioSubscribeStateChanged, rtcChannel, uid, oldState, newState, elapseSinceLastState) + } + + override fun onVideoSubscribeStateChanged(rtcChannel: RtcChannel?, uid: Int, @Annotations.AgoraStreamSubscribeState oldState: Int, @Annotations.AgoraStreamSubscribeState newState: Int, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoSubscribeStateChanged, rtcChannel, uid, oldState, newState, elapseSinceLastState) + } + + override fun onRtmpStreamingEvent(rtcChannel: RtcChannel?, url: String?, errCode: Int) { + callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, errCode) + } } diff --git a/RtcEngine.kt b/RtcEngine.kt index e8eab447d..8aea44c87 100644 --- a/RtcEngine.kt +++ b/RtcEngine.kt @@ -1,427 +1,888 @@ package io.agora.rtc.base import android.content.Context -import androidx.annotation.FloatRange -import androidx.annotation.IntRange import io.agora.rtc.* +import io.agora.rtc.internal.EncryptionConfig import io.agora.rtc.models.UserInfo -interface RtcEngineInterface : - RtcEngineManager.RtcUserInfoInterface, - RtcEngineManager.RtcAudioInterface, - RtcEngineManager.RtcVideoInterface, - RtcEngineManager.RtcAudioMixingInterface, - RtcEngineManager.RtcAudioEffectInterface, - RtcEngineManager.RtcVoiceChangerInterface, - RtcEngineManager.RtcVoicePositionInterface, - RtcEngineManager.RtcPublishStreamInterface, - RtcEngineManager.RtcMediaRelayInterface, - RtcEngineManager.RtcAudioRouteInterface, - RtcEngineManager.RtcEarMonitoringInterface, - RtcEngineManager.RtcDualStreamInterface, - RtcEngineManager.RtcFallbackInterface, - RtcEngineManager.RtcTestInterface, - RtcEngineManager.RtcMediaMetadataInterface, - RtcEngineManager.RtcWatermarkInterface, - RtcEngineManager.RtcEncryptionInterface, - RtcEngineManager.RtcAudioRecorderInterface, - RtcEngineManager.RtcInjectStreamInterface, - RtcEngineManager.RtcCameraInterface, - RtcEngineManager.RtcStreamMessageInterface { - fun create(appId: String, areaCode: Int, callback: Callback?) +class RtcEngineInterface { + interface RtcEngineInterface : RtcUserInfoInterface, RtcAudioInterface, RtcVideoInterface, + RtcAudioMixingInterface, RtcAudioEffectInterface, RtcVoiceChangerInterface, + RtcVoicePositionInterface, RtcPublishStreamInterface, RtcMediaRelayInterface, + RtcAudioRouteInterface, RtcEarMonitoringInterface, RtcDualStreamInterface, + RtcFallbackInterface, RtcTestInterface, RtcMediaMetadataInterface, + RtcWatermarkInterface, RtcEncryptionInterface, RtcAudioRecorderInterface, + RtcInjectStreamInterface, RtcCameraInterface, RtcStreamMessageInterface { + fun create(params: Map, callback: Callback) - fun destroy(callback: Callback?) + fun destroy(callback: Callback) - fun setChannelProfile(@Annotations.AgoraChannelProfile profile: Int, callback: Callback?) + fun setChannelProfile(params: Map, callback: Callback) - fun setClientRole(@Annotations.AgoraClientRole role: Int, callback: Callback?) + fun setClientRole(params: Map, callback: Callback) - fun joinChannel(token: String?, channelName: String, optionalInfo: String?, optionalUid: Int, callback: Callback?) + fun joinChannel(params: Map, callback: Callback) - fun switchChannel(token: String?, channelName: String, callback: Callback?) + fun switchChannel(params: Map, callback: Callback) - fun leaveChannel(callback: Callback?) + fun leaveChannel(callback: Callback) - fun renewToken(token: String, callback: Callback?) + fun renewToken(params: Map, callback: Callback) - @Deprecated("") - fun enableWebSdkInteroperability(enabled: Boolean, callback: Callback?) + @Deprecated("") + fun enableWebSdkInteroperability(params: Map, callback: Callback) - fun getConnectionState(callback: Callback?) + fun getConnectionState(callback: Callback) - fun getCallId(callback: Callback?) + fun getCallId(callback: Callback) - fun rate(callId: String, @IntRange(from = 1, to = 5) rating: Int, description: String?, callback: Callback?) + fun rate(params: Map, callback: Callback) - fun complain(callId: String, description: String, callback: Callback?) + fun complain(params: Map, callback: Callback) - fun setLogFile(filePath: String, callback: Callback?) + fun setLogFile(params: Map, callback: Callback) - fun setLogFilter(@Annotations.AgoraLogFilter filter: Int, callback: Callback?) + fun setLogFilter(params: Map, callback: Callback) - fun setLogFileSize(fileSizeInKBytes: Int, callback: Callback?) + fun setLogFileSize(params: Map, callback: Callback) - fun setParameters(parameters: String, callback: Callback?) + fun setParameters(params: Map, callback: Callback) + } + + interface RtcUserInfoInterface { + fun registerLocalUserAccount(params: Map, callback: Callback) + + fun joinChannelWithUserAccount(params: Map, callback: Callback) + + fun getUserInfoByUserAccount(params: Map, callback: Callback) + + fun getUserInfoByUid(params: Map, callback: Callback) + } + + interface RtcAudioInterface { + fun enableAudio(callback: Callback) + + fun disableAudio(callback: Callback) + + fun setAudioProfile(params: Map, callback: Callback) + + fun adjustRecordingSignalVolume(params: Map, callback: Callback) + + fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) + + fun adjustPlaybackSignalVolume(params: Map, callback: Callback) + + fun enableLocalAudio(params: Map, callback: Callback) + + fun muteLocalAudioStream(params: Map, callback: Callback) + + fun muteRemoteAudioStream(params: Map, callback: Callback) + + fun muteAllRemoteAudioStreams(params: Map, callback: Callback) + + fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) + + fun enableAudioVolumeIndication(params: Map, callback: Callback) + } + + interface RtcVideoInterface { + fun enableVideo(callback: Callback) + + fun disableVideo(callback: Callback) + + fun setVideoEncoderConfiguration(params: Map, callback: Callback) + + fun startPreview(callback: Callback) + + fun stopPreview(callback: Callback) + + fun enableLocalVideo(params: Map, callback: Callback) + + fun muteLocalVideoStream(params: Map, callback: Callback) + + fun muteRemoteVideoStream(params: Map, callback: Callback) + + fun muteAllRemoteVideoStreams(params: Map, callback: Callback) + + fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) + + fun setBeautyEffectOptions(params: Map, callback: Callback) + } + + interface RtcAudioMixingInterface { + fun startAudioMixing(params: Map, callback: Callback) + + fun stopAudioMixing(callback: Callback) + + fun pauseAudioMixing(callback: Callback) + + fun resumeAudioMixing(callback: Callback) + + fun adjustAudioMixingVolume(params: Map, callback: Callback) + + fun adjustAudioMixingPlayoutVolume(params: Map, callback: Callback) + + fun adjustAudioMixingPublishVolume(params: Map, callback: Callback) + + fun getAudioMixingPlayoutVolume(callback: Callback) + + fun getAudioMixingPublishVolume(callback: Callback) + + fun getAudioMixingDuration(callback: Callback) + + fun getAudioMixingCurrentPosition(callback: Callback) + + fun setAudioMixingPosition(params: Map, callback: Callback) + + fun setAudioMixingPitch(params: Map, callback: Callback) + } + + interface RtcAudioEffectInterface { + fun getEffectsVolume(callback: Callback) + + fun setEffectsVolume(params: Map, callback: Callback) + + fun setVolumeOfEffect(params: Map, callback: Callback) + + fun playEffect(params: Map, callback: Callback) + + fun stopEffect(params: Map, callback: Callback) + + fun stopAllEffects(callback: Callback) + + fun preloadEffect(params: Map, callback: Callback) + + fun unloadEffect(params: Map, callback: Callback) + + fun pauseEffect(params: Map, callback: Callback) + + fun pauseAllEffects(callback: Callback) + + fun resumeEffect(params: Map, callback: Callback) + + fun resumeAllEffects(callback: Callback) + } + + interface RtcVoiceChangerInterface { + fun setLocalVoiceChanger(params: Map, callback: Callback) + + fun setLocalVoiceReverbPreset(params: Map, callback: Callback) + + fun setLocalVoicePitch(params: Map, callback: Callback) + + fun setLocalVoiceEqualization(params: Map, callback: Callback) + + fun setLocalVoiceReverb(params: Map, callback: Callback) + } + + interface RtcVoicePositionInterface { + fun enableSoundPositionIndication(params: Map, callback: Callback) + + fun setRemoteVoicePosition(params: Map, callback: Callback) + } + + interface RtcPublishStreamInterface { + fun setLiveTranscoding(params: Map, callback: Callback) + + fun addPublishStreamUrl(params: Map, callback: Callback) + + fun removePublishStreamUrl(params: Map, callback: Callback) + } + + interface RtcMediaRelayInterface { + fun startChannelMediaRelay(params: Map, callback: Callback) + + fun updateChannelMediaRelay(params: Map, callback: Callback) + + fun stopChannelMediaRelay(callback: Callback) + } + + interface RtcAudioRouteInterface { + fun setDefaultAudioRoutetoSpeakerphone(params: Map, callback: Callback) + + fun setEnableSpeakerphone(params: Map, callback: Callback) + + fun isSpeakerphoneEnabled(callback: Callback) + } + + interface RtcEarMonitoringInterface { + fun enableInEarMonitoring(params: Map, callback: Callback) + + fun setInEarMonitoringVolume(params: Map, callback: Callback) + } + + interface RtcDualStreamInterface { + fun enableDualStreamMode(params: Map, callback: Callback) + + fun setRemoteVideoStreamType(params: Map, callback: Callback) + + fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) + } + + interface RtcFallbackInterface { + fun setLocalPublishFallbackOption(params: Map, callback: Callback) + + fun setRemoteSubscribeFallbackOption(params: Map, callback: Callback) + + fun setRemoteUserPriority(params: Map, callback: Callback) + } + + interface RtcTestInterface { + fun startEchoTest(params: Map, callback: Callback) + + fun stopEchoTest(callback: Callback) + + fun enableLastmileTest(callback: Callback) + + fun disableLastmileTest(callback: Callback) + + fun startLastmileProbeTest(params: Map, callback: Callback) + + fun stopLastmileProbeTest(callback: Callback) + } + + interface RtcMediaMetadataInterface { + fun registerMediaMetadataObserver(callback: Callback) + + fun unregisterMediaMetadataObserver(callback: Callback) + + fun setMaxMetadataSize(params: Map, callback: Callback) + + fun sendMetadata(params: Map, callback: Callback) + } + + interface RtcWatermarkInterface { + fun addVideoWatermark(params: Map, callback: Callback) + + fun clearVideoWatermarks(callback: Callback) + } + + interface RtcEncryptionInterface { + fun setEncryptionSecret(params: Map, callback: Callback) + + fun setEncryptionMode(params: Map, callback: Callback) + + fun enableEncryption(params: Map, callback: Callback) + } + + interface RtcAudioRecorderInterface { + fun startAudioRecording(params: Map, callback: Callback) + + fun stopAudioRecording(callback: Callback) + } + + interface RtcInjectStreamInterface { + fun addInjectStreamUrl(params: Map, callback: Callback) + + fun removeInjectStreamUrl(params: Map, callback: Callback) + } + + interface RtcCameraInterface { + fun switchCamera(callback: Callback) + + fun isCameraZoomSupported(callback: Callback) + + fun isCameraTorchSupported(callback: Callback) + + fun isCameraFocusSupported(callback: Callback) + + fun isCameraExposurePositionSupported(callback: Callback) + + fun isCameraAutoFocusFaceModeSupported(callback: Callback) + + fun setCameraZoomFactor(params: Map, callback: Callback) + + fun getCameraMaxZoomFactor(callback: Callback) + + fun setCameraFocusPositionInPreview(params: Map, callback: Callback) + + fun setCameraExposurePosition(params: Map, callback: Callback) + + fun enableFaceDetection(params: Map, callback: Callback) + + fun setCameraTorchOn(params: Map, callback: Callback) + + fun setCameraAutoFocusFaceModeEnabled(params: Map, callback: Callback) + + fun setCameraCapturerConfiguration(params: Map, callback: Callback) + } + + interface RtcStreamMessageInterface { + fun createDataStream(params: Map, callback: Callback) + + fun sendStreamMessage(params: Map, callback: Callback) + } } -class RtcEngineManager { - private var engine: RtcEngine? = null +class RtcEngineManager( + private val emit: (methodName: String, data: Map?) -> Unit +) : RtcEngineInterface.RtcEngineInterface { + var engine: RtcEngine? = null + private set private var mediaObserver: MediaObserver? = null - fun create(context: Context, appId: String, areaCode: Int, @Annotations.AgoraRtcAppType appType: Int, emit: (methodName: String, data: Map?) -> Unit) { + fun release() { + RtcEngine.destroy() + engine = null + mediaObserver = null + } + + override fun create(params: Map, callback: Callback) { engine = RtcEngineEx.create(RtcEngineConfig().apply { - mContext = context - mAppId = appId - mAreaCode = areaCode + mContext = params["context"] as Context + mAppId = params["appId"] as String + mAreaCode = (params["areaCode"] as Number).toInt() mEventHandler = RtcEngineEventHandler { methodName, data -> emit(methodName, data) } }) - (engine as? RtcEngineEx)?.setAppType(appType) + callback.code((engine as RtcEngineEx).setAppType((params["appType"] as Number).toInt())) } - fun destroy() { - RtcEngine.destroy() - engine = null + override fun destroy(callback: Callback) { + callback.resolve(engine) { release() } } - fun release() { - destroy() - mediaObserver = null + override fun setChannelProfile(params: Map, callback: Callback) { + callback.code(engine?.setChannelProfile((params["profile"] as Number).toInt())) } - fun engine(): RtcEngine? { - return engine + override fun setClientRole(params: Map, callback: Callback) { + callback.code(engine?.setClientRole((params["role"] as Number).toInt())) } - fun getUserInfoByUserAccount(userAccount: String): Map? { - engine?.let { - val userInfo = UserInfo() - it.getUserInfoByUserAccount(userAccount, userInfo) - return@getUserInfoByUserAccount userInfo.toMap() - } - return null + override fun joinChannel(params: Map, callback: Callback) { + callback.code(engine?.joinChannel(params["token"] as? String, params["channelName"] as String, params["optionalInfo"] as? String, (params["optionalUid"] as Number).toInt())) } - fun getUserInfoByUid(uid: Int): Map? { - engine?.let { - val userInfo = UserInfo() - it.getUserInfoByUid(uid, userInfo) - return@getUserInfoByUid userInfo.toMap() - } - return null + override fun switchChannel(params: Map, callback: Callback) { + callback.code(engine?.switchChannel(params["token"] as? String, params["channelName"] as String)) } - fun registerMediaMetadataObserver(emit: (methodName: String, data: Map?) -> Unit): Int { - engine?.let { - val mediaObserver = MediaObserver { data -> - emit(RtcEngineEvents.MetadataReceived, data) - } - val res = it.registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA) - if (res == 0) this.mediaObserver = mediaObserver - return@registerMediaMetadataObserver res - } - return Constants.ERR_NOT_INITIALIZED + override fun leaveChannel(callback: Callback) { + callback.code(engine?.leaveChannel()) } - fun unregisterMediaMetadataObserver(): Int { - engine?.let { - val res = it.registerMediaMetadataObserver(null, IMetadataObserver.VIDEO_METADATA) - if (res == 0) mediaObserver = null - return@unregisterMediaMetadataObserver res - } - return Constants.ERR_NOT_INITIALIZED + override fun renewToken(params: Map, callback: Callback) { + callback.code(engine?.renewToken(params["token"] as String)) } - fun setMaxMetadataSize(@IntRange(from = 0, to = 1024) size: Int): Int { - mediaObserver?.let { - it.maxMetadataSize = size - return@setMaxMetadataSize 0 - } - return Constants.ERR_NOT_INITIALIZED + override fun enableWebSdkInteroperability(params: Map, callback: Callback) { + callback.code(engine?.enableWebSdkInteroperability(params["enabled"] as Boolean)) } - fun addMetadata(metadata: String): Int { - mediaObserver?.let { - it.addMetadata(metadata) - return@addMetadata 0 - } - return Constants.ERR_NOT_INITIALIZED + override fun getConnectionState(callback: Callback) { + callback.resolve(engine) { it.connectionState } } - fun createDataStream(reliable: Boolean, ordered: Boolean): Int { - engine?.let { - return@createDataStream it.createDataStream(reliable, ordered) - } - return Constants.ERR_NOT_INITIALIZED + override fun getCallId(callback: Callback) { + callback.resolve(engine) { it.callId } } - fun sendStreamMessage(streamId: Int, message: String): Int { - engine?.let { - return@sendStreamMessage it.sendStreamMessage(streamId, message.toByteArray()) - } - return Constants.ERR_NOT_INITIALIZED + override fun rate(params: Map, callback: Callback) { + callback.code(engine?.rate(params["callId"] as String, (params["rating"] as Number).toInt(), params["description"] as? String)) } - interface RtcUserInfoInterface { - fun registerLocalUserAccount(appId: String, userAccount: String, callback: Callback?) + override fun complain(params: Map, callback: Callback) { + callback.code(engine?.complain(params["callId"] as String, params["description"] as String)) + } + + override fun setLogFile(params: Map, callback: Callback) { + callback.code(engine?.setLogFile(params["filePath"] as String)) + } + + override fun setLogFilter(params: Map, callback: Callback) { + callback.code(engine?.setLogFilter((params["filter"] as Number).toInt())) + } + + override fun setLogFileSize(params: Map, callback: Callback) { + callback.code(engine?.setLogFileSize((params["fileSizeInKBytes"] as Number).toInt())) + } + + override fun setParameters(params: Map, callback: Callback) { + callback.code(engine?.setParameters(params["parameters"] as String)) + } + + override fun registerLocalUserAccount(params: Map, callback: Callback) { + callback.code(engine?.registerLocalUserAccount(params["appId"] as String, params["userAccount"] as String)) + } + + override fun joinChannelWithUserAccount(params: Map, callback: Callback) { + callback.code(engine?.joinChannelWithUserAccount(params["token"] as? String, params["channelName"] as String, params["userAccount"] as String)) + } - fun joinChannelWithUserAccount(token: String?, channelName: String, userAccount: String, callback: Callback?) + override fun getUserInfoByUserAccount(params: Map, callback: Callback) { + callback.resolve(engine) { + val userInfo = UserInfo() + it.getUserInfoByUserAccount(params["userAccount"] as String, userInfo) + userInfo.toMap() + } + } - fun getUserInfoByUserAccount(userAccount: String, callback: Callback?) + override fun getUserInfoByUid(params: Map, callback: Callback) { + callback.resolve(engine) { + val userInfo = UserInfo() + it.getUserInfoByUid((params["uid"] as Number).toInt(), userInfo) + userInfo.toMap() + } + } - fun getUserInfoByUid(uid: Int, callback: Callback?) + override fun enableAudio(callback: Callback) { + callback.code(engine?.enableAudio()) } - interface RtcAudioInterface { - fun enableAudio(callback: Callback?) + override fun disableAudio(callback: Callback) { + callback.code(engine?.disableAudio()) + } - fun disableAudio(callback: Callback?) + override fun setAudioProfile(params: Map, callback: Callback) { + callback.code(engine?.setAudioProfile((params["profile"] as Number).toInt(), (params["scenario"] as Number).toInt())) + } - fun setAudioProfile(@Annotations.AgoraAudioProfile profile: Int, @Annotations.AgoraAudioScenario scenario: Int, callback: Callback?) + override fun adjustRecordingSignalVolume(params: Map, callback: Callback) { + callback.code(engine?.adjustRecordingSignalVolume((params["volume"] as Number).toInt())) + } - fun adjustRecordingSignalVolume(@IntRange(from = 0, to = 400) volume: Int, callback: Callback?) + override fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) { + callback.code(engine?.adjustUserPlaybackSignalVolume((params["uid"] as Number).toInt(), (params["volume"] as Number).toInt())) + } - fun adjustUserPlaybackSignalVolume(uid: Int, @IntRange(from = 0, to = 100) volume: Int, callback: Callback?) + override fun adjustPlaybackSignalVolume(params: Map, callback: Callback) { + callback.code(engine?.adjustPlaybackSignalVolume((params["volume"] as Number).toInt())) + } - fun adjustPlaybackSignalVolume(@IntRange(from = 0, to = 400) volume: Int, callback: Callback?) + override fun enableLocalAudio(params: Map, callback: Callback) { + callback.code(engine?.enableLocalAudio(params["enabled"] as Boolean)) + } - fun enableLocalAudio(enabled: Boolean, callback: Callback?) + override fun muteLocalAudioStream(params: Map, callback: Callback) { + callback.code(engine?.muteLocalAudioStream(params["muted"] as Boolean)) + } - fun muteLocalAudioStream(muted: Boolean, callback: Callback?) + override fun muteRemoteAudioStream(params: Map, callback: Callback) { + callback.code(engine?.muteRemoteAudioStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + } - fun muteRemoteAudioStream(uid: Int, muted: Boolean, callback: Callback?) + override fun muteAllRemoteAudioStreams(params: Map, callback: Callback) { + callback.code(engine?.muteAllRemoteAudioStreams(params["muted"] as Boolean)) + } - fun muteAllRemoteAudioStreams(muted: Boolean, callback: Callback?) + override fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) { + callback.code(engine?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as Boolean)) + } - fun setDefaultMuteAllRemoteAudioStreams(muted: Boolean, callback: Callback?) + override fun enableAudioVolumeIndication(params: Map, callback: Callback) { + callback.code(engine?.enableAudioVolumeIndication((params["interval"] as Number).toInt(), (params["smooth"] as Number).toInt(), params["report_vad"] as Boolean)) + } - fun enableAudioVolumeIndication(interval: Int, @IntRange(from = 0, to = 10) smooth: Int, report_vad: Boolean, callback: Callback?) + override fun enableVideo(callback: Callback) { + callback.code(engine?.enableVideo()) } - interface RtcVideoInterface { - fun enableVideo(callback: Callback?) + override fun disableVideo(callback: Callback) { + callback.code(engine?.disableVideo()) + } - fun disableVideo(callback: Callback?) + override fun setVideoEncoderConfiguration(params: Map, callback: Callback) { + callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as Map<*, *>))) + } - fun setVideoEncoderConfiguration(config: Map, callback: Callback?) + override fun startPreview(callback: Callback) { + callback.code(engine?.startPreview()) + } - fun startPreview(callback: Callback?) + override fun stopPreview(callback: Callback) { + callback.code(engine?.stopPreview()) + } - fun stopPreview(callback: Callback?) + override fun enableLocalVideo(params: Map, callback: Callback) { + callback.code(engine?.enableLocalVideo(params["enabled"] as Boolean)) + } - fun enableLocalVideo(enabled: Boolean, callback: Callback?) + override fun muteLocalVideoStream(params: Map, callback: Callback) { + callback.code(engine?.muteLocalVideoStream(params["muted"] as Boolean)) + } - fun muteLocalVideoStream(muted: Boolean, callback: Callback?) + override fun muteRemoteVideoStream(params: Map, callback: Callback) { + callback.code(engine?.muteRemoteVideoStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + } - fun muteRemoteVideoStream(uid: Int, muted: Boolean, callback: Callback?) + override fun muteAllRemoteVideoStreams(params: Map, callback: Callback) { + callback.code(engine?.muteAllRemoteVideoStreams(params["muted"] as Boolean)) + } - fun muteAllRemoteVideoStreams(muted: Boolean, callback: Callback?) + override fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) { + callback.code(engine?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as Boolean)) + } - fun setDefaultMuteAllRemoteVideoStreams(muted: Boolean, callback: Callback?) + override fun setBeautyEffectOptions(params: Map, callback: Callback) { + callback.code(engine?.setBeautyEffectOptions(params["enabled"] as Boolean, mapToBeautyOptions(params["options"] as Map<*, *>))) + } - fun setBeautyEffectOptions(enabled: Boolean, options: Map, callback: Callback?) + override fun startAudioMixing(params: Map, callback: Callback) { + callback.code(engine?.startAudioMixing(params["filePath"] as String, params["loopback"] as Boolean, params["replace"] as Boolean, (params["cycle"] as Number).toInt())) } - interface RtcAudioMixingInterface { - fun startAudioMixing(filePath: String, loopback: Boolean, replace: Boolean, cycle: Int, callback: Callback?) + override fun stopAudioMixing(callback: Callback) { + callback.code(engine?.stopAudioMixing()) + } - fun stopAudioMixing(callback: Callback?) + override fun pauseAudioMixing(callback: Callback) { + callback.code(engine?.pauseAudioMixing()) + } - fun pauseAudioMixing(callback: Callback?) + override fun resumeAudioMixing(callback: Callback) { + callback.code(engine?.resumeAudioMixing()) + } - fun resumeAudioMixing(callback: Callback?) + override fun adjustAudioMixingVolume(params: Map, callback: Callback) { + callback.code(engine?.adjustAudioMixingVolume((params["volume"] as Number).toInt())) + } - fun adjustAudioMixingVolume(@IntRange(from = 0, to = 100) volume: Int, callback: Callback?) + override fun adjustAudioMixingPlayoutVolume(params: Map, callback: Callback) { + callback.code(engine?.adjustAudioMixingPlayoutVolume((params["volume"] as Number).toInt())) + } - fun adjustAudioMixingPlayoutVolume(@IntRange(from = 0, to = 400) volume: Int, callback: Callback?) + override fun adjustAudioMixingPublishVolume(params: Map, callback: Callback) { + callback.code(engine?.adjustAudioMixingPublishVolume((params["volume"] as Number).toInt())) + } - fun adjustAudioMixingPublishVolume(@IntRange(from = 0, to = 100) volume: Int, callback: Callback?) + override fun getAudioMixingPlayoutVolume(callback: Callback) { + callback.code(engine?.audioMixingPlayoutVolume) { it } + } - fun getAudioMixingPlayoutVolume(callback: Callback?) + override fun getAudioMixingPublishVolume(callback: Callback) { + callback.code(engine?.audioMixingPublishVolume) { it } + } - fun getAudioMixingPublishVolume(callback: Callback?) + override fun getAudioMixingDuration(callback: Callback) { + callback.code(engine?.audioMixingDuration) { it } + } - fun getAudioMixingDuration(callback: Callback?) + override fun getAudioMixingCurrentPosition(callback: Callback) { + callback.code(engine?.audioMixingCurrentPosition) { it } + } - fun getAudioMixingCurrentPosition(callback: Callback?) + override fun setAudioMixingPosition(params: Map, callback: Callback) { + callback.code(engine?.setAudioMixingPosition((params["pos"] as Number).toInt())) + } - fun setAudioMixingPosition(pos: Int, callback: Callback?) + override fun setAudioMixingPitch(params: Map, callback: Callback) { + callback.code(engine?.setAudioMixingPitch((params["pitch"] as Number).toInt())) + } - fun setAudioMixingPitch(@IntRange(from = -12, to = 12) pitch: Int, callback: Callback?) + override fun getEffectsVolume(callback: Callback) { + callback.resolve(engine) { it.audioEffectManager.effectsVolume } } - interface RtcAudioEffectInterface { - fun getEffectsVolume(callback: Callback?) + override fun setEffectsVolume(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.setEffectsVolume((params["volume"] as Number).toDouble())) + } - fun setEffectsVolume(@FloatRange(from = 0.0, to = 100.0) volume: Double, callback: Callback?) + override fun setVolumeOfEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.setVolumeOfEffect((params["soundId"] as Number).toInt(), (params["volume"] as Number).toDouble())) + } - fun setVolumeOfEffect(soundId: Int, @FloatRange(from = 0.0, to = 100.0) volume: Double, callback: Callback?) + override fun playEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.playEffect((params["soundId"] as Number).toInt(), params["filePath"] as String, (params["loopCount"] as Number).toInt(), (params["pitch"] as Number).toDouble(), (params["pan"] as Number).toDouble(), (params["gain"] as Number).toDouble(), params["publish"] as Boolean)) + } - fun playEffect(soundId: Int, filePath: String, loopCount: Int, @FloatRange(from = 0.5, to = 2.0) pitch: Double, @FloatRange(from = -1.0, to = 1.0) pan: Double, @FloatRange(from = 0.0, to = 100.0) gain: Double, publish: Boolean, callback: Callback?) + override fun stopEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.stopEffect((params["soundId"] as Number).toInt())) + } - fun stopEffect(soundId: Int, callback: Callback?) + override fun stopAllEffects(callback: Callback) { + callback.code(engine?.audioEffectManager?.stopAllEffects()) + } - fun stopAllEffects(callback: Callback?) + override fun preloadEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.preloadEffect((params["soundId"] as Number).toInt(), params["filePath"] as String)) + } - fun preloadEffect(soundId: Int, filePath: String, callback: Callback?) + override fun unloadEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.unloadEffect((params["soundId"] as Number).toInt())) + } - fun unloadEffect(soundId: Int, callback: Callback?) + override fun pauseEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.pauseEffect((params["soundId"] as Number).toInt())) + } - fun pauseEffect(soundId: Int, callback: Callback?) + override fun pauseAllEffects(callback: Callback) { + callback.code(engine?.audioEffectManager?.pauseAllEffects()) + } - fun pauseAllEffects(callback: Callback?) + override fun resumeEffect(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.resumeEffect((params["soundId"] as Number).toInt())) + } - fun resumeEffect(soundId: Int, callback: Callback?) + override fun resumeAllEffects(callback: Callback) { + callback.code(engine?.audioEffectManager?.resumeAllEffects()) + } - fun resumeAllEffects(callback: Callback?) + override fun setLocalVoiceChanger(params: Map, callback: Callback) { + callback.code(engine?.setLocalVoiceChanger((params["voiceChanger"] as Number).toInt())) } - interface RtcVoiceChangerInterface { - fun setLocalVoiceChanger(@Annotations.AgoraAudioVoiceChanger voiceChanger: Int, callback: Callback?) + override fun setLocalVoiceReverbPreset(params: Map, callback: Callback) { + callback.code(engine?.setLocalVoiceReverbPreset((params["preset"] as Number).toInt())) + } - fun setLocalVoiceReverbPreset(@Annotations.AgoraAudioReverbPreset preset: Int, callback: Callback?) + override fun setLocalVoicePitch(params: Map, callback: Callback) { + callback.code(engine?.setLocalVoicePitch((params["pitch"] as Number).toDouble())) + } - fun setLocalVoicePitch(@FloatRange(from = 0.5, to = 2.0) pitch: Double, callback: Callback?) + override fun setLocalVoiceEqualization(params: Map, callback: Callback) { + callback.code(engine?.setLocalVoiceEqualization((params["bandFrequency"] as Number).toInt(), (params["bandGain"] as Number).toInt())) + } - fun setLocalVoiceEqualization(@IntRange(from = 0, to = 9) bandFrequency: Int, @IntRange(from = -15, to = 15) bandGain: Int, callback: Callback?) + override fun setLocalVoiceReverb(params: Map, callback: Callback) { + callback.code(engine?.setLocalVoiceReverb((params["reverbKey"] as Number).toInt(), (params["value"] as Number).toInt())) + } - fun setLocalVoiceReverb(@Annotations.AgoraAudioReverbType reverbKey: Int, value: Int, callback: Callback?) + override fun enableSoundPositionIndication(params: Map, callback: Callback) { + callback.code(engine?.enableSoundPositionIndication(params["enabled"] as Boolean)) } - interface RtcVoicePositionInterface { - fun enableSoundPositionIndication(enabled: Boolean, callback: Callback?) + override fun setRemoteVoicePosition(params: Map, callback: Callback) { + callback.code(engine?.setRemoteVoicePosition((params["uid"] as Number).toInt(), (params["pan"] as Number).toDouble(), (params["gain"] as Number).toDouble())) + } - fun setRemoteVoicePosition(uid: Int, @FloatRange(from = -1.0, to = 1.0) pan: Double, @FloatRange(from = 0.0, to = 100.0) gain: Double, callback: Callback?) + override fun setLiveTranscoding(params: Map, callback: Callback) { + callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as Map<*, *>))) } - interface RtcPublishStreamInterface { - fun setLiveTranscoding(transcoding: Map, callback: Callback?) + override fun addPublishStreamUrl(params: Map, callback: Callback) { + callback.code(engine?.addPublishStreamUrl(params["url"] as String, params["transcodingEnabled"] as Boolean)) + } - fun addPublishStreamUrl(url: String, transcodingEnabled: Boolean, callback: Callback?) + override fun removePublishStreamUrl(params: Map, callback: Callback) { + callback.code(engine?.removePublishStreamUrl(params["url"] as String)) + } - fun removePublishStreamUrl(url: String, callback: Callback?) + override fun startChannelMediaRelay(params: Map, callback: Callback) { + callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) } - interface RtcMediaRelayInterface { - fun startChannelMediaRelay(channelMediaRelayConfiguration: Map, callback: Callback?) + override fun updateChannelMediaRelay(params: Map, callback: Callback) { + callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) + } - fun updateChannelMediaRelay(channelMediaRelayConfiguration: Map, callback: Callback?) + override fun stopChannelMediaRelay(callback: Callback) { + callback.code(engine?.stopChannelMediaRelay()) + } - fun stopChannelMediaRelay(callback: Callback?) + override fun setDefaultAudioRoutetoSpeakerphone(params: Map, callback: Callback) { + callback.code(engine?.setDefaultAudioRoutetoSpeakerphone(params["defaultToSpeaker"] as Boolean)) } - interface RtcAudioRouteInterface { - fun setDefaultAudioRoutetoSpeakerphone(defaultToSpeaker: Boolean, callback: Callback?) + override fun setEnableSpeakerphone(params: Map, callback: Callback) { + callback.code(engine?.setEnableSpeakerphone(params["enabled"] as Boolean)) + } - fun setEnableSpeakerphone(enabled: Boolean, callback: Callback?) + override fun isSpeakerphoneEnabled(callback: Callback) { + callback.resolve(engine) { it.isSpeakerphoneEnabled } + } - fun isSpeakerphoneEnabled(callback: Callback?) + override fun enableInEarMonitoring(params: Map, callback: Callback) { + callback.code(engine?.enableInEarMonitoring(params["enabled"] as Boolean)) } - interface RtcEarMonitoringInterface { - fun enableInEarMonitoring(enabled: Boolean, callback: Callback?) + override fun setInEarMonitoringVolume(params: Map, callback: Callback) { + callback.code(engine?.setInEarMonitoringVolume((params["volume"] as Number).toInt())) + } - fun setInEarMonitoringVolume(@IntRange(from = 0, to = 100) volume: Int, callback: Callback?) + override fun enableDualStreamMode(params: Map, callback: Callback) { + callback.code(engine?.enableDualStreamMode(params["enabled"] as Boolean)) } - interface RtcDualStreamInterface { - fun enableDualStreamMode(enabled: Boolean, callback: Callback?) + override fun setRemoteVideoStreamType(params: Map, callback: Callback) { + callback.code(engine?.setRemoteVideoStreamType((params["uid"] as Number).toInt(), (params["streamType"] as Number).toInt())) + } - fun setRemoteVideoStreamType(uid: Int, @Annotations.AgoraVideoStreamType streamType: Int, callback: Callback?) + override fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) { + callback.code(engine?.setRemoteDefaultVideoStreamType((params["streamType"] as Number).toInt())) + } - fun setRemoteDefaultVideoStreamType(@Annotations.AgoraVideoStreamType streamType: Int, callback: Callback?) + override fun setLocalPublishFallbackOption(params: Map, callback: Callback) { + callback.code(engine?.setLocalPublishFallbackOption((params["option"] as Number).toInt())) } - interface RtcFallbackInterface { - fun setLocalPublishFallbackOption(@Annotations.AgoraStreamFallbackOptions option: Int, callback: Callback?) + override fun setRemoteSubscribeFallbackOption(params: Map, callback: Callback) { + callback.code(engine?.setRemoteSubscribeFallbackOption((params["option"] as Number).toInt())) + } - fun setRemoteSubscribeFallbackOption(@Annotations.AgoraStreamFallbackOptions option: Int, callback: Callback?) + override fun setRemoteUserPriority(params: Map, callback: Callback) { + callback.code(engine?.setRemoteUserPriority((params["uid"] as Number).toInt(), (params["userPriority"] as Number).toInt())) + } - fun setRemoteUserPriority(uid: Int, @Annotations.AgoraUserPriority userPriority: Int, callback: Callback?) + override fun startEchoTest(params: Map, callback: Callback) { + callback.code(engine?.startEchoTest((params["intervalInSeconds"] as Number).toInt())) } - interface RtcTestInterface { - fun startEchoTest(@IntRange(from = 2, to = 10) intervalInSeconds: Int, callback: Callback?) + override fun stopEchoTest(callback: Callback) { + callback.code(engine?.stopEchoTest()) + } - fun stopEchoTest(callback: Callback?) + override fun enableLastmileTest(callback: Callback) { + callback.code(engine?.enableLastmileTest()) + } - fun enableLastmileTest(callback: Callback?) + override fun disableLastmileTest(callback: Callback) { + callback.code(engine?.disableLastmileTest()) + } - fun disableLastmileTest(callback: Callback?) + override fun startLastmileProbeTest(params: Map, callback: Callback) { + callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as Map<*, *>))) + } - fun startLastmileProbeTest(config: Map, callback: Callback?) + override fun stopLastmileProbeTest(callback: Callback) { + callback.code(engine?.stopLastmileProbeTest()) + } - fun stopLastmileProbeTest(callback: Callback?) + override fun registerMediaMetadataObserver(callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + engine?.let { + val mediaObserver = MediaObserver { data -> + emit(RtcEngineEvents.MetadataReceived, data) + } + code = it.registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA) + if (code == 0) this.mediaObserver = mediaObserver + } + callback.code(code) } - interface RtcMediaMetadataInterface { - fun registerMediaMetadataObserver(callback: Callback?) + override fun unregisterMediaMetadataObserver(callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + engine?.let { + code = it.registerMediaMetadataObserver(null, IMetadataObserver.VIDEO_METADATA) + if (code == 0) mediaObserver = null + } + callback.code(code) + } - fun unregisterMediaMetadataObserver(callback: Callback?) + override fun setMaxMetadataSize(params: Map, callback: Callback) { + callback.resolve(mediaObserver) { + it.maxMetadataSize = (params["size"] as Number).toInt() + Unit + } + } - fun setMaxMetadataSize(@IntRange(from = 0, to = 1024) size: Int, callback: Callback?) + override fun sendMetadata(params: Map, callback: Callback) { + callback.resolve(mediaObserver) { + it.addMetadata(params["metadata"] as String) + } + } - fun sendMetadata(metadata: String, callback: Callback?) + override fun addVideoWatermark(params: Map, callback: Callback) { + callback.code(engine?.addVideoWatermark(params["watermarkUrl"] as String, mapToWatermarkOptions(params["options"] as Map<*, *>))) } - interface RtcWatermarkInterface { - fun addVideoWatermark(watermarkUrl: String, options: Map, callback: Callback?) + override fun clearVideoWatermarks(callback: Callback) { + callback.code(engine?.clearVideoWatermarks()) + } - fun clearVideoWatermarks(callback: Callback?) + override fun setEncryptionSecret(params: Map, callback: Callback) { + callback.code(engine?.setEncryptionSecret(params["secret"] as String)) } - interface RtcEncryptionInterface { - fun setEncryptionSecret(secret: String, callback: Callback?) + override fun setEncryptionMode(params: Map, callback: Callback) { + callback.code(engine?.setEncryptionMode(when ((params["encryptionMode"] as Number).toInt()) { + EncryptionConfig.EncryptionMode.AES_128_XTS.value -> "aes-128-xts" + EncryptionConfig.EncryptionMode.AES_128_ECB.value -> "aes-128-ecb" + EncryptionConfig.EncryptionMode.AES_256_XTS.value -> "aes-256-xts" + else -> "" + })) + } - fun setEncryptionMode(@Annotations.AgoraEncryptionMode encryptionMode: String, callback: Callback?) + override fun enableEncryption(params: Map, callback: Callback) { + callback.code(engine?.enableEncryption(params["enabled"] as Boolean, mapToEncryptionConfig(params["config"] as Map<*, *>))) } - interface RtcAudioRecorderInterface { - fun startAudioRecording(filePath: String, sampleRate: Int, @Annotations.AgoraAudioRecordingQuality quality: Int, callback: Callback?) + override fun startAudioRecording(params: Map, callback: Callback) { + callback.code(engine?.startAudioRecording(params["filePath"] as String, (params["sampleRate"] as Number).toInt(), (params["quality"] as Number).toInt())) + } - fun stopAudioRecording(callback: Callback?) + override fun stopAudioRecording(callback: Callback) { + callback.code(engine?.stopAudioRecording()) } - interface RtcInjectStreamInterface { - fun addInjectStreamUrl(url: String, config: Map, callback: Callback?) + override fun addInjectStreamUrl(params: Map, callback: Callback) { + callback.code(engine?.addInjectStreamUrl(params["url"] as String, mapToLiveInjectStreamConfig(params["config"] as Map<*, *>))) + } - fun removeInjectStreamUrl(url: String, callback: Callback?) + override fun removeInjectStreamUrl(params: Map, callback: Callback) { + callback.code(engine?.removeInjectStreamUrl(params["url"] as String)) } - interface RtcCameraInterface { - fun switchCamera(callback: Callback?) + override fun switchCamera(callback: Callback) { + callback.code(engine?.switchCamera()) + } - fun isCameraZoomSupported(callback: Callback?) + override fun isCameraZoomSupported(callback: Callback) { + callback.resolve(engine) { it.isCameraZoomSupported } + } - fun isCameraTorchSupported(callback: Callback?) + override fun isCameraTorchSupported(callback: Callback) { + callback.resolve(engine) { it.isCameraTorchSupported } + } - fun isCameraFocusSupported(callback: Callback?) + override fun isCameraFocusSupported(callback: Callback) { + callback.resolve(engine) { it.isCameraFocusSupported } + } - fun isCameraExposurePositionSupported(callback: Callback?) + override fun isCameraExposurePositionSupported(callback: Callback) { + callback.resolve(engine) { it.isCameraExposurePositionSupported } + } - fun isCameraAutoFocusFaceModeSupported(callback: Callback?) + override fun isCameraAutoFocusFaceModeSupported(callback: Callback) { + callback.resolve(engine) { it.isCameraAutoFocusFaceModeSupported } + } - fun setCameraZoomFactor(@FloatRange(from = 1.0) factor: Float, callback: Callback?) + override fun setCameraZoomFactor(params: Map, callback: Callback) { + callback.code(engine?.setCameraZoomFactor((params["factor"] as Number).toFloat())) + } - fun getCameraMaxZoomFactor(callback: Callback?) + override fun getCameraMaxZoomFactor(callback: Callback) { + callback.resolve(engine) { it.cameraMaxZoomFactor } + } - fun setCameraFocusPositionInPreview(positionX: Float, positionY: Float, callback: Callback?) + override fun setCameraFocusPositionInPreview(params: Map, callback: Callback) { + callback.code(engine?.setCameraFocusPositionInPreview((params["positionX"] as Number).toFloat(), (params["positionY"] as Number).toFloat())) + } - fun setCameraExposurePosition(positionXinView: Float, positionYinView: Float, callback: Callback?) + override fun setCameraExposurePosition(params: Map, callback: Callback) { + callback.code(engine?.setCameraExposurePosition((params["positionXinView"] as Number).toFloat(), (params["positionYinView"] as Number).toFloat())) + } - fun enableFaceDetection(enable: Boolean, callback: Callback?) + override fun enableFaceDetection(params: Map, callback: Callback) { + callback.code(engine?.enableFaceDetection(params["enable"] as Boolean)) + } - fun setCameraTorchOn(isOn: Boolean, callback: Callback?) + override fun setCameraTorchOn(params: Map, callback: Callback) { + callback.code(engine?.setCameraTorchOn(params["isOn"] as Boolean)) + } - fun setCameraAutoFocusFaceModeEnabled(enabled: Boolean, callback: Callback?) + override fun setCameraAutoFocusFaceModeEnabled(params: Map, callback: Callback) { + callback.code(engine?.setCameraAutoFocusFaceModeEnabled(params["enabled"] as Boolean)) + } - fun setCameraCapturerConfiguration(config: Map, callback: Callback?) + override fun setCameraCapturerConfiguration(params: Map, callback: Callback) { + callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as Map<*, *>))) } - interface RtcStreamMessageInterface { - fun createDataStream(reliable: Boolean, ordered: Boolean, callback: Callback?) + override fun createDataStream(params: Map, callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + engine?.let { + code = it.createDataStream(params["reliable"] as Boolean, params["ordered"] as Boolean) + } + callback.code(code) { it } + } - fun sendStreamMessage(streamId: Int, message: String, callback: Callback?) + override fun sendStreamMessage(params: Map, callback: Callback) { + var code = -Constants.ERR_NOT_INITIALIZED + engine?.let { + code = it.sendStreamMessage((params["streamId"] as Number).toInt(), (params["message"] as String).toByteArray()) + } + callback.code(code) } } diff --git a/RtcEngineEvent.kt b/RtcEngineEvent.kt index 00aaaf42e..12215e4c3 100644 --- a/RtcEngineEvent.kt +++ b/RtcEngineEvent.kt @@ -77,6 +77,13 @@ class RtcEngineEvents { const val CameraReady = "CameraReady" const val VideoStopped = "VideoStopped" const val MetadataReceived = "MetadataReceived" + const val FirstLocalAudioFramePublished = "FirstLocalAudioFramePublished" + const val FirstLocalVideoFramePublished = "FirstLocalVideoFramePublished" + const val AudioPublishStateChanged = "AudioPublishStateChanged" + const val VideoPublishStateChanged = "VideoPublishStateChanged" + const val AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + const val VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + const val RtmpStreamingEvent = "RtmpStreamingEvent" fun toMap(): Map { return hashMapOf( @@ -149,7 +156,14 @@ class RtcEngineEvents { "AudioQuality" to AudioQuality, "CameraReady" to CameraReady, "VideoStopped" to VideoStopped, - "MetadataReceived" to MetadataReceived + "MetadataReceived" to MetadataReceived, + "FirstLocalAudioFramePublished" to FirstLocalAudioFramePublished, + "FirstLocalVideoFramePublished" to FirstLocalVideoFramePublished, + "AudioPublishStateChanged" to AudioPublishStateChanged, + "VideoPublishStateChanged" to VideoPublishStateChanged, + "AudioSubscribeStateChanged" to AudioSubscribeStateChanged, + "VideoSubscribeStateChanged" to VideoSubscribeStateChanged, + "RtmpStreamingEvent" to RtmpStreamingEvent ) } } @@ -183,7 +197,7 @@ class RtcEngineEventHandler( } override fun onRejoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) { - callback(RtcEngineEvents.RejoinChannelSuccess, uid, elapsed) + callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) } override fun onLeaveChannel(stats: RtcStats?) { @@ -470,4 +484,32 @@ class RtcEngineEventHandler( override fun onVideoStopped() { callback(RtcEngineEvents.VideoStopped) } + + override fun onFirstLocalAudioFramePublished(elapsed: Int) { + callback(RtcEngineEvents.FirstLocalAudioFramePublished, elapsed) + } + + override fun onFirstLocalVideoFramePublished(elapsed: Int) { + callback(RtcEngineEvents.FirstLocalVideoFramePublished, elapsed) + } + + override fun onAudioPublishStateChanged(channel: String?, @Annotations.AgoraStreamPublishState oldState: Int, @Annotations.AgoraStreamPublishState newState: Int, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioPublishStateChanged, channel, oldState, newState, elapseSinceLastState) + } + + override fun onVideoPublishStateChanged(channel: String?, @Annotations.AgoraStreamPublishState oldState: Int, @Annotations.AgoraStreamPublishState newState: Int, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoPublishStateChanged, channel, oldState, newState, elapseSinceLastState) + } + + override fun onAudioSubscribeStateChanged(channel: String?, uid: Int, @Annotations.AgoraStreamSubscribeState oldState: Int, @Annotations.AgoraStreamSubscribeState newState: Int, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioSubscribeStateChanged, channel, uid, oldState, newState, elapseSinceLastState) + } + + override fun onVideoSubscribeStateChanged(channel: String?, uid: Int, @Annotations.AgoraStreamSubscribeState oldState: Int, @Annotations.AgoraStreamSubscribeState newState: Int, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoSubscribeStateChanged, channel, uid, oldState, newState, elapseSinceLastState) + } + + override fun onRtmpStreamingEvent(url: String?, error: Int) { + callback(RtcEngineEvents.RtmpStreamingEvent, url, error) + } } diff --git a/RtcSurfaceView.kt b/RtcSurfaceView.kt index 59b5dbf3b..f47b7fc0f 100644 --- a/RtcSurfaceView.kt +++ b/RtcSurfaceView.kt @@ -19,8 +19,7 @@ class RtcSurfaceView( try { surface = RtcEngine.CreateRendererView(context) } catch (e: UnsatisfiedLinkError) { - surface = SurfaceView(context) - e.printStackTrace() + throw RuntimeException("Please init RtcEngine first!") } canvas = VideoCanvas(surface) addView(surface) diff --git a/RtcTextureView.kt b/RtcTextureView.kt index 1d4199d66..1a64d6fa8 100644 --- a/RtcTextureView.kt +++ b/RtcTextureView.kt @@ -1,59 +1,73 @@ package io.agora.rtc.base import android.content.Context +import android.view.TextureView import android.widget.FrameLayout import io.agora.rtc.RtcChannel import io.agora.rtc.RtcEngine -import io.agora.rtc.mediaio.AgoraTextureView -import io.agora.rtc.mediaio.MediaIO +import io.agora.rtc.video.VideoCanvas import java.lang.ref.WeakReference class RtcTextureView( context: Context ) : FrameLayout(context) { - private var texture: AgoraTextureView = AgoraTextureView(context) - private var uid: Int = 0 + private var texture: TextureView + private var canvas: VideoCanvas private var channel: WeakReference? = null init { - texture.init(null) - texture.setBufferType(MediaIO.BufferType.BYTE_ARRAY) - texture.setPixelFormat(MediaIO.PixelFormat.I420) + try { + texture = RtcEngine.CreateTextureView(context) + } catch (e: UnsatisfiedLinkError) { + throw RuntimeException("Please init RtcEngine first!") + } + canvas = VideoCanvas(texture) addView(texture) } fun setData(engine: RtcEngine, channel: RtcChannel?, uid: Int) { this.channel = if (channel != null) WeakReference(channel) else null - this.uid = uid - setupVideoRenderer(engine) + canvas.channelId = this.channel?.get()?.channelId() + canvas.uid = uid + setupVideoCanvas(engine) } - fun setMirror(engine: RtcEngine, mirror: Boolean) { - texture.setMirror(mirror) - setupVideoRenderer(engine) + fun resetVideoCanvas(engine: RtcEngine) { + val canvas = VideoCanvas(null, canvas.renderMode, canvas.channelId, canvas.uid, canvas.mirrorMode) + if (canvas.uid == 0) { + engine.setupLocalVideo(canvas) + } else { + engine.setupRemoteVideo(canvas) + } } - fun resetVideoRender(engine: RtcEngine) { - if (uid == 0) { - engine.setLocalVideoRenderer(null) + private fun setupVideoCanvas(engine: RtcEngine) { + if (canvas.uid == 0) { + engine.setupLocalVideo(canvas) } else { - channel?.get()?.let { - it.setRemoteVideoRenderer(uid, null) - return@resetVideoRender - } - engine.setRemoteVideoRenderer(uid, null) + engine.setupRemoteVideo(canvas) } } - private fun setupVideoRenderer(engine: RtcEngine) { - if (uid == 0) { - engine.setLocalVideoRenderer(texture) + fun setRenderMode(engine: RtcEngine, @Annotations.AgoraVideoRenderMode renderMode: Int) { + canvas.renderMode = renderMode + setupRenderMode(engine) + } + + fun setMirrorMode(engine: RtcEngine, @Annotations.AgoraVideoMirrorMode mirrorMode: Int) { + canvas.mirrorMode = mirrorMode + setupRenderMode(engine) + } + + private fun setupRenderMode(engine: RtcEngine) { + if (canvas.uid == 0) { + engine.setLocalRenderMode(canvas.renderMode, canvas.mirrorMode) } else { channel?.get()?.let { - it.setRemoteVideoRenderer(uid, texture) - return@setupVideoRenderer + it.setRemoteRenderMode(canvas.uid, canvas.renderMode, canvas.mirrorMode) + return@setupRenderMode } - engine.setRemoteVideoRenderer(uid, texture) + engine.setRemoteRenderMode(canvas.uid, canvas.renderMode, canvas.mirrorMode) } }