/***************************************************************************
 *   Copyright (C) 2009 by Paul Lutus                                      *
 *   lutusp@arachnoid.com                                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
package fftexplorer;

import java.io.*;
import javax.sound.sampled.*;

/**
 *
 * @author lutusp
 */
public class AudioCapture {

    boolean capture = false;
    boolean suspend = false;
    ByteArrayOutputStream byteArrayOutputStream;
    AudioFormat audioFormat;
    TargetDataLine targetDataLine;
    AudioInputStream audioInputStream;
    SourceDataLine sourceDataLine;
    FFTExplorer parent;
    Thread captureThread = null;
    byte[] captureBuffer;
    double sampleRate = 44100;

    public AudioCapture(FFTExplorer p) {
        parent = p;
    }

    public void startCapture() {
        try {
            stopCapture();
            sampleRate = getSampleRate();
            parent.sv_sampleRateTextField.setText(parent.formatNum(sampleRate));
            parent.signalProcessor.initialize(false);
            captureBuffer = new byte[parent.arraySize * 2];
            audioFormat = getAudioFormat();
            capture = true;
            parent.setSampleRate();
            DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
            targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
            targetDataLine.open(audioFormat);
            targetDataLine.start();
            captureThread = new Thread(new AudioCaptureThread());
            captureThread.start();
        } catch (Exception e) {
            System.out.println("capture: " + e);
            parent.beep();
            targetDataLine = null;
        }
        parent.setAudioSampleColor(targetDataLine != null);
    }

    public boolean capturing() {
        return capture;
    }

    public double getSampleRate() {
        return parent.getDouble(parent.sv_audioDataRateComboBoxIndex, sampleRate);
    }

    public void suspend(boolean susp) {
        if (susp) {
            if (capture) {
                if (sampleRate != getSampleRate()) {
                    stopCapture();
                    sampleRate = getSampleRate();
                    startCapture();
                }
            }
        }
        suspend = susp;
    }

    public void stopCapture() {
        capture = false;
        if (captureThread != null) {
            try {
                captureThread.join();
            } catch (Exception e) {
            }
        }
        captureThread = null;
        parent.signalProcessor.stopSynthesis();
        parent.setAudioSampleColor(true);
    }

    private AudioFormat getAudioFormat() {
        //float sampleRate = 4000.0F;
        //sampleRate = 44100.0F;
        sampleRate = parent.getDouble(parent.sv_audioDataRateComboBoxIndex, sampleRate);
        //8000,11025,16000,22050,44100
        int sampleSizeInBits = 16;
        //8,16
        int channels = 1;
        //1,2
        boolean signed = true;
        //true,false
        boolean bigEndian = false;
        //true,false
        return new AudioFormat(
                (float) sampleRate,
                sampleSizeInBits,
                channels,
                signed,
                bigEndian);
    }

    class AudioCaptureThread extends Thread {

        @Override
        public void run() {
            byteArrayOutputStream = new ByteArrayOutputStream();
            capture = true;
            suspend = false;
            try {
                while (capture) {
                    if (suspend) {
                        Thread.sleep(250);
                    } else {
                        int cnt = targetDataLine.read(captureBuffer, 0, captureBuffer.length);
                        if (cnt > 0) {
                            byteArrayOutputStream.write(captureBuffer, 0, cnt);
                            parent.signalProcessor.readAudio(byteArrayOutputStream);
                        }
                    }
                }
                byteArrayOutputStream.close();
                targetDataLine.close();
            } catch (Exception e) {
                System.out.println("CaptureThread: " + e);
            }
        }
    }
}
