Introduces support for muting a call.

cusax-fix
Lyubomir Marinov 18 years ago
parent 022bc07d56
commit 8589c49d20

@ -57,6 +57,7 @@ TEXT_ITALIC_ROLLOVER_BUTTON=resources/images/impl/gui/buttons/textItalicRollover
TEXT_UNDERLINED_ROLLOVER_BUTTON=resources/images/impl/gui/buttons/textUnderlinedRollover.png
DIAL_BUTTON=resources/images/impl/gui/buttons/dialButton.png
HOLD_BUTTON=resources/images/impl/gui/buttons/holdButton.png
MUTE_BUTTON=resources/images/impl/gui/buttons/muteButton.png
INVITE_DIALOG_ICON=resources/images/impl/gui/common/inviteDialogIcon.png
SEND_SMS_ICON=resources/images/impl/gui/common/gsm.png
DIAL_BUTTON_BG=resources/images/impl/gui/buttons/dialButtonBg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -83,6 +83,10 @@ public CallParticipantPanel(CallManager callManager,
holdButton.setBounds(0, 74, 36, 36);
contactPanel.add(holdButton, new Integer(1));
Component muteButton = new MuteButton(this.callParticipant);
muteButton.setBounds(36, 74, 36, 36);
contactPanel.add(muteButton, new Integer(1));
dialButton = new DialButton(callManager,
new ImageIcon(ImageLoader.getImage(ImageLoader.DIAL_BUTTON)));

@ -0,0 +1,119 @@
/*
* 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.gui.main.call;
import java.awt.event.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
/**
* Represents an UI means to mute the audio stream sent to an associated
* <tt>CallPariticant</tt>.
*
* @author Lubomir Marinov
*/
public class MuteButton
extends JToggleButton
{
/**
* Initializes a new <tt>MuteButton</tt> instance which is to mute the audio
* stream to a specific <tt>CallParticipant</tt>.
*
* @param callParticipant the <tt>CallParticipant</tt> to be associated with
* the new instance and to have the audio stream sent to muted
*/
public MuteButton(CallParticipant callParticipant)
{
super(new ImageIcon(ImageLoader.getImage(ImageLoader.MUTE_BUTTON)));
setModel(new MuteButtonModel(callParticipant));
}
/**
* Represents the model of a toggle button that mutes the audio stream sent
* to a specific <tt>CallParticipant</tt>.
*/
private static class MuteButtonModel
extends ToggleButtonModel
{
/**
* The <tt>CallParticipant</tt> whose state is being adapted for the
* purposes of depicting as a toggle button.
*/
private final CallParticipant callParticipant;
/**
* Initializes a new <tt>MuteButtonModel</tt> instance to represent the
* state of a specific <tt>CallParticipant</tt> as a toggle button.
*
* @param callParticipant the <tt>CallParticipant</tt> whose state is to
* be represented as a toggle button
*/
public MuteButtonModel(CallParticipant callParticipant)
{
this.callParticipant = callParticipant;
addActionListener(new ActionListener()
{
/**
* Invoked when an action occurs.
*
* @param evt the <tt>ActionEvent</tt> instance containing the
* data associated with the action and the act of its
* performing
*/
public void actionPerformed(ActionEvent evt)
{
MuteButtonModel.this.actionPerformed(this, evt);
}
});
}
/**
* Handles actions performed on this model on behalf of a specific
* <tt>ActionListener</tt>.
*
* @param listener the <tt>ActionListener</tt> notified about the
* performing of the action
* @param evt the <tt>ActionEvent</tt> containing the data associated
* with the action and the act of its performing
*/
private void actionPerformed(ActionListener listener, ActionEvent evt)
{
Call call = callParticipant.getCall();
if (call != null)
{
OperationSetBasicTelephony telephony =
(OperationSetBasicTelephony) call.getProtocolProvider()
.getOperationSet(OperationSetBasicTelephony.class);
telephony.setMute(callParticipant, !callParticipant.isMute());
fireItemStateChanged(new ItemEvent(this,
ItemEvent.ITEM_STATE_CHANGED, this,
isSelected() ? ItemEvent.SELECTED : ItemEvent.DESELECTED));
fireStateChanged();
}
}
/**
* Determines whether this model represents a state which should be
* visualized by the currently depicting toggle button as selected.
*/
public boolean isSelected()
{
return callParticipant.isMute();
}
}
}

@ -403,6 +403,11 @@ public class ImageLoader {
public static final ImageID HOLD_BUTTON
= new ImageID("HOLD_BUTTON");
/**
* A mute button icon. The icon shown in the CallParticipant panel.
*/
public static final ImageID MUTE_BUTTON = new ImageID("MUTE_BUTTON");
/**
* The image used, when a contact has no photo specified.
*/

@ -58,6 +58,7 @@ TEXT_ITALIC_ROLLOVER_BUTTON=resources/images/impl/gui/buttons/textItalicRollover
TEXT_UNDERLINED_ROLLOVER_BUTTON=resources/images/impl/gui/buttons/textUnderlinedRollover.png
DIAL_BUTTON=resources/images/impl/gui/buttons/dialButton.png
HOLD_BUTTON=resources/images/impl/gui/buttons/holdButton.png
MUTE_BUTTON=resources/images/impl/gui/buttons/muteButton.png
INVITE_DIALOG_ICON=resources/images/impl/gui/common/inviteDialogIcon.png
SEND_SMS_ICON=resources/images/impl/gui/common/gsm.png
DIAL_BUTTON_BG=resources/images/impl/gui/buttons/dialButtonBg.png

@ -2370,4 +2370,25 @@ public void run()
}
}
/**
* Determines whether the audio of this session is (set to) mute.
*
* @return <tt>true</tt> if the audio of this session is (set to) mute;
* otherwise, <tt>false</tt>
*/
public boolean isMute()
{
return mediaServCallback.getMediaControl(getCall()).isMute();
}
/**
* Sets the mute state of the audio of this session.
*
* @param mute <tt>true</tt> to mute the audio of this session; otherwise,
* <tt>false</tt>
*/
public void setMute(boolean mute)
{
mediaServCallback.getMediaControl(getCall()).setMute(mute);
}
}

