diff --git a/src/java/com/threerings/openal/Sound.java b/src/java/com/threerings/openal/Sound.java index b40d95b5c..06473b773 100644 --- a/src/java/com/threerings/openal/Sound.java +++ b/src/java/com/threerings/openal/Sound.java @@ -32,6 +32,14 @@ import org.lwjgl.openal.AL10; */ public class Sound { + /** Used to await notification of the starting of a sound which may be + * delayed in loading. */ + public interface StartObserver + { + /** Called when the specified sound has started playing. */ + public void soundStarted (Sound sound); + } + /** * Returns the buffer of audio data associated with this sound. */ @@ -109,7 +117,7 @@ public class Sound */ public boolean play (boolean allowDefer) { - return play(allowDefer, false); + return play(allowDefer, false, null); } /** @@ -122,7 +130,18 @@ public class Sound */ public boolean loop (boolean allowDefer) { - return play(allowDefer, true); + return play(allowDefer, true, null); + } + + /** + * Plays this sound from the beginning, notifying the supplied observer + * when the audio starts. + * + * @param loop whether or not to loop the sampe until {@link #stop}ped. + */ + public void play (StartObserver obs, boolean loop) + { + play(true, loop, obs); } /** @@ -154,7 +173,8 @@ public class Sound _buffer = buffer; } - protected boolean play (boolean allowDefer, boolean loop) + protected boolean play ( + boolean allowDefer, final boolean loop, final StartObserver obs) { // if we're not ready to go... if (!_buffer.isPlayable()) { @@ -163,19 +183,29 @@ public class Sound // resolved _buffer.resolve(new ClipBuffer.Observer() { public void clipLoaded (ClipBuffer buffer) { - play(false); + play(false, loop, obs); } public void clipFailed (ClipBuffer buffer) { - // ugh. nothing to do here but be sad + // well, let's pretend like the sound started so that + // the observer isn't left hanging + if (obs != null) { + obs.soundStarted(Sound.this); + } } }); - + return true; } else { // sorry charlie... return false; } } + // let the observer know that (as far as they're concerned), we're + // started + if (obs != null) { + obs.soundStarted(this); + } + // if we do not already have a source, obtain one if (_sourceId == -1) { _sourceId = _group.acquireSource(this); diff --git a/src/java/com/threerings/openal/SoundManager.java b/src/java/com/threerings/openal/SoundManager.java index 059d0a97b..ad2278f10 100644 --- a/src/java/com/threerings/openal/SoundManager.java +++ b/src/java/com/threerings/openal/SoundManager.java @@ -129,9 +129,12 @@ public class SoundManager } // configure our LRU map with a removal observer - _clips.setRemovalObserver(new LRUHashMap.RemovalObserver() { - public void removedFromMap (LRUHashMap map, Object item) { - ((ClipBuffer)item).dispose(); + _clips.setRemovalObserver( + new LRUHashMap.RemovalObserver() { + public void removedFromMap (LRUHashMap map, + ClipBuffer item) { + Log.debug("Flushing " + item.getKey()); + item.dispose(); } }); @@ -152,10 +155,10 @@ public class SoundManager protected ClipBuffer getClip (ClipProvider provider, String path) { Comparable ckey = ClipBuffer.makeKey(provider, path); - ClipBuffer buffer = (ClipBuffer)_clips.get(ckey); + ClipBuffer buffer = _clips.get(ckey); if (buffer == null) { // check to see if this clip is currently loading - buffer = (ClipBuffer)_loading.get(ckey); + buffer = _loading.get(ckey); if (buffer == null) { buffer = new ClipBuffer(this, provider, path); _loading.put(ckey, buffer); @@ -197,10 +200,12 @@ public class SoundManager while (true) { final ClipBuffer buffer = (ClipBuffer)_toLoad.get(); try { + Log.debug("Loading " + buffer.getKey() + "."); final Clip clip = buffer.load(); _rqueue.postRunnable(new Runnable() { public void run () { Comparable ckey = buffer.getKey(); + Log.debug("Loaded " + ckey + "."); _loading.remove(ckey); if (buffer.bind(clip)) { _clips.put(ckey, buffer); @@ -228,10 +233,12 @@ public class SoundManager protected RunQueue _rqueue; /** Contains a mapping of all currently-loading clips. */ - protected HashMap _loading = new HashMap(); + protected HashMap _loading = + new HashMap(); /** Contains a mapping of all loaded clips. */ - protected LRUHashMap _clips = new LRUHashMap(DEFAULT_CACHE_SIZE, _sizer); + protected LRUHashMap _clips = + new LRUHashMap(DEFAULT_CACHE_SIZE, _sizer); /** Contains a queue of clip buffers waiting to be loaded. */ protected Queue _toLoad; @@ -241,12 +248,13 @@ public class SoundManager protected static SoundManager _soundmgr; /** Used to compute the in-memory size of sound samples. */ - protected static LRUHashMap.ItemSizer _sizer = new LRUHashMap.ItemSizer() { - public int computeSize (Object item) { - return ((ClipBuffer)item).getSize(); + protected static LRUHashMap.ItemSizer _sizer = + new LRUHashMap.ItemSizer() { + public int computeSize (ClipBuffer item) { + return item.getSize(); } }; /** Default to a cache size of one megabyte. */ - protected static final int DEFAULT_CACHE_SIZE = 1024 * 1024; + protected static final int DEFAULT_CACHE_SIZE = 8 * 1024 * 1024; }