Make sure OpenAlSound.Source is never accessed after the source is freed for reuse

This commit is contained in:
tovl
2021-09-28 23:34:26 +02:00
committed by reaperrr
parent 2bc03b4d84
commit a428aaa602

View File

@@ -174,7 +174,7 @@ namespace OpenRA.Platforms.Default
// Make sure we can accurately determine the end of the original sound, // Make sure we can accurately determine the end of the original sound,
// even if the source is immediately reused. // even if the source is immediately reused.
sound.Done = true; sound.UnbindSource();
var slot = kv.Value; var slot = kv.Value;
slot.SoundSource = null; slot.SoundSource = null;
@@ -279,7 +279,7 @@ namespace OpenRA.Platforms.Default
public void PauseSound(ISound sound, bool paused) public void PauseSound(ISound sound, bool paused)
{ {
if (sound == null) if (sound == null || sound.Complete)
return; return;
var source = ((OpenAlSound)sound).Source; var source = ((OpenAlSound)sound).Source;
@@ -414,10 +414,10 @@ namespace OpenRA.Platforms.Default
class OpenAlSound : ISound class OpenAlSound : ISound
{ {
public readonly uint Source; internal uint Source { get; private set; }
protected readonly float SampleRate; protected readonly float SampleRate;
public bool Done; bool done;
public OpenAlSound(uint source, bool looping, bool relative, WPos pos, float volume, int sampleRate, uint buffer) public OpenAlSound(uint source, bool looping, bool relative, WPos pos, float volume, int sampleRate, uint buffer)
: this(source, looping, relative, pos, volume, sampleRate) : this(source, looping, relative, pos, volume, sampleRate)
@@ -442,16 +442,39 @@ namespace OpenRA.Platforms.Default
AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 136533); AL10.alSourcef(source, AL10.AL_MAX_DISTANCE, 136533);
} }
internal void UnbindSource()
{
done = true;
Source = uint.MaxValue;
}
public float Volume public float Volume
{ {
get { AL10.alGetSourcef(Source, AL10.AL_GAIN, out var volume); return volume; } get
set => AL10.alSourcef(Source, AL10.AL_GAIN, value); {
if (done)
return float.NaN;
AL10.alGetSourcef(Source, AL10.AL_GAIN, out var volume);
return volume;
}
set
{
if (done)
return;
AL10.alSourcef(Source, AL10.AL_GAIN, value);
}
} }
public virtual float SeekPosition public virtual float SeekPosition
{ {
get get
{ {
if (done)
return float.NaN;
AL10.alGetSourcei(Source, AL11.AL_SAMPLE_OFFSET, out var sampleOffset); AL10.alGetSourcei(Source, AL11.AL_SAMPLE_OFFSET, out var sampleOffset);
return sampleOffset / SampleRate; return sampleOffset / SampleRate;
} }
@@ -461,7 +484,7 @@ namespace OpenRA.Platforms.Default
{ {
get get
{ {
if (Done) if (done)
return true; return true;
AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out var state); AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out var state);
@@ -471,11 +494,17 @@ namespace OpenRA.Platforms.Default
public void SetPosition(WPos pos) public void SetPosition(WPos pos)
{ {
if (done)
return;
AL10.alSource3f(Source, AL10.AL_POSITION, pos.X, pos.Y, pos.Z); AL10.alSource3f(Source, AL10.AL_POSITION, pos.X, pos.Y, pos.Z);
} }
protected void StopSource() protected void StopSource()
{ {
if (done)
return;
AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out var state); AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out var state);
if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED) if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED)
AL10.alSourceStop(Source); AL10.alSourceStop(Source);
@@ -483,6 +512,9 @@ namespace OpenRA.Platforms.Default
public virtual void Stop() public virtual void Stop()
{ {
if (done)
return;
StopSource(); StopSource();
AL10.alSourcei(Source, AL10.AL_BUFFER, 0); AL10.alSourcei(Source, AL10.AL_BUFFER, 0);
} }