Files
featherVoice/TUIKit/TUIRoomKit/Source/View/Model/EngineManager.swift

819 lines
32 KiB
Swift
Raw Normal View History

2025-08-08 10:49:36 +08:00
//
// EngineManager.swift
// TUIRoomKit
//
// Created by WesleyLei on 2022/9/22.
// Copyright © 2022 Tencent. All rights reserved.
//
import Foundation
import TUICore
import RTCRoomEngine
#if canImport(TXLiteAVSDK_TRTC)
import TXLiteAVSDK_TRTC
#elseif canImport(TXLiteAVSDK_Professional)
import TXLiteAVSDK_Professional
#endif
class EngineManager: NSObject {
static private(set) var shared = EngineManager()
private(set) lazy var store: RoomStore = {
let store = RoomStore()
return store
}()
private(set) var roomEngine = TUIRoomEngine.sharedInstance()
private lazy var eventDispatcher: RoomEventDispatcher = {
let eventDispatcher = RoomEventDispatcher()
return eventDispatcher
}()
private lazy var observer: TRTCObserver = {
let observer = TRTCObserver()
return observer
}()
private lazy var conferenceListObserver: ConferenceListObserver = {
return ConferenceListObserver()
}()
private lazy var conferenceListManager: TUIConferenceListManager? = {
guard let listManager = roomEngine.getExtension(extensionType: .conferenceListManager) as? TUIConferenceListManager else { return nil }
return listManager
}()
private let takeSeatTimeOutNumber: Double = 60
private let openRemoteDeviceTimeOutNumber: Double = 15
private let rootRouter: RoomRouter = RoomRouter.shared
private var isLoginEngine: Bool = false
private let appGroupString: String = "com.tencent.TUIRoomTXReplayKit-Screen"
override private init() {
super.init()
}
deinit {
debugPrint("deinit \(self)")
}
func setSelfInfo(userName: String, avatarURL: String, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
store.currentUser.userName = userName
store.currentUser.avatarUrl = avatarURL
TUIRoomEngine.setSelfInfo(userName: userName, avatarUrl: avatarURL) {
onSuccess()
} onError: { code, message in
onError(code, message)
debugPrint("---setSelfInfo,code:\(code),message:\(message)")
}
}
func createRoom(roomInfo: TUIRoomInfo, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
roomInfo.name = transferConferenceName(conferenceName: roomInfo.name)
if !isLoginEngine {
self.login(sdkAppId: Int(TUILogin.getSdkAppID()), userId: TUILogin.getUserID() ?? "", userSig: TUILogin.getUserSig() ?? "")
{ [weak self] in
guard let self = self else { return }
self.isLoginEngine = true
self.createEngineRoom(roomInfo: roomInfo, onSuccess: onSuccess, onError: onError)
} onError: { code, message in
onError(code, message)
}
} else {
createEngineRoom(roomInfo: roomInfo, onSuccess: onSuccess, onError: onError)
}
}
func enterRoom(roomId: String, options: TUIEnterRoomOptions? = nil, enableAudio: Bool, enableVideo: Bool, isSoundOnSpeaker: Bool,
onSuccess: @escaping TUIRoomInfoBlock, onError: @escaping TUIErrorBlock) {
store.videoSetting.isCameraOpened = enableVideo
store.audioSetting.isSoundOnSpeaker = isSoundOnSpeaker
setFramework()
if !isLoginEngine {
self.login(sdkAppId: Int(TUILogin.getSdkAppID()), userId: TUILogin.getUserID() ?? "", userSig: TUILogin.getUserSig() ?? "")
{ [weak self] in
guard let self = self else { return }
self.isLoginEngine = true
self.enterEngineRoom(roomId: roomId, options: options, enableAudio: enableAudio, onSuccess: onSuccess, onError: onError)
} onError: { code, message in
onError(code, message)
}
} else {
enterEngineRoom(roomId: roomId, options: options, enableAudio: enableAudio, onSuccess: onSuccess, onError: onError)
}
}
func exitRoom(onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.exitRoom(syncWaiting: false) { [weak self] in
guard let self = self else { return }
self.handleExitRoomResult()
onSuccess?()
} onError: { [weak self] code, message in
guard let self = self else { return }
self.handleExitRoomResult()
onError?(code, message)
}
}
func destroyRoom(onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.destroyRoom { [weak self] in
guard let self = self else { return }
self.handleDestroyRoomResult()
onSuccess?()
} onError: { [weak self] code, message in
guard let self = self else { return }
self.handleDestroyRoomResult()
onError?(code, message)
}
}
func destroyEngineManager() {
removeEngineObserver()
unsubLogoutNotification()
store = RoomStore()
}
func muteLocalAudio() {
roomEngine.muteLocalAudio()
}
func unmuteLocalAudio(onSuccess:TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.unmuteLocalAudio {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func openLocalMicrophone(onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
let actionBlock = { [weak self] in
guard let self = self else { return }
self.roomEngine.openLocalMicrophone(self.store.audioSetting.audioQuality) { [weak self] in
guard let self = self else { return }
self.store.audioSetting.isMicOpened = true
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
if RoomCommon.checkAuthorMicStatusIsDenied() {
actionBlock()
} else {
RoomCommon.micStateActionWithPopCompletion { granted in
if granted {
actionBlock()
}
}
}
}
func closeLocalCamera() {
store.videoSetting.isCameraOpened = false
roomEngine.closeLocalCamera()
}
func openLocalCamera(onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
let actionBlock = { [weak self] in
guard let self = self else { return }
self.store.videoSetting.isCameraOpened = true
self.roomEngine.openLocalCamera(isFront: self.store.videoSetting.isFrontCamera, quality:
self.store.videoSetting.videoQuality) {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
if RoomCommon.checkAuthorCamaraStatusIsDenied() {
actionBlock()
} else {
RoomCommon.cameraStateActionWithPopCompletion { granted in
if granted {
actionBlock()
}
}
}
}
func switchCamera() {
store.videoSetting.isFrontCamera = !store.videoSetting.isFrontCamera
roomEngine.getMediaDeviceManager().switchCamera(store.videoSetting.isFrontCamera)
}
func switchMirror() {
store.videoSetting.isMirror = !store.videoSetting.isMirror
let params = TRTCRenderParams()
params.mirrorType = store.videoSetting.isMirror ? .enable : .disable
setLocalRenderParams(params: params)
}
func muteAllAudioAction(isMute: Bool, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
store.roomInfo.isMicrophoneDisableForAllUser = isMute
roomEngine.disableDeviceForAllUserByAdmin(device: .microphone, isDisable:
store.roomInfo.isMicrophoneDisableForAllUser) {
onSuccess()
} onError: { code, message in
onError(code, message)
}
}
func muteAllVideoAction(isMute: Bool, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
store.roomInfo.isCameraDisableForAllUser = isMute
roomEngine.disableDeviceForAllUserByAdmin(device: .camera, isDisable:
store.roomInfo.isCameraDisableForAllUser) {
onSuccess()
} onError: { code, message in
onError(code, message)
}
}
func takeUserOnSeatByAdmin(userId: String, timeout: Double,
onAccepted: @escaping TUIRequestAcceptedBlock,
onRejected: @escaping TUIRequestRejectedBlock,
onCancelled: @escaping TUIRequestCancelledBlock,
onTimeout: @escaping TUIRequestTimeoutBlock,
onError: @escaping TUIRequestErrorBlock) {
roomEngine.takeUserOnSeatByAdmin(-1, userId: userId, timeout: timeout) { requestId, userId in
onAccepted(requestId, userId)
} onRejected: { requestId, userId, message in
onRejected( requestId, userId, message)
} onCancelled: { requestId, userId in
onCancelled(requestId, userId)
} onTimeout: { requestId, userId in
onTimeout(requestId, userId)
} onError: { requestId, userId, code, message in
onError(requestId, userId, code, message)
}
}
func setAudioRoute(isSoundOnSpeaker: Bool) {
store.audioSetting.isSoundOnSpeaker = isSoundOnSpeaker
let route: TUIAudioRoute = isSoundOnSpeaker ? .speakerphone : .earpiece
roomEngine.getMediaDeviceManager().setAudioRoute(route)
}
func takeSeat(onAccepted: TUIRequestAcceptedBlock? = nil,
onRejected: TUIRequestRejectedBlock? = nil,
onCancelled: TUIRequestCancelledBlock? = nil,
onTimeout: TUIRequestTimeoutBlock? = nil,
onError: TUIRequestErrorBlock? = nil) -> TUIRequest {
let request = self.roomEngine.takeSeat(-1, timeout: takeSeatTimeOutNumber) { [weak self] requestId, userId in
guard let self = self else { return }
self.store.currentUser.isOnSeat = true
self.store.selfTakeSeatRequestId = nil
onAccepted?(requestId, userId)
} onRejected: { [weak self] requestId, userId, message in
guard let self = self else { return }
self.store.selfTakeSeatRequestId = nil
onRejected?(requestId, userId, message)
} onCancelled: { [weak self] requestId, userId in
guard let self = self else { return }
self.store.selfTakeSeatRequestId = nil
onCancelled?(requestId, userId)
} onTimeout: { [weak self] requestId, userId in
guard let self = self else { return }
self.store.selfTakeSeatRequestId = nil
onTimeout?(requestId, userId)
} onError: { [weak self] requestId, userId, code, message in
guard let self = self else { return }
self.store.selfTakeSeatRequestId = nil
onError?(requestId, userId, code, message)
}
store.selfTakeSeatRequestId = request.requestId
return request
}
func cancelTakeSeatRequest() {
guard let requestId = store.selfTakeSeatRequestId else { return }
cancelRequest(requestId)
store.selfTakeSeatRequestId = nil
}
func fetchRoomInfo(roomId: String ,onSuccess: TUIRoomInfoBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.fetchRoomInfo(roomId: roomId, roomType: .conference) { [weak self] roomInfo in
guard let self = self, let roomInfo = roomInfo else { return }
if roomId == self.store.roomInfo.roomId {
self.store.initialRoomInfo(roomInfo)
}
onSuccess?(roomInfo)
} onError: { code, message in
onError?(code, message)
debugPrint("fetchRoomInfo,code:\(code), message:\(message)")
}
}
func setLocalRenderParams(params: TRTCRenderParams) {
roomEngine.getTRTCCloud().setLocalRenderParams(params)
}
func setGSensorMode(mode: TRTCGSensorMode) {
roomEngine.getTRTCCloud().setGSensorMode(mode)
}
func setLocalVideoView(streamType: TUIVideoStreamType, view: UIView?) {
roomEngine.setLocalVideoView(streamType: streamType, view: view)
}
func changeUserRole(userId: String, role: TUIRole, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
roomEngine.changeUserRole(userId: userId, role: role, onSuccess: onSuccess, onError: onError)
}
func responseRemoteRequest(_ requestId: String, agree: Bool, onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.responseRemoteRequest(requestId, agree: agree) {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func getUserInfo(_ userId: String, onSuccess: @escaping TUIUserInfoBlock, onError: @escaping TUIErrorBlock) {
roomEngine.getUserInfo(userId, onSuccess: onSuccess, onError: onError)
}
func stopScreenCapture() {
roomEngine.stopScreenCapture()
}
func setVideoEncoder(videoQuality: TUIVideoQuality? = nil, bitrate: Int? = nil, fps: Int? = nil) {
let param = TUIRoomVideoEncoderParams()
store.videoSetting.videoQuality = videoQuality ?? store.videoSetting.videoQuality
param.videoResolution = store.videoSetting.videoQuality
store.videoSetting.videoBitrate = bitrate ?? store.videoSetting.videoBitrate
param.bitrate = store.videoSetting.videoBitrate
store.videoSetting.videoFps = fps ?? store.videoSetting.videoFps
param.fps = store.videoSetting.videoFps
roomEngine.updateVideoQualityEx(streamType: .cameraStream, params: param)
}
func cancelRequest(_ requestId: String, onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.cancelRequest(requestId) {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func leaveSeat(onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.leaveSeat {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func startScreenCapture() {
roomEngine.startScreenCapture(appGroup: appGroupString)
}
func stopPlayRemoteVideo(userId: String, streamType: TUIVideoStreamType) {
roomEngine.stopPlayRemoteVideo(userId: userId, streamType: streamType)
}
func setRemoteVideoView(userId: String, streamType: TUIVideoStreamType, view: UIView?) {
roomEngine.setRemoteVideoView(userId: userId, streamType: streamType, view: view)
}
func startPlayRemoteVideo(userId: String, streamType: TUIVideoStreamType, onSuccess: TUISuccessBlock? = nil,
onLoading: TUIPlayOnLoadingBlock? = nil, onError: TUIPlayOnErrorBlock? = nil) {
roomEngine.startPlayRemoteVideo(userId: userId, streamType: streamType, onPlaying: { _ in
guard let onSuccess = onSuccess else { return }
onSuccess()
}, onLoading: { userId in
guard let onLoading = onLoading else { return }
onLoading(userId)
}, onError: { userId, code, message in
guard let onError = onError else { return }
onError(userId, code, message)
})
}
func setAudioCaptureVolume(_ captureVolume: Int) {
store.audioSetting.captureVolume = captureVolume
roomEngine.getTRTCCloud().setAudioCaptureVolume(captureVolume)
}
func setAudioPlayoutVolume(_ playVolume: Int) {
store.audioSetting.playVolume = playVolume
roomEngine.getTRTCCloud().setAudioPlayoutVolume(playVolume)
}
func enableAudioVolumeEvaluation(isVolumePrompt: Bool) {
store.audioSetting.volumePrompt = isVolumePrompt
if isVolumePrompt {
roomEngine.getTRTCCloud().enableAudioVolumeEvaluation(300, enable_vad: true)
} else {
roomEngine.getTRTCCloud().enableAudioVolumeEvaluation(0, enable_vad: false)
}
}
func closeRemoteDeviceByAdmin(userId: String, device: TUIMediaDevice, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
roomEngine.closeRemoteDeviceByAdmin(userId: userId, device: device, onSuccess: onSuccess, onError: onError)
}
func openRemoteDeviceByAdmin(userId: String, device: TUIMediaDevice,
onAccepted: TUIRequestAcceptedBlock? = nil,
onRejected: TUIRequestRejectedBlock? = nil,
onCancelled: TUIRequestCancelledBlock? = nil,
onTimeout: TUIRequestTimeoutBlock? = nil,
onError: TUIRequestErrorBlock? = nil) {
roomEngine.openRemoteDeviceByAdmin(userId: userId, device: device, timeout: openRemoteDeviceTimeOutNumber, onAccepted: { requestId, userId in
onAccepted?(requestId, userId)
}, onRejected: { requestId, userId, message in
onRejected?(requestId, userId, message)
}, onCancelled: { requestId, userId in
onCancelled?(requestId, userId)
}, onTimeout: { requestId, userId in
onTimeout?(requestId, userId)
}) { requestId, userId, code, message in
onError?(requestId, userId, code, message)
}
}
func disableSendingMessageByAdmin(userId: String, isDisable: Bool, onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.disableSendingMessageByAdmin(userId: userId, isDisable: isDisable) {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func kickUserOffSeatByAdmin(userId: String, onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.kickUserOffSeatByAdmin(-1, userId: userId) {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func kickRemoteUserOutOfRoom(userId: String, onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
roomEngine.kickRemoteUserOutOfRoom(userId) {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
}
func initUserList(onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
self.getUserList(nextSequence: 0, localUserList: []) { [weak self] in
guard let self = self else { return }
if self.store.roomInfo.isSeatEnabled {
self.getSeatList {
onSuccess?()
} onError: { code, message in
onError?(code, message)
}
} else {
onSuccess?()
}
} onError: { code, message in
onError?(code, message)
}
}
func updateVideoQuality(quality: TUIVideoQuality) {
roomEngine.updateVideoQuality(quality)
}
func enableGravitySensor(enable: Bool) {
roomEngine.enableGravitySensor(enable: enable)
}
func setVideoResolutionMode(streamType: TUIVideoStreamType, resolutionMode: TUIResolutionMode) {
roomEngine.setVideoResolutionMode(streamType: streamType, resolutionMode: resolutionMode)
}
func changeRaiseHandNoticeState(isShown: Bool) {
store.isShownRaiseHandNotice = isShown
}
func setRemoteRenderParams(userId: String, streamType: TRTCVideoStreamType, params: TRTCRenderParams) {
roomEngine.getTRTCCloud().setRemoteRenderParams(userId, streamType: streamType, params: params)
}
func updateSeatApplicationList() {
roomEngine.getSeatApplicationList { [weak self] list in
guard let self = self else { return }
self.store.setInviteSeatList(list: list)
} onError: { code, message in
debugPrint("getSeatApplicationList,code:\(code),message:\(message)")
}
}
}
// MARK: - Private
extension EngineManager {
private func login(sdkAppId: Int, userId: String, userSig: String, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
V2TIMManager.sharedInstance().initSDK(Int32(sdkAppId), config: V2TIMSDKConfig())
store.currentUser.userId = userId
TUIRoomEngine.login(sdkAppId: sdkAppId, userId: userId, userSig: userSig) { [weak self] in
guard let self = self else { return }
self.isLoginEngine = true
onSuccess()
} onError: { code, message in
onError(code, message)
}
}
private func createEngineRoom(roomInfo: TUIRoomInfo, onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
guard !store.isEnteredRoom else {
if store.roomInfo.roomId == roomInfo.roomId {
RoomVideoFloatView.dismiss()
onSuccess()
} else {
onError(.failed, .inAnotherRoomText)
}
return
}
self.store.roomInfo = roomInfo
self.roomEngine.createRoom(roomInfo) {
onSuccess()
} onError: { [weak self] code, message in
guard let self = self else { return }
self.destroyEngineManager()
onError(code, message)
}
}
private func transferConferenceName(conferenceName: String?) -> String {
if let confName = conferenceName, !confName.isEmpty {
return confName
}
let selfInfo = TUIRoomEngine.getSelfInfo()
let name: String = selfInfo.userName.isEmpty ? selfInfo.userId : selfInfo.userName
return name + .quickConferenceText
}
private func enterEngineRoom(roomId: String, options: TUIEnterRoomOptions? = nil, enableAudio: Bool, onSuccess: @escaping TUIRoomInfoBlock, onError: @escaping TUIErrorBlock) {
guard !store.isEnteredRoom else {
if store.roomInfo.roomId == roomId {
onSuccess(store.roomInfo)
} else {
onError(.failed, .inAnotherRoomText)
}
return
}
if let options = options {
roomEngine.enterRoom(roomId, roomType: .conference, options: options) { [weak self] roomInfo in
guard let self = self else { return }
guard let roomInfo = roomInfo else { return }
self.handleEnterRoomResult(roomInfo: roomInfo, enableAudio: enableAudio, onSuccess: onSuccess, onError: onError)
} onError: { [weak self] code, message in
guard let self = self else { return }
self.destroyEngineManager()
onError(code, message)
}
} else {
roomEngine.enterRoom(roomId) { [weak self] roomInfo in
guard let self = self else { return }
guard let roomInfo = roomInfo else { return }
self.handleEnterRoomResult(roomInfo: roomInfo, enableAudio: enableAudio, onSuccess: onSuccess, onError: onError)
} onError: { [weak self] code, message in
guard let self = self else { return }
self.destroyEngineManager()
onError(code, message)
}
}
}
private func handleEnterRoomResult(roomInfo: TUIRoomInfo, enableAudio: Bool, onSuccess: @escaping TUIRoomInfoBlock, onError: @escaping TUIErrorBlock) {
//Update the room entry data stored
addEngineObserver()
store.initialRoomInfo(roomInfo)
store.initialRoomCurrentUser()
//Initialize user list
initUserList()
//Initialize video settings
initLocalVideoState()
subLogoutNotification()
updateSeatApplicationList()
if !isNeededAutoTakeSeat() {
operateLocalMicrophone(enableAudio: enableAudio)
updateCameraState()
store.initalEnterRoomMessage()
onSuccess(roomInfo)
} else {
autoTakeSeatForOwner { [weak self] in
guard let self = self else { return }
self.operateLocalMicrophone(enableAudio: enableAudio)
self.updateCameraState()
self.store.initalEnterRoomMessage()
onSuccess(roomInfo)
} onError: { [weak self] code, message in
guard let self = self else { return }
self.destroyEngineManager()
onError(code, message)
}
}
}
private func updateCameraState() {
if store.roomInfo.isSeatEnabled && !store.currentUser.isOnSeat {
store.videoSetting.isCameraOpened = false
return
}
operateLocalCamera()
}
private func isNeededAutoTakeSeat() -> Bool {
return store.roomInfo.isSeatEnabled && store.currentUser.userId == store.roomInfo.ownerId
}
private func autoTakeSeatForOwner(onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
_ = self.takeSeat() { _,_ in
onSuccess()
} onError: { _, _, code, message in
if code == .alreadyInSeat {
onSuccess()
} else {
onError(code, message)
}
}
}
private func isPushLocalAudioStream(enableAudio: Bool) -> Bool {
if !enableAudio {
return false
}
if store.roomInfo.isMicrophoneDisableForAllUser, store.currentUser.userId != store.roomInfo.ownerId {
return false
}
if store.roomInfo.isSeatEnabled, store.currentUser.userId != store.roomInfo.ownerId {
return false
}
return true
}
private func operateLocalMicrophone(enableAudio: Bool ,onSuccess: TUISuccessBlock? = nil, onError: TUIErrorBlock? = nil) {
if isPushLocalAudioStream(enableAudio: enableAudio) {
openLocalMicrophone()
} else if RoomCommon.checkAuthorMicStatusIsDenied() {
muteLocalAudio()
openLocalMicrophone()
}
}
private func operateLocalCamera() {
let openLocalCameraActionBlock = { [weak self] in
guard let self = self else { return }
setLocalVideoView(streamType: .cameraStream, view: nil)
openLocalCamera()
}
if store.videoSetting.isCameraOpened && !store.roomInfo.isCameraDisableForAllUser {
if RoomCommon.checkAuthorCamaraStatusIsDenied() {
openLocalCameraActionBlock()
} else {
RoomCommon.cameraStateActionWithPopCompletion { granted in
if granted {
openLocalCameraActionBlock()
}
}
}
}
}
private func initLocalVideoState() {
setVideoParam()
enableGravitySensor(enable: true)
setGSensorMode(mode: .uiFixLayout)
let resolutionMode: TUIResolutionMode = isLandscape ? .landscape : .portrait
setVideoResolutionMode(streamType: .cameraStream, resolutionMode: resolutionMode)
}
private func setVideoParam() {
setVideoEncoder(videoQuality: store.videoSetting.videoQuality, bitrate: store.videoSetting.videoBitrate,
fps: store.videoSetting.videoFps)
let params = TRTCRenderParams()
params.fillMode = .fill
params.rotation = ._0
setLocalRenderParams(params: params)
}
private func getUserList(nextSequence: Int, localUserList: [UserEntity], onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
roomEngine.getUserList(nextSequence: nextSequence) { [weak self] list, nextSequence in
guard let self = self else { return }
var localUserList = localUserList
list.forEach { userInfo in
if userInfo.userName.isEmpty {
userInfo.userName = userInfo.userId
}
let userModel = UserEntity()
userModel.update(userInfo: userInfo)
localUserList.append(userModel)
}
if nextSequence != 0 {
self.getUserList(nextSequence: nextSequence, localUserList: localUserList, onSuccess: onSuccess, onError: onError)
} else {
self.store.attendeeList = localUserList
onSuccess()
if !self.store.roomInfo.isSeatEnabled {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewVideoSeatView, param: [:])
}
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_RenewUserList, param: [:])
EngineEventCenter.shared.notifyEngineEvent(event: .onGetUserListFinished, param: [:])
}
} onError: { code, message in
onError(code, message)
debugPrint("getUserList:code:\(code),message:\(message)")
}
}
private func getSeatList(onSuccess: @escaping TUISuccessBlock, onError: @escaping TUIErrorBlock) {
roomEngine.getSeatList { [weak self] seatList in
guard let self = self else { return }
self.store.initialSeatList(seatList: seatList)
self.store.initialOffSeatList()
onSuccess()
} onError: { code, message in
onError(code, message)
debugPrint("getSeatList:code:\(code),message:\(message)")
}
}
private func addEngineObserver() {
roomEngine.addObserver(eventDispatcher)
roomEngine.getTRTCCloud().addDelegate(observer)
conferenceListManager?.addObserver(conferenceListObserver)
}
private func removeEngineObserver() {
roomEngine.removeObserver(eventDispatcher)
roomEngine.getTRTCCloud().removeDelegate(observer)
conferenceListManager?.removeObserver(conferenceListObserver)
}
private func subLogoutNotification() {
NotificationCenter.default.addObserver(self, selector: #selector(handleLogout),
name: NSNotification.Name.TUILogoutSuccess, object: nil)
}
private func unsubLogoutNotification() {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.TUILogoutSuccess, object: nil)
}
@objc private func handleLogout() {
destroyEngineManager()
}
private func handleDestroyRoomResult() {
destroyEngineManager()
EngineEventCenter.shared.notifyEngineEvent(event: .onDestroyedRoom, param: [ "roomId" : store.roomInfo.roomId ])
}
private func handleExitRoomResult() {
destroyEngineManager()
EngineEventCenter.shared.notifyEngineEvent(event: .onExitedRoom, param: [ "roomId" : store.roomInfo.roomId ])
}
}
// MARK: - TUIExtensionProtocol
extension EngineManager: TUIExtensionProtocol {
func getExtensionInfo(_ key: String, param: [AnyHashable: Any]?) -> [AnyHashable: Any] {
guard let param = param else {
return [:]
}
guard let roomId: String = param["roomId"] as? String else {
return [:]
}
if key == gRoomEngineKey {
return [key: roomEngine]
} else if key == gRoomInfoKey {
return [key: store.roomInfo]
} else if key == gLocalUserInfoKey {
return [key: store.currentUser]
} else {
return [:]
}
}
}
// MARK: - setFramework
extension EngineManager {
fileprivate static let TUIRoomKitFrameworkValue = 1
fileprivate static let TUIRoomKitComponentValue = 18
fileprivate static let IMComponentValue = 19
fileprivate static let TUIRoomKitLanguageValue = 3
private func setFramework() {
let componentValue = store.isImAccess ? EngineManager.IMComponentValue : EngineManager.TUIRoomKitComponentValue
let jsonStr = """
{
"api":"setFramework",
"params":{
"framework":\(EngineManager.TUIRoomKitFrameworkValue),
"component":\(componentValue),
"language":\(EngineManager.TUIRoomKitLanguageValue)
}
}
"""
TUIRoomEngine.callExperimentalAPI(jsonStr: jsonStr)
}
}
private extension String {
static var inAnotherRoomText: String {
localized("You are already in another conference")
}
static var quickConferenceText: String {
localized("'s quick meeting")
}
}