/**
 * $Id: AudioPlayerSubModule.java,v 1.4 2008/02/14 02:00:07 nishi Exp $
 */
package galatea.io.plugins;

import galatea.logger.Logger;
import galatea.outitem.AudioOutItem;
import galatea.outitem.OutItem;
import galatea.submodule.AbstractSubModule;
import galatea.util.Util;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

public class AudioPlayerSubModule 
extends AbstractSubModule
{
	private Logger dbg = new Logger("SND", 0);
    private boolean active = false;
    private File file = null;
	private String id;
    
	public boolean startOutput(OutItem item) {
		if (!(item instanceof AudioOutItem)) return false;
		String src = ((AudioOutItem)item).getArg();
		String filename = "";
		if (src.startsWith("http:")) {
			String suffix = Util.getSuffix(src);
			filename = Util.mktemp(suffix);
			Util.saveUrlAsBinary(src, filename);
		} else if (src.startsWith("file:")){
			filename = src.replaceFirst("^file:", "");
		} else {
			filename = src;
		}
		file = new File(filename);
		id = src + " " + filename;
		
		Thread th = new Thread(new Runnable() {

			public void run() {
		        AudioInputStream ais = null;
		        SourceDataLine line = null;
		        active = true;
		        try {
		            ais = AudioSystem.getAudioInputStream(file);
		            line = (SourceDataLine)AudioSystem.getLine(new DataLine.Info(
		            		SourceDataLine.class, ais.getFormat()));
		            line.open();
		            line.flush();
		            AudioFormat format = ais.getFormat();
		            int frameSize = format.getFrameSize();
		            long frameLength = ais.getFrameLength();
		            byte[] buffer = new byte[512];
		            int len, off, l, pos = 0, prevPos = 0;
		            while (active && (len = ais.read(buffer)) > 0) {
		            	for (off = 0; active && len > 0; 
		            		off += l, len -= l, prevPos = pos, pos += l) {
		            		l = line.write(buffer, off, len);
		            		if (!line.isRunning()) {
		            			line.start();
		            		}
		            	}
		            }
		            if (active) {
		            	line.drain();
		            }
		        } catch (UnsupportedAudioFileException e) {
					e.printStackTrace();
		        } catch(IOException e) {
					e.printStackTrace();
		        } catch(LineUnavailableException e) {
					e.printStackTrace();
		        } finally {
		        	if (Util.isLinux()) {
			        	try {
							Thread.sleep(300);
						} catch (InterruptedException e1) {
							e1.printStackTrace();
						}
		        	}
		        	try {
		        		if (ais != null)
		        			ais.close();
			        	if (line != null)
			        		line.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					receiver_.receiveOutputReady("audio", id);
		        }
			}
		});
		th.start();
		receiver_.receiveOutputBusy("audio", id);
		return true;
	}

	public boolean stopOutput(OutItem item) {
		if (item instanceof AudioOutItem) {
	        active = false;
			return true;
		}
		return false;
	}

}
