
com.threerings.media.sound.SoundPlayer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nenya Show documentation
Show all versions of nenya Show documentation
Facilities for making networked multiplayer games.
The newest version!
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
// https://github.com/threerings/nenya
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.media.sound;
import java.util.Set;
import com.google.common.collect.Sets;
import com.samskivert.util.Interval;
import com.samskivert.util.ObserverList;
import com.samskivert.util.RunQueue;
import com.samskivert.util.ObserverList.ObserverOp;
/**
* Loads, plays and loops sounds.
*/
public abstract class SoundPlayer
{
/** A pan value indicating that a sound should play from the left only. */
public static final float PAN_LEFT = -1f;
/** A pan value indicating that a sound should play from the right only. */
public static final float PAN_RIGHT = 1f;
/** A pan value indicating that a sound should play from center. */
public static final float PAN_CENTER = 0f;
/**
* Create instances of this for your application to differentiate
* between different types of sounds.
*/
public static class SoundType
{
/**
* Construct a new SoundType.
* Which should be a static variable stashed somewhere for the entire application to share.
*
* @param strname a short string identifier, preferably without spaces.
*/
public SoundType (String strname)
{
_strname = strname;
}
@Override
public String toString ()
{
return _strname;
}
protected String _strname;
}
/**
* A control for sounds.
*/
public static interface Frob
{
/**
* Stop playing or looping the sound.
* At present, the granularity of this command is limited to the buffer size of the
* line spooler, or about 8k of data. Thus, if playing an 11khz sample, it could take
* 8/11ths of a second for the sound to actually stop playing.
*/
public void stop ();
/**
* Set the volume of the sound.
*/
public void setVolume (float vol);
/**
* Get the volume of this sound.
*/
public float getVolume ();
/**
* Set the pan value for the sound. Valid values are
* -1 for left-only, 0 is centered, all the way to +1 for right-only.
*/
public void setPan (float pan);
/**
* Get the pan value of this sound.
*/
public float getPan ();
}
/** The default sound type. */
public static final SoundType DEFAULT = new SoundType("default");
/**
* Shut the damn thing off.
*/
public abstract void shutdown ();
/**
* Returns a string summarizing our volume settings and disabled sound types.
*/
public String summarizeState ()
{
StringBuilder buf = new StringBuilder();
buf.append("clipVol=").append(_clipVol);
buf.append(", disabled=[");
int ii = 0;
for (SoundType soundType : _disabledTypes) {
if (ii++ > 0) {
buf.append(", ");
}
buf.append(soundType);
}
return buf.append("]").toString();
}
/**
* Is the specified soundtype enabled?
*/
public boolean isEnabled (SoundType type)
{
// by default, types are enabled..
return (!_disabledTypes.contains(type));
}
/**
* Is sound on and is the specified soundtype enabled?
*/
public boolean shouldPlay (SoundType type)
{
if (type == null) {
type = DEFAULT; // let the lazy kids play too
}
return _clipVol != 0f && isEnabled(type);
}
/**
* Turns on or off the specified sound type.
*/
public void setEnabled (final SoundType type, final boolean enabled)
{
boolean changed;
if (enabled) {
changed = _disabledTypes.remove(type);
} else {
changed = _disabledTypes.add(type);
}
if (changed) {
_enabledObservers.apply(new ObserverOp() {
public boolean apply (SoundEnabledObserver observer) {
observer.enabledChanged(type, enabled);
return true;
}
});
}
}
public void addSoundEnabledObserver (SoundEnabledObserver listener)
{
_enabledObservers.add(listener);
}
public void removeSoundEnabledObserver (SoundEnabledObserver listener)
{
_enabledObservers.remove(listener);
}
/**
* Sets the volume for all sound clips.
*
* @param vol a volume parameter between 0f and 1f, inclusive.
*/
public void setClipVolume (float vol)
{
_clipVol = Math.max(0f, Math.min(1f, vol));
}
/**
* Get the volume for all sound clips.
*/
public float getClipVolume ()
{
return _clipVol;
}
/**
* Optionally lock each of these keys prior to playing, to guarantee that it will be quickly
* available for playing.
*/
public abstract void lock (String pkgPath, String... keys);
/**
*Unlock the specified sounds so that its resources can be freed.
*/
public abstract void unlock (String pkgPath, String... keys);
/**
* Play the specified sound as the specified type of sound, immediately. Note that a sound
* need not be locked prior to playing.
*
* @return true if the sound actually played, or false if its sound type was disabled or if
* sound is off altogether.
*/
public boolean play (SoundType type, String pkgPath, String key)
{
return play(type, pkgPath, key, 0, PAN_CENTER);
}
/**
* Play the specified sound as the specified type of sound, immediately, with the specified
* pan value. Note that a sound need not be locked prior to playing.
*
* @param pan a value from -1f (all left) to +1f (all right).
* @return true if the sound actually played, or false if its sound type was disabled or if
* sound is off altogether.
*/
public boolean play (SoundType type, String pkgPath, String key, float pan)
{
return play(type, pkgPath, key, 0, pan);
}
/**
* Play the specified sound after the specified delay.
* @param delay the delay in milliseconds.
* @return true if the sound actually played, or false if its sound type was disabled or if
* sound is off altogether.
*/
public boolean play (SoundType type, String pkgPath, String key, int delay)
{
return play(type, pkgPath, key, delay, PAN_CENTER);
}
/**
* Play the specified sound after the specified delay.
* @param delay the delay in milliseconds.
* @param pan a value from -1f (all left) to +1f (all right).
* @return true if the sound actually played, or false if its sound type was disabled or if
* sound is off altogether.
*/
public boolean play (SoundType type, final String pkgPath, final String key, int delay,
final float pan)
{
if (!shouldPlay(type)) {
return false;
}
if (delay > 0) {
new Interval(getSoundQueue()) {
@Override
public void expired () {
play(pkgPath, key, pan);
}
}.schedule(delay);
} else {
play(pkgPath, key, pan);
}
return true;
}
/**
* Play the specified sound after the specified delay.
* @param pan a value from -1f (all left) to +1f (all right).
*/
protected abstract void play (String pkgPath, String key, float pan);
/**
* Loop the specified sound, stopping as quickly as possible when stop is called.
*/
public Frob loop (SoundType type, String pkgPath, String key)
{
return loop(type, pkgPath, key, PAN_CENTER);
}
/**
* Loop the specified sound, stopping as quickly as possible when stop is called.
*/
public Frob loop (SoundType type, String pkgPath, String key, float pan)
{
if (!shouldPlay(type)) {
return null;
}
return loop(pkgPath, key, pan);
}
/**
* Loop the specified sound, stopping as quickly as possible when stop is called.
*/
protected abstract Frob loop (String pkgPath, String key, float pan);
/**
* Gets the run queue on which sound should be played. It defaults to {@link RunQueue#AWT}.
*/
protected abstract RunQueue getSoundQueue ();
/** Volume level for sound clips. */
protected float _clipVol = 1f;
/** A set of soundTypes for which sound is enabled. */
protected Set _disabledTypes = Sets.newHashSet();
protected ObserverList _enabledObservers = ObserverList.newFastUnsafe();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy