package djmania.sandbox.old;

import javazoom.jl.player.Player;
import java.io.FileInputStream;
import djmania.sandbox.old.FileTools;

/**
 * MP3 player for general use.
 * <p>
 * Uses {@link PlayerThreadedPlayback} to playback MP3 file as separate thread. 
 * Should only be used for general use; for more practical application, 
 * use the {@link ThreadedPlayer} class.
 * <p>
 * Licensed under <A HREF="http://www.gnu.org/licenses/gpl.txt">GNU GPL (Version 3)</A>. 
 * <p>
 * Uses <A HREF="http://www.javazoom.net/javalayer/sources.html">
 * JLayer MP3 library</A> for playback.
 * <p>
 * @author	Philip Peng
 * @version	1.5 Oct 25, 2007
 * @deprecated
 * 
 */

// Main class
public class PlayerThreaded extends Player {
	
	// PlayerThread thread
	private PlayerThreadedPlayback foobarThread;
	
	// New pause boolean
	private boolean paused = false;
	
	/**
	 * Creates a new Player.
	 * @param	stream	File stream (FileInputStream object).
	 */
	public PlayerThreaded (FileInputStream stream)
	throws javazoom.jl.decoder.JavaLayerException {
		super(stream, null);
	}
	
	/**
	 * Creates a new Player from a converted String location.
	 * @param	file	File location (String object).
	 */
	public PlayerThreaded (String file)
	throws javazoom.jl.decoder.JavaLayerException, java.io.FileNotFoundException {
		super(FileTools.convertStringToStream(file), null);
	}
	
	/**
	 * Parent play() method in a separate thread.
	 */
	public void play() {
		if ( foobarThread == null ) {
			foobarThread = new PlayerThreadedPlayback(this);
			foobarThread.start();			
		} else if ( this.isPaused() == true ) {
			this.resume();
		}
	}
	
	/**
	 * Parent play() method.
	 */
	public void playParent()
	throws javazoom.jl.decoder.JavaLayerException {
		super.play();
	}
	
	/*
	 * Changed October 14, 2007
	 * 
	 * Uses Thread's depreciated .suspend() and .resume() methods.
	 * Original methods were depreciated due to possible unstability;
	 * however, since they don't seem to cause any issues here and are
	 * much simpler than modifying/over-riding the original JLayer's
	 * Player class source code, they are used. See commented out code
	 * below for the alternative.
	 * 
	 */
	
	/**
	 * Suspends playback thread.
	 * Note: Uses Thread's depreciated .suspend() method. May be unstable.
	 */
	public void pause() {
		foobarThread.suspend();
		this.paused = true;
	}
	
	/**
	 * Resumes playback thread.
	 * Note: Uses Thread's depreciated .resume() method. May be unstable.
	 */
	public void resume() {
		foobarThread.resume();
		this.paused = false;
	}
	
	/**
	 * Pause check
	 * @return	paused	Whether playback thread is suspended or not.
	 */
	public boolean isPaused() {
		return this.paused;
	}	
	
	/*
	 * Changed October 14, 2007
	 * 
	 * This method of adding pause/resume functionality requires
	 * the modification of the original method. It pauses the playback
	 * by disrupting frame decoding. While it does work, however, repeated
	 * use causes the audio device to become unsynchronized and results in
	 * either the audio device not resuming or not pausing.
	 * And so, while this method of implementing pause/resume does "work",
	 * to avoid buggyness and incompatibility with future versions of
	 * JLayer, this class uses Thread's depreciated but simpler
	 * .suspend() and .resume() methods (see above for more info).
	 * 
	 * To uncomment this section using Eclipse, select all the commented out code,
	 * right click and Source > Toggle Comment
	 */ 
	
//	// Parent variables; make accessible
//	private AudioDevice	audio;
//	private boolean		closed = false;
//	private boolean		complete = false;
//	
//	/**
//	 * Modified parent play(int frames) boolean with paused flag check
//	 * @param frames	The number of frames to play. 
//	 * @return	true if the last frame was played, or false if there are
//	 *			more frames. 
//	 */
//	// Basically a direct source code copy
//	public boolean play(int frames) throws JavaLayerException
//	{
//		boolean ret = true;
//		
//		while (frames-- > 0 && ret)
//		{
//			// Added paused boolean check
//			if (!paused) {
//				ret = decodeFrame();
//			}
//		}
//		
//		if (!ret)
//		{
//			// last frame, ensure all data flushed to the audio device. 
//			AudioDevice out = audio;
//			if (out!=null)
//			{				
//				out.flush();
//				synchronized (this)
//				{
//					complete = (!closed);
//					close();
//				}				
//			}
//		}
//		return ret;
//	}
//	
//	/**
//	 * Sets "paused" flag to true
//	 * SNAFU: Repeated pause/resume causes buggyness possibly from sync loss >_<
//	 */
//	public void pause() {
//		paused = true;
//	}
//	
//	/**
//	 * Sets "paused" flag to false
//	 * SNAFU: Repeated pause/resume causes buggyness possibly from sync loss >_<
//	 */
//	public void resume() {
//		paused = false;
//	}
	
} // End public class PlayerThreaded extends Player


/**
 * Helper thread for PlayerThreaded class.
 * <p>
 * Extends Thread class. 
 * Helper for {@link PlayerThreaded} class; allows threaded playback.
 * <p>
 * Licensed under <A HREF="http://www.gnu.org/licenses/gpl.txt">GNU GPL (Version 3)</A>.
 * <p>
 * @author	Philip Peng
 * @version	1.0 Oct 24, 2007
 * 
 */

// Helper thread class
class PlayerThreadedPlayback extends Thread {

	private PlayerThreaded foobarThreaded;
	
	/**
	 * Constructor
	 * @param	player	The Player itself (PlayerThreaded object).
	 */
	public PlayerThreadedPlayback (PlayerThreaded player) {
		foobarThreaded = player;
	}
	
	/**
	 * Runs PlayerThreaded's parentPlay() method.
	 */
	public void run() {
		try {
			foobarThreaded.playParent();
		} catch ( Exception e ) {
			e.printStackTrace();
		}
	}
	
} // End class PlayerThreadPlay extends Thread