//Title:       Sound Workspace
//Version:     
//Copyright:   Copyright (c) 1998
//Author:      Chris Stauffer
//Company:     MIT AI Lab
//Description: Workspace for sound projects.
package edu.mit.ai.sound;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import com.sun.java.swing.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

import java.net.URL;
import java.net.MalformedURLException;

import javax.media.*;
import javax.media.transport.*;
import javax.media.format.*;
import javax.media.sound.*;
import javax.media.sound.sampled.*;
//import borland.jbcl.control.*;
//import com.sun.java.swing.UIManager;

public class CaptureApplet extends JApplet implements TransportListener{
	PushAudioInput captureChannel = null;
	FilePushSink filePushSink = null;
	PullAudioOutput playbackChannel = null;
	PullMediaSource pullMediaSource = null;

// system parameters
  boolean isStandalone = false;
  String outputFile;
  Panel panel1 = new Panel();
  BorderLayout borderLayout1 = new BorderLayout();
  Button quitButton = new Button();
  Button button1 = new Button();
  Button button2 = new Button();
  Button button3 = new Button();
  Button button4 = new Button();
//Get a parameter value

  public String getParameter(String key, String def) {
    return isStandalone ? System.getProperty(key, def) :
      (getParameter(key) != null ? getParameter(key) : def);
  }

  //Construct the applet

  public CaptureApplet() throws MediaException {
		// create the PushAudioInput (for capture) 		
		try { 
			AudioInControlDevice deviceIn = (AudioInControlDevice)AudioManager.getControlDevice(Class.forName("javax.media.sound.sampled.AudioInControlDevice"), null); 
			captureChannel = deviceIn.newPushAudioInput();
		} catch (Exception e) {
			throw new MediaException("AudioInControlDevice not available on this system"); 
		}

		// create the PullAudioOutput (for playback)
		try { 
			AudioOutControlDevice deviceOut = (AudioOutControlDevice)AudioManager.getControlDevice(Class.forName("javax.media.sound.sampled.AudioOutControlDevice"), null); 
			playbackChannel = deviceOut.newPullAudioOutput();
		} catch (Exception e) {
			throw new MediaException("AudioInControlDevice not available on this system"); 
		}

		// register as an event listener for the playback and capture channels
		playbackChannel.addTransportListener(this);
		captureChannel.addTransportListener(this);

		// Make sure we can release our resources and exit cleanly.

  }
  
	/**
	 * Respond to TransportEvents.
	 */
	public void transportUpdate(TransportEvent e) {

		// received when playback starts

		if (e instanceof StartEvent) {

			//playbackButton.setBackground(Color.green);
			//playbackButton.setLabel("Stop");
		}

		// received when playback stops

		if (e instanceof StopEvent) {

			// release the playback channel.
			// this will allow us to acquire the capture device in half-duplex systems.
			playbackChannel.release();

			// update the GUI
			//playbackButton.setBackground(Color.black);
			//playbackButton.setLabel("Start");
			//captureButton.setEnabled(true);
		}


		// received when the resource state changes for capture or rendering
		
		if (e instanceof ResourceEvent) {
			
			if (((ResourceEvent)e).getNewState() == ResourceControl.ACQUIRED) {

				if (e.getSource().equals(playbackChannel)) {
					
					// we acquired the playback channel resources.  
					// set the button text green.
					//playbackLabel.setForeground(Color.green);
				}
			
				if (e.getSource().equals(captureChannel)) {
					
					// we acquired the capture channel resources.
					// set the button text red.
					//captureLabel.setForeground(Color.red);
				}
			}

			if (((ResourceEvent)e).getNewState() == ResourceControl.RELEASED) {

				if (e.getSource().equals(playbackChannel)) {
					
					// we released the playback channel resources.
					// set the button text white.
					//playbackLabel.setForeground(Color.white);
				}
			
				if (e.getSource().equals(captureChannel)) {
					
					// we released the capture channel resources.
					// set the button text white.
					//captureLabel.setForeground(Color.white);
				}
			}

		}
	} 


//Initialize the applet

