|
|
|
@ -17,12 +17,110 @@ public class AudioSessionHub { |
|
|
|
private let audioSession = AVAudioSession.sharedInstance() |
|
|
|
private var isInterrupted = false |
|
|
|
|
|
|
|
// 添加系统音量监听属性 |
|
|
|
private var systemVolumeObserver: NSKeyValueObservation? |
|
|
|
private var isVolumeBindingEnabled: Bool = true // 音量绑定开关 |
|
|
|
private var volumeBindingRatio: Float = 1.0 // 音量绑定比例 |
|
|
|
|
|
|
|
private init() { |
|
|
|
os_log("🎵 AudioSessionHub 开始初始化", log: logger, type: .info) |
|
|
|
setupNotifications() |
|
|
|
setupSystemVolumeBinding() // 设置系统音量绑定 |
|
|
|
os_log("🎵 AudioSessionHub 初始化完成", log: logger, type: .info) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 设置系统音量绑定 |
|
|
|
* 监听系统音量变化并同步到应用音量 |
|
|
|
*/ |
|
|
|
private func setupSystemVolumeBinding() { |
|
|
|
// 监听系统音量变化 |
|
|
|
systemVolumeObserver = audioSession.observe(\.outputVolume, options: [.new, .old]) { [weak self] session, change in |
|
|
|
guard let self = self, |
|
|
|
let newVolume = change.newValue, |
|
|
|
let oldVolume = change.oldValue, |
|
|
|
self.isVolumeBindingEnabled, |
|
|
|
abs(newVolume - oldVolume) > 0.01 else { return } |
|
|
|
|
|
|
|
DispatchQueue.main.async { |
|
|
|
self.syncAppVolumeWithSystem(systemVolume: newVolume) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
os_log("已设置系统音量绑定监听", log: logger, type: .info) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 同步应用音量与系统音量 |
|
|
|
* @param systemVolume 系统音量值 (0.0 - 1.0) |
|
|
|
*/ |
|
|
|
private func syncAppVolumeWithSystem(systemVolume: Float) { |
|
|
|
let targetAppVolume = systemVolume * volumeBindingRatio |
|
|
|
|
|
|
|
os_log("同步音量: 系统音量 %.2f -> 应用音量 %.2f (比例: %.2f)", |
|
|
|
log: logger, type: .info, systemVolume, targetAppVolume, volumeBindingRatio) |
|
|
|
|
|
|
|
// 更新所有音频播放器的音量 |
|
|
|
updateAllPlayersVolumeDirectly(targetAppVolume) |
|
|
|
|
|
|
|
// 发送音量同步通知 |
|
|
|
NotificationCenter.default.post( |
|
|
|
name: Notification.Name("VolumeBindingSync"), |
|
|
|
object: ["systemVolume": systemVolume, "appVolume": targetAppVolume] |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 启用或禁用音量绑定 |
|
|
|
* @param enabled 是否启用音量绑定 |
|
|
|
*/ |
|
|
|
public func setVolumeBindingEnabled(_ enabled: Bool) { |
|
|
|
isVolumeBindingEnabled = enabled |
|
|
|
os_log("音量绑定已%{public}@", log: logger, type: .info, enabled ? "启用" : "禁用") |
|
|
|
|
|
|
|
if enabled { |
|
|
|
// 立即同步当前系统音量 |
|
|
|
syncAppVolumeWithSystem(systemVolume: audioSession.outputVolume) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 设置音量绑定比例 |
|
|
|
* @param ratio 绑定比例 (0.0 - 2.0),1.0表示完全同步,0.5表示应用音量为系统音量的一半 |
|
|
|
*/ |
|
|
|
public func setVolumeBindingRatio(_ ratio: Float) { |
|
|
|
volumeBindingRatio = max(0.0, min(ratio, 2.0)) |
|
|
|
os_log("音量绑定比例设置为: %.2f", log: logger, type: .info, volumeBindingRatio) |
|
|
|
|
|
|
|
if isVolumeBindingEnabled { |
|
|
|
// 立即应用新比例 |
|
|
|
syncAppVolumeWithSystem(systemVolume: audioSession.outputVolume) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取当前系统音量 |
|
|
|
* @return 系统音量值 (0.0 - 1.0) |
|
|
|
*/ |
|
|
|
public func getSystemVolume() -> Float { |
|
|
|
return audioSession.outputVolume |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 直接更新所有播放器音量(不触发绑定逻辑) |
|
|
|
* @param volume 目标音量值 |
|
|
|
*/ |
|
|
|
private func updateAllPlayersVolumeDirectly(_ volume: Float) { |
|
|
|
// 这里需要你实现具体的播放器音量更新逻辑 |
|
|
|
// 例如更新 AudioPlayer 中的所有播放器实例 |
|
|
|
|
|
|
|
// 发送音量更新通知给 AudioPlayer |
|
|
|
NotificationCenter.default.post( |
|
|
|
name: Notification.Name("UpdatePlayerVolume"), |
|
|
|
object: volume |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
public static func initialize() { |
|
|
|
os_log("🎵 主动初始化 AudioSessionHub", log: shared.logger, type: .info) |
|
|
|
_ = shared // 触发单例初始化 |
|
|
|
|