diff --git a/src/java/com/threerings/openal/ClipBuffer.java b/src/java/com/threerings/openal/ClipBuffer.java index c39de189c..9e800748f 100644 --- a/src/java/com/threerings/openal/ClipBuffer.java +++ b/src/java/com/threerings/openal/ClipBuffer.java @@ -132,6 +132,13 @@ public class ClipBuffer return; } + // this shouldn't happen + if (_state == UNLOADING) { + Log.warning("Tried to resolve buffer in the process of " + + "unloading [key=" + getKey() + "]."); + return; + } + // queue up the observer if (observer != null) { _observers.add(observer); @@ -168,7 +175,14 @@ public class ClipBuffer public void dispose () { if (_bufferId != null) { - // we've been given the boot, free up our buffer + // if there are sources bound to this buffer, we must wait + // for them to be unbound + if (_bound > 0) { + _state = UNLOADING; + return; + } + + // free up our buffer AL10.alDeleteBuffers(_bufferId); _bufferId = null; _state = UNLOADED; @@ -238,6 +252,25 @@ public class ClipBuffer _observers.clear(); } + /** + * Notifies the buffer that a source has been bound to it. + */ + protected void sourceBound () + { + _bound++; + } + + /** + * Notifies the buffer that a source has been unbound from it. + */ + protected void sourceUnbound () + { + // dispose of the buffer when the last source is unbound + if (--_bound == 0 && _state == UNLOADING) { + dispose(); + } + } + protected SoundManager _manager; protected ClipProvider _provider; protected String _path; @@ -246,8 +279,10 @@ public class ClipBuffer protected int _size; protected ObserverList _observers = new ObserverList(ObserverList.FAST_UNSAFE_NOTIFY); + protected int _bound; protected static final int UNLOADED = 0; protected static final int LOADING = 1; protected static final int LOADED = 2; + protected static final int UNLOADING = 3; } diff --git a/src/java/com/threerings/openal/Sound.java b/src/java/com/threerings/openal/Sound.java index 4ab003427..05458240f 100644 --- a/src/java/com/threerings/openal/Sound.java +++ b/src/java/com/threerings/openal/Sound.java @@ -221,8 +221,9 @@ public class Sound return false; } - // bind our clip buffer to the source + // bind our clip buffer to the source and notify it AL10.alSourcei(_sourceId, AL10.AL_BUFFER, _buffer.getBufferId()); + _buffer.sourceBound(); } // configure the source with our ephemera @@ -258,6 +259,7 @@ public class Sound AL10.alGetSourcei(_sourceId, AL10.AL_SOURCE_STATE) == AL10.AL_STOPPED) { _sourceId = -1; + _buffer.sourceUnbound(); return true; } return false; diff --git a/src/java/com/threerings/openal/SoundGroup.java b/src/java/com/threerings/openal/SoundGroup.java index c3db82edc..efd2ec218 100644 --- a/src/java/com/threerings/openal/SoundGroup.java +++ b/src/java/com/threerings/openal/SoundGroup.java @@ -65,6 +65,14 @@ public class SoundGroup public void dispose () { if (_sourceIds != null) { + // make sure any bound sources are released + for (Source source : _sources) { + if (source.holder != null) { + source.holder.stop(); + source.holder.reclaim(); + } + } + _sources.clear(); AL10.alDeleteSources(_sourceIds); _sourceIds = null; }