FileDocCategorySizeDatePackage
SunAudioOutput.javaAPI DocJMF 2.1.1e16365Mon May 12 12:20:48 BST 2003com.sun.media.renderer.audio.device

SunAudioOutput

public class SunAudioOutput extends InputStream implements AudioOutput

Fields Summary
protected sun.audio.AudioStream
audioStream
protected int
bufLength
protected byte[]
buffer
protected static int
EOM
protected boolean
paused
protected boolean
started
protected boolean
flushing
private boolean
startAfterWrite
protected AudioFormat
format
private int
SUN_MAGIC
private int
HDR_SIZE
private int
FILE_LENGTH
private int
SAMPLE_RATE
private int
ENCODING
private int
CHANNELS
int
in
int
out
boolean
eom
int
samplesPlayed
private boolean
isMuted
private double
gain
private byte[]
silence
private static final int
END_OF_MEDIA_PADDING_LENGTH
padding length of silence at the end of the media (default constant)
private int
endOfMediaPaddingLength
padding length of silence at the end of the media
private byte[]
conversionBuffer
static final int
SLEEP_TIME
protected boolean
internalDelayUpdate
private SunAudioPlayThread
timeUpdatingThread
protected int
sunAudioInitialCount
protected int
sunAudioFinalCount
protected int
silenceCount
private static JMFSecurity
jmfSecurity
private static boolean
securityPrivelege
private Method[]
m
private Class[]
cl
private Object[]
args
Constructors Summary
public SunAudioOutput()


     
	try {
	    jmfSecurity = JMFSecurityManager.getJMFSecurity();
	    securityPrivelege = true;
	} catch (SecurityException e) {
	}
    
    
Methods Summary
public intbufferAvailable()

	if (SunAudioRenderer.runningOnMac)
	    return 0;
	return bufLength - dataAvailable() - 1;
    
public intdataAvailable()

	if (in == out)
	    return 0;
	else {
	    if (in > out)
		return in - out;
	    else
		return bufLength - (out - in);
	}
    
public synchronized voiddispose()


         if (audioStream != null) {
              timeUpdatingThread.kill();
	      sun.audio.AudioPlayer.player.stop(audioStream);
	}
	 buffer = null;
    
public voiddrain()


      int remain;
      int len;

      synchronized (this) {

	remain = endOfMediaPaddingLength;
        // pad the end of the media with silence
        // (used to drain sun.audio.AudioPlayer.player)

	while (remain > 0) {
	    len = write(silence,0,remain);
	    remain -= len;
	}

	// drain the JMF buffer.
	while (in != out && !paused) {
	    try {
		wait();
	    } catch (InterruptedException e) { }
	}


	// We'll need to drain longer on the Mac.
	if (SunAudioRenderer.runningOnMac) {
	    try {
		Thread.sleep(SunAudioRenderer.DEVICE_LATENCY/1000000L);
	    } catch (InterruptedException e) {}
	}
      }
    
public voidfinalize()

	super.finalize();
	dispose();
    
public synchronized voidflush()

	//System.out.println("SunAudioOutput flush ");
	in = 0;
	out = 0;
        sunAudioInitialCount = sunAudioFinalCount = samplesPlayed;
        flushing = true;
	notifyAll();
    
public doublegetGain()

	return 0f;
    
public longgetMediaNanoseconds()

	/*
	double samples = (double)samplesPlayed;
	//samples = samples/(double)format.getSampleRate();
	// SunAudioOutput plays at 8 Khz
	samples = samples/(double)8000;
	// System.out.println("AudioPlay.getTick() " + samples);
	return (audioStream == null ? 0 : (long)(samples * 1000000000L) );
	*/

	return (audioStream == null ? 0 : samplesPlayed * 125000L);
    
public booleangetMute()

	    return isMuted;
    
public floatgetRate()

	return 1.0f;
    
