diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..9f11b755a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ 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 359cc7046..ae6c5240f 100644 --- a/BeanCovertor.swift +++ b/BeanCovertor.swift @@ -6,189 +6,189 @@ // 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? Int { - point.x = CGFloat(x) + if let x = map["x"] as? NSNumber { + point.x = CGFloat(truncating: x) } - if let y = map["y"] as? Int { - point.y = CGFloat(y) + if let y = map["y"] as? NSNumber { + point.y = CGFloat(truncating: y) } return point } -func mapToSize(map: Dictionary) -> CGSize { +func mapToSize(_ map: [String: Any]) -> CGSize { var size = CGSize() - if let width = map["width"] as? Int { - size.width = CGFloat(width) + if let width = map["width"] as? NSNumber { + size.width = CGFloat(truncating: width) } - if let height = map["height"] as? Int { - size.height = CGFloat(height) + if let height = map["height"] as? NSNumber { + size.height = CGFloat(truncating: height) } return size } -func mapToRect(map: Dictionary) -> CGRect { - CGRect( - origin: mapToPoint(map: map), - size: mapToSize(map: map) +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 { - config.dimensions = mapToSize(map: dimensions) + if let dimensions = map["dimensions"] as? [String: Any] { + config.dimensions = mapToSize(dimensions) } - if let frameRate = map["frameRate"] as? Int { - config.frameRate = frameRate + if let frameRate = map["frameRate"] as? NSNumber { + config.frameRate = frameRate.intValue } - if let minFrameRate = map["minFrameRate"] as? Int { - config.minFrameRate = minFrameRate + if let minFrameRate = map["minFrameRate"] as? NSNumber { + config.minFrameRate = minFrameRate.intValue } - if let bitrate = map["bitrate"] as? Int { - config.bitrate = bitrate + if let bitrate = map["bitrate"] as? NSNumber { + config.bitrate = bitrate.intValue } - if let minBitrate = map["minBitrate"] as? Int { - config.minBitrate = minBitrate + if let minBitrate = map["minBitrate"] as? NSNumber { + config.minBitrate = minBitrate.intValue } - if let orientationMode = map["orientationMode"] as? Int { - if let orientationMode = AgoraVideoOutputOrientationMode(rawValue: orientationMode) { + if let orientationMode = map["orientationMode"] as? NSNumber { + if let orientationMode = AgoraVideoOutputOrientationMode(rawValue: orientationMode.intValue) { config.orientationMode = orientationMode } } - if let degradationPreference = map["degradationPrefer"] as? Int { - if let degradationPreference = AgoraDegradationPreference(rawValue: degradationPreference) { + if let degradationPreference = map["degradationPrefer"] as? NSNumber { + if let degradationPreference = AgoraDegradationPreference(rawValue: degradationPreference.intValue) { config.degradationPreference = degradationPreference } } - if let mirrorMode = map["mirrorMode"] as? Int { - if let mirrorMode = AgoraVideoMirrorMode(rawValue: UInt(mirrorMode)) { + if let mirrorMode = map["mirrorMode"] as? NSNumber { + if let mirrorMode = AgoraVideoMirrorMode(rawValue: mirrorMode.uintValue) { config.mirrorMode = mirrorMode } } return config } -func mapToBeautyOptions(map: Dictionary) -> AgoraBeautyOptions { +func mapToBeautyOptions(_ map: [String: Any]) -> AgoraBeautyOptions { let options = AgoraBeautyOptions() - if let lighteningContrastLevel = map["lighteningContrastLevel"] as? Int { - if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: UInt(lighteningContrastLevel)) { + if let lighteningContrastLevel = map["lighteningContrastLevel"] as? NSNumber { + if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: lighteningContrastLevel.uintValue) { options.lighteningContrastLevel = lighteningContrastLevel } } - if let lighteningLevel = map["lighteningLevel"] as? Float { - options.lighteningLevel = lighteningLevel + if let lighteningLevel = map["lighteningLevel"] as? NSNumber { + options.lighteningLevel = lighteningLevel.floatValue } - if let smoothnessLevel = map["smoothnessLevel"] as? Float { - options.smoothnessLevel = smoothnessLevel + if let smoothnessLevel = map["smoothnessLevel"] as? NSNumber { + options.smoothnessLevel = smoothnessLevel.floatValue } - if let rednessLevel = map["rednessLevel"] as? Float { - options.rednessLevel = rednessLevel + if let rednessLevel = map["rednessLevel"] as? NSNumber { + options.rednessLevel = rednessLevel.floatValue } 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) { image.url = url } } - image.rect = mapToRect(map: map) + image.rect = mapToRect(map) return image } -func mapToTranscodingUser(map: Dictionary) -> AgoraLiveTranscodingUser { +func mapToTranscodingUser(_ map: [String: Any]) -> AgoraLiveTranscodingUser { let user = AgoraLiveTranscodingUser() - if let uid = map["uid"] as? Int { - user.uid = UInt(uid) + if let uid = map["uid"] as? NSNumber { + user.uid = uid.uintValue } - user.rect = mapToRect(map: map) - if let zOrder = map["zOrder"] as? Int { - user.zOrder = zOrder + user.rect = mapToRect(map) + if let zOrder = map["zOrder"] as? NSNumber { + user.zOrder = zOrder.intValue } - if let alpha = map["alpha"] as? Double { - user.alpha = alpha + if let alpha = map["alpha"] as? NSNumber { + user.alpha = alpha.doubleValue } - if let audioChannel = map["audioChannel"] as? Int { - user.audioChannel = audioChannel + if let audioChannel = map["audioChannel"] as? NSNumber { + user.audioChannel = audioChannel.intValue } return user } -func mapToColor(map: Dictionary) -> UIColor { - UIColor( - red: CGFloat(map["red"] as! Int), - green: CGFloat(map["green"] as! Int), - blue: CGFloat(map["blue"] as! Int), +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 ) } -func mapToLiveTranscoding(map: Dictionary) -> AgoraLiveTranscoding { +func mapToLiveTranscoding(_ map: [String: Any]) -> AgoraLiveTranscoding { let transcoding = AgoraLiveTranscoding.default() - transcoding.size = mapToSize(map: map) - if let videoBitrate = map["videoBitrate"] as? Int { - transcoding.videoBitrate = videoBitrate + transcoding.size = mapToSize(map) + if let videoBitrate = map["videoBitrate"] as? NSNumber { + transcoding.videoBitrate = videoBitrate.intValue } - if let videoFramerate = map["videoFramerate"] as? Int { - transcoding.videoFramerate = videoFramerate + if let videoFramerate = map["videoFramerate"] as? NSNumber { + transcoding.videoFramerate = videoFramerate.intValue } if let lowLatency = map["lowLatency"] as? Bool { transcoding.lowLatency = lowLatency } - if let videoGop = map["videoGop"] as? Int { - transcoding.videoGop = videoGop + if let videoGop = map["videoGop"] as? NSNumber { + transcoding.videoGop = videoGop.intValue } - if let watermark = map["watermark"] as? Dictionary { - transcoding.watermark = mapToAgoraImage(map: watermark) + if let watermark = map["watermark"] as? [String: Any] { + transcoding.watermark = mapToAgoraImage(watermark) } - if let backgroundImage = map["backgroundImage"] as? Dictionary { - transcoding.backgroundImage = mapToAgoraImage(map: backgroundImage) + if let backgroundImage = map["backgroundImage"] as? [String: Any] { + transcoding.backgroundImage = mapToAgoraImage(backgroundImage) } - if let audioSampleRate = map["audioSampleRate"] as? Int { - if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate) { + if let audioSampleRate = map["audioSampleRate"] as? NSNumber { + if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate.intValue) { transcoding.audioSampleRate = audioSampleRate } } - if let audioBitrate = map["audioBitrate"] as? Int { - transcoding.audioBitrate = audioBitrate + if let audioBitrate = map["audioBitrate"] as? NSNumber { + transcoding.audioBitrate = audioBitrate.intValue } - if let audioChannels = map["audioChannels"] as? Int { - transcoding.audioChannels = audioChannels + if let audioChannels = map["audioChannels"] as? NSNumber { + transcoding.audioChannels = audioChannels.intValue } - if let audioCodecProfile = map["audioCodecProfile"] as? Int { - if let audioCodecProfile = AgoraAudioCodecProfileType(rawValue: audioCodecProfile) { + if let audioCodecProfile = map["audioCodecProfile"] as? NSNumber { + if let audioCodecProfile = AgoraAudioCodecProfileType(rawValue: audioCodecProfile.intValue) { transcoding.audioCodecProfile = audioCodecProfile } } - if let videoCodecProfile = map["videoCodecProfile"] as? Int { - if let videoCodecProfile = AgoraVideoCodecProfileType(rawValue: videoCodecProfile) { + if let videoCodecProfile = map["videoCodecProfile"] as? NSNumber { + if let videoCodecProfile = AgoraVideoCodecProfileType(rawValue: videoCodecProfile.intValue) { transcoding.videoCodecProfile = videoCodecProfile } } - if let backgroundColor = map["backgroundColor"] as? Dictionary { - transcoding.backgroundColor = mapToColor(map: backgroundColor) + 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 { - transcodingUsers.forEach { (item) in - if let item = item as? Dictionary { - transcoding.add(mapToTranscodingUser(map: item)) + if let transcodingUsers = map["transcodingUsers"] as? [Any] { + transcodingUsers.forEach { + if let item = $0 as? [String: Any] { + transcoding.add(mapToTranscodingUser(item)) } } } 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 @@ -196,21 +196,21 @@ func mapToChannelMediaInfo(map: Dictionary) -> AgoraChannelMediaRel if let token = map["token"] as? String { info.token = token } - if let uid = map["uid"] as? UInt { - info.uid = uid + if let uid = map["uid"] as? NSNumber { + info.uid = uid.uintValue } return info } -func mapToChannelMediaRelayConfiguration(map: Dictionary) -> AgoraChannelMediaRelayConfiguration { +func mapToChannelMediaRelayConfiguration(_ map: [String: Any]) -> AgoraChannelMediaRelayConfiguration { let config = AgoraChannelMediaRelayConfiguration() - if let srcInfo = map["srcInfo"] as? Dictionary { - config.sourceInfo = mapToChannelMediaInfo(map: srcInfo) + if let srcInfo = map["srcInfo"] as? [String: Any] { + config.sourceInfo = mapToChannelMediaInfo(srcInfo) } - if let destInfos = map["destInfos"] as? Array { - destInfos.forEach { (item) in - if let item = item as? Dictionary { - let info = mapToChannelMediaInfo(map: item) + if let destInfos = map["destInfos"] as? [Any] { + destInfos.forEach { + 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) -> AgoraC 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 @@ -226,71 +226,77 @@ func mapToLastmileProbeConfig(map: Dictionary) -> AgoraLastmileProb if let probeDownlink = map["probeDownlink"] as? Bool { config.probeDownlink = probeDownlink } - if let expectedUplinkBitrate = map["expectedUplinkBitrate"] as? Int { - config.expectedUplinkBitrate = UInt(expectedUplinkBitrate) + if let expectedUplinkBitrate = map["expectedUplinkBitrate"] as? NSNumber { + config.expectedUplinkBitrate = expectedUplinkBitrate.uintValue } - if let expectedDownlinkBitrate = map["expectedDownlinkBitrate"] as? Int { - config.expectedDownlinkBitrate = UInt(expectedDownlinkBitrate) + if let expectedDownlinkBitrate = map["expectedDownlinkBitrate"] as? NSNumber { + config.expectedDownlinkBitrate = expectedDownlinkBitrate.uintValue } 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 { - options.positionInLandscapeMode = mapToRect(map: positionInLandscapeMode) + if let positionInLandscapeMode = map["positionInLandscapeMode"] as? [String: Any] { + options.positionInLandscapeMode = mapToRect(positionInLandscapeMode) } - if let positionInPortraitMode = map["positionInPortraitMode"] as? Dictionary { - options.positionInPortraitMode = mapToRect(map: positionInPortraitMode) + 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: map) - if let videoGop = map["videoGop"] as? Int { - config.videoGop = videoGop + config.size = mapToSize(map) + if let videoGop = map["videoGop"] as? NSNumber { + config.videoGop = videoGop.intValue } - if let videoFramerate = map["videoFramerate"] as? Int { - config.videoFramerate = videoFramerate + if let videoFramerate = map["videoFramerate"] as? NSNumber { + config.videoFramerate = videoFramerate.intValue } - if let videoBitrate = map["videoBitrate"] as? Int { - config.videoBitrate = videoBitrate + if let videoBitrate = map["videoBitrate"] as? NSNumber { + config.videoBitrate = videoBitrate.intValue } - if let audioSampleRate = map["audioSampleRate"] as? Int { - if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate) { + if let audioSampleRate = map["audioSampleRate"] as? NSNumber { + if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate.intValue) { config.audioSampleRate = audioSampleRate } } - if let audioBitrate = map["audioBitrate"] as? Int { - config.audioBitrate = audioBitrate + if let audioBitrate = map["audioBitrate"] as? NSNumber { + config.audioBitrate = audioBitrate.intValue } - if let audioChannels = map["audioChannels"] as? Int { - config.audioChannels = audioChannels + if let audioChannels = map["audioChannels"] as? NSNumber { + config.audioChannels = audioChannels.intValue } return config } -func mapToCameraCapturerConfiguration(map: Dictionary) -> AgoraCameraCapturerConfiguration { +func mapToCameraCapturerConfiguration(_ map: [String: Any]) -> AgoraCameraCapturerConfiguration { let config = AgoraCameraCapturerConfiguration() - if let preference = map["preference"] as? Int { - if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference) { + if let preference = map["preference"] as? NSNumber { + if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference.intValue) { config.preference = preference } } - if let cameraDirection = map["cameraDirection"] as? Int { - if let cameraDirection = AgoraCameraDirection(rawValue: cameraDirection) { + 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 } } 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,5 +304,153 @@ func mapToChannelMediaOptions(map: Dictionary) -> AgoraRtcChannelMe 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: [String: Any]) -> AgoraRtcEngineConfig { + let config = AgoraRtcEngineConfig() + config.appId = map["appId"] as? String + if let areaCode = map["areaCode"] as? NSNumber { + 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 562777cae..8c5bc130a 100644 --- a/Callback.swift +++ b/Callback.swift @@ -6,24 +6,36 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation +@objc protocol Callback: class { - associatedtype T - - func success(_ data: Self.T?) + func success(_ data: Any?) func failure(_ code: String, _ message: String) } extension Callback { - func code(_ code: Int32?) { - let newCode: Int = Int(code ?? Int32(AgoraErrorCode.notInitialized.rawValue)) - if newCode == 0 { - success(nil) - } else if newCode < 0 { - failure(String(newCode), AgoraRtcEngineKit.getErrorDescription(abs(newCode)) ?? "") + func code(_ code: Int32?, _ runnable: ((Int32?) -> Any?)? = nil) { + if code == nil || code! < 0 { + let newCode = abs(Int(code ?? Int32(AgoraErrorCode.notInitialized.rawValue))) + failure(String(newCode), AgoraRtcEngineKit.getErrorDescription(newCode) ?? "") + return + } + + let res = runnable?(code) + success(res) + } + + func resolve(_ source: T?, _ runnable: (T) -> Any?) { + guard let source = source else { + let code = AgoraErrorCode.notInitialized.rawValue + failure(String(code), AgoraRtcEngineKit.getErrorDescription(code) ?? "") + return } + + let res = runnable(source) + success(res) } } diff --git a/Extensions.swift b/Extensions.swift index a4b22da0c..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 { - [ - "totalDuration": duration, + func toMap() -> [String: Any?] { + return [ + "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,25 +54,25 @@ 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, "networkTransportDelay": networkTransportDelay, @@ -81,14 +82,19 @@ extension AgoraRtcRemoteAudioStats { "receivedSampleRate": receivedSampleRate, "receivedBitrate": receivedBitrate, "totalFrozenTime": totalFrozenTime, - "frozenRate": frozenRate + "frozenRate": frozenRate, + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, + "qoeQuality": qoeQuality, + "qualityChangedReason": qualityChangedReason, + "mosValue": mosValue, ] } } extension AgoraRtcLocalVideoStats { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "sentBitrate": sentBitrate, "sentFrameRate": sentFrameRate, "encoderOutputFrameRate": encoderOutputFrameRate, @@ -100,14 +106,17 @@ 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, "width": width, @@ -118,51 +127,82 @@ extension AgoraRtcRemoteVideoStats { "packetLossRate": packetLossRate, "rxStreamType": rxStreamType.rawValue, "totalFrozenTime": totalFrozenTime, - "frozenRate": frozenRate + "frozenRate": frozenRate, + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, ] } } extension AgoraRtcAudioVolumeInfo { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "uid": uid, "volume": volume, "vad": vad, - "channelId": channelId + "channelId": channelId, ] } } -typealias AudioVolumeArray = Array - -extension AudioVolumeArray { - func toMapList() -> Array> { - var list = [Dictionary]() - forEach { (item) in - list.append(item.toMap()) +extension Array where Element: AgoraRtcAudioVolumeInfo { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { + list.append($0.toMap()) } return list } } 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() -> [String: Any?] { + return [ + "x": x, + "y": y, + "width": width, + "height": height, + "distance": distance, + ] + } +} + +extension AgoraRtcAudioFileInfo { + func toMap() -> [String: Any?] { + return [ + "filePath": filePath, + "durationMs": durationMs, + ] + } +} + +extension Array where Element: AgoraFacePositionInfo { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { + list.append($0.toMap()) + } + return list + } +} diff --git a/MediaObserver.swift b/MediaObserver.swift index 162241532..514fb21d0 100644 --- a/MediaObserver.swift +++ b/MediaObserver.swift @@ -6,33 +6,33 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class MediaObserver: NSObject { - private var emitter: (_ methodName: String, _ data: Dictionary?) -> Void - private var maxMetadataSize = 0 + private var emitter: (_ data: [String: Any?]?) -> Void + private var maxMetadataSize = 1024 private var metadataList = [String]() - init(emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ data: [String: Any?]?) -> Void) { self.emitter = emitter } - func addMetadata(metadata: String) { + func addMetadata(_ metadata: String) { metadataList.append(metadata) } - func setMaxMetadataSize(size: Int) { + func setMaxMetadataSize(_ size: Int) { maxMetadataSize = size } } extension MediaObserver: AgoraMediaMetadataDataSource { func metadataMaxSize() -> Int { - maxMetadataSize + 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) } @@ -42,10 +42,8 @@ extension MediaObserver: AgoraMediaMetadataDataSource { extension MediaObserver: AgoraMediaMetadataDelegate { func receiveMetadata(_ data: Data, fromUser uid: Int, atTimestamp timestamp: TimeInterval) { - emitter("MetadataReceived", [ - "buffer": String(data: data, encoding: .utf8), - "uid": uid, - "timeStampMs": timestamp + emitter([ + "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp], ]) } } diff --git a/RtcChannel.swift b/RtcChannel.swift index 2f1918e55..221779ffe 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, @@ -21,63 +21,137 @@ protocol RtcChannelInterface: RtcChannelEncryptionInterface, RtcChannelInjectStreamInterface, RtcChannelStreamMessageInterface { - associatedtype Map - associatedtype Callback + func create(_ params: NSDictionary, _ callback: Callback) + + func destroy(_ params: NSDictionary, _ callback: Callback) + + func setClientRole(_ params: NSDictionary, _ callback: Callback) + + func joinChannel(_ params: NSDictionary, _ callback: Callback) + + func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) + + func leaveChannel(_ params: NSDictionary, _ callback: Callback) + + func renewToken(_ params: NSDictionary, _ callback: Callback) + + 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) +} + +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 create(_ channelId: String, _ callback: Callback?) + func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) - func destroy(_ channelId: String, _ callback: Callback?) + func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - func setClientRole(_ channelId: String, _ role: Int, _ callback: Callback?) + @available(*, deprecated) + func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) +} - func joinChannel(_ channelId: String, _ token: String?, _ optionalInfo: String?, _ optionalUid: Int, _ options: Map, _ callback: Callback?) +protocol RtcChannelVoicePositionInterface { + func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) +} - func joinChannelWithUserAccount(_ channelId: String, _ token: String?, _ userAccount: String, _ options: Map, _ callback: Callback?) +protocol RtcChannelPublishStreamInterface { + func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) - func leaveChannel(_ channelId: String, _ callback: Callback?) + func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) - func renewToken(_ channelId: String, _ token: String, _ callback: Callback?) + func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) +} - func getConnectionState(_ channelId: String, _ callback: Callback?) +protocol RtcChannelMediaRelayInterface { + func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func publish(_ channelId: String, _ callback: Callback?) + func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func unpublish(_ channelId: String, _ callback: Callback?) + func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func getCallId(_ channelId: String, _ callback: Callback?) + func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + + func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelDualStreamInterface { + func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) + + func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) } -class RtcChannelManager { +protocol RtcChannelFallbackInterface { + func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelMediaMetadataInterface { + func registerMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) + + func unregisterMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) + + func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) + + func sendMetadata(_ params: NSDictionary, _ callback: Callback) +} + +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 { + func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) + + func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelStreamMessageInterface { + func createDataStream(_ params: NSDictionary, _ callback: Callback) + + func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) +} + +@objc +class RtcChannelManager: NSObject, RtcChannelInterface { + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void private var rtcChannelMap = [String: AgoraRtcChannel]() private var rtcChannelDelegateMap = [String: RtcChannelEventHandler]() private var mediaObserverMap = [String: MediaObserver]() - func create(_ engine: AgoraRtcEngineKit, _ channelId: String, _ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - if let rtcChannel = engine.createRtcChannel(channelId) { - let delegate = RtcChannelEventHandler() { methodName, data in - emit(methodName, data) - } - rtcChannel.setRtcChannelDelegate(delegate) - rtcChannelMap[channelId] = rtcChannel - rtcChannelDelegateMap[channelId] = delegate - } - } - - func destroy(_ channelId: String) -> Int32 { - if let rtcChannel = self[channelId] { - let res = rtcChannel.destroy() - if (res == 0) { - rtcChannelMap.removeValue(forKey: channelId) - rtcChannelDelegateMap.removeValue(forKey: channelId) - } - return res - } - return Int32(AgoraErrorCode.notInitialized.rawValue) + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { + self.emitter = emitter } - func release() { - rtcChannelMap.forEach { key, value in - value.destroy() + func Release() { + rtcChannelMap.forEach { + $1.destroy() } rtcChannelMap.removeAll() rtcChannelDelegateMap.removeAll() @@ -85,153 +159,245 @@ class RtcChannelManager { } subscript(channelId: String) -> AgoraRtcChannel? { - get { - rtcChannelMap[channelId] - } + return rtcChannelMap[channelId] } - func registerMediaMetadataObserver(_ channelId: String, _ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) -> Int32 { - if let rtcChannel = self[channelId] { - let mediaObserver = MediaObserver() { methodName, data in - if var `data` = data { - data["channelId"] = channelId - emit(methodName, data) + @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 + self?.emitter($0, $1) } + rtcChannel.setRtcChannelDelegate(delegate) + self?.rtcChannelMap[rtcChannel.getId()!] = rtcChannel + self?.rtcChannelDelegateMap[rtcChannel.getId()!] = delegate } - let res = rtcChannel.setMediaMetadataDelegate(mediaObserver, with: .video) - if res { - mediaObserverMap[channelId] = mediaObserver - return 0 - } + return nil } - return Int32(AgoraErrorCode.notInitialized.rawValue) } - func unregisterMediaMetadataObserver(_ channelId: String) -> Int32 { - if let rtcChannel = self[channelId] { - let res = rtcChannel.setMediaMetadataDelegate(nil, with: .video) - if res { - mediaObserverMap.removeValue(forKey: channelId) - return 0 - } - } - return Int32(AgoraErrorCode.notInitialized.rawValue) + @objc func destroy(_ params: NSDictionary, _ callback: Callback) { + callback.code(rtcChannelMap.removeValue(forKey: params["channelId"] as! String)?.destroy()) } - func setMaxMetadataSize(_ channelId: String, _ size: Int) -> Int32 { - if let observer = mediaObserverMap[channelId] { - observer.setMaxMetadataSize(size: size) - return 0 + @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 } - return Int32(AgoraErrorCode.notInitialized.rawValue) + callback.code(self[params["channelId"] as! String]?.setClientRole(role)) } - func addMetadata(_ channelId: String, _ metadata: String) -> Int32 { - if let observer = mediaObserverMap[channelId] { - observer.addMetadata(metadata: metadata) - return 0 - } - return Int32(AgoraErrorCode.notInitialized.rawValue) + @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! [String: Any]))) } -} -protocol RtcChannelAudioInterface { - associatedtype Callback + @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! [String: Any]))) + } - func adjustUserPlaybackSignalVolume(_ channelId: String, _ uid: Int, _ volume: Int, _ callback: Callback?) + @objc func leaveChannel(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.leave()) + } - func muteRemoteAudioStream(_ channelId: String, _ uid: Int, _ muted: Bool, _ callback: Callback?) + @objc func renewToken(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.renewToken(params["token"] as! String)) + } - func muteAllRemoteAudioStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) + @objc func getConnectionState(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(self[params["channelId"] as! String]) { + $0.getConnectionState().rawValue + } + } - func setDefaultMuteAllRemoteAudioStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) -} + @objc func publish(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.publish()) + } -protocol RtcChannelVideoInterface { - associatedtype Callback + @objc func unpublish(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.unpublish()) + } - func muteRemoteVideoStream(_ channelId: String, _ uid: Int, _ muted: Bool, _ callback: Callback?) + @objc func getCallId(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(self[params["channelId"] as! String]) { + $0.getCallId() + } + } - func muteAllRemoteVideoStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) + @objc func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.adjustUserPlaybackSignalVolume((params["uid"] as! NSNumber).uintValue, volume: (params["volume"] as! NSNumber).int32Value)) + } - func setDefaultMuteAllRemoteVideoStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) -} + @objc func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteRemoteAudioStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } -protocol RtcChannelVoicePositionInterface { - associatedtype Callback + @objc func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteAllRemoteAudioStreams(params["muted"] as! Bool)) + } - func setRemoteVoicePosition(_ channelId: String, _ uid: Int, _ pan: Double, _ gain: Double, _ callback: Callback?) -} + @objc func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as! Bool)) + } -protocol RtcChannelPublishStreamInterface { - associatedtype Map - associatedtype Callback + @objc func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteRemoteVideoStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } - func setLiveTranscoding(_ channelId: String, _ transcoding: Map, _ callback: Callback?) + @objc func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteAllRemoteVideoStreams(params["muted"] as! Bool)) + } - func addPublishStreamUrl(_ channelId: String, _ url: String, _ transcodingEnabled: Bool, _ callback: Callback?) + @objc func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as! Bool)) + } - func removePublishStreamUrl(_ channelId: String, _ url: String, _ callback: Callback?) -} + @objc func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteVoicePosition((params["uid"] as! NSNumber).uintValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue)) + } -protocol RtcChannelMediaRelayInterface { - associatedtype Map - associatedtype Callback + @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) + } - func startChannelMediaRelay(_ channelId: String, _ channelMediaRelayConfiguration: Map, _ callback: Callback?) + @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.addPublishStreamUrl(params["url"] as! String, transcodingEnabled: params["transcodingEnabled"] as! Bool)) + } - func updateChannelMediaRelay(_ channelId: String, _ channelMediaRelayConfiguration: Map, _ callback: Callback?) + @objc func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.removePublishStreamUrl(params["url"] as! String)) + } - func stopChannelMediaRelay(_ channelId: String, _ callback: Callback?) -} + @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) + } -protocol RtcChannelDualStreamInterface { - associatedtype Callback + @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) + } - func setRemoteVideoStreamType(_ channelId: String, _ uid: Int, _ streamType: Int, _ callback: Callback?) + @objc func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.stopMediaRelay()) + } - func setRemoteDefaultVideoStreamType(_ channelId: String, _ streamType: Int, _ callback: Callback?) -} + @objc func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteVideoStream((params["uid"] as! NSNumber).uintValue, type: AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } -protocol RtcChannelFallbackInterface { - associatedtype Callback + @objc func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteDefaultVideoStreamType(AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } - func setRemoteUserPriority(_ channelId: String, _ uid: Int, _ userPriority: Int, _ callback: Callback?) -} + @objc func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteUserPriority((params["uid"] as! NSNumber).uintValue, type: AgoraUserPriority(rawValue: (params["userPriority"] as! NSNumber).intValue)!)) + } -protocol RtcChannelMediaMetadataInterface { - associatedtype Callback + @objc func registerMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) { + let channelId = params["channelId"] as! String + let mediaObserver = MediaObserver { [weak self] in + if var data = $0 { + data["channelId"] = channelId + self?.emitter(RtcEngineEvents.MetadataReceived, data) + } + } + callback.resolve(self[channelId]) { + if $0.setMediaMetadataDelegate(mediaObserver, with: .video) { + mediaObserverMap[channelId] = mediaObserver + } + return nil + } + } - func registerMediaMetadataObserver(_ channelId: String, _ callback: Callback?) + @objc func unregisterMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) { + let channelId = params["channelId"] as! String + callback.resolve(self[channelId]) { + if $0.setMediaMetadataDelegate(nil, with: .video) { + mediaObserverMap.removeValue(forKey: channelId) + } + return nil + } + } - func unregisterMediaMetadataObserver(_ channelId: String, _ callback: Callback?) + @objc func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserverMap[params["channelId"] as! String]) { + $0.setMaxMetadataSize((params["size"] as! NSNumber).intValue) + } + } - func setMaxMetadataSize(_ channelId: String, _ size: Int, _ callback: Callback?) + @objc func sendMetadata(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserverMap[params["channelId"] as! String]) { + $0.addMetadata(params["metadata"] as! String) + } + } - func sendMetadata(_ channelId: String, _ metadata: String, _ callback: Callback?) -} + @objc func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setEncryptionSecret(params["secret"] as? String)) + } -protocol RtcChannelEncryptionInterface { - associatedtype Callback + @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { + 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)) + } - func setEncryptionSecret(_ channelId: String, _ secret: String, _ callback: Callback?) + @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]))) + } - func setEncryptionMode(_ channelId: String, _ encryptionMode: String, _ callback: Callback?) -} + @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) + } -protocol RtcChannelInjectStreamInterface { - associatedtype Map - associatedtype Callback + @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.removeInjectStreamUrl(params["url"] as! String)) + } - func addInjectStreamUrl(_ channelId: String, _ url: String, _ config: Map, _ callback: Callback?) + @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { + let channel = self[params["channelId"] as! String] + var streamId = 0 + 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 + } + } - func removeInjectStreamUrl(_ channelId: String, _ url: String, _ callback: Callback?) -} + @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)!)) + } -protocol RtcChannelStreamMessageInterface { - associatedtype Callback + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enable"] as! Bool)) + } - func createDataStream(_ channelId: String, _ reliable: Bool, _ ordered: Bool, _ callback: Callback?) + @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalAudioStream(params["muted"] as! Bool)) + } - func sendStreamMessage(_ channelId: String, _ streamId: Int, _ message: String, _ callback: Callback?) + @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 new file mode 100644 index 000000000..eca5b4da8 --- /dev/null +++ b/RtcChannelEvent.swift @@ -0,0 +1,249 @@ +// +// RtcChannelEvent.swift +// RCTAgora +// +// Created by LXH on 2020/4/10. +// Copyright © 2020 Syan. All rights reserved. +// + +import AgoraRtcKit +import Foundation + +class RtcChannelEvents { + static let Warning = "Warning" + static let Error = "Error" + static let JoinChannelSuccess = "JoinChannelSuccess" + static let RejoinChannelSuccess = "RejoinChannelSuccess" + static let LeaveChannel = "LeaveChannel" + static let ClientRoleChanged = "ClientRoleChanged" + static let UserJoined = "UserJoined" + static let UserOffline = "UserOffline" + static let ConnectionStateChanged = "ConnectionStateChanged" + static let ConnectionLost = "ConnectionLost" + static let TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" + static let RequestToken = "RequestToken" + static let ActiveSpeaker = "ActiveSpeaker" + static let VideoSizeChanged = "VideoSizeChanged" + static let RemoteVideoStateChanged = "RemoteVideoStateChanged" + static let RemoteAudioStateChanged = "RemoteAudioStateChanged" + static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" + static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" + static let RtcStats = "RtcStats" + static let NetworkQuality = "NetworkQuality" + static let RemoteVideoStats = "RemoteVideoStats" + static let RemoteAudioStats = "RemoteAudioStats" + static let RtmpStreamingStateChanged = "RtmpStreamingStateChanged" + static let TranscodingUpdated = "TranscodingUpdated" + static let StreamInjectedStatus = "StreamInjectedStatus" + static let StreamMessage = "StreamMessage" + static let StreamMessageError = "StreamMessageError" + static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" + static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" + static let MetadataReceived = "MetadataReceived" + 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, + "JoinChannelSuccess": JoinChannelSuccess, + "RejoinChannelSuccess": RejoinChannelSuccess, + "LeaveChannel": LeaveChannel, + "ClientRoleChanged": ClientRoleChanged, + "UserJoined": UserJoined, + "UserOffline": UserOffline, + "ConnectionStateChanged": ConnectionStateChanged, + "ConnectionLost": ConnectionLost, + "TokenPrivilegeWillExpire": TokenPrivilegeWillExpire, + "RequestToken": RequestToken, + "ActiveSpeaker": ActiveSpeaker, + "VideoSizeChanged": VideoSizeChanged, + "RemoteVideoStateChanged": RemoteVideoStateChanged, + "RemoteAudioStateChanged": RemoteAudioStateChanged, + "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, + "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, + "RtcStats": RtcStats, + "NetworkQuality": NetworkQuality, + "RemoteVideoStats": RemoteVideoStats, + "RemoteAudioStats": RemoteAudioStats, + "RtmpStreamingStateChanged": RtmpStreamingStateChanged, + "TranscodingUpdated": TranscodingUpdated, + "StreamInjectedStatus": StreamInjectedStatus, + "StreamMessage": StreamMessage, + "StreamMessageError": StreamMessageError, + "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, + "ChannelMediaRelayEvent": ChannelMediaRelayEvent, + "MetadataReceived": MetadataReceived, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, + ] + } +} + +class RtcChannelEventHandler: NSObject { + static let PREFIX = "io.agora.rtc." + + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> 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, + ]) + } +} + +extension RtcChannelEventHandler: AgoraRtcChannelDelegate { + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurWarning warningCode: AgoraWarningCode) { + callback(RtcChannelEvents.Warning, rtcChannel, warningCode.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurError errorCode: AgoraErrorCode) { + callback(RtcChannelEvents.Error, rtcChannel, errorCode.rawValue) + } + + public func rtcChannelDidJoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { + callback(RtcChannelEvents.JoinChannelSuccess, rtcChannel, rtcChannel.getId(), uid, elapsed) + } + + public func rtcChannelDidRejoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { + callback(RtcChannelEvents.RejoinChannelSuccess, rtcChannel, rtcChannel.getId(), uid, elapsed) + } + + public func rtcChannelDidLeave(_ rtcChannel: AgoraRtcChannel, with stats: AgoraChannelStats) { + callback(RtcChannelEvents.LeaveChannel, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + callback(RtcChannelEvents.ClientRoleChanged, rtcChannel, oldRole.rawValue, newRole.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didJoinedOfUid uid: UInt, elapsed: Int) { + callback(RtcChannelEvents.UserJoined, rtcChannel, uid, elapsed) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + callback(RtcChannelEvents.UserOffline, rtcChannel, uid, reason.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + callback(RtcChannelEvents.ConnectionStateChanged, rtcChannel, state.rawValue, reason.rawValue) + } + + public func rtcChannelDidLost(_ rtcChannel: AgoraRtcChannel) { + callback(RtcChannelEvents.ConnectionLost, rtcChannel) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, tokenPrivilegeWillExpire token: String) { + callback(RtcChannelEvents.TokenPrivilegeWillExpire, rtcChannel, token) + } + + public func rtcChannelRequestToken(_ rtcChannel: AgoraRtcChannel) { + callback(RtcChannelEvents.RequestToken, rtcChannel) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, activeSpeaker speakerUid: UInt) { + callback(RtcChannelEvents.ActiveSpeaker, rtcChannel, speakerUid) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { + callback(RtcChannelEvents.VideoSizeChanged, rtcChannel, uid, Int(size.width), Int(size.height), rotation) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + callback(RtcChannelEvents.RemoteVideoStateChanged, rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { + callback(RtcChannelEvents.RemoteAudioStateChanged, rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { + callback(RtcChannelEvents.LocalPublishFallbackToAudioOnly, rtcChannel, isFallbackOrRecover) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + callback(RtcChannelEvents.RemoteSubscribeFallbackToAudioOnly, rtcChannel, uid, isFallbackOrRecover) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, reportRtcStats stats: AgoraChannelStats) { + callback(RtcChannelEvents.RtcStats, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + callback(RtcChannelEvents.NetworkQuality, rtcChannel, uid, txQuality.rawValue, rxQuality.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + callback(RtcChannelEvents.RemoteVideoStats, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + callback(RtcChannelEvents.RemoteAudioStats, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + callback(RtcChannelEvents.RtmpStreamingStateChanged, rtcChannel, url, state.rawValue, errorCode.rawValue) + } + + public func rtcChannelTranscodingUpdated(_ rtcChannel: AgoraRtcChannel) { + callback(RtcChannelEvents.TranscodingUpdated, rtcChannel) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + callback(RtcChannelEvents.StreamInjectedStatus, rtcChannel, url, uid, status.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + callback(RtcChannelEvents.StreamMessage, rtcChannel, uid, streamId, String(data: data, encoding: .utf8)) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { + callback(RtcChannelEvents.StreamMessageError, rtcChannel, uid, streamId, error, missed, cached) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + callback(RtcChannelEvents.ChannelMediaRelayStateChanged, rtcChannel, state.rawValue, error.rawValue) + } + + 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/RtcChannelEventHandler.swift b/RtcChannelEventHandler.swift deleted file mode 100644 index b906cf38d..000000000 --- a/RtcChannelEventHandler.swift +++ /dev/null @@ -1,177 +0,0 @@ -// -// RtcChannelEventHandler.swift -// RCTAgora -// -// Created by LXH on 2020/4/10. -// Copyright © 2020 Syan. All rights reserved. -// - -import Foundation -import AgoraRtcKit - -class RtcChannelEventHandler: NSObject { - static let PREFIX = "io.agora.rtc." - static let EVENTS = [ - "Warning": "Warning", - "Error": "Error", - "JoinChannelSuccess": "JoinChannelSuccess", - "RejoinChannelSuccess": "RejoinChannelSuccess", - "LeaveChannel": "LeaveChannel", - "ClientRoleChanged": "ClientRoleChanged", - "UserJoined": "UserJoined", - "UserOffline": "UserOffline", - "ConnectionStateChanged": "ConnectionStateChanged", - "ConnectionLost": "ConnectionLost", - "TokenPrivilegeWillExpire": "TokenPrivilegeWillExpire", - "RequestToken": "RequestToken", - "ActiveSpeaker": "ActiveSpeaker", - "VideoSizeChanged": "VideoSizeChanged", - "RemoteVideoStateChanged": "RemoteVideoStateChanged", - "RemoteAudioStateChanged": "RemoteAudioStateChanged", - "LocalPublishFallbackToAudioOnly": "LocalPublishFallbackToAudioOnly", - "RemoteSubscribeFallbackToAudioOnly": "RemoteSubscribeFallbackToAudioOnly", - "RtcStats": "RtcStats", - "NetworkQuality": "NetworkQuality", - "RemoteVideoStats": "RemoteVideoStats", - "RemoteAudioStats": "RemoteAudioStats", - "RtmpStreamingStateChanged": "RtmpStreamingStateChanged", - "TranscodingUpdated": "TranscodingUpdated", - "StreamInjectedStatus": "StreamInjectedStatus", - "StreamMessage": "StreamMessage", - "StreamMessageError": "StreamMessageError", - "ChannelMediaRelayStateChanged": "ChannelMediaRelayStateChanged", - "ChannelMediaRelayEvent": "ChannelMediaRelayEvent", - "MetadataReceived": "MetadataReceived", - ] - - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void - - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - self.emitter = emitter - } - - private func callback(_ methodName: String, _ channel: AgoraRtcChannel, _ data: Any?...) { - emitter(methodName, [ - "channelId": channel.getId(), - "data": data - ]) - } -} - -extension RtcChannelEventHandler: AgoraRtcChannelDelegate { - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurWarning warningCode: AgoraWarningCode) { - callback("Warning", rtcChannel, warningCode.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurError errorCode: AgoraErrorCode) { - callback("Error", rtcChannel, errorCode.rawValue) - } - - public func rtcChannelDidJoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { - callback("JoinChannelSuccess", rtcChannel, uid, elapsed) - } - - public func rtcChannelDidRejoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { - callback("RejoinChannelSuccess", rtcChannel, uid, elapsed) - } - - public func rtcChannelDidLeave(_ rtcChannel: AgoraRtcChannel, with stats: AgoraChannelStats) { - callback("LeaveChannel", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { - callback("ClientRoleChanged", rtcChannel, oldRole.rawValue, newRole.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didJoinedOfUid uid: UInt, elapsed: Int) { - callback("UserJoined", rtcChannel, uid, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { - callback("UserOffline", rtcChannel, uid, reason.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { - callback("ConnectionStateChanged", rtcChannel, state.rawValue, reason.rawValue) - } - - public func rtcChannelDidLost(_ rtcChannel: AgoraRtcChannel) { - callback("ConnectionLost", rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, tokenPrivilegeWillExpire token: String) { - callback("TokenPrivilegeWillExpire", rtcChannel, token) - } - - public func rtcChannelRequestToken(_ rtcChannel: AgoraRtcChannel) { - callback("RequestToken", rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, activeSpeaker speakerUid: UInt) { - callback("ActiveSpeaker", rtcChannel, speakerUid) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { - callback("VideoSizeChanged", rtcChannel, uid, size.width, size.height, rotation) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { - callback("RemoteVideoStateChanged", rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { - callback("RemoteAudioStateChanged", rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { - callback("LocalPublishFallbackToAudioOnly", rtcChannel, isFallbackOrRecover) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { - callback("RemoteSubscribeFallbackToAudioOnly", rtcChannel, uid, isFallbackOrRecover) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, reportRtcStats stats: AgoraChannelStats) { - callback("RtcStats", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { - callback("NetworkQuality", rtcChannel, uid, txQuality, rxQuality) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { - callback("RemoteVideoStats", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { - callback("RemoteAudioStats", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { - callback("RtmpStreamingStateChanged", rtcChannel, url, state.rawValue, errorCode.rawValue) - } - - public func rtcChannelTranscodingUpdated(_ rtcChannel: AgoraRtcChannel) { - callback("TranscodingUpdated", rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { - callback("StreamInjectedStatus", rtcChannel, url, uid, status.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { - callback("StreamMessage", rtcChannel, uid, streamId, String(data: data, encoding: .utf8)) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { - callback("StreamMessageError", rtcChannel, uid, streamId, error, missed, cached) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { - callback("ChannelMediaRelayStateChanged", rtcChannel, state.rawValue, error.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didReceive event: AgoraChannelMediaRelayEvent) { - callback("ChannelMediaRelayEvent", rtcChannel, event.rawValue) - } -} diff --git a/RtcEngine.swift b/RtcEngine.swift index c8d5d4b34..514ec50b9 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, @@ -31,456 +31,1203 @@ protocol RtcEngineInterface: RtcEngineInjectStreamInterface, RtcEngineCameraInterface, RtcEngineStreamMessageInterface { - associatedtype Map - associatedtype Callback + func create(_ params: NSDictionary, _ callback: Callback) - func create(_ appId: String, _ callback: Callback?) + func destroy(_ callback: Callback) - func destroy(_ callback: Callback?) + func setChannelProfile(_ params: NSDictionary, _ callback: Callback) - func setChannelProfile(_ profile: Int, _ callback: Callback?) + func setClientRole(_ params: NSDictionary, _ callback: Callback) - func setClientRole(_ role: Int, _ callback: Callback?) + func joinChannel(_ params: NSDictionary, _ callback: Callback) - func joinChannel(_ token: String?, _ channelName: String, _ optionalInfo: String?, _ optionalUid: Int, _ callback: Callback?) + func switchChannel(_ params: NSDictionary, _ callback: Callback) - func switchChannel(_ token: String?, _ channelName: String, _ callback: Callback?) + func leaveChannel(_ callback: Callback) - func leaveChannel(_ callback: Callback?) - - func renewToken(_ token: String, _ callback: Callback?) + func renewToken(_ params: NSDictionary, _ callback: Callback) @available(*, deprecated) - func enableWebSdkInteroperability(_ enabled: Bool, _ callback: Callback?) + func enableWebSdkInteroperability(_ params: NSDictionary, _ callback: Callback) - func getConnectionState(_ callback: Callback?) + func getConnectionState(_ callback: Callback) - func getCallId(_ callback: Callback?) + func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) - func rate(_ callId: String, _ rating: Int, _ description: String?, _ callback: Callback?) + func getCallId(_ callback: Callback) - func complain(_ callId: String, _ description: String, _ callback: Callback?) + func rate(_ params: NSDictionary, _ callback: Callback) - func setLogFile(_ filePath: String, _ callback: Callback?) + func complain(_ params: NSDictionary, _ callback: Callback) - func setLogFilter(_ filter: Int, _ callback: Callback?) + @available(*, deprecated) + func setLogFile(_ params: NSDictionary, _ callback: Callback) - func setLogFileSize(_ fileSizeInKBytes: Int, _ callback: Callback?) + @available(*, deprecated) + func setLogFilter(_ params: NSDictionary, _ callback: Callback) - func setParameters(_ parameters: String, _ callback: Callback?) -} + @available(*, deprecated) + func setLogFileSize(_ params: NSDictionary, _ callback: Callback) -class RtcEngineManager { - private var _engine: AgoraRtcEngineKit? - private var delegate: RtcEngineEventHandler? - private var mediaObserver: MediaObserver? + func setParameters(_ params: NSDictionary, _ callback: Callback) - func create(_ appId: String, _ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - delegate = RtcEngineEventHandler() { methodName, data in - emit(methodName, data) - } - _engine = AgoraRtcEngineKit.sharedEngine(withAppId: appId, delegate: delegate) - _engine?.setAppType(.APP_TYPE_REACTNATIVE) - } + func getSdkVersion(_ callback: Callback) - func destroy() { - AgoraRtcEngineKit.destroy() - _engine = nil - delegate = nil - } + func getErrorDescription(_ params: NSDictionary, _ callback: Callback) - func release() { - destroy() - mediaObserver = nil - } + func getNativeHandle(_ callback: Callback) - var engine: AgoraRtcEngineKit? { - return _engine - } + func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUserAccount(_ userAccount: String) -> Dictionary? { - if let engine = _engine { - let userInfo = engine.getUserInfo(byUserAccount: userAccount, withError: nil) - return userInfo?.toMap() - } - return nil - } + func setCloudProxy(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUid(_ uid: Int) -> Dictionary? { - if let engine = _engine { - let userInfo = engine.getUserInfo(byUid: UInt(uid), withError: nil) - return userInfo?.toMap() - } - return nil - } - - func registerMediaMetadataObserver(_ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) -> Int32 { - if let engine = _engine { - let mediaObserver = MediaObserver() { methodName, data in - emit(methodName, data) - } - let res = engine.setMediaMetadataDelegate(mediaObserver, with: .video) - if res { - self.mediaObserver = mediaObserver - return 0 - } else { - return Int32(AgoraErrorCode.noPermission.rawValue) - } - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } + func uploadLogFile(_ callback: Callback) - func unregisterMediaMetadataObserver() -> Int32 { - if let engine = _engine { - let res = engine.setMediaMetadataDelegate(nil, with: .video) - if res { - mediaObserver = nil - return 0 - } else { - return Int32(AgoraErrorCode.noPermission.rawValue) - } - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } + func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) - func setMaxMetadataSize(_ size: Int) -> Int32 { - if let observer = mediaObserver { - observer.setMaxMetadataSize(size: size) - return 0 - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } - - func addMetadata(_ metadata: String) -> Int32 { - if let observer = mediaObserver { - observer.addMetadata(metadata: metadata) - return 0 - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } - - func createDataStream(_ reliable: Bool, _ ordered: Bool) -> Int32 { - if let engine = _engine { - var streamId = 0 - let res = engine.createDataStream(&streamId, reliable: reliable, ordered: ordered) - if res == 0 { - return Int32(streamId) - } - return res - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } - - func sendStreamMessage(_ streamId: Int, _ message: String) -> Int32 { - if let engine = _engine { - if let data = message.data(using: .utf8) { - return engine.sendStreamMessage(streamId, data: data) - } - return Int32(AgoraErrorCode.invalidArgument.rawValue) - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } + func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) + + func takeSnapshot(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineUserInfoInterface { - associatedtype Callback - - func registerLocalUserAccount(_ appId: String, _ userAccount: String, _ callback: Callback?) + func registerLocalUserAccount(_ params: NSDictionary, _ callback: Callback) - func joinChannelWithUserAccount(_ token: String?, _ channelName: String, _ userAccount: String, _ callback: Callback?) + func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUserAccount(_ userAccount: String, _ callback: Callback?) + func getUserInfoByUserAccount(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUid(_ uid: Int, _ callback: Callback?) + func getUserInfoByUid(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioInterface { - associatedtype Callback + func enableAudio(_ callback: Callback) - func enableAudio(_ callback: Callback?) + func disableAudio(_ callback: Callback) - func disableAudio(_ callback: Callback?) + func setAudioProfile(_ params: NSDictionary, _ callback: Callback) - func setAudioProfile(_ profile: Int, _ scenario: Int, _ callback: Callback?) + func adjustRecordingSignalVolume(_ params: NSDictionary, _ callback: Callback) - func adjustRecordingSignalVolume(_ volume: Int, _ callback: Callback?) + func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - func adjustUserPlaybackSignalVolume(_ uid: Int, _ volume: Int, _ callback: Callback?) + func adjustPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - func adjustPlaybackSignalVolume(_ volume: Int, _ callback: Callback?) + func enableLocalAudio(_ params: NSDictionary, _ callback: Callback) - func enableLocalAudio(_ enabled: Bool, _ callback: Callback?) + func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) - func muteLocalAudioStream(_ muted: Bool, _ callback: Callback?) + func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) - func muteRemoteAudioStream(_ uid: Int, _ muted: Bool, _ callback: Callback?) + func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) - func muteAllRemoteAudioStreams(_ muted: Bool, _ callback: Callback?) + @available(*, deprecated) + func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + + func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) - func setDefaultMuteAllRemoteAudioStreams(_ muted: Bool, _ callback: Callback?) + func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) - func enableAudioVolumeIndication(_ interval: Int, _ smooth: Int, _ report_vad: Bool, _ callback: Callback?) + func stopRhythmPlayer(_ callback: Callback) + + func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVideoInterface { - associatedtype Map - associatedtype Callback + func enableVideo(_ callback: Callback) - func enableVideo(_ callback: Callback?) + func disableVideo(_ callback: Callback) - func disableVideo(_ callback: Callback?) + func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) - func setVideoEncoderConfiguration(_ config: Map, _ callback: Callback?) + func startPreview(_ callback: Callback) - func enableLocalVideo(_ enabled: Bool, _ callback: Callback?) + func stopPreview(_ callback: Callback) - func muteLocalVideoStream(_ muted: Bool, _ callback: Callback?) + func enableLocalVideo(_ params: NSDictionary, _ callback: Callback) - func muteRemoteVideoStream(_ uid: Int, _ muted: Bool, _ callback: Callback?) + func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) - func muteAllRemoteVideoStreams(_ muted: Bool, _ callback: Callback?) + func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) - func setDefaultMuteAllRemoteVideoStreams(_ muted: Bool, _ callback: Callback?) + func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - func setBeautyEffectOptions(_ enabled: Bool, _ options: Map, _ callback: Callback?) + @available(*, deprecated) + func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + + func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioMixingInterface { - associatedtype Callback + func startAudioMixing(_ params: NSDictionary, _ callback: Callback) + + func stopAudioMixing(_ callback: Callback) - func startAudioMixing(_ filePath: String, _ loopback: Bool, _ replace: Bool, _ cycle: Int, _ callback: Callback?) + func pauseAudioMixing(_ callback: Callback) - func stopAudioMixing(_ callback: Callback?) + func resumeAudioMixing(_ callback: Callback) - func pauseAudioMixing(_ callback: Callback?) + func adjustAudioMixingVolume(_ params: NSDictionary, _ callback: Callback) - func resumeAudioMixing(_ callback: Callback?) + func adjustAudioMixingPlayoutVolume(_ params: NSDictionary, _ callback: Callback) - func adjustAudioMixingVolume(_ volume: Int, _ callback: Callback?) + func adjustAudioMixingPublishVolume(_ params: NSDictionary, _ callback: Callback) - func adjustAudioMixingPlayoutVolume(_ volume: Int, _ callback: Callback?) + func getAudioMixingPlayoutVolume(_ callback: Callback) - func adjustAudioMixingPublishVolume(_ volume: Int, _ callback: Callback?) + func getAudioMixingPublishVolume(_ callback: Callback) - func getAudioMixingPlayoutVolume(_ callback: Callback?) + func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) + + func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) - func getAudioMixingPublishVolume(_ callback: Callback?) + func getAudioMixingCurrentPosition(_ callback: Callback) - func getAudioMixingDuration(_ callback: Callback?) + func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) - func getAudioMixingCurrentPosition(_ callback: Callback?) + func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) - func setAudioMixingPosition(_ pos: Int, _ 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 { - associatedtype Callback + func getEffectsVolume(_ callback: Callback) + + func setEffectsVolume(_ params: NSDictionary, _ callback: Callback) - func getEffectsVolume(_ callback: Callback?) + func setVolumeOfEffect(_ params: NSDictionary, _ callback: Callback) - func setEffectsVolume(_ volume: Double, _ callback: Callback?) + func playEffect(_ params: NSDictionary, _ callback: Callback) - func setVolumeOfEffect(_ soundId: Int, _ volume: Double, _ callback: Callback?) + func setEffectPosition(_ params: NSDictionary, _ callback: Callback) - func playEffect(_ soundId: Int, _ filePath: String, _ loopCount: Int, _ pitch: Double, _ pan: Double, _ gain: Double, _ publish: Bool, _ callback: Callback?) + func getEffectDuration(_ params: NSDictionary, _ callback: Callback) - func stopEffect(_ soundId: Int, _ callback: Callback?) + func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) - func stopAllEffects(_ callback: Callback?) + func stopEffect(_ params: NSDictionary, _ callback: Callback) - func preloadEffect(_ soundId: Int, _ filePath: String, _ callback: Callback?) + func stopAllEffects(_ callback: Callback) - func unloadEffect(_ soundId: Int, _ callback: Callback?) + func preloadEffect(_ params: NSDictionary, _ callback: Callback) - func pauseEffect(_ soundId: Int, _ callback: Callback?) + func unloadEffect(_ params: NSDictionary, _ callback: Callback) - func pauseAllEffects(_ callback: Callback?) + func pauseEffect(_ params: NSDictionary, _ callback: Callback) - func resumeEffect(_ soundId: Int, _ callback: Callback?) + func pauseAllEffects(_ callback: Callback) - func resumeAllEffects(_ callback: Callback?) + func resumeEffect(_ params: NSDictionary, _ callback: Callback) + + func resumeAllEffects(_ callback: Callback) + + func setAudioSessionOperationRestriction(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVoiceChangerInterface { - associatedtype Callback + @available(*, deprecated) + func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceChanger(_ voiceChanger: Int, _ callback: Callback?) + @available(*, deprecated) + func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) + + func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) + + func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) + + func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceReverbPreset(_ preset: Int, _ callback: Callback?) + func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) - func setLocalVoicePitch(_ pitch: Double, _ callback: Callback?) + func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceEqualization(_ bandFrequency: Int, _ bandGain: Int, _ callback: Callback?) + func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceReverb(_ reverbKey: Int, _ value: Int, _ callback: Callback?) + func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) + + func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVoicePositionInterface { - associatedtype Callback - - func enableSoundPositionIndication(_ enabled: Bool, _ callback: Callback?) + func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) - func setRemoteVoicePosition(_ uid: Int, _ pan: Double, _ gain: Double, _ callback: Callback?) + func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) } protocol RtcEnginePublishStreamInterface { - associatedtype Map - associatedtype Callback + func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) - func setLiveTranscoding(_ transcoding: Map, _ callback: Callback?) + func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) - func addPublishStreamUrl(_ url: String, _ transcodingEnabled: Bool, _ callback: Callback?) - - func removePublishStreamUrl(_ url: String, _ callback: Callback?) + func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineMediaRelayInterface { - associatedtype Map - associatedtype Callback + func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + + func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func startChannelMediaRelay(_ channelMediaRelayConfiguration: Map, _ callback: Callback?) + func pauseAllChannelMediaRelay(_ callback: Callback) - func updateChannelMediaRelay(_ channelMediaRelayConfiguration: Map, _ callback: Callback?) + func resumeAllChannelMediaRelay(_ callback: Callback) - func stopChannelMediaRelay(_ callback: Callback?) + func stopChannelMediaRelay(_ callback: Callback) } protocol RtcEngineAudioRouteInterface { - associatedtype Callback + func setDefaultAudioRoutetoSpeakerphone(_ params: NSDictionary, _ callback: Callback) - func setDefaultAudioRoutetoSpeakerphone(_ defaultToSpeaker: Bool, _ callback: Callback?) + func setEnableSpeakerphone(_ params: NSDictionary, _ callback: Callback) - func setEnableSpeakerphone(_ enabled: Bool, _ callback: Callback?) - - func isSpeakerphoneEnabled(_ callback: Callback?) + func isSpeakerphoneEnabled(_ callback: Callback) } protocol RtcEngineEarMonitoringInterface { - associatedtype Callback - - func enableInEarMonitoring(_ enabled: Bool, _ callback: Callback?) + func enableInEarMonitoring(_ params: NSDictionary, _ callback: Callback) - func setInEarMonitoringVolume(_ volume: Int, _ callback: Callback?) + func setInEarMonitoringVolume(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineDualStreamInterface { - associatedtype Callback + func enableDualStreamMode(_ params: NSDictionary, _ callback: Callback) - func enableDualStreamMode(_ enabled: Bool, _ callback: Callback?) + func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) - func setRemoteVideoStreamType(_ uid: Int, _ streamType: Int, _ callback: Callback?) - - func setRemoteDefaultVideoStreamType(_ streamType: Int, _ callback: Callback?) + func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineFallbackInterface { - associatedtype Callback - - func setLocalPublishFallbackOption(_ option: Int, _ callback: Callback?) + func setLocalPublishFallbackOption(_ params: NSDictionary, _ callback: Callback) - func setRemoteSubscribeFallbackOption(_ option: Int, _ callback: Callback?) + func setRemoteSubscribeFallbackOption(_ params: NSDictionary, _ callback: Callback) - func setRemoteUserPriority(_ uid: Int, _ userPriority: Int, _ callback: Callback?) + func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineTestInterface { - associatedtype Map - associatedtype Callback + func startEchoTest(_ params: NSDictionary, _ callback: Callback) - func startEchoTest(_ intervalInSeconds: Int, _ callback: Callback?) + func stopEchoTest(_ callback: Callback) - func stopEchoTest(_ callback: Callback?) + func enableLastmileTest(_ callback: Callback) - func enableLastmileTest(_ callback: Callback?) + func disableLastmileTest(_ callback: Callback) - func disableLastmileTest(_ callback: Callback?) + func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) - func startLastmileProbeTest(_ config: Map, _ callback: Callback?) - - func stopLastmileProbeTest(_ callback: Callback?) + func stopLastmileProbeTest(_ callback: Callback) } protocol RtcEngineMediaMetadataInterface { - associatedtype Callback - - func registerMediaMetadataObserver(_ callback: Callback?) + func registerMediaMetadataObserver(_ callback: Callback) - func unregisterMediaMetadataObserver(_ callback: Callback?) + func unregisterMediaMetadataObserver(_ callback: Callback) - func setMaxMetadataSize(_ size: Int, _ callback: Callback?) + func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) - func sendMetadata(_ metadata: String, _ callback: Callback?) + func sendMetadata(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineWatermarkInterface { - associatedtype Map - associatedtype Callback - - func addVideoWatermark(_ watermarkUrl: String, _ options: Map, _ callback: Callback?) + func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) - func clearVideoWatermarks(_ callback: Callback?) + func clearVideoWatermarks(_ callback: Callback) } protocol RtcEngineEncryptionInterface { - associatedtype Callback + @available(*, deprecated) + func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) - func setEncryptionSecret(_ secret: String, _ callback: Callback?) + @available(*, deprecated) + func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) - func setEncryptionMode(_ encryptionMode: String, _ callback: Callback?) + func enableEncryption(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioRecorderInterface { - associatedtype Callback + func startAudioRecording(_ params: NSDictionary, _ callback: Callback) - func startAudioRecording(_ filePath: String, _ sampleRate: Int, _ quality: Int, _ callback: Callback?) - - func stopAudioRecording(_ callback: Callback?) + func stopAudioRecording(_ callback: Callback) } protocol RtcEngineInjectStreamInterface { - associatedtype Map - associatedtype Callback - - func addInjectStreamUrl(_ url: String, _ config: Map, _ callback: Callback?) + func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) - func removeInjectStreamUrl(_ url: String, _ callback: Callback?) + func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineCameraInterface { - associatedtype Map - associatedtype Callback + func switchCamera(_ callback: Callback) - func switchCamera(_ callback: Callback?) + func isCameraZoomSupported(_ callback: Callback) - func isCameraZoomSupported(_ callback: Callback?) + func isCameraTorchSupported(_ callback: Callback) - func isCameraTorchSupported(_ callback: Callback?) + func isCameraFocusSupported(_ callback: Callback) - func isCameraFocusSupported(_ callback: Callback?) + func isCameraExposurePositionSupported(_ callback: Callback) - func isCameraExposurePositionSupported(_ callback: Callback?) + func isCameraAutoFocusFaceModeSupported(_ callback: Callback) - func isCameraAutoFocusFaceModeSupported(_ callback: Callback?) + func setCameraZoomFactor(_ params: NSDictionary, _ callback: Callback) - func setCameraZoomFactor(_ factor: Float, _ callback: Callback?) + func getCameraMaxZoomFactor(_ callback: Callback) - func getCameraMaxZoomFactor(_ callback: Callback?) + func setCameraFocusPositionInPreview(_ params: NSDictionary, _ callback: Callback) - func setCameraFocusPositionInPreview(_ positionX: Float, _ positionY: Float, _ callback: Callback?) + func setCameraExposurePosition(_ params: NSDictionary, _ callback: Callback) - func setCameraExposurePosition(_ positionXinView: Float, _ positionYinView: Float, _ callback: Callback?) + func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) - func setCameraTorchOn(_ isOn: Bool, _ callback: Callback?) + func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) - func setCameraAutoFocusFaceModeEnabled(_ enabled: Bool, _ callback: Callback?) + func setCameraAutoFocusFaceModeEnabled(_ params: NSDictionary, _ callback: Callback) - func setCameraCapturerConfiguration(_ config: Map, _ callback: Callback?) + func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineStreamMessageInterface { - associatedtype Callback + func createDataStream(_ params: NSDictionary, _ callback: Callback) + + 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: [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: [String: Any?]?) -> Void, + _ agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory = AgoraRtcEngineKitFactory()) { + self.emitter = emitter + self.agoraRtcEngineKitFactory = agoraRtcEngineKitFactory + } + + func Release() { + if (engine != nil) { + AgoraRtcEngineKit.destroy() + engine = nil + } + delegate = nil + mediaObserver = nil + } + + @objc func create(_ params: NSDictionary, _ callback: Callback) { + delegate = RtcEngineEventHandler { [weak self] in + self?.emitter($0, $1) + } + 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 + } + } + + @objc func setChannelProfile(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setChannelProfile(AgoraChannelProfile(rawValue: (params["profile"] as! NSNumber).intValue)!)) + } + + @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)) + } + + @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { + let token = params["token"] as? String + 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)) + } + + @objc func leaveChannel(_ callback: Callback) { + callback.code(engine?.leaveChannel()) + } + + @objc func renewToken(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.renewToken(params["token"] as! String)) + } + + @objc func enableWebSdkInteroperability(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableWebSdkInteroperability(params["enabled"] as! Bool)) + } + + @objc func getConnectionState(_ callback: Callback) { + callback.resolve(engine) { + $0.getConnectionState().rawValue + } + } + + @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() + } + } + + @objc func rate(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.rate(params["callId"] as! String, rating: (params["rating"] as! NSNumber).intValue, description: params["description"] as? String)) + } + + @objc func complain(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.complain(params["callId"] as! String, description: params["description"] as? String)) + } + + @objc func setLogFile(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLogFile(params["filePath"] as! String)) + } + + @objc func setLogFilter(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLogFilter((params["filter"] as! NSNumber).uintValue)) + } + + @objc func setLogFileSize(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLogFileSize((params["fileSizeInKBytes"] as! NSNumber).uintValue)) + } + + @objc func getNativeHandle(_ callback: Callback) { + callback.resolve(engine) { + Int(bitPattern: $0.getNativeHandle()) + } + } + + @objc func setParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setParameters(params["parameters"] as! String)) + } + + @objc func registerLocalUserAccount(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.registerLocalUserAccount(params["userAccount"] as! String, appId: params["appId"] as! String)) + } + + @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { + 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)) + } + + @objc func getUserInfoByUserAccount(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.getUserInfo(byUserAccount: params["userAccount"] as! String, withError: nil)?.toMap() + } + } + + @objc func getUserInfoByUid(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.getUserInfo(byUid: (params["uid"] as! NSNumber).uintValue, withError: nil)?.toMap() + } + } + + @objc func enableAudio(_ callback: Callback) { + callback.code(engine?.enableAudio()) + } + + @objc func disableAudio(_ callback: Callback) { + callback.code(engine?.disableAudio()) + } + + @objc func setAudioProfile(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioProfile(AgoraAudioProfile(rawValue: (params["profile"] as! NSNumber).intValue)!, scenario: AgoraAudioScenario(rawValue: (params["scenario"] as! NSNumber).intValue)!)) + } + + @objc func adjustRecordingSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustRecordingSignalVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustUserPlaybackSignalVolume((params["uid"] as! NSNumber).uintValue, volume: (params["volume"] as! NSNumber).int32Value)) + } + + @objc func adjustPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustPlaybackSignalVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func enableLocalAudio(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableLocalAudio(params["enabled"] as! Bool)) + } + + @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteLocalAudioStream(params["muted"] as! Bool)) + } + + @objc func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteRemoteAudioStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } + + @objc func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteAllRemoteAudioStreams(params["muted"] as! Bool)) + } + + @objc func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as! Bool)) + } + + @objc func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) { + 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()) + } + + @objc func disableVideo(_ callback: Callback) { + callback.code(engine?.disableVideo()) + } + + @objc func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! [String: Any]))) + } + + @objc func startPreview(_ callback: Callback) { + callback.code(engine?.startPreview()) + } + + @objc func stopPreview(_ callback: Callback) { + callback.code(engine?.stopPreview()) + } + + @objc func enableLocalVideo(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableLocalVideo(params["enabled"] as! Bool)) + } + + @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteLocalVideoStream(params["muted"] as! Bool)) + } + + @objc func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteRemoteVideoStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } + + @objc func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteAllRemoteVideoStreams(params["muted"] as! Bool)) + } + + @objc func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as! Bool)) + } + + @objc func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) { + 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)) + } + + @objc func stopAudioMixing(_ callback: Callback) { + callback.code(engine?.stopAudioMixing()) + } + + @objc func pauseAudioMixing(_ callback: Callback) { + callback.code(engine?.pauseAudioMixing()) + } + + @objc func resumeAudioMixing(_ callback: Callback) { + callback.code(engine?.resumeAudioMixing()) + } + + @objc func adjustAudioMixingVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustAudioMixingVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func adjustAudioMixingPlayoutVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustAudioMixingPlayoutVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func adjustAudioMixingPublishVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustAudioMixingPublishVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func getAudioMixingPlayoutVolume(_ callback: Callback) { + callback.code(engine?.getAudioMixingPlayoutVolume()) { + $0 + } + } + + @objc func getAudioMixingPublishVolume(_ callback: Callback) { + callback.code(engine?.getAudioMixingPublishVolume()) { + $0 + } + } + + @objc func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getAudioMixingDuration()) { + $0 + } + } + + @objc func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) { + if let filePath = (params["filePath"] as? String) { + callback.code(engine?.getAudioFileInfo(filePath)) { + $0 + } + return + } + } + + @objc func getAudioMixingCurrentPosition(_ callback: Callback) { + callback.code(engine?.getAudioMixingCurrentPosition()) { + $0 + } + } + + @objc func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioMixingPosition((params["pos"] as! NSNumber).intValue)) + } + + @objc func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) { + 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["audioIndex"] 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() + } + } + + @objc func setEffectsVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEffectsVolume((params["volume"] as! NSNumber).doubleValue)) + } + + @objc func setVolumeOfEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVolumeOfEffect((params["soundId"] as! NSNumber).int32Value, withVolume: (params["volume"] as! NSNumber).doubleValue)) + } + + @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)) + } + + @objc func stopAllEffects(_ callback: Callback) { + callback.code(engine?.stopAllEffects()) + } + + @objc func preloadEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.preloadEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String)) + } + + @objc func unloadEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.unloadEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func pauseEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.pauseEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func pauseAllEffects(_ callback: Callback) { + callback.code(engine?.pauseAllEffects()) + } + + @objc func resumeEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.resumeEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func resumeAllEffects(_ callback: Callback) { + callback.code(engine?.resumeAllEffects()) + } + + @objc func setAudioSessionOperationRestriction(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setAudioSessionOperationRestriction(AgoraAudioSessionOperationRestriction(rawValue: (params["restriction"] as! NSNumber).uintValue)) + } + } + + @objc func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceChanger(AgoraAudioVoiceChanger(rawValue: (params["voiceChanger"] as! NSNumber).intValue)!)) + } + + @objc func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceReverbPreset(AgoraAudioReverbPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoicePitch((params["pitch"] as! NSNumber).doubleValue)) + } + + @objc func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceEqualizationOf(AgoraAudioEqualizationBandFrequency(rawValue: (params["bandFrequency"] as! NSNumber).intValue)!, withGain: (params["bandGain"] as! NSNumber).intValue)) + } + + @objc func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) { + 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)) + } + + @objc func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteVoicePosition((params["uid"] as! NSNumber).uintValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue)) + } + + @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) + } + + @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.addPublishStreamUrl(params["url"] as! String, transcodingEnabled: params["transcodingEnabled"] as! Bool)) + } + + @objc func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.removePublishStreamUrl(params["url"] as! String)) + } + + @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + 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! [String: Any]))) + } + + @objc func stopChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.stopChannelMediaRelay()) + } + + @objc func setDefaultAudioRoutetoSpeakerphone(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setDefaultAudioRouteToSpeakerphone(params["defaultToSpeaker"] as! Bool)) + } - func createDataStream(_ reliable: Bool, _ ordered: Bool, _ callback: Callback?) + @objc func setEnableSpeakerphone(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEnableSpeakerphone(params["enabled"] as! Bool)) + } + + @objc func isSpeakerphoneEnabled(_ callback: Callback) { + callback.resolve(engine) { + $0.isSpeakerphoneEnabled() + } + } + + @objc func enableInEarMonitoring(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enable(inEarMonitoring: params["enabled"] as! Bool)) + } + + @objc func setInEarMonitoringVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setInEarMonitoringVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func enableDualStreamMode(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableDualStreamMode(params["enabled"] as! Bool)) + } + + @objc func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteVideoStream((params["uid"] as! NSNumber).uintValue, type: AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } + + @objc func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteDefaultVideoStreamType(AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } + + @objc func setLocalPublishFallbackOption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalPublishFallbackOption(AgoraStreamFallbackOptions(rawValue: (params["option"] as! NSNumber).intValue)!)) + } + + @objc func setRemoteSubscribeFallbackOption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteSubscribeFallbackOption(AgoraStreamFallbackOptions(rawValue: (params["option"] as! NSNumber).intValue)!)) + } + + @objc func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteUserPriority((params["uid"] as! NSNumber).uintValue, type: AgoraUserPriority(rawValue: (params["userPriority"] as! NSNumber).intValue)!)) + } + + @objc func startEchoTest(_ params: NSDictionary, _ callback: Callback) { + 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) { + callback.code(engine?.stopEchoTest()) + } + + @objc func enableLastmileTest(_ callback: Callback) { + callback.code(engine?.enableLastmileTest()) + } - func sendStreamMessage(_ streamId: Int, _ message: String, _ callback: Callback?) + @objc func disableLastmileTest(_ callback: Callback) { + callback.code(engine?.disableLastmileTest()) + } + + @objc func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! [String: Any]))) + } + + @objc func stopLastmileProbeTest(_ callback: Callback) { + callback.code(engine?.stopLastmileProbeTest()) + } + + @objc func registerMediaMetadataObserver(_ callback: Callback) { + let mediaObserver = MediaObserver { [weak self] in + self?.emitter(RtcEngineEvents.MetadataReceived, $0) + } + callback.resolve(engine) { + if $0.setMediaMetadataDelegate(mediaObserver, with: .video) { + self.mediaObserver = mediaObserver + } + return nil + } + } + + @objc func unregisterMediaMetadataObserver(_ callback: Callback) { + callback.resolve(engine) { + if $0.setMediaMetadataDelegate(nil, with: .video) { + self.mediaObserver = nil + } + return nil + } + } + + @objc func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserver) { + $0.setMaxMetadataSize((params["size"] as! NSNumber).intValue) + } + } + + @objc func sendMetadata(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserver) { + $0.addMetadata(params["metadata"] as! String) + } + } + + @objc func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! [String: Any]))) + } + + @objc func clearVideoWatermarks(_ callback: Callback) { + callback.code(engine?.clearVideoWatermarks()) + } + + @objc func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEncryptionSecret(params["secret"] as? String)) + } + + @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { + 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)!)) + } + + @objc func stopAudioRecording(_ callback: Callback) { + callback.code(engine?.stopAudioRecording()) + } + + @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) + } + + @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.removeInjectStreamUrl(params["url"] as! String)) + } + + @objc func switchCamera(_ callback: Callback) { + callback.code(engine?.switchCamera()) + } + + @objc func isCameraZoomSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraZoomSupported() + } + } + + @objc func isCameraTorchSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraTorchSupported() + } + } + + @objc func isCameraFocusSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraFocusPositionInPreviewSupported() + } + } + + @objc func isCameraExposurePositionSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraExposurePositionSupported() + } + } + + @objc func isCameraAutoFocusFaceModeSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraAutoFocusFaceModeSupported() + } + } + + @objc func setCameraZoomFactor(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraZoomFactor(CGFloat(truncating: params["factor"] as! NSNumber)) + return nil + } + } + + @objc func getCameraMaxZoomFactor(_ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) + } + + @objc func setCameraFocusPositionInPreview(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraFocusPositionInPreview(CGPoint(x: (params["positionX"] as! NSNumber).doubleValue, y: (params["positionY"] as! NSNumber).doubleValue)) + return nil + } + } + + @objc func setCameraExposurePosition(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraExposurePosition(CGPoint(x: (params["positionXinView"] as! NSNumber).doubleValue, y: (params["positionYinView"] as! NSNumber).doubleValue)) + return nil + } + } + + @objc func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableFaceDetection(params["enable"] as! Bool)) + } + + @objc func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraTorchOn(params["isOn"] as! Bool) + return nil + } + } + + @objc func setCameraAutoFocusFaceModeEnabled(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraAutoFocusFaceModeEnabled(params["enabled"] as! Bool) + } + } + + @objc func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! [String: Any]))) + } + + @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { + var streamId = 0 + 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 new file mode 100644 index 000000000..dd4f555ed --- /dev/null +++ b/RtcEngineEvent.swift @@ -0,0 +1,536 @@ +// +// RtcEngineEvent.swift +// RCTAgora +// +// Created by LXH on 2020/4/13. +// Copyright (c) 2020 Syan. All rights reserved. +// + +import AgoraRtcKit +import Foundation + +class RtcEngineEvents { + static let Warning = "Warning" + static let Error = "Error" + static let ApiCallExecuted = "ApiCallExecuted" + static let JoinChannelSuccess = "JoinChannelSuccess" + static let RejoinChannelSuccess = "RejoinChannelSuccess" + static let LeaveChannel = "LeaveChannel" + static let LocalUserRegistered = "LocalUserRegistered" + static let UserInfoUpdated = "UserInfoUpdated" + static let ClientRoleChanged = "ClientRoleChanged" + static let UserJoined = "UserJoined" + static let UserOffline = "UserOffline" + static let ConnectionStateChanged = "ConnectionStateChanged" + static let NetworkTypeChanged = "NetworkTypeChanged" + static let ConnectionLost = "ConnectionLost" + static let TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" + static let RequestToken = "RequestToken" + static let AudioVolumeIndication = "AudioVolumeIndication" + static let ActiveSpeaker = "ActiveSpeaker" + static let FirstLocalAudioFrame = "FirstLocalAudioFrame" + static let FirstLocalVideoFrame = "FirstLocalVideoFrame" + static let UserMuteVideo = "UserMuteVideo" + static let VideoSizeChanged = "VideoSizeChanged" + static let RemoteVideoStateChanged = "RemoteVideoStateChanged" + 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" + static let CameraFocusAreaChanged = "CameraFocusAreaChanged" + static let CameraExposureAreaChanged = "CameraExposureAreaChanged" + static let FacePositionChanged = "FacePositionChanged" + static let RtcStats = "RtcStats" + static let LastmileQuality = "LastmileQuality" + static let NetworkQuality = "NetworkQuality" + static let LastmileProbeResult = "LastmileProbeResult" + static let LocalVideoStats = "LocalVideoStats" + static let LocalAudioStats = "LocalAudioStats" + static let RemoteVideoStats = "RemoteVideoStats" + static let RemoteAudioStats = "RemoteAudioStats" + static let AudioMixingFinished = "AudioMixingFinished" + static let AudioMixingStateChanged = "AudioMixingStateChanged" + static let AudioEffectFinished = "AudioEffectFinished" + static let RtmpStreamingStateChanged = "RtmpStreamingStateChanged" + static let TranscodingUpdated = "TranscodingUpdated" + static let StreamInjectedStatus = "StreamInjectedStatus" + static let StreamMessage = "StreamMessage" + static let StreamMessageError = "StreamMessageError" + static let MediaEngineLoadSuccess = "MediaEngineLoadSuccess" + static let MediaEngineStartCallSuccess = "MediaEngineStartCallSuccess" + static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" + static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" + static let FirstRemoteVideoFrame = "FirstRemoteVideoFrame" + static let FirstRemoteAudioFrame = "FirstRemoteAudioFrame" + static let FirstRemoteAudioDecoded = "FirstRemoteAudioDecoded" + static let UserMuteAudio = "UserMuteAudio" + static let StreamPublished = "StreamPublished" + static let StreamUnpublished = "StreamUnpublished" + static let RemoteAudioTransportStats = "RemoteAudioTransportStats" + static let RemoteVideoTransportStats = "RemoteVideoTransportStats" + static let UserEnableVideo = "UserEnableVideo" + static let UserEnableLocalVideo = "UserEnableLocalVideo" + static let FirstRemoteVideoDecoded = "FirstRemoteVideoDecoded" + static let MicrophoneEnabled = "MicrophoneEnabled" + static let ConnectionInterrupted = "ConnectionInterrupted" + static let ConnectionBanned = "ConnectionBanned" + static let AudioQuality = "AudioQuality" + static let CameraReady = "CameraReady" + static let VideoStopped = "VideoStopped" + static let MetadataReceived = "MetadataReceived" + 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, + "ApiCallExecuted": ApiCallExecuted, + "JoinChannelSuccess": JoinChannelSuccess, + "RejoinChannelSuccess": RejoinChannelSuccess, + "LeaveChannel": LeaveChannel, + "LocalUserRegistered": LocalUserRegistered, + "UserInfoUpdated": UserInfoUpdated, + "ClientRoleChanged": ClientRoleChanged, + "UserJoined": UserJoined, + "UserOffline": UserOffline, + "ConnectionStateChanged": ConnectionStateChanged, + "NetworkTypeChanged": NetworkTypeChanged, + "ConnectionLost": ConnectionLost, + "TokenPrivilegeWillExpire": TokenPrivilegeWillExpire, + "RequestToken": RequestToken, + "AudioVolumeIndication": AudioVolumeIndication, + "ActiveSpeaker": ActiveSpeaker, + "FirstLocalAudioFrame": FirstLocalAudioFrame, + "FirstLocalVideoFrame": FirstLocalVideoFrame, + "UserMuteVideo": UserMuteVideo, + "VideoSizeChanged": VideoSizeChanged, + "RemoteVideoStateChanged": RemoteVideoStateChanged, + "LocalVideoStateChanged": LocalVideoStateChanged, + "RemoteAudioStateChanged": RemoteAudioStateChanged, + "LocalAudioStateChanged": LocalAudioStateChanged, + "RequestAudioFileInfo": RequestAudioFileInfo, + "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, + "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, + "AudioRouteChanged": AudioRouteChanged, + "CameraFocusAreaChanged": CameraFocusAreaChanged, + "CameraExposureAreaChanged": CameraExposureAreaChanged, + "FacePositionChanged": FacePositionChanged, + "RtcStats": RtcStats, + "LastmileQuality": LastmileQuality, + "NetworkQuality": NetworkQuality, + "LastmileProbeResult": LastmileProbeResult, + "LocalVideoStats": LocalVideoStats, + "LocalAudioStats": LocalAudioStats, + "RemoteVideoStats": RemoteVideoStats, + "RemoteAudioStats": RemoteAudioStats, + "AudioMixingFinished": AudioMixingFinished, + "AudioMixingStateChanged": AudioMixingStateChanged, + "AudioEffectFinished": AudioEffectFinished, + "RtmpStreamingStateChanged": RtmpStreamingStateChanged, + "TranscodingUpdated": TranscodingUpdated, + "StreamInjectedStatus": StreamInjectedStatus, + "StreamMessage": StreamMessage, + "StreamMessageError": StreamMessageError, + "MediaEngineLoadSuccess": MediaEngineLoadSuccess, + "MediaEngineStartCallSuccess": MediaEngineStartCallSuccess, + "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, + "ChannelMediaRelayEvent": ChannelMediaRelayEvent, + "FirstRemoteVideoFrame": FirstRemoteVideoFrame, + "FirstRemoteAudioFrame": FirstRemoteAudioFrame, + "FirstRemoteAudioDecoded": FirstRemoteAudioDecoded, + "UserMuteAudio": UserMuteAudio, + "StreamPublished": StreamPublished, + "StreamUnpublished": StreamUnpublished, + "RemoteAudioTransportStats": RemoteAudioTransportStats, + "RemoteVideoTransportStats": RemoteVideoTransportStats, + "UserEnableVideo": UserEnableVideo, + "UserEnableLocalVideo": UserEnableLocalVideo, + "FirstRemoteVideoDecoded": FirstRemoteVideoDecoded, + "MicrophoneEnabled": MicrophoneEnabled, + "ConnectionInterrupted": ConnectionInterrupted, + "ConnectionBanned": ConnectionBanned, + "AudioQuality": AudioQuality, + "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, + ] + } +} + +class RtcEngineEventHandler: NSObject { + static let PREFIX = "io.agora.rtc." + + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void + + init(emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { + self.emitter = emitter + } + + private func callback(_ methodName: String, _ data: Any?...) { + emitter(methodName, ["data": data]) + } +} + +extension RtcEngineEventHandler: AgoraRtcEngineDelegate { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { + callback(RtcEngineEvents.Warning, warningCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { + callback(RtcEngineEvents.Error, errorCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { + callback(RtcEngineEvents.ApiCallExecuted, error, api, result) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.JoinChannelSuccess, channel, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { + callback(RtcEngineEvents.LeaveChannel, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { + callback(RtcEngineEvents.LocalUserRegistered, uid, userAccount) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { + callback(RtcEngineEvents.UserInfoUpdated, uid, userInfo.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + callback(RtcEngineEvents.ClientRoleChanged, oldRole.rawValue, newRole.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.UserJoined, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + callback(RtcEngineEvents.UserOffline, uid, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + callback(RtcEngineEvents.ConnectionStateChanged, state.rawValue, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { + callback(RtcEngineEvents.NetworkTypeChanged, type.rawValue) + } + + public func rtcEngineConnectionDidLost(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.ConnectionLost) + } + + public func rtcEngine(_: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { + callback(RtcEngineEvents.TokenPrivilegeWillExpire, token) + } + + public func rtcEngineRequestToken(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.RequestToken) + } + + public func rtcEngine(_: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { + callback(RtcEngineEvents.AudioVolumeIndication, speakers.toMapList(), totalVolume) + } + + public func rtcEngine(_: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { + callback(RtcEngineEvents.ActiveSpeaker, speakerUid) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { + callback(RtcEngineEvents.FirstLocalAudioFrame, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { + callback(RtcEngineEvents.FirstLocalVideoFrame, Int(size.width), Int(size.height), elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserMuteVideo, uid, muted) + } + + 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(_: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + callback(RtcEngineEvents.RemoteVideoStateChanged, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { + callback(RtcEngineEvents.LocalVideoStateChanged, state.rawValue, error.rawValue) + } + + 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(_: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { + callback(RtcEngineEvents.LocalAudioStateChanged, state.rawValue, error.rawValue) + } + + 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(_: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, uid, isFallbackOrRecover) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { + callback(RtcEngineEvents.AudioRouteChanged, routing.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { + callback(RtcEngineEvents.CameraFocusAreaChanged, rect.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { + callback(RtcEngineEvents.CameraExposureAreaChanged, rect.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { + callback(RtcEngineEvents.FacePositionChanged, width, height, faces?.toMapList()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { + callback(RtcEngineEvents.RtcStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { + callback(RtcEngineEvents.LastmileQuality, quality.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + callback(RtcEngineEvents.NetworkQuality, uid, txQuality.rawValue, rxQuality.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { + callback(RtcEngineEvents.LastmileProbeResult, result.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { + callback(RtcEngineEvents.LocalVideoStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { + callback(RtcEngineEvents.LocalAudioStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + callback(RtcEngineEvents.RemoteVideoStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + callback(RtcEngineEvents.RemoteAudioStats, stats.toMap()) + } + + public func rtcEngineLocalAudioMixingDidFinish(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.AudioMixingFinished) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) { + callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, reason.rawValue) + } + + public func rtcEngineRemoteAudioMixingDidStart(_: AgoraRtcEngineKit) { + // TODO: Not in Android + } + + public func rtcEngineRemoteAudioMixingDidFinish(_: AgoraRtcEngineKit) { + // TODO: Not in Android + } + + public func rtcEngineDidAudioEffectFinish(_: AgoraRtcEngineKit, soundId: Int) { + callback(RtcEngineEvents.AudioEffectFinished, soundId) + } + + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state.rawValue, errorCode.rawValue) + } + + public func rtcEngineTranscodingUpdated(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.TranscodingUpdated) + } + + public func rtcEngine(_: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + callback(RtcEngineEvents.StreamInjectedStatus, url, uid, status.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + callback(RtcEngineEvents.StreamMessage, uid, streamId, String(data: data, encoding: .utf8)) + } + + 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(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.MediaEngineLoadSuccess) + } + + public func rtcEngineMediaEngineDidStartCall(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.MediaEngineStartCallSuccess) + } + + public func rtcEngine(_: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state.rawValue, error.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { + callback(RtcEngineEvents.ChannelMediaRelayEvent, event.rawValue) + } + + 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(_: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.FirstRemoteAudioFrame, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserMuteAudio, uid, muted) + } + + public func rtcEngine(_: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { + callback(RtcEngineEvents.StreamPublished, url, errorCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { + callback(RtcEngineEvents.StreamUnpublished, url) + } + + public func rtcEngine(_: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + callback(RtcEngineEvents.RemoteAudioTransportStats, uid, delay, lost, rxKBitRate) + } + + public func rtcEngine(_: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + callback(RtcEngineEvents.RemoteVideoTransportStats, uid, delay, lost, rxKBitRate) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserEnableVideo, uid, enabled) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserEnableLocalVideo, uid, enabled) + } + + 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(_: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { + callback(RtcEngineEvents.MicrophoneEnabled, enabled) + } + + public func rtcEngineConnectionDidInterrupted(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.ConnectionInterrupted) + } + + public func rtcEngineConnectionDidBanned(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.ConnectionBanned) + } + + public func rtcEngine(_: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { + callback(RtcEngineEvents.AudioQuality, uid, quality.rawValue, delay, lost) + } + + public func rtcEngineCameraDidReady(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.CameraReady) + } + + 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/RtcEngineEventHandler.swift b/RtcEngineEventHandler.swift deleted file mode 100644 index 72c78c899..000000000 --- a/RtcEngineEventHandler.swift +++ /dev/null @@ -1,377 +0,0 @@ -// -// RtcEngineEventHandler.swift -// RCTAgora -// -// Created by LXH on 2020/4/13. -// Copyright (c) 2020 Syan. All rights reserved. -// - -import Foundation -import AgoraRtcKit - -class RtcEngineEventHandler: NSObject { - static let PREFIX = "io.agora.rtc." - static let EVENTS = [ - "Warning": "Warning", - "Error": "Error", - "ApiCallExecuted": "ApiCallExecuted", - "JoinChannelSuccess": "JoinChannelSuccess", - "RejoinChannelSuccess": "RejoinChannelSuccess", - "LeaveChannel": "LeaveChannel", - "LocalUserRegistered": "LocalUserRegistered", - "UserInfoUpdated": "UserInfoUpdated", - "ClientRoleChanged": "ClientRoleChanged", - "UserJoined": "UserJoined", - "UserOffline": "UserOffline", - "ConnectionStateChanged": "ConnectionStateChanged", - "NetworkTypeChanged": "NetworkTypeChanged", - "ConnectionLost": "ConnectionLost", - "TokenPrivilegeWillExpire": "TokenPrivilegeWillExpire", - "RequestToken": "RequestToken", - "AudioVolumeIndication": "AudioVolumeIndication", - "ActiveSpeaker": "ActiveSpeaker", - "FirstLocalAudioFrame": "FirstLocalAudioFrame", - "FirstLocalVideoFrame": "FirstLocalVideoFrame", - "UserMuteVideo": "UserMuteVideo", - "VideoSizeChanged": "VideoSizeChanged", - "RemoteVideoStateChanged": "RemoteVideoStateChanged", - "LocalVideoStateChanged": "LocalVideoStateChanged", - "RemoteAudioStateChanged": "RemoteAudioStateChanged", - "LocalAudioStateChanged": "LocalAudioStateChanged", - "LocalPublishFallbackToAudioOnly": "LocalPublishFallbackToAudioOnly", - "RemoteSubscribeFallbackToAudioOnly": "RemoteSubscribeFallbackToAudioOnly", - "AudioRouteChanged": "AudioRouteChanged", - "CameraFocusAreaChanged": "CameraFocusAreaChanged", - "CameraExposureAreaChanged": "CameraExposureAreaChanged", - "RtcStats": "RtcStats", - "LastmileQuality": "LastmileQuality", - "NetworkQuality": "NetworkQuality", - "LastmileProbeResult": "LastmileProbeResult", - "LocalVideoStats": "LocalVideoStats", - "LocalAudioStats": "LocalAudioStats", - "RemoteVideoStats": "RemoteVideoStats", - "RemoteAudioStats": "RemoteAudioStats", - "AudioMixingFinished": "AudioMixingFinished", - "AudioMixingStateChanged": "AudioMixingStateChanged", - "AudioEffectFinished": "AudioEffectFinished", - "RtmpStreamingStateChanged": "RtmpStreamingStateChanged", - "TranscodingUpdated": "TranscodingUpdated", - "StreamInjectedStatus": "StreamInjectedStatus", - "StreamMessage": "StreamMessage", - "StreamMessageError": "StreamMessageError", - "MediaEngineLoadSuccess": "MediaEngineLoadSuccess", - "MediaEngineStartCallSuccess": "MediaEngineStartCallSuccess", - "ChannelMediaRelayStateChanged": "ChannelMediaRelayStateChanged", - "ChannelMediaRelayEvent": "ChannelMediaRelayEvent", - "FirstRemoteVideoFrame": "FirstRemoteVideoFrame", - "FirstRemoteAudioFrame": "FirstRemoteAudioFrame", - "FirstRemoteAudioDecoded": "FirstRemoteAudioDecoded", - "UserMuteAudio": "UserMuteAudio", - "StreamPublished": "StreamPublished", - "StreamUnpublished": "StreamUnpublished", - "RemoteAudioTransportStats": "RemoteAudioTransportStats", - "RemoteVideoTransportStats": "RemoteVideoTransportStats", - "UserEnableVideo": "UserEnableVideo", - "UserEnableLocalVideo": "UserEnableLocalVideo", - "FirstRemoteVideoDecoded": "FirstRemoteVideoDecoded", - "MicrophoneEnabled": "MicrophoneEnabled", - "ConnectionInterrupted": "ConnectionInterrupted", - "ConnectionBanned": "ConnectionBanned", - "AudioQuality": "AudioQuality", - "CameraReady": "CameraReady", - "VideoStopped": "VideoStopped", - "MetadataReceived": "MetadataReceived", - ] - - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void - - init(emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - self.emitter = emitter - } - - private func callback(_ methodName: String, _ data: Any?...) { - emitter(methodName, ["data": data]) - } -} - -extension RtcEngineEventHandler: AgoraRtcEngineDelegate { - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { - callback("Warning", warningCode.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { - callback("Error", errorCode.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { - callback("ApiCallExecuted", error, api, result) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { - callback("JoinChannelSuccess", channel, uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { - callback("RejoinChannelSuccess", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { - callback("LeaveChannel", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { - callback("LocalUserRegistered", uid, userAccount) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { - callback("UserInfoUpdated", uid, userInfo.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { - callback("ClientRoleChanged", oldRole.rawValue, newRole.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { - callback("UserJoined", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { - callback("UserOffline", uid, reason.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { - callback("ConnectionStateChanged", state.rawValue, reason.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { - callback("NetworkTypeChanged", type.rawValue) - } - - public func rtcEngineConnectionDidLost(_ engine: AgoraRtcEngineKit) { - callback("ConnectionLost") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { - callback("TokenPrivilegeWillExpire", token) - } - - public func rtcEngineRequestToken(_ engine: AgoraRtcEngineKit) { - callback("RequestToken") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { - callback("AudioVolumeIndication", speakers.toMapList(), totalVolume) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { - callback("ActiveSpeaker", speakerUid) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { - callback("FirstLocalAudioFrame", elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { - callback("FirstLocalVideoFrame", size.width, size.height, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { - callback("UserMuteVideo", uid, muted) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { - callback("VideoSizeChanged", uid, size.width, size.height, rotation) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { - callback("RemoteVideoStateChanged", uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { - callback("LocalVideoStateChanged", state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { - callback("RemoteAudioStateChanged", uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { - callback("LocalAudioStateChanged", state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { - callback("LocalPublishFallbackToAudioOnly", isFallbackOrRecover) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { - callback("RemoteSubscribeFallbackToAudioOnly", uid, isFallbackOrRecover) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { - callback("AudioRouteChanged", routing.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { - callback("CameraFocusAreaChanged", rect.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { - callback("CameraExposureAreaChanged", rect.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { - callback("RtcStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { - callback("LastmileQuality", quality.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { - callback("NetworkQuality", uid, txQuality.rawValue, rxQuality.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { - callback("LastmileProbeResult", result.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { - callback("LocalVideoStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { - callback("LocalAudioStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { - callback("RemoteVideoStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { - callback("RemoteAudioStats", stats.toMap()) - } - - public func rtcEngineLocalAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { - callback("AudioMixingFinished") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, errorCode: AgoraAudioMixingErrorCode) { - callback("AudioMixingStateChanged", state.rawValue, errorCode.rawValue) - } - - public func rtcEngineRemoteAudioMixingDidStart(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android - } - - public func rtcEngineRemoteAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android - } - - public func rtcEngineDidAudioEffectFinish(_ engine: AgoraRtcEngineKit, soundId: Int) { - callback("AudioEffectFinished", soundId) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { - callback("RtmpStreamingStateChanged", url, state.rawValue, errorCode.rawValue) - } - - public func rtcEngineTranscodingUpdated(_ engine: AgoraRtcEngineKit) { - callback("TranscodingUpdated") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { - callback("StreamInjectedStatus", url, uid, status.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { - callback("StreamMessage", uid, streamId, String(data: data, encoding: .utf8)) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { - callback("StreamMessageError", uid, streamId, error, missed, cached) - } - - public func rtcEngineMediaEngineDidLoaded(_ engine: AgoraRtcEngineKit) { - callback("MediaEngineLoadSuccess") - } - - public func rtcEngineMediaEngineDidStartCall(_ engine: AgoraRtcEngineKit) { - callback("MediaEngineStartCallSuccess") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { - callback("ChannelMediaRelayStateChanged", state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { - callback("ChannelMediaRelayEvent", event.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { - callback("FirstRemoteVideoFrame", uid, size.width, size.height, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { - callback("FirstRemoteAudioFrame", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { - callback("FirstRemoteAudioDecoded", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { - callback("UserMuteAudio", uid, muted) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { - callback("StreamPublished", url, errorCode.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { - callback("StreamUnpublished", url) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { - callback("RemoteAudioTransportStats", uid, delay, lost, rxKBitRate) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { - callback("RemoteVideoTransportStats", uid, delay, lost, rxKBitRate) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { - callback("UserEnableVideo", uid, enabled) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { - callback("UserEnableLocalVideo", uid, enabled) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { - callback("FirstRemoteVideoDecoded", uid, size.width, size.height, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { - callback("MicrophoneEnabled", enabled) - } - - public func rtcEngineConnectionDidInterrupted(_ engine: AgoraRtcEngineKit) { - callback("ConnectionInterrupted") - } - - public func rtcEngineConnectionDidBanned(_ engine: AgoraRtcEngineKit) { - callback("ConnectionBanned") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { - callback("AudioQuality", uid, quality.rawValue, delay, lost) - } - - public func rtcEngineCameraDidReady(_ engine: AgoraRtcEngineKit) { - callback("CameraReady") - } - - public func rtcEngineVideoDidStop(_ engine: AgoraRtcEngineKit) { - callback("VideoStopped") - } -} 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.h b/RtcEnginePluginRegistrant.h new file mode 100644 index 000000000..27dc5e688 --- /dev/null +++ b/RtcEnginePluginRegistrant.h @@ -0,0 +1,25 @@ +#ifndef RtcEnginePluginRegistrant_h +#define RtcEnginePluginRegistrant_h + +#import +#import "RtcEnginePlugin.h" + +/** + * Class for register the `RtcEnginePlugin`. + */ +@interface RtcEnginePluginRegistrant : NSObject + +/** + * Register a `RtcEnginePlugin`. The `plugin` will be called when the `RtcEngine` is created from + * flutter side. + */ ++(void)register:(NSObject *_Nonnull)plugin; + +/** + * Unregister a previously registered `RtcEnginePlugin`. + */ ++(void)unregister:(NSObject *_Nonnull)plugin; + +@end + +#endif /* RtcEnginePluginRegistrant_h */ diff --git a/RtcEnginePluginRegistrant.m b/RtcEnginePluginRegistrant.m new file mode 100644 index 000000000..fa2dadce7 --- /dev/null +++ b/RtcEnginePluginRegistrant.m @@ -0,0 +1,22 @@ +#import +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "agora_rtc_engine-Swift.h" +#endif +#import "RtcEnginePlugin.h" +#import "RtcEnginePluginRegistrant.h" + +@implementation RtcEnginePluginRegistrant : NSObject + ++ (void)register:(NSObject *)plugin { + [RtcEnginePluginRegistrantSwift register:plugin]; +} + ++ (void)unregister:(NSObject *)plugin { + [RtcEnginePluginRegistrantSwift unregister:plugin]; +} +@end diff --git a/RtcEnginePluginRegistrantSwift.swift b/RtcEnginePluginRegistrantSwift.swift new file mode 100644 index 000000000..5def4c618 --- /dev/null +++ b/RtcEnginePluginRegistrantSwift.swift @@ -0,0 +1,11 @@ +import Foundation + +@objc public class RtcEnginePluginRegistrantSwift: NSObject { + @objc public static func register(_ plugin: RtcEnginePlugin) { + RtcEngineRegistry.shared.add(plugin) + } + + @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 2856b3cf6..1cb7f72f9 100644 --- a/RtcSurfaceView.swift +++ b/RtcSurfaceView.swift @@ -1,33 +1,64 @@ -// -// 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 lazy var canvas: AgoraRtcVideoCanvas = { - var canvas = AgoraRtcVideoCanvas() - canvas.view = self - return canvas - }() - - func setRenderMode(_ engine: AgoraRtcEngineKit, _ renderMode: Int) { - canvas.renderMode = AgoraVideoRenderMode(rawValue: UInt(renderMode))! + private var surface: UIView + private var canvas: AgoraRtcVideoCanvas + private weak var channel: AgoraRtcChannel? + + override init(frame: CGRect) { + surface = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: frame.size)) + canvas = AgoraRtcVideoCanvas() + canvas.view = surface + super.init(frame: frame) + addSubview(surface) + addObserver(self, forKeyPath: observerForKeyPath(), options: .new, context: nil) + } + + func observerForKeyPath() -> String { + return "frame" + } + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + canvas.view = nil + removeObserver(self, forKeyPath: observerForKeyPath(), context: nil) + } + + func setData(_ engine: AgoraRtcEngineKit, _ channel: AgoraRtcChannel?, _ uid: UInt) { + self.channel = channel + canvas.channelId = channel?.getId() + canvas.uid = uid + setupVideoCanvas(engine) + } + + func resetVideoCanvas(_ engine: AgoraRtcEngineKit) { + let canvas = AgoraRtcVideoCanvas() + canvas.view = nil + canvas.renderMode = self.canvas.renderMode + canvas.channelId = self.canvas.channelId + canvas.uid = self.canvas.uid + canvas.mirrorMode = self.canvas.mirrorMode + if canvas.uid == 0 { - engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) + engine.setupLocalVideo(canvas) } else { - engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) + engine.setupRemoteVideo(canvas) } } - func setChannelId(_ engine: AgoraRtcEngineKit, _ channelId: String) { - canvas.channelId = channelId + private func setupVideoCanvas(_ engine: AgoraRtcEngineKit) { + subviews.forEach { + $0.removeFromSuperview() + } + surface = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)) + addSubview(surface) + canvas.view = surface if canvas.uid == 0 { engine.setupLocalVideo(canvas) } else { @@ -35,21 +66,33 @@ class RtcSurfaceView: UIView { } } - func setMirroMode(_ engine: AgoraRtcEngineKit, _ mirrorMode: Int) { - canvas.mirrorMode = AgoraVideoMirrorMode(rawValue: UInt(mirrorMode))! + func setRenderMode(_ engine: AgoraRtcEngineKit, _ renderMode: UInt) { + canvas.renderMode = AgoraVideoRenderMode(rawValue: renderMode)! + setupRenderMode(engine) + } + + func setMirrorMode(_ engine: AgoraRtcEngineKit, _ mirrorMode: UInt) { + canvas.mirrorMode = AgoraVideoMirrorMode(rawValue: mirrorMode)! + setupRenderMode(engine) + } + + private func setupRenderMode(_ engine: AgoraRtcEngineKit) { if canvas.uid == 0 { engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) } else { - engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) + 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) + } } } - func setUid(_ engine: AgoraRtcEngineKit, _ uid: Int) { - canvas.uid = UInt(uid) - if canvas.uid == 0 { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) + 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) + } } } }