@ -6,22 +6,20 @@
*/
package net.java.sip.communicator.impl.media;
import java.awt.Dimension;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.media.*;
import javax.media.control.*;
import javax.media.format.*;
import javax.media.protocol.*;
import javax.sdp.*;
import net.java.sip.communicator.impl.media.device.*;
import net.java.sip.communicator.util.*;
import javax.sdp.*;
import net.java.sip.communicator.service.media.MediaException;
import java.util.*;
import net.java.sip.communicator.service.configuration.*;
import javax.media.control.*;
import javax.media.format.*;
import javax.media.rtp.*;
import java.awt.Dimension;
import net.java.sip.communicator.service.media.MediaException;
import net.java.sip.communicator.util.*;
/**
* This class is intended to provide a generic way to control media package.
@ -32,6 +30,7 @@
* @author Jean Lorchat
* @author Ryan Ricard
* @author Ken Larson
* @author Lubomir Marinov
*/
public class MediaControl
{
@ -57,6 +56,11 @@ public class MediaControl
*/
private DataSource avDataSource = null;
/**
* The audio <tt>DataSource</tt> which provides mute support.
*/
private MutePushBufferDataSource muteAudioDataSource;
/**
* SDP Codes of all video formats that JMF supports.
*/
@ -172,8 +176,8 @@ public class MediaControl
*/
public MediaControl()
{
}
/**
* Returns the duration of the output data source. Usually this will be
* DURATION_UNKNOWN, but if the current data source is set to an audio
@ -372,6 +376,13 @@ public void initCaptureDevices()
{
audioDataSource = createDataSource(audioDeviceInfo.getLocator());
audioCaptureDevice = (CaptureDevice) audioDataSource;
/* Provide mute support for the audio (if possible). */
if (audioDataSource instanceof PushBufferDataSource)
audioDataSource =
muteAudioDataSource =
new MutePushBufferDataSource(
(PushBufferDataSource) audioDataSource);
}
// video device
@ -1198,4 +1209,26 @@ private void registerCustomPackages()
+ currentPackagePrefix);
}
/**
* Determines whether the audio of this instance is mute.
*
* @return <tt>true</tt> if the audio of this instance is mute; otherwise,
* <tt>false</tt>
*/
public boolean isMute()
{
return (muteAudioDataSource != null) && muteAudioDataSource.isMute();
}
/**
* Sets the mute state of the audio of this instance.
*
* @param mute <tt>true</tt> to mute the audio of this instance;
* <tt>false</tt>, otherwise
*/
public void setMute(boolean mute)
{
if (muteAudioDataSource != null)
muteAudioDataSource.setMute(mute);
}
}

