58 lines
2.0 KiB
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)")
|
|
}
|
|
}
|
|
}
|