
org.jitsi.impl.neomedia.protocol.RewritablePullBufferDataSource Maven / Gradle / Ivy
/*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.impl.neomedia.protocol;
import java.io.*;
import java.util.*;
import javax.media.*;
import javax.media.protocol.*;
import org.jitsi.impl.neomedia.control.*;
import org.jitsi.service.neomedia.*;
/**
* Implements a PullBufferDataSource wrapper which provides mute
* support for the wrapped instance.
*
* Because the class wouldn't work for our use case without it,
* CaptureDevice is implemented and is being delegated to the wrapped
* DataSource (if it supports the interface in question).
*
* @author Damian Minkov
* @author Lyubomir Marinov
*/
public class RewritablePullBufferDataSource
extends PullBufferDataSourceDelegate
implements MuteDataSource,
InbandDTMFDataSource
{
/**
* The indicator which determines whether this DataSource is mute.
*/
private boolean mute;
/**
* The tones to send via inband DTMF, if not empty.
*/
private final LinkedList tones
= new LinkedList();
/**
* Initializes a new RewritablePullBufferDataSource instance which
* is to provide mute support for a specific PullBufferDataSource.
*
* @param dataSource the PullBufferDataSource the new instance is
* to provide mute support for
*/
public RewritablePullBufferDataSource(PullBufferDataSource dataSource)
{
super(dataSource);
}
/**
* Sets the mute state of this DataSource.
*
* @param mute true to mute this DataSource; otherwise,
* false
*/
public void setMute(boolean mute)
{
this.mute = mute;
}
/**
* Determines whether this DataSource is mute.
*
* @return true if this DataSource is mute; otherwise,
* false
*/
public boolean isMute()
{
return mute;
}
/**
* Adds a new inband DTMF tone to send.
*
* @param tone the DTMF tone to send.
*/
public void addDTMF(DTMFInbandTone tone)
{
this.tones.add(tone);
}
/**
* Determines whether this DataSource sends a DTMF tone.
*
* @return true if this DataSource is sending a DTMF tone;
* otherwise, false.
*/
public boolean isSendingDTMF()
{
return !this.tones.isEmpty();
}
/**
* Get wrapped DataSource.
*
* @return wrapped DataSource
*/
public PullBufferDataSource getWrappedDataSource()
{
return dataSource;
}
/**
* {@inheritDoc}
*
* Overrides the super implementation to include the type hierarchy of the
* very wrapped dataSource instance into the search for the
* specified controlType.
*/
@Override
public Object getControl(String controlType)
{
if (InbandDTMFDataSource.class.getName().equals(controlType)
|| MuteDataSource.class.getName().equals(controlType))
{
return this;
}
else
{
/*
* The super implements a delegate so we can be sure that it
* delegates the invocation of Controls#getControl(String) to the
* wrapped dataSource.
*/
return AbstractControls.queryInterface(dataSource, controlType);
}
}
/**
* Implements {@link PullBufferDataSource#getStreams()}. Wraps the streams
* of the wrapped PullBufferDataSource into
* MutePullBufferStream instances in order to provide mute support
* to them.
*
* @return an array of PullBufferStream instances with enabled mute
* support
*/
@Override
public PullBufferStream[] getStreams()
{
PullBufferStream[] streams = dataSource.getStreams();
if (streams != null)
for (int streamIndex = 0; streamIndex < streams.length; streamIndex++)
streams[streamIndex] =
new MutePullBufferStream(streams[streamIndex]);
return streams;
}
/**
* Implements a PullBufferStream wrapper which provides mute
* support for the wrapped instance.
*/
private class MutePullBufferStream
extends SourceStreamDelegate
implements PullBufferStream
{
/**
* Initializes a new MutePullBufferStream instance which is to
* provide mute support for a specific PullBufferStream.
*
* @param stream the PullBufferStream the new instance is to
* provide mute support for
*/
private MutePullBufferStream(PullBufferStream stream)
{
super(stream);
}
/**
* Implements {@link PullBufferStream#getFormat()}. Delegates to the
* wrapped PullBufferStream.
*
* @return the Format of the wrapped PullBufferStream
*/
public Format getFormat()
{
return stream.getFormat();
}
/**
* Implements PullBufferStream#read(Buffer). If this instance is muted
* (through its owning RewritablePullBufferDataSource), overwrites the
* data read from the wrapped PullBufferStream with silence data.
* @param buffer which data will be filled. @throws IOException Thrown
* if an error occurs while reading.
*/
public void read(Buffer buffer)
throws IOException
{
stream.read(buffer);
if (isSendingDTMF())
RewritablePushBufferDataSource.sendDTMF(buffer, tones.poll());
else if (isMute())
RewritablePushBufferDataSource.mute(buffer);
}
/**
* Implements PullBufferStream#willReadBlock(). Delegates to the wrapped
* PullSourceStream.
* @return true if read would block; otherwise returns
* false.
*/
public boolean willReadBlock()
{
return stream.willReadBlock();
}
}
}