@ -0,0 +1,275 @@
/*
* 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);
}
}
}
}

@ -30,8 +30,8 @@
* @author Symphorien Wanko
*/
public class OperationSetBasicTelephonyJabberImpl
implements OperationSetBasicTelephony,
RegistrationStateChangeListener,
extends AbstractOperationSetBasicTelephony
implements RegistrationStateChangeListener,
JingleMediaListener,
JingleTransportListener,
JingleSessionRequestListener,
@ -52,11 +52,6 @@ public class OperationSetBasicTelephonyJabberImpl
*/
private ProtocolProviderServiceJabberImpl protocolProvider = null;
/**
* A list of listeners registered for call events.
*/
private Vector callListeners = new Vector();
/**
* Contains references for all currently active (non ended) calls.
*/
@ -134,21 +129,6 @@ else if ((evt.getNewState() == RegistrationState.UNREGISTERED))
}
}
/**
* Registers <tt>listener</tt> with this provider so that it
* could be notified when incoming calls are received.
*
* @param listener the listener to register with this provider.
*/
public void addCallListener(CallListener listener)
{
synchronized(callListeners)
{
if (!callListeners.contains(listener))
callListeners.add(listener);
}
}
/**
* Create a new call and invite the specified CallParticipant to it.
*
@ -295,40 +275,6 @@ private CallJabberImpl createOutgoingCall(String calleeAddress)
return (CallJabberImpl) callParticipant.getCall();
}
/**
* Creates and dispatches a <tt>CallEvent</tt> notifying registered
* listeners that an event with id <tt>eventID</tt> has occurred on
* <tt>sourceCall</tt>.
*
* @param eventID the ID of the event to dispatch
* @param sourceCall the call on which the event has occurred.
*/
protected void fireCallEvent( int eventID,
CallJabberImpl sourceCall)
{
CallEvent cEvent = new CallEvent(sourceCall, eventID);
logger.debug("Dispatching a CallEvent to "
+ callListeners.size()
+ " listeners. event is: " + cEvent.toString());
Iterator listeners = null;
synchronized(callListeners)
{
listeners = new ArrayList(callListeners).iterator();
}
while(listeners.hasNext())
{
CallListener listener = (CallListener)listeners.next();
if(eventID == CallEvent.CALL_INITIATED)
listener.outgoingCallCreated(cEvent);
else if(eventID == CallEvent.CALL_RECEIVED)
listener.incomingCallReceived(cEvent);
else if(eventID == CallEvent.CALL_ENDED)
listener.callEnded(cEvent);
}
}
/**
* Returns an iterator over all currently active calls.
*
@ -363,19 +309,6 @@ public void putOnHold(CallParticipant participant)
getJingleMediaSession().setTrasmit(false);
}
/**
* Removes the <tt>listener</tt> from the list of call listeners.
*
* @param listener the listener to unregister.
*/
public void removeCallListener(CallListener listener)
{
synchronized(callListeners)
{
callListeners.remove(listener);
}
}
/**
* Implements method <tt>hangupCallParticipant</tt>
* from <tt>OperationSetBasicTelephony</tt>.

@ -13,18 +13,12 @@
* @author Damian Minkov
*/
public class MockOperationSetBasicTelephony
implements OperationSetBasicTelephony,
CallChangeListener
extends AbstractOperationSetBasicTelephony
implements CallChangeListener
{
private static final Logger logger
= Logger.getLogger(MockOperationSetBasicTelephony.class);
/**
* A list of listeners registered for
* <tt>CallEvent</tt>s.
*/
private Vector callListeners = new Vector();
/**
* A reference to the <tt>ProtocolProviderServiceSipImpl</tt> instance
* that created us.
@ -42,19 +36,6 @@ public MockOperationSetBasicTelephony(MockProvider protocolProvider)
this.protocolProvider = protocolProvider;
}
/**
* Registers the specified CallListener with this provider so that it
* could be notified when incoming calls are received.
*
* @param listener the listener to register with this provider.
*/
public void addCallListener(CallListener listener)
{
synchronized(callListeners){
callListeners.add(listener);
}
}
/**
* Indicates a user request to answer an incoming call from the specified
* CallParticipant.
@ -193,18 +174,6 @@ public void putOnHold(CallParticipant participant) throws
{
}
/**
* Removes the specified listener from the list of call listeners.
*
* @param listener the listener to unregister.
*/
public void removeCallListener(CallListener listener)
{
synchronized(callListeners){
callListeners.remove(listener);
}
}
public Call receiveCall(String fromAddress)
throws Exception
{
@ -230,38 +199,6 @@ public Call placeCall(String toAddress)
return newCall;
}
/**
* Creates and dispatches a <tt>CallEvent</tt> notifying registered
* listeners that an event with id <tt>eventID</tt> has occurred on
* <tt>sourceCall</tt>.
*
* @param eventID the ID of the event to dispatch
* @param sourceCall the call on which the event has occurred.
*/
protected void fireCallEvent( int eventID,
Call sourceCall)
{
CallEvent cEvent = new CallEvent(sourceCall, eventID);
logger.debug("Dispatching a CallEvent to "
+ callListeners.size()
+" listeners. event is: " + cEvent.toString());
Iterator listeners = new ArrayList(callListeners).iterator();
while(listeners.hasNext())
{
CallListener listener = (CallListener)listeners.next();
if(eventID == CallEvent.CALL_INITIATED)
listener.outgoingCallCreated(cEvent);
else if(eventID == CallEvent.CALL_RECEIVED)
listener.incomingCallReceived(cEvent);
else if(eventID == CallEvent.CALL_ENDED)
listener.callEnded(cEvent);
}
}
public CallParticipant addNewCallParticipant(Call call, String address)
{
MockCallParticipant callPArt = new MockCallParticipant(address, (MockCall)call);

@ -10,6 +10,7 @@
import java.util.*;
import javax.sip.address.*;
import net.java.sip.communicator.service.media.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
@ -488,4 +489,25 @@ public void setCallInfoURL(URL callControlURL)
{
this.callControlURL = callControlURL;
}
/**
* Determines whether the audio stream (if any) being sent to this
* participant is mute.
*
* @return <tt>true</tt> if an audio stream is being sent to this
* participant and it is currently mute; <tt>false</tt>, otherwise
*/
public boolean isMute()
{
CallSipImpl call = this.call;
if (call != null)
{
CallSession callSession = call.getMediaCallSession();
if (callSession != null)
return callSession.isMute();
}
return false;
}
}

@ -27,8 +27,8 @@
* @author Lubomir Marinov
*/
public class OperationSetBasicTelephonySipImpl
implements OperationSetBasicTelephony
, SipListener
extends AbstractOperationSetBasicTelephony
implements SipListener
{
private static final Logger logger
= Logger.getLogger(OperationSetBasicTelephonySipImpl.class);
@ -39,11 +39,6 @@ public class OperationSetBasicTelephonySipImpl
*/
private ProtocolProviderServiceSipImpl protocolProvider = null;
/**
* A liste of listeners registered for call events.
*/
private Vector callListeners = new Vector();
/**
* Contains references for all currently active (non ended) calls.
*/
@ -79,21 +74,6 @@ public OperationSetBasicTelephonySipImpl(
protocolProvider.registerMethodProcessor(Request.BYE, this);
}
/**
* Registers <tt>listener</tt> with this provider so that it
* could be notified when incoming calls are received.
*
* @param listener the listener to register with this provider.
*/
public void addCallListener(CallListener listener)
{
synchronized(callListeners)
{
if (!callListeners.contains(listener))
callListeners.add(listener);
}
}
/**
* Create a new call and invite the specified CallParticipant to it.
*
@ -308,42 +288,6 @@ private CallSipImpl createOutgoingCall(Address calleeAddress)
return (CallSipImpl)callParticipant.getCall();
}
/**
* Creates and dispatches a <tt>CallEvent</tt> notifying registered
* listeners that an event with id <tt>eventID</tt> has occurred on
* <tt>sourceCall</tt>.
*
* @param eventID the ID of the event to dispatch
* @param sourceCall the call on which the event has occurred.
*/
protected void fireCallEvent( int eventID,
CallSipImpl sourceCall)
{
CallEvent cEvent = new CallEvent(sourceCall, eventID);
logger.debug("Dispatching a CallEvent to "
+ callListeners.size()
+" listeners. event is: " + cEvent.toString());
Iterator listeners = null;
synchronized(callListeners)
{
listeners = new ArrayList(callListeners).iterator();
}
while(listeners.hasNext())
{
CallListener listener = (CallListener)listeners.next();
if(eventID == CallEvent.CALL_INITIATED)
listener.outgoingCallCreated(cEvent);
else if(eventID == CallEvent.CALL_RECEIVED)
listener.incomingCallReceived(cEvent);
else if(eventID == CallEvent.CALL_ENDED)
listener.callEnded(cEvent);
}
}
/**
* Returns an iterator over all currently active calls.
*
@ -534,19 +478,6 @@ private void throwOperationFailedException(String message, int errorCode,
throw new OperationFailedException(message, errorCode, cause);
}
/**
* Removes the <tt>listener</tt> from the list of call listeners.
*
* @param listener the listener to unregister.
*/
public void removeCallListener(CallListener listener)
{
synchronized(callListeners)
{
callListeners.remove(listener);
}
}
/**
* Processes a Request received on a SipProvider upon which this SipListener
* is registered.
@ -2456,4 +2387,22 @@ public synchronized void shutdown()
}
}
}
/**
* Sets the mute state of the audio stream being sent to a specific
* <tt>CallParticipant</tt>.
* <p>
* The implementation sends silence through the audio stream.
* </p>
*
* @param participant the <tt>CallParticipant</tt> who receives the audio
* stream to have its mute state set
* @param mute <tt>true</tt> to mute the audio stream being sent to
* <tt>participant</tt>; otherwise, <tt>false</tt>
*/
public void setMute(CallParticipant participant, boolean mute)
{
((CallSipImpl) participant.getCall()).getMediaCallSession().setMute(
mute);
}
}

@ -168,4 +168,20 @@ public void processSdpAnswer(CallParticipant responder, String sdpAnswer)
* URL is available.
*/
public URL getCallInfoURL();
/**
* Determines whether the audio of this session is (set to) mute.
*
* @return <tt>true</tt> if the audio of this session is (set to) mute;
* otherwise, <tt>false</tt>
*/
public boolean isMute();
/**
* Sets the mute state of the audio of this session.
*
* @param mute <tt>true</tt> to mute the audio of this session; otherwise,
* <tt>false</tt>
*/
public void setMute(boolean mute);
}

