aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator
diff options
context:
space:
mode:
authorLyubomir Marinov <lyubomir.marinov@jitsi.org>2008-07-29 03:57:32 +0000
committerLyubomir Marinov <lyubomir.marinov@jitsi.org>2008-07-29 03:57:32 +0000
commit8589c49d206e35be1c4d549df1199a2746821a67 (patch)
tree05c1c4610b4bc74dc903484b44b4944191d1a137 /src/net/java/sip/communicator
parent022bc07d5622ce94b8aa2f35cd3ad7787c705e51 (diff)
downloadjitsi-8589c49d206e35be1c4d549df1199a2746821a67.zip
jitsi-8589c49d206e35be1c4d549df1199a2746821a67.tar.gz
jitsi-8589c49d206e35be1c4d549df1199a2746821a67.tar.bz2
Introduces support for muting a call.
Diffstat (limited to 'src/net/java/sip/communicator')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java4
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java119
-rw-r--r--src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java5
-rw-r--r--src/net/java/sip/communicator/impl/gui/utils/images.properties1
-rw-r--r--src/net/java/sip/communicator/impl/media/CallSessionImpl.java21
-rw-r--r--src/net/java/sip/communicator/impl/media/MediaControl.java53
-rw-r--r--src/net/java/sip/communicator/impl/media/MutePushBufferDataSource.java275
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java71
-rw-r--r--src/net/java/sip/communicator/impl/protocol/mock/MockOperationSetBasicTelephony.java67
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java22
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java91
-rw-r--r--src/net/java/sip/communicator/service/media/CallSession.java16
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java16
-rw-r--r--src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java115
-rw-r--r--src/net/java/sip/communicator/service/protocol/CallParticipant.java9
-rw-r--r--src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java22
16 files changed, 688 insertions, 219 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java
index 0f50f21..b7da4f7 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java
@@ -82,6 +82,10 @@ public class CallParticipantPanel
Component holdButton = new HoldButton(this.callParticipant);
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)));
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java b/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java
new file mode 100644
index 0000000..4e3a138
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/MuteButton.java
@@ -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();
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index ee406c5..185a7a8 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -404,6 +404,11 @@ public class ImageLoader {
= 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.
*/
public static final ImageID DEFAULT_USER_PHOTO
diff --git a/src/net/java/sip/communicator/impl/gui/utils/images.properties b/src/net/java/sip/communicator/impl/gui/utils/images.properties
index dee6334..928796a 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/images.properties
+++ b/src/net/java/sip/communicator/impl/gui/utils/images.properties
@@ -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
diff --git a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
index ff28481..de7b45e 100644
--- a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
+++ b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java
@@ -2370,4 +2370,25 @@ public class CallSessionImpl
}
}
+ /**
+ * 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);
+ }
}
diff --git a/src/net/java/sip/communicator/impl/media/MediaControl.java b/src/net/java/sip/communicator/impl/media/MediaControl.java
index 54f8129..1c22680 100644
--- a/src/net/java/sip/communicator/impl/media/MediaControl.java
+++ b/src/net/java/sip/communicator/impl/media/MediaControl.java
@@ -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 @@ import java.awt.Dimension;
* @author Jean Lorchat
* @author Ryan Ricard
* @author Ken Larson
+ * @author Lubomir Marinov
*/
public class MediaControl
{
@@ -58,6 +57,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.
*/
private String[] supportedVideoEncodings = new String[]
@@ -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 class MediaControl
{
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 @@ public class MediaControl
+ 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);
+ }
}
diff --git a/src/net/java/sip/communicator/impl/media/MutePushBufferDataSource.java b/src/net/java/sip/communicator/impl/media/MutePushBufferDataSource.java
new file mode 100644
index 0000000..fa14d42
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/media/MutePushBufferDataSource.java
@@ -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);
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
index 8c14f80..6a61ff5 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
@@ -30,8 +30,8 @@ import org.jivesoftware.smackx.packet.DiscoverInfo;
* @author Symphorien Wanko
*/
public class OperationSetBasicTelephonyJabberImpl
- implements OperationSetBasicTelephony,
- RegistrationStateChangeListener,
+ extends AbstractOperationSetBasicTelephony
+ implements RegistrationStateChangeListener,
JingleMediaListener,
JingleTransportListener,
JingleSessionRequestListener,
@@ -53,11 +53,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.
*/
private ActiveCallsRepository activeCallsRepository
@@ -135,21 +130,6 @@ public class OperationSetBasicTelephonyJabberImpl
}
/**
- * 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.
*
* @param callee the jabber address of the callee that we should invite to a
@@ -296,40 +276,6 @@ public class OperationSetBasicTelephonyJabberImpl
}
/**
- * 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.
*
* @return an iterator over all currently active calls.
@@ -364,19 +310,6 @@ public class OperationSetBasicTelephonyJabberImpl
}
/**
- * 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>.
*
diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockOperationSetBasicTelephony.java b/src/net/java/sip/communicator/impl/protocol/mock/MockOperationSetBasicTelephony.java
index 43a2702..96b37d3 100644
--- a/src/net/java/sip/communicator/impl/protocol/mock/MockOperationSetBasicTelephony.java
+++ b/src/net/java/sip/communicator/impl/protocol/mock/MockOperationSetBasicTelephony.java
@@ -13,19 +13,13 @@ import net.java.sip.communicator.util.*;
* @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.
*/
@@ -43,19 +37,6 @@ public class MockOperationSetBasicTelephony
}
/**
- * 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 class MockOperationSetBasicTelephony
{
}
- /**
- * 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 class MockOperationSetBasicTelephony
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);
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java
index 73b08d1..87b9a7a 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java
@@ -10,6 +10,7 @@ import java.text.*;
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 class CallParticipantSipImpl
{
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;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
index 6eca61e..f4b85a4 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
@@ -27,8 +27,8 @@ import net.java.sip.communicator.util.*;
* @author Lubomir Marinov
*/
public class OperationSetBasicTelephonySipImpl
- implements OperationSetBasicTelephony
- , SipListener
+ extends AbstractOperationSetBasicTelephony
+ implements SipListener
{
private static final Logger logger
= Logger.getLogger(OperationSetBasicTelephonySipImpl.class);
@@ -40,11 +40,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.
*/
private ActiveCallsRepository activeCallsRepository
@@ -80,21 +75,6 @@ public class OperationSetBasicTelephonySipImpl
}
/**
- * 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.
*
* @param callee the sip address of the callee that we should invite to a
@@ -309,42 +289,6 @@ public class OperationSetBasicTelephonySipImpl
}
/**
- * 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.
*
* @return an iterator over all currently active calls.
@@ -535,19 +479,6 @@ public class OperationSetBasicTelephonySipImpl
}
/**
- * 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.
* <p>
@@ -2456,4 +2387,22 @@ public class OperationSetBasicTelephonySipImpl
}
}
}
+
+ /**
+ * 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);
+ }
}
diff --git a/src/net/java/sip/communicator/service/media/CallSession.java b/src/net/java/sip/communicator/service/media/CallSession.java
index b83bd88..b388521 100644
--- a/src/net/java/sip/communicator/service/media/CallSession.java
+++ b/src/net/java/sip/communicator/service/media/CallSession.java
@@ -168,4 +168,20 @@ public interface CallSession
* 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);
}
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java b/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java
index d38ab5c..b59d7e9 100644
--- a/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java
+++ b/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java
@@ -17,7 +17,6 @@ import net.java.sip.communicator.util.*;
* 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 abstract class AbstractCallParticipant
//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;
+ }
}
diff --git a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java
new file mode 100644
index 0000000..810a0ed
--- /dev/null
+++ b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicTelephony.java
@@ -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.
+ */
+ }
+}
diff --git a/src/net/java/sip/communicator/service/protocol/CallParticipant.java b/src/net/java/sip/communicator/service/protocol/CallParticipant.java
index 0c18065..21b01e2 100644
--- a/src/net/java/sip/communicator/service/protocol/CallParticipant.java
+++ b/src/net/java/sip/communicator/service/protocol/CallParticipant.java
@@ -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();
}
diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java b/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java
index 34c4ff7..c8bba6b 100644
--- a/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java
+++ b/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java
@@ -14,9 +14,10 @@ import java.text.*;
* 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 interface OperationSetBasicTelephony
/**
* 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 interface OperationSetBasicTelephony
/**
* 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 interface OperationSetBasicTelephony
* @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);
}