package net.java.sip.communicator.impl.media;
import java.io.*;
import java.util.*;
import javax.media.*;
import javax.media.control.*;
import javax.media.format.AudioFormat;
import javax.media.protocol.*;
import net.java.sip.communicator.impl.media.codec.audio.Utils;
import org.eclipse.swt.graphics.Point;
import org.mobicents.sip.phone.views.SipPhoneView;
import org.mobicents.sip.phone.views.VisualizationService;
public class MonitoredPushBufferDataSource
extends PushBufferDataSource
implements CaptureDevice
{
private final PushBufferDataSource dataSource;
private String visualizationFilter;
private int samplingRate = 44100;
private int bps = 16;
private boolean littleEndian = true;
private long phase = Long.MIN_VALUE;
public MonitoredPushBufferDataSource(PushBufferDataSource dataSource, String visualizationFilter)
{
this.dataSource = dataSource;
this.visualizationFilter = visualizationFilter;
PushBufferStream[] streams = dataSource.getStreams();
for(PushBufferStream stream:streams) {
if(stream.getFormat() instanceof AudioFormat) {
AudioFormat af = (AudioFormat) stream.getFormat();
this.samplingRate = (int)af.getSampleRate();
this.bps = af.getSampleSizeInBits();
this.littleEndian = af.getEndian() == af.LITTLE_ENDIAN;
}
}
}
public void connect() throws IOException
{
dataSource.connect();
}
public void disconnect()
{
dataSource.disconnect();
}
public CaptureDeviceInfo getCaptureDeviceInfo()
{
CaptureDeviceInfo captureDeviceInfo;
if (dataSource instanceof CaptureDevice)
captureDeviceInfo =
((CaptureDevice) dataSource).getCaptureDeviceInfo();
else
captureDeviceInfo = null;
return captureDeviceInfo;
}
public String getContentType()
{
return dataSource.getContentType();
}
public Object getControl(String controlType)
{
return dataSource.getControl(controlType);
}
public Object[] getControls()
{
return dataSource.getControls();
}
public Time getDuration()
{
return dataSource.getDuration();
}
public FormatControl[] getFormatControls()
{
FormatControl[] formatControls;
if (dataSource instanceof CaptureDevice)
formatControls = ((CaptureDevice) dataSource).getFormatControls();
else
formatControls = new FormatControl[0];
return formatControls;
}
public PushBufferStream[] getStreams()
{
PushBufferStream[] streams = dataSource.getStreams();
if (streams != null)
for (int streamIndex = 0; streamIndex < streams.length; streamIndex++)
streams[streamIndex] =
new MonitoredPushBufferStream(streams[streamIndex]);
return streams;
}
public void start() throws IOException
{
dataSource.start();
}
public void stop() throws IOException
{
dataSource.stop();
}
private class MonitoredPushBufferStream
implements PushBufferStream
{
private final PushBufferStream stream;
public MonitoredPushBufferStream(PushBufferStream stream)
{
this.stream = stream;
}
public ContentDescriptor getContentDescriptor()
{
return stream.getContentDescriptor();
}
public long getContentLength()
{
return stream.getContentLength();
}
public Object getControl(String controlType)
{
return stream.getControl(controlType);
}
public Object[] getControls()
{
return stream.getControls();
}
public Format getFormat()
{
return stream.getFormat();
}
public boolean endOfStream()
{
return stream.endOfStream();
}
public void read(Buffer buffer) throws IOException
{
stream.read(buffer);
Object data = buffer.getData();
if (data != null)
{
Class<?> dataClass = data.getClass();
final int fromIndex = buffer.getOffset();
final int toIndex = fromIndex + buffer.getLength();
int maxValue = Integer.MIN_VALUE;
int minValue = Integer.MAX_VALUE;
if (Format.byteArray.equals(dataClass)) {
byte[] byteSignal = (byte[]) data;
if(bps==16) {
int length = toIndex - fromIndex;
if(length <= 0) return;
short[] shortSignal = Utils.byteToShortArray(byteSignal, fromIndex, toIndex - fromIndex, littleEndian);
for(int q=fromIndex; q<toIndex; q++) {
maxValue = Math.max(shortSignal[q/2],maxValue);
minValue = Math.min(shortSignal[q/2],minValue);
updateValues(minValue, maxValue);
phase++;
}
} else {
for(int q=fromIndex; q<toIndex; q++) {
maxValue = Math.max(byteSignal[q],maxValue);
minValue = Math.min(byteSignal[q],minValue);
updateValues(minValue, maxValue);
phase++;
}
}
} /*
else if (Format.intArray.equals(dataClass)) {
int[] signal = (int[]) data;
for(int q=fromIndex; q<toIndex; q++) {
maxValue = Math.max(signal[q],maxValue);
minValue = Math.min(signal[q],minValue);
updateValues(minValue, maxValue);
phase++;
}
}
else if (Format.shortArray.equals(dataClass)) {
short[] signal = (short[]) data;
for(int q=fromIndex; q<toIndex; q++) {
maxValue = Math.max(signal[q],maxValue);
minValue = Math.min(signal[q],minValue);
updateValues(minValue, maxValue);
phase++;
}
}*/
buffer.setData(data);
}
}
public void updateValues(int minValue, int maxValue) {
int mod = (int)Math.abs(phase)%(samplingRate/8);
if(mod == 0) {
VisualizationService vis = SipPhoneView.getVisualizationService(visualizationFilter);
if(vis != null) {
vis.addValue(new Point(minValue, maxValue));
}
}
}
public void setTransferHandler(BufferTransferHandler transferHandler)
{
stream.setTransferHandler((transferHandler == null) ? null
: new MonitoredBufferTransferHandler(transferHandler));
}
public class MonitoredBufferTransferHandler
implements BufferTransferHandler
{
private final BufferTransferHandler transferHandler;
public MonitoredBufferTransferHandler(
BufferTransferHandler transferHandler)
{
this.transferHandler = transferHandler;
}
public void transferData(PushBufferStream stream)
{
transferHandler.transferData(MonitoredPushBufferStream.this);
}
}
}
}