Files
voice-cat/clients/apple/iOS/VoiceCatiOS/AudioSessionManager.swift

65 lines
2.3 KiB
Swift
Raw Normal View History

import AVFoundation
import VoiceCatCore
@MainActor
final class AudioSessionManager {
static let shared = AudioSessionManager()
weak var client: VoiceCatClient?
func configure() {
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(.playAndRecord, mode: .voiceChat,
options: [.allowBluetooth, .allowBluetoothA2DP,
.defaultToSpeaker, .mixWithOthers])
} catch {
print("[AudioSession] setCategory failed: \(error)")
}
NotificationCenter.default.addObserver(
self, selector: #selector(handleInterruption),
name: AVAudioSession.interruptionNotification, object: nil)
NotificationCenter.default.addObserver(
self, selector: #selector(handleRouteChange),
name: AVAudioSession.routeChangeNotification, object: nil)
}
func activateForStreaming() throws {
try AVAudioSession.sharedInstance().setActive(true, options: [])
}
func deactivateAfterStreaming() {
try? AVAudioSession.sharedInstance().setActive(false,
options: .notifyOthersOnDeactivation)
}
@objc private func handleInterruption(_ notification: Notification) {
guard let info = notification.userInfo,
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSession.InterruptionType(rawValue: typeValue)
else { return }
switch type {
case .began:
client?.audioSuspend()
case .ended:
let optionsValue = info[AVAudioSessionInterruptionOptionKey] as? UInt ?? 0
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
if options.contains(.shouldResume) {
try? AVAudioSession.sharedInstance().setActive(true)
client?.audioResume()
}
@unknown default: break
}
}
@objc private func handleRouteChange(_ notification: Notification) {
NotificationCenter.default.post(name: .voiceCatDeviceListChanged, object: nil)
}
}
extension Notification.Name {
static let voiceCatDeviceListChanged = Notification.Name("cat.voice.deviceListChanged")
}