/*
* 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.*;
/**
* Implements a <tt>PushBufferDataSource</tt> wrapper which provides mute
* support for the wrapped instance.
* <p>
* Because the class wouldn't work for our use case without it,
* <tt>CaptureDevice</tt> is implemented and is being delegated to the wrapped
* <tt>DataSource</tt> (if it supports the interface in question).
* </p>
*
* @author Lubomir Marinov
*/
public class MutePushBufferDataSource
extends PushBufferDataSource
implements CaptureDevice
{
/**
* 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 MutePushBufferDataSource(PushBufferDataSource dataSource)
{
this.dataSource = dataSource;
}
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();
if (data != null)
{
Class<?> dataClass = data.getClass();
final int fromIndex = buffer.getOffset();
final int toIndex = fromIndex + buffer.getLength();
if (Format.byteArray.equals(dataClass))
Arrays
.fill((byte[]) data, fromIndex, toIndex, (byte) 0);
else if (Format.intArray.equals(dataClass))
Arrays.fill((int[]) data, fromIndex, toIndex, 0);
else if (Format.shortArray.equals(dataClass))
Arrays.fill((short[]) data, fromIndex, toIndex,
(short) 0);
buffer.setData(data);
}
}
}
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);
}
}
}
}