⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datasourcehandler.java

📁 是一个用java实现的
💻 JAVA
字号:
/*
 * DataSourceHandler.java
 *
 * Created on March 20, 2003, 10:56 AM
 */
package gov.nist.applet.phone.media.messaging;

import java.util.Enumeration;
import java.util.Vector;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.media.DataSink;
import javax.media.MediaLocator;
import javax.media.Control;
import javax.media.datasink.DataSinkErrorEvent;
import javax.media.datasink.DataSinkEvent;
import javax.media.datasink.DataSinkListener;
import javax.media.datasink.EndOfStreamEvent;
import javax.media.protocol.SourceTransferHandler;
import javax.media.protocol.PushDataSource;
import javax.media.protocol.PushSourceStream;
import javax.media.protocol.PullDataSource;
import javax.media.protocol.DataSource;
import javax.media.protocol.SourceStream;
import javax.media.IncompatibleSourceException;

/**
 * This Data source Handler allow one to write directly from a DataSource 
 * to an array of byte.
 * This Data Source Handler allow one to fill a buffer with MPEG_AUDIO 
 * or GSM audio data.
 * Example : One can record his voice from a microphone to a buffer in either a
 * MP3 or GSM format. To get the buffer with the recorded voice just call the
 * getRecordBuffer method
 * @author Jean Deruelle <jean.deruelle@nist.gov>
 *
 * <a href="{@docRoot}/uncopyright.html">This code is in the public domain.</a>
 */
