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.
This commit is contained in:
1 parent
09b6d437e5
commit
7b0a57fea7
2 files changed
+62
No files matched your search
@@ -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>
|
||||
protected override void OnReady()
|
||||
{
|
||||
ApplicationExit.Preparing += PrepareExit;
|
||||
AddToGroup("AudioService");
|
||||
SetupBuses();
|
||||
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 lastMusicsVolume = -1;
|
||||
private int lastAmbientVolume = -1;
|
||||
|
||||
@@ -46,6 +46,33 @@ namespace Cthangover.Mods.Audio
|
||||
/// </summary>
|
||||
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 bool playlistsInited;
|
||||
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>
|
||||
protected override void OnReady()
|
||||
{
|
||||
ApplicationExit.Preparing += PrepareExit;
|
||||
AddToGroup("music_player");
|
||||
TryFindAudioPlayer();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user