Compare commits

...
2 Commits
Author SHA1 Message Date
cthangover 918cc1f2b9 Update audio_base implementation, assets and documentation 2026-10-31 15:28:48 +03:00
cthangover 7b0a57fea7 Let audio stop and free its players before the application quits
AudioService handles ApplicationExit.Preparing: it stops playback and keeps the
main loop alive briefly for the mixer fade and deferred player destruction.
2026-10-29 13:21:39 +01:00
3 changed files with 62 additions and 0 deletions

No files matched your search

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 160 KiB

+34
View File
@@ -52,6 +52,7 @@ namespace Cthangover.Mods.Audio
/// <summary>Creates the three audio buses (Music/SFX/Ambient) if missing, the music and ambient players, and applies saved settings.</summary> /// <summary>Creates the three audio buses (Music/SFX/Ambient) if missing, the music and ambient players, and applies saved settings.</summary>
protected override void OnReady() protected override void OnReady()
{ {
ApplicationExit.Preparing += PrepareExit;
AddToGroup("AudioService"); AddToGroup("AudioService");
SetupBuses(); SetupBuses();
SetupMusicPlayer(); SetupMusicPlayer();
@@ -77,6 +78,39 @@ namespace Cthangover.Mods.Audio
} }
} }
/// <summary>Stops and detaches streams while the audio server still exists, including pooled sound players.</summary>
protected override void OnExitTree()
{
ApplicationExit.Preparing -= PrepareExit;
ReleasePlayer(musicPlayer);
ReleasePlayer(ambientPlayer);
foreach (var player in soundPlayers.Values) ReleasePlayer(player);
soundPlayers.Clear();
musicPlayer = null;
ambientPlayer = null;
}
private async System.Threading.Tasks.Task PrepareExit(SceneTree tree)
{
SetProcess(false);
ambientPlayer.Finished -= OnAmbientFinished;
ReleasePlayer(musicPlayer);
ReleasePlayer(ambientPlayer);
foreach (var player in soundPlayers.Values) ReleasePlayer(player);
// Stop is queued to the mixer. Keep the main loop alive for its fade
// and deferred playback destruction before SceneTree.Quit shuts the server down.
var deadline = Godot.Time.GetTicksMsec() + 150;
while (Godot.Time.GetTicksMsec() < deadline)
await ToSignal(tree, SceneTree.SignalName.ProcessFrame);
}
private static void ReleasePlayer(AudioStreamPlayer player)
{
if (!IsInstanceValid(player)) return;
player.Stop();
player.Stream = null;
}
private int lastSoundsVolume = -1; private int lastSoundsVolume = -1;
private int lastMusicsVolume = -1; private int lastMusicsVolume = -1;
private int lastAmbientVolume = -1; private int lastAmbientVolume = -1;
+28
View File
@@ -46,6 +46,33 @@ namespace Cthangover.Mods.Audio
/// </summary> /// </summary>
public bool IsCanAutoPlay { get; set; } = true; public bool IsCanAutoPlay { get; set; } = true;
/// <summary>Releases the pending fade and player reference when the audio mod leaves the tree.</summary>
protected override void OnExitTree()
{
ApplicationExit.Preparing -= PrepareExit;
StopForExit();
}
private System.Threading.Tasks.Task PrepareExit(SceneTree tree)
{
StopForExit();
return System.Threading.Tasks.Task.CompletedTask;
}
private void StopForExit()
{
IsCanAutoPlay = false;
SetProcess(false);
if (IsInstanceValid(fadeTween)) fadeTween.Kill();
fadeTween = null;
if (IsInstanceValid(audioPlayer))
{
audioPlayer.Stop();
audioPlayer.Stream = null;
}
audioPlayer = null;
}
private Tween fadeTween; private Tween fadeTween;
private bool playlistsInited; private bool playlistsInited;
private double autoAdvanceCooldown; private double autoAdvanceCooldown;
@@ -53,6 +80,7 @@ namespace Cthangover.Mods.Audio
/// <summary>Registers in the <c>music_player</c> group and locates the AudioService music player.</summary> /// <summary>Registers in the <c>music_player</c> group and locates the AudioService music player.</summary>
protected override void OnReady() protected override void OnReady()
{ {
ApplicationExit.Preparing += PrepareExit;
AddToGroup("music_player"); AddToGroup("music_player");
TryFindAudioPlayer(); TryFindAudioPlayer();
} }