package org.avmdti.sound;

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

import javax.sound.sampled.AudioFileFormat;
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.TargetDataLine;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 
 * <b>Description : </b>
 * 
 * 
 * <p>
 * Projet : enregistreur <BR>
 * 
 * <br>
 * <b>JOSAST </b>: Java Open Source Amateur Satellite Toolbox <br>
 * The aim of the project is to create a set of tools for amateur satellite
 * purpose. All this tools could be used together to create specific software.
 * <b>JOSAST </b> project is managed by AVMDTI (
 * <A HREF="http://www.avmdti.org">http://www.avmdti.org </a>)<br>
 * This software is an open source software. Please read the <b><i>JOSAST
 * licence </b> </i> <BR>
 * ( <A HREF="http://www.avmdti.org">http://www.avmdti.org </a>)
 * <p>
 * for more information contact
 * <a href="mailto:josast@avmdti.org">josast@avmdti.org </a>
 * </p>
 * 
 * @author <a href="mailto:mercier.josast@avmdti.org">mercier </a>
 * @version 1.0
 *          <p>
 *          <b>date </b>7 janv. 2004
 *          </p>
 *          <p>
 *          <b><i>Source Update </b> </i>
 *          </p>
 *          <br>
 *          date : name : comments <br>
 *          V1 : mercier : create file
 *          <p>
 * 
 */
public class SoundRecorder extends Thread {

	private Logger log = Logger.getLogger(getClass().getName());

	private TargetDataLine line = null;

	private File fichier;

	private AudioInputStream AIS = null;

	/**
	 * Method SoundRecorder.
	 * 
	 * @param filename
	 * @param AF
	 */
	public SoundRecorder(String filename, AudioFormat AF) {
		open(filename, AF);
	}

	/**
	 * Method open
	 * 
	 * This method open the input line and the output file. Some checking are
	 * performed like : - Audio Format is available - Input line Available
	 * 
	 * The default format for the Output file is WAV
	 * 
	 * @param filename Output file name
	 * @param AF       Audio format for the input sound
	 * 
	 */
	public void open(String filename, AudioFormat AF) {

		DataLine.Info info = new DataLine.Info(TargetDataLine.class, AF);
		if (!AudioSystem.isLineSupported(info)) {
			log.log(Level.SEVERE, "AudioFormat not available");
		} else {
			try {
				line = (TargetDataLine) AudioSystem.getLine(info);
			} catch (LineUnavailableException e) {
				log.log(Level.SEVERE, e.getMessage());
				e.printStackTrace();
			}
			try {
				line.open(AF);
			} catch (LineUnavailableException e) {
				log.log(Level.SEVERE, e.getMessage());
				e.printStackTrace();
			}

			fichier = new File(filename + ".wav");
		}
	}

	/**
	 * Method close. This method release the Input device and stop specific Sound
	 * Thread
	 * 
	 * see Java sound FAQ
	 * 
	 * 
	 */
	public void close() {
		// recherche de Tread lié à la carte son et les détruire.
		// voir sur le site java sound resource

		final ThreadGroup tg = Thread.currentThread().getThreadGroup();
		final Thread[] t = new Thread[tg.activeCount()];
		final int active = tg.enumerate(t);
		for (int i = 0; i < active; i++) {
			if (t[i].getName().indexOf("Sound") != -1) {
				t[i].interrupt();
			}
		}
		// This trick was provided by Sean A. Irvine. (Matthias)

	}

	/**
	 * Method startRecord.
	 * 
	 * Start the record of the Inpout Sound. This method call the start method of
	 * the Thread.
	 */
	public void startRecord() {

		AIS = new AudioInputStream(line);
		line.start();
		this.start();
	}

	/**
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		try {
			AudioSystem.write(AIS, AudioFileFormat.Type.WAVE, fichier);
		} catch (IOException e) {
			log.log(Level.SEVERE, e.getMessage());
			e.printStackTrace();
		}
	}

	/**
	 * Method endRecord.
	 * 
	 * This Method stop the sound record and close the Input.
	 */
	public void endRecord() {

		line.flush();
		line.stop();
		try {
			AIS.close();
		} catch (IOException e) {
			log.log(Level.SEVERE, e.getMessage());
			e.printStackTrace();
		}
		line.close();
		try {
			this.join();
		} catch (InterruptedException e) {
			log.log(Level.SEVERE, e.getMessage());
			e.printStackTrace();
		}
	}

	/**
	 * Method record.
	 * 
	 * This method record sound during time seconds
	 * 
	 * @param time number seconds of sound record
	 */
	public void record(int i) {
		startRecord();
		try {
			SoundRecorder.sleep(i * 1000); // i en secondes
		} catch (InterruptedException e) {
			log.log(Level.SEVERE, e.getMessage());
			e.printStackTrace();
		}
		endRecord();

	}

}