mymuseum-visitapp/ios/Runner/AudioRoutingPlugin.swift

58 lines
2.0 KiB
Swift

// AudioRoutingPlugin.swift
// Force la sortie audio sur les lunettes Ray-Ban Meta via AVAudioSession.
// Pattern extrait de OpenGlasses (straff2002) WakeWordService.swift + GeminiLiveAudioManager.swift.
import Flutter
import AVFoundation
@objc class AudioRoutingPlugin: NSObject, FlutterPlugin {
static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "be.unov.mymuseum/audio_routing",
binaryMessenger: registrar.messenger()
)
let instance = AudioRoutingPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "enableBluetoothOutput":
enableBluetoothOutput()
result(nil)
case "restoreDefaultOutput":
restoreDefaultOutput()
result(nil)
default:
result(FlutterMethodNotImplemented)
}
}
private func enableBluetoothOutput() {
do {
let session = AVAudioSession.sharedInstance()
// Mode voiceChat + A2DP + HFP : pattern validé dans OpenGlasses
// pour jouer audio sur lunettes tout en gardant le micro disponible
try session.setCategory(
.playAndRecord,
mode: .voiceChat,
options: [.allowBluetoothHFP, .allowBluetoothA2DP, .defaultToSpeaker]
)
try session.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print("[AudioRoutingPlugin] enableBluetoothOutput error: \(error)")
}
}
private func restoreDefaultOutput() {
do {
let session = AVAudioSession.sharedInstance()
try session.setCategory(.playback, options: [])
try session.setActive(true)
} catch {
print("[AudioRoutingPlugin] restoreDefaultOutput error: \(error)")
}
}
}