From c9fe56c74e6d54e85637e98c1feff74656eb738d Mon Sep 17 00:00:00 2001 From: Max Cobb Date: Wed, 29 Sep 2021 13:58:04 +0100 Subject: [PATCH 1/4] added additional way to access all delegate methods. also changed os elsifs to check macos, rather than just else --- .../Agora-UIKit/AgoraCollectionViewer.swift | 12 +- Sources/Agora-UIKit/AgoraConnectionData.swift | 4 +- .../AgoraRtmController+AgoraRtmDelegate.swift | 7 +- .../AgoraRtmController+MuteRequests.swift | 4 +- ...raRtmController+RtmDelegateOverflows.swift | 48 +++ Sources/Agora-UIKit/AgoraSettings.swift | 7 +- .../AgoraSingleVideoView+RtmDelegate.swift | 2 +- .../AgoraSingleVideoView+RtmOptions.swift | 4 +- .../Agora-UIKit/AgoraSingleVideoView.swift | 14 +- ...raVideoViewer+AgoraRtcEngineDelegate.swift | 11 + .../AgoraVideoViewer+Buttons.swift | 20 +- .../AgoraVideoViewer+Ordering.swift | 10 +- .../AgoraVideoViewer+Permissions.swift | 4 +- ...ideoViewer+RtcEngineDelegateOverflow.swift | 350 ++++++++++++++++++ .../AgoraVideoViewer+Utilities.swift | 2 +- .../AgoraVideoViewer+VideoControl.swift | 8 +- Sources/Agora-UIKit/AgoraVideoViewer.swift | 18 +- Sources/Agora-UIKit/UIButton+Extensions.swift | 8 +- 18 files changed, 475 insertions(+), 58 deletions(-) create mode 100644 Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift create mode 100644 Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift diff --git a/Sources/Agora-UIKit/AgoraCollectionViewer.swift b/Sources/Agora-UIKit/AgoraCollectionViewer.swift index 3adf6a25..d5b8d24c 100644 --- a/Sources/Agora-UIKit/AgoraCollectionViewer.swift +++ b/Sources/Agora-UIKit/AgoraCollectionViewer.swift @@ -35,7 +35,7 @@ public class AgoraCollectionViewer: MPCollectionView { self.backgroundColor = UIColor.secondarySystemBackground.withAlphaComponent(0.9) self.register(AgoraCollectionItem.self, forCellWithReuseIdentifier: "collectionCell") } - #else + #elseif os(macOS) init(frame: CGRect, collectionViewLayout layout: MPCollectionViewLayout) { super.init(frame: frame) self.collectionViewLayout = layout @@ -90,7 +90,7 @@ open class AgoraCollectionItem: MPCollectionViewCell { #if os(iOS) avv.frame = self.bounds self.addSubview(avv) - #else + #elseif os(macOS) avv.frame = self.view.bounds self.view.addSubview(avv) #endif @@ -114,7 +114,7 @@ open class AgoraCollectionItem: MPCollectionViewCell { required public init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - #else + #elseif os(macOS) override public func loadView() { self.view = NSView(frame: .zero) } @@ -188,7 +188,7 @@ extension AgoraVideoViewer: MPCollectionViewDelegate, MPCollectionViewDataSource fatalError("cell not valid") } } - #else + #elseif os(macOS) public func collectionView( _ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath ) -> NSCollectionViewItem { @@ -236,7 +236,7 @@ extension AgoraVideoViewer: MPCollectionViewDelegate, MPCollectionViewDataSource internal func displayItem(_ item: MPCollectionViewCell, at indexPath: IndexPath) { #if os(iOS) let newVid = self.collectionViewVideos[indexPath.row] - #else + #elseif os(macOS) let newVid = self.collectionViewVideos[indexPath.item] #endif guard let cell = item as? AgoraCollectionItem else { @@ -272,7 +272,7 @@ extension AgoraVideoViewer: MPCollectionViewDelegate, MPCollectionViewDataSource guard let agoraColItem = collectionView.cellForItem(at: indexPath) as? AgoraCollectionItem else { return } - #else + #elseif os(macOS) guard let agoraColItem = collectionView.item(at: indexPath) as? AgoraCollectionItem else { return } diff --git a/Sources/Agora-UIKit/AgoraConnectionData.swift b/Sources/Agora-UIKit/AgoraConnectionData.swift index abb7ffb2..52f8319c 100644 --- a/Sources/Agora-UIKit/AgoraConnectionData.swift +++ b/Sources/Agora-UIKit/AgoraConnectionData.swift @@ -7,7 +7,7 @@ #if os(iOS) import UIKit.UIDevice -#else +#elseif os(macOS) import IOKit #endif @@ -116,7 +116,7 @@ public struct AgoraConnectionData { guard let vendorId = UIDevice.current.identifierForVendor?.uuidString else { fatalError("Could not generate vendor Id") } - #else + #elseif os(macOS) let vendorId = AgoraConnectionData.fetchSerialMd5() #endif self.rtcId = AgoraConnectionData.uidFrom(vendor: vendorId) diff --git a/Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift b/Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift index 4034d46c..3abc74eb 100644 --- a/Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift +++ b/Sources/Agora-UIKit/AgoraRtmController+AgoraRtmDelegate.swift @@ -7,7 +7,7 @@ #if os(iOS) import UIKit.UIDevice -#else +#elseif os(macOS) import IOKit #endif import AgoraRtmKit @@ -22,6 +22,7 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate { callback: self.newTokenFetched(result:) ) } + self.delegate.agSettings.rtmDelegate?.rtmKitTokenDidExpire?(kit) } /** @@ -35,6 +36,7 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate { if let rawMsg = message as? AgoraRtmRawMessage { self.decodeRawMessage(rawMsg: rawMsg, from: peerId) } + self.delegate.agSettings.rtmDelegate?.rtmKit?(kit, messageReceived: message, fromPeer: peerId) } /** @@ -51,6 +53,7 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate { */ open func channel(_ channel: AgoraRtmChannel, memberJoined member: AgoraRtmMember) { self.sendPersonalData(to: member.userId) + self.delegate.agSettings.rtmChannelDelegate?.channel?(channel, memberJoined: member) } /** @@ -70,6 +73,7 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate { if let rawMsg = message as? AgoraRtmRawMessage { self.decodeRawMessage(rawMsg: rawMsg, from: member.userId) } + self.delegate.agSettings.rtmChannelDelegate?.channel?(channel, messageReceived: message, from: member) } /// Decode an incoming AgoraRtmRawMessage @@ -108,5 +112,4 @@ extension AgoraRtmController: AgoraRtmDelegate, AgoraRtmChannelDelegate { } } } - } diff --git a/Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift b/Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift index 8c567ae7..a39fc0a9 100644 --- a/Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift +++ b/Sources/Agora-UIKit/AgoraRtmController+MuteRequests.swift @@ -7,7 +7,7 @@ #if os(iOS) import UIKit -#else +#elseif os(macOS) import AppKit #endif @@ -147,7 +147,7 @@ extension AgoraVideoViewer { alert.addAction(UIAlertAction(title: "Accept", style: .default, handler: setDevice)) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) self.presentAlert(alert: alert, animated: true) - #else + #elseif os(macOS) let alert = NSAlert() alert.addButton(withTitle: "Confirm") alert.addButton(withTitle: "Cancel") diff --git a/Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift b/Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift new file mode 100644 index 00000000..85cf60cf --- /dev/null +++ b/Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift @@ -0,0 +1,48 @@ +// +// AgoraRtmController+RtmDelegateOverflows.swift +// +// +// Created by Max Cobb on 29/09/2021. +// + +import AgoraRtmKit + +extension AgoraRtmController { + open func rtmKit(_ kit: AgoraRtmKit, peersOnlineStatusChanged onlineStatus: [AgoraRtmPeerOnlineStatus]) { + self.agoraSettings.rtmDelegate?.rtmKit?(kit, peersOnlineStatusChanged: onlineStatus) + } + open func rtmKit(_ kit: AgoraRtmKit, fileMessageReceived message: AgoraRtmFileMessage, fromPeer peerId: String) { + self.agoraSettings.rtmDelegate?.rtmKit?(kit, fileMessageReceived: message, fromPeer: peerId) + } + open func rtmKit(_ kit: AgoraRtmKit, imageMessageReceived message: AgoraRtmImageMessage, fromPeer peerId: String) { + self.agoraSettings.rtmDelegate?.rtmKit?(kit, imageMessageReceived: message, fromPeer: peerId) + } + open func rtmKit(_ kit: AgoraRtmKit, media requestId: Int64, uploadingProgress progress: AgoraRtmMediaOperationProgress) { + self.agoraSettings.rtmDelegate?.rtmKit?(kit, media: requestId, uploadingProgress: progress) + } + open func rtmKit(_ kit: AgoraRtmKit, media requestId: Int64, downloadingProgress progress: AgoraRtmMediaOperationProgress) { + self.agoraSettings.rtmDelegate?.rtmKit?(kit, media: requestId, downloadingProgress: progress) + } + open func rtmKit(_ kit: AgoraRtmKit, connectionStateChanged state: AgoraRtmConnectionState, reason: AgoraRtmConnectionChangeReason) { + self.agoraSettings.rtmDelegate?.rtmKit?(kit, connectionStateChanged: state, reason: reason) + } +} + +extension AgoraRtmController { + open func channel(_ channel: AgoraRtmChannel, memberCount count: Int32) { + self.agoraSettings.rtmChannelDelegate?.channel?(channel, memberCount: count) + } + open func channel(_ channel: AgoraRtmChannel, memberLeft member: AgoraRtmMember) { + self.agoraSettings.rtmChannelDelegate?.channel?(channel, memberLeft: member) + } + open func channel(_ channel: AgoraRtmChannel, attributeUpdate attributes: [AgoraRtmChannelAttribute]) { + self.agoraSettings.rtmChannelDelegate?.channel?(channel, attributeUpdate: attributes) + } + open func channel(_ channel: AgoraRtmChannel, fileMessageReceived message: AgoraRtmFileMessage, from member: AgoraRtmMember) { + self.agoraSettings.rtmChannelDelegate?.channel?(channel, fileMessageReceived: message, from: member) + } + open func channel(_ channel: AgoraRtmChannel, imageMessageReceived message: AgoraRtmImageMessage, from member: AgoraRtmMember) { + self.agoraSettings.rtmChannelDelegate?.channel?(channel, imageMessageReceived: message, from: member) + } +} + diff --git a/Sources/Agora-UIKit/AgoraSettings.swift b/Sources/Agora-UIKit/AgoraSettings.swift index 1b3040b8..5d4a0f0b 100644 --- a/Sources/Agora-UIKit/AgoraSettings.swift +++ b/Sources/Agora-UIKit/AgoraSettings.swift @@ -6,9 +6,14 @@ // import AgoraRtcKit +import AgoraRtmKit /// Settings used for the display and behaviour of AgoraVideoViewer public struct AgoraSettings { + + var rtcDelegate: AgoraRtcEngineDelegate? + var rtmDelegate: AgoraRtmDelegate? + var rtmChannelDelegate: AgoraRtmChannelDelegate? /// URL to fetch tokens from. If supplied, this package will automatically fetch tokens /// when the Agora Engine indicates it will be needed. /// It will follow the URL pattern found in @@ -146,7 +151,7 @@ public struct AgoraSettings { #if os(iOS) /// Scale of the icons within the buttons in the builtin button tray static var buttonIconScale: UIImage.SymbolScale = .large - #else + #elseif os(macOS) /// Font size of the builtin buttons SF Symbol text static var buttonIconSize: CGFloat = 20 #endif diff --git a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift index adddf213..feeb7c01 100644 --- a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift +++ b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmDelegate.swift @@ -7,7 +7,7 @@ #if os(iOS) import UIKit -#else +#elseif os(macOS) import AppKit #endif diff --git a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift index 4e76c550..e0ce72da 100644 --- a/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift +++ b/Sources/Agora-UIKit/AgoraSingleVideoView+RtmOptions.swift @@ -8,7 +8,7 @@ import Foundation #if os(iOS) import UIKit -#else +#elseif os(macOS) import AppKit #endif @@ -101,7 +101,7 @@ extension AgoraSingleVideoView { AgoraVideoViewer.agoraPrint(.error, message: "invalid action title: \(actionTitle)") } } - #else + #elseif os(macOS) /// Options button has been selected, now display available requests /// - Parameter sender: Button that was selected @objc public func optionsBtnSelected(sender: NSPopUpButton) { diff --git a/Sources/Agora-UIKit/AgoraSingleVideoView.swift b/Sources/Agora-UIKit/AgoraSingleVideoView.swift index 2c6a170c..1e0904e6 100644 --- a/Sources/Agora-UIKit/AgoraSingleVideoView.swift +++ b/Sources/Agora-UIKit/AgoraSingleVideoView.swift @@ -66,7 +66,7 @@ public class AgoraSingleVideoView: MPView { ) userOptionsBtn.layer.zPosition = 3 userOptionsBtn.tintColor = .systemGray - #else + #elseif os(macOS) let userOptionsBtn = NSPopUpButton(frame: .zero, pullsDown: true) // userOptionsBtn.wantsLayer = true @@ -82,7 +82,7 @@ public class AgoraSingleVideoView: MPView { ) userOptionsBtn.autoresizingMask = [.flexibleBottomMargin, .flexibleRightMargin] userOptionsBtn.addTarget(self, action: #selector(optionsBtnSelected), for: .touchUpInside) - #else + #elseif os(macOS) userOptionsBtn.isBordered = false userOptionsBtn.wantsLayer = true userOptionsBtn.layer?.backgroundColor = .clear @@ -103,7 +103,7 @@ public class AgoraSingleVideoView: MPView { #if os(iOS) let muteFlag = UIImageView(image: UIImage(systemName: MPButton.micSlashSymbol)) muteFlag.tintColor = self.micFlagColor - #else + #elseif os(macOS) let muteFlag = MPButton() muteFlag.font = .systemFont(ofSize: NSFont.systemFontSize * 1.5) muteFlag.attributedTitle = NSAttributedString( @@ -118,7 +118,7 @@ public class AgoraSingleVideoView: MPView { size: CGSize(width: 25, height: 25) ) muteFlag.autoresizingMask = [.flexibleBottomMargin, .flexibleLeftMargin] - #else + #elseif os(macOS) muteFlag.isBordered = false muteFlag.wantsLayer = true muteFlag.layer?.backgroundColor = .clear @@ -149,7 +149,7 @@ public class AgoraSingleVideoView: MPView { hostingView.frame = self.bounds #if os(iOS) hostingView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - #else + #elseif os(macOS) hostingView.autoresizingMask = [.width, .height] #endif self.canvas.view = hostingView @@ -177,7 +177,7 @@ public class AgoraSingleVideoView: MPView { withConfiguration: UIImage.SymbolConfiguration(scale: .large)), for: .normal ) - #else + #elseif os(macOS) backgroundView.wantsLayer = true backgroundView.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor let bgButton = MPButton() @@ -193,7 +193,7 @@ public class AgoraSingleVideoView: MPView { #if os(iOS) bgButton.autoresizingMask = [.flexibleWidth, .flexibleHeight] backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - #else + #elseif os(macOS) bgButton.autoresizingMask = [.width, .height] backgroundView.autoresizingMask = [.width, .height] #endif diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift b/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift index c0e2e42a..baf50c9e 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift @@ -29,6 +29,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { // Only show the camera options when we are a broadcaster self.getControlContainer().isHidden = !isHost self.rtmController?.broadcastPersonalData() + self.agSettings.rtcDelegate?.rtcEngine?(engine, didClientRoleChanged: oldRole, newRole: newRole) } /// New User joined the channel @@ -43,6 +44,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { ) { // Keeping track of all people in the session self.remoteUserIDs.insert(uid) + self.agSettings.rtcDelegate?.rtcEngine?(engine, didJoinedOfUid: uid, elapsed: elapsed) } /// This callback indicates the state change of the local audio stream, including the state of the audio recording and encoding, and allows you to troubleshoot issues when exceptions occur. @@ -68,6 +70,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { } } } + self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed) } /** @@ -99,6 +102,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { // and remove this view from the list self.removeUserVideo(with: uid) } + self.agSettings.rtcDelegate?.rtcEngine?(engine, didOfflineOfUid: uid, reason: reason) } /** @@ -119,6 +123,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { */ open func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { self.activeSpeaker = speakerUid + self.agSettings.rtcDelegate?.rtcEngine?(engine, activeSpeaker: speakerUid) } /** @@ -148,6 +153,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { default: break } + self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed) } /** @@ -170,6 +176,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { default: break } + self.agSettings.rtcDelegate?.rtcEngine?(engine, localVideoStateChange: state, error: error) } /** @@ -194,6 +201,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { default: break } + self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioStateChange: state, error: error) } /** @@ -211,6 +219,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { */ open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) { self.addLocalVideo()?.audioMuted = false + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFramePublished: elapsed) } /** @@ -229,6 +238,7 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { ) } self.delegate?.tokenDidExpire(engine) + self.agSettings.rtcDelegate?.rtcEngineRequestToken?(engine) } /** @@ -249,5 +259,6 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { ) } self.delegate?.tokenWillExpire(engine, tokenPrivilegeWillExpire: token) + self.agSettings.rtcDelegate?.rtcEngine?(engine, tokenPrivilegeWillExpire: token) } } diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift index 5e5c5d07..ac5b4034 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+Buttons.swift @@ -27,7 +27,7 @@ extension AgoraVideoViewer { container.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin] container.layer.cornerRadius = self.agoraSettings.buttonSize / 3 container.clipsToBounds = true - #else + #elseif os(macOS) container.frame = CGRect( origin: CGPoint(x: (self.bounds.width - CGFloat(contWidth)) / 2, y: 10), size: CGSize(width: contWidth, height: self.agoraSettings.buttonSize + buttonMargin * 2)) @@ -52,7 +52,7 @@ extension AgoraVideoViewer { let button = elem.element #if os(iOS) container.contentView.addSubview(button) - #else + #elseif os(macOS) container.addSubview(button) #endif button.frame = CGRect( @@ -71,7 +71,7 @@ extension AgoraVideoViewer { button.backgroundColor = self.agoraSettings.colors.buttonDefaultNormal button.tintColor = self.agoraSettings.colors.buttonTintColor } - #else + #elseif os(macOS) button.isBordered = false button.layer?.cornerRadius = buttonSize / 2 if elem.offset < builtinButtons.count { @@ -93,7 +93,7 @@ extension AgoraVideoViewer { ? self.agoraSettings.colors.camButtonNormal : self.agoraSettings.colors.camButtonSelected self.micButton?.backgroundColor = self.agoraSettings.micEnabled ? self.agoraSettings.colors.micButtonNormal : self.agoraSettings.colors.micButtonSelected - #else + #elseif os(macOS) self.camButton?.layer?.backgroundColor = ( self.agoraSettings.cameraEnabled ? self.agoraSettings.colors.camButtonNormal @@ -120,7 +120,7 @@ extension AgoraVideoViewer { } #if os(iOS) let container = UIVisualEffectView(effect: UIBlurEffect(style: .systemThinMaterial)) - #else + #elseif os(macOS) let container = NSVisualEffectView() container.blendingMode = .withinWindow container.material = .menu @@ -147,7 +147,7 @@ extension AgoraVideoViewer { ) #if os(iOS) button.addTarget(self, action: #selector(toggleCam), for: .touchUpInside) - #else + #elseif os(macOS) button.target = self button.action = #selector(self.toggleCam) #endif @@ -167,7 +167,7 @@ extension AgoraVideoViewer { ) #if os(iOS) button.addTarget(self, action: #selector(toggleMic), for: .touchUpInside) - #else + #elseif os(macOS) button.target = self button.action = #selector(toggleMic) #endif @@ -181,7 +181,7 @@ extension AgoraVideoViewer { open func getScreenShareButton() -> MPButton? { #if os(iOS) return nil - #else + #elseif os(macOS) if !self.agoraSettings.enabledButtons.contains(.screenShareButton) { return nil } if let ssButton = self.screenShareButton { return ssButton } @@ -219,7 +219,7 @@ extension AgoraVideoViewer { self.flipButton = button return button - #else + #elseif os(macOS) return nil #endif } @@ -235,7 +235,7 @@ extension AgoraVideoViewer { let button = MPButton.newToggleButton(unselected: MPButton.wandSymbol) #if os(iOS) button.addTarget(self, action: #selector(toggleBeautify), for: .touchUpInside) - #else + #elseif os(macOS) button.target = self button.action = #selector(toggleBeautify) #endif diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift index 4950f11c..830e3391 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift @@ -112,7 +112,7 @@ extension AgoraVideoViewer { .flexibleWidth, .flexibleHeight, .flexibleBottomMargin, .flexibleTopMargin, .flexibleLeftMargin, .flexibleRightMargin ] - #else + #elseif os(macOS) videoSessionView.autoresizingMask = [ .width, .height, .maxYMargin, .minYMargin, .maxXMargin, .minXMargin ] @@ -155,7 +155,7 @@ extension AgoraVideoViewer { .flexibleTopMargin, .flexibleBottomMargin, .flexibleWidth, .flexibleHeight ] - #else + #elseif os(macOS) videoSessionView.autoresizingMask = [.width, .height, .maxYMargin, .minYMargin, .maxXMargin, .minXMargin] #endif if self.agoraSettings.usingDualStream && videoID != self.userID { @@ -177,13 +177,13 @@ extension AgoraVideoViewer { if self.agoraSettings.floatPosition == .top { #if os(iOS) backgroundVideoHolder.frame.origin = CGPoint(x: 0, y: 100 + 2 * AgoraCollectionViewer.cellSpacing) - #else + #elseif os(macOS) backgroundVideoHolder.frame.origin = .zero #endif } else { #if os(iOS) backgroundVideoHolder.frame.origin = .zero - #else + #elseif os(macOS) backgroundVideoHolder.frame.origin = CGPoint(x: 0, y: 100 + 2 * AgoraCollectionViewer.cellSpacing) #endif } @@ -214,7 +214,7 @@ extension AgoraVideoViewer { } #if os(iOS) self.backgroundVideoHolder.autoresizingMask = [.flexibleWidth, .flexibleHeight] - #else + #elseif os(macOS) self.backgroundVideoHolder.autoresizingMask = [.width, .height] #endif diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift index 177ac9eb..ebf01497 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+Permissions.swift @@ -80,7 +80,7 @@ extension AgoraVideoViewer { URL(string: UIApplication.openSettingsURLString)!, options: [:] ) - #else + #elseif os(macOS) NSWorkspace.shared.open( URL(fileURLWithPath: "x-apple.systempreferences:com.apple.preference.security?Privacy_Camera") ) @@ -120,7 +120,7 @@ extension AgoraVideoViewer { DispatchQueue.main.async { self.delegate?.presentAlert(alert: alertView, animated: true) } - #else + #elseif os(macOS) let alertView = NSAlert() alertView.messageText = "Camera and Microphone" alertView.informativeText = "To become a host, you must enable the microphone and camera" diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift b/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift new file mode 100644 index 00000000..ba0367db --- /dev/null +++ b/Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift @@ -0,0 +1,350 @@ +// +// AgoraVideoViewer+RtcEngineDelegateOverflow.swift +// +// +// Created by Max Cobb on 29/09/2021. +// + +import AgoraRtcKit + +extension AgoraVideoViewer { + open func rtcEngineConnectionDidLost(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineConnectionDidLost?(engine) + } + + open func rtcEngineLocalAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineLocalAudioMixingDidFinish?(engine) + } + + open func rtcEngineRemoteAudioMixingDidStart(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineRemoteAudioMixingDidStart?(engine) + } + + open func rtcEngineRemoteAudioMixingDidFinish(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineRemoteAudioMixingDidFinish?(engine) + } + + open func rtcEngineVideoDidStop(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineVideoDidStop?(engine) + } + + open func rtcEngineCameraDidReady(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineCameraDidReady?(engine) + } + + open func rtcEngineTranscodingUpdated(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineTranscodingUpdated?(engine) + } + + open func rtcEngineConnectionDidBanned(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineConnectionDidBanned?(engine) + } + + open func rtcEngineAirPlayIsConnected(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineAirPlayIsConnected?(engine) + } + + open func rtcEngineMediaEngineDidLoaded(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineMediaEngineDidLoaded?(engine) + } + + open func rtcEngineConnectionDidInterrupted(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineConnectionDidInterrupted?(engine) + } + + open func rtcEngineMediaEngineDidStartCall(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineMediaEngineDidStartCall?(engine) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurWarning warningCode: AgoraWarningCode) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didOccurWarning: warningCode) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didOccurError: errorCode) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didLeaveChannelWith: stats) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, networkTypeChangedTo type: AgoraNetworkType) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, networkTypeChangedTo: type) + } + + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFrame elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFrame: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalPublishFallbackToAudioOnly isFallbackOrRecover: Bool) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didLocalPublishFallbackToAudioOnly: isFallbackOrRecover) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioRouteChanged routing: AgoraAudioOutputRouting) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioRouteChanged: routing) + } + + #if os(iOS) + open func rtcEngine(_ engine: AgoraRtcEngineKit, cameraFocusDidChangedTo rect: CGRect) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, cameraFocusDidChangedTo: rect) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, cameraExposureDidChangedTo rect: CGRect) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, cameraExposureDidChangedTo: rect) + } + #elseif os(macOS) + public func rtcEngine(_ engine: AgoraRtcEngineKit, device deviceId: String, type deviceType: AgoraMediaDeviceType, stateChanged state: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, device: deviceId, type: deviceType, stateChanged: state) + } + #endif + + open func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, reportRtcStats: stats) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileQuality quality: AgoraNetworkQuality) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, lastmileQuality: quality) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, lastmileProbeTest result: AgoraLastmileProbeResult) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, lastmileProbeTest: result) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStats stats: AgoraRtcLocalVideoStats) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, localVideoStats: stats) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStats stats: AgoraRtcLocalAudioStats) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioStats: stats) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStats stats: AgoraRtcRemoteVideoStats) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStats: stats) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStats stats: AgoraRtcRemoteAudioStats) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStats: stats) + } + + open func rtcEngineDidAudioEffectFinish(_ engine: AgoraRtcEngineKit, soundId: Int) { + self.agSettings.rtcDelegate?.rtcEngineDidAudioEffectFinish?(engine, soundId: soundId) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didReceive event: AgoraChannelMediaRelayEvent) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didReceive: event) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, streamUnpublishedWithUrl url: String) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, streamUnpublishedWithUrl: url) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didMicrophoneEnabled enabled: Bool) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didMicrophoneEnabled: enabled) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFramePublished elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalVideoFramePublished: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, reportAudioVolumeIndicationOfSpeakers speakers: [AgoraRtcAudioVolumeInfo], totalVolume: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, reportAudioVolumeIndicationOfSpeakers: speakers, totalVolume: totalVolume) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didRegisteredLocalUser userAccount: String, withUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didRegisteredLocalUser: userAccount, withUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didUpdatedUserInfo userInfo: AgoraUserInfo, withUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didUpdatedUserInfo: userInfo, withUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, connectionChangedTo state: AgoraConnectionStateType, reason: AgoraConnectionChangedReason) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, connectionChangedTo: state, reason: reason) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalVideoFrameWith size: CGSize, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalVideoFrameWith: size, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoMuted muted: Bool, byUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoMuted: muted, byUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didRemoteSubscribeFallbackToAudioOnly isFallbackOrRecover: Bool, byUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didRemoteSubscribeFallbackToAudioOnly: isFallbackOrRecover, byUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioMixingStateDidChanged state: AgoraAudioMixingStateCode, reason: AgoraAudioMixingReasonCode) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioMixingStateDidChanged: state, reason: reason) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, channelMediaRelayStateDidChange state: AgoraChannelMediaRelayState, error: AgoraChannelMediaRelayError) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, channelMediaRelayStateDidChange: state, error: error) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameOfUid uid: UInt, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteAudioFrameOfUid: uid, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteAudioFrameDecodedOfUid uid: UInt, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteAudioFrameDecodedOfUid: uid, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioMuted muted: Bool, byUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioMuted: muted, byUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, streamPublishedWithUrl url: String, errorCode: AgoraErrorCode) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, streamPublishedWithUrl: url, errorCode: errorCode) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoEnabled enabled: Bool, byUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoEnabled: enabled, byUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didLocalVideoEnabled enabled: Bool, byUid uid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didLocalVideoEnabled: enabled, byUid: uid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingEventWithUrl url: String, eventCode: AgoraRtmpStreamingEvent) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, rtmpStreamingEventWithUrl: url, eventCode: eventCode) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, virtualBackgroundSourceEnabled enabled: Bool, reason: AgoraVirtualBackgroundSourceStateReason) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, virtualBackgroundSourceEnabled: enabled, reason: reason) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, facePositionDidChangeWidth width: Int32, previewHeight height: Int32, faces: [AgoraFacePositionInfo]?) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, facePositionDidChangeWidth: width, previewHeight: height, faces: faces) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didApiCallExecute error: Int, api: String, result: String) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didApiCallExecute: error, api: api, result: result) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didJoinChannel: channel, withUid: uid, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didRejoinChannel channel: String, withUid uid: UInt, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didRejoinChannel: channel, withUid: uid, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, videoSizeChangedOfUid uid: UInt, size: CGSize, rotation: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, videoSizeChangedOfUid: uid, size: size, rotation: rotation) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, networkQuality uid: UInt, txQuality: AgoraNetworkQuality, rxQuality: AgoraNetworkQuality) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, networkQuality: uid, txQuality: txQuality, rxQuality: rxQuality) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, rtmpStreamingChangedToState url: String, state: AgoraRtmpStreamingState, errorCode: AgoraRtmpStreamingErrorCode) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, rtmpStreamingChangedToState: url, state: state, errorCode: errorCode) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, streamInjectedStatusOfUrl url: String, uid: UInt, status: AgoraInjectStreamStatus) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, streamInjectedStatusOfUrl: url, uid: uid, status: status) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, receiveStreamMessageFromUid uid: UInt, streamId: Int, data: Data) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, receiveStreamMessageFromUid: uid, streamId: streamId, data: data) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoFrameOfUid uid: UInt, size: CGSize, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteVideoFrameOfUid: uid, size: size, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid: UInt, size: CGSize, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstRemoteVideoDecodedOfUid: uid, size: size, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, uploadLogResultRequestId requestId: String, success: Bool, reason: AgoraUploadErrorReason) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, uploadLogResultRequestId: requestId, success: success, reason: reason) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, superResolutionEnabledOfUid uid: UInt, enabled: Bool, reason: AgoraSuperResolutionStateReason) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, superResolutionEnabledOfUid: uid, enabled: enabled, reason: reason) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, audioTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, audioTransportStatsOfUid: uid, delay: delay, lost: lost, rxKBitRate: rxKBitRate) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, videoTransportStatsOfUid uid: UInt, delay: UInt, lost: UInt, rxKBitRate: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, videoTransportStatsOfUid: uid, delay: delay, lost: lost, rxKBitRate: rxKBitRate) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, audioQualityOfUid uid: UInt, quality: AgoraNetworkQuality, delay: UInt, lost: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, audioQualityOfUid: uid, quality: quality, delay: delay, lost: lost) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioPublishStateChange: channel, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoPublishStateChange channel: String, oldState: AgoraStreamPublishState, newState: AgoraStreamPublishState, elapseSinceLastState: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoPublishStateChange: channel, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didAudioSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didAudioSubscribeStateChange: channel, withUid: uid, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didVideoSubscribeStateChange channel: String, withUid uid: UInt, oldState: AgoraStreamSubscribeState, newState: AgoraStreamSubscribeState, elapseSinceLastState: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didVideoSubscribeStateChange: channel, withUid: uid, oldState: oldState, newState: newState, elapseSinceLastState: elapseSinceLastState) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurStreamMessageErrorFromUid uid: UInt, streamId: Int, error: Int, missed: Int, cached: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didOccurStreamMessageErrorFromUid: uid, streamId: streamId, error: error, missed: missed, cached: cached) + } +} + +/* +extension AgoraVideoViewer { + open func rtcEngineRequestToken(_ engine: AgoraRtcEngineKit) { + self.agSettings.rtcDelegate?.rtcEngineRequestToken?(engine) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, tokenPrivilegeWillExpire token: String) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, tokenPrivilegeWillExpire: token) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, activeSpeaker speakerUid: UInt) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, activeSpeaker: speakerUid) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, firstLocalAudioFramePublished elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, firstLocalAudioFramePublished: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didClientRoleChanged oldRole: AgoraClientRole, newRole: AgoraClientRole) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didClientRoleChanged: oldRole, newRole: newRole) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didJoinedOfUid: uid, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, didOfflineOfUid: uid, reason: reason) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, localVideoStateChange state: AgoraLocalVideoStreamState, error: AgoraLocalVideoStreamError) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, localVideoStateChange: state, error: error) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, localAudioStateChange state: AgoraAudioLocalState, error: AgoraAudioLocalError) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, localAudioStateChange: state, error: error) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteVideoStateChangedOfUid uid: UInt, state: AgoraVideoRemoteState, reason: AgoraVideoRemoteStateReason, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed) + } + + open func rtcEngine(_ engine: AgoraRtcEngineKit, remoteAudioStateChangedOfUid uid: UInt, state: AgoraAudioRemoteState, reason: AgoraAudioRemoteStateReason, elapsed: Int) { + self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed) + } + +} +*/ diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Utilities.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Utilities.swift index 64dcf433..bff8eb30 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+Utilities.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+Utilities.swift @@ -45,7 +45,7 @@ extension AgoraVideoViewer { self.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true self.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true self.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true - #else + #elseif os(macOS) self.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true self.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true #endif diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift b/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift index 734a6a63..462877e5 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+VideoControl.swift @@ -64,7 +64,7 @@ extension AgoraVideoViewer { #if os(iOS) camButton.backgroundColor = camButton.isOn ? self.agoraSettings.colors.camButtonSelected : self.agoraSettings.colors.camButtonNormal - #else + #elseif os(macOS) if !camButton.alternateTitle.isEmpty { swap(&camButton.title, &camButton.alternateTitle) } @@ -119,7 +119,7 @@ extension AgoraVideoViewer { #if os(iOS) micButton.backgroundColor = micButton.isOn ? self.agoraSettings.colors.micButtonSelected : self.agoraSettings.colors.micButtonNormal - #else + #elseif os(macOS) if !micButton.alternateTitle.isEmpty { swap(&micButton.title, &micButton.alternateTitle) } @@ -145,7 +145,7 @@ extension AgoraVideoViewer { #if os(iOS) ssButton.isSelected.toggle() ssButton.backgroundColor = ssButton.isSelected ? .systemGreen : .systemGray - #else + #elseif os(macOS) ssButton.layer?.backgroundColor = ( ssButton.isOn ? NSColor.systemGreen : NSColor.systemGray ).cgColor @@ -184,7 +184,7 @@ extension AgoraVideoViewer { beautifyButton.isSelected ? .timbreTransformationClear : .voiceBeautifierOff ) self.agkit.setBeautyEffectOptions(beautifyButton.isSelected, options: self.beautyOptions) - #else + #elseif os(macOS) beautifyButton.layer?.backgroundColor = ( beautifyButton.isOn ? NSColor.systemGreen : NSColor.systemGray).cgColor diff --git a/Sources/Agora-UIKit/AgoraVideoViewer.swift b/Sources/Agora-UIKit/AgoraVideoViewer.swift index feaf13af..a65b906d 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer.swift @@ -40,7 +40,7 @@ public protocol AgoraVideoViewerDelegate: AnyObject { func presentAlert(alert: UIAlertController, animated: Bool) /// An array of any additional buttons to be displayed alongside camera, and microphone buttons func extraButtons() -> [UIButton] - #else + #elseif os(macOS) /// An array of any additional buttons to be displayed alongside camera, and microphone buttons func extraButtons() -> [NSButton] #endif @@ -61,7 +61,7 @@ public extension AgoraVideoViewerDelegate { } } func extraButtons() -> [UIButton] { [] } - #else + #elseif os(macOS) func extraButtons() -> [NSButton] { [] } #endif func incomingPongRequest(from peerId: String) {} @@ -154,7 +154,7 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate { #if os(iOS) collView.frame.origin = .zero collView.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin] - #else + #elseif os(macOS) collView.frame.origin = CGPoint(x: 0, y: self.bounds.height - smallerDim) collView.autoresizingMask = [.width, .minYMargin] #endif @@ -162,7 +162,7 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate { #if os(iOS) collView.frame.origin = CGPoint(x: 0, y: self.bounds.height - smallerDim) collView.autoresizingMask = [.flexibleWidth, .flexibleTopMargin] - #else + #elseif os(macOS) collView.frame.origin = .zero collView.autoresizingMask = [.width, .maxYMargin] #endif @@ -174,21 +174,21 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate { collView.frame.origin = .zero #if os(iOS) collView.autoresizingMask = [.flexibleHeight, .flexibleRightMargin] - #else + #elseif os(macOS) collView.autoresizingMask = [.height, .maxXMargin] #endif } else { collView.frame.origin = CGPoint(x: self.bounds.width - smallerDim, y: 0) #if os(iOS) collView.autoresizingMask = [.flexibleHeight, .flexibleLeftMargin] - #else + #elseif os(macOS) collView.autoresizingMask = [.height, .minXMargin] #endif } } #if os(iOS) self.bringSubviewToFront(collView) - #else + #elseif os(macOS) self.addSubview(collView, positioned: .above, relativeTo: nil) #endif return collView @@ -200,7 +200,7 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate { #if os(iOS) self.addSubview(rtnView) self.sendSubviewToBack(rtnView) - #else + #elseif os(macOS) self.addSubview(rtnView, positioned: .below, relativeTo: nil) rtnView.wantsLayer = true rtnView.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor @@ -208,7 +208,7 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate { rtnView.frame = self.bounds #if os(iOS) rtnView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - #else + #elseif os(macOS) rtnView.autoresizingMask = [.width, .height] #endif // Had issues with `self.style == .collection`, so changed to switch case diff --git a/Sources/Agora-UIKit/UIButton+Extensions.swift b/Sources/Agora-UIKit/UIButton+Extensions.swift index 39320d0c..9d0ead5e 100644 --- a/Sources/Agora-UIKit/UIButton+Extensions.swift +++ b/Sources/Agora-UIKit/UIButton+Extensions.swift @@ -20,7 +20,7 @@ extension MPButton { static func newToggleButton(unselected: String, selected: String? = nil) -> MPButton { #if os(iOS) let button = MPButton(type: .custom) - #else + #elseif os(macOS) let button = MPButton() button.wantsLayer = true #endif @@ -30,7 +30,7 @@ extension MPButton { systemName: selected, withConfiguration: MPImage.SymbolConfiguration(scale: AgoraSettings.buttonIconScale) ), for: .selected) - #else + #elseif os(macOS) button.alternateTitle = selected #endif } @@ -39,7 +39,7 @@ extension MPButton { systemName: unselected, withConfiguration: MPImage.SymbolConfiguration(scale: AgoraSettings.buttonIconScale) ), for: .normal) - #else + #elseif os(macOS) button.title = unselected button.font = .systemFont(ofSize: AgoraSettings.buttonIconSize) #endif @@ -73,7 +73,7 @@ extension MPButton { get { self.isSelected } set { self.isSelected = newValue } } - #else + #elseif os(macOS) /// SF Symbol name for camera icon for builtin button static var videoSymbol = "􀌟" /// SF Symbol name for camera alt icon for builtin button From 903f3095e189d984c717ad0870f60a109b3dcdee Mon Sep 17 00:00:00 2001 From: Max Cobb Date: Wed, 29 Sep 2021 15:32:21 +0100 Subject: [PATCH 2/4] added docs, set delegates to weak, fixed swiftlint --- .jazzy.yaml | 4 +++- .swiftlint.yml | 2 ++ Sources/Agora-UIKit/AgoraCollectionViewer.swift | 12 ++++++++---- Sources/Agora-UIKit/AgoraSettings.swift | 15 ++++++++++++--- .../AgoraVideoViewer+AgoraRtcEngineDelegate.swift | 10 ++++++++-- .../Agora-UIKit/AgoraVideoViewer+Ordering.swift | 2 +- Sources/Agora-UIKit/AgoraVideoViewer.swift | 8 +++++++- 7 files changed, 41 insertions(+), 12 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 1c94eddb..9ed47d12 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -1,4 +1,6 @@ podspec: AgoraUIKit_iOS.podspec exclude: - Sources/Agora-UIKit/iOS+macOS+typealiases.swift - - Sources/Agora-UIKit/AgoraUIKit+MD5.swift \ No newline at end of file + - Sources/Agora-UIKit/AgoraUIKit+MD5.swift + - Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift + - Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml index c8891deb..dcc4b650 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,4 +3,6 @@ line_length: excluded: - Agora-*-Example - Sources/Agora-UIKit/AgoraUIKit+MD5.swift + - Sources/Agora-UIKit/AgoraRtmController+RtmDelegateOverflows.swift + - Sources/Agora-UIKit/AgoraVideoViewer+RtcEngineDelegateOverflow.swift - .build \ No newline at end of file diff --git a/Sources/Agora-UIKit/AgoraCollectionViewer.swift b/Sources/Agora-UIKit/AgoraCollectionViewer.swift index d5b8d24c..ea7c679f 100644 --- a/Sources/Agora-UIKit/AgoraCollectionViewer.swift +++ b/Sources/Agora-UIKit/AgoraCollectionViewer.swift @@ -219,14 +219,18 @@ extension AgoraVideoViewer: MPCollectionViewDelegate, MPCollectionViewDataSource } #endif - /// Video views to be displayed in the floating collection view. - var collectionViewVideos: [AgoraSingleVideoView] { + internal func refreshCollectionData() { switch self.style { case .floating, .collection: - return Array(self.userVideoLookup.values) + if self.agSettings.showSelf { + self.collectionViewVideos = Array(self.userVideoLookup.values) + } else { + self.collectionViewVideos = Array(self.userVideoLookup.filter { $0.key != self.userID}.values) + } default: - return [] + self.collectionViewVideos.removeAll() } + self.floatingVideoHolder.reloadData() } /// Both AppKit and UIKit delegate methods call this function, to have it all in one place diff --git a/Sources/Agora-UIKit/AgoraSettings.swift b/Sources/Agora-UIKit/AgoraSettings.swift index 5d4a0f0b..f376d84f 100644 --- a/Sources/Agora-UIKit/AgoraSettings.swift +++ b/Sources/Agora-UIKit/AgoraSettings.swift @@ -11,9 +11,15 @@ import AgoraRtmKit /// Settings used for the display and behaviour of AgoraVideoViewer public struct AgoraSettings { - var rtcDelegate: AgoraRtcEngineDelegate? - var rtmDelegate: AgoraRtmDelegate? - var rtmChannelDelegate: AgoraRtmChannelDelegate? + /// Delegate for Agora Rtc Engine callbacks + public weak var rtcDelegate: AgoraRtcEngineDelegate? + + /// Delegate for Agora RTM callbacks + public weak var rtmDelegate: AgoraRtmDelegate? + + /// Delegate for Agora RTM Channel callbacks + public weak var rtmChannelDelegate: AgoraRtmChannelDelegate? + /// URL to fetch tokens from. If supplied, this package will automatically fetch tokens /// when the Agora Engine indicates it will be needed. /// It will follow the URL pattern found in @@ -71,6 +77,9 @@ public struct AgoraSettings { /// You can call this method either before or after joining a channel. public var videoSource: AgoraVideoSourceProtocol? + /// Whether to show your own camera feed + public var showSelf: Bool = true + /// Settings for applying external videos public struct ExternalAudioSettings { /// Determines whether to enable the external audio source: diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift b/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift index baf50c9e..61815cc3 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+AgoraRtcEngineDelegate.swift @@ -70,7 +70,10 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { } } } - self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteAudioStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed) + self.agSettings.rtcDelegate?.rtcEngine?( + engine, remoteAudioStateChangedOfUid: uid, state: state, + reason: reason, elapsed: elapsed + ) } /** @@ -153,7 +156,10 @@ extension AgoraVideoViewer: AgoraRtcEngineDelegate { default: break } - self.agSettings.rtcDelegate?.rtcEngine?(engine, remoteVideoStateChangedOfUid: uid, state: state, reason: reason, elapsed: elapsed) + self.agSettings.rtcDelegate?.rtcEngine?( + engine, remoteVideoStateChangedOfUid: uid, state: state, + reason: reason, elapsed: elapsed + ) } /** diff --git a/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift b/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift index 830e3391..c7620d93 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer+Ordering.swift @@ -82,7 +82,7 @@ extension AgoraVideoViewer { } return } - self.floatingVideoHolder.reloadData() + self.refreshCollectionData() self.floatingVideoHolder.isHidden = self.collectionViewVideos.isEmpty self.organiseGrid() diff --git a/Sources/Agora-UIKit/AgoraVideoViewer.swift b/Sources/Agora-UIKit/AgoraVideoViewer.swift index a65b906d..3c20a181 100644 --- a/Sources/Agora-UIKit/AgoraVideoViewer.swift +++ b/Sources/Agora-UIKit/AgoraVideoViewer.swift @@ -314,16 +314,22 @@ open class AgoraVideoViewer: MPView, SingleVideoViewDelegate { internal var userVideosForGrid: [UInt: AgoraSingleVideoView] { if self.style == .floating { + if self.overrideActiveSpeaker == nil, self.activeSpeaker == nil, !self.agSettings.showSelf { + return [:] + } return self.userVideoLookup.filter { $0.key == (self.overrideActiveSpeaker ?? self.activeSpeaker ?? self.userID) } } else if self.style == .grid { - return self.userVideoLookup + return self.userVideoLookup.filter { ($0.key != self.userID || self.agSettings.showSelf) } } else { return [:] } } + /// Video views to be displayed in the floating collection view. + var collectionViewVideos: [AgoraSingleVideoView] = [] + /// Container for the buttons (such as mute, flip camera etc.) public var controlContainer: MPBlurView? var camButton: MPButton? From d64d419d35f1b6436fc04990e74778dc202307a6 Mon Sep 17 00:00:00 2001 From: Max Cobb Date: Wed, 29 Sep 2021 16:01:14 +0100 Subject: [PATCH 3/4] bump version numbers to 1.6.4 --- AgoraUIKit_iOS.podspec | 2 +- AgoraUIKit_macOS.podspec | 2 +- Sources/Agora-UIKit/AgoraUIKit.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AgoraUIKit_iOS.podspec b/AgoraUIKit_iOS.podspec index 8b9b39ba..63d5e09f 100644 --- a/AgoraUIKit_iOS.podspec +++ b/AgoraUIKit_iOS.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'AgoraUIKit_iOS' - s.version = '1.6.3' + s.version = '1.6.4' s.summary = 'Agora video session UIKit template.' s.description = <<-DESC diff --git a/AgoraUIKit_macOS.podspec b/AgoraUIKit_macOS.podspec index e1015047..ccb9c2e0 100644 --- a/AgoraUIKit_macOS.podspec +++ b/AgoraUIKit_macOS.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'AgoraUIKit_macOS' - s.version = '1.6.3' + s.version = '1.6.4' s.summary = 'Agora video session AppKit template.' s.description = <<-DESC diff --git a/Sources/Agora-UIKit/AgoraUIKit.swift b/Sources/Agora-UIKit/AgoraUIKit.swift index d6077686..3ebaf57b 100644 --- a/Sources/Agora-UIKit/AgoraUIKit.swift +++ b/Sources/Agora-UIKit/AgoraUIKit.swift @@ -22,7 +22,7 @@ public struct AgoraUIKit: Codable { /// Framework type of UIKit. "native", "flutter", "reactnative" fileprivate(set) var framework: String /// Version of UIKit being used - static let version = "1.6.3" + static let version = "1.6.4" /// Framework type of UIKit. "native", "flutter", "reactnative" static let framework = "native" #if os(iOS) From 3f63f7f51eea000fd83d89b223b6a87842f9869d Mon Sep 17 00:00:00 2001 From: Max Cobb Date: Wed, 29 Sep 2021 20:56:18 +0100 Subject: [PATCH 4/4] updated version to 4.0.0-preview.4 --- AgoraUIKit_iOS.podspec | 2 +- Sources/Agora-UIKit/AgoraUIKit.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AgoraUIKit_iOS.podspec b/AgoraUIKit_iOS.podspec index 468f5efc..a2c375c3 100644 --- a/AgoraUIKit_iOS.podspec +++ b/AgoraUIKit_iOS.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'AgoraUIKit_iOS' - s.version = '4.0.0-preview.3' + s.version = '4.0.0-preview.4' s.summary = 'Agora video session UIKit template.' s.description = <<-DESC diff --git a/Sources/Agora-UIKit/AgoraUIKit.swift b/Sources/Agora-UIKit/AgoraUIKit.swift index 38890c1a..8370eba5 100644 --- a/Sources/Agora-UIKit/AgoraUIKit.swift +++ b/Sources/Agora-UIKit/AgoraUIKit.swift @@ -22,7 +22,7 @@ public struct AgoraUIKit: Codable { /// Framework type of UIKit. "native", "flutter", "reactnative" fileprivate(set) var framework: String /// Version of UIKit being used - static let version = "4.0.0-preview.3" + static let version = "4.0.0-preview.4" /// Framework type of UIKit. "native", "flutter", "reactnative" static let framework = "native" #if os(iOS)