From ca14124066ce7fa6108d5be112a2faf7df5f840b Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 8 Feb 2022 13:42:44 +0800 Subject: [PATCH 1/3] fix: add `AirPlay` to enum `AudioOutputRouting` #582 --- lib/src/enum_converter.g.dart | 1 + lib/src/enums.dart | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/lib/src/enum_converter.g.dart b/lib/src/enum_converter.g.dart index 224162196..54947ebb7 100644 --- a/lib/src/enum_converter.g.dart +++ b/lib/src/enum_converter.g.dart @@ -212,6 +212,7 @@ const _$AudioOutputRoutingEnumMap = { AudioOutputRouting.Speakerphone: 3, AudioOutputRouting.Loudspeaker: 4, AudioOutputRouting.HeadsetBluetooth: 5, + AudioOutputRouting.AirPlay: 9, }; AudioProfileConverter _$AudioProfileConverterFromJson( diff --git a/lib/src/enums.dart b/lib/src/enums.dart index a8eebe093..c07840bc9 100644 --- a/lib/src/enums.dart +++ b/lib/src/enums.dart @@ -279,6 +279,10 @@ enum AudioOutputRouting { /// Bluetooth headset. @JsonValue(5) HeadsetBluetooth, + + /// Apple AirPlay. + @JsonValue(9) + AirPlay, } /// Audio profile. From d474320aa8937aea213f56f98626b71e6dce28f4 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 8 Feb 2022 13:43:11 +0800 Subject: [PATCH 2/3] Squashed 'android/src/main/java/io/agora/rtc/base/' changes from 21c7655..d36dc7e d36dc7e fix: mapToColor issue 8443f1e fix: enable to enabled fbf0147 fix: getAudioFileInfo & selectAudioTrack 987de50 feat: support 3.5.2 4ebf77c feat: support 3.5.1 & plugin 27c788c chore: mapToColor 0278629 feat: support 3.5.0.2 45dcd16 chore: add API which is missing 58ca4b0 fix: AudioRecordingConfiguration bug 4a32e12 chore: prepare to migrate to iris 276c9fe chore: support 3.4.5 783aecf chore: add ERR_ALREADY_IN_RECORDING 3aed6ce fix: startAudioRecording bug 510b405 chore: optimize 4f801b9 chore: optimize ab71f52 chore: optimize startAudioRecording 07f81c7 chore: optimize 5a20e13 style: optimize 858b58f fix(uid compatible): int to uint 8d14d2d feat(upgrade): 3.4.1 be5efea Merge pull request #4 from AgoraLibrary/dev/3.3.0 382f858 Merge branch 'master' into dev/3.3.0 8671535 Merge pull request #3 from AgoraLibrary/dev/3.2.0 feabda3 Merge branch 'master' into dev/3.2.0 9e57891 Merge pull request #2 from AgoraLibrary/dev/3.1.0 df303ee fix: merge some bug fix cd7a2cd feat: support 3.3.1 for Android 551ebfe fix: annotation build warning 9c48594 feat: support 3.3.0 for Android de52ca6 Merge branch 'master' into dev/3.2.0 ddeaefb Merge branch 'master' into dev/3.2.0 2fef3ae feat: add `setClientRole(role: ClientRole, options?: ClientRoleOptions): Promise` fcb57cc feat: upgrade to 3.2.0 REVERT: 21c7655 feat: support 3.0.+ git-subtree-dir: android/src/main/java/io/agora/rtc/base git-subtree-split: d36dc7ed0ad4f69ae251389330f75a5f9dca64b0 --- Annotations.java | 251 ++++++++++++++++-- BeanCovertor.kt | 124 +++++++-- EnumCovertor.kt | 10 + Extensions.kt | 41 ++- MediaObserver.kt | 8 +- RtcChannel.kt | 221 ++++++++++++++-- RtcChannelEvent.kt | 330 ++++++++++++++++++++---- RtcEngine.kt | 588 +++++++++++++++++++++++++++++++++++++++---- RtcEngineEvent.kt | 341 +++++++++++++++++++++---- RtcEnginePlugin.kt | 47 ++++ RtcEngineRegistry.kt | 43 ++++ RtcSurfaceView.kt | 7 +- RtcTextureView.kt | 74 ++++-- 13 files changed, 1844 insertions(+), 241 deletions(-) create mode 100644 RtcEnginePlugin.kt create mode 100644 RtcEngineRegistry.kt diff --git a/Annotations.java b/Annotations.java index 58dfe3e2b..a4fc0fbba 100644 --- a/Annotations.java +++ b/Annotations.java @@ -1,15 +1,16 @@ 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.IRtcEngineEventHandler; import io.agora.rtc.RtcEngineConfig; import io.agora.rtc.video.BeautyOptions; import io.agora.rtc.video.VideoCanvas; +import io.agora.rtc.video.VirtualBackgroundSource; @SuppressWarnings("deprecation") public class Annotations { @@ -82,6 +83,7 @@ public class Annotations { Constants.LOCAL_AUDIO_STREAM_ERROR_DEVICE_BUSY, Constants.LOCAL_AUDIO_STREAM_ERROR_CAPTURE_FAILURE, Constants.LOCAL_AUDIO_STREAM_ERROR_ENCODE_FAILURE, + Constants.LOCAL_AUDIO_STREAM_ERROR_INTERRUPTED, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraAudioLocalError { @@ -98,19 +100,27 @@ public class Annotations { } @IntDef({ - Constants.MEDIA_ENGINE_AUDIO_ERROR_MIXING_OPEN, - Constants.MEDIA_ENGINE_AUDIO_ERROR_MIXING_TOO_FREQUENT, - Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_INTERRUPTED_EOF, - AgoraAudioMixingErrorCode.MEDIA_ENGINE_AUDIO_ERROR_OK, + Constants.AUDIO_MIXING_REASON_CAN_NOT_OPEN, + Constants.AUDIO_MIXING_REASON_TOO_FREQUENT_CALL, + Constants.AUDIO_MIXING_REASON_INTERRUPTED_EOF, + Constants.AUDIO_MIXING_REASON_STARTED_BY_USER, + Constants.AUDIO_MIXING_REASON_ONE_LOOP_COMPLETED, + Constants.AUDIO_MIXING_REASON_START_NEW_LOOP, + Constants.AUDIO_MIXING_REASON_ALL_LOOPS_COMPLETED, + Constants.AUDIO_MIXING_REASON_STOPPED_BY_USER, + Constants.AUDIO_MIXING_REASON_PAUSED_BY_USER, + Constants.AUDIO_MIXING_REASON_RESUMED_BY_USER, + AgoraAudioMixingReason.MEDIA_ENGINE_AUDIO_ERROR_OK, }) @Retention(RetentionPolicy.SOURCE) - public @interface AgoraAudioMixingErrorCode { + public @interface AgoraAudioMixingReason { int MEDIA_ENGINE_AUDIO_ERROR_OK = 0; } @IntDef({ Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_PLAY, Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_PAUSED, + Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_RESTART, Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_STOPPED, Constants.MEDIA_ENGINE_AUDIO_EVENT_MIXING_ERROR, }) @@ -230,6 +240,8 @@ public class Annotations { Constants.AUDIO_SCENARIO_GAME_STREAMING, Constants.AUDIO_SCENARIO_SHOWROOM, Constants.AUDIO_SCENARIO_CHATROOM_GAMING, + Constants.AUDIO_SCENARIO_IOT, + Constants.AUDIO_SCENARIO_MEETING, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraAudioScenario { @@ -264,12 +276,14 @@ public class Annotations { AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_AUTO, AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE, AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_PREVIEW, + AgoraCameraCaptureOutputPreference.CAPTURER_OUTPUT_PREFERENCE_MANUAL, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraCameraCaptureOutputPreference { int CAPTURER_OUTPUT_PREFERENCE_AUTO = 0; int CAPTURER_OUTPUT_PREFERENCE_PERFORMANCE = 1; int CAPTURER_OUTPUT_PREFERENCE_PREVIEW = 2; + int CAPTURER_OUTPUT_PREFERENCE_MANUAL = 3; } @IntDef({ @@ -313,6 +327,10 @@ public class Annotations { Constants.RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_NOT_CHANGE, Constants.RELAY_EVENT_PACKET_UPDATE_DEST_CHANNEL_IS_NULL, Constants.RELAY_EVENT_VIDEO_PROFILE_UPDATE, + Constants.RELAY_EVENT_PAUSE_SEND_PACKET_TO_DEST_CHANNEL_SUCCESS, + Constants.RELAY_EVENT_PAUSE_SEND_PACKET_TO_DEST_CHANNEL_FAILED, + Constants.RELAY_EVENT_RESUME_SEND_PACKET_TO_DEST_CHANNEL_SUCCESS, + Constants.RELAY_EVENT_RESUME_SEND_PACKET_TO_DEST_CHANNEL_FAILED, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraChannelMediaRelayEvent { @@ -361,6 +379,7 @@ public class Annotations { Constants.CONNECTION_CHANGED_RENEW_TOKEN, Constants.CONNECTION_CHANGED_CLIENT_IP_ADDRESS_CHANGED, Constants.CONNECTION_CHANGED_KEEP_ALIVE_TIMEOUT, + Constants.CONNECTION_CHANGED_PROXY_SERVER_INTERRUPTED, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraConnectionChangedReason { @@ -389,16 +408,28 @@ public class Annotations { int MAINTAIN_BALANCED = 2; } - @StringDef({ + @IntDef({ + AgoraEncryptionMode.NONE, AgoraEncryptionMode.AES128XTS, - AgoraEncryptionMode.AES256XTS, AgoraEncryptionMode.AES128ECB, + AgoraEncryptionMode.AES256XTS, + AgoraEncryptionMode.SM4128ECB, + AgoraEncryptionMode.AES128GCM, + AgoraEncryptionMode.AES256GCM, + AgoraEncryptionMode.AES128GCM2, + AgoraEncryptionMode.AES256GCM2, }) @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; + int AES128GCM = 5; + int AES256GCM = 6; + int AES128GCM2 = 7; + int AES256GCM2 = 8; } @IntDef({ @@ -422,6 +453,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, @@ -446,6 +478,8 @@ public class Annotations { Constants.ERR_PUBLISH_STREAM_INTERNAL_SERVER_ERROR, Constants.ERR_PUBLISH_STREAM_NOT_FOUND, Constants.ERR_PUBLISH_STREAM_FORMAT_NOT_SUPPORTED, + Constants.ERR_MODULE_NOT_FOUND, + Constants.ERR_ALREADY_IN_RECORDING, Constants.ERR_LOAD_MEDIA_ENGINE, Constants.ERR_START_CALL, Constants.ERR_START_CAMERA, @@ -519,6 +553,7 @@ public class Annotations { Constants.LOCAL_VIDEO_STREAM_ERROR_DEVICE_BUSY, Constants.LOCAL_VIDEO_STREAM_ERROR_CAPTURE_FAILURE, Constants.LOCAL_VIDEO_STREAM_ERROR_ENCODE_FAILURE, + Constants.LOCAL_VIDEO_STREAM_ERROR_DEVICE_NOT_FOUND }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraLocalVideoStreamError { @@ -586,6 +621,7 @@ public class Annotations { Constants.RTMP_STREAM_PUBLISH_ERROR_NOT_AUTHORIZED, Constants.RTMP_STREAM_PUBLISH_ERROR_STREAM_NOT_FOUND, Constants.RTMP_STREAM_PUBLISH_ERROR_FORMAT_NOT_SUPPORTED, + Constants.RTMP_STREAM_UNPUBLISH_ERROR_OK, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraRtmpStreamingErrorCode { @@ -622,7 +658,7 @@ public class Annotations { @IntDef({ Constants.USER_PRIORITY_HIGH, - Constants.USER_PRIORITY_NORANL, + Constants.USER_PRIORITY_NORMAL, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraUserPriority { @@ -751,26 +787,205 @@ 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, + Constants.WARN_SUPER_RESOLUTION_STREAM_OVER_LIMITATION, + Constants.WARN_SUPER_RESOLUTION_USER_COUNT_OVER_LIMITATION, + Constants.WARN_SUPER_RESOLUTION_DEVICE_NOT_SUPPORTED, }) @Retention(RetentionPolicy.SOURCE) public @interface AgoraWarningCode { } @IntDef({ - RtcEngineConfig.IPAreaCode.AREA_CN, - RtcEngineConfig.IPAreaCode.AREA_NA, - RtcEngineConfig.IPAreaCode.AREA_EUR, - RtcEngineConfig.IPAreaCode.AREA_AS, - RtcEngineConfig.IPAreaCode.AREA_GLOBAL, + 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 { + } + + @IntDef({ + Constants.RTMP_STREAMING_EVENT_FAILED_LOAD_IMAGE, + Constants.RTMP_STREAMING_EVENT_URL_ALREADY_IN_USE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraRtmpStreamingEvent { + } + + @IntDef({ + Constants.AUDIO_EFFECT_OFF, + Constants.ROOM_ACOUSTICS_KTV, + Constants.ROOM_ACOUSTICS_VOCAL_CONCERT, + Constants.ROOM_ACOUSTICS_STUDIO, + Constants.ROOM_ACOUSTICS_PHONOGRAPH, + Constants.ROOM_ACOUSTICS_VIRTUAL_STEREO, + Constants.ROOM_ACOUSTICS_SPACIAL, + Constants.ROOM_ACOUSTICS_ETHEREAL, + Constants.ROOM_ACOUSTICS_3D_VOICE, + Constants.VOICE_CHANGER_EFFECT_UNCLE, + Constants.VOICE_CHANGER_EFFECT_OLDMAN, + Constants.VOICE_CHANGER_EFFECT_BOY, + Constants.VOICE_CHANGER_EFFECT_SISTER, + Constants.VOICE_CHANGER_EFFECT_GIRL, + Constants.VOICE_CHANGER_EFFECT_PIGKING, + Constants.VOICE_CHANGER_EFFECT_HULK, + Constants.STYLE_TRANSFORMATION_RNB, + Constants.STYLE_TRANSFORMATION_POPULAR, + Constants.PITCH_CORRECTION, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraAudioEffectPreset { + } + + @IntDef({ + Constants.VOICE_BEAUTIFIER_OFF, + Constants.CHAT_BEAUTIFIER_MAGNETIC, + Constants.CHAT_BEAUTIFIER_FRESH, + Constants.CHAT_BEAUTIFIER_VITALITY, + Constants.SINGING_BEAUTIFIER, + Constants.TIMBRE_TRANSFORMATION_VIGOROUS, + Constants.TIMBRE_TRANSFORMATION_DEEP, + Constants.TIMBRE_TRANSFORMATION_MELLOW, + Constants.TIMBRE_TRANSFORMATION_FALSETTO, + Constants.TIMBRE_TRANSFORMATION_FULL, + Constants.TIMBRE_TRANSFORMATION_CLEAR, + Constants.TIMBRE_TRANSFORMATION_RESOUNDING, + Constants.TIMBRE_TRANSFORMATION_RINGING, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraVoiceBeautifierPreset { + } + + @IntDef({ + Constants.AUDIENCE_LATENCY_LEVEL_LOW_LATENCY, + Constants.AUDIENCE_LATENCY_LEVEL_ULTRA_LOW_LATENCY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraAudienceLatencyLevelType { + } + + @IntDef({ + Constants.TRANSPORT_TYPE_NONE_PROXY, + Constants.TRANSPORT_TYPE_UDP_PROXY, + Constants.TRANSPORT_TYPE_TCP_PROXY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraCloudProxyType { + } + + @IntDef({ + AgoraLogLevel.LOG_LEVEL_NONE, + AgoraLogLevel.LOG_LEVEL_INFO, + AgoraLogLevel.LOG_LEVEL_WARN, + AgoraLogLevel.LOG_LEVEL_ERROR, + AgoraLogLevel.LOG_LEVEL_FATAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraLogLevel { + int LOG_LEVEL_NONE = 0; + int LOG_LEVEL_INFO = 1; + int LOG_LEVEL_WARN = 2; + int LOG_LEVEL_ERROR = 4; + int LOG_LEVEL_FATAL = 8; + } + + @IntDef({ + Constants.CAPTURE_BRIGHTNESS_LEVEL_INVALID, + Constants.CAPTURE_BRIGHTNESS_LEVEL_NORMAL, + Constants.CAPTURE_BRIGHTNESS_LEVEL_BRIGHT, + Constants.CAPTURE_BRIGHTNESS_LEVEL_DARK, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraCaptureBrightnessLevelType { + } + + @IntDef({ + IRtcEngineEventHandler.UploadErrorReason.UPLOAD_SUCCESS, + IRtcEngineEventHandler.UploadErrorReason.UPLOAD_NET_ERROR, + IRtcEngineEventHandler.UploadErrorReason.UPLOAD_SERVER_ERROR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraUploadErrorReason { + } + + @IntDef({ + IRtcEngineEventHandler.ExperienceQuality.EXPERIENCE_GOOD, + IRtcEngineEventHandler.ExperienceQuality.EXPERIENCE_BAD, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraExperienceQualityType { + } + + @IntDef({ + IRtcEngineEventHandler.ExperiencePoorReason.EXPERIENCE_REASON_NONE, + IRtcEngineEventHandler.ExperiencePoorReason.REMOTE_NETWORK_QUALITY_POOR, + IRtcEngineEventHandler.ExperiencePoorReason.LOCAL_NETWORK_QUALITY_POOR, + IRtcEngineEventHandler.ExperiencePoorReason.WIRELESS_SIGNAL_POOR, + IRtcEngineEventHandler.ExperiencePoorReason.WIFI_BLUETOOTH_COEXIST, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraExperiencePoorReason { + } + + @IntDef({ + Constants.SR_STATE_REASON_SUCCESS, + Constants.SR_STATE_REASON_STREAM_OVER_LIMITATION, + Constants.SR_STATE_REASON_USER_COUNT_OVER_LIMITATION, + Constants.SR_STATE_REASON_DEVICE_NOT_SUPPORTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraSuperResolutionStateReason { + } + + @IntDef({ + VirtualBackgroundSource.BACKGROUND_COLOR, + VirtualBackgroundSource.BACKGROUND_IMG, + VirtualBackgroundSource.BACKGROUND_BLUR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraVirtualBackgroundSourceType { + } + + @IntDef({ + Constants.VBS_STATE_REASON_SUCCESS, + Constants.VBS_STATE_REASON_IMAGE_NOT_EXIST, + Constants.VBS_STATE_REASON_COLOR_FORMAT_NOT_SUPPORTED, + Constants.VBS_STATE_REASON_DEVICE_NOT_SUPPORTED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AgoraVirtualBackgroundSourceStateReason { + } } diff --git a/BeanCovertor.kt b/BeanCovertor.kt index 9854fdea3..f72b2b3dd 100644 --- a/BeanCovertor.kt +++ b/BeanCovertor.kt @@ -1,12 +1,17 @@ package io.agora.rtc.base -import android.graphics.Color import io.agora.rtc.RtcEngineConfig +import io.agora.rtc.audio.AgoraRhythmPlayerConfig +import io.agora.rtc.audio.AudioRecordingConfiguration +import io.agora.rtc.internal.EncryptionConfig import io.agora.rtc.internal.LastmileProbeConfig import io.agora.rtc.live.LiveInjectStreamConfig import io.agora.rtc.live.LiveTranscoding import io.agora.rtc.live.LiveTranscoding.TranscodingUser import io.agora.rtc.models.ChannelMediaOptions +import io.agora.rtc.models.ClientRoleOptions +import io.agora.rtc.models.DataStreamConfig +import io.agora.rtc.models.EchoTestConfiguration import io.agora.rtc.video.* fun mapToVideoDimensions(map: Map<*, *>): VideoEncoderConfiguration.VideoDimensions { @@ -24,7 +29,9 @@ fun mapToVideoEncoderConfiguration(map: Map<*, *>): VideoEncoderConfiguration { (map["bitrate"] as? Number)?.let { bitrate = it.toInt() } (map["minBitrate"] as? Number)?.let { minBitrate = it.toInt() } (map["orientationMode"] as? Number)?.let { orientationMode = intToOrientationMode(it.toInt()) } - (map["degradationPrefer"] as? Number)?.let { degradationPrefer = intToDegradationPreference(it.toInt()) } + (map["degradationPrefer"] as? Number)?.let { + degradationPrefer = intToDegradationPreference(it.toInt()) + } (map["mirrorMode"] as? Number)?.let { mirrorMode = it.toInt() } } } @@ -50,7 +57,7 @@ fun mapToAgoraImage(map: Map<*, *>): AgoraImage { fun mapToTranscodingUser(map: Map<*, *>): TranscodingUser { return TranscodingUser().apply { - (map["uid"] as? Number)?.let { uid = it.toInt() } + (map["uid"] as? Number)?.let { uid = it.toNativeUInt() } (map["x"] as? Number)?.let { x = it.toInt() } (map["y"] as? Number)?.let { y = it.toInt() } (map["width"] as? Number)?.let { width = it.toInt() } @@ -62,11 +69,7 @@ fun mapToTranscodingUser(map: Map<*, *>): TranscodingUser { } fun mapToColor(map: Map<*, *>): Int { - return Color.rgb( - (map["red"] as Number).toInt(), - (map["green"] as Number).toInt(), - (map["blue"] as Number).toInt() - ) + return ((map["red"] as Number).toInt() shl 16) + ((map["green"] as Number).toInt() shl 8) + (map["blue"] as Number).toInt() } fun mapToLiveTranscoding(map: Map<*, *>): LiveTranscoding { @@ -79,11 +82,17 @@ fun mapToLiveTranscoding(map: Map<*, *>): LiveTranscoding { (map["videoGop"] as? Number)?.let { videoGop = it.toInt() } (map["watermark"] as? Map<*, *>)?.let { watermark = mapToAgoraImage(it) } (map["backgroundImage"] as? Map<*, *>)?.let { backgroundImage = mapToAgoraImage(it) } - (map["audioSampleRate"] as? Number)?.let { audioSampleRate = intToLiveTranscodingAudioSampleRate(it.toInt()) } + (map["audioSampleRate"] as? Number)?.let { + audioSampleRate = intToLiveTranscodingAudioSampleRate(it.toInt()) + } (map["audioBitrate"] as? Number)?.let { audioBitrate = it.toInt() } (map["audioChannels"] as? Number)?.let { audioChannels = it.toInt() } - (map["audioCodecProfile"] as? Number)?.let { audioCodecProfile = intToAudioCodecProfile(it.toInt()) } - (map["videoCodecProfile"] as? Number)?.let { videoCodecProfile = intToVideoCodecProfile(it.toInt()) } + (map["audioCodecProfile"] as? Number)?.let { + audioCodecProfile = intToAudioCodecProfile(it.toInt()) + } + (map["videoCodecProfile"] as? Number)?.let { + videoCodecProfile = intToVideoCodecProfile(it.toInt()) + } (map["backgroundColor"] as? Map<*, *>)?.let { backgroundColor = mapToColor(it) } (map["userConfigExtraInfo"] as? String)?.let { userConfigExtraInfo = it } (map["transcodingUsers"] as? List<*>)?.let { list -> @@ -100,7 +109,7 @@ fun mapToChannelMediaInfo(map: Map<*, *>): ChannelMediaInfo { return ChannelMediaInfo( map["channelName"] as? String, map["token"] as? String, - (map["uid"] as Number).toInt() + (map["uid"] as Number).toNativeUInt() ) } @@ -139,8 +148,12 @@ fun mapToRectangle(map: Map<*, *>): WatermarkOptions.Rectangle { fun mapToWatermarkOptions(map: Map<*, *>): WatermarkOptions { return WatermarkOptions().apply { (map["visibleInPreview"] as? Boolean)?.let { visibleInPreview = it } - (map["positionInLandscapeMode"] as? Map<*, *>)?.let { positionInLandscapeMode = mapToRectangle(it) } - (map["positionInPortraitMode"] as? Map<*, *>)?.let { positionInPortraitMode = mapToRectangle(it) } + (map["positionInLandscapeMode"] as? Map<*, *>)?.let { + positionInLandscapeMode = mapToRectangle(it) + } + (map["positionInPortraitMode"] as? Map<*, *>)?.let { + positionInPortraitMode = mapToRectangle(it) + } } } @@ -151,23 +164,39 @@ fun mapToLiveInjectStreamConfig(map: Map<*, *>): LiveInjectStreamConfig { (map["videoGop"] as? Number)?.let { videoGop = it.toInt() } (map["videoFramerate"] as? Number)?.let { videoFramerate = it.toInt() } (map["videoBitrate"] as? Number)?.let { videoBitrate = it.toInt() } - (map["audioSampleRate"] as? Number)?.let { audioSampleRate = intToLiveInjectStreamConfigAudioSampleRate(it.toInt()) } + (map["audioSampleRate"] as? Number)?.let { + audioSampleRate = intToLiveInjectStreamConfigAudioSampleRate(it.toInt()) + } (map["audioBitrate"] as? Number)?.let { audioBitrate = it.toInt() } (map["audioChannels"] as? Number)?.let { audioChannels = it.toInt() } } } +fun mapToRhythmPlayerConfig(map: Map<*, *>): AgoraRhythmPlayerConfig { + return AgoraRhythmPlayerConfig().apply { + (map["beatsPerMeasure"] as? Number)?.let { beatsPerMeasure = it.toInt() } + (map["beatsPerMinute"] as? Number)?.let { beatsPerMinute = it.toInt() } + (map["publish"] as? Boolean)?.let { publish = it } + } +} + fun mapToCameraCapturerConfiguration(map: Map<*, *>): CameraCapturerConfiguration { return CameraCapturerConfiguration( intToCapturerOutputPreference((map["preference"] as Number).toInt()), intToCameraDirection((map["cameraDirection"] as Number).toInt()) - ) + ).apply { + dimensions = CameraCapturerConfiguration.CaptureDimensions() + (map["captureWidth"] as? Number)?.toInt()?.let { dimensions.width = it } + (map["captureHeight"] as? Number)?.toInt()?.let { dimensions.height = it } + } } fun mapToChannelMediaOptions(map: Map<*, *>): ChannelMediaOptions { return ChannelMediaOptions().apply { (map["autoSubscribeAudio"] as? Boolean)?.let { autoSubscribeAudio = it } (map["autoSubscribeVideo"] as? Boolean)?.let { autoSubscribeVideo = it } + (map["publishLocalAudio"] as? Boolean)?.let { publishLocalAudio = it } + (map["publishLocalVideo"] as? Boolean)?.let { publishLocalVideo = it } } } @@ -175,5 +204,68 @@ fun mapToRtcEngineConfig(map: Map<*, *>): RtcEngineConfig { return RtcEngineConfig().apply { mAppId = map["appId"] as String (map["areaCode"] as? Number)?.toInt()?.let { mAreaCode = it } + (map["logConfig"] as? Map<*, *>)?.let { mLogConfig = mapToLogConfig(it) } + } +} + +fun mapToAudioRecordingConfiguration(map: Map<*, *>): AudioRecordingConfiguration { + return AudioRecordingConfiguration().apply { + (map["filePath"] as? String)?.let { filePath = it } + (map["recordingQuality"] as? Number)?.let { recordingQuality = it.toInt() } + (map["recordingPosition"] as? Number)?.let { recordingPosition = it.toInt() } + (map["recordingSampleRate"] as? Number)?.let { recordingSampleRate = it.toInt() } + } +} + +fun mapToEncryptionConfig(map: Map<*, *>): EncryptionConfig { + return EncryptionConfig().apply { + (map["encryptionMode"] as? Number)?.let { encryptionMode = intToEncryptionMode(it.toInt()) } + (map["encryptionKey"] as? String)?.let { encryptionKey = it } + (map["encryptionKdfSalt"] as? List<*>)?.let { list -> + for (i in list.indices) { + (list[i] as? Number)?.let { + encryptionKdfSalt[i] = it.toByte() + } + } + } + } +} + +fun mapToClientRoleOptions(map: Map<*, *>): ClientRoleOptions { + return ClientRoleOptions().apply { + (map["audienceLatencyLevel"] as? Number)?.let { audienceLatencyLevel = it.toInt() } + } +} + +fun mapToLogConfig(map: Map<*, *>): RtcEngineConfig.LogConfig { + return RtcEngineConfig.LogConfig().apply { + (map["filePath"] as? String)?.let { filePath = it } + (map["fileSize"] as? Number)?.let { fileSize = it.toInt() } + (map["level"] as? Number)?.let { level = it.toInt() } + } +} + +fun mapToDataStreamConfig(map: Map<*, *>): DataStreamConfig { + return DataStreamConfig().apply { + (map["syncWithAudio"] as? Boolean)?.let { syncWithAudio = it } + (map["ordered"] as? Boolean)?.let { ordered = it } + } +} + +fun mapToVirtualBackgroundSource(map: Map<*, *>): VirtualBackgroundSource { + return VirtualBackgroundSource().apply { + (map["backgroundSourceType"] as? Number)?.let { backgroundSourceType = it.toInt() } + (map["color"] as? Map<*, *>)?.let { color = mapToColor(it) } + (map["source"] as? String)?.let { source = it } + (map["blur_degree"] as? Int)?.let { blur_degree = it } + } +} + +fun mapToEchoTestConfiguration(map: Map<*, *>): EchoTestConfiguration { + return EchoTestConfiguration().apply { + (map["enableAudio"] as? Boolean)?.let { enableAudio = it } + (map["enableVideo"] as? Boolean)?.let { enableVideo = it } + (map["token"] as? String)?.let { token = it } + (map["channelId"] as? String)?.let { channelId = it } } } diff --git a/EnumCovertor.kt b/EnumCovertor.kt index 166bbfaaf..ea423ce69 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/Extensions.kt b/Extensions.kt index 4fc01e114..cb24c448c 100644 --- a/Extensions.kt +++ b/Extensions.kt @@ -6,7 +6,7 @@ import io.agora.rtc.models.UserInfo fun UserInfo.toMap(): Map { return hashMapOf( - "uid" to uid, + "uid" to uid.toUInt().toLong(), "userAccount" to userAccount ) } @@ -15,13 +15,14 @@ fun LocalAudioStats.toMap(): Map { return hashMapOf( "numChannels" to numChannels, "sentSampleRate" to sentSampleRate, - "sentBitrate" to sentBitrate + "sentBitrate" to sentBitrate, + "txPacketLossRate" to txPacketLossRate ) } fun RtcStats.toMap(): Map { return hashMapOf( - "totalDuration" to totalDuration, + "duration" to totalDuration, "txBytes" to txBytes, "rxBytes" to rxBytes, "txAudioBytes" to txAudioBytes, @@ -34,7 +35,7 @@ fun RtcStats.toMap(): Map { "rxAudioKBitRate" to rxAudioKBitRate, "txVideoKBitRate" to txVideoKBitRate, "rxVideoKBitRate" to rxVideoKBitRate, - "users" to users, + "userCount" to users, "lastmileDelay" to lastmileDelay, "txPacketLossRate" to txPacketLossRate, "rxPacketLossRate" to rxPacketLossRate, @@ -58,7 +59,7 @@ fun Rect.toMap(): Map { fun RemoteAudioStats.toMap(): Map { return hashMapOf( - "uid" to uid, + "uid" to uid.toUInt().toLong(), "quality" to quality, "networkTransportDelay" to networkTransportDelay, "jitterBufferDelay" to jitterBufferDelay, @@ -68,7 +69,11 @@ fun RemoteAudioStats.toMap(): Map { "receivedBitrate" to receivedBitrate, "totalFrozenTime" to totalFrozenTime, "frozenRate" to frozenRate, - "totalActiveTime" to totalActiveTime + "totalActiveTime" to totalActiveTime, + "publishDuration" to publishDuration, + "qoeQuality" to qoeQuality, + "qualityChangedReason" to qualityChangedReason, + "mosValue" to mosValue ) } @@ -85,13 +90,16 @@ fun LocalVideoStats.toMap(): Map { "encodedFrameWidth" to encodedFrameWidth, "encodedFrameHeight" to encodedFrameHeight, "encodedFrameCount" to encodedFrameCount, - "codecType" to codecType + "codecType" to codecType, + "txPacketLossRate" to txPacketLossRate, + "captureFrameRate" to captureFrameRate, + "captureBrightnessLevel" to captureBrightnessLevel ) } fun RemoteVideoStats.toMap(): Map { return hashMapOf( - "uid" to uid, + "uid" to uid.toUInt().toLong(), "delay" to delay, "width" to width, "height" to height, @@ -102,13 +110,14 @@ fun RemoteVideoStats.toMap(): Map { "rxStreamType" to rxStreamType, "totalFrozenTime" to totalFrozenTime, "frozenRate" to frozenRate, - "totalActiveTime" to totalActiveTime + "totalActiveTime" to totalActiveTime, + "publishDuration" to publishDuration ) } fun AudioVolumeInfo.toMap(): Map { return hashMapOf( - "uid" to uid, + "uid" to uid.toUInt().toLong(), "volume" to volume, "vad" to vad, "channelId" to channelId @@ -146,6 +155,18 @@ fun AgoraFacePositionInfo.toMap(): Map { ) } +fun AudioFileInfo.toMap(): Map { + return hashMapOf( + "filePath" to filePath, + "durationMs" to durationMs + ) +} + fun Array.toMapList(): List> { return List(size) { this[it].toMap() } } + +@ExperimentalUnsignedTypes +internal fun Number.toNativeUInt(): Int { + return toLong().toUInt().toInt() +} diff --git a/MediaObserver.kt b/MediaObserver.kt index 21f3b20c3..b763cedeb 100644 --- a/MediaObserver.kt +++ b/MediaObserver.kt @@ -31,8 +31,10 @@ class MediaObserver( } override fun onMetadataReceived(buffer: ByteArray, uid: Int, timeStampMs: Long) { - emit(hashMapOf( - "data" to arrayListOf(String(buffer), uid, timeStampMs) - )) + emit( + hashMapOf( + "data" to arrayListOf(String(buffer), uid.toUInt().toLong(), timeStampMs) + ) + ) } } diff --git a/RtcChannel.kt b/RtcChannel.kt index 320b51165..48621739b 100644 --- a/RtcChannel.kt +++ b/RtcChannel.kt @@ -1,8 +1,10 @@ package io.agora.rtc.base +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.* class IRtcChannel { @@ -26,8 +28,10 @@ class IRtcChannel { fun getConnectionState(params: Map, callback: Callback) + @Deprecated("") fun publish(params: Map, callback: Callback) + @Deprecated("") fun unpublish(params: Map, callback: Callback) fun getCallId(params: Map, callback: Callback) @@ -36,19 +40,27 @@ class IRtcChannel { interface RtcAudioInterface { fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) + fun muteLocalAudioStream(params: Map, callback: Callback) + fun muteRemoteAudioStream(params: Map, callback: Callback) fun muteAllRemoteAudioStreams(params: Map, callback: Callback) + @Deprecated("") fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) } interface RtcVideoInterface { + fun muteLocalVideoStream(params: Map, callback: Callback) + fun muteRemoteVideoStream(params: Map, callback: Callback) fun muteAllRemoteVideoStreams(params: Map, callback: Callback) + @Deprecated("") fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) + + fun enableRemoteSuperResolution(params: Map, callback: Callback) } interface RtcVoicePositionInterface { @@ -69,6 +81,10 @@ class IRtcChannel { fun updateChannelMediaRelay(params: Map, callback: Callback) fun stopChannelMediaRelay(params: Map, callback: Callback) + + fun pauseAllChannelMediaRelay(params: Map, callback: Callback) + + fun resumeAllChannelMediaRelay(params: Map, callback: Callback) } interface RtcDualStreamInterface { @@ -92,9 +108,13 @@ class IRtcChannel { } interface RtcEncryptionInterface { + @Deprecated("") fun setEncryptionSecret(params: Map, callback: Callback) + @Deprecated("") fun setEncryptionMode(params: Map, callback: Callback) + + fun enableEncryption(params: Map, callback: Callback) } interface RtcInjectStreamInterface { @@ -129,7 +149,12 @@ class RtcChannelManager( 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) }) + it.setRtcChannelEventHandler(RtcChannelEventHandler { methodName, data -> + emit( + methodName, + data + ) + }) rtcChannelMap[it.channelId()] = it } Unit @@ -142,15 +167,37 @@ class RtcChannelManager( override fun setClientRole(params: Map, callback: Callback) { val role = (params["role"] as Number).toInt() + (params["options"] as? Map<*, *>)?.let { + callback.code( + this[params["channelId"] as String]?.setClientRole( + role, + mapToClientRoleOptions(it) + ) + ) + return@setClientRole + } callback.code(this[params["channelId"] as String]?.setClientRole(role)) } 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<*, *>))) + callback.code( + this[params["channelId"] as String]?.joinChannel( + params["token"] as? String, + params["optionalInfo"] as? String, + (params["optionalUid"] as Number).toNativeUInt(), + mapToChannelMediaOptions(params["options"] as Map<*, *>) + ) + ) } 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<*, *>))) + callback.code( + this[params["channelId"] as String]?.joinChannelWithUserAccount( + params["token"] as? String, + params["userAccount"] as String, + mapToChannelMediaOptions(params["options"] as Map<*, *>) + ) + ) } override fun leaveChannel(params: Map, callback: Callback) { @@ -178,11 +225,29 @@ class RtcChannelManager( } 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())) + callback.code( + this[params["channelId"] as String]?.adjustUserPlaybackSignalVolume( + (params["uid"] as Number).toNativeUInt(), + (params["volume"] as Number).toInt() + ) + ) + } + + override fun muteLocalAudioStream(params: Map, callback: Callback) { + callback.code( + this[params["channelId"] as String]?.muteLocalAudioStream( + params["muted"] as Boolean + ) + ) } override fun muteRemoteAudioStream(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.muteRemoteAudioStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + callback.code( + this[params["channelId"] as String]?.muteRemoteAudioStream( + (params["uid"] as Number).toNativeUInt(), + params["muted"] as Boolean + ) + ) } override fun muteAllRemoteAudioStreams(params: Map, callback: Callback) { @@ -193,8 +258,21 @@ class RtcChannelManager( callback.code(this[params["channelId"] as String]?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as Boolean)) } + override fun muteLocalVideoStream(params: Map, callback: Callback) { + callback.code( + this[params["channelId"] as String]?.muteLocalVideoStream( + params["muted"] as Boolean + ) + ) + } + override fun muteRemoteVideoStream(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.muteRemoteVideoStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + callback.code( + this[params["channelId"] as String]?.muteRemoteVideoStream( + (params["uid"] as Number).toNativeUInt(), + params["muted"] as Boolean + ) + ) } override fun muteAllRemoteVideoStreams(params: Map, callback: Callback) { @@ -205,16 +283,42 @@ class RtcChannelManager( callback.code(this[params["channelId"] as String]?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as Boolean)) } + override fun enableRemoteSuperResolution(params: Map, callback: Callback) { + callback.code( + this[params["channelId"] as String]?.enableRemoteSuperResolution( + (params["uid"] as Number).toNativeUInt(), + params["enabled"] as Boolean + ) + ) + } + 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())) + callback.code( + this[params["channelId"] as String]?.setRemoteVoicePosition( + (params["uid"] as Number).toNativeUInt(), + (params["pan"] as Number).toDouble(), + (params["gain"] as Number).toDouble() + ) + ) } override fun setLiveTranscoding(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as Map<*, *>))) + callback.code( + this[params["channelId"] as String]?.setLiveTranscoding( + mapToLiveTranscoding( + params["transcoding"] as Map<*, *> + ) + ) + ) } override fun addPublishStreamUrl(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.addPublishStreamUrl(params["url"] as String, params["transcodingEnabled"] as Boolean)) + callback.code( + this[params["channelId"] as String]?.addPublishStreamUrl( + params["url"] as String, + params["transcodingEnabled"] as Boolean + ) + ) } override fun removePublishStreamUrl(params: Map, callback: Callback) { @@ -222,19 +326,42 @@ class RtcChannelManager( } override fun startChannelMediaRelay(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) + callback.code( + this[params["channelId"] as String]?.startChannelMediaRelay( + mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>) + ) + ) } override fun updateChannelMediaRelay(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>))) + callback.code( + this[params["channelId"] as String]?.updateChannelMediaRelay( + mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as Map<*, *>) + ) + ) } override fun stopChannelMediaRelay(params: Map, callback: Callback) { callback.code(this[params["channelId"] as String]?.stopChannelMediaRelay()) } + override fun pauseAllChannelMediaRelay(params: Map, callback: Callback) { + callback.code(-Constants.ERR_NOT_SUPPORTED) +// callback.code(this[params["channelId"] as String]?.pauseAllChannelMediaRelay()) + } + + override fun resumeAllChannelMediaRelay(params: Map, callback: Callback) { + callback.code(-Constants.ERR_NOT_SUPPORTED) +// callback.code(this[params["channelId"] as String]?.resumeAllChannelMediaRelay()) + } + 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())) + callback.code( + this[params["channelId"] as String]?.setRemoteVideoStreamType( + (params["uid"] as Number).toNativeUInt(), + (params["streamType"] as Number).toInt() + ) + ) } override fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) { @@ -242,15 +369,27 @@ class RtcChannelManager( } 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())) + callback.code( + this[params["channelId"] as String]?.setRemoteUserPriority( + (params["uid"] as Number).toNativeUInt(), + (params["userPriority"] as Number).toInt() + ) + ) } override fun registerMediaMetadataObserver(params: Map, callback: Callback) { val channelId = params["channelId"] as String val mediaObserver = MediaObserver { data -> - emit(RtcChannelEvents.MetadataReceived, data?.toMutableMap()?.apply { put("channelId", channelId) }) + emit( + RtcChannelEvents.MetadataReceived, + data?.toMutableMap()?.apply { put("channelId", channelId) }) } - callback.code(this[channelId]?.registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA)) { + callback.code( + this[channelId]?.registerMediaMetadataObserver( + mediaObserver, + IMetadataObserver.VIDEO_METADATA + ) + ) { mediaObserverMap[channelId] = mediaObserver Unit } @@ -258,7 +397,12 @@ class RtcChannelManager( override fun unregisterMediaMetadataObserver(params: Map, callback: Callback) { val channelId = params["channelId"] as String - callback.code(this[channelId]?.registerMediaMetadataObserver(null, IMetadataObserver.VIDEO_METADATA)) { + callback.code( + this[channelId]?.registerMediaMetadataObserver( + null, + IMetadataObserver.VIDEO_METADATA + ) + ) { mediaObserverMap.remove(channelId) Unit } @@ -283,11 +427,34 @@ class RtcChannelManager( } override fun setEncryptionMode(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.setEncryptionMode(params["encryptionMode"] as String)) + 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 -> "" + } + ) + ) + } + + override fun enableEncryption(params: Map, callback: Callback) { + callback.code( + this[params["channelId"] as String]?.enableEncryption( + params["enabled"] as Boolean, + mapToEncryptionConfig(params["config"] as Map<*, *>) + ) + ) } override fun addInjectStreamUrl(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.addInjectStreamUrl(params["url"] as String, mapToLiveInjectStreamConfig(params["config"] as Map<*, *>))) + callback.code( + this[params["channelId"] as String]?.addInjectStreamUrl( + params["url"] as String, + mapToLiveInjectStreamConfig(params["config"] as Map<*, *>) + ) + ) } override fun removeInjectStreamUrl(params: Map, callback: Callback) { @@ -296,10 +463,24 @@ class RtcChannelManager( override fun createDataStream(params: Map, callback: Callback) { val channel = this[params["channelId"] as String] - callback.code(channel?.createDataStream(params["reliable"] as Boolean, params["ordered"] as Boolean)) { it } + (params["config"] as? Map<*, *>)?.let { config -> + callback.code(channel?.createDataStream(mapToDataStreamConfig(config))) { it } + return@createDataStream + } + callback.code( + channel?.createDataStream( + params["reliable"] as Boolean, + params["ordered"] as Boolean + ) + ) { it } } override fun sendStreamMessage(params: Map, callback: Callback) { - callback.code(this[params["channelId"] as String]?.sendStreamMessage((params["streamId"] as Number).toInt(), (params["message"] as String).toByteArray())) + callback.code( + this[params["channelId"] as String]?.sendStreamMessage( + (params["streamId"] as Number).toInt(), + (params["message"] as String).toByteArray() + ) + ) } } diff --git a/RtcChannelEvent.kt b/RtcChannelEvent.kt index e24e0a536..83bc3990c 100644 --- a/RtcChannelEvent.kt +++ b/RtcChannelEvent.kt @@ -37,6 +37,12 @@ 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" + const val UserSuperResolutionEnabled = "UserSuperResolutionEnabled" fun toMap(): Map { return hashMapOf( @@ -69,7 +75,13 @@ 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, + "UserSuperResolutionEnabled" to UserSuperResolutionEnabled ) } } @@ -84,10 +96,12 @@ class RtcChannelEventHandler( private fun callback(methodName: String, channel: RtcChannel?, vararg data: Any?) { channel?.let { - emitter(methodName, hashMapOf( - "channelId" to it.channelId(), - "data" to data.toList() - )) + emitter( + methodName, hashMapOf( + "channelId" to it.channelId(), + "data" to data.toList() + ) + ) } } @@ -100,30 +114,54 @@ class RtcChannelEventHandler( } override fun onJoinChannelSuccess(rtcChannel: RtcChannel?, uid: Int, elapsed: Int) { - callback(RtcChannelEvents.JoinChannelSuccess, rtcChannel, rtcChannel?.channelId(), uid, elapsed) + callback( + RtcChannelEvents.JoinChannelSuccess, + rtcChannel, + rtcChannel?.channelId(), + uid.toUInt().toLong(), + elapsed + ) } override fun onRejoinChannelSuccess(rtcChannel: RtcChannel?, uid: Int, elapsed: Int) { - callback(RtcChannelEvents.RejoinChannelSuccess, rtcChannel, rtcChannel?.channelId(), uid, elapsed) + callback( + RtcChannelEvents.RejoinChannelSuccess, + rtcChannel, + rtcChannel?.channelId(), + uid.toUInt().toLong(), + elapsed + ) } override fun onLeaveChannel(rtcChannel: RtcChannel?, stats: IRtcEngineEventHandler.RtcStats?) { callback(RtcChannelEvents.LeaveChannel, rtcChannel, stats?.toMap()) } - override fun onClientRoleChanged(rtcChannel: RtcChannel?, @Annotations.AgoraClientRole oldRole: Int, @Annotations.AgoraClientRole newRole: Int) { + override fun onClientRoleChanged( + rtcChannel: RtcChannel?, + @Annotations.AgoraClientRole oldRole: Int, + @Annotations.AgoraClientRole newRole: Int + ) { callback(RtcChannelEvents.ClientRoleChanged, rtcChannel, oldRole, newRole) } override fun onUserJoined(rtcChannel: RtcChannel?, uid: Int, elapsed: Int) { - callback(RtcChannelEvents.UserJoined, rtcChannel, uid, elapsed) + callback(RtcChannelEvents.UserJoined, rtcChannel, uid.toUInt().toLong(), elapsed) } - override fun onUserOffline(rtcChannel: RtcChannel?, uid: Int, @Annotations.AgoraUserOfflineReason reason: Int) { - callback(RtcChannelEvents.UserOffline, rtcChannel, uid, reason) + override fun onUserOffline( + rtcChannel: RtcChannel?, + uid: Int, + @Annotations.AgoraUserOfflineReason reason: Int + ) { + callback(RtcChannelEvents.UserOffline, rtcChannel, uid.toUInt().toLong(), reason) } - override fun onConnectionStateChanged(rtcChannel: RtcChannel?, @Annotations.AgoraConnectionStateType state: Int, @Annotations.AgoraConnectionChangedReason reason: Int) { + override fun onConnectionStateChanged( + rtcChannel: RtcChannel?, + @Annotations.AgoraConnectionStateType state: Int, + @Annotations.AgoraConnectionChangedReason reason: Int + ) { callback(RtcChannelEvents.ConnectionStateChanged, rtcChannel, state, reason) } @@ -140,46 +178,119 @@ class RtcChannelEventHandler( } override fun onActiveSpeaker(rtcChannel: RtcChannel?, uid: Int) { - callback(RtcChannelEvents.ActiveSpeaker, rtcChannel, uid) - } - - override fun onVideoSizeChanged(rtcChannel: RtcChannel?, uid: Int, width: Int, height: Int, @IntRange(from = 0, to = 360) rotation: Int) { - callback(RtcChannelEvents.VideoSizeChanged, rtcChannel, uid, width, height, rotation) - } - - override fun onRemoteVideoStateChanged(rtcChannel: RtcChannel?, uid: Int, @Annotations.AgoraVideoRemoteState state: Int, @Annotations.AgoraVideoRemoteStateReason reason: Int, elapsed: Int) { - callback(RtcChannelEvents.RemoteVideoStateChanged, rtcChannel, uid, state, reason, elapsed) - } - - override fun onRemoteAudioStateChanged(rtcChannel: RtcChannel?, uid: Int, @Annotations.AgoraAudioRemoteState state: Int, @Annotations.AgoraAudioRemoteStateReason reason: Int, elapsed: Int) { - callback(RtcChannelEvents.RemoteAudioStateChanged, rtcChannel, uid, state, reason, elapsed) - } - - override fun onLocalPublishFallbackToAudioOnly(rtcChannel: RtcChannel?, isFallbackOrRecover: Boolean) { + callback(RtcChannelEvents.ActiveSpeaker, rtcChannel, uid.toUInt().toLong()) + } + + override fun onVideoSizeChanged( + rtcChannel: RtcChannel?, + uid: Int, + width: Int, + height: Int, + @IntRange(from = 0, to = 360) rotation: Int + ) { + callback( + RtcChannelEvents.VideoSizeChanged, + rtcChannel, + uid.toUInt().toLong(), + width, + height, + rotation + ) + } + + override fun onRemoteVideoStateChanged( + rtcChannel: RtcChannel?, + uid: Int, + @Annotations.AgoraVideoRemoteState state: Int, + @Annotations.AgoraVideoRemoteStateReason reason: Int, + elapsed: Int + ) { + callback( + RtcChannelEvents.RemoteVideoStateChanged, + rtcChannel, + uid.toUInt().toLong(), + state, + reason, + elapsed + ) + } + + override fun onRemoteAudioStateChanged( + rtcChannel: RtcChannel?, + uid: Int, + @Annotations.AgoraAudioRemoteState state: Int, + @Annotations.AgoraAudioRemoteStateReason reason: Int, + elapsed: Int + ) { + callback( + RtcChannelEvents.RemoteAudioStateChanged, + rtcChannel, + uid.toUInt().toLong(), + state, + reason, + elapsed + ) + } + + override fun onLocalPublishFallbackToAudioOnly( + rtcChannel: RtcChannel?, + isFallbackOrRecover: Boolean + ) { callback(RtcChannelEvents.LocalPublishFallbackToAudioOnly, rtcChannel, isFallbackOrRecover) } - override fun onRemoteSubscribeFallbackToAudioOnly(rtcChannel: RtcChannel?, uid: Int, isFallbackOrRecover: Boolean) { - callback(RtcChannelEvents.RemoteSubscribeFallbackToAudioOnly, rtcChannel, uid, isFallbackOrRecover) + override fun onRemoteSubscribeFallbackToAudioOnly( + rtcChannel: RtcChannel?, + uid: Int, + isFallbackOrRecover: Boolean + ) { + callback( + RtcChannelEvents.RemoteSubscribeFallbackToAudioOnly, + rtcChannel, + uid.toUInt().toLong(), + isFallbackOrRecover + ) } override fun onRtcStats(rtcChannel: RtcChannel?, stats: IRtcEngineEventHandler.RtcStats?) { callback(RtcChannelEvents.RtcStats, rtcChannel, stats?.toMap()) } - override fun onNetworkQuality(rtcChannel: RtcChannel?, uid: Int, @Annotations.AgoraNetworkQuality txQuality: Int, @Annotations.AgoraNetworkQuality rxQuality: Int) { - callback(RtcChannelEvents.NetworkQuality, rtcChannel, uid, txQuality, rxQuality) - } - - override fun onRemoteVideoStats(rtcChannel: RtcChannel?, stats: IRtcEngineEventHandler.RemoteVideoStats?) { + override fun onNetworkQuality( + rtcChannel: RtcChannel?, + uid: Int, + @Annotations.AgoraNetworkQuality txQuality: Int, + @Annotations.AgoraNetworkQuality rxQuality: Int + ) { + callback( + RtcChannelEvents.NetworkQuality, + rtcChannel, + uid.toUInt().toLong(), + txQuality, + rxQuality + ) + } + + override fun onRemoteVideoStats( + rtcChannel: RtcChannel?, + stats: IRtcEngineEventHandler.RemoteVideoStats? + ) { callback(RtcChannelEvents.RemoteVideoStats, rtcChannel, stats?.toMap()) } - override fun onRemoteAudioStats(rtcChannel: RtcChannel?, stats: IRtcEngineEventHandler.RemoteAudioStats?) { + override fun onRemoteAudioStats( + rtcChannel: RtcChannel?, + stats: IRtcEngineEventHandler.RemoteAudioStats? + ) { callback(RtcChannelEvents.RemoteAudioStats, rtcChannel, stats?.toMap()) } - override fun onRtmpStreamingStateChanged(rtcChannel: RtcChannel?, url: String?, @Annotations.AgoraRtmpStreamingState state: Int, @Annotations.AgoraRtmpStreamingErrorCode errCode: Int) { + override fun onRtmpStreamingStateChanged( + rtcChannel: RtcChannel?, + url: String?, + @Annotations.AgoraRtmpStreamingState state: Int, + @Annotations.AgoraRtmpStreamingErrorCode errCode: Int + ) { callback(RtcChannelEvents.RtmpStreamingStateChanged, rtcChannel, url, state, errCode) } @@ -187,23 +298,146 @@ class RtcChannelEventHandler( callback(RtcChannelEvents.TranscodingUpdated, rtcChannel) } - override fun onStreamInjectedStatus(rtcChannel: RtcChannel?, url: String?, uid: Int, @Annotations.AgoraInjectStreamStatus status: Int) { - callback(RtcChannelEvents.StreamInjectedStatus, rtcChannel, url, uid, status) + override fun onStreamInjectedStatus( + rtcChannel: RtcChannel?, + url: String?, + uid: Int, + @Annotations.AgoraInjectStreamStatus status: Int + ) { + callback(RtcChannelEvents.StreamInjectedStatus, rtcChannel, url, uid.toUInt().toLong(), status) } override fun onStreamMessage(rtcChannel: RtcChannel?, uid: Int, streamId: Int, data: ByteArray?) { - callback(RtcChannelEvents.StreamMessage, rtcChannel, uid, streamId, data?.let { String(it, Charsets.UTF_8) }) - } - - override fun onStreamMessageError(rtcChannel: RtcChannel?, uid: Int, streamId: Int, @Annotations.AgoraErrorCode error: Int, missed: Int, cached: Int) { - callback(RtcChannelEvents.StreamMessageError, rtcChannel, uid, streamId, error, missed, cached) - } - - override fun onChannelMediaRelayStateChanged(rtcChannel: RtcChannel?, @Annotations.AgoraChannelMediaRelayState state: Int, @Annotations.AgoraChannelMediaRelayError code: Int) { + callback( + RtcChannelEvents.StreamMessage, + rtcChannel, + uid.toUInt().toLong(), + streamId, + data?.let { String(it, Charsets.UTF_8) }) + } + + override fun onStreamMessageError( + rtcChannel: RtcChannel?, + uid: Int, + streamId: Int, + @Annotations.AgoraErrorCode error: Int, + missed: Int, + cached: Int + ) { + callback( + RtcChannelEvents.StreamMessageError, + rtcChannel, + uid.toUInt().toLong(), + streamId, + error, + missed, + cached + ) + } + + override fun onChannelMediaRelayStateChanged( + rtcChannel: RtcChannel?, + @Annotations.AgoraChannelMediaRelayState state: Int, + @Annotations.AgoraChannelMediaRelayError code: Int + ) { callback(RtcChannelEvents.ChannelMediaRelayStateChanged, rtcChannel, state, code) } - override fun onChannelMediaRelayEvent(rtcChannel: RtcChannel?, @Annotations.AgoraChannelMediaRelayEvent code: Int) { + 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, + rtcChannel?.channelId(), + oldState, + newState, + elapseSinceLastState + ) + } + + override fun onVideoPublishStateChanged( + rtcChannel: RtcChannel?, + @Annotations.AgoraStreamPublishState oldState: Int, + @Annotations.AgoraStreamPublishState newState: Int, + elapseSinceLastState: Int + ) { + callback( + RtcChannelEvents.VideoPublishStateChanged, + rtcChannel, + rtcChannel?.channelId(), + oldState, + newState, + elapseSinceLastState + ) + } + + override fun onAudioSubscribeStateChanged( + rtcChannel: RtcChannel?, + uid: Int, + @Annotations.AgoraStreamSubscribeState oldState: Int, + @Annotations.AgoraStreamSubscribeState newState: Int, + elapseSinceLastState: Int + ) { + callback( + RtcChannelEvents.AudioSubscribeStateChanged, + rtcChannel, + rtcChannel?.channelId(), + uid.toUInt().toLong(), + oldState, + newState, + elapseSinceLastState + ) + } + + override fun onVideoSubscribeStateChanged( + rtcChannel: RtcChannel?, + uid: Int, + @Annotations.AgoraStreamSubscribeState oldState: Int, + @Annotations.AgoraStreamSubscribeState newState: Int, + elapseSinceLastState: Int + ) { + callback( + RtcChannelEvents.VideoSubscribeStateChanged, + rtcChannel, + rtcChannel?.channelId(), + uid.toUInt().toLong(), + oldState, + newState, + elapseSinceLastState + ) + } + + override fun onRtmpStreamingEvent( + rtcChannel: RtcChannel?, + url: String?, + @Annotations.AgoraRtmpStreamingEvent errCode: Int + ) { + callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, errCode) + } + + override fun onUserSuperResolutionEnabled( + rtcChannel: RtcChannel?, + uid: Int, + enabled: Boolean, + @Annotations.AgoraSuperResolutionStateReason reason: Int + ) { + callback( + RtcChannelEvents.UserSuperResolutionEnabled, + rtcChannel, + uid.toUInt().toLong(), + enabled, + reason + ) + } } diff --git a/RtcEngine.kt b/RtcEngine.kt index 7d620e90c..9b2566076 100644 --- a/RtcEngine.kt +++ b/RtcEngine.kt @@ -1,10 +1,8 @@ package io.agora.rtc.base import android.content.Context -import io.agora.rtc.Constants -import io.agora.rtc.IMetadataObserver -import io.agora.rtc.RtcEngine -import io.agora.rtc.RtcEngineEx +import io.agora.rtc.* +import io.agora.rtc.internal.EncryptionConfig import io.agora.rtc.models.UserInfo class IRtcEngine { @@ -36,21 +34,42 @@ class IRtcEngine { fun getConnectionState(callback: Callback) + fun sendCustomReportMessage(params: Map, callback: Callback) + fun getCallId(callback: Callback) fun rate(params: Map, callback: Callback) fun complain(params: Map, callback: Callback) + @Deprecated("") fun setLogFile(params: Map, callback: Callback) + @Deprecated("") fun setLogFilter(params: Map, callback: Callback) + @Deprecated("") fun setLogFileSize(params: Map, callback: Callback) fun setParameters(params: Map, callback: Callback) + fun getSdkVersion(callback: Callback) + + fun getErrorDescription(params: Map, callback: Callback) + fun getNativeHandle(callback: Callback) + + fun enableDeepLearningDenoise(params: Map, callback: Callback) + + fun setCloudProxy(params: Map, callback: Callback) + + fun uploadLogFile(callback: Callback) + + fun setLocalAccessPoint(params: Map, callback: Callback) + + fun enableVirtualBackground(params: Map, callback: Callback) + + fun takeSnapshot(params: Map, callback: Callback) } interface RtcUserInfoInterface { @@ -84,9 +103,16 @@ class IRtcEngine { fun muteAllRemoteAudioStreams(params: Map, callback: Callback) + @Deprecated("") fun setDefaultMuteAllRemoteAudioStreams(params: Map, callback: Callback) fun enableAudioVolumeIndication(params: Map, callback: Callback) + + fun startRhythmPlayer(params: Map, callback: Callback) + + fun stopRhythmPlayer(callback: Callback) + + fun configRhythmPlayer(params: Map, callback: Callback) } interface RtcVideoInterface { @@ -108,9 +134,12 @@ class IRtcEngine { fun muteAllRemoteVideoStreams(params: Map, callback: Callback) + @Deprecated("") fun setDefaultMuteAllRemoteVideoStreams(params: Map, callback: Callback) fun setBeautyEffectOptions(params: Map, callback: Callback) + + fun enableRemoteSuperResolution(params: Map, callback: Callback) } interface RtcAudioMixingInterface { @@ -132,13 +161,23 @@ class IRtcEngine { fun getAudioMixingPublishVolume(callback: Callback) - fun getAudioMixingDuration(callback: Callback) + fun getAudioMixingDuration(params: Map, callback: Callback) + + fun getAudioFileInfo(params: Map, callback: Callback) fun getAudioMixingCurrentPosition(callback: Callback) fun setAudioMixingPosition(params: Map, callback: Callback) fun setAudioMixingPitch(params: Map, callback: Callback) + + fun setAudioMixingPlaybackSpeed(params: Map, callback: Callback) + + fun getAudioTrackCount(callback: Callback) + + fun selectAudioTrack(params: Map, callback: Callback) + + fun setAudioMixingDualMonoMode(params: Map, callback: Callback) } interface RtcAudioEffectInterface { @@ -150,6 +189,12 @@ class IRtcEngine { fun playEffect(params: Map, callback: Callback) + fun setEffectPosition(params: Map, callback: Callback) + + fun getEffectDuration(params: Map, callback: Callback) + + fun getEffectCurrentPosition(params: Map, callback: Callback) + fun stopEffect(params: Map, callback: Callback) fun stopAllEffects(callback: Callback) @@ -170,8 +215,10 @@ class IRtcEngine { } interface RtcVoiceChangerInterface { + @Deprecated("") fun setLocalVoiceChanger(params: Map, callback: Callback) + @Deprecated("") fun setLocalVoiceReverbPreset(params: Map, callback: Callback) fun setLocalVoicePitch(params: Map, callback: Callback) @@ -179,6 +226,16 @@ class IRtcEngine { fun setLocalVoiceEqualization(params: Map, callback: Callback) fun setLocalVoiceReverb(params: Map, callback: Callback) + + fun setAudioEffectPreset(params: Map, callback: Callback) + + fun setVoiceBeautifierPreset(params: Map, callback: Callback) + + fun setVoiceConversionPreset(params: Map, callback: Callback) + + fun setAudioEffectParameters(params: Map, callback: Callback) + + fun setVoiceBeautifierParameters(params: Map, callback: Callback) } interface RtcVoicePositionInterface { @@ -201,6 +258,10 @@ class IRtcEngine { fun updateChannelMediaRelay(params: Map, callback: Callback) fun stopChannelMediaRelay(callback: Callback) + + fun pauseAllChannelMediaRelay(callback: Callback) + + fun resumeAllChannelMediaRelay(callback: Callback) } interface RtcAudioRouteInterface { @@ -264,9 +325,13 @@ class IRtcEngine { } interface RtcEncryptionInterface { + @Deprecated("") fun setEncryptionSecret(params: Map, callback: Callback) + @Deprecated("") fun setEncryptionMode(params: Map, callback: Callback) + + fun enableEncryption(params: Map, callback: Callback) } interface RtcAudioRecorderInterface { @@ -318,31 +383,51 @@ class IRtcEngine { } } -class RtcEngineManager( - private val emit: (methodName: String, data: Map?) -> Unit +open class RtcEngineFactory { + open fun create( + params: Map, + rtcEngineEventHandler: RtcEngineEventHandler + ): RtcEngine? { + val engine = RtcEngineEx.create(mapToRtcEngineConfig(params["config"] as Map<*, *>).apply { + mContext = params["context"] as Context + mEventHandler = rtcEngineEventHandler + }) + + return engine + } +} + +open class RtcEngineManager( + private val emit: (methodName: String, data: Map?) -> Unit, + private val rtcEngineFactory: RtcEngineFactory = RtcEngineFactory() ) : IRtcEngine.RtcEngineInterface { var engine: RtcEngine? = null private set private var mediaObserver: MediaObserver? = null fun release() { - RtcEngine.destroy() - engine = null + if (engine != null) { + RtcEngine.destroy() + engine = null + } mediaObserver = null } override fun create(params: Map, callback: Callback) { - engine = RtcEngineEx.create(mapToRtcEngineConfig(params["config"] as Map<*, *>).apply { - mContext = params["context"] as Context - mEventHandler = RtcEngineEventHandler { methodName, data -> - emit(methodName, data) - } + engine = rtcEngineFactory.create(params, RtcEngineEventHandler { methodName, data -> + emit(methodName, data) }) - callback.code((engine as RtcEngineEx).setAppType((params["appType"] as Number).toInt())) + callback.code((engine as RtcEngineEx).setAppType((params["appType"] as Number).toInt())) { + RtcEngineRegistry.instance.onRtcEngineCreated(engine) + it + } } override fun destroy(callback: Callback) { - callback.resolve(engine) { release() } + callback.resolve(engine) { + release() + RtcEngineRegistry.instance.onRtcEngineDestroyed() + } } override fun setChannelProfile(params: Map, callback: Callback) { @@ -351,6 +436,10 @@ class RtcEngineManager( override fun setClientRole(params: Map, callback: Callback) { val role = (params["role"] as Number).toInt() + (params["options"] as? Map<*, *>)?.let { + callback.code(engine?.setClientRole(role, mapToClientRoleOptions(it))) + return@setClientRole + } callback.code(engine?.setClientRole(role)) } @@ -358,13 +447,29 @@ class RtcEngineManager( val token = params["token"] as? String val channelName = params["channelName"] as String val optionalInfo = params["optionalInfo"] as? String - val optionalUid = (params["optionalUid"] as Number).toInt() + val optionalUid = (params["optionalUid"] as Number).toNativeUInt() + (params["options"] as? Map<*, *>)?.let { + callback.code( + engine?.joinChannel( + token, + channelName, + optionalInfo, + optionalUid, + mapToChannelMediaOptions(it) + ) + ) + return@joinChannel + } callback.code(engine?.joinChannel(token, channelName, optionalInfo, optionalUid)) } override fun switchChannel(params: Map, callback: Callback) { val token = params["token"] as? String val channelName = params["channelName"] as String + (params["options"] as? Map<*, *>)?.let { + callback.code(engine?.switchChannel(token, channelName, mapToChannelMediaOptions(it))) + return@switchChannel + } callback.code(engine?.switchChannel(token, channelName)) } @@ -384,12 +489,30 @@ class RtcEngineManager( callback.resolve(engine) { it.connectionState } } + override fun sendCustomReportMessage(params: Map, callback: Callback) { + callback.code( + engine?.sendCustomReportMessage( + params["id"] as String, + params["category"] as String, + params["event"] as String, + params["label"] as String, + (params["value"] as Number).toInt() + ) + ) + } + override fun getCallId(callback: Callback) { callback.resolve(engine) { it.callId } } override fun rate(params: Map, callback: Callback) { - callback.code(engine?.rate(params["callId"] as String, (params["rating"] as Number).toInt(), params["description"] as? String)) + callback.code( + engine?.rate( + params["callId"] as String, + (params["rating"] as Number).toInt(), + params["description"] as? String + ) + ) } override fun complain(params: Map, callback: Callback) { @@ -412,18 +535,90 @@ class RtcEngineManager( callback.code(engine?.setParameters(params["parameters"] as String)) } + override fun getSdkVersion(callback: Callback) { + callback.success(RtcEngine.getSdkVersion()) + } + + override fun getErrorDescription(params: Map, callback: Callback) { + callback.success(RtcEngine.getErrorDescription((params["error"] as Number).toInt())) + } + override fun getNativeHandle(callback: Callback) { callback.resolve(engine) { it.nativeHandle } } + override fun enableDeepLearningDenoise(params: Map, callback: Callback) { + callback.code(engine?.enableDeepLearningDenoise(params["enabled"] as Boolean)) + } + + override fun setCloudProxy(params: Map, callback: Callback) { + callback.code(engine?.setCloudProxy((params["proxyType"] as Number).toInt())) + } + + override fun uploadLogFile(callback: Callback) { + callback.resolve(engine) { it.uploadLogFile() } + } + + override fun setLocalAccessPoint(params: Map, callback: Callback) { + callback.code( + engine?.setLocalAccessPoint( + arrayListOf().apply { + (params["ips"] as? List<*>)?.let { list -> + list.forEach { item -> + (item as? String)?.let { + add(it) + } + } + } + }, + params["domain"] as String + ) + ) + } + + override fun enableVirtualBackground(params: Map, callback: Callback) { + callback.code( + engine?.enableVirtualBackground( + params["enabled"] as Boolean, + mapToVirtualBackgroundSource(params["backgroundSource"] as Map<*, *>) + ) + ) + } + + override fun takeSnapshot(params: Map, callback: Callback) { + callback.code( + engine?.takeSnapshot( + params["channel"] as String, + (params["uid"] as Number).toNativeUInt(), + params["filePath"] as String + ) + ) + } + override fun registerLocalUserAccount(params: Map, callback: Callback) { - callback.code(engine?.registerLocalUserAccount(params["appId"] as String, params["userAccount"] as String)) + callback.code( + engine?.registerLocalUserAccount( + params["appId"] as String, + params["userAccount"] as String + ) + ) } override fun joinChannelWithUserAccount(params: Map, callback: Callback) { val token = params["token"] as? String val channelName = params["channelName"] as String val userAccount = params["userAccount"] as String + (params["options"] as? Map<*, *>)?.let { + callback.code( + engine?.joinChannelWithUserAccount( + token, + channelName, + userAccount, + mapToChannelMediaOptions(it) + ) + ) + return@joinChannelWithUserAccount + } callback.code(engine?.joinChannelWithUserAccount(token, channelName, userAccount)) } @@ -438,7 +633,7 @@ class RtcEngineManager( override fun getUserInfoByUid(params: Map, callback: Callback) { callback.resolve(engine) { val userInfo = UserInfo() - it.getUserInfoByUid((params["uid"] as Number).toInt(), userInfo) + it.getUserInfoByUid((params["uid"] as Number).toNativeUInt(), userInfo) userInfo.toMap() } } @@ -452,7 +647,12 @@ class RtcEngineManager( } override fun setAudioProfile(params: Map, callback: Callback) { - callback.code(engine?.setAudioProfile((params["profile"] as Number).toInt(), (params["scenario"] as Number).toInt())) + callback.code( + engine?.setAudioProfile( + (params["profile"] as Number).toInt(), + (params["scenario"] as Number).toInt() + ) + ) } override fun adjustRecordingSignalVolume(params: Map, callback: Callback) { @@ -460,7 +660,12 @@ class RtcEngineManager( } override fun adjustUserPlaybackSignalVolume(params: Map, callback: Callback) { - callback.code(engine?.adjustUserPlaybackSignalVolume((params["uid"] as Number).toInt(), (params["volume"] as Number).toInt())) + callback.code( + engine?.adjustUserPlaybackSignalVolume( + (params["uid"] as Number).toNativeUInt(), + (params["volume"] as Number).toInt() + ) + ) } override fun adjustPlaybackSignalVolume(params: Map, callback: Callback) { @@ -476,7 +681,12 @@ class RtcEngineManager( } override fun muteRemoteAudioStream(params: Map, callback: Callback) { - callback.code(engine?.muteRemoteAudioStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + callback.code( + engine?.muteRemoteAudioStream( + (params["uid"] as Number).toNativeUInt(), + params["muted"] as Boolean + ) + ) } override fun muteAllRemoteAudioStreams(params: Map, callback: Callback) { @@ -488,7 +698,31 @@ class RtcEngineManager( } 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)) + callback.code( + engine?.enableAudioVolumeIndication( + (params["interval"] as Number).toInt(), + (params["smooth"] as Number).toInt(), + params["report_vad"] as Boolean + ) + ) + } + + override fun startRhythmPlayer(params: Map, callback: Callback) { + callback.code( + engine?.audioEffectManager?.startRhythmPlayer( + params["sound1"] as String, + params["sound2"] as String, + mapToRhythmPlayerConfig(params["config"] as Map<*, *>) + ) + ) + } + + override fun stopRhythmPlayer(callback: Callback) { + callback.code(engine?.audioEffectManager?.stopRhythmPlayer()) + } + + override fun configRhythmPlayer(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.configRhythmPlayer(mapToRhythmPlayerConfig(params as Map<*, *>))) } override fun enableVideo(callback: Callback) { @@ -520,7 +754,12 @@ class RtcEngineManager( } override fun muteRemoteVideoStream(params: Map, callback: Callback) { - callback.code(engine?.muteRemoteVideoStream((params["uid"] as Number).toInt(), params["muted"] as Boolean)) + callback.code( + engine?.muteRemoteVideoStream( + (params["uid"] as Number).toNativeUInt(), + params["muted"] as Boolean + ) + ) } override fun muteAllRemoteVideoStreams(params: Map, callback: Callback) { @@ -532,11 +771,44 @@ class RtcEngineManager( } override fun setBeautyEffectOptions(params: Map, callback: Callback) { - callback.code(engine?.setBeautyEffectOptions(params["enabled"] as Boolean, mapToBeautyOptions(params["options"] as Map<*, *>))) + callback.code( + engine?.setBeautyEffectOptions( + params["enabled"] as Boolean, + mapToBeautyOptions(params["options"] as Map<*, *>) + ) + ) + } + + override fun enableRemoteSuperResolution(params: Map, callback: Callback) { + callback.code( + engine?.enableRemoteSuperResolution( + (params["uid"] as Number).toNativeUInt(), + params["enabled"] as Boolean + ) + ) } 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())) + (params["startPos"] as? Number)?.let { startPos -> + callback.code( + engine?.startAudioMixing( + params["filePath"] as String, + params["loopback"] as Boolean, + params["replace"] as Boolean, + (params["cycle"] as Number).toInt(), + startPos.toInt() + ) + ) + return@startAudioMixing + } + callback.code( + engine?.startAudioMixing( + params["filePath"] as String, + params["loopback"] as Boolean, + params["replace"] as Boolean, + (params["cycle"] as Number).toInt() + ) + ) } override fun stopAudioMixing(callback: Callback) { @@ -571,10 +843,14 @@ class RtcEngineManager( callback.code(engine?.audioMixingPublishVolume) { it } } - override fun getAudioMixingDuration(callback: Callback) { + override fun getAudioMixingDuration(params: Map, callback: Callback) { callback.code(engine?.audioMixingDuration) { it } } + override fun getAudioFileInfo(params: Map, callback: Callback) { + callback.code(engine?.getAudioFileInfo(params["filePath"] as String)) + } + override fun getAudioMixingCurrentPosition(callback: Callback) { callback.code(engine?.audioMixingCurrentPosition) { it } } @@ -587,6 +863,22 @@ class RtcEngineManager( callback.code(engine?.setAudioMixingPitch((params["pitch"] as Number).toInt())) } + override fun setAudioMixingPlaybackSpeed(params: Map, callback: Callback) { + callback.code(engine?.setAudioMixingPlaybackSpeed((params["speed"] as Number).toInt())) + } + + override fun getAudioTrackCount(callback: Callback) { + callback.code(engine?.audioTrackCount) { it } + } + + override fun selectAudioTrack(params: Map, callback: Callback) { + callback.code(engine?.selectAudioTrack((params["index"] as Number).toInt())) + } + + override fun setAudioMixingDualMonoMode(params: Map, callback: Callback) { + callback.code(engine?.setAudioMixingDualMonoMode((params["mode"] as Number).toInt())) + } + override fun getEffectsVolume(callback: Callback) { callback.resolve(engine) { it.audioEffectManager.effectsVolume } } @@ -596,11 +888,60 @@ class RtcEngineManager( } override fun setVolumeOfEffect(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.setVolumeOfEffect((params["soundId"] as Number).toInt(), (params["volume"] as Number).toDouble())) + callback.code( + engine?.audioEffectManager?.setVolumeOfEffect( + (params["soundId"] as Number).toInt(), + (params["volume"] as Number).toDouble() + ) + ) } 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)) + (params["startPos"] as? Number)?.let { startPos -> + 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, + startPos.toInt() + ) + ) + return@playEffect + } + 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 + ) + ) + } + + override fun setEffectPosition(params: Map, callback: Callback) { + callback.code( + engine?.audioEffectManager?.setEffectPosition( + (params["soundId"] as Number).toInt(), + (params["pos"] as Number).toInt() + ) + ) + } + + override fun getEffectDuration(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.getEffectDuration(params["filePath"] as String)) { + it + } + } + + override fun getEffectCurrentPosition(params: Map, callback: Callback) { + callback.code(engine?.audioEffectManager?.getEffectCurrentPosition((params["soundId"] as Number).toInt())) { it } } override fun stopEffect(params: Map, callback: Callback) { @@ -612,7 +953,12 @@ class RtcEngineManager( } override fun preloadEffect(params: Map, callback: Callback) { - callback.code(engine?.audioEffectManager?.preloadEffect((params["soundId"] as Number).toInt(), params["filePath"] as String)) + callback.code( + engine?.audioEffectManager?.preloadEffect( + (params["soundId"] as Number).toInt(), + params["filePath"] as String + ) + ) } override fun unloadEffect(params: Map, callback: Callback) { @@ -652,11 +998,53 @@ class RtcEngineManager( } override fun setLocalVoiceEqualization(params: Map, callback: Callback) { - callback.code(engine?.setLocalVoiceEqualization((params["bandFrequency"] as Number).toInt(), (params["bandGain"] as Number).toInt())) + callback.code( + engine?.setLocalVoiceEqualization( + (params["bandFrequency"] as Number).toInt(), + (params["bandGain"] as Number).toInt() + ) + ) } override fun setLocalVoiceReverb(params: Map, callback: Callback) { - callback.code(engine?.setLocalVoiceReverb((params["reverbKey"] as Number).toInt(), (params["value"] as Number).toInt())) + callback.code( + engine?.setLocalVoiceReverb( + (params["reverbKey"] as Number).toInt(), + (params["value"] as Number).toInt() + ) + ) + } + + override fun setAudioEffectPreset(params: Map, callback: Callback) { + callback.code(engine?.setAudioEffectPreset((params["preset"] as Number).toInt())) + } + + override fun setVoiceBeautifierPreset(params: Map, callback: Callback) { + callback.code(engine?.setVoiceBeautifierPreset((params["preset"] as Number).toInt())) + } + + override fun setVoiceConversionPreset(params: Map, callback: Callback) { + callback.code(engine?.setVoiceConversionPreset((params["preset"] as Number).toInt())) + } + + override fun setAudioEffectParameters(params: Map, callback: Callback) { + callback.code( + engine?.setAudioEffectParameters( + (params["preset"] as Number).toInt(), + (params["param1"] as Number).toInt(), + (params["param2"] as Number).toInt() + ) + ) + } + + override fun setVoiceBeautifierParameters(params: Map, callback: Callback) { + callback.code( + engine?.setVoiceBeautifierParameters( + (params["preset"] as Number).toInt(), + (params["param1"] as Number).toInt(), + (params["param2"] as Number).toInt() + ) + ) } override fun enableSoundPositionIndication(params: Map, callback: Callback) { @@ -664,7 +1052,13 @@ class RtcEngineManager( } 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())) + callback.code( + engine?.setRemoteVoicePosition( + (params["uid"] as Number).toNativeUInt(), + (params["pan"] as Number).toDouble(), + (params["gain"] as Number).toDouble() + ) + ) } override fun setLiveTranscoding(params: Map, callback: Callback) { @@ -672,7 +1066,12 @@ class RtcEngineManager( } override fun addPublishStreamUrl(params: Map, callback: Callback) { - callback.code(engine?.addPublishStreamUrl(params["url"] as String, params["transcodingEnabled"] as Boolean)) + callback.code( + engine?.addPublishStreamUrl( + params["url"] as String, + params["transcodingEnabled"] as Boolean + ) + ) } override fun removePublishStreamUrl(params: Map, callback: Callback) { @@ -691,6 +1090,14 @@ class RtcEngineManager( callback.code(engine?.stopChannelMediaRelay()) } + override fun pauseAllChannelMediaRelay(callback: Callback) { + callback.code(engine?.pauseAllChannelMediaRelay()) + } + + override fun resumeAllChannelMediaRelay(callback: Callback) { + callback.code(engine?.resumeAllChannelMediaRelay()) + } + override fun setDefaultAudioRoutetoSpeakerphone(params: Map, callback: Callback) { callback.code(engine?.setDefaultAudioRoutetoSpeakerphone(params["defaultToSpeaker"] as Boolean)) } @@ -716,7 +1123,12 @@ class RtcEngineManager( } override fun setRemoteVideoStreamType(params: Map, callback: Callback) { - callback.code(engine?.setRemoteVideoStreamType((params["uid"] as Number).toInt(), (params["streamType"] as Number).toInt())) + callback.code( + engine?.setRemoteVideoStreamType( + (params["uid"] as Number).toNativeUInt(), + (params["streamType"] as Number).toInt() + ) + ) } override fun setRemoteDefaultVideoStreamType(params: Map, callback: Callback) { @@ -732,11 +1144,24 @@ class RtcEngineManager( } override fun setRemoteUserPriority(params: Map, callback: Callback) { - callback.code(engine?.setRemoteUserPriority((params["uid"] as Number).toInt(), (params["userPriority"] as Number).toInt())) + callback.code( + engine?.setRemoteUserPriority( + (params["uid"] as Number).toNativeUInt(), + (params["userPriority"] as Number).toInt() + ) + ) } override fun startEchoTest(params: Map, callback: Callback) { - callback.code(engine?.startEchoTest((params["intervalInSeconds"] as Number).toInt())) + (params["intervalInSeconds"] as? Number)?.let { intervalInSeconds -> + callback.code(engine?.startEchoTest(intervalInSeconds.toInt())) + return@startEchoTest + } + (params["config"] as? Map<*, *>)?.let { config -> + callback.code(engine?.startEchoTest(mapToEchoTestConfiguration(config))) + return@startEchoTest + } + callback.code(engine?.startEchoTest()) } override fun stopEchoTest(callback: Callback) { @@ -763,7 +1188,12 @@ class RtcEngineManager( val mediaObserver = MediaObserver { data -> emit(RtcEngineEvents.MetadataReceived, data) } - callback.code(engine?.registerMediaMetadataObserver(mediaObserver, IMetadataObserver.VIDEO_METADATA)) { + callback.code( + engine?.registerMediaMetadataObserver( + mediaObserver, + IMetadataObserver.VIDEO_METADATA + ) + ) { this.mediaObserver = mediaObserver Unit } @@ -790,7 +1220,12 @@ class RtcEngineManager( } override fun addVideoWatermark(params: Map, callback: Callback) { - callback.code(engine?.addVideoWatermark(params["watermarkUrl"] as String, mapToWatermarkOptions(params["options"] as Map<*, *>))) + callback.code( + engine?.addVideoWatermark( + params["watermarkUrl"] as String, + mapToWatermarkOptions(params["options"] as Map<*, *>) + ) + ) } override fun clearVideoWatermarks(callback: Callback) { @@ -802,11 +1237,39 @@ class RtcEngineManager( } override fun setEncryptionMode(params: Map, callback: Callback) { - callback.code(engine?.setEncryptionMode(params["encryptionMode"] as String)) + 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 -> "" + } + ) + ) + } + + override fun enableEncryption(params: Map, callback: Callback) { + callback.code( + engine?.enableEncryption( + params["enabled"] as Boolean, + mapToEncryptionConfig(params["config"] as Map<*, *>) + ) + ) } 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())) + (params["config"] as? Map<*, *>)?.let { + callback.code(engine?.startAudioRecording(mapToAudioRecordingConfiguration(it))) + return@startAudioRecording + } + callback.code( + engine?.startAudioRecording( + params["filePath"] as String, + (params["sampleRate"] as Number).toInt(), + (params["quality"] as Number).toInt() + ) + ) } override fun stopAudioRecording(callback: Callback) { @@ -814,7 +1277,12 @@ class RtcEngineManager( } override fun addInjectStreamUrl(params: Map, callback: Callback) { - callback.code(engine?.addInjectStreamUrl(params["url"] as String, mapToLiveInjectStreamConfig(params["config"] as Map<*, *>))) + callback.code( + engine?.addInjectStreamUrl( + params["url"] as String, + mapToLiveInjectStreamConfig(params["config"] as Map<*, *>) + ) + ) } override fun removeInjectStreamUrl(params: Map, callback: Callback) { @@ -854,15 +1322,25 @@ class RtcEngineManager( } override fun setCameraFocusPositionInPreview(params: Map, callback: Callback) { - callback.code(engine?.setCameraFocusPositionInPreview((params["positionX"] as Number).toFloat(), (params["positionY"] as Number).toFloat())) + callback.code( + engine?.setCameraFocusPositionInPreview( + (params["positionX"] as Number).toFloat(), + (params["positionY"] as Number).toFloat() + ) + ) } override fun setCameraExposurePosition(params: Map, callback: Callback) { - callback.code(engine?.setCameraExposurePosition((params["positionXinView"] as Number).toFloat(), (params["positionYinView"] as Number).toFloat())) + callback.code( + engine?.setCameraExposurePosition( + (params["positionXinView"] as Number).toFloat(), + (params["positionYinView"] as Number).toFloat() + ) + ) } override fun enableFaceDetection(params: Map, callback: Callback) { - callback.code(engine?.enableFaceDetection(params["enable"] as Boolean)) + callback.code(engine?.enableFaceDetection(params["enabled"] as Boolean)) } override fun setCameraTorchOn(params: Map, callback: Callback) { @@ -878,10 +1356,24 @@ class RtcEngineManager( } override fun createDataStream(params: Map, callback: Callback) { - callback.code(engine?.createDataStream(params["reliable"] as Boolean, params["ordered"] as Boolean)) { it } + (params["config"] as? Map<*, *>)?.let { config -> + callback.code(engine?.createDataStream(mapToDataStreamConfig(config))) { it } + return@createDataStream + } + callback.code( + engine?.createDataStream( + params["reliable"] as Boolean, + params["ordered"] as Boolean + ) + ) { it } } override fun sendStreamMessage(params: Map, callback: Callback) { - callback.code(engine?.sendStreamMessage((params["streamId"] as Number).toInt(), (params["message"] as String).toByteArray())) + callback.code( + engine?.sendStreamMessage( + (params["streamId"] as Number).toInt(), + (params["message"] as String).toByteArray() + ) + ) } } diff --git a/RtcEngineEvent.kt b/RtcEngineEvent.kt index 8c689e286..15ac9c19d 100644 --- a/RtcEngineEvent.kt +++ b/RtcEngineEvent.kt @@ -33,6 +33,7 @@ class RtcEngineEvents { const val LocalVideoStateChanged = "LocalVideoStateChanged" const val RemoteAudioStateChanged = "RemoteAudioStateChanged" const val LocalAudioStateChanged = "LocalAudioStateChanged" + const val RequestAudioFileInfo = "RequestAudioFileInfo" const val LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" const val RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" const val AudioRouteChanged = "AudioRouteChanged" @@ -77,6 +78,17 @@ 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" + const val UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + const val UploadLogResult = "UploadLogResult" + const val VirtualBackgroundSourceEnabled = "VirtualBackgroundSourceEnabled" + const val SnapshotTaken = "SnapshotTaken" fun toMap(): Map { return hashMapOf( @@ -106,6 +118,7 @@ class RtcEngineEvents { "LocalVideoStateChanged" to LocalVideoStateChanged, "RemoteAudioStateChanged" to RemoteAudioStateChanged, "LocalAudioStateChanged" to LocalAudioStateChanged, + "RequestAudioFileInfo" to RequestAudioFileInfo, "LocalPublishFallbackToAudioOnly" to LocalPublishFallbackToAudioOnly, "RemoteSubscribeFallbackToAudioOnly" to RemoteSubscribeFallbackToAudioOnly, "AudioRouteChanged" to AudioRouteChanged, @@ -149,7 +162,18 @@ 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, + "UserSuperResolutionEnabled" to UserSuperResolutionEnabled, + "UploadLogResult" to UploadLogResult, + "VirtualBackgroundSourceEnabled" to VirtualBackgroundSourceEnabled, + "SnapshotTaken" to SnapshotTaken ) } } @@ -174,16 +198,20 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.Error, err) } - override fun onApiCallExecuted(@Annotations.AgoraErrorCode error: Int, api: String?, result: String?) { + override fun onApiCallExecuted( + @Annotations.AgoraErrorCode error: Int, + api: String?, + result: String? + ) { callback(RtcEngineEvents.ApiCallExecuted, error, api, result) } override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) { - callback(RtcEngineEvents.JoinChannelSuccess, channel, uid, elapsed) + callback(RtcEngineEvents.JoinChannelSuccess, channel, uid.toUInt().toLong(), elapsed) } override fun onRejoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) { - callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) + callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid.toUInt().toLong(), elapsed) } override fun onLeaveChannel(stats: RtcStats?) { @@ -191,26 +219,32 @@ class RtcEngineEventHandler( } override fun onLocalUserRegistered(uid: Int, userAccount: String?) { - callback(RtcEngineEvents.LocalUserRegistered, uid, userAccount) + callback(RtcEngineEvents.LocalUserRegistered, uid.toUInt().toLong(), userAccount) } override fun onUserInfoUpdated(uid: Int, userInfo: UserInfo?) { - callback(RtcEngineEvents.UserInfoUpdated, uid, userInfo?.toMap()) + callback(RtcEngineEvents.UserInfoUpdated, uid.toUInt().toLong(), userInfo?.toMap()) } - override fun onClientRoleChanged(@Annotations.AgoraClientRole oldRole: Int, @Annotations.AgoraClientRole newRole: Int) { + override fun onClientRoleChanged( + @Annotations.AgoraClientRole oldRole: Int, + @Annotations.AgoraClientRole newRole: Int + ) { callback(RtcEngineEvents.ClientRoleChanged, oldRole, newRole) } override fun onUserJoined(uid: Int, elapsed: Int) { - callback(RtcEngineEvents.UserJoined, uid, elapsed) + callback(RtcEngineEvents.UserJoined, uid.toUInt().toLong(), elapsed) } override fun onUserOffline(uid: Int, @Annotations.AgoraUserOfflineReason reason: Int) { - callback(RtcEngineEvents.UserOffline, uid, reason) + callback(RtcEngineEvents.UserOffline, uid.toUInt().toLong(), reason) } - override fun onConnectionStateChanged(@Annotations.AgoraConnectionStateType state: Int, @Annotations.AgoraConnectionChangedReason reason: Int) { + override fun onConnectionStateChanged( + @Annotations.AgoraConnectionStateType state: Int, + @Annotations.AgoraConnectionChangedReason reason: Int + ) { callback(RtcEngineEvents.ConnectionStateChanged, state, reason) } @@ -230,12 +264,15 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.RequestToken) } - override fun onAudioVolumeIndication(speakers: Array?, @IntRange(from = 0, to = 255) totalVolume: Int) { + override fun onAudioVolumeIndication( + speakers: Array?, + @IntRange(from = 0, to = 255) totalVolume: Int + ) { callback(RtcEngineEvents.AudioVolumeIndication, speakers?.toMapList(), totalVolume) } override fun onActiveSpeaker(uid: Int) { - callback(RtcEngineEvents.ActiveSpeaker, uid) + callback(RtcEngineEvents.ActiveSpeaker, uid.toUInt().toLong()) } override fun onFirstLocalAudioFrame(elapsed: Int) { @@ -248,35 +285,64 @@ class RtcEngineEventHandler( @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) override fun onUserMuteVideo(uid: Int, muted: Boolean) { - callback(RtcEngineEvents.UserMuteVideo, uid, muted) + callback(RtcEngineEvents.UserMuteVideo, uid.toUInt().toLong(), muted) } - override fun onVideoSizeChanged(uid: Int, width: Int, height: Int, @IntRange(from = 0, to = 360) rotation: Int) { - callback(RtcEngineEvents.VideoSizeChanged, uid, width, height, rotation) + override fun onVideoSizeChanged( + uid: Int, + width: Int, + height: Int, + @IntRange(from = 0, to = 360) rotation: Int + ) { + callback(RtcEngineEvents.VideoSizeChanged, uid.toUInt().toLong(), width, height, rotation) } - override fun onRemoteVideoStateChanged(uid: Int, @Annotations.AgoraVideoRemoteState state: Int, @Annotations.AgoraVideoRemoteStateReason reason: Int, elapsed: Int) { - callback(RtcEngineEvents.RemoteVideoStateChanged, uid, state, reason, elapsed) + override fun onRemoteVideoStateChanged( + uid: Int, + @Annotations.AgoraVideoRemoteState state: Int, + @Annotations.AgoraVideoRemoteStateReason reason: Int, + elapsed: Int + ) { + callback(RtcEngineEvents.RemoteVideoStateChanged, uid.toUInt().toLong(), state, reason, elapsed) } - override fun onLocalVideoStateChanged(@Annotations.AgoraLocalVideoStreamState localVideoState: Int, @Annotations.AgoraLocalVideoStreamError error: Int) { + override fun onLocalVideoStateChanged( + @Annotations.AgoraLocalVideoStreamState localVideoState: Int, + @Annotations.AgoraLocalVideoStreamError error: Int + ) { callback(RtcEngineEvents.LocalVideoStateChanged, localVideoState, error) } - override fun onRemoteAudioStateChanged(uid: Int, @Annotations.AgoraAudioRemoteState state: Int, @Annotations.AgoraAudioRemoteStateReason reason: Int, elapsed: Int) { - callback(RtcEngineEvents.RemoteAudioStateChanged, uid, state, reason, elapsed) + override fun onRemoteAudioStateChanged( + uid: Int, + @Annotations.AgoraAudioRemoteState state: Int, + @Annotations.AgoraAudioRemoteStateReason reason: Int, + elapsed: Int + ) { + callback(RtcEngineEvents.RemoteAudioStateChanged, uid.toUInt().toLong(), state, reason, elapsed) } - override fun onLocalAudioStateChanged(@Annotations.AgoraAudioLocalState state: Int, @Annotations.AgoraAudioLocalError error: Int) { + override fun onLocalAudioStateChanged( + @Annotations.AgoraAudioLocalState state: Int, + @Annotations.AgoraAudioLocalError error: Int + ) { callback(RtcEngineEvents.LocalAudioStateChanged, state, error) } + override fun onRequestAudioFileInfo(info: AudioFileInfo?, error: Int) { + callback(RtcEngineEvents.RequestAudioFileInfo, info?.toMap(), error) + } + override fun onLocalPublishFallbackToAudioOnly(isFallbackOrRecover: Boolean) { callback(RtcEngineEvents.LocalPublishFallbackToAudioOnly, isFallbackOrRecover) } override fun onRemoteSubscribeFallbackToAudioOnly(uid: Int, isFallbackOrRecover: Boolean) { - callback(RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, uid, isFallbackOrRecover) + callback( + RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, + uid.toUInt().toLong(), + isFallbackOrRecover + ) } override fun onAudioRouteChanged(@Annotations.AgoraAudioOutputRouting routing: Int) { @@ -291,7 +357,11 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.CameraExposureAreaChanged, rect?.toMap()) } - override fun onFacePositionChanged(imageWidth: Int, imageHeight: Int, faces: Array?) { + override fun onFacePositionChanged( + imageWidth: Int, + imageHeight: Int, + faces: Array? + ) { callback(RtcEngineEvents.FacePositionChanged, imageWidth, imageHeight, faces?.toMapList()) } @@ -303,8 +373,12 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.LastmileQuality, quality) } - override fun onNetworkQuality(uid: Int, @Annotations.AgoraNetworkQuality txQuality: Int, @Annotations.AgoraNetworkQuality rxQuality: Int) { - callback(RtcEngineEvents.NetworkQuality, uid, txQuality, rxQuality) + override fun onNetworkQuality( + uid: Int, + @Annotations.AgoraNetworkQuality txQuality: Int, + @Annotations.AgoraNetworkQuality rxQuality: Int + ) { + callback(RtcEngineEvents.NetworkQuality, uid.toUInt().toLong(), txQuality, rxQuality) } override fun onLastmileProbeResult(result: LastmileProbeResult?) { @@ -325,7 +399,12 @@ class RtcEngineEventHandler( } @Deprecated("", ReplaceWith("onRemoteVideoStats")) - override fun onRemoteVideoStat(uid: Int, delay: Int, receivedBitrate: Int, receivedFrameRate: Int) { + override fun onRemoteVideoStat( + uid: Int, + delay: Int, + receivedBitrate: Int, + receivedFrameRate: Int + ) { // TODO Not in iOS } @@ -342,15 +421,22 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.AudioMixingFinished) } - override fun onAudioMixingStateChanged(@Annotations.AgoraAudioMixingStateCode state: Int, @Annotations.AgoraAudioMixingErrorCode errorCode: Int) { - callback(RtcEngineEvents.AudioMixingStateChanged, state, errorCode) + override fun onAudioMixingStateChanged( + @Annotations.AgoraAudioMixingStateCode state: Int, + @Annotations.AgoraAudioMixingReason reason: Int + ) { + callback(RtcEngineEvents.AudioMixingStateChanged, state, reason) } override fun onAudioEffectFinished(soundId: Int) { callback(RtcEngineEvents.AudioEffectFinished, soundId) } - override fun onRtmpStreamingStateChanged(url: String?, @Annotations.AgoraRtmpStreamingState state: Int, @Annotations.AgoraRtmpStreamingErrorCode errCode: Int) { + override fun onRtmpStreamingStateChanged( + url: String?, + @Annotations.AgoraRtmpStreamingState state: Int, + @Annotations.AgoraRtmpStreamingErrorCode errCode: Int + ) { callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state, errCode) } @@ -358,16 +444,37 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.TranscodingUpdated) } - override fun onStreamInjectedStatus(url: String?, uid: Int, @Annotations.AgoraInjectStreamStatus status: Int) { - callback(RtcEngineEvents.StreamInjectedStatus, url, uid, status) + override fun onStreamInjectedStatus( + url: String?, + uid: Int, + @Annotations.AgoraInjectStreamStatus status: Int + ) { + callback(RtcEngineEvents.StreamInjectedStatus, url, uid.toUInt().toLong(), status) } override fun onStreamMessage(uid: Int, streamId: Int, data: ByteArray?) { - callback(RtcEngineEvents.StreamMessage, uid, streamId, data?.let { String(it, Charsets.UTF_8) }) - } - - override fun onStreamMessageError(uid: Int, streamId: Int, @Annotations.AgoraErrorCode error: Int, missed: Int, cached: Int) { - callback(RtcEngineEvents.StreamMessageError, uid, streamId, error, missed, cached) + callback( + RtcEngineEvents.StreamMessage, + uid.toUInt().toLong(), + streamId, + data?.let { String(it, Charsets.UTF_8) }) + } + + override fun onStreamMessageError( + uid: Int, + streamId: Int, + @Annotations.AgoraErrorCode error: Int, + missed: Int, + cached: Int + ) { + callback( + RtcEngineEvents.StreamMessageError, + uid.toUInt().toLong(), + streamId, + error, + missed, + cached + ) } override fun onMediaEngineLoadSuccess() { @@ -378,7 +485,10 @@ class RtcEngineEventHandler( callback(RtcEngineEvents.MediaEngineStartCallSuccess) } - override fun onChannelMediaRelayStateChanged(@Annotations.AgoraChannelMediaRelayState state: Int, @Annotations.AgoraChannelMediaRelayError code: Int) { + override fun onChannelMediaRelayStateChanged( + @Annotations.AgoraChannelMediaRelayState state: Int, + @Annotations.AgoraChannelMediaRelayError code: Int + ) { callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state, code) } @@ -388,22 +498,22 @@ class RtcEngineEventHandler( @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) override fun onFirstRemoteVideoFrame(uid: Int, width: Int, height: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteVideoFrame, uid, width, height, elapsed) + callback(RtcEngineEvents.FirstRemoteVideoFrame, uid.toUInt().toLong(), width, height, elapsed) } @Deprecated("", ReplaceWith("onRemoteAudioStateChanged")) override fun onFirstRemoteAudioFrame(uid: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteAudioFrame, uid, elapsed) + callback(RtcEngineEvents.FirstRemoteAudioFrame, uid.toUInt().toLong(), elapsed) } @Deprecated("", ReplaceWith("onRemoteAudioStateChanged")) override fun onFirstRemoteAudioDecoded(uid: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid, elapsed) + callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid.toUInt().toLong(), elapsed) } @Deprecated("", ReplaceWith("onRemoteAudioStateChanged")) override fun onUserMuteAudio(uid: Int, muted: Boolean) { - callback(RtcEngineEvents.UserMuteAudio, uid, muted) + callback(RtcEngineEvents.UserMuteAudio, uid.toUInt().toLong(), muted) } @Deprecated("", ReplaceWith("onRtmpStreamingStateChanged")) @@ -418,27 +528,39 @@ class RtcEngineEventHandler( @Deprecated("", ReplaceWith("onRemoteAudioStats")) override fun onRemoteAudioTransportStats(uid: Int, delay: Int, lost: Int, rxKBitRate: Int) { - callback(RtcEngineEvents.RemoteAudioTransportStats, uid, delay, lost, rxKBitRate) + callback( + RtcEngineEvents.RemoteAudioTransportStats, + uid.toUInt().toLong(), + delay, + lost, + rxKBitRate + ) } @Deprecated("", ReplaceWith("onRemoteVideoStats")) override fun onRemoteVideoTransportStats(uid: Int, delay: Int, lost: Int, rxKBitRate: Int) { - callback(RtcEngineEvents.RemoteVideoTransportStats, uid, delay, lost, rxKBitRate) + callback( + RtcEngineEvents.RemoteVideoTransportStats, + uid.toUInt().toLong(), + delay, + lost, + rxKBitRate + ) } @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) override fun onUserEnableVideo(uid: Int, enabled: Boolean) { - callback(RtcEngineEvents.UserEnableVideo, uid, enabled) + callback(RtcEngineEvents.UserEnableVideo, uid.toUInt().toLong(), enabled) } @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) override fun onUserEnableLocalVideo(uid: Int, enabled: Boolean) { - callback(RtcEngineEvents.UserEnableLocalVideo, uid, enabled) + callback(RtcEngineEvents.UserEnableLocalVideo, uid.toUInt().toLong(), enabled) } @Deprecated("", ReplaceWith("onRemoteVideoStateChanged")) override fun onFirstRemoteVideoDecoded(uid: Int, width: Int, height: Int, elapsed: Int) { - callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid, width, height, elapsed) + callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid.toUInt().toLong(), width, height, elapsed) } @Deprecated("", ReplaceWith("onLocalAudioStateChanged")) @@ -457,8 +579,13 @@ class RtcEngineEventHandler( } @Deprecated("", ReplaceWith("onRemoteAudioStats")) - override fun onAudioQuality(uid: Int, @Annotations.AgoraNetworkQuality quality: Int, delay: Short, lost: Short) { - callback(RtcEngineEvents.AudioQuality, uid, quality, delay, lost) + override fun onAudioQuality( + uid: Int, + @Annotations.AgoraNetworkQuality quality: Int, + delay: Short, + lost: Short + ) { + callback(RtcEngineEvents.AudioQuality, uid.toUInt().toLong(), quality, delay, lost) } @Deprecated("", ReplaceWith("onLocalVideoStateChanged")) @@ -470,4 +597,122 @@ 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.toUInt().toLong(), + 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.toUInt().toLong(), + oldState, + newState, + elapseSinceLastState + ) + } + + override fun onRtmpStreamingEvent(url: String?, @Annotations.AgoraRtmpStreamingEvent error: Int) { + callback(RtcEngineEvents.RtmpStreamingEvent, url, error) + } + + override fun onUserSuperResolutionEnabled( + uid: Int, + enabled: Boolean, + @Annotations.AgoraSuperResolutionStateReason reason: Int + ) { + callback(RtcEngineEvents.UserSuperResolutionEnabled, uid.toUInt().toLong(), enabled, reason) + } + + override fun onUploadLogResult( + requestId: String?, + success: Boolean, + @Annotations.AgoraUploadErrorReason reason: Int + ) { + callback(RtcEngineEvents.UploadLogResult, requestId, success, reason) + } + + override fun onVirtualBackgroundSourceEnabled( + enabled: Boolean, + @Annotations.AgoraVirtualBackgroundSourceStateReason reason: Int + ) { + callback(RtcEngineEvents.VirtualBackgroundSourceEnabled, enabled, reason) + } + + override fun onSnapshotTaken( + channel: String?, + uid: Int, + filePath: String?, + width: Int, + height: Int, + errCode: Int + ) { + callback( + RtcEngineEvents.SnapshotTaken, + channel, + uid.toUInt().toLong(), + filePath, + width, + height, + errCode + ) + } } diff --git a/RtcEnginePlugin.kt b/RtcEnginePlugin.kt new file mode 100644 index 000000000..0c434437a --- /dev/null +++ b/RtcEnginePlugin.kt @@ -0,0 +1,47 @@ +package io.agora.rtc.base + +import io.agora.rtc.RtcEngine + +/** + * A [RtcEnginePlugin] allows developers to interact with the [RtcEngine] which created from flutter + * side. + */ +interface RtcEnginePlugin { + + /** + * This callback will be called when the [RtcEngine] is created by + * [RtcEngine.createWithContext](https://docs.agora.io/cn/Video/API%20Reference/flutter/agora_rtc_engine/RtcEngine/createWithContext.html) + * function from flutter. + * + * NOTE that you should not call [RtcEngine.destroy], because it will also destroy the `RtcEngine` + * used by flutter side. + * + * @param rtcEngine The same [RtcEngine] used by flutter side + */ + fun onRtcEngineCreated(rtcEngine: RtcEngine?) + + /** + * This callback will be called when the [RtcEngine.destroy](https://docs.agora.io/cn/Video/API%20Reference/flutter/v4.0.7/rtc_channel/RtcChannel/destroy.html) + * function is called from flutter. + */ + fun onRtcEngineDestroyed() + + companion object Registrant { + /** + * Register a [RtcEnginePlugin]. The [plugin] will be called when the [RtcEngine] is created from + * flutter side. + */ + fun register(plugin: RtcEnginePlugin) { + RtcEngineRegistry.instance.add(plugin = plugin) + } + + /** + * Unregister a previously registered [RtcEnginePlugin]. + */ + fun unregister(plugin: RtcEnginePlugin) { + RtcEngineRegistry.instance.remove(pluginClass = plugin.javaClass) + } + } +} + + diff --git a/RtcEngineRegistry.kt b/RtcEngineRegistry.kt new file mode 100644 index 000000000..e06866bfd --- /dev/null +++ b/RtcEngineRegistry.kt @@ -0,0 +1,43 @@ +package io.agora.rtc.base + +import io.agora.rtc.RtcEngine +import java.util.HashMap + +/** + * The [RtcEngineRegistry] is response to add, remove and notify the callback when [RtcEngine] is created + * from flutter side. + */ +internal class RtcEngineRegistry private constructor() : RtcEnginePlugin { + companion object { + val instance: RtcEngineRegistry by lazy { RtcEngineRegistry() } + } + + private val plugins: MutableMap, RtcEnginePlugin> = HashMap() + + /** + * Add a [RtcEnginePlugin]. + */ + fun add(plugin: RtcEnginePlugin) { + if (plugins.containsKey(plugin.javaClass)) return + plugins[plugin.javaClass] = plugin + } + + /** + * Remove the previously added [RtcEnginePlugin]. + */ + fun remove(pluginClass: Class) { + plugins.remove(pluginClass) + } + + override fun onRtcEngineCreated(rtcEngine: RtcEngine?) { + for (plugin in plugins.values) { + plugin.onRtcEngineCreated(rtcEngine) + } + } + + override fun onRtcEngineDestroyed() { + for (plugin in plugins.values) { + plugin.onRtcEngineDestroyed() + } + } +} diff --git a/RtcSurfaceView.kt b/RtcSurfaceView.kt index 536f7ddaf..ff31727f6 100644 --- a/RtcSurfaceView.kt +++ b/RtcSurfaceView.kt @@ -49,15 +49,16 @@ class RtcSurfaceView( } } - fun setData(engine: RtcEngine, channel: RtcChannel?, uid: Int) { + fun setData(engine: RtcEngine, channel: RtcChannel?, uid: Number) { this.channel = if (channel != null) WeakReference(channel) else null canvas.channelId = this.channel?.get()?.channelId() - canvas.uid = uid + canvas.uid = uid.toNativeUInt() setupVideoCanvas(engine) } fun resetVideoCanvas(engine: RtcEngine) { - val canvas = VideoCanvas(null, canvas.renderMode, canvas.channelId, canvas.uid, canvas.mirrorMode) + val canvas = + VideoCanvas(null, canvas.renderMode, canvas.channelId, canvas.uid, canvas.mirrorMode) if (canvas.uid == 0) { engine.setupLocalVideo(canvas) } else { diff --git a/RtcTextureView.kt b/RtcTextureView.kt index bd8570201..795f7af44 100644 --- a/RtcTextureView.kt +++ b/RtcTextureView.kt @@ -1,59 +1,79 @@ 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) { + fun setData(engine: RtcEngine, channel: RtcChannel?, uid: Number) { this.channel = if (channel != null) WeakReference(channel) else null - this.uid = uid - setupVideoRenderer(engine) + canvas.channelId = this.channel?.get()?.channelId() + canvas.uid = uid.toNativeUInt() + 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) { + removeAllViews() + texture = RtcEngine.CreateTextureView(context.applicationContext) + addView(texture) + texture.layout(0, 0, width, height) + canvas.view = texture + 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) } } From 519e8b5c7e4b163a55e5037e21d786660b180287 Mon Sep 17 00:00:00 2001 From: HUI Date: Tue, 8 Feb 2022 13:43:14 +0800 Subject: [PATCH 3/3] Squashed 'ios/Classes/Base/' changes from b664522..079b933 079b933 fix: enable to enabled da75ede fix: iOS build error 40fe426 fix: getAudioFileInfo & selectAudioTrack 9d52a5f fix: build failed on other platform a7ddd5e style: format 6db7748 feat: support 3.5.2 325c233 feat: support 3.5.1 & plugin d4e2686 fix: mapToEncryptionConfig crash f4be532 fix: compiler error 4eb127f chore: support 3.5.0.2 3c32dc5 chore: add API which is missing 3bb9210 fix: API call error 732df69 feat: support 3.4.6 782ec46 chore: prepare to migrate to iris ba7fba7 chore: support 3.4.5 f25a603 fix: startAudioRecording bug 02b6cc3 chore: optimize startAudioRecording 88b3d59 style: format code b60a451 Merge pull request #6 from AgoraLibrary/main/3.4.+ d1561f7 feat(upgrade): 3.4.1 bb84006 Merge pull request #5 from AgoraLibrary/main/3.3.+ 4623dc3 fix: getErrorDescription key error ee40ba1 Merge pull request #4 from AgoraLibrary/dev/3.3.0 f8bde68 Merge branch 'master' into dev/3.3.0 0db518f Merge pull request #3 from AgoraLibrary/dev/3.2.0 5f69768 Merge branch 'master' into dev/3.2.0 d355c51 Merge pull request #2 from AgoraLibrary/dev/3.1.0 a81db07 fix: merge some bug fix 2d1ac8f fix: iOS selector error 98c4331 fix: type cast error 836f3b4 feat: support 3.3.1 for iOS b422ce8 feat: support 3.3.0 for iOS c8a08e5 Merge branch 'master' into dev/3.2.0 561b3fd Merge branch 'master' into dev/3.2.0 da3222a Merge branch 'master' into dev/3.2.0 3a55997 feat: add `setClientRole(role: ClientRole, options?: ClientRoleOptions): Promise` 4ee51a9 feat: upgrade to 3.2.0 REVERT: b664522 fix: merge error REVERT: ed3b61b feat: support 3.0.+ git-subtree-dir: ios/Classes/Base git-subtree-split: 079b933306bc49e26f9bd62f5439d3a002e4ec59 --- AgoraRtcEngineKit.h | 69 ++++--- BeanCovertor.swift | 213 +++++++++++++++++---- Callback.swift | 16 +- Extensions.swift | 80 +++++--- MediaObserver.swift | 10 +- RtcChannel.swift | 98 ++++++++-- RtcChannelEvent.swift | 48 ++++- RtcEngine.swift | 327 +++++++++++++++++++++++++++++--- RtcEngineEvent.swift | 236 +++++++++++++++-------- RtcEnginePlugin.h | 31 +++ RtcEnginePluginRegistrant.swift | 22 +++ RtcEngineRegistry.swift | 61 ++++++ RtcSurfaceView.swift | 17 +- 13 files changed, 979 insertions(+), 249 deletions(-) create mode 100644 RtcEnginePlugin.h create mode 100644 RtcEnginePluginRegistrant.swift create mode 100644 RtcEngineRegistry.swift diff --git a/AgoraRtcEngineKit.h b/AgoraRtcEngineKit.h index 7af94d48b..cebf95c80 100644 --- a/AgoraRtcEngineKit.h +++ b/AgoraRtcEngineKit.h @@ -9,40 +9,47 @@ #import typedef NS_ENUM(NSUInteger, AgoraRtcQualityReportFormat) { - AgoraRtc_QualityReportFormat_Json = 0, - AgoraRtc_QualityReportFormat_Html = 1, + AgoraRtc_QualityReportFormat_Json = 0, + AgoraRtc_QualityReportFormat_Html = 1, }; typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { - AgoraRtc_APP_TYPE_NATIVE = 0, - AgoraRtc_APP_TYPE_COCOS = 1, - AgoraRtc_APP_TYPE_UNITY = 2, - AgoraRtc_APP_TYPE_ELECTRON = 3, - AgoraRtc_APP_TYPE_FLUTTER = 4, - AgoraRtc_APP_TYPE_UNREAL = 5, - AgoraRtc_APP_TYPE_XAMARIN = 6, - AgoraRtc_APP_TYPE_APICLOUD = 7, - AgoraRtc_APP_TYPE_REACTNATIVE = 8 + AgoraRtc_APP_TYPE_NATIVE = 0, + AgoraRtc_APP_TYPE_COCOS = 1, + AgoraRtc_APP_TYPE_UNITY = 2, + AgoraRtc_APP_TYPE_ELECTRON = 3, + AgoraRtc_APP_TYPE_FLUTTER = 4, + AgoraRtc_APP_TYPE_UNREAL = 5, + AgoraRtc_APP_TYPE_XAMARIN = 6, + AgoraRtc_APP_TYPE_APICLOUD = 7, + AgoraRtc_APP_TYPE_REACTNATIVE = 8 }; @protocol AgoraRtcEngineExtensionDelegate @optional -- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine audioTransportQualityOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost; -- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine videoTransportQualityOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost; +- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine + audioTransportQualityOfUid:(NSUInteger)uid + delay:(NSUInteger)delay + lost:(NSUInteger)lost; +- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine + videoTransportQualityOfUid:(NSUInteger)uid + delay:(NSUInteger)delay + lost:(NSUInteger)lost; @end @interface AgoraRtcEngineKit (AgoraExtension) -+ (instancetype _Nonnull)sharedEngineWithAppId:(NSString * _Nonnull)appId - extensionDelegate:(id _Nullable)delegate; ++ (instancetype _Nonnull)sharedEngineWithAppId:(NSString *_Nonnull)appId + extensionDelegate: + (id _Nullable) + delegate; /** Sets the profile to control the RTC engine. * * @param profile SDK profile in JSON format. * @param merge Whether to merge the profile data with the original value. */ -- (int)setProfile:(NSString * _Nonnull)profile - merge:(BOOL)merge; +- (int)setProfile:(NSString *_Nonnull)profile merge:(BOOL)merge; /** Set wrapper frame type by language wrapper. * @@ -54,7 +61,6 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { /** BEGIN OF AUDIO METHODS */ - /** * Enable recap * @@ -76,8 +82,7 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { andFrameRate:(NSInteger)frameRate andBitrate:(NSInteger)andBitrate; -- (int)sendReportData:(NSData * _Nonnull)data - type:(NSInteger)type; +- (int)sendReportData:(NSData *_Nonnull)data type:(NSInteger)type; /** END OF AUDIO METHODS */ /** Queries internal states @@ -85,22 +90,28 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { * json string, array type * @return a json string */ -- (NSString * _Nullable)getParameters:(NSString * _Nonnull)parameters; +- (NSString *_Nullable)getParameters:(NSString *_Nonnull)parameters; /** - * Generates a URL linking to the call quality reports. @param channel The channel name specified in the joinChannel method. + * Generates a URL linking to the call quality reports. @param channel The + channel name specified in the joinChannel method. * @param listenerUid The uid of the listener. * @param speakerUid The uid of the speaker. * @param reportFormat The format of the report. - AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns the quality report data in Json. - AgoraRtc_QualityReportFormat_Html (1): HTML.: Returns a report in HTML format, displayed on a web browser or WebVIEW components. + AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns + the quality report data in Json. AgoraRtc_QualityReportFormat_Html (1): HTML.: + Returns a report in HTML format, displayed on a web browser or WebVIEW + components. * - * @return 0 when executed successfully. return minus value when failed. return AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. + * @return 0 when executed successfully. return minus value when failed. return + AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return + AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. */ -- (NSString * _Nullable)makeQualityReportUrl:(NSString * _Nonnull) channel - listenerUid:(NSUInteger)listenerUid - speakerrUid:(NSUInteger)speakerUid - reportFormat:(AgoraRtcQualityReportFormat)reportFormat; +- (NSString *_Nullable)makeQualityReportUrl:(NSString *_Nonnull)channel + listenerUid:(NSUInteger)listenerUid + speakerrUid:(NSUInteger)speakerUid + reportFormat: + (AgoraRtcQualityReportFormat)reportFormat; /********************************************************* * Large group conference call (experiment) - END diff --git a/BeanCovertor.swift b/BeanCovertor.swift index 868a41b34..ae6c5240f 100644 --- a/BeanCovertor.swift +++ b/BeanCovertor.swift @@ -6,10 +6,10 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation -func mapToPoint(_ map: Dictionary) -> CGPoint { +func mapToPoint(_ map: [String: Any]) -> CGPoint { var point = CGPoint() if let x = map["x"] as? NSNumber { point.x = CGFloat(truncating: x) @@ -20,7 +20,7 @@ func mapToPoint(_ map: Dictionary) -> CGPoint { return point } -func mapToSize(_ map: Dictionary) -> CGSize { +func mapToSize(_ map: [String: Any]) -> CGSize { var size = CGSize() if let width = map["width"] as? NSNumber { size.width = CGFloat(truncating: width) @@ -31,16 +31,16 @@ func mapToSize(_ map: Dictionary) -> CGSize { return size } -func mapToRect(_ map: Dictionary) -> CGRect { +func mapToRect(_ map: [String: Any]) -> CGRect { return CGRect( origin: mapToPoint(map), size: mapToSize(map) ) } -func mapToVideoEncoderConfiguration(_ map: Dictionary) -> AgoraVideoEncoderConfiguration { +func mapToVideoEncoderConfiguration(_ map: [String: Any]) -> AgoraVideoEncoderConfiguration { let config = AgoraVideoEncoderConfiguration() - if let dimensions = map["dimensions"] as? Dictionary { + if let dimensions = map["dimensions"] as? [String: Any] { config.dimensions = mapToSize(dimensions) } if let frameRate = map["frameRate"] as? NSNumber { @@ -73,7 +73,7 @@ func mapToVideoEncoderConfiguration(_ map: Dictionary) -> AgoraVide return config } -func mapToBeautyOptions(_ map: Dictionary) -> AgoraBeautyOptions { +func mapToBeautyOptions(_ map: [String: Any]) -> AgoraBeautyOptions { let options = AgoraBeautyOptions() if let lighteningContrastLevel = map["lighteningContrastLevel"] as? NSNumber { if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: lighteningContrastLevel.uintValue) { @@ -92,7 +92,7 @@ func mapToBeautyOptions(_ map: Dictionary) -> AgoraBeautyOptions { return options } -func mapToAgoraImage(_ map: Dictionary) -> AgoraImage { +func mapToAgoraImage(_ map: [String: Any]) -> AgoraImage { let image = AgoraImage() if let url = map["url"] as? String { if let url = URL(string: url) { @@ -103,7 +103,7 @@ func mapToAgoraImage(_ map: Dictionary) -> AgoraImage { return image } -func mapToTranscodingUser(_ map: Dictionary) -> AgoraLiveTranscodingUser { +func mapToTranscodingUser(_ map: [String: Any]) -> AgoraLiveTranscodingUser { let user = AgoraLiveTranscodingUser() if let uid = map["uid"] as? NSNumber { user.uid = uid.uintValue @@ -121,16 +121,16 @@ func mapToTranscodingUser(_ map: Dictionary) -> AgoraLiveTranscodin return user } -func mapToColor(_ map: Dictionary) -> UIColor { +func mapToColor(_ map: [String: Any]) -> UIColor { return UIColor( - red: CGFloat((map["red"] as! NSNumber).intValue), - green: CGFloat((map["green"] as! NSNumber).intValue), - blue: CGFloat((map["blue"] as! NSNumber).intValue), - alpha: 1.0 + red: CGFloat((map["red"] as! NSNumber).intValue), + green: CGFloat((map["green"] as! NSNumber).intValue), + blue: CGFloat((map["blue"] as! NSNumber).intValue), + alpha: 1.0 ) } -func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscoding { +func mapToLiveTranscoding(_ map: [String: Any]) -> AgoraLiveTranscoding { let transcoding = AgoraLiveTranscoding.default() transcoding.size = mapToSize(map) if let videoBitrate = map["videoBitrate"] as? NSNumber { @@ -145,10 +145,10 @@ func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscodin if let videoGop = map["videoGop"] as? NSNumber { transcoding.videoGop = videoGop.intValue } - if let watermark = map["watermark"] as? Dictionary { + if let watermark = map["watermark"] as? [String: Any] { transcoding.watermark = mapToAgoraImage(watermark) } - if let backgroundImage = map["backgroundImage"] as? Dictionary { + if let backgroundImage = map["backgroundImage"] as? [String: Any] { transcoding.backgroundImage = mapToAgoraImage(backgroundImage) } if let audioSampleRate = map["audioSampleRate"] as? NSNumber { @@ -172,15 +172,15 @@ func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscodin transcoding.videoCodecProfile = videoCodecProfile } } - if let backgroundColor = map["backgroundColor"] as? Dictionary { + if let backgroundColor = map["backgroundColor"] as? [String: Any] { transcoding.backgroundColor = mapToColor(backgroundColor) } if let userConfigExtraInfo = map["userConfigExtraInfo"] as? String { transcoding.transcodingExtraInfo = userConfigExtraInfo } - if let transcodingUsers = map["transcodingUsers"] as? Array { + if let transcodingUsers = map["transcodingUsers"] as? [Any] { transcodingUsers.forEach { - if let item = $0 as? Dictionary { + if let item = $0 as? [String: Any] { transcoding.add(mapToTranscodingUser(item)) } } @@ -188,7 +188,7 @@ func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscodin return transcoding } -func mapToChannelMediaInfo(_ map: Dictionary) -> AgoraChannelMediaRelayInfo { +func mapToChannelMediaInfo(_ map: [String: Any]) -> AgoraChannelMediaRelayInfo { let info = AgoraChannelMediaRelayInfo() if let channelName = map["channelName"] as? String { info.channelName = channelName @@ -202,14 +202,14 @@ func mapToChannelMediaInfo(_ map: Dictionary) -> AgoraChannelMediaR return info } -func mapToChannelMediaRelayConfiguration(_ map: Dictionary) -> AgoraChannelMediaRelayConfiguration { +func mapToChannelMediaRelayConfiguration(_ map: [String: Any]) -> AgoraChannelMediaRelayConfiguration { let config = AgoraChannelMediaRelayConfiguration() - if let srcInfo = map["srcInfo"] as? Dictionary { + if let srcInfo = map["srcInfo"] as? [String: Any] { config.sourceInfo = mapToChannelMediaInfo(srcInfo) } - if let destInfos = map["destInfos"] as? Array { + if let destInfos = map["destInfos"] as? [Any] { destInfos.forEach { - if let item = $0 as? Dictionary { + if let item = $0 as? [String: Any] { let info = mapToChannelMediaInfo(item) config.setDestinationInfo(info, forChannelName: info.channelName ?? "") } @@ -218,7 +218,7 @@ func mapToChannelMediaRelayConfiguration(_ map: Dictionary) -> Agor return config } -func mapToLastmileProbeConfig(_ map: Dictionary) -> AgoraLastmileProbeConfig { +func mapToLastmileProbeConfig(_ map: [String: Any]) -> AgoraLastmileProbeConfig { let config = AgoraLastmileProbeConfig() if let probeUplink = map["probeUplink"] as? Bool { config.probeUplink = probeUplink @@ -235,21 +235,21 @@ func mapToLastmileProbeConfig(_ map: Dictionary) -> AgoraLastmilePr return config } -func mapToWatermarkOptions(_ map: Dictionary) -> WatermarkOptions { +func mapToWatermarkOptions(_ map: [String: Any]) -> WatermarkOptions { let options = WatermarkOptions() if let visibleInPreview = map["visibleInPreview"] as? Bool { options.visibleInPreview = visibleInPreview } - if let positionInLandscapeMode = map["positionInLandscapeMode"] as? Dictionary { + if let positionInLandscapeMode = map["positionInLandscapeMode"] as? [String: Any] { options.positionInLandscapeMode = mapToRect(positionInLandscapeMode) } - if let positionInPortraitMode = map["positionInPortraitMode"] as? Dictionary { + if let positionInPortraitMode = map["positionInPortraitMode"] as? [String: Any] { options.positionInPortraitMode = mapToRect(positionInPortraitMode) } return options } -func mapToLiveInjectStreamConfig(_ map: Dictionary) -> AgoraLiveInjectStreamConfig { +func mapToLiveInjectStreamConfig(_ map: [String: Any]) -> AgoraLiveInjectStreamConfig { let config = AgoraLiveInjectStreamConfig.default() config.size = mapToSize(map) if let videoGop = map["videoGop"] as? NSNumber { @@ -275,13 +275,19 @@ func mapToLiveInjectStreamConfig(_ map: Dictionary) -> AgoraLiveInj return config } -func mapToCameraCapturerConfiguration(_ map: Dictionary) -> AgoraCameraCapturerConfiguration { +func mapToCameraCapturerConfiguration(_ map: [String: Any]) -> AgoraCameraCapturerConfiguration { let config = AgoraCameraCapturerConfiguration() if let preference = map["preference"] as? NSNumber { if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference.intValue) { config.preference = preference } } + if let captureWidth = map["captureWidth"] as? NSNumber { + config.captureWidth = captureWidth.int32Value + } + if let captureHeight = map["captureHeight"] as? NSNumber { + config.captureHeight = captureHeight.int32Value + } if let cameraDirection = map["cameraDirection"] as? NSNumber { if let cameraDirection = AgoraCameraDirection(rawValue: cameraDirection.intValue) { config.cameraDirection = cameraDirection @@ -290,7 +296,7 @@ func mapToCameraCapturerConfiguration(_ map: Dictionary) -> AgoraCa return config } -func mapToChannelMediaOptions(_ map: Dictionary) -> AgoraRtcChannelMediaOptions { +func mapToChannelMediaOptions(_ map: [String: Any]) -> AgoraRtcChannelMediaOptions { let options = AgoraRtcChannelMediaOptions() if let autoSubscribeAudio = map["autoSubscribeAudio"] as? Bool { options.autoSubscribeAudio = autoSubscribeAudio @@ -298,14 +304,153 @@ func mapToChannelMediaOptions(_ map: Dictionary) -> AgoraRtcChannel if let autoSubscribeVideo = map["autoSubscribeVideo"] as? Bool { options.autoSubscribeVideo = autoSubscribeVideo } + if let publishLocalAudio = map["publishLocalAudio"] as? Bool { + options.publishLocalAudio = publishLocalAudio + } + if let publishLocalVideo = map["publishLocalVideo"] as? Bool { + options.publishLocalVideo = publishLocalVideo + } return options } -func mapToRtcEngineConfig(_ map: Dictionary) -> AgoraRtcEngineConfig { +func mapToRtcEngineConfig(_ map: [String: Any]) -> AgoraRtcEngineConfig { let config = AgoraRtcEngineConfig() config.appId = map["appId"] as? String if let areaCode = map["areaCode"] as? NSNumber { - config.areaCode = areaCode.int32Value + config.areaCode = areaCode.uintValue + } + if let logConfig = map["logConfig"] as? [String: Any] { + config.logConfig = mapToLogConfig(logConfig) + } + return config +} + +func mapToAudioRecordingConfiguration(_ map: [String: Any]) -> AgoraAudioRecordingConfiguration { + let config = AgoraAudioRecordingConfiguration() + if let filePath = map["filePath"] as? String { + config.filePath = filePath + } + if let recordingQuality = map["recordingQuality"] as? NSNumber { + if let recordingQuality = AgoraAudioRecordingQuality(rawValue: recordingQuality.intValue) { + config.recordingQuality = recordingQuality + } + } + if let recordingPosition = map["recordingPosition"] as? NSNumber { + if let recordingPosition = AgoraAudioRecordingPosition(rawValue: recordingPosition.intValue) { + config.recordingPosition = recordingPosition + } + } + if let recordingSampleRate = map["recordingSampleRate"] as? NSNumber { + config.recordingSampleRate = recordingSampleRate.intValue + } + return config +} + +func mapToEncryptionConfig(_ map: [String: Any]) -> AgoraEncryptionConfig { + let config = AgoraEncryptionConfig() + if let encryptionMode = map["encryptionMode"] as? NSNumber { + if let encryptionMode = AgoraEncryptionMode(rawValue: encryptionMode.intValue) { + config.encryptionMode = encryptionMode + } + } + if let encryptionKey = map["encryptionKey"] as? String { + config.encryptionKey = encryptionKey + } + if let list = map["encryptionKdfSalt"] as? [Any] { + var encryptionKdfSalt: [UInt8] = [] + for i in list.indices { + if let item = list[i] as? NSNumber { + encryptionKdfSalt.append(item.uint8Value) + } + } + config.encryptionKdfSalt = Data(bytes: encryptionKdfSalt) + } + return config +} + +func mapToRhythmPlayerConfig(_ map: [String: Any]) -> AgoraRtcRhythmPlayerConfig { + let config = AgoraRtcRhythmPlayerConfig() + if let beatsPerMeasure = map["beatsPerMeasure"] as? NSNumber { + config.beatsPerMeasure = beatsPerMeasure.uintValue + } + if let beatsPerMinute = map["beatsPerMinute"] as? NSNumber { + config.beatsPerMinute = beatsPerMinute.uintValue + } + if let publish = map["publish"] as? NSNumber { + config.publish = publish.boolValue + } + return config +} + +func mapToClientRoleOptions(_ map: [String: Any]) -> AgoraClientRoleOptions { + let options = AgoraClientRoleOptions() + if let audienceLatencyLevel = map["audienceLatencyLevel"] as? NSNumber { + if let audienceLatencyLevel = AgoraAudienceLatencyLevelType(rawValue: audienceLatencyLevel.intValue) { + options.audienceLatencyLevel = audienceLatencyLevel + } + } + return options +} + +func mapToLogConfig(_ map: [String: Any]) -> AgoraLogConfig { + let config = AgoraLogConfig() + config.filePath = map["filePath"] as? String + if let fileSize = map["fileSize"] as? NSNumber { + config.fileSize = fileSize.intValue + } + if let level = map["level"] as? NSNumber { + if let level = AgoraLogLevel(rawValue: level.intValue) { + config.level = level + } + } + return config +} + +func mapToDataStreamConfig(_ map: [String: Any]) -> AgoraDataStreamConfig { + let config = AgoraDataStreamConfig() + if let syncWithAudio = map["syncWithAudio"] as? Bool { + config.syncWithAudio = syncWithAudio + } + if let ordered = map["ordered"] as? Bool { + config.ordered = ordered + } + return config +} + +func mapToVirtualBackgroundSource(_ map: [String: Any]) -> AgoraVirtualBackgroundSource { + let backgroundSource = AgoraVirtualBackgroundSource() + if let backgroundSourceType = map["backgroundSourceType"] as? NSNumber { + if let backgroundSourceType = AgoraVirtualBackgroundSourceType(rawValue: backgroundSourceType.uintValue) { + backgroundSource.backgroundSourceType = backgroundSourceType + } + } + if let color = map["color"] as? [String: Any] { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + mapToColor(color).getRed(&red, green: &green, blue: &blue, alpha: &alpha) + backgroundSource.color = UInt(red * 255.0) << 16 + UInt(green * 255.0) << 8 + UInt(blue * 255.0) + } + backgroundSource.source = map["source"] as? String + if let blurDegree = map["blur_degree"] as? NSNumber { + if let blurDegree = AgoraBlurDegree(rawValue: blurDegree.uintValue) { + backgroundSource.blur_degree = blurDegree + } + } + return backgroundSource +} + +func mapToEchoTestConfiguration(_ map: [String: Any]) -> AgoraEchoTestConfiguration { + let config = AgoraEchoTestConfiguration() + if let enableAudio = map["enableAudio"] as? NSNumber { + config.enableAudio = enableAudio.boolValue + } + if let enableVideo = map["enableVideo"] as? NSNumber { + config.enableVideo = enableVideo.boolValue + } + if let token = map["token"] as? String { + config.token = token + } + if let channelId = map["channelId"] as? String { + config.channelId = channelId } return config } diff --git a/Callback.swift b/Callback.swift index b911dfff8..8c5bc130a 100644 --- a/Callback.swift +++ b/Callback.swift @@ -6,8 +6,8 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation @objc protocol Callback: class { @@ -25,25 +25,17 @@ extension Callback { } let res = runnable?(code) - if res is Void { - success(nil) - } else { - success(res) - } + success(res) } func resolve(_ source: T?, _ runnable: (T) -> Any?) { - guard let `source` = source else { + guard let source = source else { let code = AgoraErrorCode.notInitialized.rawValue failure(String(code), AgoraRtcEngineKit.getErrorDescription(code) ?? "") return } let res = runnable(source) - if res is Void { - success(nil) - } else { - success(res) - } + success(res) } } diff --git a/Extensions.swift b/Extensions.swift index 14ded003f..d3c6b9f9d 100644 --- a/Extensions.swift +++ b/Extensions.swift @@ -6,32 +6,33 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation extension AgoraUserInfo { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, - "userAccount": userAccount + "userAccount": userAccount, ] } } extension AgoraRtcLocalAudioStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "numChannels": numChannels, "sentSampleRate": sentSampleRate, - "sentBitrate": sentBitrate + "sentBitrate": sentBitrate, + "txPacketLossRate": txPacketLossRate, ] } } extension AgoraChannelStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ - "totalDuration": duration, + "duration": duration, "txBytes": txBytes, "rxBytes": rxBytes, "txAudioBytes": txAudioBytes, @@ -44,7 +45,7 @@ extension AgoraChannelStats { "rxAudioKBitRate": rxAudioKBitrate, "txVideoKBitRate": txVideoKBitrate, "rxVideoKBitRate": rxVideoKBitrate, - "users": userCount, + "userCount": userCount, "lastmileDelay": lastmileDelay, "txPacketLossRate": txPacketLossRate, "rxPacketLossRate": rxPacketLossRate, @@ -53,24 +54,24 @@ extension AgoraChannelStats { "gatewayRtt": gatewayRtt, "memoryAppUsageRatio": memoryAppUsageRatio, "memoryTotalUsageRatio": memoryTotalUsageRatio, - "memoryAppUsageInKbytes": memoryAppUsageInKbytes + "memoryAppUsageInKbytes": memoryAppUsageInKbytes, ] } } extension CGRect { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "left": origin.x, "top": origin.y, "right": origin.x + size.width, - "bottom": origin.y + size.height + "bottom": origin.y + size.height, ] } } extension AgoraRtcRemoteAudioStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, "quality": quality, @@ -82,13 +83,17 @@ extension AgoraRtcRemoteAudioStats { "receivedBitrate": receivedBitrate, "totalFrozenTime": totalFrozenTime, "frozenRate": frozenRate, - "totalActiveTime": totalActiveTime + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, + "qoeQuality": qoeQuality, + "qualityChangedReason": qualityChangedReason, + "mosValue": mosValue, ] } } extension AgoraRtcLocalVideoStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "sentBitrate": sentBitrate, "sentFrameRate": sentFrameRate, @@ -101,13 +106,16 @@ extension AgoraRtcLocalVideoStats { "encodedFrameWidth": encodedFrameWidth, "encodedFrameHeight": encodedFrameHeight, "encodedFrameCount": encodedFrameCount, - "codecType": codecType.rawValue + "codecType": codecType.rawValue, + "txPacketLossRate": txPacketLossRate, + "captureFrameRate": captureFrameRate, + "captureBrightnessLevel": captureBrightnessLevel.rawValue, ] } } extension AgoraRtcRemoteVideoStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, "delay": delay, @@ -120,26 +128,27 @@ extension AgoraRtcRemoteVideoStats { "rxStreamType": rxStreamType.rawValue, "totalFrozenTime": totalFrozenTime, "frozenRate": frozenRate, - "totalActiveTime": totalActiveTime + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, ] } } extension AgoraRtcAudioVolumeInfo { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, "volume": volume, "vad": vad, - "channelId": channelId + "channelId": channelId, ] } } extension Array where Element: AgoraRtcAudioVolumeInfo { - func toMapList() -> Array> { - var list = [Dictionary]() - self.forEach { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { list.append($0.toMap()) } return list @@ -147,42 +156,51 @@ extension Array where Element: AgoraRtcAudioVolumeInfo { } extension AgoraLastmileProbeOneWayResult { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "packetLossRate": packetLossRate, "jitter": jitter, - "availableBandwidth": availableBandwidth + "availableBandwidth": availableBandwidth, ] } } extension AgoraLastmileProbeResult { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "state": state.rawValue, "rtt": rtt, "uplinkReport": uplinkReport.toMap(), - "downlinkReport": downlinkReport.toMap() + "downlinkReport": downlinkReport.toMap(), ] } } extension AgoraFacePositionInfo { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "x": x, "y": y, "width": width, "height": height, - "distance": distance + "distance": distance, + ] + } +} + +extension AgoraRtcAudioFileInfo { + func toMap() -> [String: Any?] { + return [ + "filePath": filePath, + "durationMs": durationMs, ] } } extension Array where Element: AgoraFacePositionInfo { - func toMapList() -> Array> { - var list = [Dictionary]() - self.forEach { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { list.append($0.toMap()) } return list diff --git a/MediaObserver.swift b/MediaObserver.swift index d11a45705..514fb21d0 100644 --- a/MediaObserver.swift +++ b/MediaObserver.swift @@ -6,15 +6,15 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class MediaObserver: NSObject { - private var emitter: (_ data: Dictionary?) -> Void + private var emitter: (_ data: [String: Any?]?) -> Void private var maxMetadataSize = 1024 private var metadataList = [String]() - init(_ emitter: @escaping (_ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ data: [String: Any?]?) -> Void) { self.emitter = emitter } @@ -32,7 +32,7 @@ extension MediaObserver: AgoraMediaMetadataDataSource { return maxMetadataSize } - func readyToSendMetadata(atTimestamp timestamp: TimeInterval) -> Data? { + func readyToSendMetadata(atTimestamp _: TimeInterval) -> Data? { if metadataList.count > 0 { return metadataList.remove(at: 0).data(using: .utf8) } @@ -43,7 +43,7 @@ extension MediaObserver: AgoraMediaMetadataDataSource { extension MediaObserver: AgoraMediaMetadataDelegate { func receiveMetadata(_ data: Data, fromUser uid: Int, atTimestamp timestamp: TimeInterval) { emitter([ - "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp] + "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp], ]) } } diff --git a/RtcChannel.swift b/RtcChannel.swift index 01c0726ce..f6e464b77 100644 --- a/RtcChannel.swift +++ b/RtcChannel.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation protocol RtcChannelInterface: RtcChannelAudioInterface, @@ -37,8 +37,10 @@ protocol RtcChannelInterface: func getConnectionState(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func publish(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func unpublish(_ params: NSDictionary, _ callback: Callback) func getCallId(_ params: NSDictionary, _ callback: Callback) @@ -47,19 +49,27 @@ protocol RtcChannelInterface: protocol RtcChannelAudioInterface { func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) + func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) + func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) } protocol RtcChannelVideoInterface { + func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) + func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) } protocol RtcChannelVoicePositionInterface { @@ -79,6 +89,10 @@ protocol RtcChannelMediaRelayInterface { func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + + func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) } @@ -103,9 +117,13 @@ protocol RtcChannelMediaMetadataInterface { } protocol RtcChannelEncryptionInterface { + @available(*, deprecated) func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) + + func enableEncryption(_ params: NSDictionary, _ callback: Callback) } protocol RtcChannelInjectStreamInterface { @@ -122,12 +140,12 @@ protocol RtcChannelStreamMessageInterface { @objc class RtcChannelManager: NSObject, RtcChannelInterface { - private var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void private var rtcChannelMap = [String: AgoraRtcChannel]() private var rtcChannelDelegateMap = [String: RtcChannelEventHandler]() private var mediaObserverMap = [String: MediaObserver]() - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { self.emitter = emitter } @@ -141,15 +159,13 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } subscript(channelId: String) -> AgoraRtcChannel? { - get { - return rtcChannelMap[channelId] - } + return rtcChannelMap[channelId] } @objc func create(_ params: NSDictionary, _ callback: Callback) { callback.resolve(params["engine"] as? AgoraRtcEngineKit) { [weak self] in if let rtcChannel = $0.createRtcChannel(params["channelId"] as! String) { - let delegate = RtcChannelEventHandler() { [weak self] in + let delegate = RtcChannelEventHandler { [weak self] in self?.emitter($0, $1) } rtcChannel.setRtcChannelDelegate(delegate) @@ -161,20 +177,24 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func destroy(_ params: NSDictionary, _ callback: Callback) { - callback.code(rtcChannelMap.removeValue(forKey:params["channelId"] as! String)?.destroy()) + callback.code(rtcChannelMap.removeValue(forKey: params["channelId"] as! String)?.destroy()) } @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! + if let options = params["options"] as? [String: Any] { + callback.code(self[params["channelId"] as! String]?.setClientRole(role, options: mapToClientRoleOptions(options))) + return + } callback.code(self[params["channelId"] as! String]?.setClientRole(role)) } @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.join(byToken: params["token"] as? String, info: params["optionalInfo"] as? String, uid: (params["optionalUid"] as! NSNumber).uintValue, options: mapToChannelMediaOptions(params["options"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.join(byToken: params["token"] as? String, info: params["optionalInfo"] as? String, uid: (params["optionalUid"] as! NSNumber).uintValue, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) } @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.join(byUserAccount: params["userAccount"] as! String, token: params["token"] as? String, options: mapToChannelMediaOptions(params["options"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.join(byUserAccount: params["userAccount"] as! String, token: params["token"] as? String, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) } @objc func leaveChannel(_ params: NSDictionary, _ callback: Callback) { @@ -238,7 +258,7 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) } @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -250,11 +270,11 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { @@ -277,7 +297,7 @@ class RtcChannelManager: NSObject, RtcChannelInterface { let channelId = params["channelId"] as! String let mediaObserver = MediaObserver { [weak self] in if var data = $0 { - data["channelId"] = channelId; + data["channelId"] = channelId self?.emitter(RtcEngineEvents.MetadataReceived, data) } } @@ -316,11 +336,25 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setEncryptionMode(params["encryptionMode"] as? String)) + var encryptionMode = "" + switch (params["encryptionMode"] as! NSNumber).intValue { + case AgoraEncryptionMode.AES128XTS.rawValue: + encryptionMode = "aes-128-xts" + case AgoraEncryptionMode.AES128ECB.rawValue: + encryptionMode = "aes-128-ecb" + case AgoraEncryptionMode.AES256XTS.rawValue: + encryptionMode = "aes-256-xts" + default: encryptionMode = "" + } + callback.code(self[params["channelId"] as! String]?.setEncryptionMode(encryptionMode)) + } + + @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) } @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) } @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -330,10 +364,40 @@ class RtcChannelManager: NSObject, RtcChannelInterface { @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { let channel = self[params["channelId"] as! String] var streamId = 0 - callback.code(channel?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in streamId } + if let config = params["config"] as? [String: Any] { + callback.code(channel?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in + streamId + } + return + } + callback.code(channel?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in + streamId + } } @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { callback.code(self[params["channelId"] as! String]?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) } + + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enabled"] as! Bool)) + } + + @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalAudioStream(params["muted"] as! Bool)) + } + + @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalVideoStream(params["muted"] as! Bool)) + } + + @objc func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) +// callback.code(self[params["channelId"] as! String]?.pauseAllChannelMediaRelay()) + } + + @objc func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) +// callback.code(self[params["channelId"] as! String]?.resumeAllChannelMediaRelay()) + } } diff --git a/RtcChannelEvent.swift b/RtcChannelEvent.swift index 64746ac91..eca5b4da8 100644 --- a/RtcChannelEvent.swift +++ b/RtcChannelEvent.swift @@ -6,8 +6,8 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class RtcChannelEvents { static let Warning = "Warning" @@ -40,8 +40,14 @@ class RtcChannelEvents { static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" static let MetadataReceived = "MetadataReceived" - - static func toMap() -> Dictionary { + static let AudioPublishStateChanged = "AudioPublishStateChanged" + static let VideoPublishStateChanged = "VideoPublishStateChanged" + static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + static let RtmpStreamingEvent = "RtmpStreamingEvent" + static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + + static func toMap() -> [String: String] { return [ "Warning": Warning, "Error": Error, @@ -73,6 +79,12 @@ class RtcChannelEvents { "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, "ChannelMediaRelayEvent": ChannelMediaRelayEvent, "MetadataReceived": MetadataReceived, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, ] } } @@ -80,16 +92,16 @@ class RtcChannelEvents { class RtcChannelEventHandler: NSObject { static let PREFIX = "io.agora.rtc." - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { self.emitter = emitter } private func callback(_ methodName: String, _ channel: AgoraRtcChannel, _ data: Any?...) { emitter(methodName, [ "channelId": channel.getId(), - "data": data + "data": data, ]) } } @@ -210,4 +222,28 @@ extension RtcChannelEventHandler: AgoraRtcChannelDelegate { public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didReceive event: AgoraChannelMediaRelayEvent) { callback(RtcChannelEvents.ChannelMediaRelayEvent, rtcChannel, event.rawValue) } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, eventCode.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + callback(RtcChannelEvents.UserSuperResolutionEnabled, rtcChannel, uid, enabled, reason.rawValue) + } } diff --git a/RtcEngine.swift b/RtcEngine.swift index 30d26b198..4e9b905fb 100644 --- a/RtcEngine.swift +++ b/RtcEngine.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation protocol RtcEngineInterface: RtcEngineUserInfoInterface, @@ -52,21 +52,42 @@ protocol RtcEngineInterface: func getConnectionState(_ callback: Callback) + func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) + func getCallId(_ callback: Callback) func rate(_ params: NSDictionary, _ callback: Callback) func complain(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLogFile(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLogFilter(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLogFileSize(_ params: NSDictionary, _ callback: Callback) func setParameters(_ params: NSDictionary, _ callback: Callback) + func getSdkVersion(_ callback: Callback) + + func getErrorDescription(_ params: NSDictionary, _ callback: Callback) + func getNativeHandle(_ callback: Callback) + + func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) + + func setCloudProxy(_ params: NSDictionary, _ callback: Callback) + + func uploadLogFile(_ callback: Callback) + + func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) + + func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) + + func takeSnapshot(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineUserInfoInterface { @@ -100,9 +121,16 @@ protocol RtcEngineAudioInterface { func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) + + func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) + + func stopRhythmPlayer(_ callback: Callback) + + func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVideoInterface { @@ -124,9 +152,12 @@ protocol RtcEngineVideoInterface { func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioMixingInterface { @@ -148,13 +179,23 @@ protocol RtcEngineAudioMixingInterface { func getAudioMixingPublishVolume(_ callback: Callback) - func getAudioMixingDuration(_ callback: Callback) + func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) + + func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) func getAudioMixingCurrentPosition(_ callback: Callback) func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) + + func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) + + func getAudioTrackCount(_ callback: Callback) + + func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) + + func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioEffectInterface { @@ -166,6 +207,12 @@ protocol RtcEngineAudioEffectInterface { func playEffect(_ params: NSDictionary, _ callback: Callback) + func setEffectPosition(_ params: NSDictionary, _ callback: Callback) + + func getEffectDuration(_ params: NSDictionary, _ callback: Callback) + + func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) + func stopEffect(_ params: NSDictionary, _ callback: Callback) func stopAllEffects(_ callback: Callback) @@ -186,8 +233,10 @@ protocol RtcEngineAudioEffectInterface { } protocol RtcEngineVoiceChangerInterface { + @available(*, deprecated) func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) @@ -195,6 +244,16 @@ protocol RtcEngineVoiceChangerInterface { func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) + + func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) + + func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) + + func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) + + func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) + + func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVoicePositionInterface { @@ -216,6 +275,10 @@ protocol RtcEngineMediaRelayInterface { func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + func pauseAllChannelMediaRelay(_ callback: Callback) + + func resumeAllChannelMediaRelay(_ callback: Callback) + func stopChannelMediaRelay(_ callback: Callback) } @@ -280,9 +343,13 @@ protocol RtcEngineWatermarkInterface { } protocol RtcEngineEncryptionInterface { + @available(*, deprecated) func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) + + func enableEncryption(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioRecorderInterface { @@ -333,35 +400,55 @@ protocol RtcEngineStreamMessageInterface { func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) } +internal class AgoraRtcEngineKitFactory { + func create(_ params: NSDictionary, _ delegate: RtcEngineEventHandler) -> AgoraRtcEngineKit? { + let engine = AgoraRtcEngineKit.sharedEngine( + with: mapToRtcEngineConfig(params["config"] as! [String: Any]), + delegate: delegate) + + return engine + } +} + @objc class RtcEngineManager: NSObject, RtcEngineInterface { - private var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void + private var agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory private(set) var engine: AgoraRtcEngineKit? private var delegate: RtcEngineEventHandler? private var mediaObserver: MediaObserver? - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void, + _ agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory = AgoraRtcEngineKitFactory()) { self.emitter = emitter + self.agoraRtcEngineKitFactory = agoraRtcEngineKitFactory } func Release() { - AgoraRtcEngineKit.destroy() - engine = nil + if (engine != nil) { + AgoraRtcEngineKit.destroy() + engine = nil + } delegate = nil mediaObserver = nil } @objc func create(_ params: NSDictionary, _ callback: Callback) { - delegate = RtcEngineEventHandler() { [weak self] in + delegate = RtcEngineEventHandler { [weak self] in self?.emitter($0, $1) } - engine = AgoraRtcEngineKit.sharedEngine(with: mapToRtcEngineConfig(params["config"] as! Dictionary), delegate: delegate) - callback.code(engine?.setAppType(AgoraRtcAppType(rawValue: (params["appType"] as! NSNumber).uintValue)!)) + engine = agoraRtcEngineKitFactory.create(params, delegate!) + callback.code(engine?.setAppType(AgoraRtcAppType(rawValue: (params["appType"] as! NSNumber).uintValue)!)) { + RtcEngineRegistry.shared.onRtcEngineCreated(self.engine) + return $0 + } } @objc func destroy(_ callback: Callback) { callback.resolve(engine) { [weak self] _ in self?.Release() + RtcEngineRegistry.shared.onRtcEngineDestroyed() + return nil } } @@ -371,6 +458,10 @@ class RtcEngineManager: NSObject, RtcEngineInterface { @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! + if let options = params["options"] as? [String: Any] { + callback.code(engine?.setClientRole(role, options: mapToClientRoleOptions(options))) + return + } callback.code(engine?.setClientRole(role)) } @@ -379,12 +470,20 @@ class RtcEngineManager: NSObject, RtcEngineInterface { let channelName = params["channelName"] as! String let optionalInfo = params["optionalInfo"] as? String let optionalUid = params["optionalUid"] as! NSNumber + if let options = params["options"] as? [String: Any] { + callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue, options: mapToChannelMediaOptions(options))) + return + } callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue)) } @objc func switchChannel(_ params: NSDictionary, _ callback: Callback) { let token = params["token"] as? String let channelName = params["channelName"] as! String + if let options = params["options"] as? [String: Any] { + callback.code(engine?.switchChannel(byToken: token, channelId: channelName, options: mapToChannelMediaOptions(options))) + return + } callback.code(engine?.switchChannel(byToken: token, channelId: channelName)) } @@ -406,6 +505,10 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } } + @objc func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.sendCustomReportMessage(params["id"] as! String, category: params["category"] as! String, event: params["event"] as! String, label: params["label"] as! String, value: (params["value"] as! NSNumber).intValue)) + } + @objc func getCallId(_ callback: Callback) { callback.resolve(engine) { $0.getCallId() @@ -450,6 +553,10 @@ class RtcEngineManager: NSObject, RtcEngineInterface { let userAccount = params["userAccount"] as! String let token = params["token"] as? String let channelName = params["channelName"] as! String + if let options = params["options"] as? [String: Any] { + callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName, options: mapToChannelMediaOptions(options))) + return + } callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName)) } @@ -513,6 +620,18 @@ class RtcEngineManager: NSObject, RtcEngineInterface { callback.code(engine?.enableAudioVolumeIndication((params["interval"] as! NSNumber).intValue, smooth: (params["smooth"] as! NSNumber).intValue, report_vad: params["report_vad"] as! Bool)) } + @objc func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.startRhythmPlayer(params["sound1"] as! String, sound2: params["sound2"] as! String, config: mapToRhythmPlayerConfig(params["config"] as! [String: Any]))) + } + + @objc func stopRhythmPlayer(_ callback: Callback) { + callback.code(engine?.stopRhythmPlayer()) + } + + @objc func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.configRhythmPlayer(mapToRhythmPlayerConfig(params as! [String: Any]))) + } + @objc func enableVideo(_ callback: Callback) { callback.code(engine?.enableVideo()) } @@ -522,7 +641,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! Dictionary))) + callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! [String: Any]))) } @objc func startPreview(_ callback: Callback) { @@ -554,10 +673,14 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setBeautyEffectOptions(params["enabled"] as! Bool, options: mapToBeautyOptions(params["options"] as! Dictionary))) + callback.code(engine?.setBeautyEffectOptions(params["enabled"] as! Bool, options: mapToBeautyOptions(params["options"] as! [String: Any]))) } @objc func startAudioMixing(_ params: NSDictionary, _ callback: Callback) { + if let startPos = params["startPos"] as? NSNumber { + callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue, startPos: startPos.intValue)) + return + } callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue)) } @@ -597,12 +720,16 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } } - @objc func getAudioMixingDuration(_ callback: Callback) { + @objc func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.getAudioMixingDuration()) { $0 } } + @objc func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getAudioFileInfo(params["filePath"] as! String)) + } + @objc func getAudioMixingCurrentPosition(_ callback: Callback) { callback.code(engine?.getAudioMixingCurrentPosition()) { $0 @@ -617,6 +744,25 @@ class RtcEngineManager: NSObject, RtcEngineInterface { callback.code(engine?.setAudioMixingPitch((params["pitch"] as! NSNumber).intValue)) } + @objc func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioMixingPlaybackSpeed(Int32((params["speed"] as! NSNumber).intValue))) + } + + @objc func getAudioTrackCount(_ callback: Callback) { + callback.code(engine?.getAudioTrackCount()) { + $0 + } + } + + @objc func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.selectAudioTrack((params["index"] as! NSNumber).intValue)) + } + + @objc func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) { + let mode = AgoraAudioMixingDualMonoMode(rawValue: UInt((params["mode"] as! NSNumber).intValue)) + callback.code(engine?.setAudioMixingDualMonoMode(mode!)) + } + @objc func getEffectsVolume(_ callback: Callback) { callback.resolve(engine) { $0.getEffectsVolume() @@ -632,9 +778,29 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func playEffect(_ params: NSDictionary, _ callback: Callback) { + if let startPos = (params["startPos"] as? NSNumber) { + callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool, startPos: startPos.int32Value)) + return + } callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool)) } + @objc func setEffectPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEffectPosition((params["soundId"] as! NSNumber).int32Value, pos: (params["pos"] as! NSNumber).intValue)) + } + + @objc func getEffectDuration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getEffectDuration(params["filePath"] as! String)) { + $0 + } + } + + @objc func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getEffectCurrentPosition((params["soundId"] as! NSNumber).int32Value)) { + $0 + } + } + @objc func stopEffect(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.stopEffect((params["soundId"] as! NSNumber).int32Value)) } @@ -693,6 +859,22 @@ class RtcEngineManager: NSObject, RtcEngineInterface { callback.code(engine?.setLocalVoiceReverbOf(AgoraAudioReverbType(rawValue: (params["reverbKey"] as! NSNumber).intValue)!, withValue: (params["value"] as! NSNumber).intValue)) } + @objc func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioEffectPreset(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceBeautifierPreset(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceConversionPreset(AgoraVoiceConversionPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioEffectParameters(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) + } + @objc func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.enableSoundPositionIndication(params["enabled"] as! Bool)) } @@ -702,7 +884,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! Dictionary))) + callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) } @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -714,11 +896,11 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func stopChannelMediaRelay(_ callback: Callback) { @@ -772,7 +954,15 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func startEchoTest(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startEchoTest(withInterval: (params["intervalInSeconds"] as! NSNumber).intValue)) + if let intervalInSeconds = (params["intervalInSeconds"] as? NSNumber) { + callback.code(engine?.startEchoTest(withInterval: intervalInSeconds.intValue)) + return + } + if let config = (params["config"] as? [String: Any]) { + callback.code(engine?.startEchoTest(withConfig: mapToEchoTestConfiguration(config))) + return + } + callback.code(engine?.startEchoTest()) } @objc func stopEchoTest(_ callback: Callback) { @@ -788,7 +978,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! Dictionary))) + callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! [String: Any]))) } @objc func stopLastmileProbeTest(_ callback: Callback) { @@ -829,7 +1019,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! Dictionary))) + callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! [String: Any]))) } @objc func clearVideoWatermarks(_ callback: Callback) { @@ -841,10 +1031,28 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setEncryptionMode(params["encryptionMode"] as? String)) + var encryptionMode = "" + switch (params["encryptionMode"] as! NSNumber).intValue { + case AgoraEncryptionMode.AES128XTS.rawValue: + encryptionMode = "aes-128-xts" + case AgoraEncryptionMode.AES128ECB.rawValue: + encryptionMode = "aes-128-ecb" + case AgoraEncryptionMode.AES256XTS.rawValue: + encryptionMode = "aes-256-xts" + default: encryptionMode = "" + } + callback.code(engine?.setEncryptionMode(encryptionMode)) + } + + @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) } @objc func startAudioRecording(_ params: NSDictionary, _ callback: Callback) { + if let config = params["config"] as? [String: Any] { + callback.code(engine?.startAudioRecording(withConfig: mapToAudioRecordingConfiguration(config))) + return + } callback.code(engine?.startAudioRecording(params["filePath"] as! String, sampleRate: (params["sampleRate"] as! NSNumber).intValue, quality: AgoraAudioRecordingQuality(rawValue: (params["quality"] as! NSNumber).intValue)!)) } @@ -853,7 +1061,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! Dictionary))) + callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) } @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -877,7 +1085,9 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func isCameraFocusSupported(_ callback: Callback) { - callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) + callback.resolve(engine) { + $0.isCameraFocusPositionInPreviewSupported() + } } @objc func isCameraExposurePositionSupported(_ callback: Callback) { @@ -918,7 +1128,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.enableFaceDetection(params["enable"] as! Bool)) + callback.code(engine?.enableFaceDetection(params["enabled"] as! Bool)) } @objc func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) { @@ -935,15 +1145,84 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! Dictionary))) + callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! [String: Any]))) } @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { var streamId = 0 - callback.code(engine?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in streamId } + if let config = params["config"] as? [String: Any] { + callback.code(engine?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in + streamId + } + return + } + callback.code(engine?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in + streamId + } } @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) } + + @objc func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceBeautifierParameters(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) + } + + @objc func getSdkVersion(_ callback: Callback) { + callback.success(AgoraRtcEngineKit.getSdkVersion()) + } + + @objc func getErrorDescription(_ params: NSDictionary, _ callback: Callback) { + callback.success(AgoraRtcEngineKit.getErrorDescription((params["error"] as! NSNumber).intValue)) + } + + @objc func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableDeepLearningDenoise(params["enabled"] as! Bool)) + } + + @objc func setCloudProxy(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setCloudProxy(AgoraCloudProxyType(rawValue: (params["proxyType"] as! NSNumber).uintValue)!)) + } + + @objc func uploadLogFile(_ callback: Callback) { + callback.resolve(engine) { + $0.uploadLogFile() + } + } + + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enabled"] as! Bool)) + } + + @objc func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) { + let list = params["ips"] as! [Any] + var ips: [String] = [] + for i in list.indices { + if let item = list[i] as? String { + ips.append(item) + } + } + callback.code(engine?.setLocalAccessPoint(ips, domain: params["domain"] as! String)) + } + + @objc func pauseAllChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.pauseAllChannelMediaRelay()) + } + + @objc func resumeAllChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.resumeAllChannelMediaRelay()) + } + + @objc func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableVirtualBackground(params["enabled"] as! Bool, backData: mapToVirtualBackgroundSource(params["backgroundSource"] as! [String: Any]))) + } + + @objc func takeSnapshot(_ params: NSDictionary, _ callback: Callback) { + var code: Int32? + if let ret = engine?.takeSnapshot(params["channel"] as! String, uid: (params["uid"] as! NSNumber).intValue, filePath: params["filePath"] as! String) { + code = Int32(ret); + } + callback.code(code) + } } diff --git a/RtcEngineEvent.swift b/RtcEngineEvent.swift index d8de1ea50..dd4f555ed 100644 --- a/RtcEngineEvent.swift +++ b/RtcEngineEvent.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class RtcEngineEvents { static let Warning = "Warning" @@ -36,6 +36,7 @@ class RtcEngineEvents { static let LocalVideoStateChanged = "LocalVideoStateChanged" static let RemoteAudioStateChanged = "RemoteAudioStateChanged" static let LocalAudioStateChanged = "LocalAudioStateChanged" + static let RequestAudioFileInfo = "RequestAudioFileInfo" static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" static let AudioRouteChanged = "AudioRouteChanged" @@ -80,8 +81,20 @@ class RtcEngineEvents { static let CameraReady = "CameraReady" static let VideoStopped = "VideoStopped" static let MetadataReceived = "MetadataReceived" - - static func toMap() -> Dictionary { + static let FirstLocalAudioFramePublished = "FirstLocalAudioFramePublished" + static let FirstLocalVideoFramePublished = "FirstLocalVideoFramePublished" + static let AudioPublishStateChanged = "AudioPublishStateChanged" + static let VideoPublishStateChanged = "VideoPublishStateChanged" + static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + static let RtmpStreamingEvent = "RtmpStreamingEvent" + static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + static let UploadLogResult = "UploadLogResult" + static let AirPlayIsConnected = "AirPlayIsConnected" + static let VirtualBackgroundSourceEnabled = "VirtualBackgroundSourceEnabled" + static let SnapshotTaken = "SnapshotTaken" + + static func toMap() -> [String: String] { return [ "Warning": Warning, "Error": Error, @@ -109,6 +122,7 @@ class RtcEngineEvents { "LocalVideoStateChanged": LocalVideoStateChanged, "RemoteAudioStateChanged": RemoteAudioStateChanged, "LocalAudioStateChanged": LocalAudioStateChanged, + "RequestAudioFileInfo": RequestAudioFileInfo, "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, "AudioRouteChanged": AudioRouteChanged, @@ -153,6 +167,18 @@ class RtcEngineEvents { "CameraReady": CameraReady, "VideoStopped": VideoStopped, "MetadataReceived": MetadataReceived, + "FirstLocalAudioFramePublished": FirstLocalAudioFramePublished, + "FirstLocalVideoFramePublished": FirstLocalVideoFramePublished, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, + "UploadLogResult": UploadLogResult, + "AirPlayIsConnected": AirPlayIsConnected, + "VirtualBackgroundSourceEnabled": VirtualBackgroundSourceEnabled, + "SnapshotTaken": SnapshotTaken, ] } } @@ -160,9 +186,9 @@ class RtcEngineEvents { class RtcEngineEventHandler: NSObject { static let PREFIX = "io.agora.rtc." - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - init(emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { self.emitter = emitter } @@ -172,287 +198,339 @@ class RtcEngineEventHandler: NSObject { } extension RtcEngineEventHandler: AgoraRtcEngineDelegate { - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { callback(RtcEngineEvents.Warning, warningCode.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { callback(RtcEngineEvents.Error, errorCode.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { + public func rtcEngine(_: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { callback(RtcEngineEvents.ApiCallExecuted, error, api, result) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.JoinChannelSuccess, channel, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { + public func rtcEngine(_: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { callback(RtcEngineEvents.LeaveChannel, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { callback(RtcEngineEvents.LocalUserRegistered, uid, userAccount) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { callback(RtcEngineEvents.UserInfoUpdated, uid, userInfo.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + public func rtcEngine(_: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { callback(RtcEngineEvents.ClientRoleChanged, oldRole.rawValue, newRole.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.UserJoined, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + public func rtcEngine(_: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { callback(RtcEngineEvents.UserOffline, uid, reason.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + public func rtcEngine(_: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { callback(RtcEngineEvents.ConnectionStateChanged, state.rawValue, reason.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { + public func rtcEngine(_: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { callback(RtcEngineEvents.NetworkTypeChanged, type.rawValue) } - public func rtcEngineConnectionDidLost(_ engine: AgoraRtcEngineKit) { + public func rtcEngineConnectionDidLost(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.ConnectionLost) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { + public func rtcEngine(_: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { callback(RtcEngineEvents.TokenPrivilegeWillExpire, token) } - public func rtcEngineRequestToken(_ engine: AgoraRtcEngineKit) { + public func rtcEngineRequestToken(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.RequestToken) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { callback(RtcEngineEvents.AudioVolumeIndication, speakers.toMapList(), totalVolume) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { callback(RtcEngineEvents.ActiveSpeaker, speakerUid) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { callback(RtcEngineEvents.FirstLocalAudioFrame, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { callback(RtcEngineEvents.FirstLocalVideoFrame, Int(size.width), Int(size.height), elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserMuteVideo, uid, muted) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { callback(RtcEngineEvents.VideoSizeChanged, uid, Int(size.width), Int(size.height), rotation) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { callback(RtcEngineEvents.RemoteVideoStateChanged, uid, state.rawValue, reason.rawValue, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { callback(RtcEngineEvents.LocalVideoStateChanged, state.rawValue, error.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { callback(RtcEngineEvents.RemoteAudioStateChanged, uid, state.rawValue, reason.rawValue, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { callback(RtcEngineEvents.LocalAudioStateChanged, state.rawValue, error.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { + public func rtcEngine(_ engine: AgoraRtcEngineKit, didRequest info: AgoraRtcAudioFileInfo, error: AgoraAudioFileInfoError) { + callback(RtcEngineEvents.RequestAudioFileInfo, info.toMap(), error.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { callback(RtcEngineEvents.LocalPublishFallbackToAudioOnly, isFallbackOrRecover) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { callback(RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, uid, isFallbackOrRecover) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { + public func rtcEngine(_: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { callback(RtcEngineEvents.AudioRouteChanged, routing.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { + public func rtcEngine(_: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { callback(RtcEngineEvents.CameraFocusAreaChanged, rect.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { + public func rtcEngine(_: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { callback(RtcEngineEvents.CameraExposureAreaChanged, rect.toMap()) } - func rtcEngine(_ engine: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { + public func rtcEngine(_: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { callback(RtcEngineEvents.FacePositionChanged, width, height, faces?.toMapList()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { + public func rtcEngine(_: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { callback(RtcEngineEvents.RtcStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { + public func rtcEngine(_: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { callback(RtcEngineEvents.LastmileQuality, quality.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + public func rtcEngine(_: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { callback(RtcEngineEvents.NetworkQuality, uid, txQuality.rawValue, rxQuality.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { + public func rtcEngine(_: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { callback(RtcEngineEvents.LastmileProbeResult, result.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { callback(RtcEngineEvents.LocalVideoStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { callback(RtcEngineEvents.LocalAudioStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { callback(RtcEngineEvents.RemoteVideoStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { callback(RtcEngineEvents.RemoteAudioStats, stats.toMap()) } - public func rtcEngineLocalAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { + public func rtcEngineLocalAudioMixingDidFinish(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.AudioMixingFinished) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, errorCode: AgoraAudioMixingErrorCode) { - callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, errorCode.rawValue) + public func rtcEngine(_: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) { + callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, reason.rawValue) } - public func rtcEngineRemoteAudioMixingDidStart(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android + public func rtcEngineRemoteAudioMixingDidStart(_: AgoraRtcEngineKit) { + // TODO: Not in Android } - public func rtcEngineRemoteAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android + public func rtcEngineRemoteAudioMixingDidFinish(_: AgoraRtcEngineKit) { + // TODO: Not in Android } - public func rtcEngineDidAudioEffectFinish(_ engine: AgoraRtcEngineKit, soundId: Int) { + public func rtcEngineDidAudioEffectFinish(_: AgoraRtcEngineKit, soundId: Int) { callback(RtcEngineEvents.AudioEffectFinished, soundId) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state.rawValue, errorCode.rawValue) } - public func rtcEngineTranscodingUpdated(_ engine: AgoraRtcEngineKit) { + public func rtcEngineTranscodingUpdated(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.TranscodingUpdated) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + public func rtcEngine(_: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { callback(RtcEngineEvents.StreamInjectedStatus, url, uid, status.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + public func rtcEngine(_: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { callback(RtcEngineEvents.StreamMessage, uid, streamId, String(data: data, encoding: .utf8)) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { callback(RtcEngineEvents.StreamMessageError, uid, streamId, error, missed, cached) } - public func rtcEngineMediaEngineDidLoaded(_ engine: AgoraRtcEngineKit) { + public func rtcEngineMediaEngineDidLoaded(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.MediaEngineLoadSuccess) } - public func rtcEngineMediaEngineDidStartCall(_ engine: AgoraRtcEngineKit) { + public func rtcEngineMediaEngineDidStartCall(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.MediaEngineStartCallSuccess) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + public func rtcEngine(_: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state.rawValue, error.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { + public func rtcEngine(_: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { callback(RtcEngineEvents.ChannelMediaRelayEvent, event.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteVideoFrame, uid, Int(size.width), Int(size.height), elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteAudioFrame, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserMuteAudio, uid, muted) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { + public func rtcEngine(_: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { callback(RtcEngineEvents.StreamPublished, url, errorCode.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { + public func rtcEngine(_: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { callback(RtcEngineEvents.StreamUnpublished, url) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { callback(RtcEngineEvents.RemoteAudioTransportStats, uid, delay, lost, rxKBitRate) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { callback(RtcEngineEvents.RemoteVideoTransportStats, uid, delay, lost, rxKBitRate) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserEnableVideo, uid, enabled) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserEnableLocalVideo, uid, enabled) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid, Int(size.width), Int(size.height), elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { + public func rtcEngine(_: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { callback(RtcEngineEvents.MicrophoneEnabled, enabled) } - public func rtcEngineConnectionDidInterrupted(_ engine: AgoraRtcEngineKit) { + public func rtcEngineConnectionDidInterrupted(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.ConnectionInterrupted) } - public func rtcEngineConnectionDidBanned(_ engine: AgoraRtcEngineKit) { + public func rtcEngineConnectionDidBanned(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.ConnectionBanned) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { callback(RtcEngineEvents.AudioQuality, uid, quality.rawValue, delay, lost) } - public func rtcEngineCameraDidReady(_ engine: AgoraRtcEngineKit) { + public func rtcEngineCameraDidReady(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.CameraReady) } - public func rtcEngineVideoDidStop(_ engine: AgoraRtcEngineKit) { + public func rtcEngineVideoDidStop(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.VideoStopped) } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) { + callback(RtcEngineEvents.FirstLocalAudioFramePublished, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFramePublished elapsed: Int) { + callback(RtcEngineEvents.FirstLocalVideoFramePublished, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + callback(RtcEngineEvents.RtmpStreamingEvent, url, eventCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + callback(RtcEngineEvents.UserSuperResolutionEnabled, uid, enabled, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, uploadLogResultRequestId requestId: String, success: Bool, reason: AgoraUploadErrorReason) { + callback(RtcEngineEvents.UploadLogResult, requestId, success, reason.rawValue) + } + + public func rtcEngineAirPlayIsConnected(_ engine: AgoraRtcEngineKit) { + callback(RtcEngineEvents.AirPlayIsConnected) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, virtualBackgroundSourceEnabled enabled: Bool, reason: AgoraVirtualBackgroundSourceStateReason) { + callback(RtcEngineEvents.VirtualBackgroundSourceEnabled, enabled, reason.rawValue) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, snapshotTaken channel: String, uid: UInt, filePath: String, width: Int, height: Int, errCode: Int) { + callback(RtcEngineEvents.SnapshotTaken, channel, uid, filePath, width, height, errCode) + } } diff --git a/RtcEnginePlugin.h b/RtcEnginePlugin.h new file mode 100644 index 000000000..93d89eef8 --- /dev/null +++ b/RtcEnginePlugin.h @@ -0,0 +1,31 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A `RtcEnginePlugin` allows developers to interact with the `RtcEngine` which created from flutter + * side. + */ +@protocol RtcEnginePlugin + +/** + * This callback will be called when the `RtcEngine` is created by + [RtcEngine.createWithContext](https://docs.agora.io/cn/Video/API%20Reference/flutter/agora_rtc_engine/RtcEngine/createWithContext.html) + * function from flutter. + + * NOTE that you should not call `AgoraRtcEngineKit.destroy`, because it will also destroy the `RtcEngine` + * used by flutter side. + * + * @param rtcEngine The same `AgoraRtcEngineKit` used by flutter side + */ +- (void)onRtcEngineCreated:(AgoraRtcEngineKit *_Nullable)rtcEngine; + +/** + * This callback will be called when the [RtcEngine.destroy](https://docs.agora.io/cn/Video/API%20Reference/flutter/v4.0.7/rtc_channel/RtcChannel/destroy.html) + * function is called from flutter. + */ +- (void)onRtcEngineDestroyed; +@end + +NS_ASSUME_NONNULL_END diff --git a/RtcEnginePluginRegistrant.swift b/RtcEnginePluginRegistrant.swift new file mode 100644 index 000000000..9921db30e --- /dev/null +++ b/RtcEnginePluginRegistrant.swift @@ -0,0 +1,22 @@ +import Foundation + +/** + * Class for register the `RtcEnginePlugin`. + */ +@objc +public class RtcEnginePluginRegistrant: NSObject { + /** + * Register a `RtcEnginePlugin`. The `plugin` will be called when the `RtcEngine` is created from + * flutter side. + */ + @objc public static func register(_ plugin: RtcEnginePlugin) { + RtcEngineRegistry.shared.add(plugin) + } + + /** + * Unregister a previously registered `RtcEnginePlugin`. + */ + @objc public static func unregister(_ plugin: RtcEnginePlugin) { + RtcEngineRegistry.shared.remove(plugin) + } +} diff --git a/RtcEngineRegistry.swift b/RtcEngineRegistry.swift new file mode 100644 index 000000000..ca4c7ebd9 --- /dev/null +++ b/RtcEngineRegistry.swift @@ -0,0 +1,61 @@ +import Foundation +import AgoraRtcKit + +fileprivate struct PluginKey: Hashable, Equatable { + let type: AnyClass + + public static func == (lhs: PluginKey, rhs: PluginKey) -> Bool { + return lhs.type == rhs.type + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(type)) + } +} + +/** + * The `RtcEngineRegistry` is response to add, remove and notify the callback when `RtcEngine` is created + * from flutter side. + */ +internal class RtcEngineRegistry : NSObject { + + private override init() {} + + static let shared = RtcEngineRegistry() + + private var plugins: [PluginKey : RtcEnginePlugin] = [PluginKey: RtcEnginePlugin]() + + /** + * Add a `RtcEnginePlugin`. + */ + func add(_ plugin: RtcEnginePlugin) { + let key = PluginKey(type: type(of: plugin)) + guard plugins[key] == nil else { + return + } + plugins[key] = plugin + } + + /** + * Remove the previously added `RtcEnginePlugin`. + */ + func remove(_ plugin: RtcEnginePlugin) { + plugins.removeValue(forKey: PluginKey(type: type(of: plugin))) + } +} + +extension RtcEngineRegistry : RtcEnginePlugin { + // MARK: - protocol from RtcEnginePlugin + public func onRtcEngineCreated(_ rtcEngine: AgoraRtcEngineKit?) { + for (_, plugin) in plugins { + plugin.onRtcEngineCreated(rtcEngine) + } + } + + // MARK: - protocol from RtcEnginePlugin + public func onRtcEngineDestroyed() { + for (_, plugin) in plugins { + plugin.onRtcEngineDestroyed() + } + } +} diff --git a/RtcSurfaceView.swift b/RtcSurfaceView.swift index 89b4f9826..1cb7f72f9 100644 --- a/RtcSurfaceView.swift +++ b/RtcSurfaceView.swift @@ -1,14 +1,6 @@ -// -// RtcSurfaceView.swift -// RCTAgora -// -// Created by LXH on 2020/4/15. -// Copyright © 2020 Syan. All rights reserved. -// - +import AgoraRtcKit import Foundation import UIKit -import AgoraRtcKit class RtcSurfaceView: UIView { private var surface: UIView @@ -28,7 +20,8 @@ class RtcSurfaceView: UIView { return "frame" } - required init?(coder: NSCoder) { + @available(*, unavailable) + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -87,7 +80,7 @@ class RtcSurfaceView: UIView { if canvas.uid == 0 { engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) } else { - if let `channel` = channel { + if let channel = channel { channel.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) } else { engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) @@ -95,7 +88,7 @@ class RtcSurfaceView: UIView { } } - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { + override func observeValue(forKeyPath keyPath: String?, of _: Any?, change: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) { if keyPath == observerForKeyPath() { if let rect = change?[.newKey] as? CGRect { surface.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: rect.size)