public booleaninitialize(javax.media.format.AudioFormat format, int length)


	this.format = format;
	//bufLength = length;
	//bufLength = 8000;	// hardcode the number to 8000.
        bufLength = 12000;	// hardcode the number to 12000.
	buffer = new byte[bufLength];

    	silence = new byte[bufLength];
	for (int i = 0; i < bufLength; i++)
		silence[i] = 127;

	if ( /*securityPrivelege &&*/ (jmfSecurity != null) ) {
	    String permission = null;

	    try {
		if (jmfSecurity.getName().startsWith("jmf-security")) {
		    permission = "thread";
		    jmfSecurity.requestPermission(m, cl, args, JMFSecurity.THREAD);
		    m[0].invoke(cl[0], args[0]);
		    
		    permission = "thread group";
		    jmfSecurity.requestPermission(m, cl, args, JMFSecurity.THREAD_GROUP);
		    m[0].invoke(cl[0], args[0]);
		} else if (jmfSecurity.getName().startsWith("internet")) {
		    PolicyEngine.checkPermission(PermissionID.THREAD);
		    PolicyEngine.assertPermission(PermissionID.THREAD);
		}
	    } catch (Throwable e) {
		if (JMFSecurityManager.DEBUG) {
		    System.err.println("Unable to get " + permission +
				       " privilege  " + e);
		}
		securityPrivelege = false;
		// TODO: Do the right thing if permissions cannot be obtained.
		// User should be notified via an event
	    }
	}
	if ( (jmfSecurity != null) && (jmfSecurity.getName().startsWith("jdk12"))) {
	    try {
		Constructor cons = jdk12CreateThreadAction.cons;
		
		timeUpdatingThread = (SunAudioPlayThread) jdk12.doPrivM.invoke(
								   jdk12.ac,
								   new Object[] {
		    cons.newInstance(
				     new Object[] {
			SunAudioPlayThread.class,
			    })});
	    } catch (Exception e) {
	    }
	} else {
	    timeUpdatingThread = new SunAudioPlayThread();
	}

	timeUpdatingThread.setStream(this);
        setPaddingLength(END_OF_MEDIA_PADDING_LENGTH); // defualt size

	// BB
	ByteArrayOutputStream tempOut = new ByteArrayOutputStream();
	DataOutputStream tempData = new DataOutputStream(tempOut);
	try {
		tempData.writeInt(SUN_MAGIC);
		tempData.writeInt(HDR_SIZE);
		tempData.writeInt(FILE_LENGTH);
		tempData.writeInt(ENCODING);
		tempData.writeInt(SAMPLE_RATE);
		tempData.writeInt(CHANNELS);
	} catch (Exception e) {}

	byte[] buf = tempOut.toByteArray();

	write(buf, 0, buf.length);

     String encoding = format.getEncoding();
     int sampleRate = (int)format.getSampleRate();

     if (!( (format.getChannels() == 1) &&
         (sampleRate == 8000) &&
         (encoding.equals(AudioFormat.ULAW))  ) ) {

          System.out.println("AudioPlay:Unsupported Audio Format");
	  return false;

    }


	try {
		audioStream = new sun.audio.AudioStream(this);
	} catch (Exception e) {
		System.err.println("Exception: " + e);
		audioStream = null;
		return false;
	}
        return true;
    
public voidpause()


        //System.out.println("SunAudioOutput pause ");
         if (audioStream != null) {
            timeUpdatingThread.pause();
	    sun.audio.AudioPlayer.player.stop(audioStream);
	 }
	 paused = true;
    
public synchronized intread()

	// Block if the buffer is empty.
	while (in == out) {
	    if (eom) {
		eom = false;
		return EOM;
	    }
	    try {
		wait();
	    } catch (InterruptedException e) {
	    }
	}
	int ret = buffer[out++] & 0xFF;
	if (out >= buffer.length) {
	    out = 0;
	}
	return ret;
    
