import javax.media.*;
import javax.media.control.*;
import javax.media.format.*;
import javax.media.protocol.*;
import java.util.Vector;
import java.io.*;

public class MyAudioRecorder implements ControllerListener
{    
    protected CaptureDeviceInfo captureDeviceInfo = null;
    protected Processor processor = null;
    protected DataSink dataSink = null;
    protected String fileName;
    
    MyAudioRecorder(String file)
    {
        this.fileName = file;
        AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16, 2);
        Vector devices = CaptureDeviceManager.getDeviceList(af);

        if (devices.size() > 0)
            captureDeviceInfo = (CaptureDeviceInfo)devices.firstElement();
        else
        {
        	// Fail if no appropriate capture device is found
            System.exit(-1);
        }
        
        // Create a processor and register this class as event listener 
        try
        {
            processor = Manager.createProcessor(captureDeviceInfo.getLocator());
        }
        catch (Exception e)
        {
        	e.printStackTrace();
        }

        processor.addControllerListener(this);            
        processor.configure();
    }
 
    private void setOutputFormat(String format)
    {
        processor.setContentDescriptor( new FileTypeDescriptor(format) );    	
    }
    
    public synchronized void controllerUpdate(ControllerEvent event)
    {
        if (event instanceof ConfigureCompleteEvent)
        {
        	setOutputFormat(FileTypeDescriptor.MPEG_AUDIO);
        	processor.realize();
        }
        else if (event instanceof RealizeCompleteEvent)
        {
            processor.prefetch();
        }
        else if (event instanceof PrefetchCompleteEvent)
        {
            createFile();
            startRecording();
        }
        else if (event instanceof ControllerClosedEvent)
        {
            processor.close();
            dataSink.close();
        }
    }    

    private void createFile()
    {
        DataSource source = processor.getDataOutput();        

        // Create a MediaLocator for representing the output file
        MediaLocator outputF = new MediaLocator("file:" + fileName);

        // Associate our output file to a data sink
        try 
        {
            dataSink = Manager.createDataSink(source, outputF);
            dataSink.open();
        }
        catch (NoDataSinkException e)
        {
            e.printStackTrace();
            System.exit(-1);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            System.exit(-1);
        }
        catch (SecurityException e)
        {
            e.printStackTrace();
            System.exit(-1);
        }        
    }
    
    private void startRecording()
    {
    	// If processor implements StreamWriteControl, we can limit output file
    	// size by using setStreamSizeLimit()
        StreamWriterControl swc = (StreamWriterControl)processor.getControl(
        		"javax.media.control.StreamWriterControl");

        // We'll use 1MB as our size limit
        if (swc != null)
            swc.setStreamSizeLimit(1000000);
        
        // Start processing pipeline
        try
        {
            dataSink.start();
        }
        catch (IOException e)
        {
            e.printStackTrace();        	
            System.exit(-1);
        }
        
        processor.start();
    }
    
    public static void main(String[] args)
    {
        if(args.length == 1)
            new MyAudioRecorder(args[0]);
    }
}
