Make sure OpenAlSound.Source is never accessed after the source is freed for reuse
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user