public class DataSourceHandler    
    implements DataSink, SourceTransferHandler, Runnable{
    //DataSink listeners	
	protected Vector listeners = new Vector(1);
	
    final private static   boolean DEBUG = false;
    //states
    final protected static int NOT_INITIALIZED = 0;
    final protected static int OPENED = 1;
    final protected static int STARTED = 2;
    final protected static int CLOSED = 3;
    //current state
    protected int state = NOT_INITIALIZED;

    protected DataSource source;
    protected SourceStream [] streams;
    protected SourceStream stream;
    protected boolean push;   

    protected Control [] controls;
    
    //protected MediaLocator locator = null;
    protected String contentType = null;
    protected int bytesWritten = 0;
    protected static final int BUFFER_LEN = 128 * 1024;
    protected boolean syncEnabled = false;
	long lastSyncTime = -1;
	ByteArrayOutputStream baout=null;

    protected byte [] buffer1 = new byte[BUFFER_LEN];
    protected byte [] buffer2 = new byte[BUFFER_LEN];
    protected boolean buffer1Pending = false;
    protected long    buffer1PendingLocation = -1;
    protected int     buffer1Length;
    protected boolean buffer2Pending = false;
    protected long    buffer2PendingLocation = -1;
    protected int     buffer2Length;
    protected long    nextLocation = 0;
    protected Thread  writeThread = null;
    private   Integer bufferLock = new Integer(0);
    private   boolean receivedEOS = false;
    
    public  int WRITE_CHUNK_SIZE = 16384;

    private boolean streamingEnabled = false;
    
    /**
     * Constructs a new DataSourceHandler
     */
    public DataSourceHandler(){
    	baout=new ByteArrayOutputStream();
    }
    
    /**
     * Set the data source of this data source handler
     * @exception IncompatibleSourceException - if the data source cannot be 
     * handled, this exception is thrown
     */
    public void setSource(DataSource ds) throws IncompatibleSourceException {
	
		if (!(ds instanceof PushDataSource) &&
		    !(ds instanceof PullDataSource)) {
	
		    throw new IncompatibleSourceException("Incompatible datasource");
		}
		source = ds;
		
		if (source instanceof PushDataSource) {
		    push = true;
		    try {
				((PushDataSource) source).connect();
		    } catch (IOException ioe) {
		    }
		    streams = ((PushDataSource) source).getStreams();
		} else {
		    push = false;
		    try {
				((PullDataSource) source).connect();
		    } catch (IOException ioe) {
		    }
		    streams = ((PullDataSource) source).getStreams();
		}
		
		if (streams == null || streams.length != 1)
		    throw new IncompatibleSourceException("DataSource should have 1 stream");
		stream = streams[0];
		
		contentType = source.getContentType();
		if (push)
		    ((PushSourceStream)stream).setTransferHandler(this);
    }

    /**
     * Set the output <code>MediaLocator</code>.
     * This method should only be called once; an error is thrown if
     * the locator has already been set.
     * @param output <code>MediaLocator</code> that describes where 
     * 		the output goes.
     */
    public void setOutputLocator(MediaLocator output) {
		//locator = output;
    }

    /*public void setEnabled(boolean b) {
		streamingEnabled = b;
    }

    public void setSyncEnabled() {
		syncEnabled = true;
    }*/
    /**
	 * Our DataSink does not need to be opened.
     */
	public void open() {		
    }
	/**
	 * @see javax.media.DataSink#getOutputLocator()
	 */
    public MediaLocator getOutputLocator() {
    	return null;
		//return locator;
    }
	/**
	 * @see javax.media.DataSink#start()
	 */
    public void start() throws IOException {		
		//System.out.println("DATASOURCEHANDLER: start : source: "+source);		
	    if (source != null)
			source.start();
	    if (writeThread == null) {
			writeThread = new Thread(this);
			writeThread.setName("DataSourceHandler Thread");
			writeThread.start();
	    }
	    setState(STARTED);
    }

    /**
     * Stop the data-transfer.
     * If the source has not been connected and started,
     * <CODE>stop</CODE> does nothing.
     */
    public void stop() throws IOException {
    	//System.out.println("DATASOURCEHANDLER: stop");
		if (state == STARTED) {
		    if (source != null)
				source.stop();								
		    setState(OPENED);
		}
    }
	/**
	 * Set the state of this data source handler
	 */
    protected void setState(int state) {
		synchronized(this) {
		    this.state = state;
		}
    }   
	/**
	 * @see javax.media.DataSink#close()
	 */
    public final void close() {
		synchronized(this) {
		    if ( state == CLOSED )
			return;
		    setState(CLOSED);
		}
	
		if (push) {
		    for (int i = 0; i < streams.length; i++) {
				((PushSourceStream)streams[i]).setTransferHandler(null);
		    }
		}
		
		try {
		    source.stop();
		} catch (IOException e) {
		    System.err.println("IOException when stopping source " + e);
		}
		
	    // 	Disconnect the data source 
	    if (source != null)
			source.disconnect();	   
	
		removeAllListeners();
		//writeBufferToFile("d://temp//test.mp3");  
    }
	/**
	 * Get the current content type for this data source handler
	 *
	 * @return The current <CODE>ContentDescriptor</CODE> for this data source handler.
	 */
    public String getContentType() {
		return contentType;
    }
	/**
	 * Obtain the collection of objects that
	 * control the object that implements this interface.
	 * <p>
	 *
	 * No controls are supported.
	 * A zero length array is returned.
	 *
	 * @return A zero length array
	 */
    public Object [] getControls() {
		if (controls == null) {
		    controls = new Control[0];
		}
		return controls;
    }
	/**
	 * Obtain the object that implements the specified
	 * <code>Class</code> or <code>Interface</code>
	 * The full class or interface name must be used.
	 * <p>
	 *
	 * The control is not supported.
	 * <code>null</code> is returned.
	 *
	 * @return <code>null</code>.
	 */
    public Object getControl(String controlName) {
		return null;
    }

	/*
	 * @see javax.media.protocol.SourceTransferHandler#transferData(javax.media.protocol.PushSourceStream)
	 */
    public synchronized void transferData(PushSourceStream pss) {
    	if(state==STARTED){
			int totalRead = 0;
			int spaceAvailable = BUFFER_LEN;
			int bytesRead = 0;
			
			if (buffer1Pending) {
			    synchronized (bufferLock) {
				while (buffer1Pending) {
				    if (DEBUG) System.err.println("Waiting for free buffer");
				    try {
					bufferLock.wait();
				    } catch (InterruptedException ie) {
				    }
				}
			    }
			    if (DEBUG) System.err.println("Got free buffer");
			}
			
			//	System.err.println("In transferData()");
			while (spaceAvailable > 0) {
			    try {
				bytesRead = pss.read(buffer1, totalRead, spaceAvailable);
				//System.err.println("bytesRead = " + bytesRead);
				if (bytesRead > 16 * 1024 && WRITE_CHUNK_SIZE < 32 * 1024) {
				    if (  bytesRead > 64 * 1024 &&
					  WRITE_CHUNK_SIZE < 128 * 1024  )
					WRITE_CHUNK_SIZE = 128 * 1024;
				    else if (  bytesRead > 32 * 1024 &&
					       WRITE_CHUNK_SIZE < 64 * 1024  )
					WRITE_CHUNK_SIZE = 64 * 1024;
				    else if (  WRITE_CHUNK_SIZE < 32 * 1024  )
					WRITE_CHUNK_SIZE = 32 * 1024;
				    //System.err.println("Increasing buffer to " + WRITE_CHUNK_SIZE);
		
				}
			    } catch (IOException ioe) {
				// What to do here?
			    }
			    if (bytesRead <= 0) {
				break;
			    }
			    totalRead += bytesRead;
			    spaceAvailable -= bytesRead;
			}
		
			if (totalRead > 0) {
			    synchronized (bufferLock) {
				buffer1Pending = true;
				buffer1PendingLocation = nextLocation;
				buffer1Length = totalRead;
				nextLocation = -1; // assume next write is contiguous unless seeked
				// Notify availability to write thread
				if (DEBUG) 
					System.err.println("Notifying consumer");
				bufferLock.notifyAll();
			    }
			}
			// Send EOS if necessary
			if (bytesRead == -1) {
			    if (DEBUG) System.err.println("Got EOS");
			    receivedEOS = true;	    
			}
    	}
    }

    /**
     *  Asynchronous write thread
     */
    public void run() {    	
		while (!(state == CLOSED)){
			if(state==STARTED){ 	
			    synchronized (bufferLock) {		    			    	
					// Wait for some data or error
					while (!buffer1Pending && !buffer2Pending && 
					       state != CLOSED && !receivedEOS) {
				    	if (DEBUG) 
				    		System.err.println("Waiting for filled buffer");
					 	try {
							bufferLock.wait(500);
					    } catch (InterruptedException ie) {
					    }
					    if (DEBUG) 
					    	System.err.println("Consumer notified");
					}
			    }
			    // Something's pending
			    if (buffer2Pending) {
					if (DEBUG) 
						System.err.println("Writing Buffer2");
					// write that first
					write(buffer2, buffer2PendingLocation, buffer2Length);
					if (DEBUG) 
						System.err.println("Done writing Buffer2");
					buffer2Pending = false;
			    }
		
			    synchronized (bufferLock) {
					if (buffer1Pending) {
					    byte [] tempBuffer = buffer2;
					    buffer2 = buffer1;
					    buffer2Pending = true;
					    buffer2PendingLocation = buffer1PendingLocation;
					    buffer2Length = buffer1Length;
					    buffer1Pending = false;
					    buffer1 = tempBuffer;
					    if (DEBUG) System.err.println("Notifying producer");
					    bufferLock.notifyAll();
					} else {
					    if (receivedEOS)
						break;
					}
			    }
			}
			if (receivedEOS) {
			    if (DEBUG) 
			    	System.err.println("Sending EOS: streamingEnabled is " + streamingEnabled);	    
			    if (!streamingEnabled) {
					sendEndofStreamEvent();
			    }
			}
		}	
    }

	/**
	 * seek a specific location in the dataSource
	 * @return the location where the data source is now placed
	 */
    public synchronized long seek(long where) {
		nextLocation = where;
		return where;
    }
	/**
	 * Write the data in parameter in the data source handler buffer
	 * @param buffer - data to write into the data source handler buffer
	 * @param location - location to start 
	 * @param length - length to write
	 */
    private void write(byte [] buffer, long location, int length) {
		int offset, toWrite;	
	    offset = 0;
	    while (length > 0) {
			toWrite = WRITE_CHUNK_SIZE;
			if (length < toWrite)
			    toWrite = length;
			baout.write(buffer, offset, toWrite);
			bytesWritten += toWrite;
			length -= toWrite;
			offset += toWrite;		
			    						
			Thread.yield();
	    }
	
    }
    /**
     * @see javax.media.DataSink#addDataSinkListener(javax.media.datasink.DataSinkListener)
     */   
	public void addDataSinkListener(DataSinkListener dsl) {
		if (dsl != null)
			if (!listeners.contains(dsl))
				listeners.addElement(dsl);
	}
	/**
	 * @see javax.media.DataSink#removeDataSinkListener(javax.media.datasink.DataSinkListener)
	 */
	public void removeDataSinkListener(DataSinkListener dsl) {
		if (dsl != null)
			listeners.removeElement(dsl);
	}
	/**
	 * Send event to the listeners
	 * @param event - the vent to send
	 */
	protected void sendEvent(DataSinkEvent event) {
		if (!listeners.isEmpty()) {
			synchronized (listeners) {
				Enumeration list = listeners.elements();
				while (list.hasMoreElements()) {
					DataSinkListener listener = (DataSinkListener)list.nextElement();
					listener.dataSinkUpdate(event);
				}
			}
		}
	}
	/**
	 * remove All the listeners from this data source handler
	 */
	protected void removeAllListeners() {
		listeners.removeAllElements();
	}
	
	/**
	 * Send an end of stream event to the listeners
	 */    
	protected final void sendEndofStreamEvent() {
		sendEvent(new EndOfStreamEvent(this));
	}
	/**
	 * Send a data sink error event to the listeners
	 * @param reason - the reason of the error
	 */
	protected final void sendDataSinkErrorEvent(String reason) {
		sendEvent(new DataSinkErrorEvent(this, reason));
	}
	
	/**
	 * Get the recorded buffer of this data source handler
	 * @return byte array containing the data recorded
	 */
	public byte[] getRecordBuffer(){
		byte[] recordedBuffer= baout.toByteArray();
		baout.reset();
		return recordedBuffer;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -