1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-13 08:32:57 +08:00

Clean up previous sample immediately on skin source change to avoid Play after disposal

This seems to be the simplest way to avoid calls to `Play` after the
underlying sample may have been disposed. As per the issue thread, a
local workaround is acceptable here.

Closes #13223.
This commit is contained in:
Dean Herbert 2021-06-08 15:05:14 +09:00
parent 6ebac0b462
commit f3f634e969

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Audio;
@ -70,22 +71,48 @@ namespace osu.Game.Skinning
updateSample();
}
protected override void LoadComplete()
{
base.LoadComplete();
CurrentSkin.SourceChanged += skinChangedImmediate;
}
private void skinChangedImmediate()
{
// Clean up the previous sample immediately on a source change.
// This avoids a potential call to Play() of an already disposed sample (samples are disposed along with the skin, but SkinChanged is scheduled).
clearPreviousSamples();
}
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
updateSample();
}
/// <summary>
/// Whether this sample was playing before a skin source change.
/// </summary>
private bool wasPlaying;
private void clearPreviousSamples()
{
// only run if the samples aren't already cleared.
// this ensures the "wasPlaying" state is stored correctly even if multiple clear calls are executed.
if (!sampleContainer.Any()) return;
wasPlaying = Playing;
sampleContainer.Clear();
Sample = null;
}
private void updateSample()
{
if (sampleInfo == null)
return;
bool wasPlaying = Playing;
sampleContainer.Clear();
Sample = null;
var sample = CurrentSkin.GetSample(sampleInfo);
if (sample == null && AllowDefaultFallback)
@ -155,6 +182,13 @@ namespace osu.Game.Skinning
}
}
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
CurrentSkin.SourceChanged -= skinChangedImmediate;
}
#region Re-expose AudioContainer
public BindableNumber<double> Volume => sampleContainer.Volume;