public synchronized intread(byte[] b, int off, int len)

	//System.out.println("AP:needs: " + len + " available: " + dataAvailable());
 	//System.out.println("AP: read3: " + Thread.currentThread() + ": " +
 	//		   Thread.currentThread().getPriority() +
 	//		   ": paused, avail: " + paused + ": " + available());

        int inputLength=len;

	if (len <= 0) {
	    return -1;
	}


        if ( (len>4) && (!internalDelayUpdate) ) {
          //System.out.println("sunAudioInternalDelay "+len);
          internalDelayUpdate=true;
          timeUpdatingThread.setInternalDelay(len);
        }

	if (dataAvailable() == 0) {
            //System.out.println("underflow - no data: " + inputLength);
            System.arraycopy(silence, 0, b, off, inputLength);
            //timeUpdatingThread.resetSampleCountTime();
            //sunAudioInitialCount=sunAudioFinalCount;
	    silenceCount += inputLength;
            return inputLength;
	}


	// This read will not block
	int c = read();
	if (c < 0) {
	    return -1;
	}
	b[off] = (byte) c;

  	int rlen = 1;

	if ( in != out ) {
	  int avail, need, size;

	  len--; // 1 byte read and copied.
	  if (out < in) {
	    avail = (in - out);
	    if (avail > len)
	      avail = len;
 	    System.arraycopy(buffer, out, b, off+1, avail);
	    out += avail;
	    rlen += avail;
	  } else if ( out > in ) {
	    avail = bufLength - out;
	    if (avail >= len) {
	      avail = len;
	      System.arraycopy(buffer, out, b, off+1, avail);

	      out += avail;
	      if (out >= bufLength)
		out = 0;
	      rlen += avail;
	    } else {
	      System.arraycopy(buffer, out, b, off+1, avail);
	      out += avail;
	      if (out >= bufLength)
		out = 0;
	      int copied = avail;
	      rlen += avail;
	      need = (len - avail);
	      avail = (in - out);
	      if (need <= avail)
		size = need;
	      else
		size = avail;
	      System.arraycopy(buffer, 0, b, off+1+copied, size);
	      out += size;
	      rlen += size;
	    }
	  }
	}

	// Notify if there's any waiting writer.
	if (isMuted) {

	    //System.err.println("muted -- fill with silence");
            System.arraycopy(silence, 0, b, off, inputLength);

	} else {

	    if (rlen<inputLength) { 

		// pad the rest of the buffer with silence 
 		// but don't update the sample count

		//System.out.println("underflow - pad with silence: " + (inputLength-rlen));
		System.arraycopy(silence, 0, b, off+rlen, inputLength-rlen);
		silenceCount += (inputLength-rlen);

	    } else if (silenceCount > 0) {

		// There were some silence filled in before.  We'll
		// need to compensate for that.
		if (silenceCount > rlen) {
		    silenceCount -= rlen;
		    rlen = 0;
		} else {
		    rlen -= silenceCount;
		    silenceCount = 0;
		}
	    }
        }

        timeUpdatingThread.resetSampleCountTime();
        sunAudioInitialCount=sunAudioFinalCount;
        sunAudioFinalCount+=rlen;
        notifyAll();

        return inputLength;

    
public synchronized voidresume()


        //System.out.println("SunAudioOutput resume ");
        if ( (audioStream != null) && (!started || paused) )  {
                started=true;
                //System.out.println("start the player "+dataAvailable());
		sun.audio.AudioPlayer.player.start(audioStream);
                timeUpdatingThread.start();
	}

	paused = false;

    
public voidsetGain(double g)

    
public voidsetMute(boolean m)

	// System.out.println("AudioPlay.setMute()");
	isMuted = m;
    
protected voidsetPaddingLength(int paddingLength)

      //System.out.println("SunAudioOutput setPaddingLength "+ paddingLength);
      endOfMediaPaddingLength = paddingLength;
      if (endOfMediaPaddingLength > silence.length)
          endOfMediaPaddingLength = silence.length;
   
public floatsetRate(float r)

	return 1.0f;
    
public synchronized intwrite(byte[] data, int off, int len)


     //System.out.println("SunAudioOutput.write , try len"+len+" in "+in+" out "+out);
     //System.out.println("abc: SunAudioOutput.write "+len);

        flushing = false;
	if (len <= 0)
	    return 0;


	// Block if the buffer is full.
	while ((in + 1) % buffer.length == out) {
	    try {
		wait();
	    } catch (InterruptedException e) {
	    }
	}

       if (flushing) {
	    return 0;
	}

 	int wlen = 0;

	if (true) {
	  int canWrite, actualWrite, actualWrite1, length1;
	  if (in < out) {
	    canWrite = out - in -1;
	    actualWrite = (canWrite < len) ? canWrite : len;
 	    System.arraycopy(data, off, buffer, in, actualWrite);
	    in += actualWrite;
	    wlen += actualWrite;
	  } else {
	    if (out == 0)
	      length1 = bufLength - in - 1;
	    else
	      length1 = bufLength - in;

	    if (length1 >= len) {
	      actualWrite = len;
	      System.arraycopy(data, off, buffer, in, actualWrite);
	      in += actualWrite;
	      if (in >= bufLength)
		in = 0;
	      wlen += actualWrite;
	    } else {
	      actualWrite = length1;
              System.arraycopy(data, off, buffer, in, actualWrite);
	      in += actualWrite;
	      if (in >= bufLength)
		in = 0;
	      wlen += actualWrite;
	      len -= actualWrite;
	      actualWrite1 = actualWrite;

	      if (out > 0) {
		canWrite = out -in -1;
		actualWrite = (canWrite < len) ? canWrite : len;
		System.arraycopy(data, off+actualWrite1,
				 buffer, 0, actualWrite);
		wlen += actualWrite;
		in = actualWrite;
	      }
	    }
	  }
	}

	// Notify the waiting reader.
	notifyAll();

        //System.out.println("before wlen "+wlen+" in "+in+" out "+out);

        //saveInput(data,off,wlen);

 	return wlen;