/**
 * PlayerThreaded class
 * @author Philip Peng
 * 
 * Extends JLayer 1.0's Player class
 * Plays file as separate thread
 * 
 * Created by Philip Peng
 * Last updated: 2007/10/12
 * 
 * Licensed under GNU GPL (Version 3):
 * http://www.gnu.org/licenses/gpl.txt
 * 
 * JLayer website:
 * http://www.javazoom.net/javalayer/sources.html
 * 
 */

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.*;
import java.io.FileInputStream;

// Main class
public class PlayerThreaded extends Player {
	
	// PlayerThread thread
	private PlayerThreadPlay foobar = new PlayerThreadPlay(this);
	
	// Parent variables; make accessible
	private AudioDevice	audio;
	private boolean		closed = false;
	private boolean		complete = false;
	
	// New pause boolean
	public boolean paused = false;
	
	/**
	 * Constructor
	 * @param stream	File stream (FileInputStream object)
	 */
	public PlayerThreaded (FileInputStream stream)
	throws javazoom.jl.decoder.JavaLayerException {
		super(stream, null);
	}
	
	/**
	 * Constructor
	 * @param file	File location (String object)
	 */
	public PlayerThreaded (String file)
	throws javazoom.jl.decoder.JavaLayerException, java.io.FileNotFoundException {
		super(convertStringToStream(file), null);
	}
	
	/**
	 * Convert String object to FileInputStream object
	 * @param file	String of file location.
	 * @return stream	File location as a FileInputStream
	 */
	static private FileInputStream convertStringToStream(String file)
	throws java.io.FileNotFoundException {
		FileInputStream stream = new FileInputStream(file);
		return stream;
	}
	
	/**
	 * Parent play() method in a separate thread
	 */
	public void play() {
		if (!foobar.isAlive()) {
			foobar.start();
		} else {
			this.resume();
		}
	}
	
	/**
	 * Parent play() method
	 */
	public void playParent()
	throws javazoom.jl.decoder.JavaLayerException {
		paused = false;
		super.play();
	}
	
	/**
	 * 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
	 */
	public void pause() {
		paused = true;
	}
	
	/**
	 * Sets "paused" flag to false
	 */
	public void resume() {
		paused = false;
	}
	
}


// Helper thread class
class PlayerThreadPlay extends Thread {

	private PlayerThreaded foobar;
	
	/**
	 * Constructor
	 * @param foobar	The Player itself (PlayerThreaded object)
	 */
	public PlayerThreadPlay (PlayerThreaded foobar) {
		this.foobar = foobar;
	}
	
	/**
	 * Over-riding run() method; called by start()
	 */
	public void run() {
		try {
			foobar.playParent();
		} catch ( Exception e ) {
			e.printStackTrace();
		}
	}
	
}