package com.commonsensenet.realfarm.utils;
import java.util.LinkedList;
import java.util.Queue;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.util.Log;
/**
* Class that handles the Sounds. A list of sounds can be added to the Queue and
* they will be played sequentially.
*
* @author Oscar Bola�os <@oscarbolanos>
*
*/
public class SoundQueue implements OnCompletionListener {
/** Indicates if the Audio is enabled or not. */
public static boolean isAudioEnabled = true;
/** Identifier of the class used for logging. */
private static final String LOG_TAG = "SoundQueue";
/** Singleton instance of the SoundQueue. */
private static SoundQueue sInstance = null;
/**
* Gets the singleton SoundQueue instance.
*
* @return the SoundQueue instance.
*/
public static SoundQueue getInstance() {
// follows the singleton pattern to create a new instance.
if (sInstance == null) {
Log.i(LOG_TAG, "Initializing sound system");
sInstance = new SoundQueue();
}
return sInstance;
}
/** Context used to load the sounds using the resourceId. */
protected Context mContext;
/** Current MediaPlayer used to play the sound. */
protected MediaPlayer mCurrentMediaPlayer;
/** Stores the last forcePlay setting. */
private boolean mForcePlay = false;
/** Queue that contains the sounds in the order that need to be played. */
protected Queue<MediaPlayer> mResToPlay;
/**
* Creates a new SoundQueue instance. All the variables are initialized.
*/
private SoundQueue() {
// initializes the data structure used to hold the media players.
mResToPlay = new LinkedList<MediaPlayer>();
mCurrentMediaPlayer = null;
}
/**
* Adds a sound to the queue using its resourceId. The sounds will be played
* sequentially using play(). If a sound is currently being played, the new
* resource will be added to the end of the sequence.
*
* @param resourceId
* the resourceId to play
*/
public void addToQueue(int resourceId) {
if (mContext == null) {
Log.i(LOG_TAG, "Context not set, use init() to set it");
}
// adds the id to the queue to play.
if (mResToPlay != null) {
// only adds the audio if valid.
if (resourceId != -1) {
mResToPlay.add(MediaPlayer.create(mContext, resourceId));
}
} else {
Log.d(LOG_TAG, "Queue is not initialized!!");
}
}
/**
* Removes all pending sounds
*/
public void clean() {
// disposes the active sound.
if (mCurrentMediaPlayer != null) {
mCurrentMediaPlayer.setOnCompletionListener(null);
mCurrentMediaPlayer.stop();
mCurrentMediaPlayer.release();
mCurrentMediaPlayer = null;
}
// cancels any forcePlay setting.
mForcePlay = false;
// deletes all the active MediaPlayers in the queue
for (MediaPlayer p : mResToPlay) {
p.release();
}
// clears the data structures
mResToPlay.clear();
}
/**
* Sets the Context where the sounds will be loaded.
*
* @param context
* the Context to use.
*/
public void init(Context context) {
mContext = context;
}
public void onCompletion(MediaPlayer mediaPlayer) {
// releases the active media player.
mediaPlayer.setOnCompletionListener(null);
mediaPlayer.release();
// clears the reference.
mCurrentMediaPlayer = null;
// plays the next sound using the stored forcePlay setting.
play(mForcePlay);
}
/**
* Plays the next sound in the SoundQueue respecting the current sound
* setting.
*/
public void play() {
// does not override the isEnabledSound setting.
play(false);
}
/**
* Plays the next sound in the SoundQueue. The sound is only played if the
* <code>isAudioEnabled</code> is <code>true</code> or if it is forced no
* matter the <code>isAudioEnabled</code> setting. If a sound is currently
* being played, it will continue the process normally.
*
* @param forcePlay
* whether or not to override the <code>isAudioEnabled</code>
* setting.
*/
public void play(Boolean forcePlay) {
// stores the last used forcePlay setting.
mForcePlay = forcePlay;
if (isAudioEnabled || forcePlay) {
// plays the next file in the queue
// if no sound is currently being played.
if (!mResToPlay.isEmpty() && mCurrentMediaPlayer == null) {
// gets the next element.
mCurrentMediaPlayer = mResToPlay.poll();
mCurrentMediaPlayer.setOnCompletionListener(this);
// plays the current sound.
mCurrentMediaPlayer.start();
}
} else {
Log.d(LOG_TAG,
"Cleared the pending audios since the sound is disabled.");
clean();
}
}
/**
* Plays the currently playing sound and removes all pending sounds from the
* list.
*/
public void stop() {
// removes any other existing sound in the queue.
clean();
}
}