| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- //
- // MediaSettingViewModel.swift
- // TUIRoomKit
- //
- // Created by janejntang on 2023/1/16.
- // Copyright © 2023 Tencent. All rights reserved.
- //
- import Foundation
- import RTCRoomEngine
- #if canImport(TXLiteAVSDK_TRTC)
- import TXLiteAVSDK_TRTC
- #elseif canImport(TXLiteAVSDK_Professional)
- import TXLiteAVSDK_Professional
- #endif
- protocol MediaSettingViewEventResponder: AnyObject {
- func showResolutionAlert()
- func showFrameRateAlert()
- func showQualityView()
- func updateStackView(item: ListCellItemData)
- func makeToast(text: String)
- }
- class MediaSettingViewModel {
- private(set) var videoItems: [ListCellItemData] = []
- private(set) var audioItems: [ListCellItemData] = []
- private(set) var otherItems: [ListCellItemData] = []
- weak var viewResponder: MediaSettingViewEventResponder? = nil
- var engineManager: EngineManager {
- EngineManager.shared
- }
- var store: RoomStore {
- engineManager.store
- }
- var videoSetting: VideoModel {
- engineManager.store.videoSetting
- }
- var audioSetting: AudioModel {
- engineManager.store.audioSetting
- }
- let resolutionNameItems: [String] = [.smoothResolutionText, .standardResolutionText, .highResolutionText, .superResolutionText]
- private let resolutionItems: [TUIVideoQuality] = [.quality360P, .quality540P, .quality720P, .quality1080P]
- private let bitrateArray = [550, 850, 1_200, 2_000]
- let topItems: [String] = [.videoText, .audioText, .otherText]
- let frameRateArray = ["15", "20"]
-
- init() {
- createVideoItem()
- createAudioItem()
- createOtherItem()
- }
-
- private func createVideoItem() {
- let resolutionItem = ListCellItemData()
- resolutionItem.titleText = .resolutionText
- resolutionItem.hasOverAllAction = true
- resolutionItem.type = .resolutionType
- resolutionItem.hasDownLineView = true
- resolutionItem.hasRightButton = true
- let buttonData = ButtonItemData()
- if let resolutionName = getResolutionName(videoQuality: videoSetting.videoQuality) {
- buttonData.normalTitle = resolutionName
- }
- buttonData.orientation = .right
- buttonData.normalIcon = "room_down_arrow1"
- buttonData.resourceBundle = tuiRoomKitBundle()
- buttonData.titleFont = UIFont.systemFont(ofSize: 16, weight: .regular)
- buttonData.titleColor = UIColor(0xD1D9EC)
- buttonData.size = CGSize(width: 80, height: 30)
- buttonData.isEnabled = false
- resolutionItem.buttonData = buttonData
- resolutionItem.action = { [weak self] sender in
- guard let self = self else { return }
- self.resolutionAction()
- }
- videoItems.append(resolutionItem)
-
- let frameRateItem = ListCellItemData()
- frameRateItem.titleText = .frameRateText
- frameRateItem.hasOverAllAction = true
- frameRateItem.type = .frameRateType
- frameRateItem.hasRightButton = true
- let frameRateButtonData = ButtonItemData()
- frameRateButtonData.orientation = .right
- frameRateButtonData.normalIcon = "room_down_arrow1"
- frameRateButtonData.normalTitle = String(videoSetting.videoFps)
- frameRateButtonData.resourceBundle = tuiRoomKitBundle()
- frameRateButtonData.titleFont = UIFont.systemFont(ofSize: 16, weight: .regular)
- frameRateButtonData.titleColor = UIColor(0xD1D9EC)
- frameRateButtonData.size = CGSize(width: 80, height: 30)
- frameRateButtonData.isEnabled = false
- frameRateItem.buttonData = frameRateButtonData
- frameRateItem.action = { [weak self] sender in
- guard let self = self else { return }
- self.frameRateAction()
- }
- videoItems.append(frameRateItem)
- }
-
- private func createAudioItem() {
- let captureVolumeItem = ListCellItemData()
- captureVolumeItem.titleText = .captureVolumeText
- captureVolumeItem.hasSlider = true
- captureVolumeItem.hasSliderLabel = true
- captureVolumeItem.minimumValue = 0
- captureVolumeItem.maximumValue = 100
- captureVolumeItem.sliderStep = 1
- captureVolumeItem.sliderDefault = Float(audioSetting.captureVolume)
- captureVolumeItem.hasDownLineView = true
- captureVolumeItem.action = { [weak self] sender in
- guard let self = self, let view = sender as? UISlider else { return }
- self.captureVolumeAction(sender: view)
- }
- audioItems.append(captureVolumeItem)
-
- let playingVolumeItem = ListCellItemData()
- playingVolumeItem.titleText = .playVolumeText
- playingVolumeItem.hasSlider = true
- playingVolumeItem.hasSliderLabel = true
- playingVolumeItem.minimumValue = 0
- playingVolumeItem.maximumValue = 100
- playingVolumeItem.sliderStep = 1
- playingVolumeItem.sliderDefault = Float(audioSetting.playVolume)
- playingVolumeItem.hasDownLineView = true
- playingVolumeItem.action = { [weak self] sender in
- guard let self = self, let view = sender as? UISlider else { return }
- self.playingVolumeAction(sender: view)
- }
- audioItems.append(playingVolumeItem)
-
- let volumePromptItem = ListCellItemData()
- volumePromptItem.titleText = .volumePromptText
- volumePromptItem.hasSwitch = true
- volumePromptItem.isSwitchOn = audioSetting.volumePrompt
- volumePromptItem.action = { [weak self] sender in
- guard let self = self, let view = sender as? UISwitch else { return }
- self.volumePromptAction(sender: view)
- }
- audioItems.append(volumePromptItem)
- }
-
- private func resolutionAction() {
- viewResponder?.showResolutionAlert()
- }
-
- private func createOtherItem() {
- let qualityItem = ListCellItemData()
- qualityItem.titleText = .qualityInspectionText
- qualityItem.hasOverAllAction = true
- qualityItem.hasRightButton = true
- let buttonData = ButtonItemData()
- buttonData.orientation = .right
- buttonData.normalIcon = "room_right_arrow1"
- buttonData.resourceBundle = tuiRoomKitBundle()
- buttonData.titleFont = UIFont.systemFont(ofSize: 16, weight: .regular)
- buttonData.titleColor = UIColor(0xD1D9EC)
- buttonData.size = CGSize(width: 80, height: 30)
- buttonData.isEnabled = false
- qualityItem.buttonData = buttonData
- qualityItem.action = { [weak self] sender in
- guard let self = self else { return }
- self.showQualityAction()
- }
- otherItems.append(qualityItem)
-
- let floatChatItem = ListCellItemData()
- floatChatItem.titleText = .floatChatText
- floatChatItem.hasSwitch = true
- floatChatItem.isSwitchOn = store.shouldShowFloatChatView
- floatChatItem.action = { [weak self] sender in
- guard let self = self, let view = sender as? UISwitch else { return }
- self.floatChatShowAction(shouldShow: view.isOn)
- }
- otherItems.append(floatChatItem)
- }
-
- private func showQualityAction() {
- viewResponder?.showQualityView()
- }
-
- private func floatChatShowAction(shouldShow: Bool) {
- store.updateFloatChatShowState(shouldShow: shouldShow)
- }
-
- private func frameRateAction() {
- viewResponder?.showFrameRateAlert()
- }
-
- private func captureVolumeAction(sender: UISlider) {
- engineManager.setAudioCaptureVolume(Int(sender.value))
- }
-
- private func playingVolumeAction(sender: UISlider) {
- engineManager.setAudioPlayoutVolume(Int(sender.value))
- }
-
- private func volumePromptAction(sender: UISwitch) {
- engineManager.enableAudioVolumeEvaluation(isVolumePrompt: sender.isOn)
- }
-
- func changeResolutionAction(index: Int) {
- guard let videoItem = videoItems.first(where: { $0.type == .resolutionType }) else { return }
- guard let quality = resolutionItems[safe: index] else { return }
- guard let resolutionName = getResolutionName(videoQuality: quality) else { return }
- videoItem.buttonData?.normalTitle = resolutionName
- viewResponder?.updateStackView(item: videoItem)
- engineManager.setVideoEncoder(videoQuality: quality, bitrate: getBitrate(videoQuality: quality))
- }
-
- func changeFrameRateAction(index: Int) {
- guard let videoItem = videoItems.first(where: { $0.type == .frameRateType }) else { return }
- guard let frameRate = frameRateArray[safe: index] else { return }
- videoItem.buttonData?.normalTitle = frameRate
- viewResponder?.updateStackView(item: videoItem)
- engineManager.setVideoEncoder(fps: Int(frameRate))
- }
-
- func getCurrentResolutionIndex() -> Int {
- guard let index = resolutionItems.firstIndex(where: { $0 == videoSetting.videoQuality }) else { return 0 }
- return index
- }
-
- func getCurrentFrameRateIndex() -> Int {
- let frameRateString = String(videoSetting.videoFps)
- guard let index = frameRateArray.firstIndex(where: { $0 == frameRateString }) else { return 0 }
- return index
- }
-
- private func getResolutionName(videoQuality: TUIVideoQuality) -> String? {
- guard let index = resolutionItems.firstIndex(of: videoQuality) else { return nil }
- guard let resolutionName = resolutionNameItems[safe: index] else { return nil }
- return resolutionName
- }
-
- private func getBitrate(videoQuality: TUIVideoQuality) -> Int? {
- guard let index = resolutionItems.firstIndex(of: videoQuality) else { return nil }
- guard let bitrate = bitrateArray[safe: index] else { return nil }
- return bitrate
- }
-
- func reportSettingsPanelShow() {
- RoomKitReport.reportData(.metricsSettingsPanelShow)
- }
-
- deinit {
- debugPrint("deinit \(self)")
- }
- }
- private extension String {
- static var videoText: String {
- localized("Video Settings")
- }
- static var audioText: String {
- localized("Audio Settings")
- }
- static var otherText: String {
- localized("Other Settings")
- }
- static var versionLowToastText: String {
- localized("Your system version is below 12.0. Please update.")
- }
- static var resolutionText: String {
- localized("Resolution")
- }
- static var frameRateText: String {
- localized("Frame Rate")
- }
- static var bitrateText: String {
- localized("Bitrate")
- }
- static var localMirrorText: String {
- localized("Local Mirror")
- }
- static var captureVolumeText: String {
- localized("Capture Volume")
- }
- static var playVolumeText: String {
- localized("Playback Volume")
- }
- static var volumePromptText: String {
- localized("Volume Reminder")
- }
- static var audioRecordingText: String {
- localized("Audio Recording")
- }
- static var smoothResolutionText: String {
- localized("Smooth")
- }
- static var standardResolutionText: String {
- localized("Standard Definition")
- }
- static var highResolutionText: String {
- localized("High Definition")
- }
- static var superResolutionText: String {
- localized("Full High Definition")
- }
- static var qualityInspectionText: String {
- localized("Network Quality Monitoring")
- }
- static var floatChatText: String {
- localized("Floating Chat")
- }
- }
|