Visual_Novel_iOS/crush/Crush/Src/Components/Audio/SpeechManager.swift

137 lines
3.6 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// SpeechManager.swift
// Crush
//
// Created by Leon on 2025/8/1.
//
import Foundation
class SpeechManager {
// MARK: - Properties
static let shared = SpeechManager()
private weak var currentModel: SpeechModel?
private var timer: TimerModel?
private var timerCount: Int = 0
private init() {}
// MARK: - Private Methods
private func model(withPath path: String) -> SpeechModel {
let model = SpeechModel()
model.path = path
return model
}
private func timerAction() {
timerCount -= 1
DispatchQueue.main.async {[weak self] in
guard let `self` = self else {
return
}
currentModel?.timerChangedBlock?(TimeInterval(timerCount/10))
}
if let model = currentModel, model.isPlaying {
if timerCount <= 0 {
stopPlay(with: model)
}
} else {
timer?.pauseTimer()
}
if timerCount < -10000 {
timerCount = 0
}
//dlog("SpeechManager timerAction___\(timerCount)")
}
// MARK: - Lazy Timer
private var timerInstance: TimerModel {
if timer == nil {
timer = TimerModel()
timer?.timerBlock = { [weak self] in
self?.timerAction()
}
}
return timer!
}
// MARK: - Public Methods
static func checkVoiceState() -> Bool {
// 🔥 Assuming PhoneManager and ChatRoomRoute are external dependencies
if PhoneManager.isInPhoneChannel() || ChatRoomRoute.isChatRoomOpen() {
UIWindow.key?.makeToast("toast_voice_channel_is_occupied")
dlog("toast_voice_channel_is_occupied")
return false
}
return true
}
func modelWithFilePath(_ path: String) -> SpeechModel {
let model = model(withPath: path)
model.fileType = .file
return model
}
func modelWithFileUrl(_ url: String) -> SpeechModel {
let model = model(withPath: url)
model.fileType = .url
return model
}
func modelWithBase64String(_ base64String: String) -> SpeechModel {
let model = model(withPath: base64String)
model.fileType = .base64
return model
}
func startPlay(with model: SpeechModel) {
guard model.loadState != .loading else { return }
if currentModel === model {
if currentModel?.isPlaying == true {
currentModel?.stopPlay()
return
}
}
if let current = currentModel {
stopPlay(with: current)
}
model.canAutoPlay = true
if model.needLoadData() {
model.loadSpeechFile()
currentModel = model
} else {
currentModel = model
timerCount = model.audioTime
model.startPlay()
timerInstance.startTimer()
}
}
func stopPlay(with model: SpeechModel) {
model.canAutoPlay = false
// model.stateChangedBlock = nil
model.stopPlay()
if model === currentModel {
timerInstance.pauseTimer()
}
}
func stopPlayCurrent() {
if let model = currentModel {
stopPlay(with: model)
}
}
}
// 🔥 Placeholder for external dependencies
class PhoneManager {
static func isInPhoneChannel() -> Bool { return false } // 🔥 Placeholder
}
class ChatRoomRoute {
static func isChatRoomOpen() -> Bool { return false } // 🔥 Placeholder
}