/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.media;
import java.io.*;
import java.util.*;
import javax.media.*;
import javax.media.control.*;
import javax.media.protocol.*;
import org.eclipse.swt.graphics.Point;
import org.mobicents.sip.phone.SipPhoneActivator;
import org.mobicents.sip.phone.views.SipPhoneView;
import org.mobicents.sip.phone.views.VisualizationService;
import org.osgi.framework.ServiceReference;
public class SinePushDataSource
extends PushBufferDataSource
implements CaptureDevice
{
private long phase = -999999999;
private float frequency = 1000;
private float volume = 0.5f;
private int samplingRate = 44100;
/**
* The wrapped <tt>DataSource</tt> this instance provides mute support for.
*/
private final PushBufferDataSource dataSource;
/**
* The indicator which determines whether this <tt>DataSource</tt> is mute.
*/
private boolean mute;
/**
* Initializes a new <tt>MutePushBufferDataSource</tt> instance which is to
* provide mute support for a specific <tt>PushBufferDataSource</tt>.
*
* @param dataSource the <tt>PushBufferDataSource</tt> the new instance is
* to provide mute support for
*/
public SinePushDataSource(PushBufferDataSource dataSource)
{
this.dataSource = dataSource;
SipPhoneActivator.getDefault().getBundle().getBundleContext().registerService(
SinePushDataSource.class.getName(), this, null);
}
public static SinePushDataSource getSinePushDataSource() {
ServiceReference ref = SipPhoneActivator.getDefault().getBundle().getBundleContext().getServiceReference(
SinePushDataSource.class.getName());
return (SinePushDataSource)SipPhoneActivator.getDefault().getBundle().getBundleContext().getService(ref);
}
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 MutePushBufferStream(streams[streamIndex]);
return streams;
}
/**
* Determines whether this <tt>DataSource</tt> is mute.
*
* @return <tt>true</tt> if this <tt>DataSource</tt> is mute; otherwise,
* <tt>false</tt>
*/
public synchronized boolean isMute()
{
return mute;
}
/**
* Sets the mute state of this <tt>DataSource</tt>.
*
* @param mute <tt>true</tt> to mute this <tt>DataSource</tt>; otherwise,
* <tt>false</tt>
*/
public synchronized void setMute(boolean mute)
{
this.mute = mute;
}
public void start() throws IOException
{
dataSource.start();
}
public void stop() throws IOException
{
dataSource.stop();
}
/**
* Implements a <tt>PushBufferStream</tt> wrapper which provides mute
* support for the wrapped instance.
*/
private class MutePushBufferStream
implements PushBufferStream
{
/**
* The wrapped stream this instance provides mute support for.
*/
private final PushBufferStream stream;
/**
* Initializes a new <tt>MutePushBufferStream</tt> instance which is to
* provide mute support for a specific <tt>PushBufferStream</tt>.
*
* @param stream the <tt>PushBufferStream</tt> the new instance is to
* provide mute support for
*/
public MutePushBufferStream(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);
//if (isMute())
{
Object data = buffer.getData();
int maxValue = -999999999;
int minValue = 999999999;
if (data != null)
{
Class<?> dataClass = data.getClass();
final int fromIndex = buffer.getOffset();
final int toIndex = fromIndex + buffer.getLength();
if (Format.byteArray.equals(dataClass)) {
byte[] signal = (byte[]) data;
for(int q=fromIndex; q<toIndex; q++) {
signal[q] = (byte)(Byte.MAX_VALUE*volume*Math.sin(2*3.14*phase++*frequency/samplingRate));
maxValue = Math.max(signal[q],maxValue);
minValue = Math.min(signal[q],minValue);
updateValues(minValue, maxValue);
}
}
else if (Format.intArray.equals(dataClass)) {
int[] signal = (int[]) data;
for(int q=fromIndex; q<toIndex; q++) {
signal[q] = (int)(Integer.MAX_VALUE*volume*Math.sin(phase++*frequency/samplingRate));
maxValue = Math.max(signal[q],maxValue);
minValue = Math.min(signal[q],minValue);
updateValues(minValue, maxValue);
}
}
else if (Format.shortArray.equals(dataClass)) {
short[] signal = (short[]) data;
for(int q=fromIndex; q<toIndex; q++) {
signal[q] = (short)(Short.MAX_VALUE*volume*Math.sin(phase++*frequency/samplingRate));
maxValue = Math.max(signal[q],maxValue);
minValue = Math.min(signal[q],minValue);
updateValues(minValue, maxValue);
}
}
buffer.setData(data);
}
}
}
public void updateValues(int minValue, int maxValue) {
int mod = (int)Math.abs(phase)%(samplingRate/10);
if(mod == 0) {
VisualizationService vis = SipPhoneView.getVisualizationService("TYPE=OUT");
if(vis != null) {
vis.addValue(new Point(minValue, maxValue));
}
}
}
public void setTransferHandler(BufferTransferHandler transferHandler)
{
stream.setTransferHandler((transferHandler == null) ? null
: new MuteBufferTransferHandler(transferHandler));
}
/**
* Implements a <tt>BufferTransferHandler</tt> wrapper which doesn't
* expose a wrapped <tt>PushBufferStream</tt> but rather its wrapper in
* order to give full control to the
* {@link PushBufferStream#read(Buffer)} method of the wrapper.
*/
public class MuteBufferTransferHandler
implements BufferTransferHandler
{
/**
* The wrapped <tt>BufferTransferHandler</tt> which receives the
* actual events from the wrapped <tt>PushBufferStream</tt>.
*/
private final BufferTransferHandler transferHandler;
/**
* Initializes a new <tt>MuteBufferTransferHandler</tt> instance
* which is to overwrite the source <tt>PushBufferStream</tt> of a
* specific <tt>BufferTransferHandler</tt>.
*
* @param transferHandler the <tt>BufferTransferHandler</tt> the new
* instance is to overwrite the source
* <tt>PushBufferStream</tt> of
*/
public MuteBufferTransferHandler(
BufferTransferHandler transferHandler)
{
this.transferHandler = transferHandler;
}
public void transferData(PushBufferStream stream)
{
transferHandler.transferData(MutePushBufferStream.this);
}
}
}
}