feat: Enhance audio management by implementing shutdown procedures on exit

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-23 17:36:49 +01:00
parent fdf84b3a9d
commit f4d6db2db0
2 changed files with 48 additions and 3 deletions
+27 -1
View File
@@ -143,6 +143,7 @@ class _GameScreenState extends State<GameScreen> {
DefaultRendererSettingsPersistence();
final DefaultSaveGamePersistence _savePersistence =
DefaultSaveGamePersistence();
Future<void>? _audioShutdownFuture;
/// Mirrors [WolfRendererSettings.mode] into the Flutter renderer enum.
RendererMode _rendererMode = RendererMode.hardware;
@@ -180,7 +181,7 @@ class _GameScreenState extends State<GameScreen> {
Navigator.of(context).pop();
},
onQuit: () {
SystemNavigator.pop();
unawaited(_quitApplication());
},
saveGamePersistence: _savePersistence,
);
@@ -210,6 +211,31 @@ class _GameScreenState extends State<GameScreen> {
}
}
@override
void dispose() {
unawaited(_shutdownAudioForExit());
super.dispose();
}
Future<void> _quitApplication() async {
await _shutdownAudioForExit();
await SystemNavigator.pop();
}
Future<void> _shutdownAudioForExit() {
final existing = _audioShutdownFuture;
if (existing != null) {
return existing;
}
final shutdown = () async {
await widget.wolf3d.audio.stopAllAudio();
widget.wolf3d.audio.dispose();
}();
_audioShutdownFuture = shutdown;
return shutdown;
}
@override
Widget build(BuildContext context) {
return PopScope(
@@ -21,6 +21,7 @@ class NativeSubprocessAudio implements EngineAudio, DebugMusicPlayer {
bool _initialized = false;
bool _isSupported = false;
bool _disposed = false;
_AudioBackend _backend = _AudioBackend.none;
String _windowsShellCommand = 'powershell';
@@ -32,7 +33,7 @@ class NativeSubprocessAudio implements EngineAudio, DebugMusicPlayer {
@override
Future<void> init() async {
if (_initialized) {
if (_initialized || _disposed) {
return;
}
@@ -49,7 +50,25 @@ class NativeSubprocessAudio implements EngineAudio, DebugMusicPlayer {
@override
void dispose() {
unawaited(stopAllAudio());
if (_disposed) {
return;
}
_disposed = true;
_musicLoopToken++;
_musicProcess?.kill();
_musicProcess = null;
for (final process in List<Process>.from(_sfxProcesses)) {
process.kill();
}
_sfxProcesses.clear();
final path = _musicTempFilePath;
_musicTempFilePath = null;
if (path != null) {
unawaited(_cleanupTempWav(path));
}
}
@override