@ -17,7 +17,6 @@
* The DefaultCallParticipant provides a default implementation for most of the
* CallParticpant methods with the purpose of only leaving custom protocol
* development to clients using the PhoneUI service.
* <p> </p>
*
* @author Emil Ivov
*/
@ -160,4 +159,19 @@ public URL getCallInfoURL()
//they should override this method
return null;
}
/**
* Determines whether the audio stream (if any) being sent to this
* participant is mute.
* <p>
* The default implementation returns <tt>false</tt>.
* </p>
*
* @return <tt>true</tt> if an audio stream is being sent to this
* participant and it is currently mute; <tt>false</tt>, otherwise
*/
public boolean isMute()
{
return false;
}
}

@ -0,0 +1,115 @@
/*
* 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.service.protocol;
import java.util.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* Represents a default implementation of <tt>OperationSetBasicTelephony</tt> in
* order to make it easier for implementers to provide complete solutions while
* focusing on implementation-specific details.
*
* @author Lubomir Marinov
*/
public abstract class AbstractOperationSetBasicTelephony
implements OperationSetBasicTelephony
{
private static final Logger logger =
Logger.getLogger(AbstractOperationSetBasicTelephony.class);
/**
* A list of listeners registered for call events.
*/
private final List callListeners = new Vector();
/**
* Registers <tt>listener</tt> with this provider so that it
* could be notified when incoming calls are received.
*
* @param listener the listener to register with this provider.
*/
public void addCallListener(CallListener listener)
{
synchronized(callListeners)
{
if (!callListeners.contains(listener))
callListeners.add(listener);
}
}
/**
* Creates and dispatches a <tt>CallEvent</tt> notifying registered
* listeners that an event with id <tt>eventID</tt> has occurred on
* <tt>sourceCall</tt>.
*
* @param eventID the ID of the event to dispatch
* @param sourceCall the call on which the event has occurred.
*/
public void fireCallEvent(int eventID, Call sourceCall)
{
CallEvent cEvent = new CallEvent(sourceCall, eventID);
logger.debug("Dispatching a CallEvent to " + callListeners.size()
+ " listeners. event is: " + cEvent.toString());
Iterator listeners = null;
synchronized (callListeners)
{
listeners = new ArrayList(callListeners).iterator();
}
while (listeners.hasNext())
{
CallListener listener = (CallListener) listeners.next();
if (eventID == CallEvent.CALL_INITIATED)
listener.outgoingCallCreated(cEvent);
else if (eventID == CallEvent.CALL_RECEIVED)
listener.incomingCallReceived(cEvent);
else if (eventID == CallEvent.CALL_ENDED)
listener.callEnded(cEvent);
}
}
/**
* Removes the <tt>listener</tt> from the list of call listeners.
*
* @param listener the listener to unregister.
*/
public void removeCallListener(CallListener listener)
{
synchronized(callListeners)
{
callListeners.remove(listener);
}
}
/**
* Sets the mute state of the audio stream being sent to a specific
* <tt>CallParticipant</tt>.
* <p>
* The default implementation does nothing.
* </p>
*
* @param participant the <tt>CallParticipant</tt> who receives the audio
* stream to have its mute state set
* @param mute <tt>true</tt> to mute the audio stream being sent to
* <tt>participant</tt>; otherwise, <tt>false</tt>
*/
public void setMute(CallParticipant participant, boolean mute)
{
/*
* While throwing UnsupportedOperationException may be a possible
* approach, putOnHold/putOffHold just do nothing when not supported so
* this implementation takes inspiration from them.
*/
}
}