  public void init() {
    try { outputFile = this.getParameter("outputFile", "C:\\tempfile.wav"); } catch (Exception e) { e.printStackTrace(); }
    System.out.println("outputFile="+outputFile);
    try {
    jbInit();
    }
    catch (Exception e) {
    e.printStackTrace();
    }
  }
  //static {
  //  try {
  //    //UIManager.setLookAndFeel(new com.sun.java.swing.plaf.metal.MetalLookAndFeel());
  //    //UIManager.setLookAndFeel(new com.sun.java.swing.plaf.motif.MotifLookAndFeel());
  //    UIManager.setLookAndFeel(new com.sun.java.swing.plaf.windows.WindowsLookAndFeel());
  //  }
  //  catch (Exception e) {}
  //}
//Component initialization

  private void jbInit() throws Exception {
    this.getContentPane().setLayout(borderLayout1);
    this.setSize(400,300);
    quitButton.setLabel("quit");
    button1.setLabel("button1");
    button1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        button1_actionPerformed(e);
      }
    });
    button2.setLabel("button2");
    button3.setLabel("button3");
    button3.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        button3_actionPerformed(e);
      }
    });
    button4.setLabel("button4");
    button4.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        button4_actionPerformed(e);
      }
    });
    button2.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        button2_actionPerformed(e);
      }
    });
    quitButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        quitButton_actionPerformed(e);
      }
    });
    this.getContentPane().add(panel1, BorderLayout.CENTER);
    panel1.add(quitButton, null);
    panel1.add(button1, null);
    panel1.add(button2, null);
    panel1.add(button3, null);
    panel1.add(button4, null);
  }
//Start the applet

  public void start() {
  }
//Stop the applet

  public void stop() {
  }
//Destroy the applet

  public void destroy() {
  }
//Get Applet information

  public String getAppletInfo() {
    return "Applet Information";
  }
//Get parameter info

  public String[][] getParameterInfo() {
    String pinfo[][] =
    {
      {"outputFile", "String", "File to output capture data to"},
    };
    return pinfo;
  }
//Main method

  public static void main(String[] args) {
    try {
      CaptureApplet applet = new CaptureApplet();
      applet.isStandalone = true;
      JFrame frame = new JFrame();
      frame.setTitle("Applet Frame");
      frame.getContentPane().add(applet, BorderLayout.CENTER);
      applet.init();
      applet.start();
      frame.setSize(400,320);
      Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
      frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
      frame.setVisible(true);
    } catch (MediaException e) {}
  }

  void quitButton_actionPerformed(ActionEvent e) {
  	captureChannel.release();
		playbackChannel.release();
    System.exit(0);
  }

  void button1_actionPerformed(ActionEvent evt) {
    System.out.println("button1 pressed.");
 		try {

 			// acquire resources and start capturing
 			filePushSink = new FilePushSink(outputFile);
 			captureChannel.setSink(filePushSink);
 			captureChannel.acquire();
 			captureChannel.start();
 		} catch (Exception e) {

 			// bail if anything went wrong
 			System.err.println("Failed to start audio capture: " + e);
 		}

  }

  void button2_actionPerformed(ActionEvent evt) {
    System.out.println("button2 pressed.");

		// stop audio capture and release resources
		captureChannel.stop();
  	captureChannel.release();

  }

  void button3_actionPerformed(ActionEvent evt) {
				try {

  				// setup a pull media source for the captured data
					FileInputStream fis = new FileInputStream(outputFile);
					MediaStream mediaStream = new MediaStream(fis, ((Transporter)captureChannel).getFormat(), -1, null);
					pullMediaSource = new PullMediaSource(mediaStream);

					// setup the playback channel and start it
					playbackChannel.setFormat(mediaStream.getFormat());
					playbackChannel.setSource(pullMediaSource);
					playbackChannel.acquire();
					playbackChannel.start();
				} catch (Exception e) {
					System.err.println("Failed to start audio playback: " + e);
				}


  }

  void button4_actionPerformed(ActionEvent e) {		playbackChannel.stop();
  }
}

/**
 * FilePushSink is a simple PushSink which accepts Buffers containing a byte array
 * of data, and writes the data to a file.
 */
class FilePushSink extends FileOutputStream implements PushSink {

    private Format format = new Format(null, byte[].class);

    FilePushSink(String name) throws IOException {

	   super(name);
    }

    public int write(Buffer buffer) throws TransportException {

	   try {
		  write((byte[])buffer.getData(), buffer.getOffset(), buffer.getLength());
	   } catch (IOException e) {
		  throw new TransportException("Failed to write data to file.");
	   }
	   return buffer.getLength();
    }

    public Format getFormat() {

	   return format;
    }
}
