From 8671a958604b9a0c5215010f5696031951f058ea Mon Sep 17 00:00:00 2001 From: HUI Date: Mon, 13 Dec 2021 19:45:45 +0800 Subject: [PATCH] Squashed 'ios/RCTAgora/Base/' changes from df4d47e..a7ddd5e a7ddd5e style: format 6db7748 feat: support 3.5.2 325c233 feat: support 3.5.1 & plugin d4e2686 fix: mapToEncryptionConfig crash f4be532 fix: compiler error 4eb127f chore: support 3.5.0.2 3c32dc5 chore: add API which is missing 3bb9210 fix: API call error 732df69 feat: support 3.4.6 782ec46 chore: prepare to migrate to iris ba7fba7 chore: support 3.4.5 f25a603 fix: startAudioRecording bug 02b6cc3 chore: optimize startAudioRecording 88b3d59 style: format code b60a451 Merge pull request #6 from AgoraLibrary/main/3.4.+ d1561f7 feat(upgrade): 3.4.1 bb84006 Merge pull request #5 from AgoraLibrary/main/3.3.+ 4623dc3 fix: getErrorDescription key error ee40ba1 Merge pull request #4 from AgoraLibrary/dev/3.3.0 f8bde68 Merge branch 'master' into dev/3.3.0 0db518f Merge pull request #3 from AgoraLibrary/dev/3.2.0 5f69768 Merge branch 'master' into dev/3.2.0 d355c51 Merge pull request #2 from AgoraLibrary/dev/3.1.0 b87cce2 fix: merge some bug fix a81db07 fix: merge some bug fix 2d1ac8f fix: iOS selector error 98c4331 fix: type cast error 836f3b4 feat: support 3.3.1 for iOS b422ce8 feat: support 3.3.0 for iOS c8a08e5 Merge branch 'master' into dev/3.2.0 a290e73 fix: use the better way to fix rendering problems 56ab25b fix: `MetadataReceived` event parameters bug daefc68 style: use shorthand arguments for lambda 561b3fd Merge branch 'master' into dev/3.2.0 12e2561 fix: some rendering problems when change render widget order 6f52bef Merge commit 'c8845fe04c1596fe2e7242302bf160bc671910cb' into rc/3.1.+ da3222a Merge branch 'master' into dev/3.2.0 c8845fe fix: `RtcSurfaceView` memory leak 3a55997 feat: add `setClientRole(role: ClientRole, options?: ClientRoleOptions): Promise` 4ee51a9 feat: upgrade to 3.2.0 73f3a32 Merge remote-tracking branch 'origin/dev/raw_data' into dev/raw_data 374f3e9 feat: iOS raw data plugin cd09ccc iOS raw data plugin 12cf9cf * fix `setDefaultAudioRoutetoSpeakerphone` crash bug * add `setAudioSessionOperationRestriction` and `sendCustomReportMessage` method fc1e7e0 finish c034b86 iOS finished efe8898 Merge commit 'dbb223a1b79dc10717c0feb6127060eef66a895f' into rc/3.1.2 9e9ecfa - fix `Xcode10` `Swift4` compile error dbb223a * fix iOS `FirstLocalVideoFrame` `VideoSizeChanged` `FirstRemoteVideoFrame` `FirstRemoteVideoDecoded` bug d2c9afa - fix crash when rendering view without `channelId` property - fix `RtcLocalView` freezes after rendering remote view 6eec86f - fix multiple channel render bug - remove `Types` from export, you can import enum or class by `import {} from 'react-native-agora'` cab5a62 - add `startPreview` `stopPreview` e8a38b1 - add `constructor` for typescript - fix Android `mapToChannelMediaInfo` crash - fix iOS `switchChannel` `sendMetadata` crash a2b9df7 iOS finish 13282b6 iOS engine finish 65b7f70 fix bug from issue: https://github.com/syanbo/react-native-agora/issues/213 upgrade to 3.0.1 git-subtree-dir: ios/RCTAgora/Base git-subtree-split: a7ddd5e7463d720db83744c29a5982d154ddd39b --- .gitignore | 1 + AgoraRtcEngineKit.h | 69 +- BeanCovertor.swift | 406 +++++--- Callback.swift | 32 +- Extensions.swift | 120 ++- MediaObserver.swift | 22 +- RtcChannel.swift | 440 ++++++--- RtcChannelEvent.swift | 249 +++++ RtcChannelEventHandler.swift | 177 ---- RtcEngine.swift | 1287 ++++++++++++++++++++------ RtcEngineEvent.swift | 536 +++++++++++ RtcEngineEventHandler.swift | 377 -------- RtcEnginePlugin.h | 31 + RtcEnginePluginRegistrant.h | 25 + RtcEnginePluginRegistrant.m | 22 + RtcEnginePluginRegistrantSwift.swift | 11 + RtcEngineRegistry.swift | 61 ++ RtcSurfaceView.swift | 103 ++- 18 files changed, 2761 insertions(+), 1208 deletions(-) create mode 100644 .gitignore create mode 100644 RtcChannelEvent.swift delete mode 100644 RtcChannelEventHandler.swift create mode 100644 RtcEngineEvent.swift delete mode 100644 RtcEngineEventHandler.swift create mode 100644 RtcEnginePlugin.h create mode 100644 RtcEnginePluginRegistrant.h create mode 100644 RtcEnginePluginRegistrant.m create mode 100644 RtcEnginePluginRegistrantSwift.swift create mode 100644 RtcEngineRegistry.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..9f11b755a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/AgoraRtcEngineKit.h b/AgoraRtcEngineKit.h index 7af94d48b..cebf95c80 100644 --- a/AgoraRtcEngineKit.h +++ b/AgoraRtcEngineKit.h @@ -9,40 +9,47 @@ #import typedef NS_ENUM(NSUInteger, AgoraRtcQualityReportFormat) { - AgoraRtc_QualityReportFormat_Json = 0, - AgoraRtc_QualityReportFormat_Html = 1, + AgoraRtc_QualityReportFormat_Json = 0, + AgoraRtc_QualityReportFormat_Html = 1, }; typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { - AgoraRtc_APP_TYPE_NATIVE = 0, - AgoraRtc_APP_TYPE_COCOS = 1, - AgoraRtc_APP_TYPE_UNITY = 2, - AgoraRtc_APP_TYPE_ELECTRON = 3, - AgoraRtc_APP_TYPE_FLUTTER = 4, - AgoraRtc_APP_TYPE_UNREAL = 5, - AgoraRtc_APP_TYPE_XAMARIN = 6, - AgoraRtc_APP_TYPE_APICLOUD = 7, - AgoraRtc_APP_TYPE_REACTNATIVE = 8 + AgoraRtc_APP_TYPE_NATIVE = 0, + AgoraRtc_APP_TYPE_COCOS = 1, + AgoraRtc_APP_TYPE_UNITY = 2, + AgoraRtc_APP_TYPE_ELECTRON = 3, + AgoraRtc_APP_TYPE_FLUTTER = 4, + AgoraRtc_APP_TYPE_UNREAL = 5, + AgoraRtc_APP_TYPE_XAMARIN = 6, + AgoraRtc_APP_TYPE_APICLOUD = 7, + AgoraRtc_APP_TYPE_REACTNATIVE = 8 }; @protocol AgoraRtcEngineExtensionDelegate @optional -- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine audioTransportQualityOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost; -- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine videoTransportQualityOfUid:(NSUInteger)uid delay:(NSUInteger)delay lost:(NSUInteger)lost; +- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine + audioTransportQualityOfUid:(NSUInteger)uid + delay:(NSUInteger)delay + lost:(NSUInteger)lost; +- (void)rtcEngine:(AgoraRtcEngineKit *_Nonnull)engine + videoTransportQualityOfUid:(NSUInteger)uid + delay:(NSUInteger)delay + lost:(NSUInteger)lost; @end @interface AgoraRtcEngineKit (AgoraExtension) -+ (instancetype _Nonnull)sharedEngineWithAppId:(NSString * _Nonnull)appId - extensionDelegate:(id _Nullable)delegate; ++ (instancetype _Nonnull)sharedEngineWithAppId:(NSString *_Nonnull)appId + extensionDelegate: + (id _Nullable) + delegate; /** Sets the profile to control the RTC engine. * * @param profile SDK profile in JSON format. * @param merge Whether to merge the profile data with the original value. */ -- (int)setProfile:(NSString * _Nonnull)profile - merge:(BOOL)merge; +- (int)setProfile:(NSString *_Nonnull)profile merge:(BOOL)merge; /** Set wrapper frame type by language wrapper. * @@ -54,7 +61,6 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { /** BEGIN OF AUDIO METHODS */ - /** * Enable recap * @@ -76,8 +82,7 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { andFrameRate:(NSInteger)frameRate andBitrate:(NSInteger)andBitrate; -- (int)sendReportData:(NSData * _Nonnull)data - type:(NSInteger)type; +- (int)sendReportData:(NSData *_Nonnull)data type:(NSInteger)type; /** END OF AUDIO METHODS */ /** Queries internal states @@ -85,22 +90,28 @@ typedef NS_ENUM(NSUInteger, AgoraRtcAppType) { * json string, array type * @return a json string */ -- (NSString * _Nullable)getParameters:(NSString * _Nonnull)parameters; +- (NSString *_Nullable)getParameters:(NSString *_Nonnull)parameters; /** - * Generates a URL linking to the call quality reports. @param channel The channel name specified in the joinChannel method. + * Generates a URL linking to the call quality reports. @param channel The + channel name specified in the joinChannel method. * @param listenerUid The uid of the listener. * @param speakerUid The uid of the speaker. * @param reportFormat The format of the report. - AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns the quality report data in Json. - AgoraRtc_QualityReportFormat_Html (1): HTML.: Returns a report in HTML format, displayed on a web browser or WebVIEW components. + AgoraRtc_QualityReportFormat_Json (0): JSON.: Returns + the quality report data in Json. AgoraRtc_QualityReportFormat_Html (1): HTML.: + Returns a report in HTML format, displayed on a web browser or WebVIEW + components. * - * @return 0 when executed successfully. return minus value when failed. return AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. + * @return 0 when executed successfully. return minus value when failed. return + AgoraRtc_Error_Invalid_Argument (-2):Invalid argument. return + AgoraRtc_Error_Buffer_Too_Small (-6):The buffer length is too small. */ -- (NSString * _Nullable)makeQualityReportUrl:(NSString * _Nonnull) channel - listenerUid:(NSUInteger)listenerUid - speakerrUid:(NSUInteger)speakerUid - reportFormat:(AgoraRtcQualityReportFormat)reportFormat; +- (NSString *_Nullable)makeQualityReportUrl:(NSString *_Nonnull)channel + listenerUid:(NSUInteger)listenerUid + speakerrUid:(NSUInteger)speakerUid + reportFormat: + (AgoraRtcQualityReportFormat)reportFormat; /********************************************************* * Large group conference call (experiment) - END diff --git a/BeanCovertor.swift b/BeanCovertor.swift index 359cc7046..ae6c5240f 100644 --- a/BeanCovertor.swift +++ b/BeanCovertor.swift @@ -6,189 +6,189 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation -func mapToPoint(map: Dictionary) -> CGPoint { +func mapToPoint(_ map: [String: Any]) -> CGPoint { var point = CGPoint() - if let x = map["x"] as? Int { - point.x = CGFloat(x) + if let x = map["x"] as? NSNumber { + point.x = CGFloat(truncating: x) } - if let y = map["y"] as? Int { - point.y = CGFloat(y) + if let y = map["y"] as? NSNumber { + point.y = CGFloat(truncating: y) } return point } -func mapToSize(map: Dictionary) -> CGSize { +func mapToSize(_ map: [String: Any]) -> CGSize { var size = CGSize() - if let width = map["width"] as? Int { - size.width = CGFloat(width) + if let width = map["width"] as? NSNumber { + size.width = CGFloat(truncating: width) } - if let height = map["height"] as? Int { - size.height = CGFloat(height) + if let height = map["height"] as? NSNumber { + size.height = CGFloat(truncating: height) } return size } -func mapToRect(map: Dictionary) -> CGRect { - CGRect( - origin: mapToPoint(map: map), - size: mapToSize(map: map) +func mapToRect(_ map: [String: Any]) -> CGRect { + return CGRect( + origin: mapToPoint(map), + size: mapToSize(map) ) } -func mapToVideoEncoderConfiguration(map: Dictionary) -> AgoraVideoEncoderConfiguration { +func mapToVideoEncoderConfiguration(_ map: [String: Any]) -> AgoraVideoEncoderConfiguration { let config = AgoraVideoEncoderConfiguration() - if let dimensions = map["dimensions"] as? Dictionary { - config.dimensions = mapToSize(map: dimensions) + if let dimensions = map["dimensions"] as? [String: Any] { + config.dimensions = mapToSize(dimensions) } - if let frameRate = map["frameRate"] as? Int { - config.frameRate = frameRate + if let frameRate = map["frameRate"] as? NSNumber { + config.frameRate = frameRate.intValue } - if let minFrameRate = map["minFrameRate"] as? Int { - config.minFrameRate = minFrameRate + if let minFrameRate = map["minFrameRate"] as? NSNumber { + config.minFrameRate = minFrameRate.intValue } - if let bitrate = map["bitrate"] as? Int { - config.bitrate = bitrate + if let bitrate = map["bitrate"] as? NSNumber { + config.bitrate = bitrate.intValue } - if let minBitrate = map["minBitrate"] as? Int { - config.minBitrate = minBitrate + if let minBitrate = map["minBitrate"] as? NSNumber { + config.minBitrate = minBitrate.intValue } - if let orientationMode = map["orientationMode"] as? Int { - if let orientationMode = AgoraVideoOutputOrientationMode(rawValue: orientationMode) { + if let orientationMode = map["orientationMode"] as? NSNumber { + if let orientationMode = AgoraVideoOutputOrientationMode(rawValue: orientationMode.intValue) { config.orientationMode = orientationMode } } - if let degradationPreference = map["degradationPrefer"] as? Int { - if let degradationPreference = AgoraDegradationPreference(rawValue: degradationPreference) { + if let degradationPreference = map["degradationPrefer"] as? NSNumber { + if let degradationPreference = AgoraDegradationPreference(rawValue: degradationPreference.intValue) { config.degradationPreference = degradationPreference } } - if let mirrorMode = map["mirrorMode"] as? Int { - if let mirrorMode = AgoraVideoMirrorMode(rawValue: UInt(mirrorMode)) { + if let mirrorMode = map["mirrorMode"] as? NSNumber { + if let mirrorMode = AgoraVideoMirrorMode(rawValue: mirrorMode.uintValue) { config.mirrorMode = mirrorMode } } return config } -func mapToBeautyOptions(map: Dictionary) -> AgoraBeautyOptions { +func mapToBeautyOptions(_ map: [String: Any]) -> AgoraBeautyOptions { let options = AgoraBeautyOptions() - if let lighteningContrastLevel = map["lighteningContrastLevel"] as? Int { - if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: UInt(lighteningContrastLevel)) { + if let lighteningContrastLevel = map["lighteningContrastLevel"] as? NSNumber { + if let lighteningContrastLevel = AgoraLighteningContrastLevel(rawValue: lighteningContrastLevel.uintValue) { options.lighteningContrastLevel = lighteningContrastLevel } } - if let lighteningLevel = map["lighteningLevel"] as? Float { - options.lighteningLevel = lighteningLevel + if let lighteningLevel = map["lighteningLevel"] as? NSNumber { + options.lighteningLevel = lighteningLevel.floatValue } - if let smoothnessLevel = map["smoothnessLevel"] as? Float { - options.smoothnessLevel = smoothnessLevel + if let smoothnessLevel = map["smoothnessLevel"] as? NSNumber { + options.smoothnessLevel = smoothnessLevel.floatValue } - if let rednessLevel = map["rednessLevel"] as? Float { - options.rednessLevel = rednessLevel + if let rednessLevel = map["rednessLevel"] as? NSNumber { + options.rednessLevel = rednessLevel.floatValue } return options } -func mapToAgoraImage(map: Dictionary) -> AgoraImage { +func mapToAgoraImage(_ map: [String: Any]) -> AgoraImage { let image = AgoraImage() if let url = map["url"] as? String { if let url = URL(string: url) { image.url = url } } - image.rect = mapToRect(map: map) + image.rect = mapToRect(map) return image } -func mapToTranscodingUser(map: Dictionary) -> AgoraLiveTranscodingUser { +func mapToTranscodingUser(_ map: [String: Any]) -> AgoraLiveTranscodingUser { let user = AgoraLiveTranscodingUser() - if let uid = map["uid"] as? Int { - user.uid = UInt(uid) + if let uid = map["uid"] as? NSNumber { + user.uid = uid.uintValue } - user.rect = mapToRect(map: map) - if let zOrder = map["zOrder"] as? Int { - user.zOrder = zOrder + user.rect = mapToRect(map) + if let zOrder = map["zOrder"] as? NSNumber { + user.zOrder = zOrder.intValue } - if let alpha = map["alpha"] as? Double { - user.alpha = alpha + if let alpha = map["alpha"] as? NSNumber { + user.alpha = alpha.doubleValue } - if let audioChannel = map["audioChannel"] as? Int { - user.audioChannel = audioChannel + if let audioChannel = map["audioChannel"] as? NSNumber { + user.audioChannel = audioChannel.intValue } return user } -func mapToColor(map: Dictionary) -> UIColor { - UIColor( - red: CGFloat(map["red"] as! Int), - green: CGFloat(map["green"] as! Int), - blue: CGFloat(map["blue"] as! Int), +func mapToColor(_ map: [String: Any]) -> UIColor { + return UIColor( + red: CGFloat((map["red"] as! NSNumber).intValue), + green: CGFloat((map["green"] as! NSNumber).intValue), + blue: CGFloat((map["blue"] as! NSNumber).intValue), alpha: 1.0 ) } -func mapToLiveTranscoding(map: Dictionary) -> AgoraLiveTranscoding { +func mapToLiveTranscoding(_ map: [String: Any]) -> AgoraLiveTranscoding { let transcoding = AgoraLiveTranscoding.default() - transcoding.size = mapToSize(map: map) - if let videoBitrate = map["videoBitrate"] as? Int { - transcoding.videoBitrate = videoBitrate + transcoding.size = mapToSize(map) + if let videoBitrate = map["videoBitrate"] as? NSNumber { + transcoding.videoBitrate = videoBitrate.intValue } - if let videoFramerate = map["videoFramerate"] as? Int { - transcoding.videoFramerate = videoFramerate + if let videoFramerate = map["videoFramerate"] as? NSNumber { + transcoding.videoFramerate = videoFramerate.intValue } if let lowLatency = map["lowLatency"] as? Bool { transcoding.lowLatency = lowLatency } - if let videoGop = map["videoGop"] as? Int { - transcoding.videoGop = videoGop + if let videoGop = map["videoGop"] as? NSNumber { + transcoding.videoGop = videoGop.intValue } - if let watermark = map["watermark"] as? Dictionary { - transcoding.watermark = mapToAgoraImage(map: watermark) + if let watermark = map["watermark"] as? [String: Any] { + transcoding.watermark = mapToAgoraImage(watermark) } - if let backgroundImage = map["backgroundImage"] as? Dictionary { - transcoding.backgroundImage = mapToAgoraImage(map: backgroundImage) + if let backgroundImage = map["backgroundImage"] as? [String: Any] { + transcoding.backgroundImage = mapToAgoraImage(backgroundImage) } - if let audioSampleRate = map["audioSampleRate"] as? Int { - if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate) { + if let audioSampleRate = map["audioSampleRate"] as? NSNumber { + if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate.intValue) { transcoding.audioSampleRate = audioSampleRate } } - if let audioBitrate = map["audioBitrate"] as? Int { - transcoding.audioBitrate = audioBitrate + if let audioBitrate = map["audioBitrate"] as? NSNumber { + transcoding.audioBitrate = audioBitrate.intValue } - if let audioChannels = map["audioChannels"] as? Int { - transcoding.audioChannels = audioChannels + if let audioChannels = map["audioChannels"] as? NSNumber { + transcoding.audioChannels = audioChannels.intValue } - if let audioCodecProfile = map["audioCodecProfile"] as? Int { - if let audioCodecProfile = AgoraAudioCodecProfileType(rawValue: audioCodecProfile) { + if let audioCodecProfile = map["audioCodecProfile"] as? NSNumber { + if let audioCodecProfile = AgoraAudioCodecProfileType(rawValue: audioCodecProfile.intValue) { transcoding.audioCodecProfile = audioCodecProfile } } - if let videoCodecProfile = map["videoCodecProfile"] as? Int { - if let videoCodecProfile = AgoraVideoCodecProfileType(rawValue: videoCodecProfile) { + if let videoCodecProfile = map["videoCodecProfile"] as? NSNumber { + if let videoCodecProfile = AgoraVideoCodecProfileType(rawValue: videoCodecProfile.intValue) { transcoding.videoCodecProfile = videoCodecProfile } } - if let backgroundColor = map["backgroundColor"] as? Dictionary { - transcoding.backgroundColor = mapToColor(map: backgroundColor) + if let backgroundColor = map["backgroundColor"] as? [String: Any] { + transcoding.backgroundColor = mapToColor(backgroundColor) } if let userConfigExtraInfo = map["userConfigExtraInfo"] as? String { transcoding.transcodingExtraInfo = userConfigExtraInfo } - if let transcodingUsers = map["transcodingUsers"] as? Array { - transcodingUsers.forEach { (item) in - if let item = item as? Dictionary { - transcoding.add(mapToTranscodingUser(map: item)) + if let transcodingUsers = map["transcodingUsers"] as? [Any] { + transcodingUsers.forEach { + if let item = $0 as? [String: Any] { + transcoding.add(mapToTranscodingUser(item)) } } } return transcoding } -func mapToChannelMediaInfo(map: Dictionary) -> AgoraChannelMediaRelayInfo { +func mapToChannelMediaInfo(_ map: [String: Any]) -> AgoraChannelMediaRelayInfo { let info = AgoraChannelMediaRelayInfo() if let channelName = map["channelName"] as? String { info.channelName = channelName @@ -196,21 +196,21 @@ func mapToChannelMediaInfo(map: Dictionary) -> AgoraChannelMediaRel if let token = map["token"] as? String { info.token = token } - if let uid = map["uid"] as? UInt { - info.uid = uid + if let uid = map["uid"] as? NSNumber { + info.uid = uid.uintValue } return info } -func mapToChannelMediaRelayConfiguration(map: Dictionary) -> AgoraChannelMediaRelayConfiguration { +func mapToChannelMediaRelayConfiguration(_ map: [String: Any]) -> AgoraChannelMediaRelayConfiguration { let config = AgoraChannelMediaRelayConfiguration() - if let srcInfo = map["srcInfo"] as? Dictionary { - config.sourceInfo = mapToChannelMediaInfo(map: srcInfo) + if let srcInfo = map["srcInfo"] as? [String: Any] { + config.sourceInfo = mapToChannelMediaInfo(srcInfo) } - if let destInfos = map["destInfos"] as? Array { - destInfos.forEach { (item) in - if let item = item as? Dictionary { - let info = mapToChannelMediaInfo(map: item) + if let destInfos = map["destInfos"] as? [Any] { + destInfos.forEach { + if let item = $0 as? [String: Any] { + let info = mapToChannelMediaInfo(item) config.setDestinationInfo(info, forChannelName: info.channelName ?? "") } } @@ -218,7 +218,7 @@ func mapToChannelMediaRelayConfiguration(map: Dictionary) -> AgoraC return config } -func mapToLastmileProbeConfig(map: Dictionary) -> AgoraLastmileProbeConfig { +func mapToLastmileProbeConfig(_ map: [String: Any]) -> AgoraLastmileProbeConfig { let config = AgoraLastmileProbeConfig() if let probeUplink = map["probeUplink"] as? Bool { config.probeUplink = probeUplink @@ -226,71 +226,77 @@ func mapToLastmileProbeConfig(map: Dictionary) -> AgoraLastmileProb if let probeDownlink = map["probeDownlink"] as? Bool { config.probeDownlink = probeDownlink } - if let expectedUplinkBitrate = map["expectedUplinkBitrate"] as? Int { - config.expectedUplinkBitrate = UInt(expectedUplinkBitrate) + if let expectedUplinkBitrate = map["expectedUplinkBitrate"] as? NSNumber { + config.expectedUplinkBitrate = expectedUplinkBitrate.uintValue } - if let expectedDownlinkBitrate = map["expectedDownlinkBitrate"] as? Int { - config.expectedDownlinkBitrate = UInt(expectedDownlinkBitrate) + if let expectedDownlinkBitrate = map["expectedDownlinkBitrate"] as? NSNumber { + config.expectedDownlinkBitrate = expectedDownlinkBitrate.uintValue } return config } -func mapToWatermarkOptions(map: Dictionary) -> WatermarkOptions { +func mapToWatermarkOptions(_ map: [String: Any]) -> WatermarkOptions { let options = WatermarkOptions() if let visibleInPreview = map["visibleInPreview"] as? Bool { options.visibleInPreview = visibleInPreview } - if let positionInLandscapeMode = map["positionInLandscapeMode"] as? Dictionary { - options.positionInLandscapeMode = mapToRect(map: positionInLandscapeMode) + if let positionInLandscapeMode = map["positionInLandscapeMode"] as? [String: Any] { + options.positionInLandscapeMode = mapToRect(positionInLandscapeMode) } - if let positionInPortraitMode = map["positionInPortraitMode"] as? Dictionary { - options.positionInPortraitMode = mapToRect(map: positionInPortraitMode) + if let positionInPortraitMode = map["positionInPortraitMode"] as? [String: Any] { + options.positionInPortraitMode = mapToRect(positionInPortraitMode) } return options } -func mapToLiveInjectStreamConfig(map: Dictionary) -> AgoraLiveInjectStreamConfig { +func mapToLiveInjectStreamConfig(_ map: [String: Any]) -> AgoraLiveInjectStreamConfig { let config = AgoraLiveInjectStreamConfig.default() - config.size = mapToSize(map: map) - if let videoGop = map["videoGop"] as? Int { - config.videoGop = videoGop + config.size = mapToSize(map) + if let videoGop = map["videoGop"] as? NSNumber { + config.videoGop = videoGop.intValue } - if let videoFramerate = map["videoFramerate"] as? Int { - config.videoFramerate = videoFramerate + if let videoFramerate = map["videoFramerate"] as? NSNumber { + config.videoFramerate = videoFramerate.intValue } - if let videoBitrate = map["videoBitrate"] as? Int { - config.videoBitrate = videoBitrate + if let videoBitrate = map["videoBitrate"] as? NSNumber { + config.videoBitrate = videoBitrate.intValue } - if let audioSampleRate = map["audioSampleRate"] as? Int { - if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate) { + if let audioSampleRate = map["audioSampleRate"] as? NSNumber { + if let audioSampleRate = AgoraAudioSampleRateType(rawValue: audioSampleRate.intValue) { config.audioSampleRate = audioSampleRate } } - if let audioBitrate = map["audioBitrate"] as? Int { - config.audioBitrate = audioBitrate + if let audioBitrate = map["audioBitrate"] as? NSNumber { + config.audioBitrate = audioBitrate.intValue } - if let audioChannels = map["audioChannels"] as? Int { - config.audioChannels = audioChannels + if let audioChannels = map["audioChannels"] as? NSNumber { + config.audioChannels = audioChannels.intValue } return config } -func mapToCameraCapturerConfiguration(map: Dictionary) -> AgoraCameraCapturerConfiguration { +func mapToCameraCapturerConfiguration(_ map: [String: Any]) -> AgoraCameraCapturerConfiguration { let config = AgoraCameraCapturerConfiguration() - if let preference = map["preference"] as? Int { - if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference) { + if let preference = map["preference"] as? NSNumber { + if let preference = AgoraCameraCaptureOutputPreference(rawValue: preference.intValue) { config.preference = preference } } - if let cameraDirection = map["cameraDirection"] as? Int { - if let cameraDirection = AgoraCameraDirection(rawValue: cameraDirection) { + if let captureWidth = map["captureWidth"] as? NSNumber { + config.captureWidth = captureWidth.int32Value + } + if let captureHeight = map["captureHeight"] as? NSNumber { + config.captureHeight = captureHeight.int32Value + } + if let cameraDirection = map["cameraDirection"] as? NSNumber { + if let cameraDirection = AgoraCameraDirection(rawValue: cameraDirection.intValue) { config.cameraDirection = cameraDirection } } return config } -func mapToChannelMediaOptions(map: Dictionary) -> AgoraRtcChannelMediaOptions { +func mapToChannelMediaOptions(_ map: [String: Any]) -> AgoraRtcChannelMediaOptions { let options = AgoraRtcChannelMediaOptions() if let autoSubscribeAudio = map["autoSubscribeAudio"] as? Bool { options.autoSubscribeAudio = autoSubscribeAudio @@ -298,5 +304,153 @@ func mapToChannelMediaOptions(map: Dictionary) -> AgoraRtcChannelMe if let autoSubscribeVideo = map["autoSubscribeVideo"] as? Bool { options.autoSubscribeVideo = autoSubscribeVideo } + if let publishLocalAudio = map["publishLocalAudio"] as? Bool { + options.publishLocalAudio = publishLocalAudio + } + if let publishLocalVideo = map["publishLocalVideo"] as? Bool { + options.publishLocalVideo = publishLocalVideo + } + return options +} + +func mapToRtcEngineConfig(_ map: [String: Any]) -> AgoraRtcEngineConfig { + let config = AgoraRtcEngineConfig() + config.appId = map["appId"] as? String + if let areaCode = map["areaCode"] as? NSNumber { + config.areaCode = areaCode.uintValue + } + if let logConfig = map["logConfig"] as? [String: Any] { + config.logConfig = mapToLogConfig(logConfig) + } + return config +} + +func mapToAudioRecordingConfiguration(_ map: [String: Any]) -> AgoraAudioRecordingConfiguration { + let config = AgoraAudioRecordingConfiguration() + if let filePath = map["filePath"] as? String { + config.filePath = filePath + } + if let recordingQuality = map["recordingQuality"] as? NSNumber { + if let recordingQuality = AgoraAudioRecordingQuality(rawValue: recordingQuality.intValue) { + config.recordingQuality = recordingQuality + } + } + if let recordingPosition = map["recordingPosition"] as? NSNumber { + if let recordingPosition = AgoraAudioRecordingPosition(rawValue: recordingPosition.intValue) { + config.recordingPosition = recordingPosition + } + } + if let recordingSampleRate = map["recordingSampleRate"] as? NSNumber { + config.recordingSampleRate = recordingSampleRate.intValue + } + return config +} + +func mapToEncryptionConfig(_ map: [String: Any]) -> AgoraEncryptionConfig { + let config = AgoraEncryptionConfig() + if let encryptionMode = map["encryptionMode"] as? NSNumber { + if let encryptionMode = AgoraEncryptionMode(rawValue: encryptionMode.intValue) { + config.encryptionMode = encryptionMode + } + } + if let encryptionKey = map["encryptionKey"] as? String { + config.encryptionKey = encryptionKey + } + if let list = map["encryptionKdfSalt"] as? [Any] { + var encryptionKdfSalt: [UInt8] = [] + for i in list.indices { + if let item = list[i] as? NSNumber { + encryptionKdfSalt.append(item.uint8Value) + } + } + config.encryptionKdfSalt = Data(bytes: encryptionKdfSalt) + } + return config +} + +func mapToRhythmPlayerConfig(_ map: [String: Any]) -> AgoraRtcRhythmPlayerConfig { + let config = AgoraRtcRhythmPlayerConfig() + if let beatsPerMeasure = map["beatsPerMeasure"] as? NSNumber { + config.beatsPerMeasure = beatsPerMeasure.uintValue + } + if let beatsPerMinute = map["beatsPerMinute"] as? NSNumber { + config.beatsPerMinute = beatsPerMinute.uintValue + } + if let publish = map["publish"] as? NSNumber { + config.publish = publish.boolValue + } + return config +} + +func mapToClientRoleOptions(_ map: [String: Any]) -> AgoraClientRoleOptions { + let options = AgoraClientRoleOptions() + if let audienceLatencyLevel = map["audienceLatencyLevel"] as? NSNumber { + if let audienceLatencyLevel = AgoraAudienceLatencyLevelType(rawValue: audienceLatencyLevel.intValue) { + options.audienceLatencyLevel = audienceLatencyLevel + } + } return options } + +func mapToLogConfig(_ map: [String: Any]) -> AgoraLogConfig { + let config = AgoraLogConfig() + config.filePath = map["filePath"] as? String + if let fileSize = map["fileSize"] as? NSNumber { + config.fileSize = fileSize.intValue + } + if let level = map["level"] as? NSNumber { + if let level = AgoraLogLevel(rawValue: level.intValue) { + config.level = level + } + } + return config +} + +func mapToDataStreamConfig(_ map: [String: Any]) -> AgoraDataStreamConfig { + let config = AgoraDataStreamConfig() + if let syncWithAudio = map["syncWithAudio"] as? Bool { + config.syncWithAudio = syncWithAudio + } + if let ordered = map["ordered"] as? Bool { + config.ordered = ordered + } + return config +} + +func mapToVirtualBackgroundSource(_ map: [String: Any]) -> AgoraVirtualBackgroundSource { + let backgroundSource = AgoraVirtualBackgroundSource() + if let backgroundSourceType = map["backgroundSourceType"] as? NSNumber { + if let backgroundSourceType = AgoraVirtualBackgroundSourceType(rawValue: backgroundSourceType.uintValue) { + backgroundSource.backgroundSourceType = backgroundSourceType + } + } + if let color = map["color"] as? [String: Any] { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + mapToColor(color).getRed(&red, green: &green, blue: &blue, alpha: &alpha) + backgroundSource.color = UInt(red * 255.0) << 16 + UInt(green * 255.0) << 8 + UInt(blue * 255.0) + } + backgroundSource.source = map["source"] as? String + if let blurDegree = map["blur_degree"] as? NSNumber { + if let blurDegree = AgoraBlurDegree(rawValue: blurDegree.uintValue) { + backgroundSource.blur_degree = blurDegree + } + } + return backgroundSource +} + +func mapToEchoTestConfiguration(_ map: [String: Any]) -> AgoraEchoTestConfiguration { + let config = AgoraEchoTestConfiguration() + if let enableAudio = map["enableAudio"] as? NSNumber { + config.enableAudio = enableAudio.boolValue + } + if let enableVideo = map["enableVideo"] as? NSNumber { + config.enableVideo = enableVideo.boolValue + } + if let token = map["token"] as? String { + config.token = token + } + if let channelId = map["channelId"] as? String { + config.channelId = channelId + } + return config +} diff --git a/Callback.swift b/Callback.swift index 562777cae..8c5bc130a 100644 --- a/Callback.swift +++ b/Callback.swift @@ -6,24 +6,36 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation +@objc protocol Callback: class { - associatedtype T - - func success(_ data: Self.T?) + func success(_ data: Any?) func failure(_ code: String, _ message: String) } extension Callback { - func code(_ code: Int32?) { - let newCode: Int = Int(code ?? Int32(AgoraErrorCode.notInitialized.rawValue)) - if newCode == 0 { - success(nil) - } else if newCode < 0 { - failure(String(newCode), AgoraRtcEngineKit.getErrorDescription(abs(newCode)) ?? "") + func code(_ code: Int32?, _ runnable: ((Int32?) -> Any?)? = nil) { + if code == nil || code! < 0 { + let newCode = abs(Int(code ?? Int32(AgoraErrorCode.notInitialized.rawValue))) + failure(String(newCode), AgoraRtcEngineKit.getErrorDescription(newCode) ?? "") + return + } + + let res = runnable?(code) + success(res) + } + + func resolve(_ source: T?, _ runnable: (T) -> Any?) { + guard let source = source else { + let code = AgoraErrorCode.notInitialized.rawValue + failure(String(code), AgoraRtcEngineKit.getErrorDescription(code) ?? "") + return } + + let res = runnable(source) + success(res) } } diff --git a/Extensions.swift b/Extensions.swift index a4b22da0c..d3c6b9f9d 100644 --- a/Extensions.swift +++ b/Extensions.swift @@ -6,32 +6,33 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation extension AgoraUserInfo { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "uid": uid, - "userAccount": userAccount + "userAccount": userAccount, ] } } extension AgoraRtcLocalAudioStats { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "numChannels": numChannels, "sentSampleRate": sentSampleRate, - "sentBitrate": sentBitrate + "sentBitrate": sentBitrate, + "txPacketLossRate": txPacketLossRate, ] } } extension AgoraChannelStats { - func toMap() -> Dictionary { - [ - "totalDuration": duration, + func toMap() -> [String: Any?] { + return [ + "duration": duration, "txBytes": txBytes, "rxBytes": rxBytes, "txAudioBytes": txAudioBytes, @@ -44,7 +45,7 @@ extension AgoraChannelStats { "rxAudioKBitRate": rxAudioKBitrate, "txVideoKBitRate": txVideoKBitrate, "rxVideoKBitRate": rxVideoKBitrate, - "users": userCount, + "userCount": userCount, "lastmileDelay": lastmileDelay, "txPacketLossRate": txPacketLossRate, "rxPacketLossRate": rxPacketLossRate, @@ -53,25 +54,25 @@ extension AgoraChannelStats { "gatewayRtt": gatewayRtt, "memoryAppUsageRatio": memoryAppUsageRatio, "memoryTotalUsageRatio": memoryTotalUsageRatio, - "memoryAppUsageInKbytes": memoryAppUsageInKbytes + "memoryAppUsageInKbytes": memoryAppUsageInKbytes, ] } } extension CGRect { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "left": origin.x, "top": origin.y, "right": origin.x + size.width, - "bottom": origin.y + size.height + "bottom": origin.y + size.height, ] } } extension AgoraRtcRemoteAudioStats { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "uid": uid, "quality": quality, "networkTransportDelay": networkTransportDelay, @@ -81,14 +82,19 @@ extension AgoraRtcRemoteAudioStats { "receivedSampleRate": receivedSampleRate, "receivedBitrate": receivedBitrate, "totalFrozenTime": totalFrozenTime, - "frozenRate": frozenRate + "frozenRate": frozenRate, + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, + "qoeQuality": qoeQuality, + "qualityChangedReason": qualityChangedReason, + "mosValue": mosValue, ] } } extension AgoraRtcLocalVideoStats { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "sentBitrate": sentBitrate, "sentFrameRate": sentFrameRate, "encoderOutputFrameRate": encoderOutputFrameRate, @@ -100,14 +106,17 @@ extension AgoraRtcLocalVideoStats { "encodedFrameWidth": encodedFrameWidth, "encodedFrameHeight": encodedFrameHeight, "encodedFrameCount": encodedFrameCount, - "codecType": codecType.rawValue + "codecType": codecType.rawValue, + "txPacketLossRate": txPacketLossRate, + "captureFrameRate": captureFrameRate, + "captureBrightnessLevel": captureBrightnessLevel.rawValue, ] } } extension AgoraRtcRemoteVideoStats { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "uid": uid, "delay": delay, "width": width, @@ -118,51 +127,82 @@ extension AgoraRtcRemoteVideoStats { "packetLossRate": packetLossRate, "rxStreamType": rxStreamType.rawValue, "totalFrozenTime": totalFrozenTime, - "frozenRate": frozenRate + "frozenRate": frozenRate, + "totalActiveTime": totalActiveTime, + "publishDuration": publishDuration, ] } } extension AgoraRtcAudioVolumeInfo { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "uid": uid, "volume": volume, "vad": vad, - "channelId": channelId + "channelId": channelId, ] } } -typealias AudioVolumeArray = Array - -extension AudioVolumeArray { - func toMapList() -> Array> { - var list = [Dictionary]() - forEach { (item) in - list.append(item.toMap()) +extension Array where Element: AgoraRtcAudioVolumeInfo { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { + list.append($0.toMap()) } return list } } extension AgoraLastmileProbeOneWayResult { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "packetLossRate": packetLossRate, "jitter": jitter, - "availableBandwidth": availableBandwidth + "availableBandwidth": availableBandwidth, ] } } extension AgoraLastmileProbeResult { - func toMap() -> Dictionary { - [ + func toMap() -> [String: Any?] { + return [ "state": state.rawValue, "rtt": rtt, "uplinkReport": uplinkReport.toMap(), - "downlinkReport": downlinkReport.toMap() + "downlinkReport": downlinkReport.toMap(), ] } } + +extension AgoraFacePositionInfo { + func toMap() -> [String: Any?] { + return [ + "x": x, + "y": y, + "width": width, + "height": height, + "distance": distance, + ] + } +} + +extension AgoraRtcAudioFileInfo { + func toMap() -> [String: Any?] { + return [ + "filePath": filePath, + "durationMs": durationMs, + ] + } +} + +extension Array where Element: AgoraFacePositionInfo { + func toMapList() -> [[String: Any?]] { + var list = [[String: Any?]]() + forEach { + list.append($0.toMap()) + } + return list + } +} diff --git a/MediaObserver.swift b/MediaObserver.swift index 162241532..514fb21d0 100644 --- a/MediaObserver.swift +++ b/MediaObserver.swift @@ -6,33 +6,33 @@ // Copyright © 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation class MediaObserver: NSObject { - private var emitter: (_ methodName: String, _ data: Dictionary?) -> Void - private var maxMetadataSize = 0 + private var emitter: (_ data: [String: Any?]?) -> Void + private var maxMetadataSize = 1024 private var metadataList = [String]() - init(emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { + init(_ emitter: @escaping (_ data: [String: Any?]?) -> Void) { self.emitter = emitter } - func addMetadata(metadata: String) { + func addMetadata(_ metadata: String) { metadataList.append(metadata) } - func setMaxMetadataSize(size: Int) { + func setMaxMetadataSize(_ size: Int) { maxMetadataSize = size } } extension MediaObserver: AgoraMediaMetadataDataSource { func metadataMaxSize() -> Int { - maxMetadataSize + return maxMetadataSize } - func readyToSendMetadata(atTimestamp timestamp: TimeInterval) -> Data? { + func readyToSendMetadata(atTimestamp _: TimeInterval) -> Data? { if metadataList.count > 0 { return metadataList.remove(at: 0).data(using: .utf8) } @@ -42,10 +42,8 @@ extension MediaObserver: AgoraMediaMetadataDataSource { extension MediaObserver: AgoraMediaMetadataDelegate { func receiveMetadata(_ data: Data, fromUser uid: Int, atTimestamp timestamp: TimeInterval) { - emitter("MetadataReceived", [ - "buffer": String(data: data, encoding: .utf8), - "uid": uid, - "timeStampMs": timestamp + emitter([ + "data": [String(data: data, encoding: .utf8) ?? "", uid, timestamp], ]) } } diff --git a/RtcChannel.swift b/RtcChannel.swift index 2f1918e55..221779ffe 100644 --- a/RtcChannel.swift +++ b/RtcChannel.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation protocol RtcChannelInterface: RtcChannelAudioInterface, @@ -21,63 +21,137 @@ protocol RtcChannelInterface: RtcChannelEncryptionInterface, RtcChannelInjectStreamInterface, RtcChannelStreamMessageInterface { - associatedtype Map - associatedtype Callback + func create(_ params: NSDictionary, _ callback: Callback) + + func destroy(_ params: NSDictionary, _ callback: Callback) + + func setClientRole(_ params: NSDictionary, _ callback: Callback) + + func joinChannel(_ params: NSDictionary, _ callback: Callback) + + func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) + + func leaveChannel(_ params: NSDictionary, _ callback: Callback) + + func renewToken(_ params: NSDictionary, _ callback: Callback) + + func getConnectionState(_ params: NSDictionary, _ callback: Callback) + + @available(*, deprecated) + func publish(_ params: NSDictionary, _ callback: Callback) + + @available(*, deprecated) + func unpublish(_ params: NSDictionary, _ callback: Callback) + + func getCallId(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelAudioInterface { + func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) + + func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) + + func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) + + func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + + @available(*, deprecated) + func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelVideoInterface { + func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) - func create(_ channelId: String, _ callback: Callback?) + func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) - func destroy(_ channelId: String, _ callback: Callback?) + func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - func setClientRole(_ channelId: String, _ role: Int, _ callback: Callback?) + @available(*, deprecated) + func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) +} - func joinChannel(_ channelId: String, _ token: String?, _ optionalInfo: String?, _ optionalUid: Int, _ options: Map, _ callback: Callback?) +protocol RtcChannelVoicePositionInterface { + func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) +} - func joinChannelWithUserAccount(_ channelId: String, _ token: String?, _ userAccount: String, _ options: Map, _ callback: Callback?) +protocol RtcChannelPublishStreamInterface { + func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) - func leaveChannel(_ channelId: String, _ callback: Callback?) + func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) - func renewToken(_ channelId: String, _ token: String, _ callback: Callback?) + func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) +} - func getConnectionState(_ channelId: String, _ callback: Callback?) +protocol RtcChannelMediaRelayInterface { + func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func publish(_ channelId: String, _ callback: Callback?) + func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func unpublish(_ channelId: String, _ callback: Callback?) + func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func getCallId(_ channelId: String, _ callback: Callback?) + func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + + func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelDualStreamInterface { + func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) + + func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) } -class RtcChannelManager { +protocol RtcChannelFallbackInterface { + func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelMediaMetadataInterface { + func registerMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) + + func unregisterMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) + + func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) + + func sendMetadata(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelEncryptionInterface { + @available(*, deprecated) + func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) + + @available(*, deprecated) + func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) + + func enableEncryption(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelInjectStreamInterface { + func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) + + func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) +} + +protocol RtcChannelStreamMessageInterface { + func createDataStream(_ params: NSDictionary, _ callback: Callback) + + func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) +} + +@objc +class RtcChannelManager: NSObject, RtcChannelInterface { + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void private var rtcChannelMap = [String: AgoraRtcChannel]() private var rtcChannelDelegateMap = [String: RtcChannelEventHandler]() private var mediaObserverMap = [String: MediaObserver]() - func create(_ engine: AgoraRtcEngineKit, _ channelId: String, _ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - if let rtcChannel = engine.createRtcChannel(channelId) { - let delegate = RtcChannelEventHandler() { methodName, data in - emit(methodName, data) - } - rtcChannel.setRtcChannelDelegate(delegate) - rtcChannelMap[channelId] = rtcChannel - rtcChannelDelegateMap[channelId] = delegate - } - } - - func destroy(_ channelId: String) -> Int32 { - if let rtcChannel = self[channelId] { - let res = rtcChannel.destroy() - if (res == 0) { - rtcChannelMap.removeValue(forKey: channelId) - rtcChannelDelegateMap.removeValue(forKey: channelId) - } - return res - } - return Int32(AgoraErrorCode.notInitialized.rawValue) + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { + self.emitter = emitter } - func release() { - rtcChannelMap.forEach { key, value in - value.destroy() + func Release() { + rtcChannelMap.forEach { + $1.destroy() } rtcChannelMap.removeAll() rtcChannelDelegateMap.removeAll() @@ -85,153 +159,245 @@ class RtcChannelManager { } subscript(channelId: String) -> AgoraRtcChannel? { - get { - rtcChannelMap[channelId] - } + return rtcChannelMap[channelId] } - func registerMediaMetadataObserver(_ channelId: String, _ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) -> Int32 { - if let rtcChannel = self[channelId] { - let mediaObserver = MediaObserver() { methodName, data in - if var `data` = data { - data["channelId"] = channelId - emit(methodName, data) + @objc func create(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(params["engine"] as? AgoraRtcEngineKit) { [weak self] in + if let rtcChannel = $0.createRtcChannel(params["channelId"] as! String) { + let delegate = RtcChannelEventHandler { [weak self] in + self?.emitter($0, $1) } + rtcChannel.setRtcChannelDelegate(delegate) + self?.rtcChannelMap[rtcChannel.getId()!] = rtcChannel + self?.rtcChannelDelegateMap[rtcChannel.getId()!] = delegate } - let res = rtcChannel.setMediaMetadataDelegate(mediaObserver, with: .video) - if res { - mediaObserverMap[channelId] = mediaObserver - return 0 - } + return nil } - return Int32(AgoraErrorCode.notInitialized.rawValue) } - func unregisterMediaMetadataObserver(_ channelId: String) -> Int32 { - if let rtcChannel = self[channelId] { - let res = rtcChannel.setMediaMetadataDelegate(nil, with: .video) - if res { - mediaObserverMap.removeValue(forKey: channelId) - return 0 - } - } - return Int32(AgoraErrorCode.notInitialized.rawValue) + @objc func destroy(_ params: NSDictionary, _ callback: Callback) { + callback.code(rtcChannelMap.removeValue(forKey: params["channelId"] as! String)?.destroy()) } - func setMaxMetadataSize(_ channelId: String, _ size: Int) -> Int32 { - if let observer = mediaObserverMap[channelId] { - observer.setMaxMetadataSize(size: size) - return 0 + @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { + let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! + if let options = params["options"] as? [String: Any] { + callback.code(self[params["channelId"] as! String]?.setClientRole(role, options: mapToClientRoleOptions(options))) + return } - return Int32(AgoraErrorCode.notInitialized.rawValue) + callback.code(self[params["channelId"] as! String]?.setClientRole(role)) } - func addMetadata(_ channelId: String, _ metadata: String) -> Int32 { - if let observer = mediaObserverMap[channelId] { - observer.addMetadata(metadata: metadata) - return 0 - } - return Int32(AgoraErrorCode.notInitialized.rawValue) + @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.join(byToken: params["token"] as? String, info: params["optionalInfo"] as? String, uid: (params["optionalUid"] as! NSNumber).uintValue, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) } -} -protocol RtcChannelAudioInterface { - associatedtype Callback + @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.join(byUserAccount: params["userAccount"] as! String, token: params["token"] as? String, options: mapToChannelMediaOptions(params["options"] as! [String: Any]))) + } - func adjustUserPlaybackSignalVolume(_ channelId: String, _ uid: Int, _ volume: Int, _ callback: Callback?) + @objc func leaveChannel(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.leave()) + } - func muteRemoteAudioStream(_ channelId: String, _ uid: Int, _ muted: Bool, _ callback: Callback?) + @objc func renewToken(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.renewToken(params["token"] as! String)) + } - func muteAllRemoteAudioStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) + @objc func getConnectionState(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(self[params["channelId"] as! String]) { + $0.getConnectionState().rawValue + } + } - func setDefaultMuteAllRemoteAudioStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) -} + @objc func publish(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.publish()) + } -protocol RtcChannelVideoInterface { - associatedtype Callback + @objc func unpublish(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.unpublish()) + } - func muteRemoteVideoStream(_ channelId: String, _ uid: Int, _ muted: Bool, _ callback: Callback?) + @objc func getCallId(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(self[params["channelId"] as! String]) { + $0.getCallId() + } + } - func muteAllRemoteVideoStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) + @objc func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.adjustUserPlaybackSignalVolume((params["uid"] as! NSNumber).uintValue, volume: (params["volume"] as! NSNumber).int32Value)) + } - func setDefaultMuteAllRemoteVideoStreams(_ channelId: String, _ muted: Bool, _ callback: Callback?) -} + @objc func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteRemoteAudioStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } -protocol RtcChannelVoicePositionInterface { - associatedtype Callback + @objc func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteAllRemoteAudioStreams(params["muted"] as! Bool)) + } - func setRemoteVoicePosition(_ channelId: String, _ uid: Int, _ pan: Double, _ gain: Double, _ callback: Callback?) -} + @objc func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as! Bool)) + } -protocol RtcChannelPublishStreamInterface { - associatedtype Map - associatedtype Callback + @objc func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteRemoteVideoStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } - func setLiveTranscoding(_ channelId: String, _ transcoding: Map, _ callback: Callback?) + @objc func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteAllRemoteVideoStreams(params["muted"] as! Bool)) + } - func addPublishStreamUrl(_ channelId: String, _ url: String, _ transcodingEnabled: Bool, _ callback: Callback?) + @objc func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as! Bool)) + } - func removePublishStreamUrl(_ channelId: String, _ url: String, _ callback: Callback?) -} + @objc func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteVoicePosition((params["uid"] as! NSNumber).uintValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue)) + } -protocol RtcChannelMediaRelayInterface { - associatedtype Map - associatedtype Callback + @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) + } - func startChannelMediaRelay(_ channelId: String, _ channelMediaRelayConfiguration: Map, _ callback: Callback?) + @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.addPublishStreamUrl(params["url"] as! String, transcodingEnabled: params["transcodingEnabled"] as! Bool)) + } - func updateChannelMediaRelay(_ channelId: String, _ channelMediaRelayConfiguration: Map, _ callback: Callback?) + @objc func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.removePublishStreamUrl(params["url"] as! String)) + } - func stopChannelMediaRelay(_ channelId: String, _ callback: Callback?) -} + @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.startMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) + } -protocol RtcChannelDualStreamInterface { - associatedtype Callback + @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.updateMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) + } - func setRemoteVideoStreamType(_ channelId: String, _ uid: Int, _ streamType: Int, _ callback: Callback?) + @objc func stopChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.stopMediaRelay()) + } - func setRemoteDefaultVideoStreamType(_ channelId: String, _ streamType: Int, _ callback: Callback?) -} + @objc func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteVideoStream((params["uid"] as! NSNumber).uintValue, type: AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } -protocol RtcChannelFallbackInterface { - associatedtype Callback + @objc func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteDefaultVideoStreamType(AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } - func setRemoteUserPriority(_ channelId: String, _ uid: Int, _ userPriority: Int, _ callback: Callback?) -} + @objc func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setRemoteUserPriority((params["uid"] as! NSNumber).uintValue, type: AgoraUserPriority(rawValue: (params["userPriority"] as! NSNumber).intValue)!)) + } -protocol RtcChannelMediaMetadataInterface { - associatedtype Callback + @objc func registerMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) { + let channelId = params["channelId"] as! String + let mediaObserver = MediaObserver { [weak self] in + if var data = $0 { + data["channelId"] = channelId + self?.emitter(RtcEngineEvents.MetadataReceived, data) + } + } + callback.resolve(self[channelId]) { + if $0.setMediaMetadataDelegate(mediaObserver, with: .video) { + mediaObserverMap[channelId] = mediaObserver + } + return nil + } + } - func registerMediaMetadataObserver(_ channelId: String, _ callback: Callback?) + @objc func unregisterMediaMetadataObserver(_ params: NSDictionary, _ callback: Callback) { + let channelId = params["channelId"] as! String + callback.resolve(self[channelId]) { + if $0.setMediaMetadataDelegate(nil, with: .video) { + mediaObserverMap.removeValue(forKey: channelId) + } + return nil + } + } - func unregisterMediaMetadataObserver(_ channelId: String, _ callback: Callback?) + @objc func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserverMap[params["channelId"] as! String]) { + $0.setMaxMetadataSize((params["size"] as! NSNumber).intValue) + } + } - func setMaxMetadataSize(_ channelId: String, _ size: Int, _ callback: Callback?) + @objc func sendMetadata(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserverMap[params["channelId"] as! String]) { + $0.addMetadata(params["metadata"] as! String) + } + } - func sendMetadata(_ channelId: String, _ metadata: String, _ callback: Callback?) -} + @objc func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.setEncryptionSecret(params["secret"] as? String)) + } -protocol RtcChannelEncryptionInterface { - associatedtype Callback + @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { + var encryptionMode = "" + switch (params["encryptionMode"] as! NSNumber).intValue { + case AgoraEncryptionMode.AES128XTS.rawValue: + encryptionMode = "aes-128-xts" + case AgoraEncryptionMode.AES128ECB.rawValue: + encryptionMode = "aes-128-ecb" + case AgoraEncryptionMode.AES256XTS.rawValue: + encryptionMode = "aes-256-xts" + default: encryptionMode = "" + } + callback.code(self[params["channelId"] as! String]?.setEncryptionMode(encryptionMode)) + } - func setEncryptionSecret(_ channelId: String, _ secret: String, _ callback: Callback?) + @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) + } - func setEncryptionMode(_ channelId: String, _ encryptionMode: String, _ callback: Callback?) -} + @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) + } -protocol RtcChannelInjectStreamInterface { - associatedtype Map - associatedtype Callback + @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.removeInjectStreamUrl(params["url"] as! String)) + } - func addInjectStreamUrl(_ channelId: String, _ url: String, _ config: Map, _ callback: Callback?) + @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { + let channel = self[params["channelId"] as! String] + var streamId = 0 + if let config = params["config"] as? [String: Any] { + callback.code(channel?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in + streamId + } + return + } + callback.code(channel?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in + streamId + } + } - func removeInjectStreamUrl(_ channelId: String, _ url: String, _ callback: Callback?) -} + @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) + } -protocol RtcChannelStreamMessageInterface { - associatedtype Callback + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enable"] as! Bool)) + } - func createDataStream(_ channelId: String, _ reliable: Bool, _ ordered: Bool, _ callback: Callback?) + @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalAudioStream(params["muted"] as! Bool)) + } - func sendStreamMessage(_ channelId: String, _ streamId: Int, _ message: String, _ callback: Callback?) + @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(self[params["channelId"] as! String]?.muteLocalVideoStream(params["muted"] as! Bool)) + } + + @objc func pauseAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) +// callback.code(self[params["channelId"] as! String]?.pauseAllChannelMediaRelay()) + } + + @objc func resumeAllChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) +// callback.code(self[params["channelId"] as! String]?.resumeAllChannelMediaRelay()) + } } diff --git a/RtcChannelEvent.swift b/RtcChannelEvent.swift new file mode 100644 index 000000000..eca5b4da8 --- /dev/null +++ b/RtcChannelEvent.swift @@ -0,0 +1,249 @@ +// +// RtcChannelEvent.swift +// RCTAgora +// +// Created by LXH on 2020/4/10. +// Copyright © 2020 Syan. All rights reserved. +// + +import AgoraRtcKit +import Foundation + +class RtcChannelEvents { + static let Warning = "Warning" + static let Error = "Error" + static let JoinChannelSuccess = "JoinChannelSuccess" + static let RejoinChannelSuccess = "RejoinChannelSuccess" + static let LeaveChannel = "LeaveChannel" + static let ClientRoleChanged = "ClientRoleChanged" + static let UserJoined = "UserJoined" + static let UserOffline = "UserOffline" + static let ConnectionStateChanged = "ConnectionStateChanged" + static let ConnectionLost = "ConnectionLost" + static let TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" + static let RequestToken = "RequestToken" + static let ActiveSpeaker = "ActiveSpeaker" + static let VideoSizeChanged = "VideoSizeChanged" + static let RemoteVideoStateChanged = "RemoteVideoStateChanged" + static let RemoteAudioStateChanged = "RemoteAudioStateChanged" + static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" + static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" + static let RtcStats = "RtcStats" + static let NetworkQuality = "NetworkQuality" + static let RemoteVideoStats = "RemoteVideoStats" + static let RemoteAudioStats = "RemoteAudioStats" + static let RtmpStreamingStateChanged = "RtmpStreamingStateChanged" + static let TranscodingUpdated = "TranscodingUpdated" + static let StreamInjectedStatus = "StreamInjectedStatus" + static let StreamMessage = "StreamMessage" + static let StreamMessageError = "StreamMessageError" + static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" + static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" + static let MetadataReceived = "MetadataReceived" + static let AudioPublishStateChanged = "AudioPublishStateChanged" + static let VideoPublishStateChanged = "VideoPublishStateChanged" + static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + static let RtmpStreamingEvent = "RtmpStreamingEvent" + static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + + static func toMap() -> [String: String] { + return [ + "Warning": Warning, + "Error": Error, + "JoinChannelSuccess": JoinChannelSuccess, + "RejoinChannelSuccess": RejoinChannelSuccess, + "LeaveChannel": LeaveChannel, + "ClientRoleChanged": ClientRoleChanged, + "UserJoined": UserJoined, + "UserOffline": UserOffline, + "ConnectionStateChanged": ConnectionStateChanged, + "ConnectionLost": ConnectionLost, + "TokenPrivilegeWillExpire": TokenPrivilegeWillExpire, + "RequestToken": RequestToken, + "ActiveSpeaker": ActiveSpeaker, + "VideoSizeChanged": VideoSizeChanged, + "RemoteVideoStateChanged": RemoteVideoStateChanged, + "RemoteAudioStateChanged": RemoteAudioStateChanged, + "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, + "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, + "RtcStats": RtcStats, + "NetworkQuality": NetworkQuality, + "RemoteVideoStats": RemoteVideoStats, + "RemoteAudioStats": RemoteAudioStats, + "RtmpStreamingStateChanged": RtmpStreamingStateChanged, + "TranscodingUpdated": TranscodingUpdated, + "StreamInjectedStatus": StreamInjectedStatus, + "StreamMessage": StreamMessage, + "StreamMessageError": StreamMessageError, + "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, + "ChannelMediaRelayEvent": ChannelMediaRelayEvent, + "MetadataReceived": MetadataReceived, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, + ] + } +} + +class RtcChannelEventHandler: NSObject { + static let PREFIX = "io.agora.rtc." + + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void + + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { + self.emitter = emitter + } + + private func callback(_ methodName: String, _ channel: AgoraRtcChannel, _ data: Any?...) { + emitter(methodName, [ + "channelId": channel.getId(), + "data": data, + ]) + } +} + +extension RtcChannelEventHandler: AgoraRtcChannelDelegate { + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurWarning warningCode: AgoraWarningCode) { + callback(RtcChannelEvents.Warning, rtcChannel, warningCode.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurError errorCode: AgoraErrorCode) { + callback(RtcChannelEvents.Error, rtcChannel, errorCode.rawValue) + } + + public func rtcChannelDidJoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { + callback(RtcChannelEvents.JoinChannelSuccess, rtcChannel, rtcChannel.getId(), uid, elapsed) + } + + public func rtcChannelDidRejoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { + callback(RtcChannelEvents.RejoinChannelSuccess, rtcChannel, rtcChannel.getId(), uid, elapsed) + } + + public func rtcChannelDidLeave(_ rtcChannel: AgoraRtcChannel, with stats: AgoraChannelStats) { + callback(RtcChannelEvents.LeaveChannel, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + callback(RtcChannelEvents.ClientRoleChanged, rtcChannel, oldRole.rawValue, newRole.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didJoinedOfUid uid: UInt, elapsed: Int) { + callback(RtcChannelEvents.UserJoined, rtcChannel, uid, elapsed) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + callback(RtcChannelEvents.UserOffline, rtcChannel, uid, reason.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + callback(RtcChannelEvents.ConnectionStateChanged, rtcChannel, state.rawValue, reason.rawValue) + } + + public func rtcChannelDidLost(_ rtcChannel: AgoraRtcChannel) { + callback(RtcChannelEvents.ConnectionLost, rtcChannel) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, tokenPrivilegeWillExpire token: String) { + callback(RtcChannelEvents.TokenPrivilegeWillExpire, rtcChannel, token) + } + + public func rtcChannelRequestToken(_ rtcChannel: AgoraRtcChannel) { + callback(RtcChannelEvents.RequestToken, rtcChannel) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, activeSpeaker speakerUid: UInt) { + callback(RtcChannelEvents.ActiveSpeaker, rtcChannel, speakerUid) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { + callback(RtcChannelEvents.VideoSizeChanged, rtcChannel, uid, Int(size.width), Int(size.height), rotation) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + callback(RtcChannelEvents.RemoteVideoStateChanged, rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { + callback(RtcChannelEvents.RemoteAudioStateChanged, rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { + callback(RtcChannelEvents.LocalPublishFallbackToAudioOnly, rtcChannel, isFallbackOrRecover) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + callback(RtcChannelEvents.RemoteSubscribeFallbackToAudioOnly, rtcChannel, uid, isFallbackOrRecover) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, reportRtcStats stats: AgoraChannelStats) { + callback(RtcChannelEvents.RtcStats, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + callback(RtcChannelEvents.NetworkQuality, rtcChannel, uid, txQuality.rawValue, rxQuality.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + callback(RtcChannelEvents.RemoteVideoStats, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + callback(RtcChannelEvents.RemoteAudioStats, rtcChannel, stats.toMap()) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + callback(RtcChannelEvents.RtmpStreamingStateChanged, rtcChannel, url, state.rawValue, errorCode.rawValue) + } + + public func rtcChannelTranscodingUpdated(_ rtcChannel: AgoraRtcChannel) { + callback(RtcChannelEvents.TranscodingUpdated, rtcChannel) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + callback(RtcChannelEvents.StreamInjectedStatus, rtcChannel, url, uid, status.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + callback(RtcChannelEvents.StreamMessage, rtcChannel, uid, streamId, String(data: data, encoding: .utf8)) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { + callback(RtcChannelEvents.StreamMessageError, rtcChannel, uid, streamId, error, missed, cached) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + callback(RtcChannelEvents.ChannelMediaRelayStateChanged, rtcChannel, state.rawValue, error.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didReceive event: AgoraChannelMediaRelayEvent) { + callback(RtcChannelEvents.ChannelMediaRelayEvent, rtcChannel, event.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoPublishStateChange oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoPublishStateChanged, rtcChannel, rtcChannel.getId(), oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didAudioSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.AudioSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didVideoSubscribeStateChange uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcChannelEvents.VideoSubscribeStateChanged, rtcChannel, rtcChannel.getId(), uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + callback(RtcChannelEvents.RtmpStreamingEvent, rtcChannel, url, eventCode.rawValue) + } + + public func rtcChannel(_ rtcChannel: AgoraRtcChannel, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + callback(RtcChannelEvents.UserSuperResolutionEnabled, rtcChannel, uid, enabled, reason.rawValue) + } +} diff --git a/RtcChannelEventHandler.swift b/RtcChannelEventHandler.swift deleted file mode 100644 index b906cf38d..000000000 --- a/RtcChannelEventHandler.swift +++ /dev/null @@ -1,177 +0,0 @@ -// -// RtcChannelEventHandler.swift -// RCTAgora -// -// Created by LXH on 2020/4/10. -// Copyright © 2020 Syan. All rights reserved. -// - -import Foundation -import AgoraRtcKit - -class RtcChannelEventHandler: NSObject { - static let PREFIX = "io.agora.rtc." - static let EVENTS = [ - "Warning": "Warning", - "Error": "Error", - "JoinChannelSuccess": "JoinChannelSuccess", - "RejoinChannelSuccess": "RejoinChannelSuccess", - "LeaveChannel": "LeaveChannel", - "ClientRoleChanged": "ClientRoleChanged", - "UserJoined": "UserJoined", - "UserOffline": "UserOffline", - "ConnectionStateChanged": "ConnectionStateChanged", - "ConnectionLost": "ConnectionLost", - "TokenPrivilegeWillExpire": "TokenPrivilegeWillExpire", - "RequestToken": "RequestToken", - "ActiveSpeaker": "ActiveSpeaker", - "VideoSizeChanged": "VideoSizeChanged", - "RemoteVideoStateChanged": "RemoteVideoStateChanged", - "RemoteAudioStateChanged": "RemoteAudioStateChanged", - "LocalPublishFallbackToAudioOnly": "LocalPublishFallbackToAudioOnly", - "RemoteSubscribeFallbackToAudioOnly": "RemoteSubscribeFallbackToAudioOnly", - "RtcStats": "RtcStats", - "NetworkQuality": "NetworkQuality", - "RemoteVideoStats": "RemoteVideoStats", - "RemoteAudioStats": "RemoteAudioStats", - "RtmpStreamingStateChanged": "RtmpStreamingStateChanged", - "TranscodingUpdated": "TranscodingUpdated", - "StreamInjectedStatus": "StreamInjectedStatus", - "StreamMessage": "StreamMessage", - "StreamMessageError": "StreamMessageError", - "ChannelMediaRelayStateChanged": "ChannelMediaRelayStateChanged", - "ChannelMediaRelayEvent": "ChannelMediaRelayEvent", - "MetadataReceived": "MetadataReceived", - ] - - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void - - init(_ emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - self.emitter = emitter - } - - private func callback(_ methodName: String, _ channel: AgoraRtcChannel, _ data: Any?...) { - emitter(methodName, [ - "channelId": channel.getId(), - "data": data - ]) - } -} - -extension RtcChannelEventHandler: AgoraRtcChannelDelegate { - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurWarning warningCode: AgoraWarningCode) { - callback("Warning", rtcChannel, warningCode.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurError errorCode: AgoraErrorCode) { - callback("Error", rtcChannel, errorCode.rawValue) - } - - public func rtcChannelDidJoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { - callback("JoinChannelSuccess", rtcChannel, uid, elapsed) - } - - public func rtcChannelDidRejoin(_ rtcChannel: AgoraRtcChannel, withUid uid: UInt, elapsed: Int) { - callback("RejoinChannelSuccess", rtcChannel, uid, elapsed) - } - - public func rtcChannelDidLeave(_ rtcChannel: AgoraRtcChannel, with stats: AgoraChannelStats) { - callback("LeaveChannel", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { - callback("ClientRoleChanged", rtcChannel, oldRole.rawValue, newRole.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didJoinedOfUid uid: UInt, elapsed: Int) { - callback("UserJoined", rtcChannel, uid, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { - callback("UserOffline", rtcChannel, uid, reason.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { - callback("ConnectionStateChanged", rtcChannel, state.rawValue, reason.rawValue) - } - - public func rtcChannelDidLost(_ rtcChannel: AgoraRtcChannel) { - callback("ConnectionLost", rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, tokenPrivilegeWillExpire token: String) { - callback("TokenPrivilegeWillExpire", rtcChannel, token) - } - - public func rtcChannelRequestToken(_ rtcChannel: AgoraRtcChannel) { - callback("RequestToken", rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, activeSpeaker speakerUid: UInt) { - callback("ActiveSpeaker", rtcChannel, speakerUid) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { - callback("VideoSizeChanged", rtcChannel, uid, size.width, size.height, rotation) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { - callback("RemoteVideoStateChanged", rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { - callback("RemoteAudioStateChanged", rtcChannel, uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { - callback("LocalPublishFallbackToAudioOnly", rtcChannel, isFallbackOrRecover) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { - callback("RemoteSubscribeFallbackToAudioOnly", rtcChannel, uid, isFallbackOrRecover) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, reportRtcStats stats: AgoraChannelStats) { - callback("RtcStats", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { - callback("NetworkQuality", rtcChannel, uid, txQuality, rxQuality) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { - callback("RemoteVideoStats", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { - callback("RemoteAudioStats", rtcChannel, stats.toMap()) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { - callback("RtmpStreamingStateChanged", rtcChannel, url, state.rawValue, errorCode.rawValue) - } - - public func rtcChannelTranscodingUpdated(_ rtcChannel: AgoraRtcChannel) { - callback("TranscodingUpdated", rtcChannel) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { - callback("StreamInjectedStatus", rtcChannel, url, uid, status.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { - callback("StreamMessage", rtcChannel, uid, streamId, String(data: data, encoding: .utf8)) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { - callback("StreamMessageError", rtcChannel, uid, streamId, error, missed, cached) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { - callback("ChannelMediaRelayStateChanged", rtcChannel, state.rawValue, error.rawValue) - } - - public func rtcChannel(_ rtcChannel: AgoraRtcChannel, didReceive event: AgoraChannelMediaRelayEvent) { - callback("ChannelMediaRelayEvent", rtcChannel, event.rawValue) - } -} diff --git a/RtcEngine.swift b/RtcEngine.swift index c8d5d4b34..514ec50b9 100644 --- a/RtcEngine.swift +++ b/RtcEngine.swift @@ -6,8 +6,8 @@ // Copyright (c) 2020 Syan. All rights reserved. // -import Foundation import AgoraRtcKit +import Foundation protocol RtcEngineInterface: RtcEngineUserInfoInterface, @@ -31,456 +31,1203 @@ protocol RtcEngineInterface: RtcEngineInjectStreamInterface, RtcEngineCameraInterface, RtcEngineStreamMessageInterface { - associatedtype Map - associatedtype Callback + func create(_ params: NSDictionary, _ callback: Callback) - func create(_ appId: String, _ callback: Callback?) + func destroy(_ callback: Callback) - func destroy(_ callback: Callback?) + func setChannelProfile(_ params: NSDictionary, _ callback: Callback) - func setChannelProfile(_ profile: Int, _ callback: Callback?) + func setClientRole(_ params: NSDictionary, _ callback: Callback) - func setClientRole(_ role: Int, _ callback: Callback?) + func joinChannel(_ params: NSDictionary, _ callback: Callback) - func joinChannel(_ token: String?, _ channelName: String, _ optionalInfo: String?, _ optionalUid: Int, _ callback: Callback?) + func switchChannel(_ params: NSDictionary, _ callback: Callback) - func switchChannel(_ token: String?, _ channelName: String, _ callback: Callback?) + func leaveChannel(_ callback: Callback) - func leaveChannel(_ callback: Callback?) - - func renewToken(_ token: String, _ callback: Callback?) + func renewToken(_ params: NSDictionary, _ callback: Callback) @available(*, deprecated) - func enableWebSdkInteroperability(_ enabled: Bool, _ callback: Callback?) + func enableWebSdkInteroperability(_ params: NSDictionary, _ callback: Callback) - func getConnectionState(_ callback: Callback?) + func getConnectionState(_ callback: Callback) - func getCallId(_ callback: Callback?) + func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) - func rate(_ callId: String, _ rating: Int, _ description: String?, _ callback: Callback?) + func getCallId(_ callback: Callback) - func complain(_ callId: String, _ description: String, _ callback: Callback?) + func rate(_ params: NSDictionary, _ callback: Callback) - func setLogFile(_ filePath: String, _ callback: Callback?) + func complain(_ params: NSDictionary, _ callback: Callback) - func setLogFilter(_ filter: Int, _ callback: Callback?) + @available(*, deprecated) + func setLogFile(_ params: NSDictionary, _ callback: Callback) - func setLogFileSize(_ fileSizeInKBytes: Int, _ callback: Callback?) + @available(*, deprecated) + func setLogFilter(_ params: NSDictionary, _ callback: Callback) - func setParameters(_ parameters: String, _ callback: Callback?) -} + @available(*, deprecated) + func setLogFileSize(_ params: NSDictionary, _ callback: Callback) -class RtcEngineManager { - private var _engine: AgoraRtcEngineKit? - private var delegate: RtcEngineEventHandler? - private var mediaObserver: MediaObserver? + func setParameters(_ params: NSDictionary, _ callback: Callback) - func create(_ appId: String, _ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - delegate = RtcEngineEventHandler() { methodName, data in - emit(methodName, data) - } - _engine = AgoraRtcEngineKit.sharedEngine(withAppId: appId, delegate: delegate) - _engine?.setAppType(.APP_TYPE_REACTNATIVE) - } + func getSdkVersion(_ callback: Callback) - func destroy() { - AgoraRtcEngineKit.destroy() - _engine = nil - delegate = nil - } + func getErrorDescription(_ params: NSDictionary, _ callback: Callback) - func release() { - destroy() - mediaObserver = nil - } + func getNativeHandle(_ callback: Callback) - var engine: AgoraRtcEngineKit? { - return _engine - } + func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUserAccount(_ userAccount: String) -> Dictionary? { - if let engine = _engine { - let userInfo = engine.getUserInfo(byUserAccount: userAccount, withError: nil) - return userInfo?.toMap() - } - return nil - } + func setCloudProxy(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUid(_ uid: Int) -> Dictionary? { - if let engine = _engine { - let userInfo = engine.getUserInfo(byUid: UInt(uid), withError: nil) - return userInfo?.toMap() - } - return nil - } - - func registerMediaMetadataObserver(_ emit: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) -> Int32 { - if let engine = _engine { - let mediaObserver = MediaObserver() { methodName, data in - emit(methodName, data) - } - let res = engine.setMediaMetadataDelegate(mediaObserver, with: .video) - if res { - self.mediaObserver = mediaObserver - return 0 - } else { - return Int32(AgoraErrorCode.noPermission.rawValue) - } - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } + func uploadLogFile(_ callback: Callback) - func unregisterMediaMetadataObserver() -> Int32 { - if let engine = _engine { - let res = engine.setMediaMetadataDelegate(nil, with: .video) - if res { - mediaObserver = nil - return 0 - } else { - return Int32(AgoraErrorCode.noPermission.rawValue) - } - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } + func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) - func setMaxMetadataSize(_ size: Int) -> Int32 { - if let observer = mediaObserver { - observer.setMaxMetadataSize(size: size) - return 0 - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } - - func addMetadata(_ metadata: String) -> Int32 { - if let observer = mediaObserver { - observer.addMetadata(metadata: metadata) - return 0 - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } - - func createDataStream(_ reliable: Bool, _ ordered: Bool) -> Int32 { - if let engine = _engine { - var streamId = 0 - let res = engine.createDataStream(&streamId, reliable: reliable, ordered: ordered) - if res == 0 { - return Int32(streamId) - } - return res - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } - - func sendStreamMessage(_ streamId: Int, _ message: String) -> Int32 { - if let engine = _engine { - if let data = message.data(using: .utf8) { - return engine.sendStreamMessage(streamId, data: data) - } - return Int32(AgoraErrorCode.invalidArgument.rawValue) - } - return Int32(AgoraErrorCode.notInitialized.rawValue) - } + func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) + + func takeSnapshot(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineUserInfoInterface { - associatedtype Callback - - func registerLocalUserAccount(_ appId: String, _ userAccount: String, _ callback: Callback?) + func registerLocalUserAccount(_ params: NSDictionary, _ callback: Callback) - func joinChannelWithUserAccount(_ token: String?, _ channelName: String, _ userAccount: String, _ callback: Callback?) + func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUserAccount(_ userAccount: String, _ callback: Callback?) + func getUserInfoByUserAccount(_ params: NSDictionary, _ callback: Callback) - func getUserInfoByUid(_ uid: Int, _ callback: Callback?) + func getUserInfoByUid(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioInterface { - associatedtype Callback + func enableAudio(_ callback: Callback) - func enableAudio(_ callback: Callback?) + func disableAudio(_ callback: Callback) - func disableAudio(_ callback: Callback?) + func setAudioProfile(_ params: NSDictionary, _ callback: Callback) - func setAudioProfile(_ profile: Int, _ scenario: Int, _ callback: Callback?) + func adjustRecordingSignalVolume(_ params: NSDictionary, _ callback: Callback) - func adjustRecordingSignalVolume(_ volume: Int, _ callback: Callback?) + func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - func adjustUserPlaybackSignalVolume(_ uid: Int, _ volume: Int, _ callback: Callback?) + func adjustPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) - func adjustPlaybackSignalVolume(_ volume: Int, _ callback: Callback?) + func enableLocalAudio(_ params: NSDictionary, _ callback: Callback) - func enableLocalAudio(_ enabled: Bool, _ callback: Callback?) + func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) - func muteLocalAudioStream(_ muted: Bool, _ callback: Callback?) + func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) - func muteRemoteAudioStream(_ uid: Int, _ muted: Bool, _ callback: Callback?) + func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) - func muteAllRemoteAudioStreams(_ muted: Bool, _ callback: Callback?) + @available(*, deprecated) + func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) + + func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) - func setDefaultMuteAllRemoteAudioStreams(_ muted: Bool, _ callback: Callback?) + func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) - func enableAudioVolumeIndication(_ interval: Int, _ smooth: Int, _ report_vad: Bool, _ callback: Callback?) + func stopRhythmPlayer(_ callback: Callback) + + func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVideoInterface { - associatedtype Map - associatedtype Callback + func enableVideo(_ callback: Callback) - func enableVideo(_ callback: Callback?) + func disableVideo(_ callback: Callback) - func disableVideo(_ callback: Callback?) + func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) - func setVideoEncoderConfiguration(_ config: Map, _ callback: Callback?) + func startPreview(_ callback: Callback) - func enableLocalVideo(_ enabled: Bool, _ callback: Callback?) + func stopPreview(_ callback: Callback) - func muteLocalVideoStream(_ muted: Bool, _ callback: Callback?) + func enableLocalVideo(_ params: NSDictionary, _ callback: Callback) - func muteRemoteVideoStream(_ uid: Int, _ muted: Bool, _ callback: Callback?) + func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) - func muteAllRemoteVideoStreams(_ muted: Bool, _ callback: Callback?) + func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) - func setDefaultMuteAllRemoteVideoStreams(_ muted: Bool, _ callback: Callback?) + func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) - func setBeautyEffectOptions(_ enabled: Bool, _ options: Map, _ callback: Callback?) + @available(*, deprecated) + func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) + + func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) + + func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioMixingInterface { - associatedtype Callback + func startAudioMixing(_ params: NSDictionary, _ callback: Callback) + + func stopAudioMixing(_ callback: Callback) - func startAudioMixing(_ filePath: String, _ loopback: Bool, _ replace: Bool, _ cycle: Int, _ callback: Callback?) + func pauseAudioMixing(_ callback: Callback) - func stopAudioMixing(_ callback: Callback?) + func resumeAudioMixing(_ callback: Callback) - func pauseAudioMixing(_ callback: Callback?) + func adjustAudioMixingVolume(_ params: NSDictionary, _ callback: Callback) - func resumeAudioMixing(_ callback: Callback?) + func adjustAudioMixingPlayoutVolume(_ params: NSDictionary, _ callback: Callback) - func adjustAudioMixingVolume(_ volume: Int, _ callback: Callback?) + func adjustAudioMixingPublishVolume(_ params: NSDictionary, _ callback: Callback) - func adjustAudioMixingPlayoutVolume(_ volume: Int, _ callback: Callback?) + func getAudioMixingPlayoutVolume(_ callback: Callback) - func adjustAudioMixingPublishVolume(_ volume: Int, _ callback: Callback?) + func getAudioMixingPublishVolume(_ callback: Callback) - func getAudioMixingPlayoutVolume(_ callback: Callback?) + func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) + + func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) - func getAudioMixingPublishVolume(_ callback: Callback?) + func getAudioMixingCurrentPosition(_ callback: Callback) - func getAudioMixingDuration(_ callback: Callback?) + func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) - func getAudioMixingCurrentPosition(_ callback: Callback?) + func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) - func setAudioMixingPosition(_ pos: Int, _ callback: Callback?) + func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) + + func getAudioTrackCount(_ callback: Callback) + + func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) + + func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioEffectInterface { - associatedtype Callback + func getEffectsVolume(_ callback: Callback) + + func setEffectsVolume(_ params: NSDictionary, _ callback: Callback) - func getEffectsVolume(_ callback: Callback?) + func setVolumeOfEffect(_ params: NSDictionary, _ callback: Callback) - func setEffectsVolume(_ volume: Double, _ callback: Callback?) + func playEffect(_ params: NSDictionary, _ callback: Callback) - func setVolumeOfEffect(_ soundId: Int, _ volume: Double, _ callback: Callback?) + func setEffectPosition(_ params: NSDictionary, _ callback: Callback) - func playEffect(_ soundId: Int, _ filePath: String, _ loopCount: Int, _ pitch: Double, _ pan: Double, _ gain: Double, _ publish: Bool, _ callback: Callback?) + func getEffectDuration(_ params: NSDictionary, _ callback: Callback) - func stopEffect(_ soundId: Int, _ callback: Callback?) + func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) - func stopAllEffects(_ callback: Callback?) + func stopEffect(_ params: NSDictionary, _ callback: Callback) - func preloadEffect(_ soundId: Int, _ filePath: String, _ callback: Callback?) + func stopAllEffects(_ callback: Callback) - func unloadEffect(_ soundId: Int, _ callback: Callback?) + func preloadEffect(_ params: NSDictionary, _ callback: Callback) - func pauseEffect(_ soundId: Int, _ callback: Callback?) + func unloadEffect(_ params: NSDictionary, _ callback: Callback) - func pauseAllEffects(_ callback: Callback?) + func pauseEffect(_ params: NSDictionary, _ callback: Callback) - func resumeEffect(_ soundId: Int, _ callback: Callback?) + func pauseAllEffects(_ callback: Callback) - func resumeAllEffects(_ callback: Callback?) + func resumeEffect(_ params: NSDictionary, _ callback: Callback) + + func resumeAllEffects(_ callback: Callback) + + func setAudioSessionOperationRestriction(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVoiceChangerInterface { - associatedtype Callback + @available(*, deprecated) + func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceChanger(_ voiceChanger: Int, _ callback: Callback?) + @available(*, deprecated) + func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) + + func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) + + func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) + + func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceReverbPreset(_ preset: Int, _ callback: Callback?) + func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) - func setLocalVoicePitch(_ pitch: Double, _ callback: Callback?) + func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceEqualization(_ bandFrequency: Int, _ bandGain: Int, _ callback: Callback?) + func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) - func setLocalVoiceReverb(_ reverbKey: Int, _ value: Int, _ callback: Callback?) + func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) + + func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineVoicePositionInterface { - associatedtype Callback - - func enableSoundPositionIndication(_ enabled: Bool, _ callback: Callback?) + func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) - func setRemoteVoicePosition(_ uid: Int, _ pan: Double, _ gain: Double, _ callback: Callback?) + func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) } protocol RtcEnginePublishStreamInterface { - associatedtype Map - associatedtype Callback + func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) - func setLiveTranscoding(_ transcoding: Map, _ callback: Callback?) + func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) - func addPublishStreamUrl(_ url: String, _ transcodingEnabled: Bool, _ callback: Callback?) - - func removePublishStreamUrl(_ url: String, _ callback: Callback?) + func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineMediaRelayInterface { - associatedtype Map - associatedtype Callback + func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) + + func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) - func startChannelMediaRelay(_ channelMediaRelayConfiguration: Map, _ callback: Callback?) + func pauseAllChannelMediaRelay(_ callback: Callback) - func updateChannelMediaRelay(_ channelMediaRelayConfiguration: Map, _ callback: Callback?) + func resumeAllChannelMediaRelay(_ callback: Callback) - func stopChannelMediaRelay(_ callback: Callback?) + func stopChannelMediaRelay(_ callback: Callback) } protocol RtcEngineAudioRouteInterface { - associatedtype Callback + func setDefaultAudioRoutetoSpeakerphone(_ params: NSDictionary, _ callback: Callback) - func setDefaultAudioRoutetoSpeakerphone(_ defaultToSpeaker: Bool, _ callback: Callback?) + func setEnableSpeakerphone(_ params: NSDictionary, _ callback: Callback) - func setEnableSpeakerphone(_ enabled: Bool, _ callback: Callback?) - - func isSpeakerphoneEnabled(_ callback: Callback?) + func isSpeakerphoneEnabled(_ callback: Callback) } protocol RtcEngineEarMonitoringInterface { - associatedtype Callback - - func enableInEarMonitoring(_ enabled: Bool, _ callback: Callback?) + func enableInEarMonitoring(_ params: NSDictionary, _ callback: Callback) - func setInEarMonitoringVolume(_ volume: Int, _ callback: Callback?) + func setInEarMonitoringVolume(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineDualStreamInterface { - associatedtype Callback + func enableDualStreamMode(_ params: NSDictionary, _ callback: Callback) - func enableDualStreamMode(_ enabled: Bool, _ callback: Callback?) + func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) - func setRemoteVideoStreamType(_ uid: Int, _ streamType: Int, _ callback: Callback?) - - func setRemoteDefaultVideoStreamType(_ streamType: Int, _ callback: Callback?) + func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineFallbackInterface { - associatedtype Callback - - func setLocalPublishFallbackOption(_ option: Int, _ callback: Callback?) + func setLocalPublishFallbackOption(_ params: NSDictionary, _ callback: Callback) - func setRemoteSubscribeFallbackOption(_ option: Int, _ callback: Callback?) + func setRemoteSubscribeFallbackOption(_ params: NSDictionary, _ callback: Callback) - func setRemoteUserPriority(_ uid: Int, _ userPriority: Int, _ callback: Callback?) + func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineTestInterface { - associatedtype Map - associatedtype Callback + func startEchoTest(_ params: NSDictionary, _ callback: Callback) - func startEchoTest(_ intervalInSeconds: Int, _ callback: Callback?) + func stopEchoTest(_ callback: Callback) - func stopEchoTest(_ callback: Callback?) + func enableLastmileTest(_ callback: Callback) - func enableLastmileTest(_ callback: Callback?) + func disableLastmileTest(_ callback: Callback) - func disableLastmileTest(_ callback: Callback?) + func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) - func startLastmileProbeTest(_ config: Map, _ callback: Callback?) - - func stopLastmileProbeTest(_ callback: Callback?) + func stopLastmileProbeTest(_ callback: Callback) } protocol RtcEngineMediaMetadataInterface { - associatedtype Callback - - func registerMediaMetadataObserver(_ callback: Callback?) + func registerMediaMetadataObserver(_ callback: Callback) - func unregisterMediaMetadataObserver(_ callback: Callback?) + func unregisterMediaMetadataObserver(_ callback: Callback) - func setMaxMetadataSize(_ size: Int, _ callback: Callback?) + func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) - func sendMetadata(_ metadata: String, _ callback: Callback?) + func sendMetadata(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineWatermarkInterface { - associatedtype Map - associatedtype Callback - - func addVideoWatermark(_ watermarkUrl: String, _ options: Map, _ callback: Callback?) + func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) - func clearVideoWatermarks(_ callback: Callback?) + func clearVideoWatermarks(_ callback: Callback) } protocol RtcEngineEncryptionInterface { - associatedtype Callback + @available(*, deprecated) + func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) - func setEncryptionSecret(_ secret: String, _ callback: Callback?) + @available(*, deprecated) + func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) - func setEncryptionMode(_ encryptionMode: String, _ callback: Callback?) + func enableEncryption(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineAudioRecorderInterface { - associatedtype Callback + func startAudioRecording(_ params: NSDictionary, _ callback: Callback) - func startAudioRecording(_ filePath: String, _ sampleRate: Int, _ quality: Int, _ callback: Callback?) - - func stopAudioRecording(_ callback: Callback?) + func stopAudioRecording(_ callback: Callback) } protocol RtcEngineInjectStreamInterface { - associatedtype Map - associatedtype Callback - - func addInjectStreamUrl(_ url: String, _ config: Map, _ callback: Callback?) + func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) - func removeInjectStreamUrl(_ url: String, _ callback: Callback?) + func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineCameraInterface { - associatedtype Map - associatedtype Callback + func switchCamera(_ callback: Callback) - func switchCamera(_ callback: Callback?) + func isCameraZoomSupported(_ callback: Callback) - func isCameraZoomSupported(_ callback: Callback?) + func isCameraTorchSupported(_ callback: Callback) - func isCameraTorchSupported(_ callback: Callback?) + func isCameraFocusSupported(_ callback: Callback) - func isCameraFocusSupported(_ callback: Callback?) + func isCameraExposurePositionSupported(_ callback: Callback) - func isCameraExposurePositionSupported(_ callback: Callback?) + func isCameraAutoFocusFaceModeSupported(_ callback: Callback) - func isCameraAutoFocusFaceModeSupported(_ callback: Callback?) + func setCameraZoomFactor(_ params: NSDictionary, _ callback: Callback) - func setCameraZoomFactor(_ factor: Float, _ callback: Callback?) + func getCameraMaxZoomFactor(_ callback: Callback) - func getCameraMaxZoomFactor(_ callback: Callback?) + func setCameraFocusPositionInPreview(_ params: NSDictionary, _ callback: Callback) - func setCameraFocusPositionInPreview(_ positionX: Float, _ positionY: Float, _ callback: Callback?) + func setCameraExposurePosition(_ params: NSDictionary, _ callback: Callback) - func setCameraExposurePosition(_ positionXinView: Float, _ positionYinView: Float, _ callback: Callback?) + func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) - func setCameraTorchOn(_ isOn: Bool, _ callback: Callback?) + func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) - func setCameraAutoFocusFaceModeEnabled(_ enabled: Bool, _ callback: Callback?) + func setCameraAutoFocusFaceModeEnabled(_ params: NSDictionary, _ callback: Callback) - func setCameraCapturerConfiguration(_ config: Map, _ callback: Callback?) + func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) } protocol RtcEngineStreamMessageInterface { - associatedtype Callback + func createDataStream(_ params: NSDictionary, _ callback: Callback) + + func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) +} + +internal class AgoraRtcEngineKitFactory { + func create(_ params: NSDictionary, _ delegate: RtcEngineEventHandler) -> AgoraRtcEngineKit? { + let engine = AgoraRtcEngineKit.sharedEngine( + with: mapToRtcEngineConfig(params["config"] as! [String: Any]), + delegate: delegate) + + return engine + } +} + +@objc +class RtcEngineManager: NSObject, RtcEngineInterface { + private var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void + private var agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory + private(set) var engine: AgoraRtcEngineKit? + private var delegate: RtcEngineEventHandler? + private var mediaObserver: MediaObserver? + + init(_ emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void, + _ agoraRtcEngineKitFactory: AgoraRtcEngineKitFactory = AgoraRtcEngineKitFactory()) { + self.emitter = emitter + self.agoraRtcEngineKitFactory = agoraRtcEngineKitFactory + } + + func Release() { + if (engine != nil) { + AgoraRtcEngineKit.destroy() + engine = nil + } + delegate = nil + mediaObserver = nil + } + + @objc func create(_ params: NSDictionary, _ callback: Callback) { + delegate = RtcEngineEventHandler { [weak self] in + self?.emitter($0, $1) + } + engine = agoraRtcEngineKitFactory.create(params, delegate!) + callback.code(engine?.setAppType(AgoraRtcAppType(rawValue: (params["appType"] as! NSNumber).uintValue)!)) { + RtcEngineRegistry.shared.onRtcEngineCreated(self.engine) + return $0 + } + } + + @objc func destroy(_ callback: Callback) { + callback.resolve(engine) { [weak self] _ in + self?.Release() + RtcEngineRegistry.shared.onRtcEngineDestroyed() + return nil + } + } + + @objc func setChannelProfile(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setChannelProfile(AgoraChannelProfile(rawValue: (params["profile"] as! NSNumber).intValue)!)) + } + + @objc func setClientRole(_ params: NSDictionary, _ callback: Callback) { + let role = AgoraClientRole(rawValue: (params["role"] as! NSNumber).intValue)! + if let options = params["options"] as? [String: Any] { + callback.code(engine?.setClientRole(role, options: mapToClientRoleOptions(options))) + return + } + callback.code(engine?.setClientRole(role)) + } + + @objc func joinChannel(_ params: NSDictionary, _ callback: Callback) { + let token = params["token"] as? String + let channelName = params["channelName"] as! String + let optionalInfo = params["optionalInfo"] as? String + let optionalUid = params["optionalUid"] as! NSNumber + if let options = params["options"] as? [String: Any] { + callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue, options: mapToChannelMediaOptions(options))) + return + } + callback.code(engine?.joinChannel(byToken: token, channelId: channelName, info: optionalInfo, uid: optionalUid.uintValue)) + } + + @objc func switchChannel(_ params: NSDictionary, _ callback: Callback) { + let token = params["token"] as? String + let channelName = params["channelName"] as! String + if let options = params["options"] as? [String: Any] { + callback.code(engine?.switchChannel(byToken: token, channelId: channelName, options: mapToChannelMediaOptions(options))) + return + } + callback.code(engine?.switchChannel(byToken: token, channelId: channelName)) + } + + @objc func leaveChannel(_ callback: Callback) { + callback.code(engine?.leaveChannel()) + } + + @objc func renewToken(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.renewToken(params["token"] as! String)) + } + + @objc func enableWebSdkInteroperability(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableWebSdkInteroperability(params["enabled"] as! Bool)) + } + + @objc func getConnectionState(_ callback: Callback) { + callback.resolve(engine) { + $0.getConnectionState().rawValue + } + } + + @objc func sendCustomReportMessage(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.sendCustomReportMessage(params["id"] as! String, category: params["category"] as! String, event: params["event"] as! String, label: params["label"] as! String, value: (params["value"] as! NSNumber).intValue)) + } + + @objc func getCallId(_ callback: Callback) { + callback.resolve(engine) { + $0.getCallId() + } + } + + @objc func rate(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.rate(params["callId"] as! String, rating: (params["rating"] as! NSNumber).intValue, description: params["description"] as? String)) + } + + @objc func complain(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.complain(params["callId"] as! String, description: params["description"] as? String)) + } + + @objc func setLogFile(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLogFile(params["filePath"] as! String)) + } + + @objc func setLogFilter(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLogFilter((params["filter"] as! NSNumber).uintValue)) + } + + @objc func setLogFileSize(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLogFileSize((params["fileSizeInKBytes"] as! NSNumber).uintValue)) + } + + @objc func getNativeHandle(_ callback: Callback) { + callback.resolve(engine) { + Int(bitPattern: $0.getNativeHandle()) + } + } + + @objc func setParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setParameters(params["parameters"] as! String)) + } + + @objc func registerLocalUserAccount(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.registerLocalUserAccount(params["userAccount"] as! String, appId: params["appId"] as! String)) + } + + @objc func joinChannelWithUserAccount(_ params: NSDictionary, _ callback: Callback) { + let userAccount = params["userAccount"] as! String + let token = params["token"] as? String + let channelName = params["channelName"] as! String + if let options = params["options"] as? [String: Any] { + callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName, options: mapToChannelMediaOptions(options))) + return + } + callback.code(engine?.joinChannel(byUserAccount: userAccount, token: token, channelId: channelName)) + } + + @objc func getUserInfoByUserAccount(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.getUserInfo(byUserAccount: params["userAccount"] as! String, withError: nil)?.toMap() + } + } + + @objc func getUserInfoByUid(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.getUserInfo(byUid: (params["uid"] as! NSNumber).uintValue, withError: nil)?.toMap() + } + } + + @objc func enableAudio(_ callback: Callback) { + callback.code(engine?.enableAudio()) + } + + @objc func disableAudio(_ callback: Callback) { + callback.code(engine?.disableAudio()) + } + + @objc func setAudioProfile(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioProfile(AgoraAudioProfile(rawValue: (params["profile"] as! NSNumber).intValue)!, scenario: AgoraAudioScenario(rawValue: (params["scenario"] as! NSNumber).intValue)!)) + } + + @objc func adjustRecordingSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustRecordingSignalVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func adjustUserPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustUserPlaybackSignalVolume((params["uid"] as! NSNumber).uintValue, volume: (params["volume"] as! NSNumber).int32Value)) + } + + @objc func adjustPlaybackSignalVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustPlaybackSignalVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func enableLocalAudio(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableLocalAudio(params["enabled"] as! Bool)) + } + + @objc func muteLocalAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteLocalAudioStream(params["muted"] as! Bool)) + } + + @objc func muteRemoteAudioStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteRemoteAudioStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } + + @objc func muteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteAllRemoteAudioStreams(params["muted"] as! Bool)) + } + + @objc func setDefaultMuteAllRemoteAudioStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setDefaultMuteAllRemoteAudioStreams(params["muted"] as! Bool)) + } + + @objc func enableAudioVolumeIndication(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableAudioVolumeIndication((params["interval"] as! NSNumber).intValue, smooth: (params["smooth"] as! NSNumber).intValue, report_vad: params["report_vad"] as! Bool)) + } + + @objc func startRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.startRhythmPlayer(params["sound1"] as! String, sound2: params["sound2"] as! String, config: mapToRhythmPlayerConfig(params["config"] as! [String: Any]))) + } + + @objc func stopRhythmPlayer(_ callback: Callback) { + callback.code(engine?.stopRhythmPlayer()) + } + + @objc func configRhythmPlayer(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.configRhythmPlayer(mapToRhythmPlayerConfig(params as! [String: Any]))) + } + + @objc func enableVideo(_ callback: Callback) { + callback.code(engine?.enableVideo()) + } + + @objc func disableVideo(_ callback: Callback) { + callback.code(engine?.disableVideo()) + } + + @objc func setVideoEncoderConfiguration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVideoEncoderConfiguration(mapToVideoEncoderConfiguration(params["config"] as! [String: Any]))) + } + + @objc func startPreview(_ callback: Callback) { + callback.code(engine?.startPreview()) + } + + @objc func stopPreview(_ callback: Callback) { + callback.code(engine?.stopPreview()) + } + + @objc func enableLocalVideo(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableLocalVideo(params["enabled"] as! Bool)) + } + + @objc func muteLocalVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteLocalVideoStream(params["muted"] as! Bool)) + } + + @objc func muteRemoteVideoStream(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteRemoteVideoStream((params["uid"] as! NSNumber).uintValue, mute: params["muted"] as! Bool)) + } + + @objc func muteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.muteAllRemoteVideoStreams(params["muted"] as! Bool)) + } + + @objc func setDefaultMuteAllRemoteVideoStreams(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setDefaultMuteAllRemoteVideoStreams(params["muted"] as! Bool)) + } + + @objc func setBeautyEffectOptions(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setBeautyEffectOptions(params["enabled"] as! Bool, options: mapToBeautyOptions(params["options"] as! [String: Any]))) + } + + @objc func startAudioMixing(_ params: NSDictionary, _ callback: Callback) { + if let startPos = params["startPos"] as? NSNumber { + callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue, startPos: startPos.intValue)) + return + } + callback.code(engine?.startAudioMixing(params["filePath"] as! String, loopback: params["loopback"] as! Bool, replace: params["replace"] as! Bool, cycle: (params["cycle"] as! NSNumber).intValue)) + } + + @objc func stopAudioMixing(_ callback: Callback) { + callback.code(engine?.stopAudioMixing()) + } + + @objc func pauseAudioMixing(_ callback: Callback) { + callback.code(engine?.pauseAudioMixing()) + } + + @objc func resumeAudioMixing(_ callback: Callback) { + callback.code(engine?.resumeAudioMixing()) + } + + @objc func adjustAudioMixingVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustAudioMixingVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func adjustAudioMixingPlayoutVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustAudioMixingPlayoutVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func adjustAudioMixingPublishVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.adjustAudioMixingPublishVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func getAudioMixingPlayoutVolume(_ callback: Callback) { + callback.code(engine?.getAudioMixingPlayoutVolume()) { + $0 + } + } + + @objc func getAudioMixingPublishVolume(_ callback: Callback) { + callback.code(engine?.getAudioMixingPublishVolume()) { + $0 + } + } + + @objc func getAudioMixingDuration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getAudioMixingDuration()) { + $0 + } + } + + @objc func getAudioFileInfo(_ params: NSDictionary, _ callback: Callback) { + if let filePath = (params["filePath"] as? String) { + callback.code(engine?.getAudioFileInfo(filePath)) { + $0 + } + return + } + } + + @objc func getAudioMixingCurrentPosition(_ callback: Callback) { + callback.code(engine?.getAudioMixingCurrentPosition()) { + $0 + } + } + + @objc func setAudioMixingPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioMixingPosition((params["pos"] as! NSNumber).intValue)) + } + + @objc func setAudioMixingPitch(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioMixingPitch((params["pitch"] as! NSNumber).intValue)) + } + + @objc func setAudioMixingPlaybackSpeed(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioMixingPlaybackSpeed(Int32((params["speed"] as! NSNumber).intValue))) + } + + @objc func getAudioTrackCount(_ callback: Callback) { + callback.code(engine?.getAudioTrackCount()) { + $0 + } + } + + @objc func selectAudioTrack(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.selectAudioTrack((params["audioIndex"] as! NSNumber).intValue)) + } + + @objc func setAudioMixingDualMonoMode(_ params: NSDictionary, _ callback: Callback) { + let mode = AgoraAudioMixingDualMonoMode(rawValue: UInt((params["mode"] as! NSNumber).intValue)) + callback.code(engine?.setAudioMixingDualMonoMode(mode!)) + } + + @objc func getEffectsVolume(_ callback: Callback) { + callback.resolve(engine) { + $0.getEffectsVolume() + } + } + + @objc func setEffectsVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEffectsVolume((params["volume"] as! NSNumber).doubleValue)) + } + + @objc func setVolumeOfEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVolumeOfEffect((params["soundId"] as! NSNumber).int32Value, withVolume: (params["volume"] as! NSNumber).doubleValue)) + } + + @objc func playEffect(_ params: NSDictionary, _ callback: Callback) { + if let startPos = (params["startPos"] as? NSNumber) { + callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool, startPos: startPos.int32Value)) + return + } + callback.code(engine?.playEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String, loopCount: (params["loopCount"] as! NSNumber).int32Value, pitch: (params["pitch"] as! NSNumber).doubleValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue, publish: params["publish"] as! Bool)) + } + + @objc func setEffectPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEffectPosition((params["soundId"] as! NSNumber).int32Value, pos: (params["pos"] as! NSNumber).intValue)) + } + + @objc func getEffectDuration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getEffectDuration(params["filePath"] as! String)) { + $0 + } + } + + @objc func getEffectCurrentPosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.getEffectCurrentPosition((params["soundId"] as! NSNumber).int32Value)) { + $0 + } + } + + @objc func stopEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.stopEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func stopAllEffects(_ callback: Callback) { + callback.code(engine?.stopAllEffects()) + } + + @objc func preloadEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.preloadEffect((params["soundId"] as! NSNumber).int32Value, filePath: params["filePath"] as? String)) + } + + @objc func unloadEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.unloadEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func pauseEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.pauseEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func pauseAllEffects(_ callback: Callback) { + callback.code(engine?.pauseAllEffects()) + } + + @objc func resumeEffect(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.resumeEffect((params["soundId"] as! NSNumber).int32Value)) + } + + @objc func resumeAllEffects(_ callback: Callback) { + callback.code(engine?.resumeAllEffects()) + } + + @objc func setAudioSessionOperationRestriction(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setAudioSessionOperationRestriction(AgoraAudioSessionOperationRestriction(rawValue: (params["restriction"] as! NSNumber).uintValue)) + } + } + + @objc func setLocalVoiceChanger(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceChanger(AgoraAudioVoiceChanger(rawValue: (params["voiceChanger"] as! NSNumber).intValue)!)) + } + + @objc func setLocalVoiceReverbPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceReverbPreset(AgoraAudioReverbPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setLocalVoicePitch(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoicePitch((params["pitch"] as! NSNumber).doubleValue)) + } + + @objc func setLocalVoiceEqualization(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceEqualizationOf(AgoraAudioEqualizationBandFrequency(rawValue: (params["bandFrequency"] as! NSNumber).intValue)!, withGain: (params["bandGain"] as! NSNumber).intValue)) + } + + @objc func setLocalVoiceReverb(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalVoiceReverbOf(AgoraAudioReverbType(rawValue: (params["reverbKey"] as! NSNumber).intValue)!, withValue: (params["value"] as! NSNumber).intValue)) + } + + @objc func setAudioEffectPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioEffectPreset(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setVoiceBeautifierPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceBeautifierPreset(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setVoiceConversionPreset(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceConversionPreset(AgoraVoiceConversionPreset(rawValue: (params["preset"] as! NSNumber).intValue)!)) + } + + @objc func setAudioEffectParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setAudioEffectParameters(AgoraAudioEffectPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) + } + + @objc func enableSoundPositionIndication(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableSoundPositionIndication(params["enabled"] as! Bool)) + } + + @objc func setRemoteVoicePosition(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteVoicePosition((params["uid"] as! NSNumber).uintValue, pan: (params["pan"] as! NSNumber).doubleValue, gain: (params["gain"] as! NSNumber).doubleValue)) + } + + @objc func setLiveTranscoding(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLiveTranscoding(mapToLiveTranscoding(params["transcoding"] as! [String: Any]))) + } + + @objc func addPublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.addPublishStreamUrl(params["url"] as! String, transcodingEnabled: params["transcodingEnabled"] as! Bool)) + } + + @objc func removePublishStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.removePublishStreamUrl(params["url"] as! String)) + } + + @objc func startChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.startChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) + } + + @objc func updateChannelMediaRelay(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.updateChannelMediaRelay(mapToChannelMediaRelayConfiguration(params["channelMediaRelayConfiguration"] as! [String: Any]))) + } + + @objc func stopChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.stopChannelMediaRelay()) + } + + @objc func setDefaultAudioRoutetoSpeakerphone(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setDefaultAudioRouteToSpeakerphone(params["defaultToSpeaker"] as! Bool)) + } - func createDataStream(_ reliable: Bool, _ ordered: Bool, _ callback: Callback?) + @objc func setEnableSpeakerphone(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEnableSpeakerphone(params["enabled"] as! Bool)) + } + + @objc func isSpeakerphoneEnabled(_ callback: Callback) { + callback.resolve(engine) { + $0.isSpeakerphoneEnabled() + } + } + + @objc func enableInEarMonitoring(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enable(inEarMonitoring: params["enabled"] as! Bool)) + } + + @objc func setInEarMonitoringVolume(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setInEarMonitoringVolume((params["volume"] as! NSNumber).intValue)) + } + + @objc func enableDualStreamMode(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableDualStreamMode(params["enabled"] as! Bool)) + } + + @objc func setRemoteVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteVideoStream((params["uid"] as! NSNumber).uintValue, type: AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } + + @objc func setRemoteDefaultVideoStreamType(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteDefaultVideoStreamType(AgoraVideoStreamType(rawValue: (params["streamType"] as! NSNumber).intValue)!)) + } + + @objc func setLocalPublishFallbackOption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setLocalPublishFallbackOption(AgoraStreamFallbackOptions(rawValue: (params["option"] as! NSNumber).intValue)!)) + } + + @objc func setRemoteSubscribeFallbackOption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteSubscribeFallbackOption(AgoraStreamFallbackOptions(rawValue: (params["option"] as! NSNumber).intValue)!)) + } + + @objc func setRemoteUserPriority(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setRemoteUserPriority((params["uid"] as! NSNumber).uintValue, type: AgoraUserPriority(rawValue: (params["userPriority"] as! NSNumber).intValue)!)) + } + + @objc func startEchoTest(_ params: NSDictionary, _ callback: Callback) { + if let intervalInSeconds = (params["intervalInSeconds"] as? NSNumber) { + callback.code(engine?.startEchoTest(withInterval: intervalInSeconds.intValue)) + return + } + if let config = (params["config"] as? [String: Any]) { + callback.code(engine?.startEchoTest(withConfig: mapToEchoTestConfiguration(config))) + return + } + callback.code(engine?.startEchoTest()) + } + + @objc func stopEchoTest(_ callback: Callback) { + callback.code(engine?.stopEchoTest()) + } + + @objc func enableLastmileTest(_ callback: Callback) { + callback.code(engine?.enableLastmileTest()) + } - func sendStreamMessage(_ streamId: Int, _ message: String, _ callback: Callback?) + @objc func disableLastmileTest(_ callback: Callback) { + callback.code(engine?.disableLastmileTest()) + } + + @objc func startLastmileProbeTest(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.startLastmileProbeTest(mapToLastmileProbeConfig(params["config"] as! [String: Any]))) + } + + @objc func stopLastmileProbeTest(_ callback: Callback) { + callback.code(engine?.stopLastmileProbeTest()) + } + + @objc func registerMediaMetadataObserver(_ callback: Callback) { + let mediaObserver = MediaObserver { [weak self] in + self?.emitter(RtcEngineEvents.MetadataReceived, $0) + } + callback.resolve(engine) { + if $0.setMediaMetadataDelegate(mediaObserver, with: .video) { + self.mediaObserver = mediaObserver + } + return nil + } + } + + @objc func unregisterMediaMetadataObserver(_ callback: Callback) { + callback.resolve(engine) { + if $0.setMediaMetadataDelegate(nil, with: .video) { + self.mediaObserver = nil + } + return nil + } + } + + @objc func setMaxMetadataSize(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserver) { + $0.setMaxMetadataSize((params["size"] as! NSNumber).intValue) + } + } + + @objc func sendMetadata(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(mediaObserver) { + $0.addMetadata(params["metadata"] as! String) + } + } + + @objc func addVideoWatermark(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.addVideoWatermark(URL(string: params["watermarkUrl"] as! String)!, options: mapToWatermarkOptions(params["options"] as! [String: Any]))) + } + + @objc func clearVideoWatermarks(_ callback: Callback) { + callback.code(engine?.clearVideoWatermarks()) + } + + @objc func setEncryptionSecret(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setEncryptionSecret(params["secret"] as? String)) + } + + @objc func setEncryptionMode(_ params: NSDictionary, _ callback: Callback) { + var encryptionMode = "" + switch (params["encryptionMode"] as! NSNumber).intValue { + case AgoraEncryptionMode.AES128XTS.rawValue: + encryptionMode = "aes-128-xts" + case AgoraEncryptionMode.AES128ECB.rawValue: + encryptionMode = "aes-128-ecb" + case AgoraEncryptionMode.AES256XTS.rawValue: + encryptionMode = "aes-256-xts" + default: encryptionMode = "" + } + callback.code(engine?.setEncryptionMode(encryptionMode)) + } + + @objc func enableEncryption(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableEncryption(params["enabled"] as! Bool, encryptionConfig: mapToEncryptionConfig(params["config"] as! [String: Any]))) + } + + @objc func startAudioRecording(_ params: NSDictionary, _ callback: Callback) { + if let config = params["config"] as? [String: Any] { + callback.code(engine?.startAudioRecording(withConfig: mapToAudioRecordingConfiguration(config))) + return + } + callback.code(engine?.startAudioRecording(params["filePath"] as! String, sampleRate: (params["sampleRate"] as! NSNumber).intValue, quality: AgoraAudioRecordingQuality(rawValue: (params["quality"] as! NSNumber).intValue)!)) + } + + @objc func stopAudioRecording(_ callback: Callback) { + callback.code(engine?.stopAudioRecording()) + } + + @objc func addInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.addInjectStreamUrl(params["url"] as! String, config: mapToLiveInjectStreamConfig(params["config"] as! [String: Any]))) + } + + @objc func removeInjectStreamUrl(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.removeInjectStreamUrl(params["url"] as! String)) + } + + @objc func switchCamera(_ callback: Callback) { + callback.code(engine?.switchCamera()) + } + + @objc func isCameraZoomSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraZoomSupported() + } + } + + @objc func isCameraTorchSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraTorchSupported() + } + } + + @objc func isCameraFocusSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraFocusPositionInPreviewSupported() + } + } + + @objc func isCameraExposurePositionSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraExposurePositionSupported() + } + } + + @objc func isCameraAutoFocusFaceModeSupported(_ callback: Callback) { + callback.resolve(engine) { + $0.isCameraAutoFocusFaceModeSupported() + } + } + + @objc func setCameraZoomFactor(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraZoomFactor(CGFloat(truncating: params["factor"] as! NSNumber)) + return nil + } + } + + @objc func getCameraMaxZoomFactor(_ callback: Callback) { + callback.code(-Int32(AgoraErrorCode.notSupported.rawValue)) + } + + @objc func setCameraFocusPositionInPreview(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraFocusPositionInPreview(CGPoint(x: (params["positionX"] as! NSNumber).doubleValue, y: (params["positionY"] as! NSNumber).doubleValue)) + return nil + } + } + + @objc func setCameraExposurePosition(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraExposurePosition(CGPoint(x: (params["positionXinView"] as! NSNumber).doubleValue, y: (params["positionYinView"] as! NSNumber).doubleValue)) + return nil + } + } + + @objc func enableFaceDetection(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableFaceDetection(params["enable"] as! Bool)) + } + + @objc func setCameraTorchOn(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraTorchOn(params["isOn"] as! Bool) + return nil + } + } + + @objc func setCameraAutoFocusFaceModeEnabled(_ params: NSDictionary, _ callback: Callback) { + callback.resolve(engine) { + $0.setCameraAutoFocusFaceModeEnabled(params["enabled"] as! Bool) + } + } + + @objc func setCameraCapturerConfiguration(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setCameraCapturerConfiguration(mapToCameraCapturerConfiguration(params["config"] as! [String: Any]))) + } + + @objc func createDataStream(_ params: NSDictionary, _ callback: Callback) { + var streamId = 0 + if let config = params["config"] as? [String: Any] { + callback.code(engine?.createDataStream(&streamId, config: mapToDataStreamConfig(config))) { _ in + streamId + } + return + } + callback.code(engine?.createDataStream(&streamId, reliable: params["reliable"] as! Bool, ordered: params["ordered"] as! Bool)) { _ in + streamId + } + } + + @objc func sendStreamMessage(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.sendStreamMessage((params["streamId"] as! NSNumber).intValue, data: (params["message"] as! String).data(using: .utf8)!)) + } + + @objc func setVoiceBeautifierParameters(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setVoiceBeautifierParameters(AgoraVoiceBeautifierPreset(rawValue: (params["preset"] as! NSNumber).intValue)!, param1: (params["param1"] as! NSNumber).int32Value, param2: (params["param2"] as! NSNumber).int32Value)) + } + + @objc func getSdkVersion(_ callback: Callback) { + callback.success(AgoraRtcEngineKit.getSdkVersion()) + } + + @objc func getErrorDescription(_ params: NSDictionary, _ callback: Callback) { + callback.success(AgoraRtcEngineKit.getErrorDescription((params["error"] as! NSNumber).intValue)) + } + + @objc func enableDeepLearningDenoise(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableDeepLearningDenoise(params["enabled"] as! Bool)) + } + + @objc func setCloudProxy(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.setCloudProxy(AgoraCloudProxyType(rawValue: (params["proxyType"] as! NSNumber).uintValue)!)) + } + + @objc func uploadLogFile(_ callback: Callback) { + callback.resolve(engine) { + $0.uploadLogFile() + } + } + + @objc func enableRemoteSuperResolution(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableRemoteSuperResolution((params["uid"] as! NSNumber).uintValue, enabled: params["enabled"] as! Bool)) + } + + @objc func setLocalAccessPoint(_ params: NSDictionary, _ callback: Callback) { + let list = params["ips"] as! [Any] + var ips: [String] = [] + for i in list.indices { + if let item = list[i] as? String { + ips.append(item) + } + } + callback.code(engine?.setLocalAccessPoint(ips, domain: params["domain"] as! String)) + } + + @objc func pauseAllChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.pauseAllChannelMediaRelay()) + } + + @objc func resumeAllChannelMediaRelay(_ callback: Callback) { + callback.code(engine?.resumeAllChannelMediaRelay()) + } + + @objc func enableVirtualBackground(_ params: NSDictionary, _ callback: Callback) { + callback.code(engine?.enableVirtualBackground(params["enabled"] as! Bool, backData: mapToVirtualBackgroundSource(params["backgroundSource"] as! [String: Any]))) + } + + @objc func takeSnapshot(_ params: NSDictionary, _ callback: Callback) { + var code: Int32? + if let ret = engine?.takeSnapshot(params["channel"] as! String, uid: (params["uid"] as! NSNumber).intValue, filePath: params["filePath"] as! String) { + code = Int32(ret); + } + callback.code(code) + } } diff --git a/RtcEngineEvent.swift b/RtcEngineEvent.swift new file mode 100644 index 000000000..dd4f555ed --- /dev/null +++ b/RtcEngineEvent.swift @@ -0,0 +1,536 @@ +// +// RtcEngineEvent.swift +// RCTAgora +// +// Created by LXH on 2020/4/13. +// Copyright (c) 2020 Syan. All rights reserved. +// + +import AgoraRtcKit +import Foundation + +class RtcEngineEvents { + static let Warning = "Warning" + static let Error = "Error" + static let ApiCallExecuted = "ApiCallExecuted" + static let JoinChannelSuccess = "JoinChannelSuccess" + static let RejoinChannelSuccess = "RejoinChannelSuccess" + static let LeaveChannel = "LeaveChannel" + static let LocalUserRegistered = "LocalUserRegistered" + static let UserInfoUpdated = "UserInfoUpdated" + static let ClientRoleChanged = "ClientRoleChanged" + static let UserJoined = "UserJoined" + static let UserOffline = "UserOffline" + static let ConnectionStateChanged = "ConnectionStateChanged" + static let NetworkTypeChanged = "NetworkTypeChanged" + static let ConnectionLost = "ConnectionLost" + static let TokenPrivilegeWillExpire = "TokenPrivilegeWillExpire" + static let RequestToken = "RequestToken" + static let AudioVolumeIndication = "AudioVolumeIndication" + static let ActiveSpeaker = "ActiveSpeaker" + static let FirstLocalAudioFrame = "FirstLocalAudioFrame" + static let FirstLocalVideoFrame = "FirstLocalVideoFrame" + static let UserMuteVideo = "UserMuteVideo" + static let VideoSizeChanged = "VideoSizeChanged" + static let RemoteVideoStateChanged = "RemoteVideoStateChanged" + static let LocalVideoStateChanged = "LocalVideoStateChanged" + static let RemoteAudioStateChanged = "RemoteAudioStateChanged" + static let LocalAudioStateChanged = "LocalAudioStateChanged" + static let RequestAudioFileInfo = "RequestAudioFileInfo" + static let LocalPublishFallbackToAudioOnly = "LocalPublishFallbackToAudioOnly" + static let RemoteSubscribeFallbackToAudioOnly = "RemoteSubscribeFallbackToAudioOnly" + static let AudioRouteChanged = "AudioRouteChanged" + static let CameraFocusAreaChanged = "CameraFocusAreaChanged" + static let CameraExposureAreaChanged = "CameraExposureAreaChanged" + static let FacePositionChanged = "FacePositionChanged" + static let RtcStats = "RtcStats" + static let LastmileQuality = "LastmileQuality" + static let NetworkQuality = "NetworkQuality" + static let LastmileProbeResult = "LastmileProbeResult" + static let LocalVideoStats = "LocalVideoStats" + static let LocalAudioStats = "LocalAudioStats" + static let RemoteVideoStats = "RemoteVideoStats" + static let RemoteAudioStats = "RemoteAudioStats" + static let AudioMixingFinished = "AudioMixingFinished" + static let AudioMixingStateChanged = "AudioMixingStateChanged" + static let AudioEffectFinished = "AudioEffectFinished" + static let RtmpStreamingStateChanged = "RtmpStreamingStateChanged" + static let TranscodingUpdated = "TranscodingUpdated" + static let StreamInjectedStatus = "StreamInjectedStatus" + static let StreamMessage = "StreamMessage" + static let StreamMessageError = "StreamMessageError" + static let MediaEngineLoadSuccess = "MediaEngineLoadSuccess" + static let MediaEngineStartCallSuccess = "MediaEngineStartCallSuccess" + static let ChannelMediaRelayStateChanged = "ChannelMediaRelayStateChanged" + static let ChannelMediaRelayEvent = "ChannelMediaRelayEvent" + static let FirstRemoteVideoFrame = "FirstRemoteVideoFrame" + static let FirstRemoteAudioFrame = "FirstRemoteAudioFrame" + static let FirstRemoteAudioDecoded = "FirstRemoteAudioDecoded" + static let UserMuteAudio = "UserMuteAudio" + static let StreamPublished = "StreamPublished" + static let StreamUnpublished = "StreamUnpublished" + static let RemoteAudioTransportStats = "RemoteAudioTransportStats" + static let RemoteVideoTransportStats = "RemoteVideoTransportStats" + static let UserEnableVideo = "UserEnableVideo" + static let UserEnableLocalVideo = "UserEnableLocalVideo" + static let FirstRemoteVideoDecoded = "FirstRemoteVideoDecoded" + static let MicrophoneEnabled = "MicrophoneEnabled" + static let ConnectionInterrupted = "ConnectionInterrupted" + static let ConnectionBanned = "ConnectionBanned" + static let AudioQuality = "AudioQuality" + static let CameraReady = "CameraReady" + static let VideoStopped = "VideoStopped" + static let MetadataReceived = "MetadataReceived" + static let FirstLocalAudioFramePublished = "FirstLocalAudioFramePublished" + static let FirstLocalVideoFramePublished = "FirstLocalVideoFramePublished" + static let AudioPublishStateChanged = "AudioPublishStateChanged" + static let VideoPublishStateChanged = "VideoPublishStateChanged" + static let AudioSubscribeStateChanged = "AudioSubscribeStateChanged" + static let VideoSubscribeStateChanged = "VideoSubscribeStateChanged" + static let RtmpStreamingEvent = "RtmpStreamingEvent" + static let UserSuperResolutionEnabled = "UserSuperResolutionEnabled" + static let UploadLogResult = "UploadLogResult" + static let AirPlayIsConnected = "AirPlayIsConnected" + static let VirtualBackgroundSourceEnabled = "VirtualBackgroundSourceEnabled" + static let SnapshotTaken = "SnapshotTaken" + + static func toMap() -> [String: String] { + return [ + "Warning": Warning, + "Error": Error, + "ApiCallExecuted": ApiCallExecuted, + "JoinChannelSuccess": JoinChannelSuccess, + "RejoinChannelSuccess": RejoinChannelSuccess, + "LeaveChannel": LeaveChannel, + "LocalUserRegistered": LocalUserRegistered, + "UserInfoUpdated": UserInfoUpdated, + "ClientRoleChanged": ClientRoleChanged, + "UserJoined": UserJoined, + "UserOffline": UserOffline, + "ConnectionStateChanged": ConnectionStateChanged, + "NetworkTypeChanged": NetworkTypeChanged, + "ConnectionLost": ConnectionLost, + "TokenPrivilegeWillExpire": TokenPrivilegeWillExpire, + "RequestToken": RequestToken, + "AudioVolumeIndication": AudioVolumeIndication, + "ActiveSpeaker": ActiveSpeaker, + "FirstLocalAudioFrame": FirstLocalAudioFrame, + "FirstLocalVideoFrame": FirstLocalVideoFrame, + "UserMuteVideo": UserMuteVideo, + "VideoSizeChanged": VideoSizeChanged, + "RemoteVideoStateChanged": RemoteVideoStateChanged, + "LocalVideoStateChanged": LocalVideoStateChanged, + "RemoteAudioStateChanged": RemoteAudioStateChanged, + "LocalAudioStateChanged": LocalAudioStateChanged, + "RequestAudioFileInfo": RequestAudioFileInfo, + "LocalPublishFallbackToAudioOnly": LocalPublishFallbackToAudioOnly, + "RemoteSubscribeFallbackToAudioOnly": RemoteSubscribeFallbackToAudioOnly, + "AudioRouteChanged": AudioRouteChanged, + "CameraFocusAreaChanged": CameraFocusAreaChanged, + "CameraExposureAreaChanged": CameraExposureAreaChanged, + "FacePositionChanged": FacePositionChanged, + "RtcStats": RtcStats, + "LastmileQuality": LastmileQuality, + "NetworkQuality": NetworkQuality, + "LastmileProbeResult": LastmileProbeResult, + "LocalVideoStats": LocalVideoStats, + "LocalAudioStats": LocalAudioStats, + "RemoteVideoStats": RemoteVideoStats, + "RemoteAudioStats": RemoteAudioStats, + "AudioMixingFinished": AudioMixingFinished, + "AudioMixingStateChanged": AudioMixingStateChanged, + "AudioEffectFinished": AudioEffectFinished, + "RtmpStreamingStateChanged": RtmpStreamingStateChanged, + "TranscodingUpdated": TranscodingUpdated, + "StreamInjectedStatus": StreamInjectedStatus, + "StreamMessage": StreamMessage, + "StreamMessageError": StreamMessageError, + "MediaEngineLoadSuccess": MediaEngineLoadSuccess, + "MediaEngineStartCallSuccess": MediaEngineStartCallSuccess, + "ChannelMediaRelayStateChanged": ChannelMediaRelayStateChanged, + "ChannelMediaRelayEvent": ChannelMediaRelayEvent, + "FirstRemoteVideoFrame": FirstRemoteVideoFrame, + "FirstRemoteAudioFrame": FirstRemoteAudioFrame, + "FirstRemoteAudioDecoded": FirstRemoteAudioDecoded, + "UserMuteAudio": UserMuteAudio, + "StreamPublished": StreamPublished, + "StreamUnpublished": StreamUnpublished, + "RemoteAudioTransportStats": RemoteAudioTransportStats, + "RemoteVideoTransportStats": RemoteVideoTransportStats, + "UserEnableVideo": UserEnableVideo, + "UserEnableLocalVideo": UserEnableLocalVideo, + "FirstRemoteVideoDecoded": FirstRemoteVideoDecoded, + "MicrophoneEnabled": MicrophoneEnabled, + "ConnectionInterrupted": ConnectionInterrupted, + "ConnectionBanned": ConnectionBanned, + "AudioQuality": AudioQuality, + "CameraReady": CameraReady, + "VideoStopped": VideoStopped, + "MetadataReceived": MetadataReceived, + "FirstLocalAudioFramePublished": FirstLocalAudioFramePublished, + "FirstLocalVideoFramePublished": FirstLocalVideoFramePublished, + "AudioPublishStateChanged": AudioPublishStateChanged, + "VideoPublishStateChanged": VideoPublishStateChanged, + "AudioSubscribeStateChanged": AudioSubscribeStateChanged, + "VideoSubscribeStateChanged": VideoSubscribeStateChanged, + "RtmpStreamingEvent": RtmpStreamingEvent, + "UserSuperResolutionEnabled": UserSuperResolutionEnabled, + "UploadLogResult": UploadLogResult, + "AirPlayIsConnected": AirPlayIsConnected, + "VirtualBackgroundSourceEnabled": VirtualBackgroundSourceEnabled, + "SnapshotTaken": SnapshotTaken, + ] + } +} + +class RtcEngineEventHandler: NSObject { + static let PREFIX = "io.agora.rtc." + + var emitter: (_ methodName: String, _ data: [String: Any?]?) -> Void + + init(emitter: @escaping (_ methodName: String, _ data: [String: Any?]?) -> Void) { + self.emitter = emitter + } + + private func callback(_ methodName: String, _ data: Any?...) { + emitter(methodName, ["data": data]) + } +} + +extension RtcEngineEventHandler: AgoraRtcEngineDelegate { + public func rtcEngine(_: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { + callback(RtcEngineEvents.Warning, warningCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { + callback(RtcEngineEvents.Error, errorCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { + callback(RtcEngineEvents.ApiCallExecuted, error, api, result) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.JoinChannelSuccess, channel, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.RejoinChannelSuccess, channel, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { + callback(RtcEngineEvents.LeaveChannel, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { + callback(RtcEngineEvents.LocalUserRegistered, uid, userAccount) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { + callback(RtcEngineEvents.UserInfoUpdated, uid, userInfo.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + callback(RtcEngineEvents.ClientRoleChanged, oldRole.rawValue, newRole.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.UserJoined, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + callback(RtcEngineEvents.UserOffline, uid, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + callback(RtcEngineEvents.ConnectionStateChanged, state.rawValue, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { + callback(RtcEngineEvents.NetworkTypeChanged, type.rawValue) + } + + public func rtcEngineConnectionDidLost(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.ConnectionLost) + } + + public func rtcEngine(_: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { + callback(RtcEngineEvents.TokenPrivilegeWillExpire, token) + } + + public func rtcEngineRequestToken(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.RequestToken) + } + + public func rtcEngine(_: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { + callback(RtcEngineEvents.AudioVolumeIndication, speakers.toMapList(), totalVolume) + } + + public func rtcEngine(_: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { + callback(RtcEngineEvents.ActiveSpeaker, speakerUid) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { + callback(RtcEngineEvents.FirstLocalAudioFrame, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { + callback(RtcEngineEvents.FirstLocalVideoFrame, Int(size.width), Int(size.height), elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserMuteVideo, uid, muted) + } + + public func rtcEngine(_: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { + callback(RtcEngineEvents.VideoSizeChanged, uid, Int(size.width), Int(size.height), rotation) + } + + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + callback(RtcEngineEvents.RemoteVideoStateChanged, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { + callback(RtcEngineEvents.LocalVideoStateChanged, state.rawValue, error.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { + callback(RtcEngineEvents.RemoteAudioStateChanged, uid, state.rawValue, reason.rawValue, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { + callback(RtcEngineEvents.LocalAudioStateChanged, state.rawValue, error.rawValue) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, didRequest info: AgoraRtcAudioFileInfo, error: AgoraAudioFileInfoError) { + callback(RtcEngineEvents.RequestAudioFileInfo, info.toMap(), error.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { + callback(RtcEngineEvents.LocalPublishFallbackToAudioOnly, isFallbackOrRecover) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.RemoteSubscribeFallbackToAudioOnly, uid, isFallbackOrRecover) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { + callback(RtcEngineEvents.AudioRouteChanged, routing.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { + callback(RtcEngineEvents.CameraFocusAreaChanged, rect.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { + callback(RtcEngineEvents.CameraExposureAreaChanged, rect.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { + callback(RtcEngineEvents.FacePositionChanged, width, height, faces?.toMapList()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { + callback(RtcEngineEvents.RtcStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { + callback(RtcEngineEvents.LastmileQuality, quality.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + callback(RtcEngineEvents.NetworkQuality, uid, txQuality.rawValue, rxQuality.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { + callback(RtcEngineEvents.LastmileProbeResult, result.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { + callback(RtcEngineEvents.LocalVideoStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { + callback(RtcEngineEvents.LocalAudioStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + callback(RtcEngineEvents.RemoteVideoStats, stats.toMap()) + } + + public func rtcEngine(_: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + callback(RtcEngineEvents.RemoteAudioStats, stats.toMap()) + } + + public func rtcEngineLocalAudioMixingDidFinish(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.AudioMixingFinished) + } + + public func rtcEngine(_: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) { + callback(RtcEngineEvents.AudioMixingStateChanged, state.rawValue, reason.rawValue) + } + + public func rtcEngineRemoteAudioMixingDidStart(_: AgoraRtcEngineKit) { + // TODO: Not in Android + } + + public func rtcEngineRemoteAudioMixingDidFinish(_: AgoraRtcEngineKit) { + // TODO: Not in Android + } + + public func rtcEngineDidAudioEffectFinish(_: AgoraRtcEngineKit, soundId: Int) { + callback(RtcEngineEvents.AudioEffectFinished, soundId) + } + + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + callback(RtcEngineEvents.RtmpStreamingStateChanged, url, state.rawValue, errorCode.rawValue) + } + + public func rtcEngineTranscodingUpdated(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.TranscodingUpdated) + } + + public func rtcEngine(_: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + callback(RtcEngineEvents.StreamInjectedStatus, url, uid, status.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + callback(RtcEngineEvents.StreamMessage, uid, streamId, String(data: data, encoding: .utf8)) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { + callback(RtcEngineEvents.StreamMessageError, uid, streamId, error, missed, cached) + } + + public func rtcEngineMediaEngineDidLoaded(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.MediaEngineLoadSuccess) + } + + public func rtcEngineMediaEngineDidStartCall(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.MediaEngineStartCallSuccess) + } + + public func rtcEngine(_: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + callback(RtcEngineEvents.ChannelMediaRelayStateChanged, state.rawValue, error.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { + callback(RtcEngineEvents.ChannelMediaRelayEvent, event.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { + callback(RtcEngineEvents.FirstRemoteVideoFrame, uid, Int(size.width), Int(size.height), elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.FirstRemoteAudioFrame, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { + callback(RtcEngineEvents.FirstRemoteAudioDecoded, uid, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserMuteAudio, uid, muted) + } + + public func rtcEngine(_: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { + callback(RtcEngineEvents.StreamPublished, url, errorCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { + callback(RtcEngineEvents.StreamUnpublished, url) + } + + public func rtcEngine(_: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + callback(RtcEngineEvents.RemoteAudioTransportStats, uid, delay, lost, rxKBitRate) + } + + public func rtcEngine(_: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + callback(RtcEngineEvents.RemoteVideoTransportStats, uid, delay, lost, rxKBitRate) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserEnableVideo, uid, enabled) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { + callback(RtcEngineEvents.UserEnableLocalVideo, uid, enabled) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { + callback(RtcEngineEvents.FirstRemoteVideoDecoded, uid, Int(size.width), Int(size.height), elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { + callback(RtcEngineEvents.MicrophoneEnabled, enabled) + } + + public func rtcEngineConnectionDidInterrupted(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.ConnectionInterrupted) + } + + public func rtcEngineConnectionDidBanned(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.ConnectionBanned) + } + + public func rtcEngine(_: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { + callback(RtcEngineEvents.AudioQuality, uid, quality.rawValue, delay, lost) + } + + public func rtcEngineCameraDidReady(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.CameraReady) + } + + public func rtcEngineVideoDidStop(_: AgoraRtcEngineKit) { + callback(RtcEngineEvents.VideoStopped) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) { + callback(RtcEngineEvents.FirstLocalAudioFramePublished, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, firstLocalVideoFramePublished elapsed: Int) { + callback(RtcEngineEvents.FirstLocalVideoFramePublished, elapsed) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoPublishStateChanged, channel, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didAudioSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.AudioSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, didVideoSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + callback(RtcEngineEvents.VideoSubscribeStateChanged, channel, uid, oldState.rawValue, newState.rawValue, elapseSinceLastState) + } + + public func rtcEngine(_: AgoraRtcEngineKit, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + callback(RtcEngineEvents.RtmpStreamingEvent, url, eventCode.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + callback(RtcEngineEvents.UserSuperResolutionEnabled, uid, enabled, reason.rawValue) + } + + public func rtcEngine(_: AgoraRtcEngineKit, uploadLogResultRequestId requestId: String, success: Bool, reason: AgoraUploadErrorReason) { + callback(RtcEngineEvents.UploadLogResult, requestId, success, reason.rawValue) + } + + public func rtcEngineAirPlayIsConnected(_ engine: AgoraRtcEngineKit) { + callback(RtcEngineEvents.AirPlayIsConnected) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, virtualBackgroundSourceEnabled enabled: Bool, reason: AgoraVirtualBackgroundSourceStateReason) { + callback(RtcEngineEvents.VirtualBackgroundSourceEnabled, enabled, reason.rawValue) + } + + public func rtcEngine(_ engine: AgoraRtcEngineKit, snapshotTaken channel: String, uid: UInt, filePath: String, width: Int, height: Int, errCode: Int) { + callback(RtcEngineEvents.SnapshotTaken, channel, uid, filePath, width, height, errCode) + } +} diff --git a/RtcEngineEventHandler.swift b/RtcEngineEventHandler.swift deleted file mode 100644 index 72c78c899..000000000 --- a/RtcEngineEventHandler.swift +++ /dev/null @@ -1,377 +0,0 @@ -// -// RtcEngineEventHandler.swift -// RCTAgora -// -// Created by LXH on 2020/4/13. -// Copyright (c) 2020 Syan. All rights reserved. -// - -import Foundation -import AgoraRtcKit - -class RtcEngineEventHandler: NSObject { - static let PREFIX = "io.agora.rtc." - static let EVENTS = [ - "Warning": "Warning", - "Error": "Error", - "ApiCallExecuted": "ApiCallExecuted", - "JoinChannelSuccess": "JoinChannelSuccess", - "RejoinChannelSuccess": "RejoinChannelSuccess", - "LeaveChannel": "LeaveChannel", - "LocalUserRegistered": "LocalUserRegistered", - "UserInfoUpdated": "UserInfoUpdated", - "ClientRoleChanged": "ClientRoleChanged", - "UserJoined": "UserJoined", - "UserOffline": "UserOffline", - "ConnectionStateChanged": "ConnectionStateChanged", - "NetworkTypeChanged": "NetworkTypeChanged", - "ConnectionLost": "ConnectionLost", - "TokenPrivilegeWillExpire": "TokenPrivilegeWillExpire", - "RequestToken": "RequestToken", - "AudioVolumeIndication": "AudioVolumeIndication", - "ActiveSpeaker": "ActiveSpeaker", - "FirstLocalAudioFrame": "FirstLocalAudioFrame", - "FirstLocalVideoFrame": "FirstLocalVideoFrame", - "UserMuteVideo": "UserMuteVideo", - "VideoSizeChanged": "VideoSizeChanged", - "RemoteVideoStateChanged": "RemoteVideoStateChanged", - "LocalVideoStateChanged": "LocalVideoStateChanged", - "RemoteAudioStateChanged": "RemoteAudioStateChanged", - "LocalAudioStateChanged": "LocalAudioStateChanged", - "LocalPublishFallbackToAudioOnly": "LocalPublishFallbackToAudioOnly", - "RemoteSubscribeFallbackToAudioOnly": "RemoteSubscribeFallbackToAudioOnly", - "AudioRouteChanged": "AudioRouteChanged", - "CameraFocusAreaChanged": "CameraFocusAreaChanged", - "CameraExposureAreaChanged": "CameraExposureAreaChanged", - "RtcStats": "RtcStats", - "LastmileQuality": "LastmileQuality", - "NetworkQuality": "NetworkQuality", - "LastmileProbeResult": "LastmileProbeResult", - "LocalVideoStats": "LocalVideoStats", - "LocalAudioStats": "LocalAudioStats", - "RemoteVideoStats": "RemoteVideoStats", - "RemoteAudioStats": "RemoteAudioStats", - "AudioMixingFinished": "AudioMixingFinished", - "AudioMixingStateChanged": "AudioMixingStateChanged", - "AudioEffectFinished": "AudioEffectFinished", - "RtmpStreamingStateChanged": "RtmpStreamingStateChanged", - "TranscodingUpdated": "TranscodingUpdated", - "StreamInjectedStatus": "StreamInjectedStatus", - "StreamMessage": "StreamMessage", - "StreamMessageError": "StreamMessageError", - "MediaEngineLoadSuccess": "MediaEngineLoadSuccess", - "MediaEngineStartCallSuccess": "MediaEngineStartCallSuccess", - "ChannelMediaRelayStateChanged": "ChannelMediaRelayStateChanged", - "ChannelMediaRelayEvent": "ChannelMediaRelayEvent", - "FirstRemoteVideoFrame": "FirstRemoteVideoFrame", - "FirstRemoteAudioFrame": "FirstRemoteAudioFrame", - "FirstRemoteAudioDecoded": "FirstRemoteAudioDecoded", - "UserMuteAudio": "UserMuteAudio", - "StreamPublished": "StreamPublished", - "StreamUnpublished": "StreamUnpublished", - "RemoteAudioTransportStats": "RemoteAudioTransportStats", - "RemoteVideoTransportStats": "RemoteVideoTransportStats", - "UserEnableVideo": "UserEnableVideo", - "UserEnableLocalVideo": "UserEnableLocalVideo", - "FirstRemoteVideoDecoded": "FirstRemoteVideoDecoded", - "MicrophoneEnabled": "MicrophoneEnabled", - "ConnectionInterrupted": "ConnectionInterrupted", - "ConnectionBanned": "ConnectionBanned", - "AudioQuality": "AudioQuality", - "CameraReady": "CameraReady", - "VideoStopped": "VideoStopped", - "MetadataReceived": "MetadataReceived", - ] - - var emitter: (_ methodName: String, _ data: Dictionary?) -> Void - - init(emitter: @escaping (_ methodName: String, _ data: Dictionary?) -> Void) { - self.emitter = emitter - } - - private func callback(_ methodName: String, _ data: Any?...) { - emitter(methodName, ["data": data]) - } -} - -extension RtcEngineEventHandler: AgoraRtcEngineDelegate { - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { - callback("Warning", warningCode.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { - callback("Error", errorCode.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { - callback("ApiCallExecuted", error, api, result) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { - callback("JoinChannelSuccess", channel, uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { - callback("RejoinChannelSuccess", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { - callback("LeaveChannel", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { - callback("LocalUserRegistered", uid, userAccount) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { - callback("UserInfoUpdated", uid, userInfo.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { - callback("ClientRoleChanged", oldRole.rawValue, newRole.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { - callback("UserJoined", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { - callback("UserOffline", uid, reason.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { - callback("ConnectionStateChanged", state.rawValue, reason.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { - callback("NetworkTypeChanged", type.rawValue) - } - - public func rtcEngineConnectionDidLost(_ engine: AgoraRtcEngineKit) { - callback("ConnectionLost") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { - callback("TokenPrivilegeWillExpire", token) - } - - public func rtcEngineRequestToken(_ engine: AgoraRtcEngineKit) { - callback("RequestToken") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { - callback("AudioVolumeIndication", speakers.toMapList(), totalVolume) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { - callback("ActiveSpeaker", speakerUid) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { - callback("FirstLocalAudioFrame", elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { - callback("FirstLocalVideoFrame", size.width, size.height, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { - callback("UserMuteVideo", uid, muted) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { - callback("VideoSizeChanged", uid, size.width, size.height, rotation) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { - callback("RemoteVideoStateChanged", uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { - callback("LocalVideoStateChanged", state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { - callback("RemoteAudioStateChanged", uid, state.rawValue, reason.rawValue, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { - callback("LocalAudioStateChanged", state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { - callback("LocalPublishFallbackToAudioOnly", isFallbackOrRecover) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { - callback("RemoteSubscribeFallbackToAudioOnly", uid, isFallbackOrRecover) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { - callback("AudioRouteChanged", routing.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { - callback("CameraFocusAreaChanged", rect.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { - callback("CameraExposureAreaChanged", rect.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { - callback("RtcStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { - callback("LastmileQuality", quality.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { - callback("NetworkQuality", uid, txQuality.rawValue, rxQuality.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { - callback("LastmileProbeResult", result.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { - callback("LocalVideoStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { - callback("LocalAudioStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { - callback("RemoteVideoStats", stats.toMap()) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { - callback("RemoteAudioStats", stats.toMap()) - } - - public func rtcEngineLocalAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { - callback("AudioMixingFinished") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, errorCode: AgoraAudioMixingErrorCode) { - callback("AudioMixingStateChanged", state.rawValue, errorCode.rawValue) - } - - public func rtcEngineRemoteAudioMixingDidStart(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android - } - - public func rtcEngineRemoteAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { - // TODO Not in Android - } - - public func rtcEngineDidAudioEffectFinish(_ engine: AgoraRtcEngineKit, soundId: Int) { - callback("AudioEffectFinished", soundId) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { - callback("RtmpStreamingStateChanged", url, state.rawValue, errorCode.rawValue) - } - - public func rtcEngineTranscodingUpdated(_ engine: AgoraRtcEngineKit) { - callback("TranscodingUpdated") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { - callback("StreamInjectedStatus", url, uid, status.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { - callback("StreamMessage", uid, streamId, String(data: data, encoding: .utf8)) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { - callback("StreamMessageError", uid, streamId, error, missed, cached) - } - - public func rtcEngineMediaEngineDidLoaded(_ engine: AgoraRtcEngineKit) { - callback("MediaEngineLoadSuccess") - } - - public func rtcEngineMediaEngineDidStartCall(_ engine: AgoraRtcEngineKit) { - callback("MediaEngineStartCallSuccess") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { - callback("ChannelMediaRelayStateChanged", state.rawValue, error.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { - callback("ChannelMediaRelayEvent", event.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { - callback("FirstRemoteVideoFrame", uid, size.width, size.height, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { - callback("FirstRemoteAudioFrame", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { - callback("FirstRemoteAudioDecoded", uid, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { - callback("UserMuteAudio", uid, muted) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { - callback("StreamPublished", url, errorCode.rawValue) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { - callback("StreamUnpublished", url) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { - callback("RemoteAudioTransportStats", uid, delay, lost, rxKBitRate) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { - callback("RemoteVideoTransportStats", uid, delay, lost, rxKBitRate) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { - callback("UserEnableVideo", uid, enabled) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { - callback("UserEnableLocalVideo", uid, enabled) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { - callback("FirstRemoteVideoDecoded", uid, size.width, size.height, elapsed) - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { - callback("MicrophoneEnabled", enabled) - } - - public func rtcEngineConnectionDidInterrupted(_ engine: AgoraRtcEngineKit) { - callback("ConnectionInterrupted") - } - - public func rtcEngineConnectionDidBanned(_ engine: AgoraRtcEngineKit) { - callback("ConnectionBanned") - } - - public func rtcEngine(_ engine: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { - callback("AudioQuality", uid, quality.rawValue, delay, lost) - } - - public func rtcEngineCameraDidReady(_ engine: AgoraRtcEngineKit) { - callback("CameraReady") - } - - public func rtcEngineVideoDidStop(_ engine: AgoraRtcEngineKit) { - callback("VideoStopped") - } -} diff --git a/RtcEnginePlugin.h b/RtcEnginePlugin.h new file mode 100644 index 000000000..93d89eef8 --- /dev/null +++ b/RtcEnginePlugin.h @@ -0,0 +1,31 @@ +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A `RtcEnginePlugin` allows developers to interact with the `RtcEngine` which created from flutter + * side. + */ +@protocol RtcEnginePlugin + +/** + * This callback will be called when the `RtcEngine` is created by + [RtcEngine.createWithContext](https://docs.agora.io/cn/Video/API%20Reference/flutter/agora_rtc_engine/RtcEngine/createWithContext.html) + * function from flutter. + + * NOTE that you should not call `AgoraRtcEngineKit.destroy`, because it will also destroy the `RtcEngine` + * used by flutter side. + * + * @param rtcEngine The same `AgoraRtcEngineKit` used by flutter side + */ +- (void)onRtcEngineCreated:(AgoraRtcEngineKit *_Nullable)rtcEngine; + +/** + * This callback will be called when the [RtcEngine.destroy](https://docs.agora.io/cn/Video/API%20Reference/flutter/v4.0.7/rtc_channel/RtcChannel/destroy.html) + * function is called from flutter. + */ +- (void)onRtcEngineDestroyed; +@end + +NS_ASSUME_NONNULL_END diff --git a/RtcEnginePluginRegistrant.h b/RtcEnginePluginRegistrant.h new file mode 100644 index 000000000..27dc5e688 --- /dev/null +++ b/RtcEnginePluginRegistrant.h @@ -0,0 +1,25 @@ +#ifndef RtcEnginePluginRegistrant_h +#define RtcEnginePluginRegistrant_h + +#import +#import "RtcEnginePlugin.h" + +/** + * Class for register the `RtcEnginePlugin`. + */ +@interface RtcEnginePluginRegistrant : NSObject + +/** + * Register a `RtcEnginePlugin`. The `plugin` will be called when the `RtcEngine` is created from + * flutter side. + */ ++(void)register:(NSObject *_Nonnull)plugin; + +/** + * Unregister a previously registered `RtcEnginePlugin`. + */ ++(void)unregister:(NSObject *_Nonnull)plugin; + +@end + +#endif /* RtcEnginePluginRegistrant_h */ diff --git a/RtcEnginePluginRegistrant.m b/RtcEnginePluginRegistrant.m new file mode 100644 index 000000000..fa2dadce7 --- /dev/null +++ b/RtcEnginePluginRegistrant.m @@ -0,0 +1,22 @@ +#import +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "agora_rtc_engine-Swift.h" +#endif +#import "RtcEnginePlugin.h" +#import "RtcEnginePluginRegistrant.h" + +@implementation RtcEnginePluginRegistrant : NSObject + ++ (void)register:(NSObject *)plugin { + [RtcEnginePluginRegistrantSwift register:plugin]; +} + ++ (void)unregister:(NSObject *)plugin { + [RtcEnginePluginRegistrantSwift unregister:plugin]; +} +@end diff --git a/RtcEnginePluginRegistrantSwift.swift b/RtcEnginePluginRegistrantSwift.swift new file mode 100644 index 000000000..5def4c618 --- /dev/null +++ b/RtcEnginePluginRegistrantSwift.swift @@ -0,0 +1,11 @@ +import Foundation + +@objc public class RtcEnginePluginRegistrantSwift: NSObject { + @objc public static func register(_ plugin: RtcEnginePlugin) { + RtcEngineRegistry.shared.add(plugin) + } + + @objc public static func unregister(_ plugin: RtcEnginePlugin) { + RtcEngineRegistry.shared.remove(plugin) + } +} diff --git a/RtcEngineRegistry.swift b/RtcEngineRegistry.swift new file mode 100644 index 000000000..ca4c7ebd9 --- /dev/null +++ b/RtcEngineRegistry.swift @@ -0,0 +1,61 @@ +import Foundation +import AgoraRtcKit + +fileprivate struct PluginKey: Hashable, Equatable { + let type: AnyClass + + public static func == (lhs: PluginKey, rhs: PluginKey) -> Bool { + return lhs.type == rhs.type + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(type)) + } +} + +/** + * The `RtcEngineRegistry` is response to add, remove and notify the callback when `RtcEngine` is created + * from flutter side. + */ +internal class RtcEngineRegistry : NSObject { + + private override init() {} + + static let shared = RtcEngineRegistry() + + private var plugins: [PluginKey : RtcEnginePlugin] = [PluginKey: RtcEnginePlugin]() + + /** + * Add a `RtcEnginePlugin`. + */ + func add(_ plugin: RtcEnginePlugin) { + let key = PluginKey(type: type(of: plugin)) + guard plugins[key] == nil else { + return + } + plugins[key] = plugin + } + + /** + * Remove the previously added `RtcEnginePlugin`. + */ + func remove(_ plugin: RtcEnginePlugin) { + plugins.removeValue(forKey: PluginKey(type: type(of: plugin))) + } +} + +extension RtcEngineRegistry : RtcEnginePlugin { + // MARK: - protocol from RtcEnginePlugin + public func onRtcEngineCreated(_ rtcEngine: AgoraRtcEngineKit?) { + for (_, plugin) in plugins { + plugin.onRtcEngineCreated(rtcEngine) + } + } + + // MARK: - protocol from RtcEnginePlugin + public func onRtcEngineDestroyed() { + for (_, plugin) in plugins { + plugin.onRtcEngineDestroyed() + } + } +} diff --git a/RtcSurfaceView.swift b/RtcSurfaceView.swift index 2856b3cf6..1cb7f72f9 100644 --- a/RtcSurfaceView.swift +++ b/RtcSurfaceView.swift @@ -1,33 +1,64 @@ -// -// RtcSurfaceView.swift -// RCTAgora -// -// Created by LXH on 2020/4/15. -// Copyright © 2020 Syan. All rights reserved. -// - +import AgoraRtcKit import Foundation import UIKit -import AgoraRtcKit class RtcSurfaceView: UIView { - private lazy var canvas: AgoraRtcVideoCanvas = { - var canvas = AgoraRtcVideoCanvas() - canvas.view = self - return canvas - }() - - func setRenderMode(_ engine: AgoraRtcEngineKit, _ renderMode: Int) { - canvas.renderMode = AgoraVideoRenderMode(rawValue: UInt(renderMode))! + private var surface: UIView + private var canvas: AgoraRtcVideoCanvas + private weak var channel: AgoraRtcChannel? + + override init(frame: CGRect) { + surface = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: frame.size)) + canvas = AgoraRtcVideoCanvas() + canvas.view = surface + super.init(frame: frame) + addSubview(surface) + addObserver(self, forKeyPath: observerForKeyPath(), options: .new, context: nil) + } + + func observerForKeyPath() -> String { + return "frame" + } + + @available(*, unavailable) + required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + canvas.view = nil + removeObserver(self, forKeyPath: observerForKeyPath(), context: nil) + } + + func setData(_ engine: AgoraRtcEngineKit, _ channel: AgoraRtcChannel?, _ uid: UInt) { + self.channel = channel + canvas.channelId = channel?.getId() + canvas.uid = uid + setupVideoCanvas(engine) + } + + func resetVideoCanvas(_ engine: AgoraRtcEngineKit) { + let canvas = AgoraRtcVideoCanvas() + canvas.view = nil + canvas.renderMode = self.canvas.renderMode + canvas.channelId = self.canvas.channelId + canvas.uid = self.canvas.uid + canvas.mirrorMode = self.canvas.mirrorMode + if canvas.uid == 0 { - engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) + engine.setupLocalVideo(canvas) } else { - engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) + engine.setupRemoteVideo(canvas) } } - func setChannelId(_ engine: AgoraRtcEngineKit, _ channelId: String) { - canvas.channelId = channelId + private func setupVideoCanvas(_ engine: AgoraRtcEngineKit) { + subviews.forEach { + $0.removeFromSuperview() + } + surface = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)) + addSubview(surface) + canvas.view = surface if canvas.uid == 0 { engine.setupLocalVideo(canvas) } else { @@ -35,21 +66,33 @@ class RtcSurfaceView: UIView { } } - func setMirroMode(_ engine: AgoraRtcEngineKit, _ mirrorMode: Int) { - canvas.mirrorMode = AgoraVideoMirrorMode(rawValue: UInt(mirrorMode))! + func setRenderMode(_ engine: AgoraRtcEngineKit, _ renderMode: UInt) { + canvas.renderMode = AgoraVideoRenderMode(rawValue: renderMode)! + setupRenderMode(engine) + } + + func setMirrorMode(_ engine: AgoraRtcEngineKit, _ mirrorMode: UInt) { + canvas.mirrorMode = AgoraVideoMirrorMode(rawValue: mirrorMode)! + setupRenderMode(engine) + } + + private func setupRenderMode(_ engine: AgoraRtcEngineKit) { if canvas.uid == 0 { engine.setLocalRenderMode(canvas.renderMode, mirrorMode: canvas.mirrorMode) } else { - engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) + if let channel = channel { + channel.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) + } else { + engine.setRemoteRenderMode(canvas.uid, renderMode: canvas.renderMode, mirrorMode: canvas.mirrorMode) + } } } - func setUid(_ engine: AgoraRtcEngineKit, _ uid: Int) { - canvas.uid = UInt(uid) - if canvas.uid == 0 { - engine.setupLocalVideo(canvas) - } else { - engine.setupRemoteVideo(canvas) + override func observeValue(forKeyPath keyPath: String?, of _: Any?, change: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) { + if keyPath == observerForKeyPath() { + if let rect = change?[.newKey] as? CGRect { + surface.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: rect.size) + } } } }