@ -132,4 +132,13 @@ public interface CallParticipant
* is available.
*/
public URL getCallInfoURL();
/**
* Determines whether the audio stream (if any) being sent to this
* participant is mute.
*
* @return <tt>true</tt> if an audio stream is being sent to this
* participant and it is currently mute; <tt>false</tt>, otherwise
*/
public boolean isMute();
}

@ -14,9 +14,10 @@
* An Operation Set defining all basic telephony operations such as conducting
* simple calls and etc. Note that video is not considered as a part of a
* supplementary operation set and if included in the service should be available
* behind the basic telephoy set.
* behind the basic telephony set.
*
* @author Emil Ivov
* @author Lubomir Marinov
*/
public interface OperationSetBasicTelephony
extends OperationSet
@ -74,7 +75,7 @@ public Call createCall(Contact callee)
/**
* Indicates a user request to answer an incoming call from the specified
* CallParticipant.
* @param participant the call participant that we'd like to anwer.
* @param participant the call participant that we'd like to answer.
* @throws OperationFailedException with the corresponding code if we
* encounter an error while performing this operation.
*/
@ -106,7 +107,7 @@ public void putOffHold(CallParticipant participant)
/**
* Indicates a user request to end a call with the specified call
* particiapnt.
* participant.
* @param participant the participant that we'd like to hang up on.
* @throws OperationFailedException with the corresponding code if we
* encounter an error while performing this operation.
@ -119,4 +120,19 @@ public void hangupCallParticipant(CallParticipant participant)
* @return Iterator
*/
public Iterator getActiveCalls();
/**
* Sets the mute state of the audio stream being sent to a specific
* <tt>CallParticipant</tt>.
* <p>
* Muting an audio stream is implementation specific and one of the possible
* approaches to it is sending silence.
* </p>
*
* @param participant the <tt>CallParticipant</tt> who receives the audio
* stream to have its mute state set
* @param mute <tt>true</tt> to mute the audio stream being sent to
* <tt>participant</tt>; otherwise, <tt>false</tt>
*/
public void setMute(CallParticipant participant, boolean mute);
}

Loading…
Cancel
Save