diff --git a/AgoraRtcEngineKit.h b/AgoraRtcEngineKit.h index 7af94d48b..cebf95c80 100644 --- a/AgoraRtcEngineKit.h +++ b/AgoraRtcEngineKit.h @@ -9,40 +9,47 @@ #import typedef NS_ENUM(NSUInteger, AgoraRtcQualityReportFormat) { - AgoraRtc_QualityReportFormat_Json = 0, - AgoraRtc_QualityReportFormat_Html = 1, + AgoraRtc_QualityReportFormat_Json = 0, + AgoraRtc_QualityReportFormat_Html = 1, }; typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { - AgoraRtc_APP_TYPE_NATIVE = 0, - AgoraRtc_APP_TYPE_COCOS = 1, - AgoraRtc_APP_TYPE_UNITY = 2, - AgoraRtc_APP_TYPE_ELECTRON = 3, - AgoraRtc_APP_TYPE_FLUTTER = 4, - AgoraRtc_APP_TYPE_UNREAL = 5, - AgoraRtc_APP_TYPE_XAMARIN = 6, - AgoraRtc_APP_TYPE_APICLOUD = 7, - AgoraRtc_APP_TYPE_REACTNATIVE = 8 + AgoraRtc_APP_TYPE_NATIVE = 0, + AgoraRtc_APP_TYPE_COCOS = 1, + AgoraRtc_APP_TYPE_UNITY = 2, + AgoraRtc_APP_TYPE_ELECTRON = 3, + AgoraRtc_APP_TYPE_FLUTTER = 4, + AgoraRtc_APP_TYPE_UNREAL = 5, + AgoraRtc_APP_TYPE_XAMARIN = 6, + AgoraRtc_APP_TYPE_APICLOUD = 7, + AgoraRtc_APP_TYPE_REACTNATIVE = 8 }; @protocol AgoraRtcEngineExtensionDelegate @optional -- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine audioTransportQualityOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost; -- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine videoTransportQualityOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost; +- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine + audioTransportQualityOfUid:(NSUInteger)uid + delay:(NSUInteger)delay + lost:(NSUInteger)lost; +- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine + videoTransportQualityOfUid:(NSUInteger)uid + delay:(NSUInteger)delay + lost:(NSUInteger)lost; @end @interface AgoraRtcEngineKit (AgoraExtension) -+ (instancetype _Nonnull)sharedEngineWithAppId:(NSString * _Nonnull)appId - extensionDelegate:(id _Nullable)delegate; ++ (instancetype _Nonnull)sharedEngineWithAppId:(NSString *_Nonnull)appId + extensionDelegate: + (id _Nullable) + delegate; /** Sets the profile to control the RTC engine. * * @param profile SDK profile in JSON format. * @param merge Whether to merge the profile data with the original value. */ -- (int)setProfile:(NSString * _Nonnull)profile - merge:(BOOL)merge; +- (int)setProfile:(NSString *_Nonnull)profile merge:(BOOL)merge; /** Set wrapper frame type by language wrapper. * @@ -54,7 +61,6 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { /** BEGIN OF AUDIO METHODS */ - /** * Enable recap * @@ -76,8 +82,7 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { andFrameRate:(NSInteger)frameRate andBitrate:(NSInteger)andBitrate; -- (int)sendReportData:(NSData * _Nonnull)data - type:(NSInteger)type; +- (int)sendReportData:(NSData *_Nonnull)data type:(NSInteger)type; /** END OF AUDIO METHODS */ /** Queries internal states @@ -85,22 +90,28 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { * json string, array type * @return a json string */ -- (NSString * _Nullable)getParameters:(NSString * _Nonnull)parameters; +- (NSString *_Nullable)getParameters:(NSString *_Nonnull)parameters; /** - * Generates a URL linking to the call quality reports. @param channel The channel name specified in the joinChannel method. + * Generates a URL linking to the call quality reports. @param channel The + channel name specified in the joinChannel method. * @param listenerUid The uid of the listener. * @param speakerUid The uid of the speaker. * @param reportFormat The format of the report. - AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns the quality report data in Json. - AgoraRtc_QualityReportFormat_Html (1): HTML.: Returns a report in HTML format, displayed on a web browser or WebVIEW components. + AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns + the quality report data in Json. AgoraRtc_QualityReportFormat_Html (1): HTML.: + Returns a report in HTML format, displayed on a web browser or WebVIEW + components. * - * @return 0 when executed successfully. return minus value when failed. return AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. + * @return 0 when executed successfully. return minus value when failed. return + AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return + AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. */ -- (NSString * _Nullable)makeQualityReportUrl:(NSString * _Nonnull) channel - listenerUid:(NSUInteger)listenerUid - speakerrUid:(NSUInteger)speakerUid - reportFormat:(AgoraRtcQualityReportFormat)reportFormat; +- (NSString *_Nullable)makeQualityReportUrl:(NSString *_Nonnull)channel + listenerUid:(NSUInteger)listenerUid + speakerrUid:(NSUInteger)speakerUid + reportFormat: + (AgoraRtcQualityReportFormat)reportFormat; /********************************************************* * Large group conference call (experiment) - END diff --git a/BeanCovertor.swift b/BeanCovertor.swift index 868a41b34..ae6c5240f 100644 --- a/BeanCovertor.swift +++ b/BeanCovertor.swift @@ -6,10 +6,10 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation -func mapToPoint(_ map: Dictionary) -> CGPoint { +func mapToPoint(_ map: [String: Any]) -> CGPoint { var point = CGPoint() if let x = map["x"] as? NSNumber { point.x = CGFloat(truncating: x) @@ -20,7 +20,7 @@ func mapToPoint(_ map: Dictionary) -> CGPoint { return point } -func mapToSize(_ map: Dictionary) -> CGSize { +func mapToSize(_ map: [String: Any]) -> CGSize { var size = CGSize() if let width = map["width"] as? NSNumber { size.width = CGFloat(truncating: width) @@ -31,16 +31,16 @@ func mapToSize(_ map: Dictionary) -> CGSize { return size } -func mapToRect(_ map: Dictionary) -> CGRect { +func mapToRect(_ map: [String: Any]) -> CGRect { return CGRect( origin: mapToPoint(map), size: mapToSize(map) ) } -func mapToVideoEncoderConfiguration(_ map: Dictionary) -> AgoraVideoEncoderConfiguration { +func mapToVideoEncoderConfiguration(_ map: [String: Any]) -> AgoraVideoEncoderConfiguration { let config = AgoraVideoEncoderConfiguration() - if let dimensions = map["dimensions"] as? Dictionary { + if let dimensions = map["dimensions"] as? [String: Any] { config.dimensions = mapToSize(dimensions) } if let frameRate = map["frameRate"] as? NSNumber { @@ -73,7 +73,7 @@ func mapToVideoEncoderConfiguration(_ map: Dictionary) -> AgoraVide return config } -func mapToBeautyOptions(_ map: Dictionary) -> AgoraBeautyOptions { +func mapToBeautyOptions(_ map: [String: Any]) -> AgoraBeautyOptions { let options = AgoraBeautyOptions() if let lighteningContrastLevel = map["lighteningContrastLevel"] as? NSNumber { if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: lighteningContrastLevel.uintValue) { @@ -92,7 +92,7 @@ func mapToBeautyOptions(_ map: Dictionary) -> AgoraBeautyOptions { return options } -func mapToAgoraImage(_ map: Dictionary) -> AgoraImage { +func mapToAgoraImage(_ map: [String: Any]) -> AgoraImage { let image = AgoraImage() if let url = map["url"] as? String { if let url = URL(string: url) { @@ -103,7 +103,7 @@ func mapToAgoraImage(_ map: Dictionary) -> AgoraImage { return image } -func mapToTranscodingUser(_ map: Dictionary) -> AgoraLiveTranscodingUser { +func mapToTranscodingUser(_ map: [String: Any]) -> AgoraLiveTranscodingUser { let user = AgoraLiveTranscodingUser() if let uid = map["uid"] as? NSNumber { user.uid = uid.uintValue @@ -121,16 +121,16 @@ func mapToTranscodingUser(_ map: Dictionary) -> AgoraLiveTranscodin return user } -func mapToColor(_ map: Dictionary) -> UIColor { +func mapToColor(_ map: [String: Any]) -> UIColor { return UIColor( - red: CGFloat((map["red"] as! NSNumber).intValue), - green: CGFloat((map["green"] as! NSNumber).intValue), - blue: CGFloat((map["blue"] as! NSNumber).intValue), - alpha: 1.0 + red: CGFloat((map["red"] as! NSNumber).intValue), + green: CGFloat((map["green"] as! NSNumber).intValue), + blue: CGFloat((map["blue"] as! NSNumber).intValue), + alpha: 1.0 ) } -func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscoding { +func mapToLiveTranscoding(_ map: [String: Any]) -> AgoraLiveTranscoding { let transcoding = AgoraLiveTranscoding.default() transcoding.size = mapToSize(map) if let videoBitrate = map["videoBitrate"] as? NSNumber { @@ -145,10 +145,10 @@ func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscodin if let videoGop = map["videoGop"] as? NSNumber { transcoding.videoGop = videoGop.intValue } - if let watermark = map["watermark"] as? Dictionary { + if let watermark = map["watermark"] as? [String: Any] { transcoding.watermark = mapToAgoraImage(watermark) } - if let backgroundImage = map["backgroundImage"] as? Dictionary { + if let backgroundImage = map["backgroundImage"] as? [String: Any] { transcoding.backgroundImage = mapToAgoraImage(backgroundImage) } if let audioSampleRate = map["audioSampleRate"] as? NSNumber { @@ -172,15 +172,15 @@ func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscodin transcoding.videoCodecProfile = videoCodecProfile } } - if let backgroundColor = map["backgroundColor"] as? Dictionary { + if let backgroundColor = map["backgroundColor"] as? [String: Any] { transcoding.backgroundColor = mapToColor(backgroundColor) } if let userConfigExtraInfo = map["userConfigExtraInfo"] as? String { transcoding.transcodingExtraInfo = userConfigExtraInfo } - if let transcodingUsers = map["transcodingUsers"] as? Array { + if let transcodingUsers = map["transcodingUsers"] as? [Any] { transcodingUsers.forEach { - if let item = $0 as? Dictionary { + if let item = $0 as? [String: Any] { transcoding.add(mapToTranscodingUser(item)) } } @@ -188,7 +188,7 @@ func mapToLiveTranscoding(_ map: Dictionary) -> AgoraLiveTranscodin return transcoding } -func mapToChannelMediaInfo(_ map: Dictionary) -> AgoraChannelMediaRelayInfo { +func mapToChannelMediaInfo(_ map: [String: Any]) -> AgoraChannelMediaRelayInfo { let info = AgoraChannelMediaRelayInfo() if let channelName = map["channelName"] as? String { info.channelName = channelName @@ -202,14 +202,14 @@ func mapToChannelMediaInfo(_ map: Dictionary) -> AgoraChannelMediaR return info } -func mapToChannelMediaRelayConfiguration(_ map: Dictionary) -> AgoraChannelMediaRelayConfiguration { +func mapToChannelMediaRelayConfiguration(_ map: [String: Any]) -> AgoraChannelMediaRelayConfiguration { let config = AgoraChannelMediaRelayConfiguration() - if let srcInfo = map["srcInfo"] as? Dictionary { + if let srcInfo = map["srcInfo"] as? [String: Any] { config.sourceInfo = mapToChannelMediaInfo(srcInfo) } - if let destInfos = map["destInfos"] as? Array { + if let destInfos = map["destInfos"] as? [Any] { destInfos.forEach { - if let item = $0 as? Dictionary { + if let item = $0 as? [String: Any] { let info = mapToChannelMediaInfo(item) config.setDestinationInfo(info, forChannelName: info.channelName ?? "") } @@ -218,7 +218,7 @@ func mapToChannelMediaRelayConfiguration(_ map: Dictionary) -> Agor return config } -func mapToLastmileProbeConfig(_ map: Dictionary) -> AgoraLastmileProbeConfig { +func mapToLastmileProbeConfig(_ map: [String: Any]) -> AgoraLastmileProbeConfig { let config = AgoraLastmileProbeConfig() if let probeUplink = map["probeUplink"] as? Bool { config.probeUplink = probeUplink @@ -235,21 +235,21 @@ func mapToLastmileProbeConfig(_ map: Dictionary) -> AgoraLastmilePr return config } -func mapToWatermarkOptions(_ map: Dictionary) -> WatermarkOptions { +func mapToWatermarkOptions(_ map: [String: Any]) -> WatermarkOptions { let options = WatermarkOptions() if let visibleInPreview = map["visibleInPreview"] as? Bool { options.visibleInPreview = visibleInPreview } - if let positionInLandscapeMode = map["positionInLandscapeMode"] as? Dictionary { + if let positionInLandscapeMode = map["positionInLandscapeMode"] as? [String: Any] { options.positionInLandscapeMode = mapToRect(positionInLandscapeMode) } - if let positionInPortraitMode = map["positionInPortraitMode"] as? Dictionary { + if let positionInPortraitMode = map["positionInPortraitMode"] as? [String: Any] { options.positionInPortraitMode = mapToRect(positionInPortraitMode) } return options } -func mapToLiveInjectStreamConfig(_ map: Dictionary) -> AgoraLiveInjectStreamConfig { +func mapToLiveInjectStreamConfig(_ map: [String: Any]) -> AgoraLiveInjectStreamConfig { let config = AgoraLiveInjectStreamConfig.default() config.size = mapToSize(map) if let videoGop = map["videoGop"] as? NSNumber { @@ -275,13 +275,19 @@ func mapToLiveInjectStreamConfig(_ map: Dictionary) -> AgoraLiveInj return config } -func mapToCameraCapturerConfiguration(_ map: Dictionary) -> AgoraCameraCapturerConfiguration { +func mapToCameraCapturerConfiguration(_ map: [String: Any]) -> AgoraCameraCapturerConfiguration { let config = AgoraCameraCapturerConfiguration() if let preference = map["preference"] as? NSNumber { if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference.intValue) { config.preference = preference } } + if let captureWidth = map["captureWidth"] as? NSNumber { + config.captureWidth = captureWidth.int32Value + } + if let captureHeight = map["captureHeight"] as? NSNumber { + config.captureHeight = captureHeight.int32Value + } if let cameraDirection = map["cameraDirection"] as? NSNumber { if let cameraDirection = AgoraCameraDirection(rawValue: cameraDirection.intValue) { config.cameraDirection = cameraDirection @@ -290,7 +296,7 @@ func mapToCameraCapturerConfiguration(_ map: Dictionary) -> AgoraCa return config } -func mapToChannelMediaOptions(_ map: Dictionary) -> AgoraRtcChannelMediaOptions { +func mapToChannelMediaOptions(_ map: [String: Any]) -> AgoraRtcChannelMediaOptions { let options = AgoraRtcChannelMediaOptions() if let autoSubscribeAudio = map["autoSubscribeAudio"] as? Bool { options.autoSubscribeAudio = autoSubscribeAudio @@ -298,14 +304,153 @@ func mapToChannelMediaOptions(_ map: Dictionary) -> AgoraRtcChannel if let autoSubscribeVideo = map["autoSubscribeVideo"] as? Bool { options.autoSubscribeVideo = autoSubscribeVideo } + if let publishLocalAudio = map["publishLocalAudio"] as? Bool { + options.publishLocalAudio = publishLocalAudio + } + if let publishLocalVideo = map["publishLocalVideo"] as? Bool { + options.publishLocalVideo = publishLocalVideo + } return options } -func mapToRtcEngineConfig(_ map: Dictionary) -> AgoraRtcEngineConfig { +func mapToRtcEngineConfig(_ map: [String: Any]) -> AgoraRtcEngineConfig { let config = AgoraRtcEngineConfig() config.appId = map["appId"] as? String if let areaCode = map["areaCode"] as? NSNumber { - config.areaCode = areaCode.int32Value + config.areaCode = areaCode.uintValue + } + if let logConfig = map["logConfig"] as? [String: Any] { + config.logConfig = mapToLogConfig(logConfig) + } + return config +} + +func mapToAudioRecordingConfiguration(_ map: [String: Any]) -> AgoraAudioRecordingConfiguration { + let config = AgoraAudioRecordingConfiguration() + if let filePath = map["filePath"] as? String { + config.filePath = filePath + } + if let recordingQuality = map["recordingQuality"] as? NSNumber { + if let recordingQuality = AgoraAudioRecordingQuality(rawValue: recordingQuality.intValue) { + config.recordingQuality = recordingQuality + } + } + if let recordingPosition = map["recordingPosition"] as? NSNumber { + if let recordingPosition = AgoraAudioRecordingPosition(rawValue: recordingPosition.intValue) { + config.recordingPosition = recordingPosition + } + } + if let recordingSampleRate = map["recordingSampleRate"] as? NSNumber { + config.recordingSampleRate = recordingSampleRate.intValue + } + return config +} + +func mapToEncryptionConfig(_ map: [String: Any]) -> AgoraEncryptionConfig { + let config = AgoraEncryptionConfig() + if let encryptionMode = map["encryptionMode"] as? NSNumber { + if let encryptionMode = AgoraEncryptionMode(rawValue: encryptionMode.intValue) { + config.encryptionMode = encryptionMode + } + } + if let encryptionKey = map["encryptionKey"] as? String { + config.encryptionKey = encryptionKey + } + if let list = map["encryptionKdfSalt"] as? [Any] { + var encryptionKdfSalt: [UInt8] = [] + for i in list.indices { + if let item = list[i] as? NSNumber { + encryptionKdfSalt.append(item.uint8Value) + } + } + config.encryptionKdfSalt = Data(bytes: encryptionKdfSalt) + } + return config +} + +func mapToRhythmPlayerConfig(_ map: [String: Any]) -> AgoraRtcRhythmPlayerConfig { + let config = AgoraRtcRhythmPlayerConfig() + if let beatsPerMeasure = map["beatsPerMeasure"] as? NSNumber { + config.beatsPerMeasure = beatsPerMeasure.uintValue + } + if let beatsPerMinute = map["beatsPerMinute"] as? NSNumber { + config.beatsPerMinute = beatsPerMinute.uintValue + } + if let publish = map["publish"] as? NSNumber { + config.publish = publish.boolValue + } + return config +} + +func mapToClientRoleOptions(_ map: [String: Any]) -> AgoraClientRoleOptions { + let options = AgoraClientRoleOptions() + if let audienceLatencyLevel = map["audienceLatencyLevel"] as? NSNumber { + if let audienceLatencyLevel = AgoraAudienceLatencyLevelType(rawValue: audienceLatencyLevel.intValue) { + options.audienceLatencyLevel = audienceLatencyLevel + } + } + return options +} + +func mapToLogConfig(_ map: [String: Any]) -> AgoraLogConfig { + let config = AgoraLogConfig() + config.filePath = map["filePath"] as? String + if let fileSize = map["fileSize"] as? NSNumber { + config.fileSize = fileSize.intValue + } + if let level = map["level"] as? NSNumber { + if let level = AgoraLogLevel(rawValue: level.intValue) { + config.level = level + } + } + return config +} + +func mapToDataStreamConfig(_ map: [String: Any]) -> AgoraDataStreamConfig { + let config = AgoraDataStreamConfig() + if let syncWithAudio = map["syncWithAudio"] as? Bool { + config.syncWithAudio = syncWithAudio + } + if let ordered = map["ordered"] as? Bool { + config.ordered = ordered + } + return config +} + +func mapToVirtualBackgroundSource(_ map: [String: Any]) -> AgoraVirtualBackgroundSource { + let backgroundSource = AgoraVirtualBackgroundSource() + if let backgroundSourceType = map["backgroundSourceType"] as? NSNumber { + if let backgroundSourceType = AgoraVirtualBackgroundSourceType(rawValue: backgroundSourceType.uintValue) { + backgroundSource.backgroundSourceType = backgroundSourceType + } + } + if let color = map["color"] as? [String: Any] { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + mapToColor(color).getRed(&red, green: &green, blue: &blue, alpha: &alpha) + backgroundSource.color = UInt(red * 255.0) << 16 + UInt(green * 255.0) << 8 + UInt(blue * 255.0) + } + backgroundSource.source = map["source"] as? String + if let blurDegree = map["blur_degree"] as? NSNumber { + if let blurDegree = AgoraBlurDegree(rawValue: blurDegree.uintValue) { + backgroundSource.blur_degree = blurDegree + } + } + return backgroundSource +} + +func mapToEchoTestConfiguration(_ map: [String: Any]) -> AgoraEchoTestConfiguration { + let config = AgoraEchoTestConfiguration() + if let enableAudio = map["enableAudio"] as? NSNumber { + config.enableAudio = enableAudio.boolValue + } + if let enableVideo = map["enableVideo"] as? NSNumber { + config.enableVideo = enableVideo.boolValue + } + if let token = map["token"] as? String { + config.token = token + } + if let channelId = map["channelId"] as? String { + config.channelId = channelId } return config } diff --git a/Callback.swift b/Callback.swift index b911dfff8..8c5bc130a 100644 --- a/Callback.swift +++ b/Callback.swift @@ -6,8 +6,8 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation @objc protocol Callback: class { @@ -25,25 +25,17 @@ extension Callback { } let res = runnable?(code) - if res is Void { - success(nil) - } else { - success(res) - } + success(res) } func resolve(_ source: T?, _ runnable: (T) -> Any?) { - guard let `source` = source else { + guard let source = source else { let code = AgoraErrorCode.notInitialized.rawValue failure(String(code), AgoraRtcEngineKit.getErrorDescription(code) ?? "") return } let res = runnable(source) - if res is Void { - success(nil) - } else { - success(res) - } + success(res) } } diff --git a/Extensions.swift b/Extensions.swift index 14ded003f..d3c6b9f9d 100644 --- a/Extensions.swift +++ b/Extensions.swift @@ -6,32 +6,33 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation extension AgoraUserInfo { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, - "userAccount": userAccount + "userAccount": userAccount, ] } } extension AgoraRtcLocalAudioStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "numChannels": numChannels, "sentSampleRate": sentSampleRate, - "sentBitrate": sentBitrate + "sentBitrate": sentBitrate, + "txPacketLossRate": txPacketLossRate, ] } } extension AgoraChannelStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ - "totalDuration": duration, + "duration": duration, "txBytes": txBytes, "rxBytes": rxBytes, "txAudioBytes": txAudioBytes, @@ -44,7 +45,7 @@ extension AgoraChannelStats { "rxAudioKBitRate": rxAudioKBitrate, "txVideoKBitRate": txVideoKBitrate, "rxVideoKBitRate": rxVideoKBitrate, - "users": userCount, + "userCount": userCount, "lastmileDelay": lastmileDelay, "txPacketLossRate": txPacketLossRate, "rxPacketLossRate": rxPacketLossRate, @@ -53,24 +54,24 @@ extension AgoraChannelStats { "gatewayRtt": gatewayRtt, "memoryAppUsageRatio": memoryAppUsageRatio, "memoryTotalUsageRatio": memoryTotalUsageRatio, - "memoryAppUsageInKbytes": memoryAppUsageInKbytes + "memoryAppUsageInKbytes": memoryAppUsageInKbytes, ] } } extension CGRect { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "left": origin.x, "top": origin.y, "right": origin.x + size.width, - "bottom": origin.y + size.height + "bottom": origin.y + size.height, ] } } extension AgoraRtcRemoteAudioStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, "quality": quality, @@ -82,13 +83,17 @@ extension AgoraRtcRemoteAudioStats { "receivedBitrate": receivedBitrate, "totalFrozenTime": totalFrozenTime, "frozenRate": frozenRate, - "totalActiveTime": totalActiveTime + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, + "qoeQuality": qoeQuality, + "qualityChangedReason": qualityChangedReason, + "mosValue": mosValue, ] } } extension AgoraRtcLocalVideoStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "sentBitrate": sentBitrate, "sentFrameRate": sentFrameRate, @@ -101,13 +106,16 @@ extension AgoraRtcLocalVideoStats { "encodedFrameWidth": encodedFrameWidth, "encodedFrameHeight": encodedFrameHeight, "encodedFrameCount": encodedFrameCount, - "codecType": codecType.rawValue + "codecType": codecType.rawValue, + "txPacketLossRate": txPacketLossRate, + "captureFrameRate": captureFrameRate, + "captureBrightnessLevel": captureBrightnessLevel.rawValue, ] } } extension AgoraRtcRemoteVideoStats { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, "delay": delay, @@ -120,26 +128,27 @@ extension AgoraRtcRemoteVideoStats { "rxStreamType": rxStreamType.rawValue, "totalFrozenTime": totalFrozenTime, "frozenRate": frozenRate, - "totalActiveTime": totalActiveTime + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, ] } } extension AgoraRtcAudioVolumeInfo { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "uid": uid, "volume": volume, "vad": vad, - "channelId": channelId + "channelId": channelId, ] } } extension Array where Element: AgoraRtcAudioVolumeInfo { - func toMapList() -> Array> { - var list = [Dictionary]() - self.forEach { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { list.append($0.toMap()) } return list @@ -147,42 +156,51 @@ extension Array where Element: AgoraRtcAudioVolumeInfo { } extension AgoraLastmileProbeOneWayResult { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "packetLossRate": packetLossRate, "jitter": jitter, - "availableBandwidth": availableBandwidth + "availableBandwidth": availableBandwidth, ] } } extension AgoraLastmileProbeResult { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "state": state.rawValue, "rtt": rtt, "uplinkReport": uplinkReport.toMap(), - "downlinkReport": downlinkReport.toMap() + "downlinkReport": downlinkReport.toMap(), ] } } extension AgoraFacePositionInfo { - func toMap() -> Dictionary { + func toMap() -> [String: Any?] { return [ "x": x, "y": y, "width": width, "height": height, - "distance": distance + "distance": distance, + ] + } +} + +extension AgoraRtcAudioFileInfo { + func toMap() -> [String: Any?] { + return [ + "filePath": filePath, + "durationMs": durationMs, ] } } extension Array where Element: AgoraFacePositionInfo { - func toMapList() -> Array> { - var list = [Dictionary]() - self.forEach { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { list.append($0.toMap()) } return list diff --git a/MediaObserver.swift b/MediaObserver.swift index d11a45705..514fb21d0 100644 --- a/MediaObserver.swift +++ b/MediaObserver.swift @@ -6,15 +6,15 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class MediaObserver: NSObject { - private var emitter: (_ data: Dictionary?) -> Void + private var emitter: (_ data: [String: Any?]?) -> Void private var maxMetadataSize = 1024 private var metadataList = [String]() - init(_ emitter: @escaping (_ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ data: [String: Any?]?) -> Void) { self.emitter = emitter } @@ -32,7 +32,7 @@ extension MediaObserver: AgoraMediaMetadataDataSource { return maxMetadataSize } - func readyToSendMetadata(atTimestamp timestamp: TimeInterval) -> Data? { + func readyToSendMetadata(atTimestamp _: TimeInterval) -> Data? { if metadataList.count > 0 { return metadataList.remove(at: 0).data(using: .utf8) } @@ -43,7 +43,7 @@ extension MediaObserver: AgoraMediaMetadataDataSource { extension MediaObserver: AgoraMediaMetadataDelegate { func receiveMetadata(_ data: Data, fromUser uid: Int, atTimestamp timestamp: TimeInterval) { emitter([ - "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp] + "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp], ]) } } diff --git a/RtcChannel.swift b/RtcChannel.swift index 01c0726ce..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, @@ -37,8 +37,10 @@ protocol RtcChannelInterface: func getConnectionState(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func publish(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func unpublish(_ params: NSDictionary, _ callback: Callback) func getCallId(_ params: NSDictionary, _ callback: Callback) @@ -47,19 +49,27 @@ protocol RtcChannelInterface: protocol RtcChannelAudioInterface { func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) + func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) + func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) } protocol RtcChannelVideoInterface { + func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) + func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) } protocol RtcChannelVoicePositionInterface { @@ -79,6 +89,10 @@ protocol RtcChannelMediaRelayInterface { func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + + func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) } @@ -103,9 +117,13 @@ protocol RtcChannelMediaMetadataInterface { } protocol RtcChannelEncryptionInterface { + @available(*, deprecated) func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) + + func enableEncryption(_ params: NSDictionary, _ callback: Callback) } protocol RtcChannelInjectStreamInterface { @@ -122,12 +140,12 @@ protocol RtcChannelStreamMessageInterface { @objc class RtcChannelManager: NSObject, RtcChannelInterface { - private var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void private var rtcChannelMap = [String: AgoraRtcChannel]() private var rtcChannelDelegateMap = [String: RtcChannelEventHandler]() private var mediaObserverMap = [String: MediaObserver]() - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { self.emitter = emitter } @@ -141,15 +159,13 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } subscript(channelId: String) -> AgoraRtcChannel? { - get { - return rtcChannelMap[channelId] - } + return rtcChannelMap[channelId] } @objc func create(_ params: NSDictionary, _ callback: Callback) { callback.resolve(params["engine"] as? AgoraRtcEngineKit) { [weak self] in if let rtcChannel = $0.createRtcChannel(params["channelId"] as! String) { - let delegate = RtcChannelEventHandler() { [weak self] in + let delegate = RtcChannelEventHandler { [weak self] in self?.emitter($0, $1) } rtcChannel.setRtcChannelDelegate(delegate) @@ -161,20 +177,24 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func destroy(_ params: NSDictionary, _ callback: Callback) { - callback.code(rtcChannelMap.removeValue(forKey:params["channelId"] as! String)?.destroy()) + callback.code(rtcChannelMap.removeValue(forKey: params["channelId"] as! String)?.destroy()) } @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! + if let options = params["options"] as? [String: Any] { + callback.code(self[params["channelId"] as! String]?.setClientRole(role, options: mapToClientRoleOptions(options))) + return + } callback.code(self[params["channelId"] as! String]?.setClientRole(role)) } @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.join(byToken: params["token"] as? String, info: params["optionalInfo"] as? String, uid: (params["optionalUid"] as! NSNumber).uintValue, options: mapToChannelMediaOptions(params["options"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.join(byToken: params["token"] as? String, info: params["optionalInfo"] as? String, uid: (params["optionalUid"] as! NSNumber).uintValue, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) } @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.join(byUserAccount: params["userAccount"] as! String, token: params["token"] as? String, options: mapToChannelMediaOptions(params["options"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.join(byUserAccount: params["userAccount"] as! String, token: params["token"] as? String, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) } @objc func leaveChannel(_ params: NSDictionary, _ callback: Callback) { @@ -238,7 +258,7 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) } @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -250,11 +270,11 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { @@ -277,7 +297,7 @@ class RtcChannelManager: NSObject, RtcChannelInterface { let channelId = params["channelId"] as! String let mediaObserver = MediaObserver { [weak self] in if var data = $0 { - data["channelId"] = channelId; + data["channelId"] = channelId self?.emitter(RtcEngineEvents.MetadataReceived, data) } } @@ -316,11 +336,25 @@ class RtcChannelManager: NSObject, RtcChannelInterface { } @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.setEncryptionMode(params["encryptionMode"] as? String)) + var encryptionMode = "" + switch (params["encryptionMode"] as! NSNumber).intValue { + case AgoraEncryptionMode.AES128XTS.rawValue: + encryptionMode = "aes-128-xts" + case AgoraEncryptionMode.AES128ECB.rawValue: + encryptionMode = "aes-128-ecb" + case AgoraEncryptionMode.AES256XTS.rawValue: + encryptionMode = "aes-256-xts" + default: encryptionMode = "" + } + callback.code(self[params["channelId"] as! String]?.setEncryptionMode(encryptionMode)) + } + + @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) } @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! Dictionary))) + callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) } @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -330,10 +364,40 @@ class RtcChannelManager: NSObject, RtcChannelInterface { @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { let channel = self[params["channelId"] as! String] var streamId = 0 - callback.code(channel?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in streamId } + if let config = params["config"] as? [String: Any] { + callback.code(channel?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in + streamId + } + return + } + callback.code(channel?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in + streamId + } } @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { callback.code(self[params["channelId"] as! String]?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) } + + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enable"] as! Bool)) + } + + @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalAudioStream(params["muted"] as! Bool)) + } + + @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalVideoStream(params["muted"] as! Bool)) + } + + @objc func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) +// callback.code(self[params["channelId"] as! String]?.pauseAllChannelMediaRelay()) + } + + @objc func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) +// callback.code(self[params["channelId"] as! String]?.resumeAllChannelMediaRelay()) + } } diff --git a/RtcChannelEvent.swift b/RtcChannelEvent.swift index 64746ac91..eca5b4da8 100644 --- a/RtcChannelEvent.swift +++ b/RtcChannelEvent.swift @@ -6,8 +6,8 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class RtcChannelEvents { static let Warning = "Warning" @@ -40,8 +40,14 @@ class RtcChannelEvents { static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" static let MetadataReceived = "MetadataReceived" - - static func toMap() -> Dictionary { + static let AudioPublishStateChanged = "AudioPublishStateChanged" + static let VideoPublishStateChanged = "VideoPublishStateChanged" + static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + static let RtmpStreamingEvent = "RtmpStreamingEvent" + static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + + static func toMap() -> [String: String] { return [ "Warning": Warning, "Error": Error, @@ -73,6 +79,12 @@ class RtcChannelEvents { "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, "ChannelMediaRelayEvent": ChannelMediaRelayEvent, "MetadataReceived": MetadataReceived, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, ] } } @@ -80,16 +92,16 @@ class RtcChannelEvents { class RtcChannelEventHandler: NSObject { static let PREFIX = "io.agora.rtc." - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { self.emitter = emitter } private func callback(_ methodName: String, _ channel: AgoraRtcChannel, _ data: Any?...) { emitter(methodName, [ "channelId": channel.getId(), - "data": data + "data": data, ]) } } @@ -210,4 +222,28 @@ extension RtcChannelEventHandler: AgoraRtcChannelDelegate { public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didReceive event: AgoraChannelMediaRelayEvent) { callback(RtcChannelEvents.ChannelMediaRelayEvent, rtcChannel, event.rawValue) } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, eventCode.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + callback(RtcChannelEvents.UserSuperResolutionEnabled, rtcChannel, uid, enabled, reason.rawValue) + } } diff --git a/RtcEngine.swift b/RtcEngine.swift index 30d26b198..c304f39f6 100644 --- a/RtcEngine.swift +++ b/RtcEngine.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation protocol RtcEngineInterface: RtcEngineUserInfoInterface, @@ -52,21 +52,42 @@ protocol RtcEngineInterface: func getConnectionState(_ callback: Callback) + func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) + func getCallId(_ callback: Callback) func rate(_ params: NSDictionary, _ callback: Callback) func complain(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLogFile(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLogFilter(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLogFileSize(_ params: NSDictionary, _ callback: Callback) func setParameters(_ params: NSDictionary, _ callback: Callback) + func getSdkVersion(_ callback: Callback) + + func getErrorDescription(_ params: NSDictionary, _ callback: Callback) + func getNativeHandle(_ callback: Callback) + + func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) + + func setCloudProxy(_ params: NSDictionary, _ callback: Callback) + + func uploadLogFile(_ callback: Callback) + + func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) + + func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) + + func takeSnapshot(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineUserInfoInterface { @@ -100,9 +121,16 @@ protocol RtcEngineAudioInterface { func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) + + func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) + + func stopRhythmPlayer(_ callback: Callback) + + func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVideoInterface { @@ -124,9 +152,12 @@ protocol RtcEngineVideoInterface { func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioMixingInterface { @@ -148,13 +179,23 @@ protocol RtcEngineAudioMixingInterface { func getAudioMixingPublishVolume(_ callback: Callback) - func getAudioMixingDuration(_ callback: Callback) + func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) + + func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) func getAudioMixingCurrentPosition(_ callback: Callback) func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) + + func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) + + func getAudioTrackCount(_ callback: Callback) + + func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) + + func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioEffectInterface { @@ -166,6 +207,12 @@ protocol RtcEngineAudioEffectInterface { func playEffect(_ params: NSDictionary, _ callback: Callback) + func setEffectPosition(_ params: NSDictionary, _ callback: Callback) + + func getEffectDuration(_ params: NSDictionary, _ callback: Callback) + + func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) + func stopEffect(_ params: NSDictionary, _ callback: Callback) func stopAllEffects(_ callback: Callback) @@ -186,8 +233,10 @@ protocol RtcEngineAudioEffectInterface { } protocol RtcEngineVoiceChangerInterface { + @available(*, deprecated) func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) @@ -195,6 +244,16 @@ protocol RtcEngineVoiceChangerInterface { func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) + + func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) + + func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) + + func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) + + func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) + + func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVoicePositionInterface { @@ -216,6 +275,10 @@ protocol RtcEngineMediaRelayInterface { func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + func pauseAllChannelMediaRelay(_ callback: Callback) + + func resumeAllChannelMediaRelay(_ callback: Callback) + func stopChannelMediaRelay(_ callback: Callback) } @@ -280,9 +343,13 @@ protocol RtcEngineWatermarkInterface { } protocol RtcEngineEncryptionInterface { + @available(*, deprecated) func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) + @available(*, deprecated) func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) + + func enableEncryption(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioRecorderInterface { @@ -333,35 +400,55 @@ protocol RtcEngineStreamMessageInterface { func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) } +internal class AgoraRtcEngineKitFactory { + func create(_ params: NSDictionary, _ delegate: RtcEngineEventHandler) -> AgoraRtcEngineKit? { + let engine = AgoraRtcEngineKit.sharedEngine( + with: mapToRtcEngineConfig(params["config"] as! [String: Any]), + delegate: delegate) + + return engine + } +} + @objc class RtcEngineManager: NSObject, RtcEngineInterface { - private var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void + private var agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory private(set) var engine: AgoraRtcEngineKit? private var delegate: RtcEngineEventHandler? private var mediaObserver: MediaObserver? - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void, + _ agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory = AgoraRtcEngineKitFactory()) { self.emitter = emitter + self.agoraRtcEngineKitFactory = agoraRtcEngineKitFactory } func Release() { - AgoraRtcEngineKit.destroy() - engine = nil + if (engine != nil) { + AgoraRtcEngineKit.destroy() + engine = nil + } delegate = nil mediaObserver = nil } @objc func create(_ params: NSDictionary, _ callback: Callback) { - delegate = RtcEngineEventHandler() { [weak self] in + delegate = RtcEngineEventHandler { [weak self] in self?.emitter($0, $1) } - engine = AgoraRtcEngineKit.sharedEngine(with: mapToRtcEngineConfig(params["config"] as! Dictionary), delegate: delegate) - callback.code(engine?.setAppType(AgoraRtcAppType(rawValue: (params["appType"] as! NSNumber).uintValue)!)) + engine = agoraRtcEngineKitFactory.create(params, delegate!) + callback.code(engine?.setAppType(AgoraRtcAppType(rawValue: (params["appType"] as! NSNumber).uintValue)!)) { + RtcEngineRegistry.shared.onRtcEngineCreated(self.engine) + return $0 + } } @objc func destroy(_ callback: Callback) { callback.resolve(engine) { [weak self] _ in self?.Release() + RtcEngineRegistry.shared.onRtcEngineDestroyed() + return nil } } @@ -371,6 +458,10 @@ class RtcEngineManager: NSObject, RtcEngineInterface { @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! + if let options = params["options"] as? [String: Any] { + callback.code(engine?.setClientRole(role, options: mapToClientRoleOptions(options))) + return + } callback.code(engine?.setClientRole(role)) } @@ -379,12 +470,20 @@ class RtcEngineManager: NSObject, RtcEngineInterface { let channelName = params["channelName"] as! String let optionalInfo = params["optionalInfo"] as? String let optionalUid = params["optionalUid"] as! NSNumber + if let options = params["options"] as? [String: Any] { + callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue, options: mapToChannelMediaOptions(options))) + return + } callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue)) } @objc func switchChannel(_ params: NSDictionary, _ callback: Callback) { let token = params["token"] as? String let channelName = params["channelName"] as! String + if let options = params["options"] as? [String: Any] { + callback.code(engine?.switchChannel(byToken: token, channelId: channelName, options: mapToChannelMediaOptions(options))) + return + } callback.code(engine?.switchChannel(byToken: token, channelId: channelName)) } @@ -406,6 +505,10 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } } + @objc func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.sendCustomReportMessage(params["id"] as! String, category: params["category"] as! String, event: params["event"] as! String, label: params["label"] as! String, value: (params["value"] as! NSNumber).intValue)) + } + @objc func getCallId(_ callback: Callback) { callback.resolve(engine) { $0.getCallId() @@ -450,6 +553,10 @@ class RtcEngineManager: NSObject, RtcEngineInterface { let userAccount = params["userAccount"] as! String let token = params["token"] as? String let channelName = params["channelName"] as! String + if let options = params["options"] as? [String: Any] { + callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName, options: mapToChannelMediaOptions(options))) + return + } callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName)) } @@ -513,6 +620,18 @@ class RtcEngineManager: NSObject, RtcEngineInterface { callback.code(engine?.enableAudioVolumeIndication((params["interval"] as! NSNumber).intValue, smooth: (params["smooth"] as! NSNumber).intValue, report_vad: params["report_vad"] as! Bool)) } + @objc func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.startRhythmPlayer(params["sound1"] as! String, sound2: params["sound2"] as! String, config: mapToRhythmPlayerConfig(params["config"] as! [String: Any]))) + } + + @objc func stopRhythmPlayer(_ callback: Callback) { + callback.code(engine?.stopRhythmPlayer()) + } + + @objc func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.configRhythmPlayer(mapToRhythmPlayerConfig(params as! [String: Any]))) + } + @objc func enableVideo(_ callback: Callback) { callback.code(engine?.enableVideo()) } @@ -522,7 +641,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! Dictionary))) + callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! [String: Any]))) } @objc func startPreview(_ callback: Callback) { @@ -554,10 +673,14 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setBeautyEffectOptions(params["enabled"] as! Bool, options: mapToBeautyOptions(params["options"] as! Dictionary))) + callback.code(engine?.setBeautyEffectOptions(params["enabled"] as! Bool, options: mapToBeautyOptions(params["options"] as! [String: Any]))) } @objc func startAudioMixing(_ params: NSDictionary, _ callback: Callback) { + if let startPos = params["startPos"] as? NSNumber { + callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue, startPos: startPos.intValue)) + return + } callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue)) } @@ -597,12 +720,16 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } } - @objc func getAudioMixingDuration(_ callback: Callback) { + @objc func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.getAudioMixingDuration()) { $0 } } + @objc func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getAudioFileInfo(params["filePath"] as! String)) + } + @objc func getAudioMixingCurrentPosition(_ callback: Callback) { callback.code(engine?.getAudioMixingCurrentPosition()) { $0 @@ -617,6 +744,25 @@ class RtcEngineManager: NSObject, RtcEngineInterface { callback.code(engine?.setAudioMixingPitch((params["pitch"] as! NSNumber).intValue)) } + @objc func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioMixingPlaybackSpeed(Int32((params["speed"] as! NSNumber).intValue))) + } + + @objc func getAudioTrackCount(_ callback: Callback) { + callback.code(engine?.getAudioTrackCount()) { + $0 + } + } + + @objc func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.selectAudioTrack((params["index"] as! NSNumber).intValue)) + } + + @objc func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) { + let mode = AgoraAudioMixingDualMonoMode(rawValue: UInt((params["mode"] as! NSNumber).intValue)) + callback.code(engine?.setAudioMixingDualMonoMode(mode!)) + } + @objc func getEffectsVolume(_ callback: Callback) { callback.resolve(engine) { $0.getEffectsVolume() @@ -632,9 +778,29 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func playEffect(_ params: NSDictionary, _ callback: Callback) { + if let startPos = (params["startPos"] as? NSNumber) { + callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool, startPos: startPos.int32Value)) + return + } callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool)) } + @objc func setEffectPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEffectPosition((params["soundId"] as! NSNumber).int32Value, pos: (params["pos"] as! NSNumber).intValue)) + } + + @objc func getEffectDuration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getEffectDuration(params["filePath"] as! String)) { + $0 + } + } + + @objc func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getEffectCurrentPosition((params["soundId"] as! NSNumber).int32Value)) { + $0 + } + } + @objc func stopEffect(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.stopEffect((params["soundId"] as! NSNumber).int32Value)) } @@ -693,6 +859,22 @@ class RtcEngineManager: NSObject, RtcEngineInterface { callback.code(engine?.setLocalVoiceReverbOf(AgoraAudioReverbType(rawValue: (params["reverbKey"] as! NSNumber).intValue)!, withValue: (params["value"] as! NSNumber).intValue)) } + @objc func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioEffectPreset(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceBeautifierPreset(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceConversionPreset(AgoraVoiceConversionPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioEffectParameters(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) + } + @objc func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.enableSoundPositionIndication(params["enabled"] as! Bool)) } @@ -702,7 +884,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! Dictionary))) + callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) } @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -714,11 +896,11 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! Dictionary))) + callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) } @objc func stopChannelMediaRelay(_ callback: Callback) { @@ -772,7 +954,15 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func startEchoTest(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startEchoTest(withInterval: (params["intervalInSeconds"] as! NSNumber).intValue)) + if let intervalInSeconds = (params["intervalInSeconds"] as? NSNumber) { + callback.code(engine?.startEchoTest(withInterval: intervalInSeconds.intValue)) + return + } + if let config = (params["config"] as? [String: Any]) { + callback.code(engine?.startEchoTest(withConfig: mapToEchoTestConfiguration(config))) + return + } + callback.code(engine?.startEchoTest()) } @objc func stopEchoTest(_ callback: Callback) { @@ -788,7 +978,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! Dictionary))) + callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! [String: Any]))) } @objc func stopLastmileProbeTest(_ callback: Callback) { @@ -829,7 +1019,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! Dictionary))) + callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! [String: Any]))) } @objc func clearVideoWatermarks(_ callback: Callback) { @@ -841,10 +1031,28 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setEncryptionMode(params["encryptionMode"] as? String)) + var encryptionMode = "" + switch (params["encryptionMode"] as! NSNumber).intValue { + case AgoraEncryptionMode.AES128XTS.rawValue: + encryptionMode = "aes-128-xts" + case AgoraEncryptionMode.AES128ECB.rawValue: + encryptionMode = "aes-128-ecb" + case AgoraEncryptionMode.AES256XTS.rawValue: + encryptionMode = "aes-256-xts" + default: encryptionMode = "" + } + callback.code(engine?.setEncryptionMode(encryptionMode)) + } + + @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) } @objc func startAudioRecording(_ params: NSDictionary, _ callback: Callback) { + if let config = params["config"] as? [String: Any] { + callback.code(engine?.startAudioRecording(withConfig: mapToAudioRecordingConfiguration(config))) + return + } callback.code(engine?.startAudioRecording(params["filePath"] as! String, sampleRate: (params["sampleRate"] as! NSNumber).intValue, quality: AgoraAudioRecordingQuality(rawValue: (params["quality"] as! NSNumber).intValue)!)) } @@ -853,7 +1061,7 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! Dictionary))) + callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) } @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { @@ -877,7 +1085,9 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func isCameraFocusSupported(_ callback: Callback) { - callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) + callback.resolve(engine) { + $0.isCameraFocusPositionInPreviewSupported() + } } @objc func isCameraExposurePositionSupported(_ callback: Callback) { @@ -935,15 +1145,84 @@ class RtcEngineManager: NSObject, RtcEngineInterface { } @objc func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) { - callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! Dictionary))) + callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! [String: Any]))) } @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { var streamId = 0 - callback.code(engine?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in streamId } + if let config = params["config"] as? [String: Any] { + callback.code(engine?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in + streamId + } + return + } + callback.code(engine?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in + streamId + } } @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { callback.code(engine?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) } + + @objc func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceBeautifierParameters(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) + } + + @objc func getSdkVersion(_ callback: Callback) { + callback.success(AgoraRtcEngineKit.getSdkVersion()) + } + + @objc func getErrorDescription(_ params: NSDictionary, _ callback: Callback) { + callback.success(AgoraRtcEngineKit.getErrorDescription((params["error"] as! NSNumber).intValue)) + } + + @objc func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableDeepLearningDenoise(params["enabled"] as! Bool)) + } + + @objc func setCloudProxy(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setCloudProxy(AgoraCloudProxyType(rawValue: (params["proxyType"] as! NSNumber).uintValue)!)) + } + + @objc func uploadLogFile(_ callback: Callback) { + callback.resolve(engine) { + $0.uploadLogFile() + } + } + + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enabled"] as! Bool)) + } + + @objc func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) { + let list = params["ips"] as! [Any] + var ips: [String] = [] + for i in list.indices { + if let item = list[i] as? String { + ips.append(item) + } + } + callback.code(engine?.setLocalAccessPoint(ips, domain: params["domain"] as! String)) + } + + @objc func pauseAllChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.pauseAllChannelMediaRelay()) + } + + @objc func resumeAllChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.resumeAllChannelMediaRelay()) + } + + @objc func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableVirtualBackground(params["enabled"] as! Bool, backData: mapToVirtualBackgroundSource(params["backgroundSource"] as! [String: Any]))) + } + + @objc func takeSnapshot(_ params: NSDictionary, _ callback: Callback) { + var code: Int32? + if let ret = engine?.takeSnapshot(params["channel"] as! String, uid: (params["uid"] as! NSNumber).intValue, filePath: params["filePath"] as! String) { + code = Int32(ret); + } + callback.code(code) + } } diff --git a/RtcEngineEvent.swift b/RtcEngineEvent.swift index d8de1ea50..dd4f555ed 100644 --- a/RtcEngineEvent.swift +++ b/RtcEngineEvent.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class RtcEngineEvents { static let Warning = "Warning" @@ -36,6 +36,7 @@ class RtcEngineEvents { static let LocalVideoStateChanged = "LocalVideoStateChanged" static let RemoteAudioStateChanged = "RemoteAudioStateChanged" static let LocalAudioStateChanged = "LocalAudioStateChanged" + static let RequestAudioFileInfo = "RequestAudioFileInfo" static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" static let AudioRouteChanged = "AudioRouteChanged" @@ -80,8 +81,20 @@ class RtcEngineEvents { static let CameraReady = "CameraReady" static let VideoStopped = "VideoStopped" static let MetadataReceived = "MetadataReceived" - - static func toMap() -> Dictionary { + static let FirstLocalAudioFramePublished = "FirstLocalAudioFramePublished" + static let FirstLocalVideoFramePublished = "FirstLocalVideoFramePublished" + static let AudioPublishStateChanged = "AudioPublishStateChanged" + static let VideoPublishStateChanged = "VideoPublishStateChanged" + static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + static let RtmpStreamingEvent = "RtmpStreamingEvent" + static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + static let UploadLogResult = "UploadLogResult" + static let AirPlayIsConnected = "AirPlayIsConnected" + static let VirtualBackgroundSourceEnabled = "VirtualBackgroundSourceEnabled" + static let SnapshotTaken = "SnapshotTaken" + + static func toMap() -> [String: String] { return [ "Warning": Warning, "Error": Error, @@ -109,6 +122,7 @@ class RtcEngineEvents { "LocalVideoStateChanged": LocalVideoStateChanged, "RemoteAudioStateChanged": RemoteAudioStateChanged, "LocalAudioStateChanged": LocalAudioStateChanged, + "RequestAudioFileInfo": RequestAudioFileInfo, "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, "AudioRouteChanged": AudioRouteChanged, @@ -153,6 +167,18 @@ class RtcEngineEvents { "CameraReady": CameraReady, "VideoStopped": VideoStopped, "MetadataReceived": MetadataReceived, + "FirstLocalAudioFramePublished": FirstLocalAudioFramePublished, + "FirstLocalVideoFramePublished": FirstLocalVideoFramePublished, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, + "UploadLogResult": UploadLogResult, + "AirPlayIsConnected": AirPlayIsConnected, + "VirtualBackgroundSourceEnabled": VirtualBackgroundSourceEnabled, + "SnapshotTaken": SnapshotTaken, ] } } @@ -160,9 +186,9 @@ class RtcEngineEvents { class RtcEngineEventHandler: NSObject { static let PREFIX = "io.agora.rtc." - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void - init(emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { self.emitter = emitter } @@ -172,287 +198,339 @@ class RtcEngineEventHandler: NSObject { } extension RtcEngineEventHandler: AgoraRtcEngineDelegate { - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { callback(RtcEngineEvents.Warning, warningCode.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { callback(RtcEngineEvents.Error, errorCode.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { + public func rtcEngine(_: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { callback(RtcEngineEvents.ApiCallExecuted, error, api, result) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.JoinChannelSuccess, channel, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { + public func rtcEngine(_: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { callback(RtcEngineEvents.LeaveChannel, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { callback(RtcEngineEvents.LocalUserRegistered, uid, userAccount) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { callback(RtcEngineEvents.UserInfoUpdated, uid, userInfo.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + public func rtcEngine(_: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { callback(RtcEngineEvents.ClientRoleChanged, oldRole.rawValue, newRole.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.UserJoined, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + public func rtcEngine(_: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { callback(RtcEngineEvents.UserOffline, uid, reason.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + public func rtcEngine(_: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { callback(RtcEngineEvents.ConnectionStateChanged, state.rawValue, reason.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { + public func rtcEngine(_: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { callback(RtcEngineEvents.NetworkTypeChanged, type.rawValue) } - public func rtcEngineConnectionDidLost(_ engine: AgoraRtcEngineKit) { + public func rtcEngineConnectionDidLost(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.ConnectionLost) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { + public func rtcEngine(_: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { callback(RtcEngineEvents.TokenPrivilegeWillExpire, token) } - public func rtcEngineRequestToken(_ engine: AgoraRtcEngineKit) { + public func rtcEngineRequestToken(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.RequestToken) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { callback(RtcEngineEvents.AudioVolumeIndication, speakers.toMapList(), totalVolume) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { callback(RtcEngineEvents.ActiveSpeaker, speakerUid) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { callback(RtcEngineEvents.FirstLocalAudioFrame, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { callback(RtcEngineEvents.FirstLocalVideoFrame, Int(size.width), Int(size.height), elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserMuteVideo, uid, muted) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { callback(RtcEngineEvents.VideoSizeChanged, uid, Int(size.width), Int(size.height), rotation) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { callback(RtcEngineEvents.RemoteVideoStateChanged, uid, state.rawValue, reason.rawValue, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { callback(RtcEngineEvents.LocalVideoStateChanged, state.rawValue, error.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { callback(RtcEngineEvents.RemoteAudioStateChanged, uid, state.rawValue, reason.rawValue, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { callback(RtcEngineEvents.LocalAudioStateChanged, state.rawValue, error.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { + public func rtcEngine(_ engine: AgoraRtcEngineKit, didRequest info: AgoraRtcAudioFileInfo, error: AgoraAudioFileInfoError) { + callback(RtcEngineEvents.RequestAudioFileInfo, info.toMap(), error.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { callback(RtcEngineEvents.LocalPublishFallbackToAudioOnly, isFallbackOrRecover) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { callback(RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, uid, isFallbackOrRecover) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { + public func rtcEngine(_: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { callback(RtcEngineEvents.AudioRouteChanged, routing.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { + public func rtcEngine(_: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { callback(RtcEngineEvents.CameraFocusAreaChanged, rect.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { + public func rtcEngine(_: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { callback(RtcEngineEvents.CameraExposureAreaChanged, rect.toMap()) } - func rtcEngine(_ engine: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { + public func rtcEngine(_: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { callback(RtcEngineEvents.FacePositionChanged, width, height, faces?.toMapList()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { + public func rtcEngine(_: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { callback(RtcEngineEvents.RtcStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { + public func rtcEngine(_: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { callback(RtcEngineEvents.LastmileQuality, quality.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + public func rtcEngine(_: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { callback(RtcEngineEvents.NetworkQuality, uid, txQuality.rawValue, rxQuality.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { + public func rtcEngine(_: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { callback(RtcEngineEvents.LastmileProbeResult, result.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { callback(RtcEngineEvents.LocalVideoStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { callback(RtcEngineEvents.LocalAudioStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { callback(RtcEngineEvents.RemoteVideoStats, stats.toMap()) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { callback(RtcEngineEvents.RemoteAudioStats, stats.toMap()) } - public func rtcEngineLocalAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { + public func rtcEngineLocalAudioMixingDidFinish(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.AudioMixingFinished) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, errorCode: AgoraAudioMixingErrorCode) { - callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, errorCode.rawValue) + public func rtcEngine(_: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) { + callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, reason.rawValue) } - public func rtcEngineRemoteAudioMixingDidStart(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android + public func rtcEngineRemoteAudioMixingDidStart(_: AgoraRtcEngineKit) { + // TODO: Not in Android } - public func rtcEngineRemoteAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android + public func rtcEngineRemoteAudioMixingDidFinish(_: AgoraRtcEngineKit) { + // TODO: Not in Android } - public func rtcEngineDidAudioEffectFinish(_ engine: AgoraRtcEngineKit, soundId: Int) { + public func rtcEngineDidAudioEffectFinish(_: AgoraRtcEngineKit, soundId: Int) { callback(RtcEngineEvents.AudioEffectFinished, soundId) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state.rawValue, errorCode.rawValue) } - public func rtcEngineTranscodingUpdated(_ engine: AgoraRtcEngineKit) { + public func rtcEngineTranscodingUpdated(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.TranscodingUpdated) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + public func rtcEngine(_: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { callback(RtcEngineEvents.StreamInjectedStatus, url, uid, status.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + public func rtcEngine(_: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { callback(RtcEngineEvents.StreamMessage, uid, streamId, String(data: data, encoding: .utf8)) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { callback(RtcEngineEvents.StreamMessageError, uid, streamId, error, missed, cached) } - public func rtcEngineMediaEngineDidLoaded(_ engine: AgoraRtcEngineKit) { + public func rtcEngineMediaEngineDidLoaded(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.MediaEngineLoadSuccess) } - public func rtcEngineMediaEngineDidStartCall(_ engine: AgoraRtcEngineKit) { + public func rtcEngineMediaEngineDidStartCall(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.MediaEngineStartCallSuccess) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + public func rtcEngine(_: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state.rawValue, error.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { + public func rtcEngine(_: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { callback(RtcEngineEvents.ChannelMediaRelayEvent, event.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteVideoFrame, uid, Int(size.width), Int(size.height), elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteAudioFrame, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid, elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserMuteAudio, uid, muted) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { + public func rtcEngine(_: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { callback(RtcEngineEvents.StreamPublished, url, errorCode.rawValue) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { + public func rtcEngine(_: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { callback(RtcEngineEvents.StreamUnpublished, url) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { callback(RtcEngineEvents.RemoteAudioTransportStats, uid, delay, lost, rxKBitRate) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { callback(RtcEngineEvents.RemoteVideoTransportStats, uid, delay, lost, rxKBitRate) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserEnableVideo, uid, enabled) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { callback(RtcEngineEvents.UserEnableLocalVideo, uid, enabled) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid, Int(size.width), Int(size.height), elapsed) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { + public func rtcEngine(_: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { callback(RtcEngineEvents.MicrophoneEnabled, enabled) } - public func rtcEngineConnectionDidInterrupted(_ engine: AgoraRtcEngineKit) { + public func rtcEngineConnectionDidInterrupted(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.ConnectionInterrupted) } - public func rtcEngineConnectionDidBanned(_ engine: AgoraRtcEngineKit) { + public func rtcEngineConnectionDidBanned(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.ConnectionBanned) } - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { + public func rtcEngine(_: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { callback(RtcEngineEvents.AudioQuality, uid, quality.rawValue, delay, lost) } - public func rtcEngineCameraDidReady(_ engine: AgoraRtcEngineKit) { + public func rtcEngineCameraDidReady(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.CameraReady) } - public func rtcEngineVideoDidStop(_ engine: AgoraRtcEngineKit) { + public func rtcEngineVideoDidStop(_: AgoraRtcEngineKit) { callback(RtcEngineEvents.VideoStopped) } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) { + callback(RtcEngineEvents.FirstLocalAudioFramePublished, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFramePublished elapsed: Int) { + callback(RtcEngineEvents.FirstLocalVideoFramePublished, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + callback(RtcEngineEvents.RtmpStreamingEvent, url, eventCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + callback(RtcEngineEvents.UserSuperResolutionEnabled, uid, enabled, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, uploadLogResultRequestId requestId: String, success: Bool, reason: AgoraUploadErrorReason) { + callback(RtcEngineEvents.UploadLogResult, requestId, success, reason.rawValue) + } + + public func rtcEngineAirPlayIsConnected(_ engine: AgoraRtcEngineKit) { + callback(RtcEngineEvents.AirPlayIsConnected) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, virtualBackgroundSourceEnabled enabled: Bool, reason: AgoraVirtualBackgroundSourceStateReason) { + callback(RtcEngineEvents.VirtualBackgroundSourceEnabled, enabled, reason.rawValue) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, snapshotTaken channel: String, uid: UInt, filePath: String, width: Int, height: Int, errCode: Int) { + callback(RtcEngineEvents.SnapshotTaken, channel, uid, filePath, width, height, errCode) + } } diff --git a/RtcEnginePlugin.h b/RtcEnginePlugin.h new file mode 100644 index 000000000..93d89eef8 --- /dev/null +++ b/RtcEnginePlugin.h @@ -0,0 +1,31 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A `RtcEnginePlugin` allows developers to interact with the `RtcEngine` which created from flutter + * side. + */ +@protocol RtcEnginePlugin + +/** + * This callback will be called when the `RtcEngine` is created by + [RtcEngine.createWithContext](https://docs.agora.io/cn/Video/API%20Reference/flutter/agora_rtc_engine/RtcEngine/createWithContext.html) + * function from flutter. + + * NOTE that you should not call `AgoraRtcEngineKit.destroy`, because it will also destroy the `RtcEngine` + * used by flutter side. + * + * @param rtcEngine The same `AgoraRtcEngineKit` used by flutter side + */ +- (void)onRtcEngineCreated:(AgoraRtcEngineKit *_Nullable)rtcEngine; + +/** + * This callback will be called when the [RtcEngine.destroy](https://docs.agora.io/cn/Video/API%20Reference/flutter/v4.0.7/rtc_channel/RtcChannel/destroy.html) + * function is called from flutter. + */ +- (void)onRtcEngineDestroyed; +@end + +NS_ASSUME_NONNULL_END diff --git a/RtcEnginePluginRegistrant.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/RtcEnginePluginRegistrantSwift.swift b/RtcEnginePluginRegistrantSwift.swift new file mode 100644 index 000000000..d6ef15334 --- /dev/null +++ b/RtcEnginePluginRegistrantSwift.swift @@ -0,0 +1,12 @@ +import Foundation + +@objc(RtcEnginePluginRegistrant) +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 89b4f9826..1cb7f72f9 100644 --- a/RtcSurfaceView.swift +++ b/RtcSurfaceView.swift @@ -1,14 +1,6 @@ -// -// RtcSurfaceView.swift -// RCTAgora -// -// Created by LXH on 2020/4/15. -// Copyright © 2020 Syan. All rights reserved. -// - +import AgoraRtcKit import Foundation import UIKit -import AgoraRtcKit class RtcSurfaceView: UIView { private var surface: UIView @@ -28,7 +20,8 @@ class RtcSurfaceView: UIView { return "frame" } - required init?(coder: NSCoder) { + @available(*, unavailable) + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -87,7 +80,7 @@ class RtcSurfaceView: UIView { if canvas.uid == 0 { engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) } else { - if let `channel` = channel { + if let channel = channel { channel.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) } else { engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) @@ -95,7 +88,7 @@ class RtcSurfaceView: UIView { } } - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { + override func observeValue(forKeyPath keyPath: String?, of _: Any?, change: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) { if keyPath == observerForKeyPath() { if let rect = change?[.newKey] as? CGRect { surface.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: rect.size)