Permalink
Browse files

Added Sound.release() and Assets.getMusic().

Sound.release allows you to free up audio resources immediately rather than
waiting for GC, which can be fiddly if you're up against the wall.
Assets.getMusic() allows us to differentiate between short SFX clips
(getSound()) and longer, possibly streamed music (getMusic()).

A forthcoming patch to the Android backend will make use of this, but I will
probably also change the Java backend to use BigClip only on getMusic() calls.
  • Loading branch information...
1 parent e517a5d commit f8e93a6d3105d9b9a1af1729f3627a7b47cfaaa8 @samskivert samskivert committed Jan 8, 2013
@@ -81,6 +81,11 @@ public Image getRemoteImage(String url, float width, float height) {
}
@Override
+ public Sound getMusic(String path) {
+ return getSound(path);
+ }
+
+ @Override
public void getText(final String path, final Callback<String> callback) {
platform.invokeAsync(new Runnable() {
public void run () {
@@ -88,6 +88,14 @@ public void setVolume(float volume) {
}
@Override
+ public void release() {
+ if (impl != null) {
+ releaseImpl();
+ impl = null;
+ }
+ }
+
+ @Override
public final void addCallback(Callback<? super Sound> callback) {
if (impl != null)
callback.onSuccess(this);
@@ -97,6 +105,10 @@ else if (error != null)
callbacks = Callbacks.createAdd(callbacks, callback);
}
+ protected void finalize() {
+ release();
+ }
+
protected boolean prepareImpl() {
return false;
}
@@ -107,4 +119,5 @@ protected boolean playingImpl() {
protected abstract void stopImpl();
protected abstract void setLoopingImpl(boolean looping);
protected abstract void setVolumeImpl(float volume);
+ protected abstract void releaseImpl();
}
@@ -61,15 +61,30 @@
Image getRemoteImage(String url, float width, float height);
/**
- * Asynchronously loads and returns a sound. If a request to play the sound is made before the
- * sound is loaded, it will be noted and the sound will be played when loading has completed.
+ * Asynchronously loads and returns a short sound effect.
+ *
+ * <p> Note: if a request to play the sound is made before the sound is loaded, it will be noted
+ * and the sound will be played when loading has completed.
*
* @param path the path to the sound resource. NOTE: this should not include a file extension,
- * PlayN will automatically add {@code .mp3}, (or {@code .aif} on iOS).
+ * PlayN will automatically add {@code .mp3}, (or {@code .caf} on iOS).
*/
Sound getSound(String path);
/**
+ * Asynchronously loads and returns a music resource. On some platforms, the backend will use a
+ * different implementation from {@link #getSound} which is better suited to the much larger size
+ * of music audio data.
+ *
+ * <p> Note: if a request to play the sound is made before the sound is loaded, it will be noted
+ * and the sound will be played when loading has completed.
+ *
+ * @param path the path to the sound resource. NOTE: this should not include a file extension,
+ * PlayN will automatically add {@code .mp3}, (or {@code .caf} on iOS).
+ */
+ Sound getMusic(String path);
+
+ /**
* Returns a text asset, encoded in UTF-8.
*
* @param path the path to the text asset.
@@ -83,6 +83,16 @@ public Sound getSound(String path) {
}
@Override
+ public Sound getMusic(String path) {
+ Object object = null;
+ if ((object = cache.get(path)) == null) {
+ object = delegate.getMusic(path);
+ cache.put(path, object);
+ }
+ return (Sound) object;
+ }
+
+ @Override
public String getTextSync(String path) throws Exception {
// no caching for text loading
return delegate.getTextSync(path);
@@ -48,6 +48,9 @@ public boolean isPlaying() {
return false;
}
@Override
+ public void release() {
+ }
+ @Override
public void addCallback(Callback<? super Sound> callback) {
callback.onSuccess(this);
}
@@ -119,6 +122,13 @@ public void addCallback(Callback<? super Sound> callback) {
boolean isPlaying();
/**
+ * Releases resources used by this sound. It will no longer be usable after release. This will
+ * also happen automatically when this sound is garbage collected, but one may need to manually
+ * release sounds sooner to avoid running out of audio resources.
+ */
+ void release();
+
+ /**
* Adds a callback to be notified when this sound has loaded. If the sound is
* already loaded the callback will be notified immediately. The callback is
* discarded once the sound is loaded.
@@ -84,6 +84,14 @@ public final Sound getSound(String path) {
}
@Override
+ public final Sound getMusic(String path) {
+ incrementRequestCount();
+ Sound sound = delegate.getMusic(path);
+ sound.addCallback(callback);
+ return sound;
+ }
+
+ @Override
public String getTextSync(String path) throws Exception {
// no tracking for text loading
return delegate.getTextSync(path);
@@ -101,4 +101,9 @@ protected void setVolumeImpl(float volume) {
soundChannel.setVolume(volume);
}
}
+
+ @Override
+ protected void releaseImpl() {
+ // TODO: anything?
+ }
}
@@ -77,4 +77,9 @@ protected void setLoopingImpl(boolean looping) {
protected void setVolumeImpl(float volume) {
impl.setVolume((int) (volume * 100));
}
+
+ @Override
+ protected void releaseImpl() {
+ // TODO: anything?
+ }
}
@@ -56,8 +56,8 @@ protected void setVolumeImpl(float volume) {
impl.set_Volume(volume);
}
- protected void finalize() {
- if (impl != null)
- impl.Dispose(); // meh
+ @Override
+ protected void releaseImpl() {
+ impl.Dispose();
}
}
@@ -55,19 +55,17 @@ protected void setVolumeImpl(float volume) {
volctrl.setValue(toGain(volume, volctrl.getMinimum(), volctrl.getMaximum()));
}
+ @Override
+ protected void releaseImpl() {
+ impl.close();
+ }
+
// @Override
// public float volume() {
// FloatControl volctrl = (FloatControl) impl.getControl(FloatControl.Type.MASTER_GAIN);
// return toVolume(volctrl.getValue());
// }
- protected void finalize() {
- if (impl != null) {
- impl.close();
- impl = null;
- }
- }
-
// protected static float toVolume (float gain) {
// return FloatMath.pow(10, gain/20);
// }

0 comments on commit f8e93a6

Please sign in to comment.