import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:mymuseum_visitapp/Services/Glasses/engines/wake_word_engine.dart'; /// Wake word via OpenWakeWord — service Android natif (foreground service). /// Utilise ONNX Runtime pour l'inférence on-device du modèle hey_visit.onnx. /// Survit au background Android contrairement au STT continu. /// /// iOS non supporté — fallback sur SpeechToTextWakeWordEngine côté iOS. class OpenWakeWordEngine implements WakeWordEngine { static const _methodChannel = MethodChannel('be.unov.mymuseum/wake_word'); static const _eventChannel = EventChannel('be.unov.mymuseum/wake_word_events'); /// Nom du fichier .tflite dans assets/files (sans extension). /// Ex: "hey_visit", "hey_museum", "hey_guide" final String modelName; StreamSubscription? _subscription; void Function()? _onDetected; bool _running = false; OpenWakeWordEngine({this.modelName = 'hey_visit'}); @override Future start({ required void Function() onDetected, void Function(String command)? onDetectedWithCommand, }) async { if (_running) return; if (!_isAndroid) { debugPrint('[OpenWakeWordEngine] Android only — no-op on this platform'); return; } _onDetected = onDetected; _running = true; _subscription = _eventChannel.receiveBroadcastStream().listen( (event) { if (event == 'detected' && _running) { debugPrint('[OpenWakeWordEngine] Wake word detected'); // OpenWakeWord ne capture pas la commande inline — l'orchestrateur // lance un cycle STT séparé via onDetected() _onDetected?.call(); } }, onError: (e) => debugPrint('[OpenWakeWordEngine] Event error: $e'), ); await _methodChannel.invokeMethod('start', {'modelName': modelName}); debugPrint('[OpenWakeWordEngine] Service started (model: $modelName)'); } @override Future stop() async { if (!_running) return; _running = false; await _subscription?.cancel(); _subscription = null; if (_isAndroid) { await _methodChannel.invokeMethod('stop'); } debugPrint('[OpenWakeWordEngine] Service stopped'); } bool get _isAndroid => defaultTargetPlatform == TargetPlatform.android; }