import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;
import javax.sound.sampled.*;
public class PlayAu implements Runnable
 {
  final int bufSize = 16384;
  AudioFormat myformat;
  AudioInputStream audioInputStream;
  String errStr;
  double duration, seconds;
  SourceDataLine sdline;
  Thread thread;
  public PlayAu(AudioInputStream ais) 
   {
    audioInputStream=ais;
    myformat=audioInputStream.getFormat();
    try 
     {
      long milliseconds=(long)((audioInputStream.getFrameLength()*1000)/myformat.getFrameRate());
      duration = milliseconds / 1000.0;
     }
    catch (Exception ex) { reportStatus(ex.toString()); }
   }
  private void reportStatus(String msg) 
   {
    if ((errStr = msg) != null) System.out.println(errStr);
   }
  public void start() 
   {
    errStr = null;
    thread = new Thread(this);
    thread.setName("PlayAu");
    thread.start();
   }
  public void stop() { thread = null; }
  private void shutDown(String message) 
   {
    if ((errStr = message) != null) System.err.println(errStr);
    if (thread != null) 
     {
      thread = null;
     }
   }
  public void run() 
   {
    try { audioInputStream.reset(); }
    catch (Exception e) 
     {
      shutDown("Unable to reset the stream\n" + e);
      return;
     }
    AudioInputStream playbackInputStream = AudioSystem.getAudioInputStream(myformat, audioInputStream);
    if (playbackInputStream == null) 
     {
      shutDown("Unable to convert stream of format " + audioInputStream + " to format " + myformat);
      return;
     }
    // define the required attributes for our sdline, and make sure a compatible sdline is supported.
    DataLine.Info info = new DataLine.Info(SourceDataLine.class, myformat);
    if (!AudioSystem.isLineSupported(info)) 
     {
      shutDown("Line matching " + info + " not supported.");
      return;
     }
    // get and open the source data sdline for playback.
    try 
     {
      sdline = (SourceDataLine) AudioSystem.getLine(info);
      sdline.open(myformat, bufSize);
     }
    catch (LineUnavailableException ex) 
     {
      shutDown("Unable to open the sdline: " + ex);
      return;
     }
    // play back the captured audio data
    int frameSizeInBytes = myformat.getFrameSize();
    int bufferLengthInFrames = sdline.getBufferSize() / 8;
    int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
    byte[] data = new byte[bufferLengthInBytes];
    int numBytesRead = 0;
    // start the source data sdline
    sdline.start();
    while (thread != null) 
     {
      try 
       {
        if ((numBytesRead = playbackInputStream.read(data)) == -1) break;
        int numBytesRemaining = numBytesRead;
        while (numBytesRemaining > 0 ) numBytesRemaining -= sdline.write(data, 0, numBytesRemaining);
       }
      catch (Exception e) 
       {
        shutDown("Error during playback: " + e);
        break;
       }
     }
    // we reached the end of the stream.  let the data play out, then stop and close the sdline.
    if (thread != null) sdline.drain();
    sdline.stop();
    sdline.close();
    sdline = null;
    shutDown(null);
   }
 }
