Browse Source

Merge remote-tracking branch 'github/new_dev' into new_dev

newdev_shunjiawei
lxm 1 year ago
parent
commit
6ff2fa1959
  1. 118
      local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift
  2. 2
      local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift
  3. 10
      local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift
  4. 3
      local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift

118
local_plugins/agent_service/ios/agent_service/Sources/agent_service/AudioSessionHub.swift

@ -541,11 +541,19 @@ public class AudioSessionHub {
} }
private func performVolumeControlWithMPVolumeView(action: VolumeControlAction, value: Float?, completion: @escaping (Bool, String) -> Void) { private func performVolumeControlWithMPVolumeView(action: VolumeControlAction, value: Float?, completion: @escaping (Bool, String) -> Void) {
// 创建更大的 frame,有助于子视图正确初始化 // 确保在有音频会话的情况下进行音量控制
do {
try audioSession.setActive(true)
// 设置为播放类别,这样音量控制才能生效
try audioSession.setCategory(.playback, mode: .default, options: [])
} catch {
os_log("设置音频会话失败: %{public}@", log: logger, type: .error, error.localizedDescription)
}
let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) let volumeView = MPVolumeView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
volumeView.showsVolumeSlider = true volumeView.showsVolumeSlider = true
volumeView.showsRouteButton = false volumeView.showsRouteButton = false
volumeView.alpha = 0.01 // 几乎透明 volumeView.alpha = 0.01
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.windows.first else { let window = windowScene.windows.first else {
@ -557,71 +565,63 @@ public class AudioSessionHub {
volumeView.setNeedsLayout() volumeView.setNeedsLayout()
volumeView.layoutIfNeeded() volumeView.layoutIfNeeded()
var retryCount = 0 // 增加延迟时间,确保滑块完全初始化
let maxRetries = 5 DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
func findSliderRecursively(in view: UIView) -> UISlider? {
func attemptVolumeControl() { if let slider = view as? UISlider {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { return slider
os_log("尝试第 %d 次音量控制", log: self.logger, type: .debug, retryCount + 1) }
for subview in view.subviews {
// 递归查找滑块 if let foundSlider = findSliderRecursively(in: subview) {
func findSliderRecursively(in view: UIView) -> UISlider? { return foundSlider
if let slider = view as? UISlider {
return slider
}
for subview in view.subviews {
if let foundSlider = findSliderRecursively(in: subview) {
return foundSlider
}
} }
return nil
} }
return nil
}
if let slider = findSliderRecursively(in: volumeView) {
let currentValue = slider.value
let newValue: Float
if let slider = findSliderRecursively(in: volumeView) { switch action {
let currentValue = slider.value case .increase:
let newValue: Float newValue = min(currentValue + 0.1, 1.0) // 改回0.1避免变化过大
case .decrease:
switch action { newValue = max(currentValue - 0.1, 0.0)
case .increase: case .mute:
newValue = min(currentValue + 0.2, 1.0) // 从 0.1 改为 0.2 (20%) newValue = 0.0
case .decrease: case .setMax:
newValue = max(currentValue - 0.2, 0.0) // 从 0.1 改为 0.2 (20%) newValue = 1.0
case .mute: case .setValue(let val):
newValue = 0.0 newValue = max(0.0, min(val, 1.0))
case .setMax: }
newValue = 1.0
case .setValue(let val): os_log("设置音量从 %.2f 到 %.2f", log: self.logger, type: .info, currentValue, newValue)
newValue = max(0.0, min(val, 1.0))
} // 模拟用户触摸操作
slider.setValue(newValue, animated: true)
os_log("设置音量从 %.2f 到 %.2f", log: self.logger, type: .info, currentValue, newValue) slider.sendActions(for: .touchDown)
slider.sendActions(for: .valueChanged)
slider.sendActions(for: .touchUpInside)
// 再次确认设置
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
slider.value = newValue slider.value = newValue
slider.sendActions(for: .valueChanged) slider.sendActions(for: .valueChanged)
slider.sendActions(for: .touchUpInside)
let message = self.getVolumeActionMessage(action: action)
completion(true, message)
volumeView.removeFromSuperview()
} else {
retryCount += 1
if retryCount < maxRetries {
os_log("音量控制重试 %d/%d", log: self.logger, type: .debug, retryCount, maxRetries)
attemptVolumeControl()
} else {
os_log("所有重试都失败,使用备选方案", log: self.logger, type: .error)
volumeView.removeFromSuperview()
// 备选方案:至少记录当前音量状态
let currentVolume = self.audioSession.outputVolume
let message = "音量控制请求已处理(当前音量: \(Int(currentVolume * 100))%)"
completion(true, message)
}
} }
let message = self.getVolumeActionMessage(action: action)
completion(true, message)
volumeView.removeFromSuperview()
} else {
os_log("无法找到音量滑块", log: self.logger, type: .error)
volumeView.removeFromSuperview()
// 提供用户友好的反馈
let message = "音量控制需要在播放音频时才能生效,请先播放音频后再调整音量"
completion(false, message)
} }
} }
attemptVolumeControl()
} }
private func getVolumeActionMessage(action: VolumeControlAction) -> String { private func getVolumeActionMessage(action: VolumeControlAction) -> String {

2
local_plugins/azure_speech/ios/azure_speech/Sources/tools/SimpleAudioReceiver.swift

@ -561,7 +561,7 @@ private func convertAudioBuffer(_ buffer: AVAudioPCMBuffer, to targetFormat: AVA
* @throws 音频会话配置失败时抛出错误 * @throws 音频会话配置失败时抛出错误
*/ */
private func setupAudioSession() throws { private func setupAudioSession() throws {
try audioSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth]) try audioSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker, .allowBluetooth,.mixWithOthers])
try audioSession.setActive(true) try audioSession.setActive(true)
// // 设置首选的音频参数 - 修改为16000Hz以匹配Azure Speech要求 // // 设置首选的音频参数 - 修改为16000Hz以匹配Azure Speech要求

10
local_plugins/chat_api/ios/chat_api/Sources/chat_api/QQMusicSystemFunctionHandler.swift

@ -205,7 +205,7 @@ private class QQMusicSearchHandler: FunctionHandler {
private class QQMusicPauseHandler: FunctionHandler { private class QQMusicPauseHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
QPlayAutoManager.shared.pause() QPlayAutoManager.shared.pause()
let result: [String: Any] = ["success": true, "message": "Music paused"] let result: [String: Any] = ["success": true,"broadcast": false, "message": "Music paused"]
let jsonData = try JSONSerialization.data(withJSONObject: result) let jsonData = try JSONSerialization.data(withJSONObject: result)
return String(data: jsonData, encoding: .utf8) ?? "{}" return String(data: jsonData, encoding: .utf8) ?? "{}"
} }
@ -214,7 +214,7 @@ private class QQMusicPauseHandler: FunctionHandler {
private class QQMusicResumeHandler: FunctionHandler { private class QQMusicResumeHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
QPlayAutoManager.shared.play() QPlayAutoManager.shared.play()
let result: [String: Any] = ["success": true, "message": "Music resumed"] let result: [String: Any] = ["success": true,"broadcast": false, "message": "Music resumed"]
let jsonData = try JSONSerialization.data(withJSONObject: result) let jsonData = try JSONSerialization.data(withJSONObject: result)
return String(data: jsonData, encoding: .utf8) ?? "{}" return String(data: jsonData, encoding: .utf8) ?? "{}"
} }
@ -223,7 +223,7 @@ private class QQMusicResumeHandler: FunctionHandler {
private class QQMusicStopHandler: FunctionHandler { private class QQMusicStopHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
QPlayAutoManager.shared.stop() QPlayAutoManager.shared.stop()
let result: [String: Any] = ["success": true, "message": "Music stopped"] let result: [String: Any] = ["success": true,"broadcast": false, "message": "Music stopped"]
let jsonData = try JSONSerialization.data(withJSONObject: result) let jsonData = try JSONSerialization.data(withJSONObject: result)
return String(data: jsonData, encoding: .utf8) ?? "{}" return String(data: jsonData, encoding: .utf8) ?? "{}"
} }
@ -232,7 +232,7 @@ private class QQMusicStopHandler: FunctionHandler {
private class QQMusicNextHandler: FunctionHandler { private class QQMusicNextHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
QPlayAutoManager.shared.next() QPlayAutoManager.shared.next()
let result: [String: Any] = ["success": true, "message": "Skipped to next song"] let result: [String: Any] = ["success": true, "broadcast": false, "message": "Skipped to next song"]
let jsonData = try JSONSerialization.data(withJSONObject: result) let jsonData = try JSONSerialization.data(withJSONObject: result)
return String(data: jsonData, encoding: .utf8) ?? "{}" return String(data: jsonData, encoding: .utf8) ?? "{}"
} }
@ -241,7 +241,7 @@ private class QQMusicNextHandler: FunctionHandler {
private class QQMusicPreviousHandler: FunctionHandler { private class QQMusicPreviousHandler: FunctionHandler {
func handle(arguments: [String: Any]) async throws -> String { func handle(arguments: [String: Any]) async throws -> String {
QPlayAutoManager.shared.previous() QPlayAutoManager.shared.previous()
let result: [String: Any] = ["success": true, "message": "Skipped to previous song"] let result: [String: Any] = ["success": true, "broadcast": false, "message": "Skipped to previous song"]
let jsonData = try JSONSerialization.data(withJSONObject: result) let jsonData = try JSONSerialization.data(withJSONObject: result)
return String(data: jsonData, encoding: .utf8) ?? "{}" return String(data: jsonData, encoding: .utf8) ?? "{}"
} }

3
local_plugins/qq_music/ios/qq_music/Sources/qq_music/QPlayAutoManager.swift

@ -840,9 +840,6 @@ extension QPlayAutoManager: QPlayAutoSDKDelegate {
for weakDelegate in delegates { for weakDelegate in delegates {
weakDelegate.delegate?.onConnectStateChanged?(newState) weakDelegate.delegate?.onConnectStateChanged?(newState)
} }
if newState == QPlayAutoConnectState.disconnect {
connect(forceLogin: false)
}
} }
public func onQPlayAutoPlayStateChanged(_ playState: QPlayAutoPlayState, song: QPlayAutoListItem, position: Int) { public func onQPlayAutoPlayStateChanged(_ playState: QPlayAutoPlayState, song: QPlayAutoListItem, position: Int) {

Loading…
Cancel
Save